结果
暂无结果
-点击“预览 JSON”或“上传”后,这里会显示多行结果。
+点击“上传”后,这里会显示多行结果。
@@ -69,7 +70,7 @@ const elements = {
data: document.querySelector('#data'),
result: document.querySelector('#result'),
fileInput: document.querySelector('#fileInput'),
- previewBtn: document.querySelector('#previewBtn'),
+ pasteBtn: document.querySelector('#pasteBtn'),
uploadBtn: document.querySelector('#uploadBtn'),
};
@@ -83,7 +84,7 @@ function setStatus(text, tone = 'neutral') {
}
function setBusy(busy) {
- elements.previewBtn.disabled = busy;
+ elements.pasteBtn.disabled = busy;
elements.uploadBtn.disabled = busy;
}
@@ -115,6 +116,21 @@ function collectForm() {
};
}
+async function readClipboardText() {
+ try {
+ const text = await ClipboardGetText();
+ if (typeof text === 'string' && text.trim() !== '') {
+ return text;
+ }
+ } catch {
+ // 回退到浏览器剪贴板 API
+ }
+ if (navigator.clipboard?.readText) {
+ return await navigator.clipboard.readText();
+ }
+ throw new Error('无法读取剪贴板内容');
+}
+
async function init() {
const api = backend();
if (!api) {
@@ -140,7 +156,7 @@ elements.fileInput.addEventListener('change', async (event) => {
if (!file) return;
try {
elements.data.value = await file.text();
- elements.result.textContent = '文件已载入,可以预览或上传。';
+ elements.result.textContent = '文件已载入,可以上传。';
setStatus('已载入文件', 'ok');
} catch (err) {
setStatus('读取文件失败', 'error');
@@ -150,17 +166,23 @@ elements.fileInput.addEventListener('change', async (event) => {
}
});
-elements.previewBtn.addEventListener('click', async () => {
- const api = backend();
+elements.pasteBtn.addEventListener('click', async () => {
setBusy(true);
- setStatus('正在生成预览...', 'neutral');
- saveSettings();
+ setStatus('正在读取剪贴板...', 'neutral');
try {
- elements.result.textContent = await api.Preview(collectForm());
- setStatus('预览已生成', 'ok');
+ const text = await readClipboardText();
+ if (!text || !text.trim()) {
+ setStatus('剪贴板为空', 'error');
+ elements.result.textContent = '剪贴板没有可用的文本内容。';
+ return;
+ }
+ elements.data.value = text;
+ elements.result.textContent = '已从剪贴板填入账号数据,可以上传。';
+ setStatus('已粘贴剪贴板', 'ok');
+ elements.data.focus();
} catch (err) {
elements.result.textContent = String(err);
- setStatus('预览失败', 'error');
+ setStatus('读取剪贴板失败', 'error');
} finally {
setBusy(false);
}
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
new file mode 100644
index 0000000..2abf84d
--- /dev/null
+++ b/frontend/vite.config.js
@@ -0,0 +1,10 @@
+import { defineConfig } from 'vite'
+
+// 使用项目专属端口,避免多项目同时开发时与 Vite 默认 5173 冲突
+export default defineConfig({
+ server: {
+ host: 'localhost',
+ port: 5188,
+ strictPort: true,
+ },
+})
diff --git a/internal/hfb/parser.go b/internal/hfb/parser.go
index da851fc..38a3b65 100644
--- a/internal/hfb/parser.go
+++ b/internal/hfb/parser.go
@@ -43,7 +43,7 @@ func ParseUploadText(text string) (ParsedUpload, error) {
if err != nil {
return ParsedUpload{}, err
}
- account.SecretKD, err = parseRequiredFloat(values, "绝密KD", "绝密kd")
+ account.SecretKD, err = parseOptionalFloat(values, "绝密KD", "绝密kd")
if err != nil {
return ParsedUpload{}, err
}
@@ -51,10 +51,12 @@ func ParseUploadText(text string) (ParsedUpload, error) {
if err != nil {
return ParsedUpload{}, err
}
- account.BanRecord = optionalDefault(firstValue(values, "封禁记录"), "无")
+ banRaw := firstValue(values, "封禁记录")
+ account.BanRecord = normalizeBanFlag(banRaw)
account.CommonRegion = firstValue(values, "常用地区", "常用区域")
account.ContactPhone = firstValue(values, "联系电话", "手机号", "电话")
account.OwnerOnlineTime = firstValue(values, "号主在线时间", "在线时间")
+ account.Remark = composeRemark(firstValue(values, "备注", "说明"), banRaw)
account.Currency.HafuCoin, err = parseRequiredFloat(values, "哈夫币纯币", "哈夫币")
if err != nil {
@@ -134,6 +136,43 @@ func optionalDefault(value, fallback string) string {
return strings.TrimSpace(value)
}
+// normalizeBanFlag 只输出“有/无”,具体封禁历史放到备注。
+func normalizeBanFlag(value string) string {
+ value = strings.TrimSpace(value)
+ if value == "" || isNoBanRecord(value) {
+ return "无"
+ }
+ return "有"
+}
+
+func isNoBanRecord(value string) bool {
+ value = strings.TrimSpace(value)
+ switch value {
+ case "无", "无封禁", "无封禁记录", "否", "没有", "none", "None", "NONE":
+ return true
+ default:
+ return false
+ }
+}
+
+// composeRemark 合并原文备注与封禁历史详情。
+func composeRemark(remark, banRaw string) string {
+ remark = strings.TrimSpace(remark)
+ banDetail := strings.TrimSpace(banRaw)
+ if banDetail == "" || isNoBanRecord(banDetail) {
+ return remark
+ }
+ // 如果原文已经是“有/无”,不当作详情追加
+ if banDetail == "有" || banDetail == "是" || banDetail == "有封禁" || banDetail == "有封禁记录" {
+ return remark
+ }
+ banLine := "封禁历史:" + banDetail
+ if remark == "" {
+ return banLine
+ }
+ return remark + "\n" + banLine
+}
+
func parseRequiredInt(values map[string]string, labels ...string) (int, error) {
value := firstValue(values, labels...)
if value == "" {
@@ -170,6 +209,18 @@ func parseRequiredFloat(values map[string]string, labels ...string) (float64, er
return number, nil
}
+func parseOptionalFloat(values map[string]string, labels ...string) (float64, error) {
+ value := firstValue(values, labels...)
+ if value == "" {
+ return 0, nil
+ }
+ number, err := parseFloatText(value, false)
+ if err != nil {
+ return 0, fmt.Errorf("%s 数字格式不正确:%s", labels[0], value)
+ }
+ return number, nil
+}
+
func parseRequiredRatio(values map[string]string, labels ...string) (float64, error) {
value := firstValue(values, labels...)
if value == "" {
diff --git a/internal/hfb/parser_test.go b/internal/hfb/parser_test.go
index 3cefecd..7857894 100644
--- a/internal/hfb/parser_test.go
+++ b/internal/hfb/parser_test.go
@@ -66,3 +66,51 @@ func TestParseUploadTextMissingRequiredField(t *testing.T) {
t.Fatal("ParseUploadText() expected error")
}
}
+
+func TestParseUploadTextBanRecordAndRemark(t *testing.T) {
+ text := `上号方式:QQ扫码
+哈夫币纯币:156
+段位:铂金
+等级:60
+保险格数:9
+每日消耗:10
+体力:7
+负重:7
+AWM子弹数量:80
+6头数量:13
+6甲数量:12
+皮肤:暗星
+绝密KD:0.2
+押金:350
+号主在线时间:11:00 至 00:00
+封禁记录:2026/01/23封禁3天 2026/01/26封禁一天
+常用地区:海南
+回收比例:1:47.0
+回收租金:332
+联系电话:15203616450
+备注:有语音封禁`
+ parsed, err := ParseUploadText(text)
+ if err != nil {
+ t.Fatalf("ParseUploadText() error = %v", err)
+ }
+ if parsed.Account.BanRecord != "有" {
+ t.Fatalf("BanRecord = %q, want 有", parsed.Account.BanRecord)
+ }
+ wantRemark := "有语音封禁\n封禁历史:2026/01/23封禁3天 2026/01/26封禁一天"
+ if parsed.Account.Remark != wantRemark {
+ t.Fatalf("Remark = %q, want %q", parsed.Account.Remark, wantRemark)
+ }
+}
+
+func TestParseUploadTextNoBanKeepsEmptyRemark(t *testing.T) {
+ parsed, err := ParseUploadText(sampleText)
+ if err != nil {
+ t.Fatalf("ParseUploadText() error = %v", err)
+ }
+ if parsed.Account.BanRecord != "无" {
+ t.Fatalf("BanRecord = %q, want 无", parsed.Account.BanRecord)
+ }
+ if parsed.Account.Remark != "" {
+ t.Fatalf("Remark = %q, want empty", parsed.Account.Remark)
+ }
+}
diff --git a/internal/hfb/types.go b/internal/hfb/types.go
index 0bb305d..9e4051c 100644
--- a/internal/hfb/types.go
+++ b/internal/hfb/types.go
@@ -28,6 +28,7 @@ type ExternalAccountData struct {
CommonRegion string `json:"commonRegion"`
ContactPhone string `json:"contactPhone"`
OwnerOnlineTime string `json:"ownerOnlineTime"`
+ Remark string `json:"remark,omitempty"`
Currency ExternalUploadCurrency `json:"currency"`
DailyConsumption ExternalDailyConsumption `json:"dailyConsumption"`
Inventory ExternalUploadInventory `json:"inventory"`
diff --git a/wails.json b/wails.json
index 880599e..1abcafb 100644
--- a/wails.json
+++ b/wails.json
@@ -5,7 +5,8 @@
"frontend:install": "npm install",
"frontend:build": "npm run build",
"frontend:dev:watcher": "npm run dev",
- "frontend:dev:serverUrl": "auto",
+ "frontend:dev:serverUrl": "http://localhost:5188",
+ "devServer": "localhost:34188",
"author": {
"name": "yml",
"email": ""