package app import ( "context" "fmt" "io" "os" "strings" "time" "fyne.io/fyne/v2" fyneapp "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/widget" "updata_hfb/internal/hfb" ) const sampleText = `上号方式:QQ扫码 哈夫币纯币:156 段位:铂金 等级:60 保险格数:9 每日消耗:10 体力:7 负重:7 AWM子弹数量:80 6头数量:13 6甲数量:12 皮肤:暗星 绝密KD:0.2 押金:350 号主在线时间:11:00 至 00:00 封禁记录:无 常用地区:海南 回收比例:1:47.0 回收租金:332 联系电话:15203616450` func Run() { a := fyneapp.NewWithID("com.hfb.updata") w := a.NewWindow("哈夫币外部上传") w.Resize(fyne.NewSize(920, 760)) serverEntry := widget.NewEntry() serverEntry.SetText(envDefault("HFB_SERVER", "http://127.0.0.1:8080")) serverEntry.SetPlaceHolder("例如:http://127.0.0.1:8080") uploaderEntry := widget.NewEntry() uploaderEntry.SetText(strings.TrimSpace(os.Getenv("HFB_UPLOADER_NAME"))) uploaderEntry.SetPlaceHolder("后台上传管理员名称") secretEntry := widget.NewEntry() secretEntry.Password = true secretEntry.SetText(strings.TrimSpace(os.Getenv("HFB_UPLOAD_SECRET"))) secretEntry.SetPlaceHolder("未配置密钥可留空") timeoutEntry := widget.NewEntry() timeoutEntry.SetText("15s") timeoutEntry.SetPlaceHolder("例如:15s") dataEntry := widget.NewMultiLineEntry() dataEntry.Wrapping = fyne.TextWrapWord dataEntry.SetMinRowsVisible(18) dataEntry.SetPlaceHolder(sampleText) resultEntry := widget.NewMultiLineEntry() resultEntry.Wrapping = fyne.TextWrapWord resultEntry.SetMinRowsVisible(8) resultEntry.Disable() statusLabel := widget.NewLabel("准备就绪") setResult := func(text string) { resultEntry.Enable() resultEntry.SetText(text) resultEntry.Disable() } setBusy := func(uploadBtn *widget.Button, previewBtn *widget.Button, busy bool) { if busy { uploadBtn.Disable() previewBtn.Disable() statusLabel.SetText("正在上传,请稍等...") return } uploadBtn.Enable() previewBtn.Enable() } var uploadBtn *widget.Button var previewBtn *widget.Button loadBtn := widget.NewButton("打开文件", func() { dialog.ShowFileOpen(func(reader fyne.URIReadCloser, err error) { if err != nil { dialog.ShowError(fmt.Errorf("打开文件失败:%w", err), w) return } if reader == nil { return } defer reader.Close() content, err := io.ReadAll(reader) if err != nil { dialog.ShowError(fmt.Errorf("读取文件失败:%w", err), w) return } dataEntry.SetText(string(content)) statusLabel.SetText("已载入文件") }, w) }) sampleBtn := widget.NewButton("填入示例", func() { dataEntry.SetText(sampleText) statusLabel.SetText("已填入示例数据") }) clearBtn := widget.NewButton("清空", func() { dataEntry.SetText("") setResult("") statusLabel.SetText("已清空") }) previewBtn = widget.NewButton("预览 JSON", func() { req, err := buildRequest(uploaderEntry.Text, dataEntry.Text) if err != nil { statusLabel.SetText("解析失败") dialog.ShowError(err, w) return } out, err := hfb.MarshalPretty(req) if err != nil { statusLabel.SetText("生成 JSON 失败") dialog.ShowError(err, w) return } setResult(string(out)) statusLabel.SetText("预览已生成") }) uploadBtn = widget.NewButton("上传", func() { timeout, err := time.ParseDuration(strings.TrimSpace(timeoutEntry.Text)) if err != nil || timeout <= 0 { dialog.ShowError(fmt.Errorf("请求超时时间不正确:%s", timeoutEntry.Text), w) return } req, err := buildRequest(uploaderEntry.Text, dataEntry.Text) if err != nil { statusLabel.SetText("解析失败") dialog.ShowError(err, w) return } server := strings.TrimSpace(serverEntry.Text) secret := strings.TrimSpace(secretEntry.Text) setBusy(uploadBtn, previewBtn, true) setResult("") go func() { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() resp, err := hfb.Client{ Server: server, Secret: secret, Timeout: timeout, }.Upload(ctx, req) fyne.Do(func() { setBusy(uploadBtn, previewBtn, false) if err != nil { statusLabel.SetText("上传失败") setResult(err.Error()) dialog.ShowError(err, w) return } statusLabel.SetText("上传成功") setResult(resp) dialog.ShowInformation("上传成功", "数据已经提交到服务器。", w) }) }() }) uploadBtn.Importance = widget.HighImportance form := widget.NewForm( widget.NewFormItem("服务器", serverEntry), widget.NewFormItem("上传人", uploaderEntry), widget.NewFormItem("上传密钥", secretEntry), widget.NewFormItem("超时时间", timeoutEntry), ) toolbar := container.NewHBox(loadBtn, sampleBtn, clearBtn, previewBtn, uploadBtn) content := container.NewBorder( nil, container.NewVBox(statusLabel), nil, nil, container.NewVScroll(container.NewVBox( widget.NewLabel("连接配置"), form, toolbar, widget.NewLabel("账号数据"), dataEntry, widget.NewLabel("结果"), resultEntry, )), ) w.SetContent(content) w.ShowAndRun() } func buildRequest(uploaderName string, rawText string) (hfb.ExternalUploadRequest, error) { if strings.TrimSpace(rawText) == "" { return hfb.ExternalUploadRequest{}, fmt.Errorf("账号数据不能为空") } parsed, err := hfb.ParseUploadText(rawText) if err != nil { return hfb.ExternalUploadRequest{}, err } name := strings.TrimSpace(uploaderName) if name == "" { name = parsed.UploaderName } if name == "" { return hfb.ExternalUploadRequest{}, fmt.Errorf("缺少上传人名称:请在“上传人”里填写,或在文本中增加“上传人:姓名”") } return hfb.NewExternalUploadRequest(name, parsed.Account, time.Now()), nil } func envDefault(key string, fallback string) string { value := strings.TrimSpace(os.Getenv(key)) if value == "" { return fallback } return value }