Files
lingxi/docs/评估/_调研/dewu-调研报告.md
T
Stev_Wang 6096568621 docs: 新增双项目整合评估、调研报告与技术栈架构定稿
- 新增双项目整合可行性评估 V0.1 rev.2:覆盖度矩阵、方案对比、目标架构、工作量/TCO、风险与决策清单
- 新增 dewu/sucaigongfang 两份调研报告(内部资料,平台敏感值已脱敏)
- 新增技术栈与架构定稿 V1.0:Node 24.15.0 / pnpm 11.4.0 / Prisma 7.10.1 / PostgreSQL 18 / Redis 7
- 更新 README 文档索引与仓库结构
2026-10-30 14:13:00 +08:00

83 KiB
Raw Blame History

dewu-material-Downloader 调研报告

调研对象:参考项目/dewu-material-Downloader/(应用名「得物素材助手」,v2.7.0,git HEAD fe7646b)。 密级:内部;文中平台接口/签名等敏感信息已脱敏,原文见受控知识库。 调研方式:只读通读源码与文档,交叉核对 git 历史、CI 配置与构建脚本;未安装依赖、未运行构建、未修改参考项目。凡文档与代码冲突处,以代码为准,并在文中注明文档已过时的位置。 路径简写:下文 dw/ = 参考项目/dewu-material-Downloader/;dw:line 均指该仓库内文件行号。 数字口径:LOC 用 find <dir> -name '*.ts' -o -name '*.tsx'(scripts 为 *.mjs/*.cjs)+ wc -l,口径在 §7.1 写明;文件数不含 node_modules/、dist/、dist-electron/、release/、.cache/、.probe-material-page/、review/ 等产物或本地取证目录。 调研时间:2026-10-30。


0. 结论速览

  • 一句话定位:这不是一个简单的「下载器」,而是得物「星光平台」软广素材的桌面端运营工作台——已从 v1 的「登录→抓素材→下视频」演进为「素材下载 + 商品查询 + 素材审核查询 + 批量送审/混剪送审 + DPLink 一键复制」五段闭环。
  • 端形态:Electron 44 单窗口桌面应用(Windows 为主力历史平台、macOS 为当前开发/验证机;Linux 有配置但未验证);contextIsolation: true + preload 白名单;React 19 + Semi Design 2 + Tailwind 3 + Playwright(dw/package.json:3、dw/electron/main.ts:1)。
  • 成熟度:v2.7.0;git 记录 228 个提交 / 21 个 tag / 2026-05-23 → 2026-10-22(约 5 个月;最后 tag 为 v2.4.0,2.5.0–2.7.0 未打 tag,仅有 release 提交);功能覆盖深、但真机验证不均(送审非混剪已端到端成功,混剪「是」分支未真机;素材审核页仍挂 BETA)。
  • 质量基线:TypeScript strict 全开、tsc --noEmit 是 CI 第一道门禁;无单一测框架(无 vitest/jest),但有 32 个验证脚本、15,411 行、CI 三个 job(verify:ui v2.7.0 记录 480 条通过、verify:platform 260 条通过;脚本内 ok() 断言点分别为 472/255);无 ESLint/Prettier 配置。
  • 体量:src/ 19,120 行(67 个 ts/tsx)、electron/ 17,345 行(45 个 ts)、scripts/ 27,828 行(73 个 mjs/cjs)、release-scripts/ 875 行(mjs/cjs,不含 .sh/README 的 622 行),合计 65,168 行;另有 CSS 3,675 行、docs 30 篇 Markdown 14,633 行。
  • 最大的整合事实:它只覆盖 得物/星光一个平台(全仓检索不到唯品会/vipshop 代码),且只覆盖 PRD 的 P-01/P-04 与 P-05 的一部分;P-02 图片模板、P-03 视频 AI、P-06 多平台、P-07 资产管理完全不含。新平台这两条产线必须另起,不能指望从本项目迁移。
  • Web 化的核心结论:「读」链路可以做到无浏览器(签名 + 只读接口已验证,纯 Node 可复现);「写」链路(送审)必须保留服务端浏览器自动化(平台上传走页面第一方 SDK + duToken 网关,重放成本高且易踩风控);Electron 外壳能力(内嵌 webview、本地文件路径、FTP Cookie 同步、safeStorage、自动更新、代码签名)全部重写或废弃。

0.1 结论表(能力域 → Web 化结论)

能力域 Web 化结论 关键原因 粗估人日
登录态(接口验证码登录 / 浏览器兜底 / Cookie 同步) 服务端重写 单账号单会话;凭据是本机 safeStorage 加密文件 + FTP 静态共享;服务端需多用户账号归属与 KMS 加密 8–12
素材读取(软广素材库列表/详情、审核列表、枚举) 改造复用 只读接口 + MD5 签名 + 信封解析已跑通,纯 Node 可复现;去掉 Electron 直接作为服务端模块 5–8
原始物料下载(含任务工作台 UI + 视频 CDN 直连 + 商品图/主视频) 服务端重写 浏览器只用于「登录/兜底」;下载、MD5 去重、分批冷却可保留策略,但文件落盘改为对象存储/下载中心;UI 需按新设计系统重做 25–38
商品查询(SPU 解析 + 商品详情 + 素材 9 项) 改造复用 商品详情是 SSR HTML 直取,不需要浏览器;链接短链解析可服务端做 12–18(含 UI)
内嵌商品 H5 画布 + 净化模式 废弃 依赖 Electron <webview> + 移动端 UA + 持久分区;Web 端受 iframe/X-Frame-Options 限制,且价值低于「数据直取」 0(可选 3–5)
素材审核页(列表/筛选/驳回原因/上传记录/CSV) 改造复用 纯只读接口 + 平台枚举,无 Electron 依赖;UI 需按新设计系统重做 8–12
送审判定 / 命名解析 / 预检规则 直接复用 已是应用与门禁共用的纯逻辑(scripts/lib/submit-naming.mjs 等),零 Electron 依赖 3–5
批量送审(页面自动化 + 上传 + 幂等 + 回查 + 账本/审计) 服务端重写 浏览器填表 + setInputFiles + 观察响应;服务端需浏览器池、大文件上传通道、会话串行;策略层可复用 26–37
混剪送审(双栏配对 + 源检索 + N 组提交) 服务端重写(UI 改造复用) 纯逻辑已抽到 scripts/lib/mix-submit.mjs;「混剪=是」写链路尚未真机验证 14–22
DPLink 一键复制 改造复用 纯算法 4/4 样本逐字符复现;仅两个只读接口 + 硬广凭据 5–8
应用设置 / 远端配置 / 日志 改造复用 配置分层、档位预设、白名单和签名机制可迁移;用户配置改服务端 DB 7–10
自动更新 / 关于页 / 旧版本清理 / 窗口状态 废弃 桌面应用专属(Squirrel/ShipIt、legacy-bundle、BrowserWindow maximize) 0–1
验证门禁与纯逻辑资产 改造复用 21 个 scripts/lib/*.mjs + fixtures + 32 个 verify 脚本,可直接转服务端单测/契约测试 6–10

人日为「分析员粗估、供排期参考」,含联调与验收、不含图片/视频 AI 产线;合计约 115–190 人日(逐项见 §8)。


1. 项目定位与业务链路

1.1 解决什么问题、给谁用

业务背景:得物「星光平台」是软广/KOL 投放的素材后台,素材库、审核、送审都在内网/H5 体系里,没有面向内部的开放 API,也没有批量下载能力。运营与剪辑的日常是:

  1. 在软广视频库里逐条点「预览」,复制视频地址,手工记录 媒体任务ID / 视频ID / SPUID / 投放类目 / 授权时间;
  2. 手工改名落盘,反复登录网页版导致桌面工具掉线;
  3. 剪辑后回到素材池「KOL原生二创素材上传」抽屉,逐条填投放渠道、媒体任务ID、视频ID、SPUID、挂 140–190MB 成片、点提交;
  4. 被拒后去审核列表逐条看驳回原因;
  5. 投放前再去星光「商品生成链接」页手工选落地页、商品,复制 iOS/Android 唤端链接。

目标用户:得物软广素材运营、剪辑、投放优化师(小团队、共享少数星光账号)。产品一直是内部效率工具,不是多租户 SaaS——这决定了它大量假设「一台机器、一个人、一个账号」。

1.2 主链路(端到端)

① 登录星光(接口验证码登录 / 浏览器登录兜底 / 云端 Cookie 同步)
   ↓
② 选品
   A. 素材下载页:输入 SPUID(可多个)→ 软广视频库筛选 → 提取素材
   B. 商品查询页:输入 SPUID / 商品链接 / App 分享文本 → 商品详情 + 9 项原始素材
   ↓
③ 原始物料获取
   A. 视频:按「媒体任务ID-视频ID-SPUID-类目-授权起-授权止.mp4」命名 → CDN 直连下载 → MD5 去重
   B. 商品图/主视频:按「<下载目录>/商品素材/<spuId>-<货号>-<标题前40字>/」落盘
   ↓
④ 本地剪辑 / 混剪(应用外,本仓库不覆盖)
   ↓
⑤ 提审:命名解析 → md5 本地查重 → 预检弹窗 → 页面自动化逐条提交 → 超时只回查不重试
   → 已送审 md5 账本 + JSONL 审计
   ↓
⑥ 审核查询:审核中/通过/不通过/全部 → 驳回原因、审核人、视频直链、上传记录 xlsx、CSV 导出
   ↓
⑦ 投放配置:商品查询页复制 iOS UniversalLink / 安卓 DeepLink(DPLink)

与旧版下载器的关键差异(git 历史可证):v1.x 只有 ①③(登录 + 下载)以及更新/设置;v2.0 加商品查询页;v2.1 收敛设置/远端配置/更新验签;v2.2 升 Electron 44 并落地 mac 签名公证;v2.3 把「读」接口化(P1);v2.4 加素材审核(P2);v2.5 加素材送审(P4)+ 改名 + mac 原生更新;v2.6 加 DPLink;v2.7 改为任务工作台、加混剪送审/素材预览/过滤开关。它已经是一个流程闭环产品,而不是单点脚本。

1.3 与 PRD 1.1 问题的对应关系

PRD 编号 PRD 问题 本项目覆盖度 证据 / 说明
P-01 原始物料:详情页图片逐张人工下载、分散存放 部分覆盖 商品查询页支持主图/详情图/主视频一键下载并按商品目录归档(dw/electron/shop/materials.ts:24-26);视频素材库支持按 SPUID 批量下载(dw/electron/platform/materials.ts)。只覆盖得物单平台,且无「本次选品物料库」概念
P-02 图片:三规格 × 四层信息人工排版 不覆盖 全仓无 PSD 解析、无模板合成、无 800×800/1280×720/1080×1920 产出代码
P-03 视频:依赖实拍与个人脚本经验 不覆盖 无脚本生成、无 AI 视频、无 TTS/画面组合
P-04 命名提审:手工改名与登记,进度散落 覆盖 命名规范 + 末三段解析 + 预检弹窗 + 批量送审 + 审核状态跟踪 + md5 幂等 + 审计(dw/electron/submit/*、dw/docs/送审命名规范与预检规则.md)
P-05 账户搭建:DP、承接页逐条复制 部分覆盖(仅 DPLink) 只做「商品 → 投放唤端链接」拼接与复制,不做 DP 编写、不做承接页字段批量替换(PRD 中 DP 的具体口径也待业务确认)
P-06 多平台:资源与口径不统一 不覆盖 全仓检索 唯品会/vipshop/vip.com 无命中;平台地址只有星光 + 得物商品站
P-07 资产管理:模板/脚本散落 不覆盖 无模板/脚本/Logo 资产库;仅有「落地页列表」与「商品库」两个只读数据源

结论:本项目是新平台「选品→原始物料→提审→投放链接」段的现成参考实现,但不是「图片/视频产线」的参考实现;新平台需要「得物作业端(迁移+增强) + 图片/视频产线(新建) + 多平台抽象(新建)」三块并行。


2. 功能模块清单(全量)

以 dw/src/App.tsx:240-306 的侧边栏 6 个入口 + 代码内实际存在的能力为准;「实现状态」按代码与文档的真实完成度标注(完整 / BETA / Phase 1 待真机 / 仅配置 / 未实现)。

模块 页面/入口 核心功能点 实现状态 关键文件:行 依赖 Electron 能力
素材下载 侧边栏「素材下载」/ SPUID 筛选(多值、中文分隔归一化、填写后显示各 SPUID 素材数);按页数/按数量两种范围;提取「拦截→接口→DOM 兜底」三级路径并显示读取方式;两个下载前过滤开关(30 天内到期 / 未授权快手);素材预览;分批+并发+随机延迟+指数退避+冷却;MD5 去重;任务详情/重试历史;打开下载目录/系统通知/日志导出;新建任务(保留前置条件) 完整(v2.7.0 真机可用) dw/src/pages/DownloadPage/index.tsx:250、dw/electron/browser/manager.ts、dw/electron/downloader/manager.ts、dw/electron/platform/materials.ts 是:Playwright、文件系统、dialog、通知、剪贴板、shell.openPath
商品查询 侧边栏「商品查询」/shop 输入 SPUID / 商品链接 / App 分享文本;左栏内嵌得物 H5 商品页(移动 UA + 独立持久分区 + 净化模式 + 导航白名单 + 右键菜单);右栏 SSR 直取商品卡片(标题/价格/货号/SKU/主图/详情图/主视频/来源链接);9 项素材格;下载范围「主图+视频 / 全部」;逐文件进度与取消;DPLink 两个复制按钮 完整(2026-10-22 摘除 BETA) dw/src/pages/ShopPage/index.tsx:426、dw/src/components/SpuCanvas.tsx、dw/electron/shop/session.ts:32-66、dw/electron/shop/detail.ts:11-27 是:<webview>、partition、dialog、文件系统
素材审核 侧边栏「素材审核」/review 审核中/通过/不通过/全部 4 Tab + 总数;按素材ID、审核时间、上传时间筛选;列表(32 条/页,与网页版一致);详情弹窗(视频、字段、审核人);驳回原因富文本(白名单 AST,不 dangerouslySetInnerHTML);上传/送审记录(含 xlsx 预签名下载);勾选行导出 CSV;权限前置「建议而非硬拦」 BETA(数据来自平台接口,界面仍按反馈调整) dw/src/pages/ReviewPage/index.tsx:627、dw/src/pages/ReviewPage/ReviewTable.tsx、dw/electron/platform/reviews.ts:43-48、dw/scripts/lib/review-csv.mjs 否(只读 HTTP);CSV 落盘用 dialog
批量送审 素材审核页「批量送审 / 选文件夹」→ 预检弹窗 → 进度浮层 命名两模式解析(文件夹名恰好三段 / 文件名末三段);SPUID 回显;md5 流式查重 + 已送审账本;批内去重;就地改 ID / 批量补 SPUID / 冲突二选一;逐条开抽屉→选混剪=否→投放渠道→填 3 字段→setInputFiles→等上传→提交→观察响应;超时只回查;掉线停批;审计 JSONL 完整(非混剪链路 2026-10-16 端到端成功 1 条;离线门禁全绿) dw/src/pages/ReviewPage/SubmitPrecheckModal.tsx、dw/electron/submit/page.ts:47-110、dw/electron/submit/batch.ts:1-40、dw/electron/submit/verify.ts 是:Playwright、dialog
混剪送审 素材审核页「混剪送审」→ 双栏配对弹窗 成品文件名只取末段 SPUID;右栏按 SPUID 自动检索平台素材/本机下载库;授权状态(有效/≤30天/已过期/未生效/长期/未知);N 组 {xtTaskId, videoId} 配对;提交前校验配对/渠道/SPUID 一致性/组数;页面自动化选「混剪=是」并回读组数 Phase 1 已落地,待真机(「混剪=是」写链路未验证) dw/src/pages/ReviewPage/MixSubmitModal.tsx、dw/electron/submit/mix.ts、dw/electron/platform/source-search.ts、dw/scripts/lib/mix-submit.mjs 是:Playwright、dialog
送审进度 全局浮层 + 页面卡片 逐条阶段(填表/上传/提交/回查)、成功/跳过/失败/未知、可中断(当前条跑完即停)、切页不中断、可按 md5 看审计尾部 完整 dw/src/pages/ReviewPage/SubmitProgressPopover.tsx、dw/src/hooks/useSubmitProgress.ts 是(经 IPC)
DPLink 一键复制 商品查询页「复制 iOS DPLink / 复制安卓 DPLink」+ 设置「投放落地页」 拉落地页列表(含 flag/_gsign/navControl)、按 SPU 反查商品库 cSpuId、拼两层链接(内层整段 encode)、复制到剪贴板;硬广账号独立凭据、云端 accounts.dplink 分区、错误分类(未配置/无权限/未选落地页/不在商品库/网络) 完整(2.6.0;4 条样本 4/4 逐字符复现;依赖客户共享硬广账号) dw/src/pages/ShopPage/index.tsx:695-703、dw/electron/dplink/link.ts:39-41、dw/electron/dplink/account.ts:1-40 剪贴板(主进程 clipboard);凭据 safeStorage
登录态 侧边栏底部状态、登录弹窗、设置「账号与同步」 软广账号:接口发码/登录(不启浏览器)、浏览器登录兜底、无头/有头切换、登录预检(启动检测)、退出(只清本机+忽略云端);硬广账号:独立加密槽 + 独立登录;云端 Cookie 同步 v2(soft/dplink 分区、HTTP 拉、FTP 推、写后回读) 完整(接口登录 verify:login 9/9 实测;云端同步为遗留架构) dw/src/components/SidebarLoginStatus.tsx:32-74、dw/src/components/LoginDialog.tsx、dw/electron/platform/auth.ts:1-70、dw/electron/browser/cookieSync.ts:1-40 是:Playwright、safeStorage、FTP、文件系统
配置管理 侧边栏「应用设置」/config 分区清单:账号与同步 / 下载(路径、完成后自动打开、三档速度)/ 外观与启动(主题、启动最大化)/ 更新(启动检查、自动下载、退出安装)/ 投放落地页 / 诊断与日志(版本、日志、远端配置来源、忽略远端配置);未保存改动导航守卫;恢复默认 完整 dw/src/pages/ConfigPage/index.tsx:716-1180、dw/electron/config/default.ts:52-72、dw/electron/config/presets.ts:59-102 是:dialog、safeStorage、BrowserWindow
远端配置 设置「诊断与日志 → 远端配置」 Ed25519 验签、JSONC 解析、白名单+区间校验、revision 单调、三级回退(远端→缓存→内置)、紧急 disabled、送审总开关 enableSubmitReview 完整(线上 revision 2) dw/electron/config/remote.ts:1-40、dw/scripts/lib/remote-config-schema.mjs:32-80、dw/remote-config/app-config.json:26,72 否(HTTP GET)
运行日志 设置「诊断与日志」、下载/送审页 内存缓冲 + 按日文件(保留 7 个)+ 导出 + 打开目录 + 跨天切换 完整 dw/electron/logger.ts:41-101 是:文件系统、shell
自动更新 侧边栏「软件更新」/update 检查/下载/安装/跳过此版本/恢复提醒;更新元数据 .sig Ed25519 验签;强制更新、最低版本、更新说明 Markdown 渲染;mac 走 Squirrel 原生替换 .app 完整(CI 签名+公证+装订;本机 ad-hoc 包点更新会失败属预期) dw/src/pages/UpdatePage/index.tsx、dw/electron/updater/manager.ts:56-90,185,274-301 是:electron-updater、shell、app 生命周期
关于页 侧边栏「关于应用」/about 版本徽标、复制版本信息、日志入口、第三方许可清单/完整文本、企微反馈;无更新逻辑(跳更新页) 完整 dw/src/pages/AboutPage/index.tsx:23-59 是:clipboard、shell、许可文件路径
应用外壳 App.tsx HashRouter 6 页、侧边栏、主题(亮/暗/跟随系统)、4 页骨架屏、错误边界、退出二次确认、崩溃兜底、单实例锁、窗口最小尺寸/启动最大化、Cmd/Ctrl+, 打开设置 完整 dw/src/App.tsx:240-306,437-442、dw/src/contexts/*、dw/electron/window/state.ts 是:BrowserWindow、Menu、app 事件
浏览器组件分发 首次启动/设置提示 三级检测:PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH → 系统 Chrome → 自建服务器 manifest 下载;manifest Ed25519 验签 + sha256 + revision 精确匹配;无 CDN 回退(防无校验下载) 完整(曾有版本错配事故,已修并加门禁) dw/electron/browser/playwrightInstaller.ts:1-125,436、dw/scripts/lib/browser-manifest-trust.mjs 是:Chromium 下载/解压、文件系统
旧版本应用清理 macOS 启动弹窗 改名后新旧 .app 并存,检测旧包→移入废纸篓/访达显示/7 天稍后提醒;路径二次校验防后门 完整(仅 macOS) dw/electron/legacy/bundle.ts:33-64,60 是:shell、应用枚举
素材预览 / 过滤偏好 素材下载页 素材卡片首帧预览、已过滤卡片隐藏与计数、两个开关记 localStorage、DOM 兜底路径同一规则 完整(门禁 43 条;真实数据过滤比例待真机) dw/src/components/MaterialPreview.tsx、dw/scripts/lib/material-filter.mjs、dw/docs/素材下载过滤开关-实现说明.md 否(渲染层)
SPUID 素材数量即时查询 素材下载页筛选区 填完 SPUID 后显示各 SPUID 达人素材条数;最多 20 个、超出显式截断;单条失败不拖垮整批 完整 dw/src/components/SpuMaterialCounts.tsx、dw/electron/platform/materials.ts:112-140 否(只读接口)
混剪 Excel/CSV 导入(Phase 2) 方案文档 批量导入清单 未实现(仅文档 + 模板 xlsx) dw/docs/混剪素材批量上传-开发方案.md、dw/docs/混剪素材批量上传模板.xlsx —

核对说明:侧边栏只有 6 个一级入口,但「素材审核」页内聚合了 4 个写/读子能力(批量送审、混剪送审、上传明细、CSV 导出),菜单文字易让人低估其分量;「素材下载」页也不只是下载,而是任务工作台(提取、预览、过滤、结果分级)。另:PRD 语境里的「混剪素材」在本项目中不是下载分类,而是审核页的混剪送审(源素材检索 + N 组配对提交);下载侧只有「软广视频库素材」与「商品原始素材」两条链路。


3. 技术栈与架构

3.1 栈与关键版本

层 选型 版本(声明 → 实测) 说明
渲染层 React / react-dom ^19.3.0 → 19.3.0 无全局状态库;Theme/LoginStatus/UnsavedChanges 三个 Context
路由 react-router-dom ^6.20.0 → 6.30.3 HashRouter(Windows 打包后 BrowserRouter 失效的历史修复)
UI @douyinfe/semi-ui ^2.103.0 → 2.103.0 2026-10 全量从 Ant Design 迁到 Semi(commit bf350ae);@douyinfe/semi-vite-plugin
样式 Tailwind CSS / PostCSS ^3.4.0 → 3.4.19 大量页面级 CSS + Semi token 变量(--semi-color-*)
图标 @remixicon/react ^4.9.0 → 4.9.0 统一图标库(src/icons.tsx 173 行)
Markdown marked ^18.1.0 → 18.1.0 发版说明渲染(Changelog.tsx)
桌面 Electron ^44.7.0 contextIsolation + preload;主进程 ESM 打包为 dist-electron/main.js
浏览器自动化 playwright ^1.40.0 → 1.60.0(⚠️ 漂移) 核心能力:登录、DOM 兜底、送审抽屉自动化、上传
构建 Vite + vite-plugin-electron 5.4.21 / 0.28 三份构建配置(frontend 配置为死文件)
打包 electron-builder ^26.15.3 Win NSIS / mac dmg+zip / Linux;extraResources 分发许可文本
更新 electron-updater ^6.8.9 generic provider + 自建签名元数据
其他 basic-ftp、adm-zip、fs-extra 6.2.3 / 0.6.1 / 11.3.5 Cookie FTP 同步、Chromium zip 解压
类型 TypeScript ^5.3.0 → 5.9.3 strict / noUnusedLocals / noUnusedParameters / noFallthroughCasesInSwitch 全开(dw/tsconfig.json)

3.2 进程模型与数据流

Renderer(React,HashRouter,6 页)
  └─ window.electronAPI(preload.ts contextBridge,唯一通道)
       ├─ invoke/handle:87 条(请求-响应)
       └─ on/send:14 条单向事件(进度/登录态/更新)
Main(Electron)
  ├─ ipc/handlers.ts(1822 行,模块级单例协调层,唯一组装点)
  │    ├─ BrowserManager(Playwright 会话、登录、提取、送审编排,1962 行)
  │    ├─ DownloadManager(下载、MD5、分批/并发/重试,516 行)
  │    ├─ PlaywrightInstaller(浏览器分发,864 行)
  │    ├─ configManager(三层配置:用户/档位/开发者 + 远端覆盖)
  │    ├─ platform/*(只读接口层:client/http/sign/auth/materials/reviews/cache/authorization)
  │    ├─ submit/*(写链路:page 自动化 / batch 执行器 / plan 会话 / verify 回查 / idempotency 账本 / audit)
  │    ├─ shop/*(商品查询:webview 承载 / SSR 直取 / 素材下载)
  │    ├─ dplink/*(硬广凭据 + 只读商品库/落地页 + 拼链)
  │    └─ updater / logger / legacy / task-state / window-state

文件落盘:主进程是唯一写文件的地方——userData/config.json、cookies.json、dplink-*.json、platform-cache/*、submit-audit.jsonl、submit-payloads.jsonl、remote-config.cache.json、logs/、下载目录(默认 ~/Downloads/得物素材 或用户指定)。渲染层无文件系统权限,所有落盘必须经 IPC(CSV 导出、日志导出、下载目录选择)。

关键约束(详见 dw/docs/新功能开发计划.md:455-475):

  1. 业务写只走页面自动化,绝不直接调用写接口;唯一豁免是登录(electron/platform/auth.ts 只含两条硬编码路径且不重试);
  2. 不另开浏览器 context(平台单账号单会话,另开会被判新会话并踢掉自己);
  3. 提交超时只回查、不重试;
  4. 筛选/取数失败显式失败,不静默降级为「下载全部」;
  5. 选择器不绑哈希类名(previewBtn___* 集中到 legacySelectors.ts,仅 DOM 兜底可用)。

3.3 IPC 契约(按域汇总,不逐条贴参数)

域 通道数 主要用途 事件 定义位置
browser:* 24 启停、登录预检/登录/退出、发码/验证码登录、切换无头、导航/分页/提取、保存 Cookie、浏览器组件安装 browser:loginStateChanged、browser:download:progress dw/electron/ipc/channels.ts、dw/electron/preload.ts:5-100
submit:* 16 可用性、选文件/解析、md5 计算、起批、混剪选成品/检索/计算/起批、中断、状态快照、审计尾部、忘记已送审 submit:md5Progress、submit:batchProgress dw/electron/preload.ts:190-240
update:* 11 检查/下载/安装/跳过/恢复/状态 + 5 个事件 进度/可用/无更新/已下载/错误 dw/electron/preload.ts:300-380
platform:* 10 签名自检、取素材页/详情、SPUID 数量、预览、审核列表、上传记录、枚举、标签树、账号详情 — dw/electron/platform/*
dplink:* 9 硬广账号状态/发码/登录/复核/退出、落地页列表/读取/保存、按 SPU 拼链 — dw/electron/dplink/*
download:* 8 开始/停止/统计/打开目录 + 4 个事件 进度/完成/汇总/状态 dw/electron/downloader/*
shop:* 6 承载配置、链接解析、商品详情、素材下载、取消 + 进度事件 shop:downloadProgress dw/electron/shop/*
config:* 4 读取/保存/恢复默认/刷新远端配置 — dw/electron/config/*
legacy:* 4 检测/移入废纸篓/访达显示/7 天稍后 — dw/electron/legacy/bundle.ts
log:* 3 日志目录/导出/打开 — dw/electron/logger.ts
其他 6 通知、剪贴板、许可、dialog、shell.openExternal、review 导出 CSV — dw/electron/ipc/channels.ts
合计 101 87 invoke + 14 event — dw/scripts/verify-channels.mjs 断言唯一来源

通道名收口到 IpcChannel 常量表(dw/electron/ipc/channels.ts:1),verify:channels 静态守「handlers/preload 不得出现字符串字面量」——这是 2026-10 修掉的历史债(旧版 channels.ts 曾是死代码且含拼写错误)。

3.4 构建与发布链路

  • 开发:npm run dev(Vite + vite-plugin-electron 热重载);postinstall 是 playwright install chromium --dry-run,装依赖不会装浏览器。
  • 构建:build:web(licenses + tsc + vite build)与 build[:win|:mac|:linux](再跑 electron-builder)。
  • CI:三个 workflow——ci.yml(每次 push/PR:gates 20+ 步、ui-verify 480 条通过、package-size)、build-release.yml(仅 workflow_dispatch,Win 构建 + mac 签名/公证 + 产物断言 + 更新元数据签名 + GitHub Release + FTP)、build-chromium.yml(手动构建 Chromium 包 + manifest)。
  • 发版唯一入口:npm run release(scripts/release.mjs,改版本号 + 预检 + 门禁 + 推送 + gh workflow run),已移除 tag 触发后门。
  • 签名/信任根:远端配置 Ed25519、更新元数据 Ed25519、浏览器 manifest Ed25519 三把独立密钥;macOS Developer ID + 公证 + 装订(verify:mac-sign 断言产物本身)。

4. 数据模型与持久化

4.1 存储位置与形态(app.getPath('userData'))

数据 路径 形态 加密 说明
用户配置 config.json JSON 字段级 safeStorage(ftpPassword/cookieSyncKey 加 encrypted: 前缀) 明文可读;解析失败静默回退默认,不备份坏文件(排查坑)
软广 Cookie cookies.json safeStorage 整文件加密 是 跨机器复制解不开且静默解析失败(双刃剑)
硬广账号 dplink-account.json safeStorage 整文件 是 与软广凭据完全隔离,绝不注入浏览器上下文
硬广落地页设置 dplink-settings.json safeStorage 整文件 是 只在本机、不同步云端;旧明文首次读取自动迁移
平台枚举/标签树缓存 platform-cache/enums.json、label-tree.json JSON + fetchedAt 否 TTL 24 小时;过期仍返回并标 stale(离线可用)
已送审 md5 账本 platform-cache/submitted-md5.json JSON {version, md5s[], updatedAt} 否 无 TTL(100 年);原子写;审核列表回灌自愈
送审审计 submit-audit.jsonl JSONL 追加 否 每条结果/阶段/md5/groups;写失败不阻断送审
送审请求体快照 submit-payloads.jsonl JSONL 追加 脱敏后否 与同事「人工提交」做字段级对账
远端配置缓存 remote-config.cache.json JSON + .sig 校验后缓存 否 读缓存重新验签,防本地投毒
旧版本清理状态 legacy-bundle.json JSON 否 已处理/稍后提醒(7 天)
云 Cookie 上传临时文件 _cloud_cookies_upload.json JSON 明文 否 遗留 P1 风险:上传临时文件明文落盘
日志 logs/YYYY-MM-DD.log 文本,保留 7 个 否 内存缓冲 + 按日 + 跨天切换
本地操作偏好 localStorage download.skipExpiring、download.skipUnauthorizedChannel、submit.lastSpuId、最近 SPU 等 否 渲染层,生产 file:// 下可能不可用,读写全 try/catch

无 sqlite、无数据库:全部 JSON/JSONL;缓存写入一律「临时文件 + rename」原子写(dw/electron/platform/cache.ts:11-24)。

4.2 配置项全表

A. 用户项(PersistedUserConfig,dw/electron/config/default.ts:16-72)

键 默认 含义 远端可覆盖
theme light 亮/暗/跟随系统 否
downloadPath '' → ~/Downloads/得物素材 素材保存目录 否
downloadPreset balanced 下载速度档位(保守/均衡/快速) 档位数值可覆盖
autoOpenDownloadDir true 完成后打开下载目录 否
cookieCloudSync true 登录态云同步开关 否
checkUpdateOnStart true 启动检查更新 否
autoDownloadUpdate false 自动后台下载新版本 否
installOnQuit true 退出时安装已下载更新 否
ignoreRemoteConfig false 忽略远端配置(逃生口) 否
maximizeOnStart true 启动最大化(≠全屏) 否

B. 档位参数(downloadPresets,dw/electron/config/presets.ts:59-102)

参数 保守 均衡(默认) 快速 远端允许区间
maxConcurrent 2 3 5 1–10
retryTimes 5 3 3 0–10
downloadTimeout(秒) 180 120 90 30–600
downloadDelayMin/Max(秒) 3/8 1/3 0/1 0–30 / 0–60
batchSize 3 5 10 1–50
batchCooldownMin/Max(秒) 20/45 10/20 3/8 0–300 / 0–600
retryBaseDelay/MaxDelay(秒) 5/120 3/60 2/30 1–60 / 10–300

C. 远端可下发字段(dw/scripts/lib/remote-config-schema.mjs:32-53)

字段 类型 说明
platform.baseUrl URL 星光主站
platform.videoLibraryUrl URL 软广视频库页面
platform.updateCheckUrl URL 更新 feed
platform.cookieCloudUrl URL 云端 Cookie 读地址
platform.enableSubmitReview boolean(独立白名单) 送审总开关,内置默认 true,远端 false 一键止血
presets.{gentle,balanced,fast}.* number 档位数值覆盖,超区间整份拒收

D. 开发者项(dw/electron/config/developer.ts:65-160,不出现在 UI)

键 值/默认 说明
baseUrl / videoLibraryUrl / spuDetailUrlTemplate 星光 + fast.dewu.com/page/productDetail spuDetailUrlTemplate 不在远端白名单(要改需同时改白名单并重签)
updateCheckUrl / cookieCloudUrl http://dw_update.xinsenidea.com/... 明文 HTTP(历史债)
cookieSyncKey / ftpHost / ftpPort / ftpUser / ftpPassword / ftpRemotePath 仓库内明文默认值(developer.ts:130,135) 🔴 严重:凭据仍在源码与 git 历史中,Web 化前必须轮换并改为服务端密钥管理
timeout / headless 30 秒 / true 浏览器自动化内部参数,无 UI 开关
remoteConfigBootstrap.url/publicKey 远端配置地址 + Ed25519 公钥 信任根,不可远端下发
updateMetadataPublicKey Ed25519 公钥 与远端配置是两把独立密钥

4.3 下载文件命名与路径规则

视频素材(星光软广素材库):

{媒体任务ID}-{视频ID}-{SPUID}-{投放类目}-{授权开始日期}-{授权结束日期}.mp4
  • 空值哨兵:SPUID → 无商品ID;类目 → 未知类目;开始 → 无开始日期;结束 → 无限用日期;
  • -/unknown/空 均视为无值;长期授权 → 长期-长期;
  • 非法字符 < > : " / \ | ? * 替换为 _;
  • 落盘:先写 {name}.downloading{ext} 临时文件 → 校验 MD5 → rename 原子转正。
  • 证据:dw/electron/downloader/utils.ts:11-20,24-37、dw/electron/downloader/manager.ts:430(-internal.aliyuncs.com → .aliyuncs.com 内网转公网改写)。

商品原始物料(商品查询页):

<下载目录>/商品素材/<spuId>-<货号>-<标题前40字>/
    主图-01.jpg … 主图-06.jpg
    详情图-<段落名>-01.jpg …
    主视频.mp4
  • 取的是 SSR 载荷里的原图(cdn.poizon.com/pro-img/origin-img/...),不是页面 webimg.dewucdn.com 的压缩衍生图;详情图在 imageAndTextMap 下;
  • 证据:dw/electron/shop/materials.ts:24-26、dw/electron/shop/detail.ts:11-27,242-280。

提审文件命名(与下载命名刻意不同):

  • 模式 A(文件夹批量):文件夹名恰好 {媒体任务ID}-{视频ID}-{SPUID};
  • 模式 B(单文件批量):文件名末三段 = {媒体任务ID}-{视频ID}-{SPUID},前缀(日期/版本/商品名/授权期/剪辑师)只展示不校验;
  • 不兼容应用自己下载的 ID 在开头 的命名 → 明确判识别失败并标红,不会误提交;
  • 证据:dw/docs/送审命名规范与预检规则.md:20-75、dw/scripts/lib/submit-naming.mjs。

4.4 状态机

状态机 取值 说明/证据
登录态(渲染层) checking / logging_in / logged_in / not_logged_in / error / not_ready dw/electron/browser/manager.ts:46-55
提取/下载任务 idle → extracting → downloading → done/stopped/failed(渲染层 currentStep 0..3) dw/src/pages/DownloadPage/index.tsx:289,1562-1573
下载单文件结果 success / skipped / failed + retryHistory dw/electron/downloader/manager.ts:288-339
送审行状态 pending / warning / conflict / invalid / duplicate / already_submitted / submitted / failed / unknown dw/src/types/index.ts:511-520
送审批次结果 submitted / skipped / failed / unknown dw/electron/submit/batch.ts:1-30、dw/src/types/index.ts:792-802
混剪授权状态 valid / soon / expired / not_started / longterm / unknown dw/src/types/index.ts:629、dw/scripts/lib/mix-submit.mjs
审核状态(平台) 数字:待审核=1 / 通过=2 / 拒绝=3;字符串 toBeReviewed/reviewPassed/reviewFailed;Tab 另加「全部=null」 dw/scripts/lib/platform-material-mapping.mjs:424-506、dw/docs/星光平台API接口文档.md:551

4.5 去重与校验

  • 下载去重:按内容 MD5(不是文件名)。下载前一次性扫描目录建 md5 → path 映射;命中则跳过并写明「经md5校验,本地已存在相同的文件」。已知性能债:同步全量扫描 + 整文件读内存(dw/electron/downloader/manager.ts:174、dw/electron/downloader/utils.ts:78-100;评估文档 §5.1 标 P0)。
  • 送审去重:只按 md5,双向同步——提交成功后立即记账;每次打开审核页/回查把平台审核行的 md5 并进账本(换机/清 userData 后能自愈)。平台侧同样按 md5 在「提交」步查重(code:900 + msg 含 md5/重复/已送审),本地只是提前拦一次流量。
  • 签名/完整性:远端配置、更新元数据、浏览器 manifest 三处 Ed25519;安装包 sha512 由 electron-updater 校验;浏览器包 sha256 + revision 精确匹配。
  • 上传预检:原视频授权渠道(authedMediaIds 与投放渠道 deliveryMediaIds 求交集)、videoId↔xtTaskId 成对性、SPUID 回显、批内同名/同 md5、组数为 0 等。

5. 外部平台集成(重点)

5.1 星光平台(唯一外部平台)

域名与鉴权

项 值 证据
主站 https://material-manage.shizhuang-inc.com dw/electron/config/developer.ts:119(可由远端配置覆盖)
商品站 https://fast.dewu.com/page/productDetail?spuId=… dw/electron/config/developer.ts:124
CDN h5cdn.dewu.com、delivery-platform.dewucdn.com、delivery-platform.oss-cn-shanghai.aliyuncs.com dw/docs/星光平台API接口文档.md:19-24
凭据 Cookie materialAccessToken(非 HttpOnly,会话 Cookie)→ 请求头 authorization: <token> dw/docs/星光平台API接口文档.md:54-62
未登录 HTTP 401 + {"code":700,"msg":"请先登录"};hacking-kol 族则是 HTTP 200 + code:401 同上 §1.4
会话特性 单账号单会话:网页版登录会顶掉应用 token;应用内所有操作复用同一个 Playwright context dw/docs/星光平台送审与审核查询-可行性评估.md:1-120

登录方式(三条通道)

  1. 接口登录(主力,P1/P2 已上线):POST /platform/user/send-code → POST /platform/user/login → 响应体 data.token(实测长度 168);裸 Node 可完成,不启浏览器;GET /platform/user/detail 复核并取账号信息/权限菜单。实测 9/9(dw/electron/platform/auth.ts:1-70、dw/docs/接口登录通道-实现说明.md:146-169)。
  2. 浏览器登录(兜底):有头 Chromium 打开登录页,轮询 120 秒 + 登录后 detectLoginState() 再确认;成功后切无头;换账号时先清本地 Cookie。
  3. 云端 Cookie 同步(历史架构):HTTP GET cookies.json(带 X-Sync-Key)+ FTP 上传;v2 分区 accounts.soft / accounts.dplink,写时只替换自己的分区并回读校验;本地 safeStorage 加密。明文 HTTP + FTP 无 TLS,且是「全体共享一个账号」的传输方式(dw/electron/browser/cookieSync.ts:1-40)。

Cookie 保活:没有定时刷新/心跳。保活依赖三个检查点——① 启动时 probeLoginState() 无头校验;② 业务导航落到登录页时广播 not_logged_in 并抛错;③ 用户点侧边栏「重新登录」(清旧 Cookie 或以新 token 覆盖)。云端同步只发生在启动/登录/退出等节点,不是持续保活机制;平台无刷新 token 接口,token 失效只能重登。

接口清单(实测/代码在用;完整 106 条静态枚举见 API 文档 §9.3)

用途 方法 路径 证据
软广素材列表(含下载直链) POST /api/v1/h5/delivery-platform/v1/platform/soft-material/material-library/list dw/electron/platform/materials.ts:91、API 文档 §2.1
素材全字段详情 POST …/soft-material/material-library/detail dw/electron/platform/materials.ts:177、API 文档 §2.2
审核列表(状态/驳回原因/md5) POST …/platform/self-material/list dw/electron/platform/reviews.ts:43、API 文档 §3.1
上传/送审记录(含明细 xlsx 预签名) POST …/platform/self-material/publishRecord dw/electron/platform/reviews.ts:44、API 文档 §3.2
万能枚举(35 键:驳回原因/品牌/角色…) GET …/platform/common/config-list dw/electron/platform/reviews.ts:45、API 文档 §5.1
标签树 POST …/platform/material-label/label-tree dw/electron/platform/reviews.ts:46、API 文档 §3.3
账号信息 + 权限菜单 GET …/platform/user/detail dw/electron/platform/reviews.ts:48、API 文档 §6
发短信验证码 POST …/platform/user/send-code dw/electron/platform/auth.ts:66
验证码登录 POST …/platform/user/login dw/electron/platform/auth.ts:68
媒体多清晰度详情 POST /api/v1/h5/media-data-center/v1/media/query API 文档 §3.4(代码未接入)
SPUID 预检(标题/品牌/货号) POST …/soft-material/kol-native/spuid-check API 文档 §4.1(送审预检数据源)
OSS 直传凭证 POST /api/v2/h5/oss-platform/token/customize/stsToken/v2 API 文档 §4.2(由页面 SDK 调用,应用不实现)
登记 mediaId POST /api/v1/h5/media-center/v1/media/create API 文档 §4.4(由页面 SDK 调用)
提交审核(写) POST …/soft-material/kol-native/upload-derivative-material dw/electron/submit/page.ts:47、API 文档 §4.5
DPLink 落地页列表 GET …/platform/material-library/list-landing dw/electron/dplink/link.ts:39、DPLink 文档 §4.4
DPLink 商品库反查 cSpuId POST …/platform/material-library/list-commodities dw/electron/dplink/link.ts:41、DPLink 文档 §4.4

签名/加密/remote-config

  • 每个请求带 ?sign=<32位hex>:md5(按 key 升序拼接的 "key" + serialize(value) + SALT),SALT = <已脱敏;原值见受控文档>;GET 覆盖 query、POST 覆盖 JSON body(dw/scripts/lib/platform-sign.mjs:37,106、dw/electron/platform/sign.ts:18-36)。
  • 启动自校验:sign({}) 必须等于平台未登录时实际发出的签名(fe26befc…);盐变化时日志直接报「签名盐已变化」,避免把所有 401 误判成登录失效。
  • 平台前端常量(userId=1000000、bizSourceId=500041536、上传 appId=Jem7c…、OSS bucket/prefix)来自前端硬编码,应用侧应配置化而非再硬编码(API 文档 §1.6)。
  • 送审写链路不重放接口:用 page.setInputFiles 把文件交给平台自己的上传 SDK(含 md5/分片/OSS token/duToken 网关),应用只填表 + 点提交 + 观察响应。
  • remote-config 是应用自身的运维配置(非星光),见 §4.2;三把 Ed25519 密钥分别守护远端配置、更新元数据、浏览器 manifest。

CDN 直连下载与防限速

  • 下载不走浏览器:Node http/https.get 直连素材 url;把 -internal.aliyuncs.com 改写成 .aliyuncs.com(内网地址转公网);downloadWithRetry 指数退避 min(base*2^n, max);随机延迟、分批、批间冷却、并发信号量;文件名/目录规则见 §4.3(dw/electron/downloader/manager.ts:181-227,374-430)。
  • 商品图/视频下载同样直连 CDN,但只允许 poizon.com / dewu.com / dewucdn.com 三个域(IPC 入参防越权),带 User-Agent 与 Referer(dw/electron/shop/materials.ts:82-95,212)。
  • 已识别的限速/风控线索:平台按账号会话统计;应用刻意把详情并发限制为 4、SPUID 数量查询串行、不并发轰炸(dw/electron/platform/materials.ts:1-32,121-140)。

其他平台

  • 唯品会:无任何代码(全仓检索 唯品会/vipshop/vip.com 零命中)。PRD 的 P-06 多平台能力在本项目完全没有参考实现;sucaigongfang 项目是否覆盖唯品会需由另一份调研确认(本报告不越界)。

5.2 服务端(无 Electron、多用户并发)复现评估

集成点 服务端复现可行性 改造点 结论
只读接口(素材/审核/枚举/标签) 高:纯 HTTPS + 签名 + 信封,Node 即可 把 electron/platform/* 抽成服务端 SDK;token 从「本机加密文件」改为「用户/账号凭据服务」;加缓存与限流 直接迁移(工作量小)
登录(发码/验证码) 高:不需要浏览器 服务端接收用户手机号/验证码;token 加密落库(KMS/信封加密);处理短信频控与失败码未知问题 可迁移,但账号归属需重设计
会话模型(单账号单会话) 中:技术可行,业务冲突 必须按「账号」串行化(同一账号同一时刻只允许一个任务),或为不同用户分配不同账号;Web 多用户共享一个 token 会互相顶号 最大架构约束之一
素材下载(CDN 直连) 高 服务端可直接下载并转存对象存储;或下发签名 URL 让浏览器直下(省带宽);保留 MD5 去重与冷却策略,去重索引改 DB/Redis 可迁移
商品详情 SSR 直取 高 服务端 HTTP GET + 解析 __remixContext,无需 UA/浏览器;短链解析放服务端(域名白名单) 可迁移且更稳
内嵌商品 H5 / 净化 低 Web 端 iframe 受 X-Frame-Options/CSP 限制;Electron <webview> 无对应物。替代:只保留数据卡片 / 服务端截图(成本高、收益低) 建议废弃
送审写链路(页面自动化) 中:必须服务端浏览器 浏览器池 + 每账号一个 context + 上传通道(浏览器→服务端 140–190MB 或服务端代传 OSS)+ 队列/断点/回查/审计;风控暴露面从「单机」变成「机房 IP」 可做,但成本最高、风险最高
DPLink 高:纯算法 + 两个只读接口 硬广账号凭据独立密钥槽;落地页配置存用户/项目级;错误分类保留 最划算的迁移项
Cookie 云同步(HTTP+FTP) 低:架构应废弃 改为服务端凭据库(加密、审计、按用户/账号授权);FTP 与明文 HTTP 不应保留 废弃并重写
自动更新/浏览器分发/代码签名 不适用 Web 无客户端分发;服务端浏览器镜像由部署流水线维护 废弃
本机文件/账本/审计 中 本地 JSON/JSONL → 数据库表;文件下载 → 对象存储 + 下载中心;路径语义(下载目录)改为「云端素材库/导出任务」 需数据模型重设计

建议的 Web 目标形态(供后续架构评审):

  1. BFF + Worker 两层:BFF 走只读接口与元数据;Worker 承担 Playwright 浏览器任务(送审、登录兜底),按账号加分布式锁,任务状态落 Redis/DB,前端用 SSE/WebSocket 订阅进度(替代 IPC 事件)。
  2. 上传走「浏览器/客户端 → OSS 直传」:服务端只发 STS 临时凭证并登记 mediaId,避免 140MB 文件绕行应用服务器;必要时再让服务端浏览器 setInputFiles 指向挂载的临时对象。
  3. 凭据服务:平台 token 与硬广 token 分别加密存储(KMS + 信封),按「用户/项目/账号」授权;禁止再出现仓库内硬编码密钥。
  4. 账号串行化:以 accountId 为粒度排队;同一账号的下载/送审/审核查询并发需互斥(沿用现在 runExclusive 的思路,但改为分布式锁)。
  5. 只读优先:把「读」全部走接口(无浏览器),仅「写」用浏览器,显著降低风控暴露面与资源成本。

6. 关键机制与难点

6.1 Playwright 浏览器自动化

  • 登录/会话:smartStart 状态机——有会话且有效→复用;云端/本地 Cookie→无头启动注入→校验→写回;失败则有头手动登录(120 秒轮询)→切无头。所有会动会话的操作走 runExclusive 串行队列(dw/electron/browser/manager.ts:223,617-812)。
  • 读路径:先挂 page.on('response') 拦截页面自身列表响应(第 1 页),后续页/详情走接口;失败整体降级 DOM(点预览弹窗 + 解析字段)。DOM 兜底只保留一期,哈希类名集中在 legacySelectors.ts 并加门禁。
  • 写路径:开送审抽屉 → 定位 #deliveryMediaIds/#xtTaskId/#videoId/#spuIds/#url input[type=file] → setInputFiles → 等上传完成(最长 15 分钟)→ 点提交 → waitForResponse(SUBMIT_API_PATH)(60 秒)。选择器必须「限定抽屉内 + 按 label[title] 精确匹配」,否则会命中页面上的「KOL投放渠道」筛选框(真机踩坑记录 dw/electron/submit/page.ts:209-222、dw/docs/星光平台API接口文档.md:800-830)。
  • 难点:平台改版即失效(最高频维护工作);上传完成没有可靠事件,只能轮询百分比/表单回显;抽屉复用必须显式清空上一条残值;「提交超时」不能重试。

6.2 登录态托管

  • 本地 safeStorage 加密 + 云端 v2 分区共享;loginInteractive(force) 换账号;logout 只清本机并置 ignoreCloudCookies;启动预检 probeLoginState 用无头浏览器只校验、不弹窗。
  • 已知边界:单账号单会话(网页版登录会顶掉);接口登录失败码未实测;应用侧凭据落地(落盘/注入/云同步)仍需真人点一次才能验证;verify:login 刻意不进 CI(会发真短信、会让跑的人生效掉线)。

6.3 批量上传:并发/重试/断点

  • 串行而非并发(同一个浏览器会话,且上传本身占满上行);整批圈进 runExclusive,下载/送审互斥。
  • 可中断:中断请求在当前条跑完才停(避免半截抽屉 + 账本未落盘)。
  • 可续跑:账本按 md5 拦住已成功项;失败项不记账;「结果未知」只回查(3 次退避)不重试。
  • 重试:只有网络错误/5xx 才重试 1 次;提交响应超时绝不重试。
  • 失败显式:抽屉打不开、字段找不到、上传未完成 → 带 reasonCode 的 failed,并 dump 页面实况(抽屉数量、入口是否被遮、elementFromPoint)。

6.4 命名字段组合与预检规则

  • 命名只承载三要素(媒体任务ID/视频ID/SPUID),前缀不校验;末三段解析 + 文件夹名恰好三段双候选,冲突不自动挑、要求人工确认;无spuid 五种写法大小写不敏感;位数 ≠ 19 只警告不阻断。
  • 预检两段式:① 文件名解析(毫秒级,不读盘)先出结果;② md5 查重 + SPUID 商品标题回显(秒~几十秒,异步可取消)。只有 pending/warning 可勾选;失败可「就地修好」。
  • 送审前额外预检:原视频授权渠道、videoId↔xtTaskId 配对、SPUID 一致性、组数;「unknown 不阻断」是刻意保守策略(宁可白传一次,不可误拦)。

6.5 混剪任务

  • 成品只解析最后一个 SPUID;每条成品带 N 组 {xtTaskId, videoId};右栏从平台素材库或本机下载目录检索源,授权状态六档;已过期/未生效/明确未授权默认不勾;平台检索目前只取第一页(最多 30 条)、无「加载更多」;Phase 2 Excel/CSV 导入未实现。
  • 风险点:「混剪=是」的写链路(选「是」、增删行、无 id 的视频ID输入框、组数回读)尚未真机验证,只做了离线门禁。

6.6 错误码与重试

平台回答 应用行为 说明
code:200 成功,记 md5 成功必须看 code,不能只看 HTTP 状态
HTTP 401 + code:700 未登录:停止批次、侧边栏变红、指向重登 与平台故障区分
HTTP 200 + code:401 平台族故障(hacking-kol),不当作未登录 平台自身页面也报错
HTTP 200 + code:900 业务校验失败:必须看 msg;只有含 md5/重复/已送审 才当重复记账,否则按 failed 显式展示 曾因「只看 900」把业务拒绝误记成已送审
提交超时/无响应 unknown → 回查审核列表(3 次);命中记 submitted,未命中提示稍后刷新 绝不重试
网络错误/5xx 只读请求重试 1 次;下载按档位指数退避;发短信不重试 —

6.7 更新与代码签名(Web 化后大概率废弃,但资产有价值)

  • 桌面更新链路:electron-updater + 自建 feed;更新元数据 .sig Ed25519 验签 → 强制/最低版本/跳过版本;mac 走 Squirrel/ShipIt 原生替换 .app 并支持改名迁移;Win NSIS 静默安装。
  • 代码签名:mac Developer ID 签名 + 公证 + 装订 + 产物门禁;Win 目前无签名(历史状态)。
  • Web 化后这些全部消失,但可复用其设计模式:信任根不可远端下发、原始字节签名、灰度放行策略表、revision 单调、双密钥隔离。这些模式可直接用于新平台的「配置中心/发布系统」安全设计。

7. 代码规模与质量

7.1 规模(口径见页首)

目录 文件数 行数 主要内容
src/ 67(ts/tsx) 19,120 6 页 + 19 组件 + 3 Context + 1 Hook + 15 个 .d.ts + 1 个 types/index.ts
electron/ 45(ts) 17,345 IPC/浏览器/平台接口/送审/商品查询/DPLink/配置/更新/日志
scripts/ 73(mjs/cjs) 27,828 32 个 verify 脚本 + 21 个共享纯逻辑 + 探针/截图/发版/签名
release-scripts/ 5 875(mjs/cjs;含 .sh/README 共 1,497) 本机发版、mac 签名/公证、Windows 构建
合计 190 65,168 不含 CSS(3,675 行)与 docs(30 篇、14,633 行)

单文件 Top(复杂度集中点):DownloadPage/index.tsx 2,241 行;browser/manager.ts 1,962;ipc/handlers.ts 1,822;submit/page.ts 1,824;ConfigPage/index.tsx 1,241;SubmitPrecheckModal.tsx 1,035;ReviewPage/index.tsx 1,004;UpdatePage/index.tsx 896;playwrightInstaller.ts 864;ShopPage/index.tsx 841。

7.2 类型与规范

  • tsconfig.json:strict: true、noUnusedLocals、noUnusedParameters、noFallthroughCasesInSwitch;include: ["src","electron"];无 allowJs,因此 scripts/lib/*.mjs 靠手写 .d.ts 副本+ verify:type-declarations 门禁保证一致。
  • 无 ESLint / Prettier 配置(仓库根目录无相关文件);格式靠约定与 review。
  • any 仍有:preload.ts 51 处、handlers.ts 15 处、src 16 处(跨进程类型未共享,历史评估标 P1)。
  • 无全局状态管理库:Context + 页面内 state;下载/送审状态主进程持有,渲染层用事件订阅。

7.3 测试与质量门禁

层 现状
单元测试框架 无(无 vitest/jest,src/App.test.tsx 名不副实,是组件不是测试)
离线验证 32 个 verify:* 脚本,合计 15,411 行;verify:ui 5,283 行 / 472 个 ok() 断言点(v2.7.0 记录 480 通过;真实 Chromium 加载真实 dist/);verify:platform 2,352 行 / 255 个 ok() 断言点(v2.7.0 记录 260 通过;真实抓包 fixture + 静态边界);verify:channels 101 条通道唯一来源;verify:type-declarations 33 个导出;verify:mix 24;verify:filter 43
实机对比脚本 compare:extraction-paths、compare:review-list、compare:submit-payload(人工登录后跑,结果落盘对账)
CI ci.yml 三 job(gates / ui-verify / package-size);发版走 release.mjs + build-release.yml;历史教训「验证资产 10 个只有 1 个进 CI」已修
依赖审计 audit:prod 强制官方 registry(防 npmmirror 不支持 audit 导致「无漏洞」假象);critical/high 失败
已知质量债 大文件上帝模块;preload 大量 any;CSP 宽松(允许 http/https/ws/unsafe-eval 已移除但范围仍宽);scanDirectoryMd5 同步读内存;日志/控制台噪音;无前端虚拟列表;无端到端自动化(写链路靠人工真机)

7.4 文档与已知风险

  • docs/ 现有 121 个文件、30 篇 Markdown(14,633 行),包括:星光 API 接口文档(807 行,含签名盐与 106 条接口)、送审/审核可行性评估(928 行)、P1/P2/P4 实现说明、送审命名规范、混剪方案、DPLink 评估、远端配置运维手册、签名/公证清单、项目评估 2.1.0(1,063 行)等。
  • DEVELOPMENT.md 2,380 行,是以代码为准的交接文档,但其 §1-§14 基线停在 v1.0.6,已明显滞后于 v2.7.0;§17-§19 是后续补的登录态/商品查询/接口登录章节。新平台调研应优先信任代码与 2.x 的实现说明文档。
  • 已知问题与风险(代码/文档交叉确认):
    1. 🔴 仓库内仍硬编码运维凭据(cookieSyncKey、FTP 密码,dw/electron/config/developer.ts:130,135),且在 git 历史中;Web 化前必须轮换、改服务端密钥管理,不可沿用。
    2. 🟠 单账号单会话是平台行为(网页版登录顶掉应用 token);多用户 Web 化必须按账号串行/分账号。
    3. 🟠 明文 HTTP + FTP 无 TLS 用于更新/远端配置/Cookie 同步;新平台应拒绝此模式。
    4. 🟠 平台接口/页面结构随时可能变更:签名盐、字段、选择器、权限菜单;维护成本高(docs/ 多篇文档都在记录平台变更)。
    5. 🟡 Playwright 依赖声明 ^1.40.0 与实际 1.60.0 漂移(已有 verify:playwright-version 守版本→revision 映射,但锁文件仍应 pin)。
    6. 🟡 浏览器分发/更新/签名/旧包清理的复杂度对 Web 化无意义,但占主进程相当比例代码与文档。
  • DEVELOPMENT.md §12 列出「文档与实现的偏差」,docs/项目评估与优化建议-2.1.0.md 给健康度加权 3.0/5(产品完成度 4.5、安全信任链 2.0、测试质量 2.0、性能 3.0);其中 P0 缺陷多数已在 2.1.x-2.7.0 修复(重试退避、可重入、浏览器版本、验签),硬编码凭据与 MD5 扫描仍是历史遗留。

8. 逐模块 Web 化复用评估(核心交付)

复用级别:A=前端页面/组件几乎直接复用;B=改造成本可控;C=需服务端重写;D=废弃。人日为粗估(含联调,不含需求/设计评审)。

模块 现有实现 目标端形态 复用级别 改造要点 粗估人日 风险
应用外壳/导航/主题/骨架屏/错误边界 React + Semi + Tailwind;App.tsx 558 行 新平台 Shell A(结构)/B(视觉) 保留信息架构(侧边栏、页头、分区、骨架屏、未保存守卫);重写导航与主题 token;Semi 组件替换(见 §8.1) 3–5 低
素材下载 · 任务工作台 UI DownloadPage 2,241 行;阶段化布局、双重过滤、素材预览、结果分级、重试历史 新平台「原始物料获取」页 B 保留交互模型与状态机;Semi→新 UI;localStorage 偏好改用户配置;「打开目录/通知」改「导出到素材库/下载中心」 8–12 中(页面巨大、需重排信息层级)
素材提取(只读接口路径) platform/materials.ts、browser/manager.ts 拦截路径 服务端取数服务 B 直接用签名客户端;去掉浏览器与 DOM 兜底;保留「读取方式/降级」可观测语义 5–8 中(签名盐/接口变更)
下载引擎(CDN/MD5/限速/重试) downloader/manager.ts + utils.ts 服务端下载 Worker + 对象存储 C 文件系统→对象存储;MD5 扫描→DB/Redis 索引+流式 MD5;并发/冷却策略保留;临时文件/原子改名改为分片上传完成标记 12–18 中高(带宽/存储成本、平台限速)
商品查询 · 工作台 UI ShopPage 841 行 + ActionBar/MaterialGrid/useShopDownload 新平台「选品」页 B 保留「命令条+画布+面板+底栏」布局与 9 项素材格;去掉 webview 画布或改为可选;Semi→新 UI 8–12 中
商品详情 SSR 直取/短链解析 shop/detail.ts 359 行 服务端选品服务 B 服务端 HTTP + __remixContext 解析;短链解析+域名白名单;图片原图 URL 规则保留 4–6 低中(站点结构变更)
内嵌商品 H5 + 净化模式 SpuCanvas.tsx、shop/session.ts — D Web 端无法等价复现;最多保留「查看原页」外链或服务端截图 0(可选 3–5) 中(做了也价值低)
素材审核页 ReviewPage 1,004 行 + 6 子组件 + review-csv.mjs 新平台「提审/审核」页 B 只读接口直接迁移;表格/筛选/驳回富文本/CSV 逻辑保留;Semi→新 UI;权限提示保留「建议不硬拦」 8–12 中(平台字段/权限变化)
只读接口层(签名/客户端/缓存/授权预检) electron/platform/* 2,526 行 服务端 SDK B 抽包;凭据来源改注入;缓存改 Redis/DB;错误分类保留;authorization.ts 的「unknown 不阻断」策略保留 5–8 中(签名/接口契约)
命名解析/预检/CSV/过滤/进度模型等纯逻辑 21 个 scripts/lib/*.mjs + .d.ts 服务端/前端共用包 A 直接抽成 npm 包(保持「应用与门禁同一份实现」);补真单测 3–5 低
批量送审判定与编排 submit/plan.ts、idempotency.ts、audit.ts、verify.ts、batch.ts 服务端送审服务 B–C 策略层可复用(串行/中断/回查/记账/审计);存储改 DB;队列改任务系统;进度改 SSE 8–12 中高(写操作)
送审页面自动化(Playwright) submit/page.ts 1,824 行 服务端浏览器 Worker C 浏览器池 + 账号锁;选择器集中配置化;上传改「客户端→OSS→服务端挂载」;日志/证据链保留 18–25 高(平台风控/改版/大文件)
混剪配对 UI MixSubmitModal.tsx 683 行 新平台混剪送审页 B 双栏交互与授权状态保留;Semi→新 UI;补「加载更多」与 Excel Phase 2 8–12 中
混剪服务端编排 submit/mix.ts、source-search.ts、mix-submit.mjs 服务端 C 源检索(平台+本地下载库)改「平台素材库+云端素材库」;N 组配对校验保留;「混剪=是」需真机验证 6–10 高(未真机)
DPLink 拼装/复制 dplink/link.ts 420 行 + account.ts + dplink-link.mjs 服务端投放配置服务 B 纯算法与错误分类直接迁移;硬广凭据改 KMS;落地页配置改项目级;复制按钮保留(前端) 5–8 中(硬广账号权限/共用凭据)
登录态与账号体系 auth.ts、cookieSync.ts、SidebarLoginStatus、LoginDialog 平台账号中心 C 接口登录可迁移;浏览器兜底需 Worker;云端 FTP 同步废弃→凭据库;多用户账号归属/授权/审计重设计 8–12 高(单会话/账号归属/合规)
配置管理/远端配置 config/*(1,261 行)+ remote-config-schema.mjs 平台配置中心 B 用户项→用户级 DB;档位预设与白名单保留;远端配置改服务端配置中心(不必 Ed25519,除非仍需离线下发);enableSubmitReview 保留为运维开关 4–6 低中
日志/审计/诊断 logger.ts、submit/audit.ts 服务端日志/审计 B 本地文件→结构化日志/审计表;保留「审计只追加、写失败不阻断」的语义 3–4 低
IPC 通道层 101 条通道 / preload HTTP API + SSE/WebSocket C 契约可参考(通道名/入参/进度事件),实现全部重写;长任务改异步任务 + 订阅 5–8 中
自动更新/关于页/旧版清理/窗口状态 updater 438 行 + legacy + window state — D Web 无客户端;关于页可保留为「帮助/版本信息」薄页 0–1 低
验证门禁资产 32 个 verify 脚本 + fixtures 新平台测试套件 B .mjs 纯逻辑断言可直接用;真实抓包 fixture 可做契约测试;UI 断言(472 条)大部分随新 UI 失效,需重写 6–10 低中

合计粗估:约 115–190 人日(低值=理想路径、无返工;高值=含平台改版适配/联调/真机验证)。其中「送审页面自动化 + 账号体系 + 下载引擎」三项占 50% 以上,是 Web 化成败关键。

8.1 Semi Design 2 与新平台 UI 选型的冲突处理

冲突事实:当前 UI 是 2026-10 从 Ant Design 全量迁到 Semi Design 2.103(React 19),组件 API/主题/图标/表单校验/表格/弹窗都深度绑定 Semi;页面级 CSS 3,675 行大量使用 --semi-color-* token、@layer tailwind-utils 与 .semi-* 类名。如果新平台 UI 选型是 Ant Design/Arco/自研,组件层不能直接复用。

建议策略(按投入产出排序):

  1. 分层复用,不整体搬迁:把「纯逻辑 + 类型 + 接口封装 + 页面状态机」与「视觉组件」切开。前者(约 30–40% 代码量)跨 UI 库可复用;后者重写。
  2. 先定设计 token,再谈组件:把 Semi 的语义色/圆角/间距收敛成新平台 token(现在代码里已有集中化迹象:icons.tsx、PageHeader、ProgressRow、SettingsRow),避免把 --semi-* 变量原样搬进新平台。
  3. 只对高价值组件做适配层:表格(审核列表)、弹窗/抽屉(送审判定)、进度行、Toast 提示可写薄适配层;不要为每个组件做 Semi↔新库 shim(维护成本会超过重写)。
  4. 样式资产可复用的部分:布局类(.shop-*/.dl-*/.review-*)本质是 CSS Grid/Flex,可提取为设计系统布局原语;依赖 .semi-* 内部 DOM 的样式必须丢弃(verify:css-layers 也说明层叠顺序是精心维护的)。
  5. 如果新平台也选 Semi:可复用度显著提高(页面组件可近乎直搬),但仍需处理 React 版本、主题、路由与 Electron API 替换。建议在 UI 选型评审时把「是否 Semi」作为明确决策项,因为它直接决定 8–12 人日的差异。

9. 可复用资产清单

9.1 纯逻辑 / 协议层(最高价值,A 级)

资产 路径 价值
星光请求签名 + 序列化规则 + 自校验 dw/scripts/lib/platform-sign.mjs(含 SALT,敏感值已脱敏)、dw/electron/platform/sign.ts 服务端直连星光的关键;自校验能第一时间发现盐变更
平台字段映射 / 授权时间解析 / 审核状态映射 / 权限判定 dw/scripts/lib/platform-material-mapping.mjs(719 行) 与真实抓包逐字段对齐;P1/P2 的地基
送审命名解析 + 预检/载荷/审计记录形状 dw/scripts/lib/submit-naming.mjs(1,013 行) 新平台「命名规则 + 提审预检」可直接复用;有大量真实样本
混剪成品/源组/授权状态/结构校验 dw/scripts/lib/mix-submit.mjs(约 500 行) 混剪业务规则唯一实现
审核 CSV 构建 + 公式注入防护 dw/scripts/lib/review-csv.mjs 导出与界面列同源;安全细节可复用
驳回原因 HTML 白名单 AST dw/scripts/lib/reason-html.mjs(1,028 行) 平台自由文本渲染的安全方案(非 dangerouslySetInnerHTML)
素材过滤规则(30 天/渠道) dw/scripts/lib/material-filter.mjs 与 PRD「授权/到期」相关的业务规则
DPLink 拼装(双层/encode/常量) dw/scripts/lib/dplink-link.mjs 4 条样本 4/4 逐字符复现,可直接迁移
进度模型 / 送审进度模型 dw/scripts/lib/progress-model.mjs、submit-progress.mjs 统一进度语义与界面断言
远端配置 schema/白名单/区间 dw/scripts/lib/remote-config-schema.mjs 若新平台需要「运维不发版改配置」,可直接复用设计
Cookie 分区 bundle(v1/v2 兼容) dw/scripts/lib/cookie-bundle.mjs 多账号凭据分区与迁移思路;传输方式需重写
Ed25519 原始字节签名/验签 dw/scripts/lib/ed25519-signature.mjs、update-metadata.mjs、browser-manifest-trust.mjs 信任链设计可迁移到配置中心/发布系统

9.2 服务端候选代码(B 级,抽包后可用)

资产 路径 说明
只读 HTTP 客户端 + 信封解析 + 失败分类 dw/electron/platform/http.ts、client.ts、types.ts 超时/重试/响应上限/code 分类;与登录层共用一份
素材列表/详情取数(并发 4、降级可见) dw/electron/platform/materials.ts 直接改造成服务端模块
审核列表/记录/枚举/标签树 + TTL 缓存 dw/electron/platform/reviews.ts、cache.ts 缓存/TTL/stale 语义清晰
授权渠道预检(unknown 不阻断) dw/electron/platform/authorization.ts 送审前风控策略可直接用
商品详情 SSR 解析 + 短链解析 dw/electron/shop/detail.ts 无浏览器取数的高价值实现
商品素材下载/命名/URL 白名单 dw/electron/shop/materials.ts 原始物料落盘结构参考
送审批次策略机(串行/中断/回查/记账/审计) dw/electron/submit/{batch,plan,verify,idempotency,audit}.ts 写链路业务策略层,独立于 Playwright
DPLink 拼装编排/错误分类 dw/electron/dplink/link.ts、account.ts 依赖硬广账号;接口参数已在文档中核实到「两个只读接口」

9.3 前端页面/组件(B 级,需去 Semi 化)

  • 页面:DownloadPage(任务工作台与三阶段布局)、ShopPage+ActionBar+MaterialGrid(工作台布局)、ReviewPage+ReviewTable+ReviewFilters+ReviewDetailModal+PublishRecordsModal(审核表格与筛选)、SubmitPrecheckModal(预检/就地编辑/批量补字段)、MixSubmitModal(双栏配对)、SubmitProgressPopover/SubmitProgressBody(进度浮层)、ConfigPage(分区清单设置页)、UpdatePage/AboutPage(可参考信息架构)。
  • 通用组件:PageHeader、ProgressRow、SettingsRow、SettingsSection、MaterialPreview、SpuCanvas(仅参考承载思路)、CopyButton(页面内)、ErrorBoundary、4 个骨架屏、LoginDialog、SidebarLoginStatus、DplinkAccountDialog、DplinkLandingDialog。
  • 状态/工具:src/contexts/{Theme,LoginStatus,UnsavedChanges}.tsx(未保存守卫可直接复用思路)、src/utils/spu.ts(SPU 解析/价格/最近查询)、spuIdList.ts(多 SPUID 归一化/校验)、updateLabels.ts、remote-config-label.ts。
  • 类型契约:src/types/index.ts(1,000+ 行,含 ElectronAPI、IPC 载荷、审核/送审/混剪/下载/更新类型)、13 个 .d.ts 纯逻辑类型声明——可作为新平台 API DTO 草案,但需与后端共同评审。

9.4 文档(可直接迁移,价值排序)

文档 行数 迁移价值
docs/星光平台API接口文档.md 807 ⭐⭐⭐⭐⭐ 接口/签名/枚举/选择器/错误码全量,是服务端复现的唯一权威(注意含盐值,不可外发)
docs/送审命名规范与预检规则.md 235 ⭐⭐⭐⭐⭐ 命名/解析/预检/批量语义,直接对应 PRD P-04
docs/星光平台送审与审核查询-可行性评估.md 928 ⭐⭐⭐⭐ 读写分离、页面自动化理由、单会话约束
docs/DPLink组成与一键复制-可行性评估.md 545 ⭐⭐⭐⭐ 双层链接算法/字段/实测样本,对应 PRD P-05
docs/P1读数据接口化-实现说明.md / P2素材审核查询-实现说明.md / P4素材送审-实现说明.md 540/516/1,068 ⭐⭐⭐⭐ 实现取舍、真机踩坑、门禁清单(P4 含 19 轮真机记录)
docs/混剪素材批量上传-开发方案.md / 混剪素材批量送审-实现说明.md 496/151 ⭐⭐⭐ 混剪业务规则与 Phase 2 方向
docs/接口登录通道-实现说明.md 273 ⭐⭐⭐ 登录接口化实测与红线
docs/远端配置运维手册.md 190 ⭐⭐⭐ 白名单/签名/revision/应急停用;可迁移为配置中心 SOP
docs/项目评估与优化建议-2.1.0.md 1,063 ⭐⭐⭐ 架构/性能/安全/测试的系统性评估(部分已修,需按现状核对)
DEVELOPMENT.md 2,380 ⭐⭐⭐ 目录/主进程/IPC/配置/踩坑全量,但基线 v1.0.6,只读 §3-§8 与 §17-§19,其余核对代码
docs/签名与公证落地清单.md、构建发布与版本更新指南.md 227/859 ⭐⭐ 桌面端专用,Web 化后仅作历史参考

10. 风险与待确认问题

10.1 风险

R1 平台合规/封禁(高)

  • 本项目是未授权的页面自动化 + 接口逆向:签名盐从平台前端产物取得,账号是客户共享账号;平台条款是否允许此类工具、是否会把团队账号风控,没有任何书面确认。
  • Web 化后从「个人电脑 IP」变为「机房 IP + 多用户高频」,平台侧流量特征更显眼,封号/限流风险上升。
  • 建议:法务/客户成功提前确认;保留「只读优先、写操作人工确认、可一键停用」的设计(现有 enableSubmitReview 就是范式)。

R2 登录态与账号归属(高)

  • 平台单账号单会话:网页版登录会顶掉应用 token;多用户 Web 化若共享一个 token 会互踢。现有云端 Cookie 同步(HTTP+FTP 明文)是「团队共享一个账号」的临时方案,不适合作为平台级账号体系。
  • 硬广账号是客户给团队的共用账号,DPLink 依赖它;多人同时使用/退出语义(退出只清本机)需要产品化定义。
  • 账号归属、权限(platform 的 user/detail 权限菜单表)、数据可见范围(谁看谁的送审/审核)都需要新平台的权限模型。

R3 接口/页面稳定性(高)

  • 签名盐、字段、枚举、选择器、权限菜单都可能随平台发版变化;本项目用 32 个验证脚本 + 真机对比脚本 + 抓包 fixture 对抗,但没有 SLA/版本协商。
  • 混剪「混剪=是」写链路、登录失败码、素材审核部分字段尚未真机覆盖(文档已标注)。
  • 新平台应把「平台适配层」隔离为可独立发版的服务,并提供「平台变更检测/健康检查」机制(签名自校验已有雏形)。

R4 Electron 能力缺口(中)

  • 内嵌 webview、本地文件路径/对话框、剪贴板、系统通知、打开目录、safeStorage、FTP、自动更新、代码签名、窗口状态——Web 端均无等价物,需要替代方案(对象存储、浏览器下载、通知中心、KMS、部署流水线)。
  • 特别是送审大文件(140–190MB)从「本地路径 setInputFiles」变为「浏览器→服务端→平台」,带宽与上传成功率是新增风险;建议优先设计「客户端→OSS 直传 + 服务端只发凭证」。

R5 数据迁移(中)

  • 本地 config.json/cookies.json/dplink-*/submitted-md5.json/submit-audit.jsonl/下载目录命名规则都是「单机事实」;迁移到多用户平台需要:
    • 账号与凭据迁移(safeStorage 加密跨机器不可解,必须重新登录);
    • 已送审账本(避免重复送审)与审计日志的历史价值;
    • 下载文件/命名规则兼容(历史文件如何进新素材库);
    • 本地路径偏好(下载目录)在新平台无意义。
  • 建议迁移策略:不做客户端数据自动迁移,只提供「md5 账本 + 审计日志导入」与「重新登录」;历史素材通过新平台重新拉取/上传。

R6 凭据泄露(高,且为既成事实)

  • 星光/FTP 凭据曾在源码与 git 历史中;即使轮换,旧仓库/文档/随包产物仍可能流出。新平台不得复用这些凭据;上线前必须轮换并审计。

10.2 待确认清单

编号 问题 为什么影响整合 建议向谁确认
Q-01 星光平台是否允许内部工具/服务端自动化?客户/平台方对此的书面态度? 决定「服务端重写送审」是否合规,可能直接否决整个写链路 业务方 + 客户成功 + 法务
Q-02 新平台的账号体系:一人一星光账号,还是团队共享账号池? 决定会话串行化、权限、审计与凭据设计;现有单账号假设不成立 产品负责人 + 客户
Q-03 新平台是否也要服务唯品会?其后台是否有可复用的接口/登录方式? 决定 P-06 是否另起一套适配层;本项目零参考 产品 + 另一项目调研(sucaigongfang)
Q-04 DP / 承接页的准确业务口径是什么?DPLink 是否就是 PRD 所指的「自动配置」? 决定 P-05 的范围;本项目只做了得物 DPLink(iOS/安卓唤端链接),不含 DP 字段 业务方(PRD 1.1.3)
Q-05 新平台的 UI 选型是否包含 Semi?还是 Ant Design/Arco/自研? 直接决定前端 8–12 人日差异与组件复用边界(§8.1) 设计负责人 + 前端负责人
Q-06 平台原始素材(图片/视频)在新平台的存储形态:对象存储?CDN?保留多久? 决定下载引擎改造与成本;现有「本地目录 + 文件名」语义要替换 架构 + 运维
Q-07 「图片/视频 AI 产线」是否已有供应商/模型选型? 与 dewu 项目无关,但影响整体排期与数据流(原始物料→产线→提审) 产品 + AI 负责人
Q-08 混剪送审是否仍由人工配对,还是需要 Excel/CSV 导入(Phase 2)? 决定 8–12 人日 UI 的范围;当前 Phase 2 未实现 业务方
Q-09 历史数据(已送审 md5、审计日志、下载文件)是否需要迁移? 决定迁移成本与「重复送审」风险 业务方 + 产品
Q-10 写链路是否保留「人工确认 + 可中断 + 远端一键停用」的安全设计? 若要求无人值守批量提交,风险与实现复杂度都会显著上升 业务方 + 风控
Q-11 平台接口的 SLA/变更通知机制是否存在?谁负责平台改版后的适配? 决定长期维护成本归属(≈1 人持续投入) 客户/平台方 + 研发负责人
Q-12 账号权限菜单(user/detail.list)是否可作为新平台的功能门禁依据? 现有实现只做「建议不硬拦」;若要做硬权限需确认菜单稳定性 平台方 + 产品

11. 证据索引

路径前缀 dw/ = 参考项目/dewu-material-Downloader/。以下为关键结论的最小证据集(≥25 条)。

# 结论 证据
1 版本 2.7.0、应用标识 dw/package.json:3、dw/electron-builder.yml:1-2
2 技术栈(Electron 44 / React 19 / Semi 2 / Playwright) dw/package.json:70-96
3 6 个一级入口与 BETA 标记 dw/src/App.tsx:240-306
4 6 条路由 dw/src/App.tsx:437-442
5 101 条 IPC 通道、87 invoke + 14 event dw/electron/ipc/channels.ts:1、dw/electron/preload.ts:15,87,124,190,230,300
6 写链路红线(不直接调写接口) dw/electron/submit/page.ts:2-30
7 提交接口路径与上传超时 15 分钟 dw/electron/submit/page.ts:47,68
8 送审抽屉选择器(按 label 精确匹配、限定抽屉) dw/electron/submit/page.ts:77-110,209-222
9 批量送审策略表(成功/重复/失败/超时/掉线) dw/electron/submit/batch.ts:1-30
10 只按 md5 幂等 + 双向同步 dw/electron/submit/idempotency.ts:1-36
11 审计/请求体 JSONL 路径 dw/electron/submit/audit.ts:29-40,151
12 命名规范(模式 A/B、末三段、无 spuid) dw/docs/送审命名规范与预检规则.md:20-93
13 下载命名规则 dw/electron/downloader/utils.ts:11-20
14 下载分批/并发/冷却/重试 dw/electron/downloader/manager.ts:181-227,374-430
15 MD5 全量同步扫描(性能债) dw/electron/downloader/manager.ts:174、dw/electron/downloader/utils.ts:78-100
16 星光签名盐与算法 dw/scripts/lib/platform-sign.mjs:20-37,73-106
17 素材列表/详情接口路径 dw/electron/platform/materials.ts:91,177
18 审核/记录/枚举/账号接口路径 dw/electron/platform/reviews.ts:43-48
19 登录接口路径与 token 事实 dw/electron/platform/auth.ts:1-70
20 接口登录实测 9/9 dw/docs/接口登录通道-实现说明.md:146-169
21 平台 API 全量文档(含签名/枚举/送审) dw/docs/星光平台API接口文档.md:130,197,229,277,326,342,366,379,522,594
22 读写分离与单会话红线 dw/docs/星光平台送审与审核查询-可行性评估.md:1-120、dw/docs/新功能开发计划.md:455-475
23 送审四步链路与 SPU 误报教训 dw/docs/星光平台API接口文档.md:340-520
24 远端配置三道防线/白名单 dw/electron/config/remote.ts:1-40、dw/scripts/lib/remote-config-schema.mjs:32-53
25 送审总开关/线上配置 revision 2 dw/remote-config/app-config.json:26,72
26 硬编码凭据仍在源码 dw/electron/config/developer.ts:130,135
27 三档下载参数与远端区间 dw/electron/config/presets.ts:59-102、dw/scripts/lib/remote-config-schema.mjs:60-80
28 商品详情 SSR 直取(无浏览器) dw/electron/shop/detail.ts:11-27,182-280
29 商品素材落盘结构/URL 白名单 dw/electron/shop/materials.ts:24-26,82-95
30 内嵌页 UA/分区/净化(Electron 依赖) dw/electron/shop/session.ts:32-66,198-200
31 DPLink 双层算法与接口 dw/docs/DPLink组成与一键复制-可行性评估.md:12-35、dw/electron/dplink/link.ts:39-41
32 DPLink 硬广凭据隔离 dw/electron/dplink/account.ts:1-40
33 Cookie 同步 v2 分区(soft/dplink) dw/electron/browser/cookieSync.ts:1-40
34 登录态状态机与串行队列 dw/electron/browser/manager.ts:46-55,223
35 浏览器组件三级检测/验签 dw/electron/browser/playwrightInstaller.ts:1-125,436
36 更新元数据验签/强制/最低版本 dw/electron/updater/manager.ts:185,231,274-301
37 CI 三 job 与门禁清单 dw/.github/workflows/ci.yml:53-217,257
38 验证脚本规模(verify:ui 480 通过 / verify:platform 260 通过) dw/scripts/verify-ui-behavior.mjs(5,283 行)、dw/scripts/verify-platform.mjs(2,352 行)
39 TypeScript strict dw/tsconfig.json
40 项目评估健康度 3.0/5 与 P0 清单 dw/docs/项目评估与优化建议-2.1.0.md:27-43,314,455,705
41 素材过滤规则(30 天/未授权快手) dw/scripts/lib/material-filter.mjs、dw/docs/素材下载过滤开关-实现说明.md:1-40
42 混剪 Phase 1 未真机 dw/docs/混剪素材批量送审-实现说明.md:1-65
43 审核状态映射与 CSV 列 dw/scripts/lib/platform-material-mapping.mjs:424-506、dw/scripts/lib/review-csv.mjs:34-45
44 DEVELOPMENT.md 基线过时(v1.0.6 vs 2.7.0) dw/DEVELOPMENT.md:1-13,1715-1830
45 无唯品会代码 全仓检索 唯品会|vipshop|vip.com 零命中