package main //import ( // "bufio" // "context" // "encoding/json" // "fmt" // "gopkg.in/yaml.v3" // "image" // "image/color" // "io" // "io/ioutil" // "net" // "net/http" // "os" // "os/exec" // "path/filepath" // "strings" // "syscall" // "time" // "unsafe" // // "gioui.org/app" // "gioui.org/io/key" // "gioui.org/layout" // "gioui.org/op" // "gioui.org/op/clip" // "gioui.org/op/paint" // "gioui.org/unit" // "gioui.org/widget" // "gioui.org/widget/material" //) // //// ============================ 常量定义 ============================ //const ( // ColorReset = "\033[0m" // ColorRed = "\033[31m" // ColorGreen = "\033[32m" // ColorYellow = "\033[33m" // ColorBlue = "\033[34m" // ColorMagenta = "\033[35m" // ColorCyan = "\033[36m" // ColorWhite = "\033[37m" // ColorGray = "\033[90m" // // ColorBoldRed = "\033[1;31m" // ColorBoldGreen = "\033[1;32m" // ColorBoldYellow = "\033[1;33m" // ColorBoldBlue = "\033[1;34m" // // ColorBgRed = "\033[41m" // ColorBgGreen = "\033[42m" //) // //// ============================ 结构体定义 ============================ //type VersionConfig struct { // CsvVersion string `json:"csv"` // KongfzVersion string `json:"kongfz"` // LoggerVersion string `json:"logger"` // ModuleErpVersion string `json:"module-erp"` // ModuleKongfzVersion string `json:"module-kongfz"` // ModuleTaskPoolVersion string `json:"module-taskPool"` // ModuleVerifyPriceVersion string `json:"module-verifyPrice"` // ModuleCenterBookVersion string `json:"module-centerBook"` // ModuleLoginVersion string `json:"module-login"` // PicToolVersion string `json:"picTool"` // ProxyVersion string `json:"proxy"` //} // //type VerifyPriceYAML struct { // VerifyPriceLatestVersion string `yaml:"verifyPriceLatestVersion"` //} // //type VersionInfo struct { // LatestVersion string `json:"latestVersion"` // HistoricalVersions []string `json:"historicalVersions"` // VerifyPriceLatestVersion string `json:"verifyPriceLatestVersion"` //} // //// ============================ Gio GUI 结构体 ============================ //type UpdaterApp struct { // window *app.Window // theme *material.Theme // // // 小部件 // progress float32 // statusText string // actionBtn widget.Clickable // showConsole bool // consoleText string // logEntries []string // // isPaused bool // isUpdating bool // isComplete bool // isChecking bool // isDownloading bool // // totalSize int64 // downloaded int64 // currentSpeed float64 // startTime time.Time // // // 更新状态 // currentFile string // totalFiles int // completedFiles int // // // 数据 // versionsJSON *VersionConfig // verifyPriceVersion *VersionInfo // localConfig VerifyPriceYAML // currentDir string // yamlPath string // // // 布局 // ops op.Ops // scroll widget.List //} // //// ============================ 控制台输出函数 ============================ //func printInfo(format string, v ...interface{}) { // message := fmt.Sprintf(format, v...) // fmt.Printf(ColorCyan + "[信息] " + message + ColorReset + "\n") // if globalApp != nil { // globalApp.addLog("[信息] " + message) // } //} // //func printSuccess(format string, v ...interface{}) { // message := fmt.Sprintf(format, v...) // fmt.Printf(ColorGreen + "[成功] " + message + ColorReset + "\n") // if globalApp != nil { // globalApp.addLog("[成功] " + message) // } //} // //func printWarning(format string, v ...interface{}) { // message := fmt.Sprintf(format, v...) // fmt.Printf(ColorYellow + "[警告] " + message + ColorReset + "\n") // if globalApp != nil { // globalApp.addLog("[警告] " + message) // } //} // //func printError(format string, v ...interface{}) { // message := fmt.Sprintf(format, v...) // fmt.Printf(ColorRed + "[错误] " + message + ColorReset + "\n") // if globalApp != nil { // globalApp.addLog("[错误] " + message) // } //} // //func printDebug(format string, v ...interface{}) { // message := fmt.Sprintf(format, v...) // fmt.Printf(ColorGray + "[调试] " + message + ColorReset + "\n") // if globalApp != nil { // globalApp.addLog("[调试] " + message) // } //} // //func printBanner(format string, v ...interface{}) { // message := fmt.Sprintf(format, v...) // fmt.Printf(ColorBoldBlue + "== " + message + " ==\n" + ColorReset) // if globalApp != nil { // globalApp.addLog("== " + message + " ==") // } //} // //func printDownload(format string, v ...interface{}) { // message := fmt.Sprintf(format, v...) // fmt.Printf(ColorBoldGreen + "[下载] " + message + ColorReset + "\n") // if globalApp != nil { // globalApp.addLog("[下载] " + message) // } //} // //func printVersionInfo(label, version string) { // message := fmt.Sprintf("%-30s: %s", label, version) // fmt.Printf(ColorBoldYellow+"%-30s: "+ColorCyan+"%s"+ColorReset+"\n", label, version) // if globalApp != nil { // globalApp.addLog(message) // } //} // //// ============================ 全局变量 ============================ //var globalApp *UpdaterApp // //// ============================ Gio GUI 方法 ============================ //// NewUpdaterApp 创建新的更新器应用 //func NewUpdaterApp() *UpdaterApp { // // 使用新的 Window 创建方式 // window := new(app.Window) // // // 设置窗口选项 // window.Option( // app.Title("核价软件更新器"), // app.Size(unit.Dp(800), unit.Dp(600)), // app.MinSize(unit.Dp(600), unit.Dp(400)), // ) // // // 创建主题 // theme := material.NewTheme() // // appNew := &UpdaterApp{ // window: window, // theme: theme, // progress: 0.0, // statusText: "初始化更新器...", // isPaused: false, // isUpdating: true, // startTime: time.Now(), // showConsole: true, // totalFiles: 12, // DLL文件数量 + 主程序 // scroll: widget.List{ // List: layout.List{ // Axis: layout.Vertical, // }, // }, // } // // globalApp = appNew // return appNew //} // //// addLog 添加日志条目 //func (u *UpdaterApp) addLog(message string) { // u.logEntries = append(u.logEntries, message) // // 保持最后100条日志 // if len(u.logEntries) > 100 { // u.logEntries = u.logEntries[len(u.logEntries)-100:] // } // u.window.Invalidate() //} // //// updateStatus 更新状态文本 //func (u *UpdaterApp) updateStatus(status string) { // u.statusText = status // u.addLog(status) // u.window.Invalidate() //} // //// updateProgress 更新进度 //func (u *UpdaterApp) updateProgress(progress float32) { // u.progress = progress // u.window.Invalidate() //} // //// updateFileProgress 更新文件进度 //func (u *UpdaterApp) updateFileProgress(currentFile string, downloaded, totalSize int64) { // u.currentFile = currentFile // u.downloaded = downloaded // u.totalSize = totalSize // // if totalSize > 0 { // u.progress = float32(downloaded) / float32(totalSize) // } // // // 计算速度 // elapsed := time.Since(u.startTime).Seconds() // if elapsed > 0 && downloaded > 0 { // u.currentSpeed = float64(downloaded) / elapsed / 1024 / 1024 // } // // u.window.Invalidate() //} // //// updateFileCount 更新文件计数 //func (u *UpdaterApp) updateFileCount(completed int) { // u.completedFiles = completed // // // 计算总体进度(文件计数占30%,文件内进度占70%) // fileProgress := float32(completed) / float32(u.totalFiles) // overallProgress := 0.3*fileProgress + 0.7*u.progress // u.updateProgress(overallProgress) // // u.window.Invalidate() //} // //// Run 运行GUI主循环 //func (u *UpdaterApp) Run() error { // // 启动更新过程 // go u.startUpdateProcess() // // var ops op.Ops // for { // ev := u.window.Event() // switch e := ev.(type) { // case app.DestroyEvent: // return e.Err // // case app.FrameEvent: // gtx := app.NewContext(&ops, e) // u.handleEvents(gtx) // u.drawUI(gtx) // e.Frame(gtx.Ops) // // case key.Event: // if e.Name == "C" && e.Modifiers.Contain(key.ModCtrl) { // u.showConsole = !u.showConsole // u.window.Invalidate() // } // } // } //} // //// handleEvents 处理用户事件 //func (u *UpdaterApp) handleEvents(gtx layout.Context) { // // 处理按钮点击 // if u.actionBtn.Clicked(gtx) { // if u.isComplete { // // 启动核价软件 // u.startVerifyPriceApp() // } else if u.isPaused { // // 继续更新 // u.isPaused = false // u.updateStatus("继续更新...") // } else { // // 暂停更新 // u.isPaused = true // u.updateStatus("更新已暂停") // } // } //} // //// drawUI 绘制用户界面 //func (u *UpdaterApp) drawUI(gtx layout.Context) layout.Dimensions { // // 背景色 // paint.Fill(gtx.Ops, color.NRGBA{R: 245, G: 245, B: 245, A: 255}) // // return layout.Flex{ // Axis: layout.Vertical, // Spacing: layout.SpaceBetween, // }.Layout(gtx, // // 标题栏 // layout.Rigid(u.drawHeader), // // // 主内容区域 // layout.Flexed(1, u.drawMainContent), // // // 底部控制栏 // layout.Rigid(u.drawFooter), // ) //} // //// drawHeader 绘制标题栏 //func (u *UpdaterApp) drawHeader(gtx layout.Context) layout.Dimensions { // return layout.Inset{ // Top: unit.Dp(10), // Bottom: unit.Dp(10), // Left: unit.Dp(20), // Right: unit.Dp(20), // }.Layout(gtx, func(gtx layout.Context) layout.Dimensions { // return layout.Flex{ // Axis: layout.Horizontal, // Spacing: layout.SpaceBetween, // Alignment: layout.Middle, // }.Layout(gtx, // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // title := material.H4(u.theme, "核价软件更新器") // title.Color = color.NRGBA{R: 0, G: 100, B: 200, A: 255} // return title.Layout(gtx) // }), // // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // // 状态文本和颜色的逻辑保持不变 // statusText := "就绪" // if u.isChecking { // statusText = "检查中" // } else if u.isDownloading { // statusText = "下载中" // } else if u.isPaused { // statusText = "已暂停" // } else if u.isComplete { // statusText = "已完成" // } // // // 根据状态设置文本颜色 // statusLabel := material.Body2(u.theme, statusText) // if u.isPaused { // statusLabel.Color = color.NRGBA{R: 241, G: 196, B: 15, A: 255} // 黄色 // } else if u.isDownloading { // statusLabel.Color = color.NRGBA{R: 52, G: 152, B: 219, A: 255} // 蓝色 // } else if u.isChecking { // statusLabel.Color = color.NRGBA{R: 155, G: 89, B: 182, A: 255} // 紫色 // } else if u.isComplete { // statusLabel.Color = color.NRGBA{R: 46, G: 204, B: 113, A: 255} // 绿色 // } else { // statusLabel.Color = color.NRGBA{R: 120, G: 120, B: 120, A: 255} // 灰色 // } // // return material.Body2(u.theme, statusText).Layout(gtx) // }), // ) // }) //} // //// drawMainContent 绘制主内容区域 //func (u *UpdaterApp) drawMainContent(gtx layout.Context) layout.Dimensions { // return layout.Flex{ // Axis: layout.Vertical, // Spacing: layout.SpaceSides, // }.Layout(gtx, // // 状态信息区域 // layout.Rigid(u.drawStatusInfo), // // // 进度条区域 // layout.Rigid(u.drawProgressBar), // // // 文件信息区域 // layout.Rigid(u.drawFileInfo), // // // 日志区域(可折叠) // layout.Flexed(1, u.drawLogArea), // ) //} // //// drawStatusInfo 绘制状态信息 //func (u *UpdaterApp) drawStatusInfo(gtx layout.Context) layout.Dimensions { // return layout.Inset{ // Left: unit.Dp(20), // Right: unit.Dp(20), // Top: unit.Dp(10), // }.Layout(gtx, func(gtx layout.Context) layout.Dimensions { // return layout.Flex{ // Axis: layout.Vertical, // Spacing: layout.SpaceEnd, // }.Layout(gtx, // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // status := material.H6(u.theme, u.statusText) // status.Color = color.NRGBA{R: 60, G: 60, B: 60, A: 255} // return status.Layout(gtx) // }), // // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // if u.currentFile != "" { // fileInfo := material.Caption(u.theme, "当前文件: "+u.currentFile) // return fileInfo.Layout(gtx) // } // return layout.Dimensions{} // }), // ) // }) //} // //// drawProgressBar 绘制进度条 //func (u *UpdaterApp) drawProgressBar(gtx layout.Context) layout.Dimensions { // return layout.Inset{ // Left: unit.Dp(20), // Right: unit.Dp(20), // Top: unit.Dp(15), // Bottom: unit.Dp(15), // }.Layout(gtx, func(gtx layout.Context) layout.Dimensions { // // 进度条背景 // barHeight := gtx.Dp(unit.Dp(30)) // barWidth := gtx.Constraints.Max.X // // // 圆角矩形背景 // rrect := clip.UniformRRect( // image.Rect(0, 0, barWidth, barHeight), // gtx.Dp(unit.Dp(6)), // ) // paint.FillShape(gtx.Ops, color.NRGBA{R: 230, G: 230, B: 230, A: 255}, rrect.Op(gtx.Ops)) // // // 进度条前景 // progressWidth := int(float32(barWidth) * u.progress) // if progressWidth > 0 { // progressRrect := clip.UniformRRect( // image.Rect(0, 0, progressWidth, barHeight), // gtx.Dp(unit.Dp(6)), // ) // // // 根据进度选择颜色 // var barColor color.NRGBA // if u.isComplete { // barColor = color.NRGBA{R: 46, G: 204, B: 113, A: 255} // 绿色 // } else if u.progress < 0.3 { // barColor = color.NRGBA{R: 231, G: 76, B: 60, A: 255} // 红色 // } else if u.progress < 0.7 { // barColor = color.NRGBA{R: 241, G: 196, B: 15, A: 255} // 黄色 // } else { // barColor = color.NRGBA{R: 52, G: 152, B: 219, A: 255} // 蓝色 // } // // paint.FillShape(gtx.Ops, barColor, progressRrect.Op(gtx.Ops)) // } // // // 使用 Flex 布局来居中文本 // return layout.Flex{ // Axis: layout.Vertical, // Spacing: layout.SpaceSides, // Alignment: layout.Middle, // 水平居中 // }.Layout(gtx, // // 占位空间,让文本垂直居中 // layout.Flexed(1, func(gtx layout.Context) layout.Dimensions { // return layout.Dimensions{} // }), // // 文本行 // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // return layout.Flex{ // Axis: layout.Horizontal, // Spacing: layout.SpaceSides, // Alignment: layout.Middle, // 水平居中 // }.Layout(gtx, // // 占位空间,让文本水平居中 // layout.Flexed(1, func(gtx layout.Context) layout.Dimensions { // return layout.Dimensions{} // }), // // 实际文本 // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // text := material.Body1(u.theme, fmt.Sprintf("%.1f%%", u.progress*100)) // if u.progress < 0.5 { // text.Color = color.NRGBA{R: 60, G: 60, B: 60, A: 255} // } else { // text.Color = color.NRGBA{R: 255, G: 255, B: 255, A: 255} // } // return text.Layout(gtx) // }), // // 占位空间,让文本水平居中 // layout.Flexed(1, func(gtx layout.Context) layout.Dimensions { // return layout.Dimensions{} // }), // ) // }), // // 占位空间,让文本垂直居中 // layout.Flexed(50, func(gtx layout.Context) layout.Dimensions { // return layout.Dimensions{} // }), // ) // }) //} // //// drawFileInfo 绘制文件信息 //func (u *UpdaterApp) drawFileInfo(gtx layout.Context) layout.Dimensions { // return layout.Inset{ // Left: unit.Dp(20), // Right: unit.Dp(20), // Bottom: unit.Dp(10), // }.Layout(gtx, func(gtx layout.Context) layout.Dimensions { // return layout.Flex{ // Axis: layout.Horizontal, // Spacing: layout.SpaceAround, // Alignment: layout.Middle, // }.Layout(gtx, // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // fileCount := fmt.Sprintf("文件: %d/%d", u.completedFiles, u.totalFiles) // return material.Caption(u.theme, fileCount).Layout(gtx) // }), // // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // var sizeInfo string // if u.totalSize > 0 { // sizeInfo = fmt.Sprintf("大小: %.2f/%.2f MB", // float64(u.downloaded)/(1024*1024), // float64(u.totalSize)/(1024*1024)) // } else { // sizeInfo = "大小: 计算中..." // } // return material.Caption(u.theme, sizeInfo).Layout(gtx) // }), // // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // speedInfo := fmt.Sprintf("速度: %.2f MB/s", u.currentSpeed) // return material.Caption(u.theme, speedInfo).Layout(gtx) // }), // ) // }) //} // //// drawLogArea 绘制日志区域 //func (u *UpdaterApp) drawLogArea(gtx layout.Context) layout.Dimensions { // if !u.showConsole { // return layout.Dimensions{} // } // // return layout.Inset{ // Left: unit.Dp(20), // Right: unit.Dp(20), // Top: unit.Dp(10), // Bottom: unit.Dp(10), // }.Layout(gtx, func(gtx layout.Context) layout.Dimensions { // return material.List(u.theme, &u.scroll).Layout(gtx, len(u.logEntries), func(gtx layout.Context, index int) layout.Dimensions { // return layout.Inset{ // Bottom: unit.Dp(4), // }.Layout(gtx, func(gtx layout.Context) layout.Dimensions { // logText := material.Body2(u.theme, u.logEntries[index]) // logText.Color = color.NRGBA{R: 100, G: 100, B: 100, A: 255} // // // 根据日志类型设置颜色 // logTextStr := u.logEntries[index] // if strings.Contains(logTextStr, "[错误]") { // logText.Color = color.NRGBA{R: 231, G: 76, B: 60, A: 255} // } else if strings.Contains(logTextStr, "[警告]") { // logText.Color = color.NRGBA{R: 241, G: 196, B: 15, A: 255} // } else if strings.Contains(logTextStr, "[成功]") { // logText.Color = color.NRGBA{R: 46, G: 204, B: 113, A: 255} // } else if strings.Contains(logTextStr, "[信息]") { // logText.Color = color.NRGBA{R: 52, G: 152, B: 219, A: 255} // } else if strings.Contains(logTextStr, "[下载]") { // logText.Color = color.NRGBA{R: 155, G: 89, B: 182, A: 255} // } // // return logText.Layout(gtx) // }) // }) // }) //} // //// drawFooter 绘制底部控制栏 //func (u *UpdaterApp) drawFooter(gtx layout.Context) layout.Dimensions { // return layout.Inset{ // Top: unit.Dp(10), // Bottom: unit.Dp(15), // Left: unit.Dp(20), // Right: unit.Dp(20), // }.Layout(gtx, func(gtx layout.Context) layout.Dimensions { // return layout.Flex{ // Axis: layout.Horizontal, // Spacing: layout.SpaceBetween, // Alignment: layout.Middle, // }.Layout(gtx, // //layout.Rigid(func(gtx layout.Context) layout.Dimensions { // // hint := material.Caption(u.theme, "提示: 按 Ctrl+C 切换日志显示") // // hint.Color = color.NRGBA{R: 150, G: 150, B: 150, A: 255} // // return hint.Layout(gtx) // //}), // // layout.Rigid(func(gtx layout.Context) layout.Dimensions { // var btnText string // var btnColor color.NRGBA // // if u.isComplete { // btnText = "启动核价软件" // btnColor = color.NRGBA{R: 46, G: 204, B: 113, A: 255} // } else if u.isPaused { // btnText = "继续更新" // btnColor = color.NRGBA{R: 46, G: 204, B: 113, A: 255} // } else { // btnText = "暂停更新" // btnColor = color.NRGBA{R: 241, G: 196, B: 15, A: 255} // } // // btn := material.Button(u.theme, &u.actionBtn, btnText) // btn.CornerRadius = unit.Dp(8) // btn.TextSize = unit.Sp(14) // btn.Background = btnColor // btn.Color = color.NRGBA{R: 255, G: 255, B: 255, A: 255} // btn.Inset = layout.UniformInset(unit.Dp(12)) // // return btn.Layout(gtx) // }), // ) // }) //} // //// ============================ 更新过程 ============================ //func (u *UpdaterApp) startUpdateProcess() { // // 初始化 // u.updateStatus("正在初始化...") // u.updateProgress(0.05) // // // 获取当前目录 // currentDir, err := os.Getwd() // if err != nil { // u.updateStatus(fmt.Sprintf("获取当前目录失败: %v", err)) // return // } // u.currentDir = currentDir // u.yamlPath = filepath.Join(currentDir, "version.yaml") // // // 步骤1: 检查核价软件版本 // u.isChecking = true // u.updateStatus("正在检查核价软件版本...") // u.updateProgress(0.1) // u.verifyPriceVersion, err = getVerifyPriceVersionJSON() // if err != nil { // u.updateStatus(fmt.Sprintf("读取核价软件版本失败: %v", err)) // u.isChecking = false // return // } // u.isChecking = false // // // 步骤2: 读取本地配置 // u.updateStatus("正在读取本地配置...") // u.updateProgress(0.15) // data, err := ioutil.ReadFile(u.yamlPath) // if err == nil { // yaml.Unmarshal(data, &u.localConfig) // } else { // u.localConfig = VerifyPriceYAML{} // } // // // 步骤3: 检查并下载主程序 // u.updateStatus("检查核价软件主程序...") // u.updateProgress(0.2) // err = u.checkAndDownloadMainApp() // if err != nil { // u.updateStatus(fmt.Sprintf("主程序处理失败: %v", err)) // } // // // 步骤4: 检查DLL组件版本 // u.isChecking = true // u.updateStatus("正在检查DLL组件版本...") // u.updateProgress(0.3) // u.versionsJSON, err = getVersionsJSON() // if err != nil { // u.updateStatus(fmt.Sprintf("读取DLL版本失败: %v", err)) // u.isChecking = false // return // } // u.isChecking = false // // // 步骤5: 下载所有DLL文件 // u.isDownloading = true // u.updateStatus("开始更新DLL组件...") // u.updateProgress(0.4) // err = u.updateAllDLLs() // if err != nil { // u.updateStatus(fmt.Sprintf("DLL更新失败: %v", err)) // } // u.isDownloading = false // // // 步骤6: 完成 // u.updateStatus("所有更新已完成!") // u.updateProgress(1.0) // u.isComplete = true // u.isUpdating = false // // // 自动启动核价软件(3秒后) // go func() { // time.Sleep(3 * time.Second) // if u.isComplete { // u.startVerifyPriceApp() // } // }() //} // //func (u *UpdaterApp) checkAndDownloadMainApp() error { // exePath := filepath.Join(u.currentDir, "VerifyPriceApp.exe") // // if _, err := os.Stat(exePath); os.IsNotExist(err) { // // 文件缺失,下载 // u.updateStatus("发现核价软件缺失,开始下载...") // url := fmt.Sprintf("http://103.236.81.185:8099/exe/VerifyPriceApp_%s.exe", // u.verifyPriceVersion.VerifyPriceLatestVersion) // err = u.downloadWithProgress(url, exePath, "VerifyPriceApp.exe") // if err != nil { // return fmt.Errorf("下载失败: %v", err) // } // u.updateStatus("核价软件下载完成") // u.localConfig.VerifyPriceLatestVersion = u.verifyPriceVersion.VerifyPriceLatestVersion // writeYAML(u.yamlPath, u.localConfig) // } else { // // 检查版本 // if u.verifyPriceVersion.VerifyPriceLatestVersion != u.localConfig.VerifyPriceLatestVersion { // u.updateStatus("发现新版本,开始更新...") // url := fmt.Sprintf("http://103.236.81.185:8099/exe/VerifyPriceApp_%s.exe", // u.verifyPriceVersion.VerifyPriceLatestVersion) // err = u.downloadWithProgress(url, exePath, "VerifyPriceApp.exe") // if err != nil { // return fmt.Errorf("更新失败: %v", err) // } // u.updateStatus("核价软件更新完成") // u.localConfig.VerifyPriceLatestVersion = u.verifyPriceVersion.VerifyPriceLatestVersion // writeYAML(u.yamlPath, u.localConfig) // } else { // u.updateStatus("核价软件已是最新版本") // } // } // // u.completedFiles++ // u.updateFileCount(u.completedFiles) // // return nil //} // //func (u *UpdaterApp) updateAllDLLs() error { // dlls := []struct { // name string // version string // checker func(string, string) (string, error) // }{ // {"csv.dll", u.versionsJSON.CsvVersion, csvDllVersion}, // //{"kongfz.dll", u.versionsJSON.KongfzVersion, kongfzDllVersion}, // //{"logger.dll", u.versionsJSON.LoggerVersion, loggerDllVersion}, // //{"module-centerBook.dll", u.versionsJSON.ModuleCenterBookVersion, moduleCenterBookDllVersion}, // //{"module-login.dll", u.versionsJSON.ModuleLoginVersion, moduleLoginDllVersion}, // //{"module-erp.dll", u.versionsJSON.ModuleErpVersion, moduleErpDllVersion}, // //{"module-kongfz.dll", u.versionsJSON.ModuleKongfzVersion, moduleKongfzDllVersion}, // //{"module-taskPool.dll", u.versionsJSON.ModuleTaskPoolVersion, moduleTaskPoolDllVersion}, // //{"module-verifyPrice.dll", u.versionsJSON.ModuleVerifyPriceVersion, moduleVerifyPriceDllVersion}, // //{"picTool.dll", u.versionsJSON.PicToolVersion, picToolDllVersion}, // //{"proxy.dll", u.versionsJSON.ProxyVersion, proxyDllVersion}, // } // // for i, dll := range dlls { // // 检查是否暂停 // for u.isPaused { // time.Sleep(100 * time.Millisecond) // } // // u.updateStatus(fmt.Sprintf("检查 %s...", dll.name)) // u.currentFile = dll.name // // // 检查当前版本 // currentVersion, err := dll.checker(u.currentDir, dll.version) // if err != nil { // u.updateStatus(fmt.Sprintf("检查 %s 失败: %v", dll.name, err)) // continue // } // // // 如果需要更新 // if dll.version != currentVersion && currentVersion != "" { // u.updateStatus(fmt.Sprintf("更新 %s...,版本:%s", dll.name, dll.version)) // // // 创建带new-前缀的临时文件名 // newFileName := "new-" + dll.name // dllDir := filepath.Join(u.currentDir, "dll") // newDllPath := filepath.Join(dllDir, newFileName) // finalDllPath := filepath.Join(dllDir, dll.name) // // //dllPath := filepath.Join(u.currentDir, "dll", dll.name) // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", newDllPath, dll.name, dll.version) // //if err != nil { // // u.updateStatus(fmt.Sprintf("更新 %s 失败: %v", dll.name, err)) // //} else { // // u.updateStatus(fmt.Sprintf("%s 更新完成", dll.name)) // //} // // if err != nil { // u.updateStatus(fmt.Sprintf("更新 %s 失败: %v", dll.name, err)) // } else { // // 下载成功后,删除原文件(如果存在)并将new-文件重命名为原文件名 // if _, err := os.Stat(finalDllPath); err == nil { // os.Remove(finalDllPath) // } // if err := os.Rename(newDllPath, finalDllPath); err != nil { // u.updateStatus(fmt.Sprintf("重命名 %s 失败: %v", dll.name, err)) // } else { // u.updateStatus(fmt.Sprintf("%s 更新完成", dll.name)) // } // } // } else { // u.updateStatus(fmt.Sprintf("%s 已是最新版本", dll.name)) // } // // // 更新进度 // u.completedFiles++ // progress := 0.4 + 0.5*(float32(i+1)/float32(len(dlls))) // u.updateProgress(progress) // u.updateFileCount(u.completedFiles) // // // 短暂暂停以避免UI卡顿 // time.Sleep(100 * time.Millisecond) // } // // return nil //} // //func (u *UpdaterApp) downloadWithProgress(url, filePath, fileName string) error { // u.currentFile = fileName // u.startTime = time.Now() // u.downloaded = 0 // // // 创建目录 // os.MkdirAll(filepath.Dir(filePath), 0755) // // // 发送请求 // client := &http.Client{Timeout: 30 * time.Minute} // resp, err := client.Get(url) // if err != nil { // return err // } // defer resp.Body.Close() // // if resp.StatusCode != http.StatusOK { // return fmt.Errorf("HTTP错误: %d", resp.StatusCode) // } // // // 获取文件大小 // u.totalSize = resp.ContentLength // // // 创建临时文件 // tempPath := filePath + ".tmp" // file, err := os.Create(tempPath) // if err != nil { // return err // } // defer file.Close() // // // 下载文件 // buf := make([]byte, 32*1024) // 32KB缓冲区 // for { // // 检查是否暂停 // for u.isPaused { // time.Sleep(100 * time.Millisecond) // } // // n, err := resp.Body.Read(buf) // if n > 0 { // _, writeErr := file.Write(buf[:n]) // if writeErr != nil { // return writeErr // } // u.downloaded += int64(n) // u.updateFileProgress(fileName, u.downloaded, u.totalSize) // } // // if err != nil { // if err == io.EOF { // break // } // return err // } // } // // // 关闭文件 // file.Close() // // // 重命名为最终文件 // if err := os.Rename(tempPath, filePath); err != nil { // // 如果重命名失败,尝试复制 // if err := copyFile(tempPath, filePath); err != nil { // return err // } // } // // // 清理临时文件 // os.Remove(tempPath) // // return nil //} // //func (u *UpdaterApp) startVerifyPriceApp() { // exePath := filepath.Join(u.currentDir, "VerifyPriceApp.exe") // // u.updateStatus("正在启动核价软件...") // // cmd := exec.Command(exePath) // cmd.Dir = u.currentDir // // err := cmd.Start() // if err != nil { // u.updateStatus(fmt.Sprintf("启动失败: %v", err)) // u.updateStatus("请手动运行 VerifyPriceApp.exe") // } else { // u.updateStatus("核价软件已启动,即将退出...") // time.Sleep(2 * time.Second) // os.Exit(0) // } //} // //// ============================ 主函数 ============================ //func main() { // //// 隐藏控制台窗口(仅Windows) // //hideConsoleWindow() // // // 检查是否以控制台模式运行 // if len(os.Args) > 1 && os.Args[1] == "--console" { // runConsoleMode() // return // } // // // GUI模式 // go func() { // app := NewUpdaterApp() // if err := app.Run(); err != nil { // fmt.Fprintf(os.Stderr, "错误: %v\n", err) // os.Exit(1) // } // }() // app.Main() //} // ////// hideConsoleWindow 隐藏控制台窗口(仅Windows有效) ////func hideConsoleWindow() { //// // 仅在Windows平台下生效 //// kernel32 := syscall.NewLazyDLL("kernel32.dll") //// getConsoleWindow := kernel32.NewProc("GetConsoleWindow") //// showWindow := syscall.NewLazyDLL("user32.dll").NewProc("ShowWindow") //// //// if hwnd, _, _ := getConsoleWindow.Call(); hwnd != 0 { //// showWindow.Call(hwnd, 0) // 0 = SW_HIDE //// } ////} // //func runConsoleMode() { // // 控制台模式(原main.go的逻辑) // printBanner("核价软件更新器") // printWarning("更新时请勿操作!!!") // // // 获取当前工作目录 // currentDir, err := os.Getwd() // if err != nil { // printError("获取当前目录失败: %v", err) // return // } // printInfo("当前目录: %v", currentDir) // // // 获取选品中心中verify_price_version.json // printInfo("正在检查核价软件版本...") // verifyPriceVersionJSON, err := getVerifyPriceVersionJSON() // if err != nil { // printError("读取核价软件版本信息失败: %v", err) // return // } // // // 直接读取yaml文件 // yamlPath := filepath.Join(currentDir, "version.yaml") // data, err := ioutil.ReadFile(yamlPath) // if err != nil { // printError("读取YAML配置文件失败: %v", err) // } // // // 解析 YAML // var config VerifyPriceYAML // err = yaml.Unmarshal(data, &config) // if err != nil { // printError("解析 YAML 配置失败: %v", err) // } // printVersionInfo("当前核价软件版本号", config.VerifyPriceLatestVersion) // // // 检查并下载核价软件主程序 // printInfo("检查核价软件主程序...") // if _, err := os.Stat(filepath.Join(currentDir, "VerifyPriceApp.exe")); os.IsNotExist(err) { // printDownload("发现核价软件缺失,开始下载...") // url := fmt.Sprintf("http://103.236.81.185:8099/exe/VerifyPriceApp_%s.exe", verifyPriceVersionJSON.VerifyPriceLatestVersion) // err = downloadEXE(url, currentDir, "VerifyPriceApp.exe") // if err != nil { // if err.Error() == "The process cannot access the file because it is being used by another process." { // printWarning("文件被占用,请重新启动与书同行.exe软件") // } else { // printError("下载核价软件失败: %v", err) // } // } else { // printSuccess("核价软件下载完成") // } // //修改yaml文件 // config.VerifyPriceLatestVersion = verifyPriceVersionJSON.VerifyPriceLatestVersion // err = writeYAML(yamlPath, config) // if err != nil { // printError("更新YAML配置文件失败: %v", err) // } // } else { // if verifyPriceVersionJSON.VerifyPriceLatestVersion != config.VerifyPriceLatestVersion || config.VerifyPriceLatestVersion == "" { // printDownload("发现新版本核价软件,开始更新...") // url := fmt.Sprintf("http://103.236.81.185:8099/exe/VerifyPriceApp_%s.exe", verifyPriceVersionJSON.VerifyPriceLatestVersion) // err = downloadEXE(url, currentDir, "VerifyPriceApp.exe") // if err != nil { // if err.Error() == "The process cannot access the file because it is being used by another process." { // printWarning("文件被占用,请重新启动与书同行.exe软件") // } else { // printError("下载核价软件失败: %v", err) // } // } else { // printSuccess("核价软件更新完成") // } // //修改yaml文件 // config.VerifyPriceLatestVersion = verifyPriceVersionJSON.VerifyPriceLatestVersion // err = writeYAML(yamlPath, config) // if err != nil { // printError("更新YAML配置文件失败: %v", err) // } // } else { // printSuccess("核价软件已是最新版本") // } // } // // // 获取ES2中version.json // printInfo("正在检查DLL组件版本...") // versionsJSON, err := getVersionsJSON() // if err != nil { // printError("读取DLL版本信息失败: %v", err) // return // } // // // 打印版本信息标题 // printBanner("版本信息") // // // 打印所有版本信息 // printVersionInfo("最新核价软件版本", verifyPriceVersionJSON.VerifyPriceLatestVersion) // printVersionInfo("csv.dll版本号:", versionsJSON.CsvVersion) // printVersionInfo("kongfz.dll版本号:", versionsJSON.KongfzVersion) // printVersionInfo("logger.dll版本号:", versionsJSON.LoggerVersion) // printVersionInfo("module-centerBook.dll版本号:", versionsJSON.ModuleCenterBookVersion) // printVersionInfo("module-login.dll版本号:", versionsJSON.ModuleLoginVersion) // printVersionInfo("module-erp.dll版本号:", versionsJSON.ModuleErpVersion) // printVersionInfo("module-kongfz.dll版本号:", versionsJSON.ModuleKongfzVersion) // printVersionInfo("module-taskPool.dll版本号:", versionsJSON.ModuleTaskPoolVersion) // printVersionInfo("module-verifyPrice.dll版本号:", versionsJSON.ModuleVerifyPriceVersion) // printVersionInfo("picTool.dll版本号:", versionsJSON.PicToolVersion) // printVersionInfo("proxy.dll版本号:", versionsJSON.ProxyVersion) // // // 验证并更新DLL文件 // printBanner("组件检查与更新") // // // 验证csv.dll文件版本 // printInfo("检查csv.dll...") // csvVersion, err := csvDllVersion(currentDir, versionsJSON.CsvVersion) // if err != nil { // printWarning("获取csv.dll版本失败: %v", err) // } // if versionsJSON.CsvVersion != csvVersion && csvVersion != "" { // printDownload("csv.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "csv.dll"), "csv.dll", "") // if err != nil { // printError("下载csv.dll失败: %v", err) // } else { // printSuccess("csv.dll更新完成") // } // } else { // printSuccess("csv.dll已是最新版本") // } // // // 验证kongfz.dll文件版本 // printInfo("检查kongfz.dll...") // kongfzVersion, err := kongfzDllVersion(currentDir, versionsJSON.KongfzVersion) // if err != nil { // printWarning("获取kongfz.dll版本失败: %v", err) // } // if versionsJSON.KongfzVersion != kongfzVersion && kongfzVersion != "" { // printDownload("kongfz.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "kongfz.dll"), "kongfz.dll", "") // if err != nil { // printError("下载kongfz.dll失败: %v", err) // } else { // printSuccess("kongfz.dll更新完成") // } // } else { // printSuccess("kongfz.dll已是最新版本") // } // // // 验证logger.dll文件版本 // printInfo("检查logger.dll...") // loggerVersion, err := loggerDllVersion(currentDir, versionsJSON.LoggerVersion) // if err != nil { // printWarning("获取logger.dll版本失败: %v", err) // } // if versionsJSON.LoggerVersion != loggerVersion && loggerVersion != "" { // printDownload("logger.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "logger.dll"), "logger.dll", "") // if err != nil { // printError("下载logger.dll失败: %v", err) // } else { // printSuccess("logger.dll更新完成") // } // } else { // printSuccess("logger.dll已是最新版本") // } // // // 验证module-centerBook.dll文件版本 // printInfo("检查module-centerBook.dll...") // moduleCenterBookVersion, err := moduleCenterBookDllVersion(currentDir, versionsJSON.ModuleCenterBookVersion) // if err != nil { // printWarning("获取module-centerBook.dll版本失败: %v", err) // } // if versionsJSON.ModuleCenterBookVersion != moduleCenterBookVersion && moduleCenterBookVersion != "" { // printDownload("module-centerBook.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-centerBook.dll"), "module-centerBook.dll", "") // if err != nil { // printError("下载module-centerBook.dll失败: %v", err) // } else { // printSuccess("module-centerBook.dll更新完成") // } // } else { // printSuccess("module-centerBook.dll已是最新版本") // } // // // 验证module-login.dll文件版本 // printInfo("检查module-login.dll...") // moduleLoginVersion, err := moduleLoginDllVersion(currentDir, versionsJSON.ModuleLoginVersion) // if err != nil { // printWarning("获取module-login.dll版本失败: %v", err) // } // if versionsJSON.ModuleLoginVersion != moduleLoginVersion && moduleLoginVersion != "" { // printDownload("module-login.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-login.dll"), "module-login.dll", "") // if err != nil { // printError("下载module-login.dll失败: %v", err) // } else { // printSuccess("module-login.dll更新完成") // } // } else { // printSuccess("module-login.dll已是最新版本") // } // // // 验证module-erp.dll文件版本 // printInfo("检查module-erp.dll...") // moduleErpVersion, err := moduleErpDllVersion(currentDir, versionsJSON.ModuleErpVersion) // if err != nil { // printWarning("获取module-erp.dll版本失败: %v", err) // } // if versionsJSON.ModuleErpVersion != moduleErpVersion && moduleErpVersion != "" { // printDownload("module-erp.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-erp.dll"), "module-erp.dll", "") // if err != nil { // printError("下载module-erp.dll失败: %v", err) // } else { // printSuccess("module-erp.dll更新完成") // } // } else { // printSuccess("module-erp.dll已是最新版本") // } // // // 验证module-kongfz.dll文件版本 // printInfo("检查module-kongfz.dll...") // moduleKongfzVersion, err := moduleKongfzDllVersion(currentDir, versionsJSON.ModuleKongfzVersion) // if err != nil { // printWarning("获取module-kongfz.dll版本失败: %v", err) // } // if versionsJSON.ModuleKongfzVersion != moduleKongfzVersion && moduleKongfzVersion != "" { // printDownload("module-kongfz.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-kongfz.dll"), "module-kongfz.dll", "") // if err != nil { // printError("下载module-kongfz.dll失败: %v", err) // } else { // printSuccess("module-kongfz.dll更新完成") // } // } else { // printSuccess("module-kongfz.dll已是最新版本") // } // // // 验证module-taskPool.dll文件版本 // printInfo("检查module-taskPool.dll...") // moduleTaskPoolVersion, err := moduleTaskPoolDllVersion(currentDir, versionsJSON.ModuleTaskPoolVersion) // if err != nil { // printWarning("获取module-taskPool.dll版本失败: %v", err) // } // if versionsJSON.ModuleTaskPoolVersion != moduleTaskPoolVersion && moduleTaskPoolVersion != "" { // printDownload("module-taskPool.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-taskPool.dll"), "module-taskPool.dll", "") // if err != nil { // printError("下载module-taskPool.dll失败: %v", err) // } else { // printSuccess("module-taskPool.dll更新完成") // } // } else { // printSuccess("module-taskPool.dll已是最新版本") // } // // // 验证module-verifyPrice.dll文件版本 // printInfo("检查module-verifyPrice.dll...") // moduleVerifyPriceVersion, err := moduleVerifyPriceDllVersion(currentDir, versionsJSON.ModuleVerifyPriceVersion) // if err != nil { // printWarning("获取module-verifyPrice.dll版本失败: %v", err) // } // if versionsJSON.ModuleVerifyPriceVersion != moduleVerifyPriceVersion && moduleVerifyPriceVersion != "" { // printDownload("module-verifyPrice.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "module-verifyPrice.dll"), "module-verifyPrice.dll", "") // if err != nil { // printError("下载module-verifyPrice.dll失败: %v", err) // } else { // printSuccess("module-verifyPrice.dll更新完成") // } // } else { // printSuccess("module-verifyPrice.dll已是最新版本") // } // // // 验证picTool.dll文件版本 // printInfo("检查picTool.dll...") // picToolVersion, err := picToolDllVersion(currentDir, versionsJSON.PicToolVersion) // if err != nil { // printWarning("获取picTool.dll版本失败: %v", err) // } // if versionsJSON.PicToolVersion != picToolVersion && picToolVersion != "" { // printDownload("picTool.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "picTool.dll"), "picTool.dll", "") // if err != nil { // printError("下载picTool.dll失败: %v", err) // } else { // printSuccess("picTool.dll更新完成") // } // } else { // printSuccess("picTool.dll已是最新版本") // } // // // 验证proxy.dll文件版本 // printInfo("检查proxy.dll...") // proxyVersion, err := proxyDllVersion(currentDir, versionsJSON.ProxyVersion) // if err != nil { // printWarning("获取proxy.dll版本失败: %v", err) // } // if versionsJSON.ProxyVersion != proxyVersion && proxyVersion != "" { // printDownload("proxy.dll需要更新") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", filepath.Join(currentDir, "dll", "proxy.dll"), "proxy.dll", "") // if err != nil { // printError("下载proxy.dll失败: %v", err) // } else { // printSuccess("proxy.dll更新完成") // } // } else { // printSuccess("proxy.dll已是最新版本") // } // // printWarning("更新完成!按回车键打开核价软件...") // // // 等待用户输入 // bufio.NewReader(os.Stdin).ReadBytes('\n') // // // 启动核价软件 // verifyPriceAppPath := filepath.Join(currentDir, "VerifyPriceApp.exe") // if _, err := os.Stat(verifyPriceAppPath); os.IsNotExist(err) { // printError("核价软件主程序不存在: %s", verifyPriceAppPath) // } else { // cmd := exec.Command(verifyPriceAppPath) // cmd.Dir = currentDir // err := cmd.Start() // if err != nil { // printError("启动核价软件失败: %v", err) // } else { // printSuccess("核价软件已启动 (PID: %d)", cmd.Process.Pid) // } // } // // printBanner("程序执行完毕") //} // //// ============================ 原main.go的函数 ============================ //func writeYAML(filePath string, config VerifyPriceYAML) error { // yamlData, err := yaml.Marshal(config) // if err != nil { // return fmt.Errorf("序列化YAML失败: %v", err) // } // // backupFilePath := filePath + ".bak" // err = backupFile(filePath, backupFilePath) // if err != nil { // printDebug("创建备份文件失败: %v", err) // } // // err = ioutil.WriteFile(filePath, yamlData, 0755) // if err != nil { // return fmt.Errorf("写入文件失败: %v", err) // } // // return nil //} // //func backupFile(originalPath, backupPath string) error { // data, err := ioutil.ReadFile(originalPath) // if err != nil { // return err // } // return ioutil.WriteFile(backupPath, data, 0755) //} // //// 下载exe文件 //func downloadEXE(url, folderPath, filename string) error { // if err := os.MkdirAll(folderPath, 0755); err != nil { // return fmt.Errorf("创建文件夹失败: %v", err) // } // // filePath := filepath.Join(folderPath, filename) // printDebug("下载到: %s", filePath) // // resp, err := http.Get(url) // if err != nil { // return fmt.Errorf("请求失败: %v", err) // } // defer resp.Body.Close() // // if resp.StatusCode != http.StatusOK { // return fmt.Errorf("下载失败,状态码: %d", resp.StatusCode) // } // // file, err := os.Create(filePath) // if err != nil { // return fmt.Errorf("创建文件失败: %v", err) // } // defer file.Close() // // _, err = io.Copy(file, resp.Body) // if err != nil { // return fmt.Errorf("写入文件失败: %v", err) // } // // return nil //} // //func getVerifyPriceVersionJSON() (*VersionInfo, error) { // url := "http://103.236.81.185:8099/verify_price_version.json" // client := &http.Client{Timeout: 30 * time.Second} // // resp, err := client.Get(url) // if err != nil { // return nil, fmt.Errorf("请求失败: %v", err) // } // defer resp.Body.Close() // // if resp.StatusCode != http.StatusOK { // return nil, fmt.Errorf("HTTP请求失败,状态码: %d", resp.StatusCode) // } // // body, err := io.ReadAll(resp.Body) // if err != nil { // return nil, fmt.Errorf("读取响应失败: %v", err) // } // // var versionInfo VersionInfo // err = json.Unmarshal(body, &versionInfo) // if err != nil { // return nil, fmt.Errorf("解析JSON失败: %v", err) // } // return &versionInfo, nil //} // //func getVersionsJSON() (*VersionConfig, error) { // url := "http://36.212.20.113:53300/versionNew.json" // client := &http.Client{Timeout: 30 * time.Second} // // resp, err := client.Get(url) // if err != nil { // return nil, fmt.Errorf("请求失败: %v", err) // } // defer resp.Body.Close() // // if resp.StatusCode != http.StatusOK { // return nil, fmt.Errorf("HTTP请求失败,状态码: %d", resp.StatusCode) // } // // body, err := io.ReadAll(resp.Body) // if err != nil { // return nil, fmt.Errorf("读取响应失败: %v", err) // } // // var versionConfig VersionConfig // err = json.Unmarshal(body, &versionConfig) // if err != nil { // return nil, fmt.Errorf("解析JSON失败: %v", err) // } // return &versionConfig, nil //} // //func cStr(ptr uintptr) string { // if ptr == 0 { // return "" // } // var b []byte // for { // c := *(*byte)(unsafe.Pointer(ptr)) // if c == 0 { // break // } // b = append(b, c) // ptr++ // } // return string(b) //} // //func csvDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "csv.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("csv.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "csv.dll", version) // if err != nil { // return "", fmt.Errorf("下载 csv.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载csv.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找csv.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用csv.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func kongfzDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "kongfz.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("kongfz.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "kongfz.dll", version) // if err != nil { // return "", fmt.Errorf("下载 kongfz.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载kongfz.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找kongfz.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用kongfz.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func loggerDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "logger.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("logger.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "logger.dll", version) // if err != nil { // return "", fmt.Errorf("下载 logger.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载logger.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找logger.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用logger.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func moduleCenterBookDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "module-centerBook.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("module-centerBook.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-centerBook.dll", version) // if err != nil { // return "", fmt.Errorf("下载 module-centerBook.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载module-centerBook.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找module-centerBook.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用module-centerBook.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func moduleLoginDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "module-login.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("module-login.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-login.dll", version) // if err != nil { // return "", fmt.Errorf("下载 module-login.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载module-login.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找module-login.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用module-login.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func moduleErpDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "module-erp.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("module-erp.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-erp.dll", version) // if err != nil { // return "", fmt.Errorf("下载 module-erp.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载module-erp.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找module-erp.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用module-erp.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func moduleKongfzDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "module-kongfz.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("module-kongfz.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-kongfz.dll", version) // if err != nil { // return "", fmt.Errorf("下载 module-kongfz.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载module-kongfz.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找module-kongfz.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用module-kongfz.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func moduleTaskPoolDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "module-taskPool.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("module-taskPool.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-taskPool.dll", version) // if err != nil { // return "", fmt.Errorf("下载 module-taskPool.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载module-taskPool.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找module-taskPool.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用module-taskPool.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func moduleVerifyPriceDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "module-verifyPrice.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("module-verifyPrice.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "module-verifyPrice.dll", version) // if err != nil { // return "", fmt.Errorf("下载 module-verifyPrice.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载module-verifyPrice.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找module-verifyPrice.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用module-verifyPrice.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func picToolDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "picTool.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("picTool.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "picTool.dll", version) // if err != nil { // return "", fmt.Errorf("下载 picTool.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载picTool.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找picTool.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用picTool.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func proxyDllVersion(currentDir string, version string) (string, error) { // dllPath := filepath.Join(currentDir, "dll", "proxy.dll") // // _, err := os.Stat(dllPath) // if err != nil { // if os.IsNotExist(err) { // printDownload("proxy.dll文件缺失,开始下载...") // err = downloadDLL("http://36.212.20.113:53300/api/downLoad", dllPath, "proxy.dll", version) // if err != nil { // return "", fmt.Errorf("下载 proxy.dll 文件失败: %v", err) // } // return "", nil // } // } // // dll, err := syscall.LoadDLL(dllPath) // if err != nil { // return "", fmt.Errorf("加载proxy.dll文件失败: %v", err) // } // // proc, err := dll.FindProc("GetVersion") // if err != nil { // return "", fmt.Errorf("查找proxy.dll GetVersion 函数失败: %v", err) // } // // ret, _, err := proc.Call() // if err != nil && err.Error() != "The operation completed successfully." { // return "", fmt.Errorf("调用proxy.dll GetVersion 函数失败: %v", err) // } // str := cStr(ret) // // if proc, err = dll.FindProc("FreeCString"); err == nil { // defer proc.Call(ret) // } // return str, nil //} // //func downloadDLL(url, outputPath, filename, version string) error { // // 1. 确保目录存在 // dir := filepath.Dir(outputPath) // if err := os.MkdirAll(dir, 0755); err != nil { // return fmt.Errorf("创建目录失败: %v", err) // } // // // 2. 创建临时文件路径 // tempPath := outputPath + ".tmp" // // // 3. 清理可能存在的旧临时文件 // if _, err := os.Stat(tempPath); err == nil { // os.Remove(tempPath) // } // // // 4. 检查目标文件是否存在 // if _, err := os.Stat(outputPath); err == nil { // backupPath := outputPath + ".bak" // if err := os.Rename(outputPath, backupPath); err != nil { // // 重命名失败,尝试直接删除 // for i := 0; i < 3; i++ { // if err := os.Remove(outputPath); err == nil { // break // } // if i == 2 { // if strings.Contains(err.Error(), "Access is denied") { // return fmt.Errorf("文件被其他程序占用,请关闭可能使用此文件的程序后再试: %s", outputPath) // } // return fmt.Errorf("无法删除已存在的文件: %v", err) // } // time.Sleep(1 * time.Second) // } // } else { // // 异步清理备份文件 // go func() { // time.Sleep(30 * time.Second) // if _, err := os.Stat(backupPath); err == nil { // os.Remove(backupPath) // } // }() // } // } // // // 5. 打印下载信息 // if version == "" { // printDownload("正在下载: %s (版本: 最新版本)", filename) // } else { // printDownload("正在下载: %s (版本: %s)", filename, version) // } // // // 6. 首先尝试获取文件大小信息(HEAD请求) // headClient := &http.Client{ // Timeout: 30 * time.Second, // } // // headReq, err := http.NewRequest("HEAD", url, nil) // if err != nil { // printError("创建HEAD请求失败,使用默认超时设置: %v", err) // } else { // // 添加查询参数 // q := headReq.URL.Query() // q.Add("filename", filename) // if version != "" { // q.Add("version", version) // } // headReq.URL.RawQuery = q.Encode() // headReq.Header.Set("User-Agent", "DLL-Downloader/1.0") // // resp, err := headClient.Do(headReq) // if err == nil && resp.StatusCode == http.StatusOK { // if contentLength := resp.ContentLength; contentLength > 0 { // fmt.Printf(ColorGray+"获取到文件大小: %.2f MB\n"+ColorReset, // float64(contentLength)/1024/1024) // } // resp.Body.Close() // } // } // // // 7. 创建长时间下载的HTTP客户端 // transport := &http.Transport{ // Proxy: http.ProxyFromEnvironment, // DialContext: (&net.Dialer{ // Timeout: 30 * time.Second, // KeepAlive: 30 * time.Second, // DualStack: true, // }).DialContext, // ForceAttemptHTTP2: true, // MaxIdleConns: 100, // MaxIdleConnsPerHost: 10, // IdleConnTimeout: 90 * time.Second, // TLSHandshakeTimeout: 15 * time.Second, // ExpectContinueTimeout: 5 * time.Second, // ResponseHeaderTimeout: 30 * time.Second, // ReadBufferSize: 128 * 1024, // 128KB // WriteBufferSize: 128 * 1024, // } // // client := &http.Client{ // Transport: transport, // } // // // 8. 创建下载请求 // ctx, cancel := context.WithTimeout(context.Background(), 3*time.Hour) // defer cancel() // // req, err := http.NewRequestWithContext(ctx, "GET", url, nil) // if err != nil { // return fmt.Errorf("创建请求失败: %v", err) // } // // // 添加查询参数 // q := req.URL.Query() // q.Add("filename", filename) // if version != "" { // q.Add("version", version) // } // req.URL.RawQuery = q.Encode() // // // 添加请求头 // req.Header.Set("User-Agent", "DLL-Downloader/1.0") // req.Header.Set("Accept", "*/*") // req.Header.Set("Accept-Encoding", "gzip, deflate") // req.Header.Set("Connection", "keep-alive") // // // 9. 发送请求 // resp, err := client.Do(req) // if err != nil { // if strings.Contains(err.Error(), "context deadline exceeded") { // return fmt.Errorf("连接超时,请检查网络连接: %v", err) // } // return fmt.Errorf("请求失败: %v", err) // } // defer resp.Body.Close() // // if resp.StatusCode != http.StatusOK { // body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024)) // return fmt.Errorf("服务器返回错误: %d - %s", resp.StatusCode, string(body)) // } // // // 10. 获取文件大小 // totalSize := resp.ContentLength // if totalSize > 0 { // fmt.Printf(ColorGray+"文件大小: %.2f MB\n"+ColorReset, float64(totalSize)/1024/1024) // // // 根据文件大小提供预估时间 // minSpeed := 50.0 * 1024 // estimatedTime := time.Duration(float64(totalSize)/minSpeed) * time.Second // if estimatedTime > 30*time.Second { // fmt.Printf(ColorGray+"预估下载时间: %v (基于50KB/s最低速度)\n"+ColorReset, // estimatedTime.Round(time.Second)) // } // } else { // fmt.Println(ColorGray + "文件大小: 未知" + ColorReset) // } // // // 11. 创建临时文件 // out, err := os.OpenFile(tempPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0755) // if err != nil { // return fmt.Errorf("创建临时文件失败: %v", err) // } // defer out.Close() // // // 12. 确保下载失败时清理临时文件 // downloadSuccess := false // defer func() { // if !downloadSuccess { // os.Remove(tempPath) // } // }() // // // 13. 活动检测机制 // activityCh := make(chan time.Time, 100) // var lastActivity time.Time // lastActivity = time.Now() // // // 创建活动检测的reader // activityReader := &activityReader{ // reader: resp.Body, // activityCh: activityCh, // activityPtr: &lastActivity, // } // // // 启动活动检测goroutine // activityCtx, activityCancel := context.WithCancel(context.Background()) // defer activityCancel() // // go func() { // ticker := time.NewTicker(30 * time.Second) // defer ticker.Stop() // // for { // select { // case <-activityCtx.Done(): // return // case activityTime := <-activityCh: // lastActivity = activityTime // case <-ticker.C: // if time.Since(lastActivity) > 60*time.Second { // printError("下载活动超时,60秒内没有收到数据") // cancel() // return // } // } // } // }() // // // 14. 下载进度显示 // startTime := time.Now() // var downloaded int64 = 0 // var lastUpdate time.Time // lastUpdate = time.Now() // // // 15. 创建缓冲区 // buf := make([]byte, 128*1024) // // // 显示初始进度 // fmt.Print(ColorCyan + "下载进度: 0.00% (0.00/0.00 MB)" + ColorReset) // // for { // select { // case <-ctx.Done(): // return fmt.Errorf("下载被取消: %v", ctx.Err()) // default: // } // // n, err := activityReader.Read(buf) // if n > 0 { // if _, writeErr := out.Write(buf[:n]); writeErr != nil { // return fmt.Errorf("写入文件失败: %v", writeErr) // } // // downloaded += int64(n) // // if time.Since(lastUpdate) > 1*time.Second || err != nil { // if totalSize > 0 { // percent := float64(downloaded) / float64(totalSize) * 100 // elapsed := time.Since(startTime).Seconds() // speed := 0.0 // if elapsed > 0 { // speed = float64(downloaded) / elapsed / 1024 / 1024 // } // // remaining := time.Duration(0) // if speed > 0 && downloaded > 0 { // remainingSecs := float64(totalSize-downloaded) / (float64(downloaded) / elapsed) // remaining = time.Duration(remainingSecs) * time.Second // } // // fmt.Printf("\r\033[K"+ColorCyan+"下载进度: %.2f%% (%.2f/%.2f MB) 速度: %.2f MB/s 剩余: %v"+ColorReset, // percent, // float64(downloaded)/1024/1024, // float64(totalSize)/1024/1024, // speed, // remaining.Round(time.Second)) // } else { // elapsed := time.Since(startTime).Seconds() // speed := 0.0 // if elapsed > 0 { // speed = float64(downloaded) / elapsed / 1024 / 1024 // } // fmt.Printf("\r\033[K"+ColorCyan+"已下载: %.2f MB 速度: %.2f MB/s"+ColorReset, // float64(downloaded)/1024/1024, // speed) // } // lastUpdate = time.Now() // } // } // // if err != nil { // if err == io.EOF { // break // } // if ctx.Err() != nil { // return fmt.Errorf("下载中断: %v", ctx.Err()) // } // return fmt.Errorf("读取数据失败: %v", err) // } // } // // // 16. 下载完成,显示最终进度 // if totalSize > 0 && downloaded < totalSize { // downloaded = totalSize // } // // if totalSize > 0 { // fmt.Printf("\r\033[K"+ColorGreen+"下载完成: 100.00%% (%.2f/%.2f MB)\n"+ColorReset, // float64(downloaded)/1024/1024, // float64(totalSize)/1024/1024) // } else { // fmt.Printf("\r\033[K"+ColorGreen+"下载完成: %.2f MB\n"+ColorReset, // float64(downloaded)/1024/1024) // } // // activityCancel() // // // 17. 验证下载的文件大小 // if totalSize > 0 { // fi, err := os.Stat(tempPath) // if err != nil { // return fmt.Errorf("无法验证下载文件: %v", err) // } // if fi.Size() != totalSize { // return fmt.Errorf("文件大小不匹配: 期望 %d 字节, 实际 %d 字节", totalSize, fi.Size()) // } // } // // // 18. 将临时文件重命名为目标文件 // maxRetries := 5 // for i := 0; i < maxRetries; i++ { // if err := os.Rename(tempPath, outputPath); err == nil { // downloadSuccess = true // break // } // // if i == maxRetries-1 { // if err := copyFile(tempPath, outputPath); err != nil { // return fmt.Errorf("保存文件失败: %v", err) // } // downloadSuccess = true // } else { // time.Sleep(500 * time.Millisecond * time.Duration(i+1)) // } // } // // // 19. 验证最终文件 // fi, err := os.Stat(outputPath) // if err != nil { // return fmt.Errorf("最终文件验证失败: %v", err) // } // // elapsed := time.Since(startTime) // speed := float64(fi.Size()) / elapsed.Seconds() / 1024 / 1024 // printSuccess("下载完成: %s (大小: %.2f MB, 耗时: %v, 平均速度: %.2f MB/s)", // filepath.Base(outputPath), // float64(fi.Size())/1024/1024, // elapsed.Round(time.Second), // speed) // // return nil //} // //type activityReader struct { // reader io.Reader // activityCh chan<- time.Time // activityPtr *time.Time //} // //func (r *activityReader) Read(p []byte) (n int, err error) { // n, err = r.reader.Read(p) // if n > 0 { // now := time.Now() // r.activityCh <- now // if r.activityPtr != nil { // *r.activityPtr = now // } // } // return //} // //func copyFile(src, dst string) error { // source, err := os.Open(src) // if err != nil { // return err // } // defer source.Close() // // destination, err := os.Create(dst) // if err != nil { // return err // } // defer destination.Close() // // _, err = io.Copy(destination, source) // return err //}