Files
cmshoppe/docs/tasks/T-700.md
T

76 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: T-700
title: 会员过期强制提示与续费后重新检测
phase: 8
deps: [T-696, T-698]
status: DONE
created: 2026-07-23
---
## 问题 / 背景
桌面端已经具备真实订阅查询和强制门禁分支。强制模式检测到 `expired` 时会禁用除“设置”外的业务 Tab,并阻止新的 AI 生成、AI 帮写和商品套图提交,但当前只在状态栏显示到期原因,没有明确的续费入口。
用户需要在套餐到期时立即知道业务功能为何不可用,并能从默认浏览器进入线上会员中心。打开会员中心后程序仍应保持运行和锁定,让用户续费完成后主动重新检测,不要求修改设置或重启软件。
## 方案
### 1. 强制模式与弹窗触发
- 当前开发测试版本启用真实查询与客户端强制门禁。
- 仅当强制门禁开启,且本次程序运行期间首次进入 `expired` 状态时弹出中文模态框。
- 重复检查仍为 `expired` 时不重复弹窗;恢复为允许工作流的 `active`、`grace` 或 `legacy` 后,再次进入 `expired` 可以重新弹出。
- 网络抖动、接口暂时不可用、Key 无效、未订阅、撤销或账号禁用不复用该过期弹窗,继续使用各自现有中文状态和门禁语义。
- 应先应用业务 Tab 门禁和状态栏提示,再显示弹窗,避免弹窗关闭瞬间出现短暂可操作窗口。
### 2. 过期弹窗
- 标题使用「会员套餐已过期」,正文说明当前账号会员到期、业务功能已暂停,需要前往会员中心续费或更换套餐。
- 提供「前往会员中心」和「退出程序」两个明确操作:
- 「前往会员中心」调用 Qt 桌面服务,在系统默认浏览器打开 `SubscriptionStatus.manage_url`;应用保持打开并停留在受限的设置页。
- 「退出程序」关闭主窗口,沿用现有关闭事件、未保存设置确认和后台 worker 协作取消,不强杀进程。
- `manage_url` 只使用 `subscription._safe_manage_url()` 已接受的同网关主机 HTTPS 地址;地址缺失或不安全时禁用跳转按钮并显示中文说明,绝不猜测会员中心路径或打开其它协议。
- 默认按钮优先为可用的「前往会员中心」;不得把「退出程序」设为易误触的默认动作。关闭弹窗标题栏只关闭提示,业务门禁仍保持。
- 默认浏览器打开失败时显示中文状态反馈,不能暴露完整接口路径、API Key 或原始错误。
### 3. 续费后重新检测
- 设置页增加「重新检测会员状态」按钮,只负责通知主窗口重新执行现有异步订阅检查,不复制订阅请求逻辑。
- 检查运行期间按钮防重复触发;完成后恢复可用。返回 `active/grace/legacy` 时恢复业务 Tab,返回 `expired` 时继续锁定且不重复弹窗。
- 保存设置后的自动重查、启动异步检查、请求 token 隔离和陈旧结果丢弃逻辑保持不变。
## 验收要点
- 强制模式启动检测为 `expired` 时,先只保留“设置”Tab,再弹出一次「会员套餐已过期」。
- 同一次运行中连续返回 `expired` 不重复弹窗;恢复有效后再次到期会重新弹出。
- 点击「前往会员中心」使用默认浏览器打开经过安全过滤的 `manage_url`,应用保持打开且业务功能仍锁定。
- `manage_url` 缺失、非 HTTPS、带账号密码或跨域时不能打开,跳转按钮不可用并有中文说明。
- 点击「退出程序」走主窗口正常关闭流程;存在未保存设置时仍遵守现有保存/放弃/取消确认。
- 点击「重新检测会员状态」复用主窗口现有异步检查;续费后返回有效状态会恢复业务 Tab。
- 观察模式不弹过期框、不限制工作流;已有异步任务查询、下载、历史和导出不受影响。
- 自动验证:
- 订阅状态与安全会员中心地址测试
- 主窗口过期弹窗、去重、浏览器跳转、退出和重新检测定向 GUI 测试
- `py -3.10 -m unittest discover -s tests`
- `py -3.10 -m ruff check app tests main.py`
- `py -3.10 -m compileall app main.py`
- `git diff --check`
## 边界(不改什么)
- 不实现客户端会员中心、登录、支付、订单、退款或套餐购买页面。
- 不修改 cmhub 订阅接口路径、响应 schema、套餐状态或服务端最终授权。
- 不为 `manage_url` 设置硬编码备用网址,不开放 HTTP、外部域名或自定义协议。
- 不修改 AI、CDP、采集、封面上传、拖拽排序或更新蝦皮逻辑。
- 不中止已提交的异步生成任务,不限制本地历史查看和导出。
## 执行记录
- 2026-07-23:当前开发版本启用真实订阅查询与客户端强制门禁;查询期间及非允许状态只保留“设置”Tab,新提交继续由主窗口统一预检拦截。
- 新增「会员套餐已过期」中文模态框:本次运行首次进入 `expired` 时在门禁生效后弹出,连续过期查询不重复弹;恢复有效、宽限或旧服务兼容后再次到期可重新提示。
- 弹窗提供「前往会员中心」和「退出程序」。前者只消费订阅层已过滤的同网关 HTTPS `manage_url` 并用系统默认浏览器打开;地址缺失时禁用按钮,浏览器启动失败显示中文状态。后者调用主窗口正常关闭,保留未保存设置确认和 worker 协作取消。
- 设置页底部新增「重新检测会员状态」,通过 signal 通知主窗口复用现有异步检查;运行时按钮禁用并显示“正在检测会员状态...”,线程结束后恢复。保存设置自动重查、请求 token 和陈旧结果隔离逻辑不变。
- 更新架构和界面流程文档;新增过期弹窗去重、浏览器跳转失败、无地址禁用、退出、重新检测按钮状态及观察模式兼容测试。已提交任务的查询、下载、历史、预览和导出不受门禁影响。
- 本机脱敏联调结果仍为 `active`、允许产品工作流且安全会员中心地址可用;真实 `expired` 弹窗需 cmhub 将 dev 测试账号套餐改为过期后再人工验收,自动测试已覆盖该状态。
- 验证通过:订阅测试 6 项、`tests.test_gui`(222 项)、`py -3.10 -m unittest discover -s tests`(688 项)、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check`。