feat(onboarding): add first-run membership activation
This commit is contained in:
+12
-6
@@ -79,7 +79,7 @@ imported → collected → generated → applied
|
||||
- `cdp`:连接调试端口、找/开 tab、执行 JS、拖拽、注入文件。
|
||||
- `editor`:登录检测、读取商品状态、**采集**(读旧标题、下载旧封面)、改标题、换封面、点更新。
|
||||
- `product_status`:商品状态代码 `normal/unlisted/reviewing/unknown` 的归一化、中文显示、EDS 提示分类和下游任务分组;①②③只能复用该模块,不各自判断。
|
||||
- `subscription`:使用 cmhub API Key 查询 `GET /api/v1/cmshopee/subscription/status`,把远端权益结果归一化为有效、宽限、未订阅、到期、撤销、账号不可用、Key 无效、暂时不可用或旧服务兼容状态;不保存、展示或记录 API Key,服务端始终是最终授权方。T-700 后当前开发版本固定为 `SUBSCRIPTION_CHECK_ENABLED = True`、`SUBSCRIPTION_ENFORCEMENT_ENABLED = True`:查询期间和明确不允许状态只保留“设置”Tab,新提交统一由主窗口预检拦截;有效、宽限和旧服务兼容状态恢复工作流。
|
||||
- `subscription`:使用默认网关 API Key 查询 `GET /api/v1/cmshopee/subscription/status`,把远端权益结果归一化为有效、宽限、未订阅、到期、撤销、账号不可用、Key 无效、暂时不可用或旧服务兼容状态;不展示或记录 API Key,服务端始终是最终授权方。T-700 后当前开发版本固定为 `SUBSCRIPTION_CHECK_ENABLED = True`、`SUBSCRIPTION_ENFORCEMENT_ENABLED = True`:查询期间和明确不允许状态只保留“设置”Tab,新提交统一由主窗口预检拦截;有效、宽限和旧服务兼容状态恢复工作流。T-701 后缺少 Key 的干净安装不再裸露技术设置,而是显示只收集“会员 API Key”的激活窗口;输入值先在内存中验证,只有服务端未拒绝该凭据时才保存到 `data/config/cmhub.json`。
|
||||
- `ai`:`gen_title(prompt, old_title)`、`gen_cover(prompt, old_cover_path)`、`analyze_product_images(instruction, context, image_paths)`;前两者分别负责②标题/生图,后者只供商品套图中的「AI帮写」调用 cmhub 图片理解接口,读取1至8张按 `source_order` 排序的本地商品原图并返回可编辑卖点与白名单计费元数据。
|
||||
- `cmhub_models`:格式化 cmhub 模型别名,并维护仅进程内有效的短期模型目录缓存;缓存键使用规整网关地址和别名,不含 API Key,不写入配置、SQLite、日志或导出文件。
|
||||
|
||||
@@ -88,7 +88,7 @@ imported → collected → generated → applied
|
||||
- 应用配置(模型选择、生成参数、目录、Chrome 路径)→ `data/config.json`。
|
||||
- AI 模型清单(direct 内部兼容模式 url/模型/密钥/类型/连接超时)→ `data/config/ai_models.json`(API Key 本地明文保存,必须 gitignore,UI 打码显示;普通设置页不再暴露 direct 切换入口)。
|
||||
- cmhub 网关 Key → `data/config/cmhub.json`,schema `{ "api_key": "..." }`;`config.json` 只保存 Base URL、别名和超时,不保存 Key。
|
||||
- 订阅状态 → 仅进程内 `SubscriptionStatus`;有效/宽限状态把服务端返回的账号显示名、套餐名和有效期追加到 Windows 原生窗口标题,其他状态恢复纯应用名称并在底部状态栏显示脱敏中文结果。Tabs 上方不保留会员状态行,状态不写入 SQLite、诊断日志或导出。强制模式首次进入 `expired` 时,在门禁生效后弹一次中文窗口;安全的同网关 HTTPS `manage_url` 可用默认浏览器打开,退出走主窗口正常关闭。重复 `expired` 不重弹,恢复允许状态后才重置本次运行的弹窗标记。设置页只发出“重新检测会员状态”信号,由主窗口复用异步查询和陈旧结果隔离;`404` 表示服务端尚未启用订阅接口并按旧服务兼容放行,网络异常不被误判为会员到期。
|
||||
- 订阅状态 → 仅进程内 `SubscriptionStatus`;有效/宽限状态把服务端返回的账号显示名、套餐名和有效期追加到 Windows 原生窗口标题,其他状态恢复纯应用名称并在底部状态栏显示脱敏中文结果。Tabs 上方不保留会员状态行,状态不写入 SQLite、诊断日志或导出。强制模式首次进入 `expired` 时,在门禁生效后弹一次中文窗口;安全的同网关 HTTPS `manage_url` 可用默认浏览器打开,退出走主窗口正常关闭。重复 `expired` 不重弹,恢复允许状态后才重置本次运行的弹窗标记。设置页只发出“重新检测会员状态”信号,由主窗口复用异步查询和陈旧结果隔离;`404` 表示服务端尚未启用订阅接口并按旧服务兼容放行,网络异常不被误判为会员到期。首次激活后的使用清单只在 `config.json` 保存非敏感状态 `onboarding.first_use_guide_state`,取值为空、`pending`、`completed` 或 `dismissed`;默认空值保证存量用户不会被误判为新用户。
|
||||
- cmhub 模型目录与 AI帮写/正式套图预估价格 → 仅内存短期缓存;预估值只供用户确认,实际扣点仍以网关响应 metadata 为准。
|
||||
- 业务数据(账号、任务、各阶段结果)→ SQLite `data/cmshopee.db`。
|
||||
- 图片(采集的旧封面、AI 生成的新封面)→ `data/images/`(路径记在 DB)。
|
||||
@@ -123,7 +123,7 @@ T-538 后统一数据根为 `data/`:打包版默认 `<exe目录>/data`,源
|
||||
"generate_mode": "title",
|
||||
"backend": "cmhub",
|
||||
"cmhub": {
|
||||
"base_url": "",
|
||||
"base_url": "https://cm.833729.com",
|
||||
"title_alias": "",
|
||||
"image_alias": "",
|
||||
"vision_alias": "vision-standard",
|
||||
@@ -152,6 +152,12 @@ T-538 后统一数据根为 `data/`:打包版默认 `<exe目录>/data`,源
|
||||
"language": "繁体中文",
|
||||
"ratio": "1:1"
|
||||
}
|
||||
},
|
||||
"subscription": {
|
||||
"last_notice_id": ""
|
||||
},
|
||||
"onboarding": {
|
||||
"first_use_guide_state": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -159,7 +165,7 @@ T-538 后统一数据根为 `data/`:打包版默认 `<exe目录>/data`,源
|
||||
`ai` 段只放**选择 + 全局生成参数**:
|
||||
|
||||
- `backend`:内部字段,取值仍支持 `cmhub` / `direct`;普通产品默认 `cmhub`,设置页不再展示「AI 后端」label 或 direct/cmhub 下拉,保存设置固定写 `cmhub`。`direct` 仅保留为内部兼容/手工回滚路径。
|
||||
- `cmhub`:cmhub 网关配置,`base_url` 为网关根地址,保存和请求前会规整为 scheme+host(+port),去掉 `/api`、`/api/v1`、其它路径、查询串和片段;`title_alias` / `image_alias` / `vision_alias` 分别对应②标题、②与商品套图正式生图、商品套图中的「AI帮写」图片理解,`vision_alias` 缺失时旧配置迁移为 `vision-standard`,`connect_timeout` 为连接超时;API Key 不在此处保存。设置页展示三类别名和扣点提示,其中图片理解下拉只接受 `operation_type=vision`、`requires_image=true` 且已定价的模型;已保存但暂不可用的值保留并明确提示。商品套图正式生成仍只使用已保存的生图 alias,不展示 OpenAI Key、Provider URL、上游接口路径或直连模型 slug。
|
||||
- `cmhub`:cmhub 网关配置,`base_url` 为网关根地址,干净安装和空值默认使用 `https://cm.833729.com`,已有非空地址保持不变;保存和请求前会规整为 scheme+host(+port),去掉 `/api`、`/api/v1`、其它路径、查询串和片段。`title_alias` / `image_alias` / `vision_alias` 分别对应②标题、②与商品套图正式生图、商品套图中的「AI帮写」图片理解,`vision_alias` 缺失时旧配置迁移为 `vision-standard`,`connect_timeout` 为连接超时;API Key 不在此处保存。设置页展示三类别名和扣点提示,其中图片理解下拉只接受 `operation_type=vision`、`requires_image=true` 且已定价的模型;已保存但暂不可用的值保留并明确提示。商品套图正式生成仍只使用已保存的生图 alias,不展示 OpenAI Key、Provider URL、上游接口路径或直连模型 slug。
|
||||
- `default_text_model` / `default_image_model`:仅 direct 内部兼容模式下引用 `ai_models.json` 里的模型名(标题用文本模型、封面用图像模型);普通 cmhub 模式不读取这些模型定义,设置页不再展示标题/图片模型角色下拉。
|
||||
- `generate_mode`:②「生成内容」下拉的主字段,取值 `title` / `cover` / `title_cover`,分别表示只生成标题、只生成封面、生成标题和封面;默认 `title`,避免用户无意产生封面生成成本。
|
||||
- `generate_cover`:旧兼容字段;保存配置时仍写回,值由 `generate_mode` 推导。旧配置 `false` 会迁移为 `title`,`true` 会迁移为 `title_cover`。GUI 和生成逻辑以 `generate_mode` 为准。
|
||||
@@ -221,8 +227,8 @@ T-538 后统一数据根为 `data/`:打包版默认 `<exe目录>/data`,源
|
||||
```
|
||||
|
||||
- 文件必须 gitignore,不提交;UI 展示打码。
|
||||
- `appconfig.load_cmhub_config()` 缺文件时返回空 Key;普通产品默认 backend 仍为 cmhub,但未配置 Key/Base URL/别名时生成阶段会给出清晰配置错误,不静默回退 direct。
|
||||
- `backend=cmhub` 但 Base URL、API Key 或别名缺失时,`app/ai.py` 抛 `CMHubError(code="cmhub_not_configured")`,提示去设置配置,不静默回退 direct;cmhub HTTP 404 映射为 `CMHubError(code="not_found")`,提示检查 Base URL 或实例是否已部署 `/api/v1/models`。
|
||||
- `appconfig.load_cmhub_config()` 缺文件时返回空 Key;普通产品默认 backend 和公开 Base URL 已内置,但 API Key/别名未配置时仍给出清晰错误,不静默回退 direct。
|
||||
- `backend=cmhub` 但 API Key 或本轮所需别名缺失时,`app/ai.py` 抛 `CMHubError(code="cmhub_not_configured")`,提示完成默认网关配置,不静默回退 direct;cmhub HTTP 404 映射为 `CMHubError(code="not_found")`,提示检查 Base URL 或实例是否已部署 `/api/v1/models`。
|
||||
- cmhub `/models` 如返回 `display_name/tags/recommended_for/tier/prices`,GUI 优先用这些字段生成中文档位说明;缺少这些字段时按 alias/tag 的保守规则兜底到“默认档”。客户端不得把 OpenAI 原始模型名作为默认执行事实。
|
||||
|
||||
### 5.2 SQLite `cmshopee.db`
|
||||
|
||||
+4
-1
@@ -234,6 +234,8 @@ cmshopee\
|
||||
|
||||
源码运行时同理使用项目根目录下的 `data\`。`config.json` 内的 `user_data_root`、`image_dir`、`db_path` 默认仍保存为 `chrome_user_data_dir`、`images`、`cmshopee.db` 等相对值,运行时再解析到 `data\` 下,保持便携。
|
||||
|
||||
干净安装的默认网关地址已经内置为 `https://cm.833729.com`,用户不需要先填写 Base URL。`data\config\cmhub.json` 不随安装包分发真实 Key;首次启动检测到 Key 缺失时会显示「激活蝦皮圈优化助手」,用户从官方会员中心取得会员 API Key 后在该窗口验证。无效 Key 或网络失败不会写入本地,验证通过后才保存到 `data\config\cmhub.json`,随后显示添加店铺、人工登录、导入 Excel 和开始采集的首次使用清单。
|
||||
|
||||
这些文件属于用户本地数据,不随新版本程序包覆盖。
|
||||
|
||||
### 旧布局迁移
|
||||
@@ -272,7 +274,8 @@ powershell -ExecutionPolicy Bypass -File scripts\build_exe.ps1
|
||||
- 当前 PyInstaller 6.11.1 下 `dist\cmshopee\_internal\` 必须存在。
|
||||
- `dist\cmshopee\` 中没有第四节列出的本地数据,尤其不能含 `data\`。
|
||||
- `release\蝦皮圈優化助手<APP_VERSION>\version.txt`、GUI 标题栏版本、压缩包文件名三者一致。
|
||||
- 在干净目录首次启动时能生成 `data\config.json` 并进入 GUI。
|
||||
- 在干净目录首次启动时能生成 `data\config.json`,默认网关地址为 `https://cm.833729.com`,并出现只要求“会员 API Key”的中文激活窗口;安装包和新建 `data\` 中不得预置任何真实 Key。
|
||||
- 使用测试接口模拟无效 Key、网络失败和有效套餐:前两者不得生成含输入 Key 的本地文件或日志,有效套餐才写入 `data\config\cmhub.json`、启用业务 Tab 并显示首次使用清单。
|
||||
- 在目标 Windows 10/11 机器或虚拟机上启动 release exe 后,主窗口标题栏完整可见,左边缘不出屏,用户能用标题栏拖动窗口;小分辨率环境不得出现窗口卡在左上角且标题栏不可拖动的问题(见 T-541)。
|
||||
|
||||
涉及 Shopee/CDP 的真实更新能力,仍按任务文档要求用测试商品做人工回归;打包任务本身不新增自动绕过登录、验证码或风控的能力。
|
||||
|
||||
+5
-2
@@ -29,6 +29,8 @@
|
||||
|
||||
- 当前开发版本启用真实查询和强制门禁:`SUBSCRIPTION_CHECK_ENABLED = True`、`SUBSCRIPTION_ENFORCEMENT_ENABLED = True`。查询期间以及未配置 Key、Key 无效、账号禁用、未订阅、到期、撤销或暂时不可用时,只保留「设置」Tab并阻止新的产品请求;有效、宽限或旧服务兼容状态恢复工作流。
|
||||
- 强制升级检查完成、主窗口显示后,后台用 `data/config/cmhub.json` 的 API Key 请求 `GET /api/v1/cmshopee/subscription/status`;不会阻塞 Qt 主线程或把 Key 放入 URL、状态栏、日志和错误提示。
|
||||
- 干净安装默认网关地址内置为 `https://cm.833729.com`。检测到 Key 缺失时不把零基础用户直接丢进技术设置,而是显示窗口级模态框「激活蝦皮圈优化助手」:只收集“会员 API Key”,提供显示/隐藏、验证、前往官方会员中心和退出。输入值先由 worker 在内存中验证;Key 无效或网络失败不落盘,服务端未拒绝凭据后才写入 `data/config/cmhub.json`。关闭激活窗口等同退出程序,后台业务 Tab 始终不可操作。
|
||||
- 首次激活成功后显示四步使用清单“添加店铺账号 → 人工登录 Chrome → 导入 Excel → 采集/生成/更新”。「开始配置店铺」进入账号管理,「稍后提醒」仅延后到下次启动,「不再提示」停止提示。该状态只存 `onboarding.first_use_guide_state`;默认空值不触发,因此已有 Key 的存量用户不会被误弹新手引导。
|
||||
- Tabs 上方不保留应用内标题或会员状态行。Windows 原生标题默认只显示应用名称;订阅有效时追加“账号名 · 套餐名 · 有效至日期”,宽限期追加宽限截止日。检测中和其他状态立即恢复纯应用名称并在底部状态栏显示脱敏中文结果。标题不得展示 API Key、接口地址、会员中心地址、通知标识或原始错误。
|
||||
- 本次程序运行中首次进入 `expired` 时,先应用门禁并切换「设置」,再弹出「会员套餐已过期」。安全 `manage_url` 可通过系统默认浏览器打开;地址缺失时跳转按钮禁用。重复过期检查不重弹,恢复有效后再次到期才重弹;「退出程序」沿用正常关闭和未保存设置确认。
|
||||
- 设置页底部提供「重新检测会员状态」;检测期间按钮禁用并显示运行状态。它只通知主窗口复用现有异步检查,保存 cmhub 设置后的自动重查和陈旧线程结果隔离保持不变。
|
||||
@@ -259,7 +261,8 @@
|
||||
|
||||
| 组件 | 归属 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `MainWindow(QMainWindow)` | 根窗口 | 持有 `QTabWidget`、原生窗口标题会员摘要、底部状态栏、订阅受限恢复入口和全局消息 |
|
||||
| `MainWindow(QMainWindow)` | 根窗口 | 持有 `QTabWidget`、原生窗口标题会员摘要、底部状态栏、首次激活/引导、订阅受限恢复入口和全局消息 |
|
||||
| `MembershipActivationDialog(QDialog)` | 根窗口 | 干净安装只收集会员 API Key,展示本地明文保存说明并发出验证/会员中心操作;不持有网络请求或保存业务 |
|
||||
| `CollectTab(QWidget)` | ① | 导入、任务表、采集、回写 |
|
||||
| `GenerateTab(QWidget)` | ② | 左提示词管理 + 右筛选/任务列表;双击看新旧封面;先确认商品状态生成范围,再按本轮「生成内容」下拉接入 `GenerateWorker` |
|
||||
| `ApplyTab(QWidget)` | ③ | 已生成任务筛选 +「更新内容」下拉 + 商品状态优先/内容完整性预检剔除 +「检查本轮更新」+ 分批开始更新确认 + 检查/真实更新运行日志 + 结果回写与结束汇总 |
|
||||
@@ -270,7 +273,7 @@
|
||||
| `BaseWorker(QObject)` | 后台 | 定义 `progress/log/row_updated/failed/finished/cancelled` signals |
|
||||
| `ApplyWorker(BaseWorker)` | ③ | 账号就绪预检、检查本轮更新、按每批最大条数分批、按账号并行或串行调用 `editor.apply_task(...)`、逐条 `set_applied()`,失败继续,写运行日志;执行层再次拒绝非正常商品状态 |
|
||||
| `AIModelTestWorker(BaseWorker)` | 设置 | 后台调用 `appconfig.test_ai_model()` 测试模型连接 |
|
||||
| `SubscriptionCheckWorker(BaseWorker)` | 根窗口 | 后台查询 cmhub 账号订阅状态;结果只通过 signal 回主线程更新会员标签和工作流可用性 |
|
||||
| `SubscriptionCheckWorker(BaseWorker)` | 根窗口 | 后台查询默认网关账号订阅状态;首次激活可使用只在内存中存在的 Base URL/Key 覆盖值,结果只通过 signal 回主线程更新会员状态和工作流可用性 |
|
||||
| `WriteBackWorker(BaseWorker)` | ①③ | ①回写旧字段;③回写新标题/新封面/更新状态 |
|
||||
| `ImageStudioPullImagesWorker / ImageStudioDownloadOriginalWorker / ProductSuiteImportImagesWorker / ProductSuiteGenerateWorker / ProductSuiteAiWriteWorker / CMHubModelCatalogWorker` | 商品套图 | 后台执行只读拉主图、远程原图下载、本地图片校验复制、默认网关异步或自定义网关同步套图生成、AI帮写和只读模型目录;拉图和本轮下载支持安全边界协作停止,worker 不直接操作 QWidget |
|
||||
|
||||
|
||||
+6
-1
@@ -3,7 +3,7 @@ id: T-701
|
||||
title: 新用户首次启动激活与使用引导
|
||||
phase: 8
|
||||
deps: [T-700]
|
||||
status: TODO
|
||||
status: DONE
|
||||
created: 2026-07-23
|
||||
---
|
||||
|
||||
@@ -88,3 +88,8 @@ created: 2026-07-23
|
||||
## 执行记录
|
||||
|
||||
- 2026-07-23:根据零基础新用户首次启动体验评审创建任务。当前实现只自动切到设置并显示状态栏提示,缺少会员 API Key 激活入口、默认地址和激活后的工作流引导。
|
||||
- 2026-07-23:内置默认网关和官方会员中心公开地址 `https://cm.833729.com`;配置缺失或空 Base URL 时使用默认值,已有非空地址保持不变。新增非敏感 `onboarding.first_use_guide_state`,空值不触发引导,避免存量用户被误判为新用户。
|
||||
- 2026-07-23:新增 `MembershipActivationDialog`。缺少 Key 时只显示会员 API Key、显示/隐藏、本地明文保存说明、验证、会员中心和退出;关闭窗口等同退出。验证使用 worker 内存覆盖值,不提前落盘;Key 无效、网络失败或非法响应保留输入且不保存,服务端未拒绝凭据后才写入 `data/config/cmhub.json`。
|
||||
- 2026-07-23:有效、宽限和旧服务兼容状态恢复业务 Tab;有效 Key 但未订阅、过期、撤销或账号不可用时保存 Key 供续费后重查,但激活窗口和业务门禁保持。首次激活成功后显示“添加店铺 → 人工登录 → 导入 Excel → 采集/生成/更新”清单,支持开始配置、稍后提醒和不再提示。
|
||||
- 2026-07-23:同步 `docs/04-architecture.md`、`docs/routes.md`、`docs/packaging.md`;新增配置、订阅、激活窗口、凭据落盘边界、官方会员中心、首次引导和存量配置兼容测试。临时 Qt 截图验证窗口约 `520×318`,控件无几何重叠;本机测试环境缺少 Qt 字体目录,因此截图不用于中文字形验收。
|
||||
- 2026-07-23:验证通过:`py -3.10 -m unittest discover -s tests`(699 项)、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check`。自动测试只使用临时目录和模拟订阅结果,未请求真实接口、未写入真实 `data/`、未使用真实 API Key。
|
||||
|
||||
Reference in New Issue
Block a user