15 KiB
15 KiB
工作交接说明(HANDOFF)
更新:2026-08-30 读者:下一个接手工作的 AI / 开发者(工具无关)。先读本文再动手,避免重复探索。 配套文档:
README(项目总览)、collect.md(采集)、trial-page.md(试算页)、image-suite.md(生图)、background-jobs.md(后台任务中心方案、实施状态与路线图)、image-asset-lifecycle.md(图片与水印存储规则)、api.md(契约)、backend-structure.md(后端结构)
1. 项目一句话
Ozon 跨境上品工具链。当前主链路(V2.1,已放弃 Ozon API 直传):
extensions/collector 扩展采集(Ozon/1688/淘宝/天猫)
→ 「上报商品」POST /api/materials 入库 + 自动打开试算页
→ studio /trial/{id} 试算页:计价 → 俄文文案 → AI 生图(套图+单张)→ 登记
→ 导出 CSV / 组合码 → 人工上 Ozon 卖家后台
技术栈:FastAPI(server,8800)+ React19/Vite/antd6(studio,8900)+ WXT Chrome 扩展(extensions/collector)。SQLite(data/app.db),无鉴权(V2.1 决策:先功能后鉴权)。
2. 启动与构建
# 一键启动(推荐):自动装依赖 → 构建采集插件 → 起插件改动监听 → 起 studio → 起 server
./start.command
# server 单独起(等价;日志建议重定向到 /tmp/osk-server.log)
.venv/bin/uvicorn main:app --app-dir server --reload --reload-include "*.yaml" --host 127.0.0.1 --port 8800
# 扩展改动后(start.command 的监听会自动构建,仍需去 chrome://extensions 手动点刷新)
pnpm -C extensions/collector build # 产物 .output/chrome-mv3
- start.command 新增:启动时会先执行
alembic upgrade head,再自动构建采集插件并起后台监听(3s 轮询src/**+wxt.config.ts,改动自动重建;BSD find 语法,无新依赖)。Ctrl+C 会连同监听进程一起清理。 - 后台任务 Worker:
start.command会额外启动python server/worker.py。单独启动 server 时也要另开终端运行该命令,否则生图任务只会停在“排队中”。 - 运行态提醒:交接时 server 是上个会话用 nohup 起的后台进程(日志
/tmp/osk-server.log),原 start.command 终端已被停掉。新会话建议:kill $(lsof -ti :8800)后用./start.command正常接管。 uvicorn --reload不监控.env:改.env后必须手动重启 server(Kill 8800 端口进程再起)。- 密钥在根目录
.env:DEEPSEEK_API_KEY(规划+文案)、DASHSCOPE_API_KEY(通义,可用 ✅)、RIGHTAPI_API_KEY(RightCode 中转,通道当前故障 ❌)、PCORE_API_KEY(pcore.ai,可用 ✅)、ARK_API_KEY未配(豆包未用)。.env.example有全部键位说明。
3. 生图供应商现状(2026-08-29,重要)
| 供应商 | 域名 | 模型(下拉显示) | 状态 |
|---|---|---|---|
| 通义/阿里 | dashscope.aliyuncs.com | qwen-image-3.0-pro 等(阿里巴巴) |
✅ 可用,实测 10s 出图 |
| RightCode | rightapi.ai | gpt-image-2、gpt-image-2-vip、nano-banana 系列(RightCode) |
❌ 通道故障:任务能提交但生成阶段 503/「No available channel」,纯文生图也失败;中转侧问题,待其恢复 |
| Pcore | pcore.ai | gpt-image-2@pcore(Pcore) |
✅ 可用(用户已在 pcore 开通 image2 分组后端到端跑通,全链路约 1 分钟/张) |
- 默认生图模型 =
gpt-image-2@pcore(studio/src/services/suite.ts的DEFAULT_IMAGE_MODEL)。 - 同名模型多中转的路由约定:前端模型 value 用「api模型@provider」后缀区分(目前仅 pcore 用到),服务端
schemas/suite.py的MODEL_PROVIDERS+api_model()(剥后缀)处理;白名单PCORE_MODELS。 - pcore 协议要点(
generator.py的_pcore_request/_pcore_poll_task):无参考图走POST /v1/images/generations,带参考图走/v1/images/edits且 images 必须是[{image_url: dataURI}]对象数组(纯字符串报错);均为异步:提交拿id→ 轮询GET /v1/images/{kind}/{task_id}→completed后data[0].url取图。size是枚举(1024x1536/1024x1024),不接受自定义尺寸。new_api 系中转常见「HTTP 200/503 + 错误体」,错误解析已兼容嵌套error.{code,message};「No available channel」类错误不重试直接失败。 - 速率:image2 分组 RPM 70 / RPD 1.2K(日限);当前独立 Worker 单进程逐图领取任务,远碰不到 RPM。pcore 账户余额 $5,按张扣费。
4. AI 规划张数策略(planner.py)
- 不设硬性数量:prompt 让 AI 按商品复杂度自主决定,「建议 8 张左右」;规划规则 = 先保证每个 SKU 1 张主图,其余类型自行取舍。
- 用户可通过「生图要求」指定张数:写了「N 张」AI 必须严格执行;服务端
_total_budget()用正则提取,安全上限:默认 15、指定时按 N 最大 24(防跑飞,超限从尾部截断,SKU 主图优先保留)。 - 规划器曾频繁报「规划器未返回有效方案项」:根因是 deepseek-v4 是思维链模型而规划器裸调用没禁 thinking,token 被推理烧光、正文为空。已修复:请求体加
"thinking": {"type": "disabled"}+ 解析失败/空方案自动重试一次 + 失败时记录原始输出 + 缺 title 的方案项从 detail/kind 兜底合成不再丢弃。30 SKU 压测 3/3 通过。
5. 当前进度
✅ 已完成(含 2026-08-29 一轮,全部未提交,见 §6)
| 模块 | 内容 |
|---|---|
| 试算页 | 五区块页面、计价、俄文文案、采集图片/出图方案/生成结果、登记导出 |
| 采集对接 | ISS 扩展并入 extensions/collector/,「上报商品」入库 + 自动打开试算页 |
| 生图服务端 | planner/generator/prompts/watermark/jobs + 独立 Worker,套图 + 单张 AI 生图 + 水印 + ZIP 导出 |
| 本轮:Pcore 接入 | 新 provider 全链路(生成/编辑/轮询/重试/错误处理),@pcore 路由约定,下拉带供应商名,默认模型切 Pcore |
| 本轮:规划器修复 | thinking 禁用 + 重试 + 张数策略(AI 自主,建议 8 张左右,生图要求可指定) |
| 本轮:采集箱 | 勾选列 + 全选/取消全选 + 批量删除(硬删、Popconfirm 二次确认、删空页自动回退) |
| 本轮:采集图片区改版 | 8 列网格;AI 生图按钮半透明悬浮图片右下角;图名显示在图片下方(取 URL 末段);SKU 名并入图名行(不再悬浮遮挡勾选钮);勾选钮在右上角;默认全部不勾选 |
| 本轮:生成结果区 | 「导出图片」按钮(水印按钮右侧,复用 POST /api/export/images,ZIP 内分「套图结果/单张生图」文件夹);「单张 AI 生图」小节改名「生图记录」(落库历史,刷新后保留) |
| 本轮:图片生命周期 | 采集、上传与 AI 图片统一保存为 original + current;只保留当前水印版;重加/移除水印自动回收旧对象;删除单图/硬删商品会清理本地或七牛对象;具体规则见 image-asset-lifecycle.md |
| 本轮:图片资源上限 | 单张上传/下载默认 20 MB;采集最多 100 张;导出最多 50 张、总量 200 MB;ZIP 超过 2 MB 自动落临时磁盘并分块返回,配置见 .env.example |
| 本轮:生图任务与轮询 | 单张 AI 编辑改为提交统一异步任务并立即返回 suite_id;套图与单张弹窗均采用无重叠递归轮询、取消在途请求与失败退避;套图任务 ID 可在刷新页面后从浏览器会话恢复 |
| 本轮:持久化图片任务 | 套图、单张编辑与批量添加水印已迁入数据库任务表和独立 Worker;Pcore/RightAPI/通义万相保存第三方任务 ID 并可在重启后恢复轮询;水印逐图进度可刷新恢复、取消并按失败项重试,详见 background-jobs.md |
| 本轮:关键 bug 修复 | ① axios 全局 Content-Type 导致 FormData 被 JSON 化 → 上传 422(api.ts 移除全局头,今后勿设);② TrialPage load() 置 loading 导致整页闪 Spin、卸载面板(杀生图轮询/丢勾选)→ 改静默刷新;③ web v1 页面因 cdn.tailwindcss.com 被墙整页无样式 → tailwind 运行时固化到 web/vendor/tailwind.js |
| 本轮:杂项 | 采买地址「打开地址」改图标按钮(与复制图标同款);start.command 自动构建+监听插件 |
验证口径(本轮均实测通过)
- 上传/生图/导出/批量删除/规划,全部真实接口+浏览器操作验证;Pcore 端到端 56s 出图并回写素材。
- 每个 UI 改动后
pnpm -C studio exec tsc -b零错误;插件构建通过;/api/health200。
6. ⚠️ 未提交改动清单(当前最大事项)
分支 feat-2.1.0,工作区仍有多项未提交改动,建议按模块分 4-5 个 commit:
- Pcore 生图接入 + 规划器修复 + 张数策略
server/services/{generator,planner,suite_service,prompts/__init__}.py、server/{api/suite.py,schemas/suite.py,config/settings.py}、studio/src/services/suite.ts、.env.example、docs/v2.1/{image-suite,api}.md - 试算页 UI 迭代 + 采集箱批量操作 + 请求层修复
studio/src/pages/trial/{TrialSuitePanel,TrialInfoPanel,TrialPage}.tsx、studio/src/pages/collection/CollectionPage.tsx、studio/src/services/api.ts - web v1 样式修复(CDN 固化)+ start.command 插件自动构建
web/ozonSeller.html、web/vendor/tailwind.js(新目录)、start.command - 图片生命周期与水印回收:
server/services/image_assets.py、server/services/storage.py、server/{api/materials,api/products,models/asset}.py、迁移a41e8c7f4b20_add_asset_image_lifecycle.py、试算页水印入口 - 交接文档:
docs/v2.1/{HANDOFF,image-asset-lifecycle,optimization-audit}.md
提交前:git checkout -- studio/tsconfig.app.tsbuildinfo(构建产物,勿提交)。
7. 下一步(按优先级)
- 提交:按 §6 分组提交。
- 手动全流程回归(浏览器 + Chrome 真机扩展):采集 → 上报 → 试算页五区块 → 生成(Pcore)/编辑/删除 → 登记表录入/导出 CSV/组合码 → 清空。
- 运营观察:pcore 余额($5 起步)与 image2 分组日限(1.2K 张/天);RightCode 通道恢复情况(恢复后 nano-banana 系列可回归)。
- Phase D 待办:批量 CSV 服务端化(
GET /api/export/trial-csv);登记表数据存 localStorage(跨设备需落库)。 - 远期:鉴权/账户体系重做(从
deps.py层重引);ISS-only 产品模式构建;extension-v1/v2、web/、server/legacy/清理时机。
8. 已知坑(新会话必读)
| # | 坑 | 对策 |
|---|---|---|
| 1 | uvicorn --reload 不监控 .env |
改 .env 后手动重启 server |
| 2 | 生图任务依赖独立 Worker | start.command 会启动;若手动运行 uvicorn,必须另开 python server/worker.py,否则任务会一直排队 |
| 3 | SQLite 仅适合单机 Worker | 当前通过租约恢复异常退出的任务;未来多实例前先迁移 PostgreSQL,再做多 Worker 竞争领取 |
| 4 | 外部模型任务可恢复范围不同 | Pcore/RightAPI/通义万相保存 provider task id 后可继续轮询;豆包/同步千问没有外部任务 id,进程恰在请求中断时只能重试 |
| 5 | axios 实例勿设全局 Content-Type | axios 1.x 遇「默认 JSON 头 + FormData」会把表单转 JSON 发送(formDataToJSON),multipart 接口全 422。已从 api.ts 移除;对象请求体 axios 会自动补 JSON 头 |
| 6 | web/ 样式依赖公网 CDN |
tailwind 已固化 web/vendor/tailwind.js;font-awesome/jsdelivr 若也断,同样方式下载到 web/vendor/ 改引用 |
| 7 | 试算页水印文本存 localStorage(trialWatermark) |
改默认值不影响已保存设置;登记表同理存 localStorage trialRegisterRecords |
| 8 | studio/tsconfig.app.tsbuildinfo 是构建产物 |
提交前 git checkout -- studio/tsconfig.app.tsbuildinfo |
| 9 | 冻结代码不要投入 | server/legacy/、extension-v1/、extension-v2/、web/(本轮 CDN 固化属修复例外)、studio 商品编辑页的属性映射/发布区块 |
| 10 | AI 规划/生图花钱 | pcore 按 $ 扣费、RightCode 按张计费;联调时 plan 张数设 1-2、优先低成本模型 |
| 11 | TrialPage load() 勿再置 loading |
置 loading = 整页 Spin + 卸载面板 = 杀生图轮询/丢状态(已修,保持静默刷新) |
| 12 | 浏览器自动化调试怪癖(如 ZCode IAB) | 截图偶发超时(重试一次多半仍失败,改用几何测量/计算样式验证);文件上传需用 DataTransfer+input change 事件模拟;改代码后 React 事件偶发失灵 → reload 页面即恢复 |
| 13 | 图片上传/导出存在大小限制 | 默认单张 20 MB、采集 100 张、导出 50 张、ZIP 200 MB;超限接口返回 413。需要调整时改 .env 的 IMAGE_* / EXPORT_* 配置并重启服务 |
9. 关键文件速查
| 功能 | 前端(studio/src/) | 后端(server/) |
|---|---|---|
| 试算页骨架 | pages/trial/TrialPage.tsx(load() 是静默刷新,见坑 11) |
— |
| 01 商品信息(采买地址图标、型号/货号联动) | pages/trial/TrialInfoPanel.tsx |
api/materials.py |
| 02 价格试算 | pages/trial/TrialPricingPanel.tsx + pricing/pricing.ts |
— |
| 03 俄文文案 | pages/product/CopyPanel.tsx(共用) |
api/ai.py + services/deepseek.py + prompts/copy_ru.py |
| 04 图片与生图(7 列网格/悬浮按钮/图名) | pages/trial/TrialSuitePanel.tsx + AiImageGenModal.tsx |
api/suite.py + services/{jobs,job_worker,suite_service,generator,planner,prompts/,watermark,image_assets}.py |
| 图片原图/水印/删除回收 | TrialSuitePanel.tsx(水印设置) |
api/materials.py、api/products.py、services/{image_assets,storage}.py |
| 生图供应商路由 | services/suite.ts(IMAGE_MODEL_OPTIONS 带供应商名;DEFAULT_IMAGE_MODEL) |
schemas/suite.py(MODEL_PROVIDERS/@pcore 约定)+ services/generator.py(generate_pcore 等) |
| 05 登记与导出 | pages/trial/TrialExportPanel.tsx(localStorage trialRegisterRecords) |
— |
| 生成结果导出 | TrialSuitePanel.tsx handleExportResult(套图+单张分组 ZIP) |
api/export.py |
| 采集箱(全选/批量删除) | pages/collection/CollectionPage.tsx |
api/products.py(DELETE hard=true) |
| 前端服务层 | services/{suite,product,ai,fx,api}.ts |
schemas/suite.py(契约对齐) |
| 扩展上报 | extensions/collector/src/api/report.ts + entrypoints/{background,sidepanel/App}.tsx + storage/settings.ts |
api/materials.py |
10. 验收标准(改完怎么算完成)
pnpm -C studio exec tsc -b零错误、pnpm -C studio build通过(提交前还原tsconfig.app.tsbuildinfo)- 改扩展:
pnpm -C extensions/collector build通过 - 改 server:
/api/health200、涉及接口 curl/页面冒烟通过 - UI 改动:浏览器实测 + 必要时截图确认