From f9994885d04e134074796b10e24f60d339dafcce Mon Sep 17 00:00:00 2001 From: QiuSW <105186638@qq.com> Date: Tue, 6 Oct 2026 14:19:12 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=94=AF=E6=8C=81=E5=90=8C=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=20ffprobe=20=E5=B9=B6=E5=9C=A8=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E6=97=B6=E6=A3=80=E6=9F=A5=20(#34)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 16 +++++++++ build.bat | 10 +++--- docs/04-local-development-and-verification.md | 8 +++-- frontend/src/App.vue | 15 +++++++- internal/downloader/downloader.go | 36 +++++++++++++++++-- internal/downloader/downloader_test.go | 20 +++++++++++ 6 files changed, 95 insertions(+), 10 deletions(-) diff --git a/app.go b/app.go index bdf3c5c..ace1264 100644 --- a/app.go +++ b/app.go @@ -79,6 +79,11 @@ func (a *App) startup(ctx context.Context) { }) a.log.Info("cmsp 启动") + go func() { + if err := downloader.CheckFFProbe(); err != nil { + a.log.Warn("视频校验工具不可用:%v", err) + } + }() cfg, err := config.Load(a.cfgPath) if err != nil { @@ -130,6 +135,11 @@ func (a *App) GetConfig() config.Config { return a.cfg } +// CheckFFProbe 供启动界面显示视频校验工具是否就绪。 +func (a *App) CheckFFProbe() error { + return downloader.CheckFFProbe() +} + // SaveConfig 校验并保存配置。 // // 返回的 error 会变成前端的 Promise reject,界面直接把消息弹出来, @@ -386,6 +396,9 @@ type UploadPreview struct { // FetchVideosForProduct 为一个商品依次搜同款、提取视频并下载到本地。 // 单商品入口与批量任务共用 prepareVideoFetch;这里保持原有串行下载行为。 func (a *App) FetchVideosForProduct(productID string) (FetchResult, error) { + if err := downloader.CheckFFProbe(); err != nil { + return FetchResult{ProductID: productID}, err + } ctx := a.appContext() riskGuard := task.NewEmptyRiskGuard(a.cfg.Download.RiskEmptyThreshold) result, work, err := a.prepareVideoFetch(ctx, productID, riskGuard, make(taobao.DetailCache), &taobao.LoginGuard{}) @@ -869,6 +882,9 @@ func (a *App) StartVideoTask(productIDs []string) error { if len(productIDs) == 0 { return fmt.Errorf("请先勾选要处理的商品") } + if err := downloader.CheckFFProbe(); err != nil { + return err + } a.videoTaskMu.Lock() defer a.videoTaskMu.Unlock() diff --git a/build.bat b/build.bat index c34d562..a024416 100644 --- a/build.bat +++ b/build.bat @@ -8,8 +8,8 @@ rem rem ============================================================ rem cmsp ´ò°ü½ű¾ rem -rem ˫»÷±¾Îļþ£¬°ѳÌÐò´ò°ü³Éһ¸ö exe£¬¿ÉÒÔֱ½ӷ¢¸øͬÊÂʹÓᣠ-rem ²úÎïÔÚ build\bin\cmsp.exe¡£ +rem Copy cmsp.exe and ffprobe.exe together to the target computer. +rem Build output: build\bin\cmsp.exe. rem rem ֻÊÇÏë¸ĴúÂ뿴Ч¹û£¬Çë˫»÷ run_dev.bat£¬²»ҪÓÃÕâ¸ö¡£ rem ´ò°ü±ȿª·¢ģʽÂýºܶࡣ @@ -172,11 +172,11 @@ echo ============================================================ echo ´ò°ü³ɹ¦ echo ============================================================ echo. -echo ²úÎ%CD%\build\bin\cmsp.exe +echo Build output: %CD%\build\bin\cmsp.exe for %%f in ("build\bin\cmsp.exe") do echo ´óС£º%%~zf ×ֽÚ echo. echo ·¢¸øͬÊÂʱµÄעÒâÊÂÏ -echo - ֻ·¢ cmsp.exe ¾͹»Áˣ¬ËüÒѾ­°ѽçÃæ´ò°ü½øȥÁË +echo - Copy cmsp.exe and ffprobe.exe into the same folder. echo - [±ØÐë] ²»Ҫ°Ñ config.yaml һÆ𷢳öȥ£¬ÀïÃæÓÐÕ˺ÅÃÜÂë echo - [±ØÐë] ²»Ҫ°Ñ cmsp.db һÆ𷢳öȥ£¬ÀïÃæÓеǼ״̬ echo - ¶Է½µÚһ´δ򿪺󣬵½¡¸²ÎÊýÉèÖá¹ҳÌî×ԼºµÄÕ˺Å @@ -185,7 +185,7 @@ echo echo - Microsoft Edge WebView2 ÔËÐÐʱ echo ^(Win10 һ°ã×Դø£»ûÓеϰ³ÌÐò»áÌáʾȥװ^) echo - Google Chrome ^(ÓÃÀ´µÇ¼ÌԱ¦^) -echo - ffprobe ^(ÓÃÀ´УÑéÏÂÔصÄÊÓƵÊǷñÍêÕû^) +echo - ffprobe.exe in the same folder as cmsp.exe ^(no PATH setup needed^) echo. rem ´򿪲úÎïËùÔÚĿ¼£¬ʡµÃÊֶ¯Õҡ£ diff --git a/docs/04-local-development-and-verification.md b/docs/04-local-development-and-verification.md index cfd688b..500bbf4 100644 --- a/docs/04-local-development-and-verification.md +++ b/docs/04-local-development-and-verification.md @@ -2,12 +2,16 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Local-Development-and-Verification wiki_url: https://git.ilapage.cn/chengma/cmsp/wiki/Local-Development-and-Verification.- -wiki_revision: ebd03ea3ee41b327b1ed7dd4070f918a586cf4f2 -synchronized_at: 2026-10-05T10:01:41Z +wiki_revision: 71370ea41be2c2da57519d75c4da44f9dbe81ce5 +synchronized_at: 2026-10-06T06:15:48Z # 本地开发与验证 +## 跨电脑运行的 ffprobe(2026-10-06) + +下载与上传前的视频完整性校验需要 `ffprobe.exe`。将打包后的 `cmsp.exe` 与 `ffprobe.exe` 复制到目标电脑的**同一目录**,无需在目标电脑配置 PATH。程序优先使用同目录文件;开发环境未放同目录文件时才查找 PATH。启动时若缺失或无法运行,界面与运行日志会提示;批量取视频在开始前也会检查,避免逐商品下载后才失败。`build.bat` 只生成 cmsp.exe,不会自动复制 ffprobe.exe;交付时须一并复制,不要复制本机配置、数据库或浏览器 Profile。 + ## 批量上传并发与选择范围(2026-10-05) `upload.concurrency` 在本机 `config.yaml` 中配置,默认 1、允许 1—4;`config.example.yaml` 给出示例,参数设置页可修改并保存。旧配置缺字段保持串行;该值与仅控制 CDN 文件下载的 `download.concurrency` 独立。`app_upload.go` 对不同商品有界并行,单商品幂等键、未决操作只查原键、批次互斥及 `succeeded` 才写本地完成状态的规则不变。模拟 HTTP/临时 SQLite 的 `TestUploadBatchRespectsConfiguredConcurrency` 覆盖默认串行和并发 3,配置测试覆盖旧文件默认、保存读回与非法值;真实批量写入及 ERPGo 限流需单独验收。 diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 8737742..b8bd404 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -5,13 +5,14 @@ * 页面切换用 v-show 而不是 v-if,这样从设置页切回商品列表时 * 表格不用重新查一遍数据库。 */ -import { ref } from 'vue' +import { onMounted, ref } from 'vue' // 组件已在 main.js 里整体注册,这里只取中文语言包。 import { zhCN, dateZhCN } from 'naive-ui' import Sidebar from './components/Sidebar.vue' import LogWindow from './components/LogWindow.vue' import ProductListView from './views/ProductListView.vue' import SettingsView from './views/SettingsView.vue' +import { CheckFFProbe } from '../wailsjs/go/main/App' // 'list' 或 'set' const page = ref('list') @@ -19,6 +20,15 @@ const collapsed = ref(false) const showLogs = ref(false) const taobaoOk = ref(false) +const ffprobeError = ref('') + +onMounted(async () => { + try { + await CheckFFProbe() + } catch (err) { + ffprobeError.value = String(err) + } +})