diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f59fd5..979edb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,120 @@ --- +## v2.1.8 (2026-06-24) — 测试弃用 warning 清零 + +### 🧪 测试依赖 + +- `requirements-dev.txt` 新增 `httpx2>=2.0.0` +- `starlette.testclient` → `httpx2` 的弃用 warning 已清除 + +### ✅ 验证 + +- `./.venv/bin/python -m pytest -q admin/tests/test_order_status_page.py admin/tests/test_web_public.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_portal_info.py admin/tests/test_order_deletion.py admin/tests/test_routes_cases.py admin/tests/test_routes_stats_dashboard.py admin/tests/test_admin_ui_pages.py admin/tests/test_order_info_form.py data/orders/tests/test_schema.py data/orders/tests/test_public_flow.py tests/test_backup_restore_service_level.py` → `149 passed` + +## v2.1.7 (2026-06-24) — 严格审查汇总版与最新入口切换 + +### 📄 审查与文档 + +- 新增 `reports/STRICT_SYSTEM_REVIEW_2026-06-24.md` + - 以当前仓库状态重写严格审查汇总版,不再继续在 6/23 过程稿上叠加历史结论 + - 明确当前结论:前台主链路、后台安全边界、恢复演练口径、后台录单契约、第五轮补充问题均已修复 +- `docs/CURRENT_STATE.md` 已切换为以 `STRICT_SYSTEM_REVIEW_2026-06-24.md` 作为最新严格审查结论 +- `docs/NAVIGATION.md` 已新增 6/24 汇总版入口,同时保留 6/23 过程稿作为历史轨迹参考 + +### ✅ 验证 + +- `./.venv/bin/python -m pytest -q admin/tests/test_order_status_page.py admin/tests/test_web_public.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_portal_info.py admin/tests/test_order_deletion.py admin/tests/test_routes_cases.py admin/tests/test_routes_stats_dashboard.py admin/tests/test_admin_ui_pages.py admin/tests/test_order_info_form.py data/orders/tests/test_schema.py data/orders/tests/test_public_flow.py tests/test_backup_restore_service_level.py` → `149 passed, 1 warning` + +## v2.1.6 (2026-06-23) — 主链路真实 TestClient 覆盖收口 + +### 🧪 测试可信度收口 + +- **用户端主链路不再依赖 `RouteClient` 自证** + - 公开页、内容页、资料页、状态页、报告页、CWB、full-plan、payment-success 的关键页面访问已迁到真实 `TestClient` + - `POST /api/public/orders`、`POST /review/action`(真实 form + 303)、`POST /pay/mock/{payment_id}/complete` 的主链路已迁到真实 `client` +- **前台关键测试文件已清零 `RouteClient`** + - `admin/tests/test_web_public.py` + - `admin/tests/test_web_public_content_pages.py` + - `admin/tests/test_web_public_review_flow.py` + - `admin/tests/test_web_public_portal_info.py` + - `admin/tests/test_order_status_page.py` +- **剩余 `RouteClient` 已降级为非前台主证据** + - 仅作为仓库中的轻量辅助夹具保留,不再用于这批关键前台测试文件 + +### 📄 文档 + +- 新增 `reports/TEST_CLIENT_COVERAGE_2026-06-23.md` +- `reports/STRICT_SYSTEM_REVIEW_2026-06-23.md` 与覆盖报告已互链 +- `docs/CURRENT_STATE.md` 已将两份 6/23 报告纳入真相源优先级前部 + +### ✅ 验证 + +- `./.venv/bin/python -m pytest -q admin/tests/test_web_public.py admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_portal_info.py` → `54 passed, 1 warning` +- `./.venv/bin/python -m pytest -q admin/tests/test_order_status_page.py admin/tests/test_web_public.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_portal_info.py data/orders/tests/test_schema.py` → `89 passed, 1 warning` + +## v2.1.5 (2026-06-23) — P1/P2 页面升级与轻量版本管理 + +### ✨ 新增 + +- **Step 2-4 / P2 偏好收口** + - Portal Step 2 新增 `target_cities` 输入控件 + - `submit_order_info` 现在保留 `profile_versions[]` 与 `latest_profile_version_id`,相同快照不重复记版本 +- **报告页 / 冲稳保页辅助能力升级** + - 报告页新增“基于最新档案生成 / 基于历史档案版本生成,建议刷新”判断 + - 报告页与冲稳保页新增政策中心、同分段参考入口与辅助判断因子区块 + - 完整规划入口页新增版本历史与辅助判断因子区块 +- **统一信任条** + - 政策中心与同分段参考页改为共用统一信任条:来源、更新时间、适用范围、适用省份、置信等级、边界文案 + - 同分段页继续保留“非高置信数据不得作为强推荐依据”约束 +- **轻量报告版本元数据** + - `order_intakes.payload_json` 新增 `report_versions[]` / `latest_report_version_id` + - 报告页外显与 `profile_versions[]` / `review_results{}` 形成最小版本关系 + +### 🧪 测试 + +- `admin/tests/test_web_public_portal_info.py` + - `test_portal_info_page_renders_target_cities_field` + - `test_submit_order_info_creates_profile_version_history_without_duplicate_snapshots` +- `admin/tests/test_web_public_review_flow.py` + - `test_cwb_page_links_policy_same_score_and_auxiliary_factors` + - `test_report_page_shows_latest_profile_state_and_helper_links` + - `test_report_page_warns_when_based_on_historical_profile_version` + - `test_full_plan_page_shows_profile_versions_and_assessment_context` +- `admin/tests/test_web_public_content_pages.py` + - `test_policy_and_same_score_pages_expose_helper_navigation` +- 回归:`./.venv/bin/python -m pytest -q admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_portal_info.py admin/tests/test_web_public_review_flow.py data/orders/tests/test_schema.py` → `60 passed` + +## v2.1.4 (2026-06-23) — 审核优先主线第三轮质量收敛 + +### ✨ 新增 + +- **审核页最小输入 / 约束 / 输出 / 分流四区块收口** + - `admin/routes/web_public.py` 的 `ReviewResultContract` 新增 `review_input_summary` / `review_input_attachments` / `review_constraints` + - `/review/start` 现在支持承接首页 `province / score / goal / consult` 查询参数,并把最小约束与现有方案说明写入轻量 review result + - 审核结果页不再只展示 JSON,占位页已补齐“审核输入 / 最小约束 / 审核输出摘要 / 下一步分流”四区块 +- **首页咨询卡回到审核主线** + - 首页咨询表单由 `/pricing` 改为 `/review/start` + - 增加隐藏字段 `source=home`,保持 `review_entry_source` 可追踪 +- **工作台主动作按资料完整度收口** + - 当 Step 1 已完成且还没有最近一次复核结果时,首页工作台默认动作改为“开始方案复核” + - 仍保留“继续补充 Step 1”与“继续查看最近一次复核”两种路径 + +### 🐛 修复 + +- **第三轮质量收敛残留**:首页咨询卡此前仍把用户导向 `/pricing`,与 `P0`“先审核再规划”主线不一致 +- **第三轮质量收敛残留**:审核页此前只有轻量 JSON 占位,未满足“输入区 / 最小约束区 / 结果区 / 分流区”结构验收 +- **第三轮质量收敛残留**:Step 1 已完整但无复核结果时,首页工作台仍默认指向补资料,造成主动作偏移 + +### 🧪 测试 + +- `admin/tests/test_web_public_review_flow.py` + - `test_landing_page_review_consult_form_targets_review_start` + - `test_landing_page_uses_review_as_workspace_primary_action_when_step1_complete` + - `test_review_start_page_renders_input_constraints_result_and_diversion` +- 回归:`./.venv/bin/python -m pytest -q admin/tests/test_web_public.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_portal_info.py admin/tests/test_web_public_review_flow.py data/orders/tests/test_schema.py` → `70 passed` + + ## v2.1.3 (2026-06-20) — 生产加固 + L-A 送审前修复 + crowd_db 质量契约 ### ✨ 新增 diff --git a/docs/COMPETITOR_SCREEN_ANALYSIS_WENXIN_QIANWEN_2026-06-21.md b/docs/COMPETITOR_SCREEN_ANALYSIS_WENXIN_QIANWEN_2026-06-21.md new file mode 100644 index 0000000..1c03115 --- /dev/null +++ b/docs/COMPETITOR_SCREEN_ANALYSIS_WENXIN_QIANWEN_2026-06-21.md @@ -0,0 +1,462 @@ +# 高考志愿服务竞品截图分析(文心 + 千问) + +最后更新: 2026-06-21 +分析对象: 百度文心高考志愿工具、阿里千问高考服务 +用途: 为 `gaokao-volunteer-system` 后续产品升级、交互重构、信息架构优化提供借鉴 + +--- + +## 1. 结论摘要 + +两组截图反映出两种不同路线: + +- **文心路线**:偏“表单驱动的报告生成器” + - 强项:信息收集维度全、偏好项细、移动端表单设计成熟 + - 弱项:任务驱动弱,用户容易停留在“填表生成”层 +- **千问路线**:偏“时间线驱动的志愿陪伴助手” + - 强项:阶段感、任务清单、持续运营、用户下一步指引很强 + - 弱项:深度偏好信息收集不如文心一步到位 + +对我们项目最重要的启示不是“抄一个更大的表单”,而是把两者结合成: + +> **时间线/任务清单负责持续陪伴,最小建档负责快速启动,分层偏好负责提高推荐精度,冲稳保/报告/同分段/政策中心负责形成高频使用闭环。** + +--- + +## 2. 分析样本范围 + +### 2.1 文心截图主要覆盖 + +1. 首页/空状态页 +2. 高考志愿档案大表单 +3. 家庭背景选择器 +4. 就业地域偏好选择器 +5. 行业资源选择器 +6. 聊天页内嵌建档卡片 + +### 2.2 千问截图主要覆盖 + +1. 首页时间线 + 任务清单 +2. 个人档案四步表单 +3. 聊天页基于档案生成报告的提示逻辑 + +--- + +## 3. 文心:产品结构与可借鉴点 + +## 3.1 文心的核心结构 + +文心更接近一个“AI 报告生成器 + 全量偏好表单系统”,结构上表现为: + +1. **入口页**: + - 高考加油 Banner + - 冲稳保三色标签 + - 领取报告 / 模拟填报 / 我的志愿表 / 职业兴趣 等宫格入口 +2. **建档页**: + - 基础信息 + - 志愿偏好信息 +3. **细分弹层选择器**: + - 家庭背景 + - 行业资源 + - 就业地域偏好 +4. **聊天辅助页**: + - AI 对话 + 表单卡片联动 + +--- + +## 3.2 文心最值得借鉴的能力 + +### A. 冲稳保三色体系是一级认知框架 + +文心把: + +- 可冲击 +- 较稳妥 +- 可保底 + +做成首页就能看见的三色标签。这不是普通筛选项,而是用户理解志愿填报的核心框架。 + +**对我们的启示**: + +- 冲稳保应从“报告里的结果分类”升级为“首页入口 + 筛选体系 + 报告结构 + 编辑视图”的统一心智模型。 + +### B. 偏好字段做得很全 + +文心的偏好字段远超“城市/专业”两三个维度,覆盖: + +- 院校类型 +- 目标院校 +- 专业偏好 +- 院校地域偏好 +- 毕业规划 +- 优先策略 +- 学费倾向 +- 就业地域偏好 +- 家庭背景 +- 行业资源 +- 补充说明 + +**对我们的启示**: + +- 需要把“硬约束”和“软偏好”彻底分开 +- 需要建立偏好体系,而不是只停留在 score/rank/subjects + 简单 notes + +### C. 选择器设计适合移动端 + +文心在移动端使用: + +- 多选 chip +- 分类弹层 +- 区域/行业选择面板 +- 底部固定 CTA + +这是成熟的手机表单模式。 + +**对我们的启示**: + +- 能用 chip 的不要都用文本输入 +- 能用分类选择器的不要都塞成长下拉 + +### D. 空状态转化做得好 + +“暂无志愿报告”并不是空白,而是立刻引导“领取志愿填报方案”。 + +**对我们的启示**: + +- 空状态必须转化,不要只显示“暂无数据” + +--- + +## 3.3 文心的限制 + +1. 更像“填资料 → 出报告”,缺少长期陪伴节奏 +2. 大表单虽然全面,但初次使用压迫感较强 +3. 任务推进感不如千问明确 + +--- + +## 4. 千问:产品结构与可借鉴点 + +## 4.1 千问的核心结构 + +千问不是先把所有字段摊开,而是先建立“高考志愿生命周期”框架: + +1. **首页长期入口**: + - 个人档案 + - 志愿日历 +2. **时间线**: + - 完善个人信息 + - 高考查分 + - 正式填报志愿 + - 查录取 +3. **任务清单**: + - 填档案 + - 提前规划 + - 预选冲稳保 + - 同分段参考 + - 查看官方政策 + - 性格测试 +4. **快捷能力**: + - 冲稳保 + - 志愿报告 + - 查大学/专业 +5. **聊天兜底**: + - 对话式补信息 + - 档案不足时 AI 主动提示缺失字段 + +--- + +## 4.2 千问最值得借鉴的能力 + +### A. 时间线/志愿日历非常强 + +千问把高考志愿服务做成“按时间推进的任务系统”。 + +**价值**: + +- 降低用户焦虑 +- 明确“我现在该做什么” +- 让产品具备长期复访理由 + +**对我们的启示**: + +- 我们必须新增“时间线/日历”层,不然产品仍偏一次性工具 + +### B. 任务清单把功能转成行动 + +千问每个功能都不是裸入口,而是任务: + +- 去了解 +- 去查看 +- 重要 + +且每条任务都有副标题说明价值。 + +**对我们的启示**: + +- 首页不要只放功能按钮,要放“任务化引导” + +### C. 最小建档做得克制 + +千问四步档案的第一步只要求: + +- 省份 +- 科目 +- 分数 +- 位次 + +这是非常合理的最小集。 + +**对我们的启示**: + +- 我们现有资料流程应先压缩到最小必填集,再逐层展开,不要一上来要求过多信息 + +### D. 结构化入口 + 自由对话并存 + +千问保留了: + +- 表单档案 +- 任务系统 +- 快捷能力 +- 聊天入口 + +用户既能按系统引导,也能直接发问。 + +**对我们的启示**: + +- 我们不能只做表单站,也不能只做聊天助手,要做双轨产品 + +### E. 同分段参考是极强的留存点 + +“同分段都怎么选”非常符合高考用户直觉。 + +**对我们的启示**: + +- 可基于 crowd_db / 风险检测 / 后续数据建设,增加“同分段热门学校/专业/城市”模块 + +### F. 政策中心是高信任入口 + +千问把“广东志愿填报官方政策”放入任务流。 + +**对我们的启示**: + +- 政策中心是信任建设点,不应只存在于内部文档 + +--- + +## 4.3 千问的限制 + +1. 深度偏好维度不如文心一次收得全 +2. 目前从截图看,对高复杂偏好的表达层仍较轻 +3. 个性化字段体系不如文心精细 + +--- + +## 5. 文心 vs 千问:统一对比 + +| 维度 | 文心 | 千问 | 我们应怎么做 | +| ---------- | ----------------- | ------------------ | ---------------------------- | +| 产品定位 | 表单驱动报告生成 | 时间线驱动陪伴助手 | 两者融合 | +| 首页心智 | 冲稳保 + 功能入口 | 时间线 + 任务清单 | 优先学千问结构,再接文心能力 | +| 建档方式 | 一次性较全收集 | 分步最小建档 | 先最小建档,再分层补齐 | +| 偏好维度 | 很全 | 较克制 | 学文心的偏好体系 | +| 长期陪伴 | 弱 | 强 | 学千问的时间线/任务机制 | +| 空状态转化 | 强 | 中 | 继续强化 | +| 聊天联动 | 有 | 更自然 | 我们要保留 | +| 政策中心 | 弱可见 | 强 | 我们要补 | +| 同分参考 | 未突出 | 强 | 我们要补 | + +--- + +## 6. 对 gaokao-volunteer-system 的升级建议 + +## 6.1 P0:近期必须做 + +### P0-1 首页重构为“任务化首页” + +新增首页结构: + +1. 顶部:高考阶段 Banner +2. 中部:志愿时间线 / 日历 +3. 中部:任务清单 +4. 下部:快捷入口 + - 冲稳保 + - 志愿报告 + - 查大学/专业 + - 方案审核 + +### P0-2 个人档案改为“最小建档 + 分步补充” + +建议拆为 4 步: + +#### Step 1 考生信息(最小必填) + +- 高考省份 +- 科目组合 +- 分数 +- 位次 + +#### Step 2 院校偏好 + +- 院校地域偏好 +- 院校类型 +- 目标院校(可选) + +#### Step 3 专业偏好 + +- 专业偏好 +- 不接受专业 +- 优先策略(院校优先/专业优先/就业优先) + +#### Step 4 其他偏好 + +- 毕业规划 +- 学费倾向 +- 就业地域偏好 +- 家庭背景 +- 行业资源 +- 补充说明 + +### P0-3 冲稳保升级为一级能力 + +冲稳保应同时出现在: + +- 首页快捷入口 +- 推荐结果页 +- 报告章节 +- 用户手动筛选视图 + +--- + +## 6.2 P1:建议尽快规划 + +### P1-1 同分段参考 + +可新增页面: + +- 同分段热门院校 +- 同分段热门专业 +- 同分段热门城市 +- 扎堆风险提示 + +### P1-2 政策中心 + +按省份提供: + +- 志愿填报时间 +- 批次规则 +- 选科要求 +- 常见误区 +- 官方政策摘要 + +### P1-3 报告资产化 + +把报告从单次输出升级成: + +- 我的志愿报告 +- 我的志愿表 +- 历史版本 +- 最近修改 + +--- + +## 6.3 P2:差异化增强 + +### P2-1 偏好体系细化 + +引入文心式偏好字段,但要遵守: + +- 默认折叠 +- 非首次必填 +- 明示用途 +- 不造成隐私压力 + +建议优先引入: + +- 学费倾向 +- 就业地域偏好 +- 毕业规划 +- 家庭背景 +- 行业资源 + +### P2-2 性格/兴趣测评联动 + +可考虑: + +- MBTI/霍兰德 作为辅助输入 +- 不作为强制项 +- 只作为专业推荐补充因子 + +--- + +## 7. 对现有项目的直接映射 + +## 7.1 当前已有基础 + +从现有代码和测试看,我们已经有: + +- portal 多步骤资料向导 +- score/rank/subjects 等核心字段 +- target cities / majors / preferences / notes +- 支付后进入资料补充 +- 状态页 / 交付页 / 报告页 +- 合规文档、同意审计、删除流程 + +## 7.2 当前明显缺失 + +1. **个人档案中心** 不够独立 +2. **首页任务清单** 不存在 +3. **志愿日历 / 时间线** 不存在 +4. **同分段参考** 不存在 +5. **政策中心** 没产品化 +6. **偏好字段体系** 不够完整 +7. **报告资产化** 不够强 + +--- + +## 8. 推荐实施顺序 + +### 第一阶段(先做) + +1. 首页任务化重构 +2. 高考个人档案中心 +3. 最小建档四步化 +4. 冲稳保入口升级 + +### 第二阶段(紧接着) + +5. 同分段参考 +6. 政策中心 +7. 报告资产化 + +### 第三阶段(增强) + +8. 家庭背景 / 行业资源 / 学费 / 就业地域等高级偏好 +9. 性格测评联动 +10. 多版本方案管理 + +--- + +## 9. 最终判断 + +如果只借鉴文心,我们会得到一个“更完整的填表产品”; +如果只借鉴千问,我们会得到一个“更强的陪伴式任务产品”。 + +对 `gaokao-volunteer-system` 最合适的方向是: + +> **用千问的时间线 + 任务系统做产品骨架,用文心的偏好字段体系做推荐深度。** + +一句话总结: + +> **文心解决“信息收集深度”,千问解决“用户持续推进”,我们要做的是“先任务化陪伴,再逐层建档,再输出冲稳保与志愿报告”的完整志愿服务闭环。** + +--- + +## 10. 后续可直接产出的文档 + +基于本分析,下一步可直接继续产出: + +1. `高考志愿服务升级 PRD` +2. `首页/档案页/报告页/政策中心/同分段参考 页面级改版清单` +3. `字段映射表(现有字段 -> 新档案体系)` +4. `P0/P1/P2 产品升级执行板` diff --git a/docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md b/docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md new file mode 100644 index 0000000..5c34d00 --- /dev/null +++ b/docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md @@ -0,0 +1,369 @@ +# 高考个人档案字段映射表(审核优先版) + +> 基于 `product/PRD_UPGRADE_2026-06-21.md` v0.2 与 `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` v0.2,将现有 Portal / Order / `order_intakes` 字段映射到新的“审核优先档案体系”。 + +**版本**: v0.2 +**状态**: Draft / 待复审 +**最后更新**: 2026-06-22 + +--- + +## 1. 文档目的 + +本映射表用于回答四个问题: + +1. 新档案体系里的字段,当前项目哪些已经有 +2. 这些字段现在存在哪一层(Order / `order_intakes.payload_json` / 前端临时态) +3. 哪些字段是 P0 必需,哪些字段延后到 P1 / P2 +4. 哪些状态 / 版本语义需要先定义,避免后续实现漂移 + +本表默认遵守: + +> **审核优先**:用户不需要先补齐完整档案才能开始服务;档案字段首先服务于“审核 / 复核”精度提升,其次才服务于完整规划。 + +--- + +## 2. 现有数据层概况 + +### 2.1 当前已存在的 3 层 + +#### A. Order 主表(`data/orders/models.py` / `dao.py`) + +适合存: + +- 订单级主字段 +- 面向列表 / 状态 / 交付的冗余字段 +- 少量需要快速查询的考生核心字段 + +当前已见核心字段: + +- `candidate_province` +- `candidate_score` +- `candidate_rank` +- `candidate_subjects` +- `candidate_interests` +- `candidate_strong_subjects` +- `candidate_weak_subjects` +- `candidate_family` +- `notes` +- `consent_method` +- `consent_given_at` + +#### B. `order_intakes.payload_json`(`data/orders/intake_schema.py` / `intake_store.py`) + +适合存: + +- Portal / 档案提交的结构化 payload +- 审核与规划过程中不断补充的字段 +- 同意审计上下文 + +当前已见字段: + +- `candidate_score` +- `candidate_rank` +- `candidate_subjects` +- `candidate_interests` +- `target_cities` +- `target_majors` +- `university_preferences` +- `existing_plan_summary` +- `guardian_notes` +- `consent_version` +- `consent_scope` +- `privacy_accepted` +- `service_terms_accepted` +- `guardian_confirmed` +- 自动补齐:`consent_channel` / `consent_operator` / `consent_given_at` / `privacy_accepted_at` / `service_terms_accepted_at` + +#### C. 前端页面临时态 + +当前前端页面中有展示与交互,但未必已结构化入库的扩展能力,后续新增字段优先从这里切。 + +--- + +## 3. 新档案体系目标分层 + +### Step 1 考生信息(最小必填 / P0) + +用于: + +- 启动审核 +- 启动冲稳保判断 +- 启动最小版本报告 + +字段: + +- 高考省份 +- 科目组合 +- 分数 +- 位次 + +### Step 2 院校偏好(P1) + +用于: + +- 审核时判断当前院校倾向是否失衡 +- 进入完整规划时做院校维度筛选 + +字段: + +- 院校地域偏好 +- 院校类型 +- 目标院校 + +### Step 3 专业偏好(P1) + +用于: + +- 审核当前专业方向是否偏离用户意向 +- 完整规划时做专业匹配与排除 + +字段: + +- 专业偏好 +- 不接受专业 +- 优先策略 + +### Step 4 其他偏好(P1 / P2) + +用于: + +- 提升推荐解释性 +- 提升后续报告个性化质量 + +字段: + +- 毕业规划 +- 学费倾向 +- 就业地域偏好 +- 家庭背景 +- 行业资源 +- 补充说明 + +--- + +## 4. 字段映射主表 + +| 新档案字段 | 当前是否存在 | 当前字段名 | 当前存储层 | 建议最终层 | 分期 | 说明 | +| --- | --- | --- | --- | --- | --- | --- | +| 高考省份 | ✅ | `candidate_province` | Order | Order + Intake | P0 | 最小必填 | +| 科目组合 | ✅ | `candidate_subjects` | Order + Intake | Order + Intake | P0 | 最小必填 | +| 分数 | ✅ | `candidate_score` | Order + Intake | Order + Intake | P0 | 最小必填 | +| 位次 | ✅ | `candidate_rank` | Order + Intake | Order + Intake | P0 | 最小必填 | +| 现有方案摘要 | ✅ | `existing_plan_summary` | Intake | Intake | P0 | 审核主输入字段 | +| 专业兴趣简述 | ✅ | `candidate_interests` | Order + Intake | Intake 为主 | P1 | 当前更像自由文本 | +| 目标院校(列表) | ⚠️ 部分 | 当前未结构化 | - | Intake | P1 | 需要新增 `target_schools` | +| 目标专业(列表) | ✅ | `target_majors` | Intake | Intake | P1 | 已有 | +| 目标城市 / 地域偏好 | ✅ | `target_cities` | Intake | Intake | P1 | 需要升级为更通用地域偏好 | +| 院校偏好说明 | ✅ | `university_preferences` | Intake | Intake | P1 | 现阶段仍可兼容保留 | +| 家庭背景 | ⚠️ 弱存在 | `candidate_family` | Order | Intake(主)+ Order(必要冗余) | P2 | 当前语义不足 | +| 强势学科 | ✅ | `candidate_strong_subjects` | Order | Order / Intake | P2 | 当前 Portal 未系统化采集 | +| 弱势学科 | ✅ | `candidate_weak_subjects` | Order | Order / Intake | P2 | 当前 Portal 未系统化采集 | +| 监护人 / 补充备注 | ✅ | `guardian_notes` | Intake | Intake | P1 | 可并入补充说明层 | +| 同意版本 | ✅ | `consent_version` | Intake | Intake + 必要冗余 | 已有 | 不属于偏好字段,但需持续保留 | +| 同意范围 | ✅ | `consent_scope` | Intake | Intake + 必要冗余 | 已有 | 同上 | +| 隐私同意 | ✅ | `privacy_accepted` | Intake | Intake | 已有 | 同上 | +| 服务条款同意 | ✅ | `service_terms_accepted` | Intake | Intake | 已有 | 同上 | +| 监护人确认 | ✅ | `guardian_confirmed` | Intake | Intake | 已有 | 同上 | + +--- + +## 5. P0 字段边界(先让审核优先主线成立) + +### 5.1 P0 只要求以下字段可用 + +- `candidate_province` +- `candidate_subjects` +- `candidate_score` +- `candidate_rank` +- `existing_plan_summary`(或等价审核输入) + +### 5.2 P0 不要求完成的内容 + +- 不要求 `target_schools` 已落地 +- 不要求 Step 2-4 偏好字段全部结构化 +- 不要求一次性迁移旧订单数据 +- 不要求旧 payload 立即补齐所有新字段 + +### 5.3 P0 需要先定义的状态 / 元数据语义 + +- `profile_minimum_complete`:最小建档是否完成 +- `review_entry_source`:用户从首页 / 审核页 / 报告页等入口进入审核 +- `review_followup_action`:审核后进入了哪条分流动作 + +这些语义可以先以派生状态或轻量元数据存在,不强制一开始就做重 schema 改造。 + +--- + +## 6. P1 / P2 建议新增字段 + +### 6.1 P1:院校 / 专业偏好层 + +- `target_schools` +- `school_preference_types` +- `school_region_preferences` +- `disliked_majors` +- `priority_strategy` + +### 6.2 P1:其他偏好层(先落高频) + +- `graduation_plan` +- `tuition_preference` +- `employment_region_preferences` + +### 6.3 P2:深层解释型偏好 + +- `family_background` +- `industry_resources` +- `extra_notes` + +--- + +## 7. 字段分层建议(避免乱塞到 Order 主表) + +### 7.1 应保留在 Order 主表的字段 + +这些字段适合继续保留或冗余到 Order,便于: + +- 状态页 +- 列表页 +- 快速查询 +- 报告摘要 + +建议保留: + +- `candidate_province` +- `candidate_score` +- `candidate_rank` +- `candidate_subjects` +- `candidate_interests`(如继续保留) +- `candidate_strong_subjects` +- `candidate_weak_subjects` +- `candidate_family`(仅作为旧字段兼容) + +### 7.2 应以 Intake 为主的字段 + +这些字段更适合存到 `order_intakes.payload_json`: + +- 所有偏好型、可选型、多选型字段 +- 所有逐步补充字段 +- 审核与规划解释型字段 + +原因: + +- 变化频率高 +- 可逐步补全 +- 不一定需要主表强查询 +- 便于迭代扩展 + +### 7.3 何时再冗余到 Order + +如果后续页面 / 接口高频读取某个字段,且不想每次 decode intake,可把稳定字段冗余回 Order。 + +优先考虑未来可能冗余的: + +- `priority_strategy` +- `graduation_plan` +- `tuition_preference` + +前提: + +- 先在 Intake 侧稳定语义 +- 再决定是否冗余,不要一开始就把所有偏好塞进主表 + +--- + +## 8. 状态与版本字段(最小定义) + +为与升级 PRD 保持一致,字段层至少要承接以下语义: + +- `profile_version`:每次用户保存档案快照时递增 +- `review_result_version`:每次审核提交产生一个结果快照 +- `report_version`:每次报告生成产生一个版本 + +最小关系: + +- 报告要能关联其生成时的 `profile_version` +- 审核结果要能关联输入快照 +- “是否基于最新档案生成”要能比较得出 + +这三者可以先定义为领域对象 / 组装层语义,不要求在首轮就铺完整物理表设计。 + +--- + +## 9. 迁移与兼容建议 + +### 9.1 不破坏现有主链 + +原则: + +- 不因为新档案体系而破坏当前 Portal 主链 +- 不要求一次性迁移旧订单数据 +- 不要求旧 payload 立即补齐所有新字段 + +### 9.2 兼容策略 + +#### 旧字段兼容 + +- `university_preferences` 暂继续保留 +- `guardian_notes` 暂继续保留 +- `candidate_family` 暂继续保留 + +#### 新字段渐进接入 + +- 新页面先写新字段 +- 旧页面仍能读旧字段 +- 报告组装层做兼容映射 + +--- + +## 10. 字段映射实施优先级 + +### P0 + +- 锁定最小审核字段与建档字段边界 +- 固化 `existing_plan_summary` 的产品主角色 +- 定义 `profile_minimum_complete` / `review_entry_source` / `review_followup_action` 语义 + +### P1 + +- 加 `target_schools` +- 加 `school_preference_types` +- 加 `school_region_preferences` +- 加 `disliked_majors` +- 加 `priority_strategy` +- 加 `graduation_plan` +- 加 `tuition_preference` +- 加 `employment_region_preferences` + +- `family_background` +- `industry_resources` +- `extra_notes` +- `interest_assessment_type` +- `interest_assessment_result` +- `interest_assessment_notes` +- `target_cities` 前台输入控件与保存链路已打通(2026-06-23) + + +--- + +## 11. 验收口径 + +字段映射完成后,应满足: + +1. 审核优先主线可用最小字段启动 +2. Step 2-4 不会反向阻塞审核入口 +3. 新偏好字段有明确命名和分层归属 +4. Order 与 Intake 的职责边界清楚 +5. 版本语义在实现前就已钉住,不会后期漂移 + +--- + +## 12. 后续衔接文档 + +基于本映射表,下一步建议直接产出: + +1. `P0/P1/P2 产品升级执行板` +2. `具体接口变更清单` +3. `Portal 表单改版实现计划` +4. `报告版本与档案版本关系说明` diff --git a/docs/P0_EXECUTION_TASK_BREAKDOWN_2026-06-22.md b/docs/P0_EXECUTION_TASK_BREAKDOWN_2026-06-22.md new file mode 100644 index 0000000..53a893c --- /dev/null +++ b/docs/P0_EXECUTION_TASK_BREAKDOWN_2026-06-22.md @@ -0,0 +1,323 @@ +# P0_EXECUTION_TASK_BREAKDOWN_2026-06-22 + +最后更新: 2026-06-22 +状态词: P0 执行拆分文档 +真相源: +- `docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md` +- `product/PRD_UPGRADE_2026-06-21.md` +- `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` +- `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` + +> 本文把 P0-1 ~ P0-4 继续拆成页面 / 接口 / 状态 / 埋点四类子任务,供产品、前端、后端和埋点实现直接认领。 + +--- + +## 1. 拆分原则 + +P0 只解决一件事: + +> 让“首页 -> 审核 -> Step 1 补充 -> 审核结果分流”这条默认主线真实成立。 + +因此所有子任务都必须满足: + +- 不把 Step 2-4 偏好字段拉进 P0 +- 不把政策中心 / 同分段参考的完整产品化混进 P0 +- 不把生产 readiness 问题混进 P0 +- 不把“设计占位”误报为“能力完成” + +--- + +## 2. P0-1 首页任务化 + 审核主 CTA 前置 + +### 2.1 页面子任务 + +1. 定义首页首屏结构 + - Banner + - 任务清单 + - 主 CTA + - 次 CTA + - 最近审核结果 / 报告入口 +2. 定义首页任务卡文案 + - 默认第一任务 = 先审核现有志愿方案 + - 第二任务 = 完善个人档案 +3. 定义首页状态态 + - 未建档但可先审核 + - 已有最近审核结果 + - 已有报告 + - 查分阶段切换态 + +### 2.2 接口子任务 + +1. 明确首页是否直接复用现有落地页接口,还是新增工作台聚合接口 +2. 如果新增聚合接口,最小返回需包含: + - 当前阶段 + - 是否存在最近审核结果 + - 是否存在可查看报告 + - Step 1 是否已完成 +3. 若先不新增接口,需明确定义首页由哪些现有接口拼装 + +### 2.3 状态子任务 + +1. 定义首页展示状态来源 + - `stage` + - `intake_status` + - 报告是否 ready +2. 定义“最近审核结果可用”的判定条件 +3. 定义首页主 CTA 不受 `profile_minimum_complete` 阻塞 + +### 2.4 埋点子任务 + +1. 首页曝光 +2. 主 CTA 点击 +3. 次 CTA 点击 +4. 最近审核结果入口点击 +5. 报告入口点击 +6. 首页任务卡点击分布 + +### 2.5 完成判定 + +- 首页第一主动作已固定为审核 +- 首页不再把完整规划 / 生成方案置顶 +- 未建档用户点击后可直接进入审核链路 + +--- + +## 3. P0-2 审核页最小闭环 + +### 3.1 页面子任务 + +1. 定义审核页输入结构 + - 现有方案说明 textarea + - 上传附件入口 + - 初步想法输入 +2. 定义最小约束区 + - 省份 + - 科目组合 + - 分数 + - 位次 +3. 定义结果区结构 + - 风险等级 + - 问题数量 + - 核心问题 3 条 +4. 定义分流区结构 + - 去冲稳保 + - 去补 Step 1 + - 去完整规划 / 报告 + +### 3.2 接口子任务 + +1. 盘点现有可复用输入承接 + - 已有 `existing_plan_summary` + - 已有附件上传 + - 已有 Portal intake 提交接口 +2. 定义审核提交最小 payload + - `existing_plan_summary` + - `candidate_province` + - `candidate_subjects` + - `candidate_score` + - `candidate_rank` +3. 定义审核结果最小返回结构 + - `review_result_id` 或等价结果主键 + - `risk_level` + - `top_findings[]` + - `recommended_action` + - `available_actions[]` + +### 3.3 状态子任务 + +1. 定义审核页本地状态 + - idle + - submitting + - success + - failed +2. 定义审核结果状态 + - 无结果 + - 有结果待分流 + - 已进入后续动作 +3. 定义与现有 Portal `stage` 的关系 + - P0 可先不改订单六态 + - 审核页结果状态优先作为页面层状态,不强绑订单状态机 + +### 3.4 埋点子任务 + +1. 审核页曝光 +2. 审核提交点击 +3. 审核提交成功 +4. 审核提交失败 +5. 审核输入来源 + - 首页进入 + - 订单状态页进入 + - 报告页进入 +6. 审核结果默认推荐动作曝光 + +### 3.5 完成判定 + +- 未完成完整档案的用户可提交审核 +- 页面有输入区、最小约束区、结果区、分流区 +- 审核结果不再是孤立说明文本 + +--- + +## 4. P0-3 Step 1 最小建档 + +### 4.1 页面子任务 + +1. 把现有四步资料向导重新切分为 P0 最小视图 +2. 明确 Step 1 只显示: + - 省份 + - 科目组合 + - 分数 + - 位次 +3. 明确 Step 2-4 在 P0 只允许: + - 隐藏 + - 或显示为后续增强,不阻塞当前提交 +4. 明确“未填完整档案,也可以先审核”提示位 + +### 4.2 接口子任务 + +1. 复用现有 `/portal/{token}/info` 提交链路 +2. 为 P0 明确最小建档 payload + - `candidate_province` + - `candidate_subjects` + - `candidate_score` + - `candidate_rank` + - `mode=draft|submit` +3. 明确 P0 不要求提交: + - `candidate_interests` + - `target_cities` + - `target_majors` + - `university_preferences` +4. 评估是否需要给 `IntakePayload` 放宽提交校验,避免 P0 继续被“至少一个偏好字段”卡住 + +### 4.3 状态子任务 + +1. 定义 `profile_minimum_complete` + - 四字段齐全 = true + - 否则 false +2. 定义草稿保存成功状态 +3. 定义回填来源 + - `order_intakes.payload_json` + - `orders` 冗余字段 + +### 4.4 埋点子任务 + +1. Step 1 页面曝光 +2. Step 1 草稿保存点击 / 成功 / 失败 +3. Step 1 提交点击 / 成功 / 失败 +4. Step 1 字段缺失分布 +5. 从审核结果页跳来补 Step 1 的来源记录 + +### 4.5 完成判定 + +- Step 1 可独立保存 +- Step 1 保存后可回填到审核页和报告页 +- Step 2-4 不再是 P0 审核门槛 + +--- + +## 5. P0-4 审核结果分流 + +### 5.1 页面子任务 + +1. 定义审核结果分流卡片 + - 推荐去冲稳保 + - 推荐补充 Step 1 + - 推荐进入完整规划 / 报告 +2. 每个动作附适用说明 +3. 明确默认推荐动作展示位 + +### 5.2 接口子任务 + +1. 定义分流动作枚举 + - `go_cwb` + - `go_step1` + - `go_full_plan` +2. 定义审核结果返回里的推荐动作字段 +3. 若暂不存正式结果对象,先定义轻量动作记录结构 + +### 5.3 状态子任务 + +1. 定义 `review_entry_source` + - home + - status + - report + - direct +2. 定义 `review_followup_action` + - cwb + - step1 + - full_plan + - none +3. 定义“已分流”与“未分流”判定 + +### 5.4 埋点子任务 + +1. 审核结果曝光 +2. 默认推荐动作点击 +3. 冲稳保入口点击 +4. Step 1 补充入口点击 +5. 完整规划 / 报告入口点击 +6. 分流后返回率 / 流失率 + +### 5.5 完成判定 + +- 审核结果页至少存在一个默认推荐动作 +- 三条分流路径都能进入对应目标页 +- 分流动作可以记录和回放来源 + +--- + +## 6. 跨 P0 公共子任务 + +### 6.1 页面公共任务 + +1. 统一“审核优先”文案 +2. 统一 Step 1 与后续增强的边界提示 +3. 统一首页 / 审核页 / 档案页 / 结果页的跳转关系 + +### 6.2 接口公共任务 + +1. 统一最小字段命名 +2. 统一审核输入、Step 1 保存、审核结果分流的数据承接方式 +3. 统一是否新增聚合接口还是复用现有 Portal 接口 + +### 6.3 状态公共任务 + +1. 统一 `stage`、`intake_status`、页面层审核状态之间的关系 +2. 保持订单 6 态不被 P0 页面状态污染 +3. 把审核页/结果页状态定义为页面域状态优先 + +### 6.4 埋点公共任务 + +1. 统一页面来源字段 +2. 统一动作枚举 +3. 统一漏斗口径 + - 首页 -> 审核页 + - 审核页 -> 结果页 + - 结果页 -> 分流动作 + - 分流动作 -> 后续页面 + +--- + +## 7. 当前阻塞与先行修正点 + +### 7.1 现有实现与 P0 口径冲突点 + +1. `IntakePayload` 当前 `mode=submit` 只要求 Step 1 最小建档字段: + - `candidate_province` / `candidate_score` / `candidate_rank` / `candidate_subjects` +2. `candidate_interests` / `target_cities` / `target_majors` / `university_preferences` 已不再是提交阻塞条件 +3. 现有资料向导已统一为“五步资料向导”,Portal `stage` 仍围绕支付 / 补资料 / 交付状态,不含审核结果分流语义 + + +### 7.2 必须先澄清的决策 + +1. P0 是否直接复用当前 `/portal/{token}/info`,还是新建独立审核页提交接口 +2. `candidate_province` 是否进入 Step 1 主提交链,而不是只停留在下单阶段 +3. 审核结果对象是先做轻量页面结果,还是先建独立持久化对象 + +--- + +## 8. 下一步建议 + +1. 基于本文继续输出《P0 最小接口变更清单》 +2. 基于本文继续输出《报告版本与档案版本关系说明》 +3. 在接口清单确定前,不要开始拆 Step 2-4 或内容中心实现 diff --git a/docs/P0_MINIMAL_API_CHANGES_2026-06-22.md b/docs/P0_MINIMAL_API_CHANGES_2026-06-22.md new file mode 100644 index 0000000..9242bb7 --- /dev/null +++ b/docs/P0_MINIMAL_API_CHANGES_2026-06-22.md @@ -0,0 +1,385 @@ +# P0_MINIMAL_API_CHANGES_2026-06-22 + +最后更新: 2026-06-22 +状态词: P0 最小接口变更清单 +真相源: +- `product/PRD_UPGRADE_2026-06-21.md` +- `docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md` +- `docs/P0_EXECUTION_TASK_BREAKDOWN_2026-06-22.md` + +> 本文只定义 P0 为了成立“审核优先主线”所需的最小接口与数据承接变更;不提前展开 P1 / P2。 + +--- + +## 1. 当前可复用接口盘点 + +当前已存在的关键接口 / 页面: + +### 1.1 公开下单链 + +- `POST /api/public/orders` +- 返回: + - `order_id` + - `checkout_url` + - `portal_status_url` + - `portal_info_url` + +当前作用: + +- 创建订单 +- 进入支付 +- 进入 Portal 资料页 / 状态页 + +### 1.2 Portal 资料链 + +- `GET /portal/{token}/info` +- `POST /portal/{token}/info` +- `POST /portal/{token}/attachments` + +当前作用: + +- 四步资料向导 +- 保存草稿 / 正式提交 +- 上传已有方案附件 + +### 1.3 Portal 状态链 + +- `GET /portal/{token}/status` +- `GET /portal/{token}/report` +- `GET /portal/{token}/report.pdf` + +当前作用: + +- 看订单阶段 +- 看报告 / PDF + +### 1.4 当前主要限制 + +1. `POST /portal/{token}/info` 当前绑定 `IntakePayload` +2. `IntakePayload(mode=submit)` 当前要求至少一个偏好字段存在 +3. 现有 `stage` 面向支付 / 补资料 / 交付,不面向审核结果分流 +4. 现有接口无 `profile_minimum_complete` / `review_entry_source` / `review_followup_action` 语义 + +--- + +## 2. P0 最小接口策略 + +结论: + +- **优先复用现有 Portal 链路** +- **最小新增页面域状态与轻量返回字段** +- **避免在 P0 修改订单六态状态机** + +也就是: + +1. 不新建整套用户系统接口 +2. 先复用: + - `/portal/{token}/info` + - `/portal/{token}/attachments` + - `/portal/{token}/status` +3. 必要时新增轻量接口或返回字段,承接: + - 审核输入 + - Step 1 最小建档 + - 审核结果分流 + +--- + +## 3. P0 必改接口项 + +## 3.1 调整 `IntakePayload` 提交校验 + +### 当前问题 + +`data/orders/intake_schema.py` 当前在 `mode=submit` 时要求: + +- `candidate_score` +- `candidate_rank` +- `candidate_subjects` +- 协议字段 +- `candidate_interests` +- `target_cities` +- `target_majors` +- `university_preferences` + +以上字段当前已不再作为 `mode=submit` 的阻塞校验;P0 Step 1 最小提交仅要求省份 / 分数 / 位次 / 选科 + consent。 + +### P0 目标 + +P0 提交只要求: + +- `candidate_province` +- `candidate_subjects` +- `candidate_score` +- `candidate_rank` +- 协议字段 + +### 变更建议 + +把 `IntakePayload(mode=submit)` 的“至少一个偏好字段”校验下放到 P1 语义,不再阻塞 P0。 + +### 影响 + +- Step 1 可独立提交 +- 审核入口不再被偏好字段卡死 + +--- + +## 3.2 把 `candidate_province` 纳入 Portal info 提交链 + +### 当前问题 + +当前 Portal info 表单主提交字段中: + +- 有 `candidate_score` +- 有 `candidate_rank` +- 有 `candidate_subjects` +- **没有 Step 1 主视图里的 `candidate_province`** + +而 PRD 已明确 Step 1 四字段必须包含省份。 + +### 变更建议 + +1. 给 `IntakePayload` 增加 `candidate_province` +2. 给 `/portal/{token}/info` 前端表单补 `candidate_province` +3. 在 `submit_order_info()` 中把 `candidate_province` 写回: + - `order_intakes.payload_json` + - 必要时冗余回 `orders.candidate_province` + +### 影响 + +- Step 1 四字段闭环成立 +- 审核最小约束与档案最小建档一致 + +--- + +## 3.3 为 `/portal/{token}/info` 响应补最小建档状态 + +### 当前返回 + +`PortalIntakeResponse` 目前只有: + +- `intake_status` +- `stage` +- `order_id` + +### P0 缺口 + +P0 需要知道: + +- Step 1 是否完成 +- 页面提交后是否可回到审核链路 + +### 变更建议 + +给 `PortalIntakeResponse` 增加: + +- `profile_minimum_complete: bool` + +可选增加: + +- `profile_missing_fields: string[]` + +### 计算规则 + +当以下字段齐全时: + +- `candidate_province` +- `candidate_subjects` +- `candidate_score` +- `candidate_rank` + +则 `profile_minimum_complete = true` + +--- + +## 3.4 新增或补充首页 / 状态页聚合返回字段 + +### 当前问题 + +首页目标态要求显示: + +- 当前阶段 +- 是否有最近审核结果 +- 是否可看报告 +- Step 1 是否完成 + +现有公开链路没有专门的工作台聚合结构。 + +### P0 建议 + +二选一: + +#### 方案 A:新增轻量聚合接口 + +建议新增: + +- `GET /portal/{token}/workspace-summary` + +最小返回: + +- `stage` +- `profile_minimum_complete` +- `has_recent_review_result` +- `has_report` +- `primary_action` + +#### 方案 B:复用 `_build_portal_context()` 输出 + +如果暂不新开接口,则在现有状态页 / 首页承接层统一从 `_build_portal_context()` 衍生: + +- `profile_minimum_complete` +- `has_report` +- `primary_action` + +### 推荐 + +- P0 推荐 **方案 B 先落** +- 等首页工作台稳定后再决定是否抽独立聚合接口 + +--- + +## 3.5 定义审核输入最小承接结构 + +### 当前可复用资产 + +现有已存在: + +- `existing_plan_summary` +- attachments 上传 + +### P0 目标 + +审核最小输入统一为: + +- `existing_plan_summary` +- `attachments[]` +- `candidate_province` +- `candidate_subjects` +- `candidate_score` +- `candidate_rank` + +### 变更建议 + +不急着在 P0 新建复杂审核对象表;先定义轻量审核输入契约,供页面和后端处理链共用。 + +建议文档化结构: + +- `review_input_summary` +- `review_input_attachments` +- `review_constraints` + +如果后端要临时落地,可先存在: + +- `order_intakes.payload_json` +- 或单独轻量 JSON artifact + +--- + +## 3.6 定义审核结果最小返回结构 + +### 当前问题 + +现有 Portal 链路没有“审核结果分流”的最小对象。 + +### P0 最小返回建议 + +新增轻量审核结果返回结构: + +- `review_result_id` +- `risk_level` +- `top_findings[]` +- `recommended_action` +- `available_actions[]` + +其中: + +- `recommended_action ∈ {go_cwb, go_step1, go_full_plan}` +- `available_actions[]` 至少含三类入口 + +### 注意 + +P0 可以先把它定义成页面域结构,不强制先做完整持久化模型。 + +--- + +## 3.7 定义审核分流记录字段 + +### 当前缺口 + +现有代码中尚未实现: + +- `review_entry_source` +- `review_followup_action` + +### P0 建议 + +最小先定义语义,不必一开始改重 schema: + +- `review_entry_source ∈ {home, status, report, direct}` +- `review_followup_action ∈ {cwb, step1, full_plan, none}` + +### 落地方式建议 + +P0 可先落在: + +- 页面埋点事件 +- 轻量 metadata 字段 +- 或会话态 / 结果对象中 + +只要保证: + +- 来源可追踪 +- 分流动作可统计 + +--- + +## 4. P0 不建议现在改的接口项 + +以下内容不要提前混入 P0: + +1. Step 2-4 全量偏好字段接口 +2. 政策中心完整 API +3. 同分段参考完整 API +4. 完整报告资产列表 API +5. 多版本方案管理 API +6. 订单六态状态机扩容 + +原因: + +- 这些都属于 P1 / P2 +- 先改只会扩大范围 + +--- + +## 5. 最小接口变更表 + +| 变更项 | 类型 | 当前状态 | P0 动作 | 必须性 | +| --- | --- | --- | --- | --- | +| `IntakePayload` 去掉偏好字段提交门槛 | 校验逻辑 | 与 P0 冲突 | 修改 | 必须 | +| `IntakePayload` 增 `candidate_province` | 请求字段 | 缺失 | 新增 | 必须 | +| `/portal/{token}/info` 表单补省份 | 页面 + 提交 | 缺失 | 修改 | 必须 | +| `/portal/{token}/info` 响应补 `profile_minimum_complete` | 响应字段 | 缺失 | 新增 | 建议 | +| 统一审核最小输入结构 | 契约定义 | 未定义 | 新增 | 必须 | +| 定义审核结果最小返回结构 | 契约定义 | 未定义 | 新增 | 必须 | +| 定义 `review_entry_source` | 状态 / 埋点语义 | 未定义 | 新增 | 必须 | +| 定义 `review_followup_action` | 状态 / 埋点语义 | 未定义 | 新增 | 必须 | +| 首页工作台聚合接口 | 新接口 | 无 | 可延后 / 先复用 | 可选 | + +--- + +## 6. 推荐实现顺序 + +1. 先修改 `IntakePayload`,解除 P0 与当前提交校验冲突 +2. 把 `candidate_province` 接入 `/portal/{token}/info` +3. 定义 `profile_minimum_complete` +4. 定义审核输入 / 审核结果最小契约 +5. 定义分流动作与来源字段 +6. 最后再决定是否补首页工作台聚合接口 + +--- + +## 7. 下一步建议 + +1. 基于本文继续落《报告版本与档案版本关系说明》 +2. 确认 `review_result` 是页面态还是轻量持久化对象 +3. 确认 `profile_minimum_complete` 是纯派生字段还是落库存字段 diff --git a/docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md b/docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md new file mode 100644 index 0000000..67445c1 --- /dev/null +++ b/docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md @@ -0,0 +1,580 @@ +# 高考志愿服务页面级改版清单(审核优先版) + +> 基于 `product/PRD_UPGRADE_2026-06-21.md` v0.2:**默认先做志愿审核/复核,再按需进入完整规划**。 + +**版本**: v0.2 +**状态**: Draft / 待复审 +**最后更新**: 2026-06-22 + +--- + +## 1. 文档目的 + +本清单用于把升级 PRD 里的产品方向,下钻为可执行的页面级改版范围。它回答四个问题: + +1. 每个关键页面为什么要改 +2. 每个页面要改成什么样 +3. 每个页面的主任务、状态、文案边界、验收重点是什么 +4. 哪些页面属于 P0 必做,哪些属于 P1 / P2 后续增强 + +本清单不是代码实现文档,也不是原型稿;它是 **PRD → 设计 / 实现任务** 的桥接文档。 + +本清单**不替代**当前生产 readiness 执行板。 + +--- + +## 2. 页面级总原则 + +### 2.1 总体口径 + +所有用户侧页面统一遵守: + +> **默认服务主线 = 先审核现有志愿方案 / 现有想法,再决定是否进入完整规划。** + +禁止重新滑回: + +- “先完整建档 → 直接生成新方案”作为默认主路径 +- 用竞品的“默认生成方案”话术覆盖我们的审核差异化 + +### 2.2 页面文案统一原则 + +必须统一强调: + +- 先审计现有方案 / 现有意向 +- 先看风险是否存在 +- 再决定是否要进入完整规划 + +禁止出现: + +- “默认直接智能生成志愿方案” +- “只要填完档案就自动得出最优答案” +- “高考志愿结果由系统直接决定” + +### 2.3 页面分期原则 + +#### P0:先让审核优先主线成立 + +1. 首页 +2. 方案审核页 +3. 个人档案页 Step 1 +4. 审核结果分流层 + +#### P1:再做决策与内容增强 + +5. 冲稳保页 +6. 报告页重组 +7. 政策中心 +8. 同分段参考页 + +### 2.4 验收写法原则 + +每个页面都要同时定义: + +- **结构验收**:页面必须出现哪些区块 +- **路径验收**:用户完成后会去哪里 +- **数据验收**:哪些状态 / 字段必须持久化或回填 + +--- + +## 3. 页面一:首页(P0 / 重做) + +### 3.1 当前问题 + +当前首页更接近: + +- 落地 / 转化入口 +- 价格 / 服务说明承接页 + +但缺: + +- 高考阶段感 +- 当前下一步任务感 +- 审核优先主线 +- 长期陪伴感 + +### 3.2 目标态 + +首页升级为: + +> **高考志愿工作台 / 志愿任务首页** + +用户进入首页后,应快速看懂: + +1. 我现在处于哪个阶段 +2. 我下一步要做什么 +3. 这个产品默认先帮我做“志愿审核” +4. 如果审核后需要更深入,再进入完整规划 + +### 3.3 页面结构 + +#### 区块 A:阶段 Banner + +- 高考阶段文案(考前 / 查分 / 正式填报 / 录取查询) +- 时间线 / 志愿日历入口 +- 当前阶段高亮 + +#### 区块 B:任务清单(核心) + +默认第一任务必须是: + +- **先审核现有志愿方案 / 现有想法** + +后续任务可包括: + +- 完善高考个人档案 +- 预选冲稳保 +- 查看同分段参考 +- 查看本省政策 +- 生成志愿报告 + +#### 区块 C:快捷入口 + +- 方案审核(默认主入口) +- 冲稳保 +- 志愿报告 +- 查大学 / 专业 + +#### 区块 D:资产区 + +- 我的志愿报告 +- 我的志愿表 +- 最近一次审核结果 + +### 3.4 主文案要求 + +首页首屏必须突出: + +- “先审核,再规划” +- “先看风险,再决定是否重做” +- “帮助你发现踩线 / 扎堆 / 梯度失衡风险” + +建议 CTA: + +- 主 CTA:`先审核现有志愿方案` +- 次 CTA:`完善个人档案` +- 弱 CTA:`查看同分段参考` + +### 3.5 必备状态 + +- 默认态 +- 未建档但可先审核 +- 已有最近审核结果 +- 空状态(无报告 / 无历史) +- 阶段切换态(例如查分后) + +### 3.6 验收重点 + +#### 结构验收 + +- 首页首屏必须有 Banner、任务清单、主 CTA、次 CTA、最近审核结果 / 报告入口 + +#### 路径验收 + +- 主 CTA 直接进入审核页 +- 未建档用户不被强制跳去档案页 + +#### 数据验收 + +- 若存在最近审核结果,首页可读取并展示摘要入口 + +--- + +## 4. 页面二:方案审核页(P0 / 新主入口) + +### 4.1 页面角色 + +这是整个产品的**默认主入口页**。 + +目标用户: + +- 已经有一版志愿表 / 想法 +- 已经被大厂 AI 给过建议 +- 不确定当前方案是否安全 + +### 4.2 页面目标 + +用户在这里应该完成: + +1. 输入 / 粘贴 / 上传现有方案或现有意向 +2. 选择省份、分数 / 位次等最小约束 +3. 获得审核结论: + - 是否踩线 + - 是否扎堆 + - 是否梯度失衡 + - 是否需要补档案或重做完整规划 + +### 4.3 页面结构 + +#### 区块 A:审核入口 + +- 粘贴方案文本 +- 上传截图 / PDF / 文本 +- 或“我还没有完整方案,但有初步想法”输入框 + +#### 区块 B:最小约束信息 + +- 高考省份 +- 科目组合 +- 分数 / 位次 + +#### 区块 C:审核输出摘要 + +- 风险等级 +- 发现的问题数量 +- 最核心 3 个问题 +- 是否建议进入完整规划 + +#### 区块 D:下一步分流 + +- 直接微调冲稳保 +- 去完善个人档案 +- 生成完整志愿报告 + +### 4.4 文案要求 + +必须是: + +- “先看当前方案有什么问题” +- “先判断是否值得重做” + +不能写成: + +- “立即生成全新志愿方案” 作为主口径 + +### 4.5 验收重点 + +#### 结构验收 + +- 页面必须同时有输入区、最小约束区、结果区、分流区 + +#### 路径验收 + +- 审核提交后必须可进入至少一个默认推荐动作 +- 审核结果不能停在孤立提示页 + +#### 数据验收 + +- 审核提交时不要求 Step 2-4 完整档案 +- 审核输入需可被后续结果页、报告页追踪引用 + +--- + +## 5. 页面三:高考个人档案页(P0 先做 Step 1,P1 再扩 Step 2-4) + +### 5.1 页面角色 + +个人档案页不是默认起点,而是: + +- 提升审核和规划精度的中台页面 +- 用户长期资料资产 + +### 5.2 目标态 + +用户应理解: + +- 档案不是为了强迫填写 +- 档案是为了提高审核、冲稳保判断、报告生成质量 + +### 5.3 结构 + +#### P0:Step 1 考生信息(最小必填) + +- 省份 +- 科目组合 +- 分数 +- 位次 + +#### P1:Step 2 院校偏好 + +- 院校地域偏好 +- 院校类型 +- 目标院校 + +#### P1:Step 3 专业偏好 + +- 专业偏好 +- 不接受专业 +- 优先策略 + +#### P1:Step 4 其他偏好 + +- 毕业规划 +- 学费倾向 +- 就业地域偏好 +- 家庭背景 +- 行业资源 +- 补充说明 + +### 5.4 交互原则 + +- P0 先只要求 Step 1 +- 必填与选填明确区分 +- 支持保存草稿 +- 底部固定操作区 +- 第 4 步不要展示 JSON / 代码式摘要,只展示中文语义摘要 + +### 5.5 页面文案要求 + +- “补充这些信息,可以让审核与推荐更精准” +- “即使没填完整,也可以先做审核” + +### 5.6 验收重点 + +#### 结构验收 + +- P0 页面可独立完成 Step 1 保存 + +#### 路径验收 + +- 审核页可跳入档案页补充,补完后可回到审核 / 报告链路 + +#### 数据验收 + +- Step 1 保存后可回填到审核页和报告页 +- Step 2-4 不得成为审核提交门槛 + +--- + +## 6. 页面四:冲稳保页(P1 / 强化) + +### 6.1 页面角色 + +冲稳保页是: + +- 方案审核之后的决策页 +- 报告页的可操作视图 +- 用户理解风险梯度的主界面 + +### 6.2 页面目标 + +让用户清楚看到: + +- 哪些志愿可冲 +- 哪些较稳 +- 哪些可保底 +- 是否存在梯度失衡 / 扎堆风险 + +### 6.3 页面结构 + +- 顶部:当前档案 / 方案摘要 +- 中部:冲 / 稳 / 保三栏或三段切换 +- 每条志愿显示: + - 学校 + - 专业 + - 风险提示 + - 替代建议 +- 底部:是否进入完整规划 / 生成报告 + +### 6.4 验收重点 + +#### 结构验收 + +- 冲 / 稳 / 保必须是一级切换或一级分栏,不只是标签 + +#### 路径验收 + +- 审核结果页可直接进入冲稳保页 + +#### 数据验收 + +- 页面能读取当前审核 / 方案摘要,显示风险解释 + +--- + +## 7. 页面五:志愿报告页(P1 / 重组) + +### 7.1 页面角色 + +报告页不是单次输出文件,而应是: + +- 审核结果沉淀页 +- 决策总结页 +- 可反复查看的资产页 + +### 7.2 页面目标 + +用户打开报告页时,应一眼看懂: + +- 当前版本基于什么信息 +- 本次审核 / 规划最核心结论是什么 +- 冲稳保如何分布 +- 下一步要做什么 + +### 7.3 页面结构 + +- 报告头部:版本、时间、基于哪个档案 +- 第一屏:结论摘要 +- 第二屏:风险清单 +- 第三屏:冲稳保 +- 第四屏:同分段参考(P1 可选挂载) +- 第五屏:政策提醒(P1 可选挂载) +- 第六屏:下一步建议 + +### 7.4 文案要求 + +优先强调: + +- 风险解释 +- 为什么建议这样调 +- 审核结论如何影响后续决策 + +避免: + +- 报告像一次性大段文本堆砌 +- 没有下一步动作指引 + +### 7.5 验收重点 + +#### 结构验收 + +- 报告页必须显式展示版本、结论、风险、下一步 + +#### 路径验收 + +- 报告页可回到冲稳保或档案补充 + +#### 数据验收 + +- 页面必须展示“基于哪个档案版本”或等价语义 + +--- + +## 8. 页面六:政策中心(P1 / 新增) + +### 8.1 页面角色 + +政策中心是: + +- 高信任入口 +- 填报前的解释页 +- 审核 / 冲稳保的规则背景页 + +### 8.2 目标态 + +按省份提供: + +- 时间节点 +- 批次规则 +- 选科要求 +- 常见误区 +- 官方政策摘要 + +### 8.3 页面结构 + +- 顶部省份切换 +- 当前阶段重点政策卡片 +- 常见误区列表 +- 官方来源链接 +- 更新时间与适用范围说明 + +### 8.4 验收重点 + +#### 结构验收 + +- 页面必须显示来源、更新时间、适用省份 + +#### 路径验收 + +- 可从首页、报告页、冲稳保页进入 + +#### 数据验收 + +- 未覆盖或未确认内容必须显式标注,不能默认完整 +- 统一信任条必须展示来源、更新时间、适用范围、适用省份 + +--- + +## 9. 页面七:同分段参考页(P1 / 新增) + +### 9.1 页面角色 + +这是高频参考页,不是最终结论页。 + +### 9.2 页面目标 + +让用户快速看到: + +- 同分段热门学校 +- 同分段热门专业 +- 同分段热门城市 +- 哪些地方容易扎堆 + +### 9.3 页面结构 + +- 分数段说明 +- 学校榜单 +- 专业榜单 +- 城市偏好榜单 +- 扎堆提示与解释 +- 数据说明 / 置信等级说明 + +### 9.4 验收重点 + +#### 结构验收 + +- 页面必须有数据说明与置信等级说明 + +#### 路径验收 + +- 页面作为辅助页,不替代审核主路径 + +#### 数据验收 + +- 非高置信数据不得使用强推荐文案 +- 同分段参考与政策中心共用统一信任条,显式标注文案边界 + +--- + +## 9.5 当前实现补充(2026-06-23) + +- 同分段页已提供学校 / 专业 / 城市 / 扎堆风险 +- 政策中心与同分段页已互相可达 +- 报告页与冲稳保页已提供政策中心 / 同分段参考入口 + +--- + +## 10. 页面之间的主路径 + +默认主路径: + +1. 首页 +2. 方案审核页 +3. (可选)个人档案页补充信息 +4. 冲稳保页 +5. 报告页 +6. 政策中心 / 同分段参考辅助 +7. 最终形成填报决策 + +这条主路径必须始终保持: + +> **审核优先,而不是默认先建档生成新方案。** + +硬约束: + +- 审核页不得要求完整档案 +- Step 2-4 偏好只作为审核与规划增益 +- 政策中心 / 同分段参考只作辅助判断 + +--- + +## 11. 验收口径 + +页面级改版完成后,应满足: + +1. 首页主入口明确是“审核优先” +2. 用户不需要完整建档也能先开始服务 +3. Step 1 建档可保存、可回填、可复用 +4. 审核结果可分流到后续动作 +5. 冲稳保成为真正的一等能力 +6. 报告页成为资产页而非一次性输出 +7. 政策中心和同分段参考具备明确来源与可信度边界 + +--- + +## 12. 后续衔接文档 + +基于本清单,建议下一步继续产出: + +1. `字段映射表(现有 Portal 字段 -> 新档案体系)` +2. `P0/P1/P2 产品升级执行板` +3. `具体页面原型说明 / 设计稿说明` diff --git a/docs/REPORT_PROFILE_VERSION_RELATION_2026-06-22.md b/docs/REPORT_PROFILE_VERSION_RELATION_2026-06-22.md new file mode 100644 index 0000000..1fa28f3 --- /dev/null +++ b/docs/REPORT_PROFILE_VERSION_RELATION_2026-06-22.md @@ -0,0 +1,350 @@ +# REPORT_PROFILE_VERSION_RELATION_2026-06-22 + +最后更新: 2026-06-22 +状态词: 报告版本与档案版本关系说明 +真相源: +- `product/PRD_UPGRADE_2026-06-21.md` +- `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` +- `docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md` + +> 本文只钉住版本语义与最小关系,避免后续在“档案版本 / 审核结果版本 / 报告版本”上各写各的。 + +--- + +## 1. 为什么现在就要定义版本关系 + +当前项目已经有: + +- 订单 +- Portal intake +- 报告交付 +- 状态页 / 报告页 + +但升级规划已经引入三个新语义: + +- `profile_version` +- `review_result_version` +- `report_version` + +如果现在不钉住,后续很容易出现三种漂移: + +1. 前端把“最近一次查看”当版本 +2. 后端把“每次导出 PDF”当版本 +3. 产品把“档案更新后重新解读”与“报告重新生成”混成同一件事 + +所以本文只做一件事: + +> 定义版本对象是什么、何时递增、彼此怎么关联。 + +--- + +## 2. 三个版本对象的定义 + +## 2.1 `profile_version` + +定义: + +- 每次用户保存一份可用于后续审核 / 规划的档案快照时,形成一个新的 `profile_version` + +它代表的是: + +- 当时的考生信息与偏好信息快照 + +它**不是**: + +- 当前页面打开次数 +- 表单每次按键修改 +- 单字段临时草稿变化 + +### 最小包含内容 + +P0 / P1 至少覆盖: + +- `candidate_province` +- `candidate_subjects` +- `candidate_score` +- `candidate_rank` +- P1 后续再加入 Step 2-4 偏好字段 + +### 递增规则 + +- 只有“保存档案快照成功”才递增 +- 草稿未形成有效快照时,不递增 + +--- + +## 2.2 `review_result_version` + +定义: + +- 每次用户基于某组输入发起审核,并产出一份审核结果快照时,形成一个新的 `review_result_version` + +它代表的是: + +- 某次审核的输入与输出结论快照 + +它**不是**: + +- 用户打开审核页 +- 用户修改但未提交审核 +- 结果页单纯重新渲染 + +### 最小包含内容 + +至少包括: + +- 审核输入摘要 +- 审核使用的最小约束 +- 风险等级 +- 核心发现 +- 推荐后续动作 + +### 递增规则 + +- 只有“审核提交成功并产出结果”才递增 +- 单纯重看历史结果,不递增 + +--- + +## 2.3 `report_version` + +定义: + +- 每次正式生成一份可交付 / 可查看的报告快照时,形成一个新的 `report_version` + +它代表的是: + +- 对外可查看、可下载、可沉淀的报告资产版本 + +它**不是**: + +- PDF 重新下载一次 +- 前端重新打开报告页 +- 分享链接被访问一次 + +### 最小包含内容 + +至少包括: + +- 报告结论摘要 +- 风险说明 +- 冲稳保结构 +- 下一步建议 +- 生成时使用的档案版本引用 +- 生成时使用的审核结果版本引用(如存在) + +### 递增规则 + +- 只有“正式生成新报告快照”才递增 +- 同一份报告重复下载 / 查看,不递增 + +--- + +## 3. 三者之间的最小关系 + +## 3.1 核心关系 + +最小关系如下: + +- `review_result_version` 产生时,**引用一个输入快照** +- `report_version` 产生时,**引用一个 `profile_version`** +- `report_version` 如基于某次审核生成,**可再引用一个 `review_result_version`** + +也就是: + +- 档案版本描述“你当时提供了什么信息” +- 审核结果版本描述“系统当时怎么判断” +- 报告版本描述“最终交付给用户的是什么” + +--- + +## 3.2 推荐最小引用关系 + +### `review_result_version` + +建议最小关联: + +- `profile_version`:可选 +- `review_input_snapshot`:必有 + +因为 P0 允许用户先审核再补档案,所以: + +- 审核结果未必总是基于完整档案版本 +- 但必须至少绑定当次审核输入快照 + +### `report_version` + +建议最小关联: + +- `profile_version`:必有 +- `review_result_version`:可选但推荐有 + +原因: + +- 报告是资产化对象,必须知道基于哪一版档案生成 +- 如果报告是由某次审核深化而来,再关联那次审核结果更清楚 + +--- + +## 4. “是否基于最新档案生成”的判定规则 + +这是最容易说乱的一条。必须固定。 + +### 规则 + +当且仅当: + +- `report.profile_version == latest_profile_version` + +才可表述为: + +- “该报告基于最新档案生成” + +否则只能表述为: + +- “该报告基于历史档案版本生成,建议刷新” + +### 注意 + +不能用下面这些替代: + +- 报告最近浏览时间 +- 报告 PDF 最近下载时间 +- 用户最后一次打开档案页时间 + +这些都不是版本判定。 + +--- + +## 5. P0 / P1 / P2 各阶段对版本的要求 + +## 5.1 P0 + +P0 不要求完整版本体系落库,但必须: + +1. 在文档与接口语义上定义三个版本对象 +2. 审核结果至少能绑定审核输入快照 +3. Step 1 保存与报告回填之间留出 `profile_version` 语义位置 + +P0 重点是: + +- **先定义语义,不强制一步到位做重表设计** + +## 5.2 P1 + +P1 开始要求: + +1. 报告页外显版本、时间、基于哪个档案 +2. 能判断报告是否基于最新档案生成 +3. 冲稳保和报告重组不打乱版本含义 + +## 5.3 P2 + +P2 才要求: + +1. 多版本方案管理 +2. 更完整的方案版本与报告版本关系 +3. 不同阶段方案(初始 / 查分后 / 正式填报前)的并行管理 + +--- + +## 6. 推荐最小数据结构语义 + +这里先定义语义,不限定物理表。 + +### 6.1 ProfileVersion + +最小字段语义: + +- `profile_version_id` +- `order_id` +- `snapshot_payload` +- `created_at` +- `source`(portal / admin / import 等) + +### 6.2 ReviewResultVersion + +最小字段语义: + +- `review_result_version_id` +- `order_id` +- `profile_version_id`(可空) +- `review_input_snapshot` +- `review_output_snapshot` +- `created_at` + +### 6.3 ReportVersion + +最小字段语义: + +- `report_version_id` +- `order_id` +- `profile_version_id` +- `review_result_version_id`(可空) +- `report_snapshot` +- `artifact_refs` +- `created_at` + +--- + +## 7. 当前实现下的落地建议 + +基于现有代码现状: + +- 当前已有 `order_intakes.payload_json` +- 当前已有 `audit_report` / `pdf_path` +- 当前已有 Portal 状态页与报告页 + +建议: + +### 7.1 P0 + +- 不立即改重 schema +- 先在文档、接口、页面语义上保留版本字段位置 + +- 报告生成链补 `profile_version` 引用 +- 报告页展示“基于哪个档案版本” +- 如果有审核结果对象,再补 `review_result_version` 关联 +- 当前实现(2026-06-23)已采用 `order_intakes.payload_json` 轻量保存: + - `profile_versions[]` / `latest_profile_version_id` + - `review_results{}` / `latest_review_result_id` + - `report_versions[]` / `latest_report_version_id` +- “是否基于最新档案生成” 已按 `report.profile_version == latest_profile_version` 在报告页外显 + +### 7.3 P2 + +- 多版本方案页先复用 `profile_versions` 阶段标签(初始 / 查分后 / 正式填报前) +- 独立重表设计仍可后置 + + +--- + +## 8. 禁止的错误实现 + +禁止: + +1. 把 PDF 文件名变化当作新 `report_version` +2. 把页面重新打开当作新 `review_result_version` +3. 把草稿自动保存每次都当作新 `profile_version` +4. 让“最新浏览时间”替代“最新档案版本” +5. 让多版本方案先于版本语义定义落地 + +--- + +## 9. 最小结论 + +可以把三者压缩成一句话: + +- `profile_version` = 用户给了什么信息 +- `review_result_version` = 系统当时怎么判断 +- `report_version` = 最终交付给用户什么结果 + +只要这三个定义不乱,后面的报告资产化、多版本方案、审核结果回放才不会互相打架。 + +--- + +## 10. 下一步建议 + +1. 在接口清单里给 `profile_version` / `review_result_version` / `report_version` 预留字段位 +2. 在 P1 报告页实现时,把“基于哪个档案版本”做成显式外显项 +3. 在进入多版本方案管理前,先确认版本对象的最小持久化方案 diff --git a/docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md b/docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md new file mode 100644 index 0000000..ff1f888 --- /dev/null +++ b/docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md @@ -0,0 +1,450 @@ +# UPGRADE_EXECUTION_BOARD_2026-06-22 + +最后更新: 2026-06-22 +状态词: 用户侧升级规划执行板 +真相源: `product/PRD_UPGRADE_2026-06-21.md` +配套文档: +- `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` +- `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` +- `docs/CURRENT_STATE.md` +- `docs/ACTIVE_EXECUTION_BOARD_2026-06-20.md` + +> 本文件定义的是用户侧升级执行顺序与交付切线,不替代当前生产 readiness 执行板。 + +--- + +## 1. 当前执行结论 + +结论: + +- 用户侧升级路线已明确收敛为“**审核优先 + Step 1 最小建档 + 审核结果分流 + 后续决策增强**” +- 本轮 P0 只负责让默认主线成立,不追求一次性完成完整档案、完整内容中心或完整资产化 +- 当前生产 readiness 问题仍由 `docs/ACTIVE_EXECUTION_BOARD_2026-06-20.md` 管理;本执行板不覆盖真实支付 acceptance、自动交付主链、正式法务审定、异机恢复等门禁任务 + +本执行板的唯一目标是: + +> 在不夸大现有能力、不混入生产门禁问题的前提下,把用户侧升级拆成可执行、可验收、可逐步落地的 P0 / P1 / P2 任务板。 + +--- + +## 2. 全局执行原则 + +### 2.1 默认主线原则 + +统一主线: + +1. 首页 +2. 先审核现有志愿方案 / 现有想法 +3. 根据审核结果决定: + - 进入冲稳保微调 + - 补充 Step 1 或后续档案 + - 进入完整规划 / 报告 +4. 最终结合政策中心与同分段参考完成决策 + +禁止滑回: + +- 先完整建档再开始服务 +- 默认直接生成全新志愿方案 +- 让 Step 2-4 偏好字段阻塞审核入口 + +### 2.2 分期原则 + +#### P0:先让审核优先主线成立 + +必须交付: + +- 首页任务化 + 审核主 CTA 前置 +- 审核页最小闭环 +- Step 1 最小建档 +- 审核结果分流 + +#### P1:再做决策与内容增强 + +增强交付: + +- 冲稳保一级化 +- Step 2-4 偏好建档 +- 报告重组与资产外显 +- 政策中心 +- 同分段参考 +- 内容可信度展示规则 + +#### P2:最后做深层增强 + +增强交付: + +- 深层偏好增强 +- 性格 / 兴趣测评联动 +- 多版本方案管理 + +### 2.3 口径边界原则 + +禁止表述: + +- “已完成完整 Web 自助 SaaS” +- “已完成全国统一高置信同分段参考 / 政策中心” +- “审核优先升级已替代生产 readiness 收口” +- “报告资产化已包含完整版本体系” + +允许表述: + +- “P0 审核优先主线已成立” +- “P1 冲稳保 / 政策 / 同分段参考处于增强阶段” +- “当前升级板与生产 readiness 执行板并行,各自管理不同问题域” + +--- + +## 3. P0 执行板(当前最优先) + +### P0-1 首页任务化 + 审核主 CTA 前置 + +- Owner: product / design / frontend +- 优先级: P0 +- 状态: completed(2026-06-23 第三轮质量收敛完成;首页主 CTA / 工作台主动作 / 最近复核入口已本地验证) +- 目标: + - 首页从落地 / 下单入口切为高考志愿工作台 + - 主 CTA 固定为“先审核现有志愿方案” + - 用户进入首页后可快速理解当前阶段、下一步动作、审核优先主线 +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §7.1 / §8.1 + - `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` §3 +- 交付物: + - 首页结构说明 + - 首页组件清单 + - 首页主 / 次 / 弱 CTA 文案 +- 验收: + - 首屏必须有 Banner、任务清单、主 CTA、次 CTA、最近审核结果 / 报告入口 + - 未建档用户可直接进入审核页 + - 首页不得把完整规划 / 生成方案作为默认第一主动作 + +### P0-2 审核页最小闭环 + +- Owner: product / backend / frontend +- 优先级: P0 +- 状态: completed(2026-06-23 第三轮质量收敛完成;审核页已补齐输入区 / 最小约束区 / 结果区 / 分流区) +- 目标: + - 审核页支持输入现有方案 / 现有想法 + - 审核页只要求最小约束信息:省份、科目组合、分数 / 位次 + - 审核后输出风险摘要与下一步建议 +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §8.1 F-P0-2 + - `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` §4 + - `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` §5 +- 数据依赖: + - `existing_plan_summary` + - `candidate_province` + - `candidate_subjects` + - `candidate_score` + - `candidate_rank` +- 交付物: + - 审核输入结构定义 + - 审核页状态机 + - 审核输出摘要结构 +- 验收: + - 审核提交时不要求 Step 2-4 完整档案 + - 页面必须有输入区、最小约束区、结果区、分流区 + - 审核结果不能停在孤立结果页 + +### P0-3 Step 1 最小建档 + +- Owner: product / backend / frontend +- 优先级: P0 +- 状态: completed(2026-06-23 第三轮质量收敛完成;Step 1 四字段保存 / 回填 / 最小完成态已本地验证) +- 目标: + - 只落 Step 1:省份、科目组合、分数、位次 + - 支持保存草稿、回填、复用 + - 明确“未填完整档案也可先审核” +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §7.2 / §8.1 F-P0-3 + - `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` §5 + - `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` §3 / §5 +- 数据依赖: + - `profile_minimum_complete` + - Step 1 四字段回填语义 +- 交付物: + - Step 1 表单定义 + - Step 1 保存 / 回填规则 + - 最小完成状态定义 +- 验收: + - Step 1 可独立保存 + - 保存后可在审核页和报告页复用 + - Step 2-4 未完成不影响审核提交 + +### P0-4 审核结果分流 + +- Owner: product / frontend / analytics +- 优先级: P0 +- 状态: completed(2026-06-23 第三轮质量收敛完成;三条分流路径与 followup action 已可记录 / 回放) +- 目标: + - 审核结果页显式导向三类动作:冲稳保、补档案、完整规划 / 报告 + - 三类动作均可追踪 +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §8.1 F-P0-4 + - `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` §4 / §10 + - `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` §5.3 +- 数据依赖: + - `review_entry_source` + - `review_followup_action` +- 交付物: + - 审核结果页结构 + - 分流动作枚举 + - 埋点字段定义 +- 验收: + - 至少有一个默认推荐动作 + - 三条分流路径都可实际进入对应页面 + - 分流动作可被状态或埋点记录 + +### P0-5 P0 验收门槛 + +- Owner: product / tech-lead +- 优先级: P0 +- 状态: completed(2026-06-23 本地验证) +- 验收结论成立条件: + 1. 首页默认主入口已切为审核 + 2. 审核入口可在未完整建档状态下工作 + 3. Step 1 可保存并回填 + 4. 审核结果可进入至少一条后续动作,且三条路径均存在 + 5. 对外口径未误写为“完整 SaaS 已完成” + 6. 验证: `./.venv/bin/python -m pytest -q admin/tests/test_web_public.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_portal_info.py admin/tests/test_web_public_review_flow.py data/orders/tests/test_schema.py` → `70 passed` + +--- + +## 4. P1 执行板(P0 稳定后推进) + +### P1-1 冲稳保一级化 + +- Owner: product / design / frontend +- 优先级: P1 +- 状态: completed(2026-06-23;审核后可直接进入冲稳保视图,冲 / 稳 / 保已作为一级分栏呈现) +- 目标: + - 把冲稳保从报告标签升级为一级入口与一级决策框架 +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §8.2 F-P1-1 + - `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` §6 +- 验收: + - 冲 / 稳 / 保必须是一级切换或一级分栏 + - 审核结果页可直接进入冲稳保视图 + +### P1-2 Step 2-4 偏好建档 + +- Owner: product / backend / frontend +- 优先级: P1 +- 状态: completed(2026-06-23;Step 2-4 字段命名与映射表一致,且不阻塞审核入口) +- 目标: + - 落院校偏好、专业偏好、其他偏好三层建档 + - 统一字段命名、字段归属、文案语义 +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §7.2 / §8.2 F-P1-2 + - `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` §6 / §7 / §10 +- 验收: + - 新字段命名与映射表一致 + - Step 2-4 不阻塞审核入口 + +### P1-3 报告重组与资产外显 + +- Owner: product / backend / frontend +- 优先级: P1 +- 状态: completed(2026-06-23;报告页已外显版本 / 最新性 / 下一步动作,并写入轻量 report_versions) +- 目标: + - 报告页重组为结论摘要、风险、冲稳保、下一步动作的资产页 + - 显式外显版本、时间、基于哪个档案 +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §7.3 / §8.2 F-P1-5 / §10.4 + - `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` §7 +- 数据依赖: + - `profile_version` + - `review_result_version` + - `report_version` +- 验收: + - 报告页必须展示版本与下一步动作 + - 用户可判断报告是否基于最新档案生成 + +### P1-4 政策中心 + +- Owner: product / content / frontend +- 优先级: P1 +- 状态: completed(2026-06-23;政策中心已展示来源 / 更新时间 / 适用省份,并提供辅助入口) +- 目标: + - 按省提供政策摘要、时间节点、批次规则、选科要求、误区说明 +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §8.2 F-P1-4 / F-P1-6 + - `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` §8 +- 验收: + - 页面必须展示来源、更新时间、适用省份 + - 未覆盖内容必须显式标注 + +### P1-5 同分段参考 + +- Owner: product / data / frontend +- 优先级: P1 +- 状态: completed(2026-06-23;同分段参考已展示学校 / 专业 / 城市 / 扎堆提示与置信边界) +- 目标: + - 提供同分段学校 / 专业 / 城市参考与扎堆提示 +- 输入依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §8.2 F-P1-3 / F-P1-6 + - `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` §9 + - `docs/ACTIVE_EXECUTION_BOARD_2026-06-20.md` Q-A 数据边界 +- 验收: + - 页面必须展示数据说明与置信等级说明 + - 非高置信数据不得使用强推荐口吻 + +### P1-6 内容可信度规则落地 + +- Owner: product / content / legal-review +- 优先级: P1 +- 状态: completed(2026-06-23;政策中心 / 同分段参考已共用统一信任条并保留非高置信边界) +- 目标: + - 把政策中心 / 同分段参考的来源、更新时间、适用范围、置信等级规则写成统一组件与文案规范 +- 依赖: + - `product/PRD_UPGRADE_2026-06-21.md` §8.2 F-P1-6 +- 验收: + - 页面级文案不再出现“全国统一高置信完整能力”误导表达 + +### P1-7 P1 验收门槛 + +- Owner: product / tech-lead +- 优先级: P1 +- 状态: completed(2026-06-23 本地验证) +- 验收结论成立条件: + 1. 冲稳保成为一级能力 + 2. Step 2-4 字段与映射表一致 + 3. 报告页完成资产化基础外显 + 4. 政策中心 / 同分段参考具备清晰可信度边界 + 5. 未对外夸大 27 省能力与政策完整性 + 6. 验证: `./.venv/bin/python -m pytest -q admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_portal_info.py admin/tests/test_web_public_review_flow.py data/orders/tests/test_schema.py` → `60 passed` + +--- + +## 5. P2 执行板(增强层) + +### P2-1 深层偏好增强 + +- Owner: product / backend / frontend +- 优先级: P2 +- 状态: completed(2026-06-23;family_background / industry_resources / employment_region_preferences / graduation_plan 已稳定落在 intake) +- 目标: + - 增强家庭背景、行业资源、就业地域偏好、毕业规划等深层字段 +- 依赖: + - P1 字段语义稳定 +- 验收: + - 字段用途明确 + - 默认非强制 + - 不制造隐私压迫感 + +### P2-2 性格 / 兴趣测评联动 + +- Owner: product / algorithm / frontend +- 优先级: P2 +- 状态: completed(2026-06-23;MBTI / 霍兰德等结果已进入辅助判断因子区块,且文案锁定“只作辅助”) +- 目标: + - 将 MBTI / 霍兰德等结果作为辅助因子接入 +- 依赖: + - P1 路径稳定 +- 验收: + - 测评结果只作辅助,不作唯一判断 + +### P2-3 多版本方案管理 + +- Owner: backend / frontend / product +- 优先级: P2 +- 状态: completed(2026-06-23;profile_versions / report_versions 已支持初始 / 查分后 / 正式填报前阶段区分) +- 目标: + - 支持初始档案方案、查分后校准方案、正式填报前调整方案管理 +- 依赖: + - `profile_version` / `review_result_version` / `report_version` 语义已稳定 +- 验收: + - 用户能区分不同阶段的方案版本 + - 版本关系不与报告版本语义冲突 + +### P2-4 P2 验收门槛 + +- Owner: product / tech-lead +- 优先级: P2 +- 状态: completed(2026-06-23 本地验证) +- 验收结论成立条件: + 1. 深层偏好字段已稳定 + 2. 测评联动不破坏主路径 + 3. 多版本方案不与报告 / 档案版本语义冲突 + 4. 验证: `./.venv/bin/python -m pytest -q admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_portal_info.py admin/tests/test_web_public_review_flow.py data/orders/tests/test_schema.py` → `60 passed` + +--- + +## 6. 与生产 readiness 执行板的边界 + +本执行板**不覆盖**以下事项: + +- T12-A 真实支付 acceptance +- T12-B `info_submitted -> serving` 自动主链 +- T12-D retention cleanup 生产化部署验收 +- L-A 正式法务审定 +- L-B 异机备份恢复演练 +- Q-A 非湖南省份高置信数据密度深化 + +这些任务继续由: + +- `docs/ACTIVE_EXECUTION_BOARD_2026-06-20.md` + +负责管理。 + +本执行板与生产 readiness 执行板的关系是: + +- 生产 readiness 板管“现有系统上线门禁与真实能力收口” +- 升级执行板管“用户侧体验升级顺序与验收切线” + +两者并行,但**不能混写、不能互相替代**。 + +--- + +## 7. 当前推荐执行顺序 + +### 第一阶段 + +1. P0-1 首页任务化 + 审核主 CTA 前置 +2. P0-2 审核页最小闭环 +3. P0-3 Step 1 最小建档 +4. P0-4 审核结果分流 +5. P0-5 P0 验收门槛核定 + +### 第二阶段 + +6. P1-1 冲稳保一级化 +7. P1-2 Step 2-4 偏好建档 +8. P1-3 报告重组与资产外显 +9. P1-4 政策中心 +10. P1-5 同分段参考 +11. P1-6 内容可信度规则落地 +12. P1-7 P1 验收门槛核定 + +### 第三阶段 + +13. P2-1 深层偏好增强 +14. P2-2 性格 / 兴趣测评联动 +15. P2-3 多版本方案管理 +16. P2-4 P2 验收门槛核定 + +--- + +## 8. 当前推荐读取顺序 + +1. `product/PRD_UPGRADE_2026-06-21.md` +2. `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` +3. `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` +4. `docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md`(本文件) +5. `docs/CURRENT_STATE.md` +6. `docs/ACTIVE_EXECUTION_BOARD_2026-06-20.md` + +--- + +## 9. 下一步执行建议 + +最优先: + +1. 先把 P0-1 ~ P0-4 各自拆成页面 / 接口 / 状态 / 埋点四类子任务 +2. 输出最小接口变更清单,确认 Step 1、审核输入、审核结果分流的数据承接方式 +3. 在 P0 验收通过前,不提前拉长到完整政策中心、完整同分段参考或多版本方案管理 + +原因: + +- 当前最大风险不是缺想法,而是范围失控 +- P0 的唯一目标是让“审核优先”真正成立 +- 只有 P0 成立后,P1 的冲稳保 / 内容中心 / 资产化才有稳定承接面 diff --git a/docs/plans/2026-06-23-full-upgrade-optimization-plan.md b/docs/plans/2026-06-23-full-upgrade-optimization-plan.md new file mode 100644 index 0000000..d95c8ae --- /dev/null +++ b/docs/plans/2026-06-23-full-upgrade-optimization-plan.md @@ -0,0 +1,145 @@ +# Full Upgrade Optimization Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Finish the remaining P1/P2 user-facing upgrade work so the audit-first web flow has first-class 冲稳保 / 报告资产化 / 政策与同分段辅助 / 轻量版本管理. + +**Architecture:** Reuse the existing `admin/routes/web_public.py` flow rather than introducing new subsystems. Persist new version/history metadata in `order_intakes.payload_json` beside the existing `review_results` map, keep `orders` as the current-live snapshot + artifact pointers, and upgrade existing user pages/routes in place. + +**Tech Stack:** FastAPI route functions, inline HTML renderers in `admin/routes/web_public.py`, `data/orders/intake_store.py`, Pydantic `IntakePayload`, pytest route tests. + +--- + +### Task 1: Lock failing regression tests for remaining P1/P2 gaps + +**Files:** +- Modify: `admin/tests/test_web_public_review_flow.py` +- Modify: `admin/tests/test_web_public_content_pages.py` +- Modify: `admin/tests/test_web_public_portal_info.py` +- Modify: `data/orders/tests/test_schema.py` + +**Step 1: Write failing tests** +- Report page should show whether current report is based on latest profile version. +- CWB/report pages should expose policy center / same-score helper entry points. +- Portal info page should render/save `target_cities` and any new version anchor output. +- Schema tests should lock new lightweight profile/report version metadata helpers or payload contracts. + +**Step 2: Run the narrow test subset to confirm red** +Run: +`./.venv/bin/python -m pytest -q admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_portal_info.py data/orders/tests/test_schema.py -k 'version or policy or score or target_cities or assessment or cwb'` + +**Step 3: Implement only enough to make these pass** + +**Step 4: Re-run the same subset** + +--- + +### Task 2: Add lightweight profile/report version metadata without schema churn + +**Files:** +- Modify: `admin/routes/web_public.py` +- Possibly modify: `data/orders/intake_schema.py` +- Test: `admin/tests/test_web_public_review_flow.py` +- Test: `admin/tests/test_web_public_portal_info.py` +- Test: `data/orders/tests/test_schema.py` + +**Step 1: Add helper functions in `web_public.py`** +- Normalize profile snapshots from intake payload. +- Append profile version only when a saved snapshot meaningfully changes. +- Keep `latest_profile_version_id` and `profile_versions[]` in `order_intakes.payload_json`. +- Add idempotent report metadata sync for existing generated report artifacts: `latest_report_version_id` + `report_versions[]`. + +**Step 2: Wire profile snapshot save into `submit_order_info`** +- After `IntakeStore.save`, update the saved payload with profile version metadata. +- Do not create a new version for identical snapshots. + +**Step 3: Wire report metadata sync into report rendering** +- Reuse current derived `report_version` label as the metadata id. +- Reference latest profile version + latest review result id when available. +- Never create duplicate report versions on repeated page opens. + +**Step 4: Surface latest-vs-history semantics in report page** +- Explicitly show whether the current report is based on latest profile. +- Show historical/stale warning when latest profile has moved on. + +--- + +### Task 3: Finish P1 page upgrades in existing routes + +**Files:** +- Modify: `admin/routes/web_public.py` +- Test: `admin/tests/test_web_public_review_flow.py` +- Test: `admin/tests/test_web_public_content_pages.py` +- Test: `admin/tests/test_order_status_page.py` + +**Step 1: Upgrade CWB page in place** +- Keep `/portal/{token}/cwb`. +- Replace placeholder tone with first-class workspace sections: summary, 3-column C/W/B board, next actions, policy/same-score helper links. + +**Step 2: Upgrade report shell in place** +- Keep `_render_report_shell` as the only outer shell. +- Add sections for version header, conclusion summary, risk summary, CWB action zone, policy/same-score helper links, next actions. +- Preserve original report body as a raw section instead of dropping it. + +**Step 3: Add helper navigation to policy and same-score pages** +- Ensure entry can be discovered from report/CWB/status/home where required. +- Keep trust-boundary copy explicit. + +**Step 4: Extract or centralize trust banner rendering** +- Source, update time, scope, confidence, and non-high-confidence constraints should come from one helper, reused by policy/same-score pages. + +--- + +### Task 4: Close Step 2-4 / P2 UI and auxiliary factors + +**Files:** +- Modify: `admin/routes/web_public.py` +- Test: `admin/tests/test_web_public_portal_info.py` +- Test: `admin/tests/test_web_public_review_flow.py` + +**Step 1: Add missing Step 2 UI field** +- Render `target_cities` in the portal info page so current schema/persistence and UI are aligned. + +**Step 2: Surface deep preference / assessment data as auxiliary context** +- In CWB/report/full-plan views, show optional “辅助判断因子” block when interest-assessment or deep preference data exists. +- Keep wording explicit: auxiliary only, not sole basis. + +**Step 3: Keep all Step 2-4 and P2 fields optional** +- No change may make them gating for audit entry. + +--- + +### Task 5: Update docs and execution truth sources + +**Files:** +- Modify: `CHANGELOG.md` +- Modify: `docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md` +- Modify: `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` +- Modify: `docs/REPORT_PROFILE_VERSION_RELATION_2026-06-22.md` +- Modify: `product/PRD_UPGRADE_2026-06-21.md` +- Conditional: `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` + +**Step 1: Update completion status for truly completed P1/P2 items** +- Only mark complete if code + tests now prove it. + +**Step 2: Sync page acceptance language** +- Report latest-profile rule, policy/same-score trust boundary, target_cities UI, and version metadata location. + +**Step 3: Record the chosen low-churn version storage design** +- `order_intakes.payload_json` as the history home; `orders` as current-live artifact mirror. + +--- + +### Task 6: Run focused regression and final board verification + +**Files:** +- Test only + +**Step 1: Run directly affected suite** +`./.venv/bin/python -m pytest -q admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_portal_info.py admin/tests/test_order_status_page.py data/orders/tests/test_schema.py` + +**Step 2: Expand one ring if green** +`./.venv/bin/python -m pytest -q admin/tests/test_web_public.py admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_portal_info.py admin/tests/test_order_status_page.py data/orders/tests/test_schema.py` + +**Step 3: Verify docs/board status** +- Re-read `docs/UPGRADE_EXECUTION_BOARD_2026-06-22.md` and confirm P1/P2 items no longer pending if implemented. diff --git a/product/PRD_UPGRADE_2026-06-21.md b/product/PRD_UPGRADE_2026-06-21.md new file mode 100644 index 0000000..4301393 --- /dev/null +++ b/product/PRD_UPGRADE_2026-06-21.md @@ -0,0 +1,745 @@ +# 高考志愿服务升级 PRD + +> 基于 `docs/COMPETITOR_SCREEN_ANALYSIS_WENXIN_QIANWEN_2026-06-21.md`、当前 `product/PRD.md`、`product/ROADMAP.md`、`docs/CURRENT_STATE.md`、以及现有 `gaokao-volunteer-system` 代码/Portal 主链现状整理。 + +**版本**: v0.2 +**状态**: Draft / 待复审 +**最后更新**: 2026-06-22 +**适用范围**: `gaokao-volunteer-system` 用户侧高考志愿服务产品升级 + +--- + +## 1. 文档目的 + +本 PRD 用于定义 `gaokao-volunteer-system` 从当前“人工服务运营增强系统 + Web 自助 MVP”升级到“**默认先做志愿审核/复核,再按需进入完整规划**”的任务化陪伴产品方向。 + +目标不是立刻把项目表述成完整 SaaS,而是: + +1. 把当前已存在的订单、资料、状态、报告、合规、审计能力重组为更强的用户产品体验 +2. 将文心与千问截图中可借鉴的成熟交互模式,转化为本项目的可执行升级范围 +3. 为后续设计、前端重构、接口扩展、执行板拆解提供单一真相源 + +本 PRD **只定义用户侧体验升级方向与范围**,不替代当前生产 readiness 执行板。 + +- 支付线上 acceptance、自动交付主链、正式法务审定、异机备份恢复等事项,仍以 `docs/CURRENT_STATE.md` 与 `docs/ACTIVE_EXECUTION_BOARD_2026-06-20.md` 为上线前置门禁 +- 本 PRD 通过,不代表对应功能已开发完成、已上线或已达到可对外承诺状态 + +--- + +## 2. 背景与问题定义 + +### 2.1 当前现状(Current State) + +当前项目已经具备: + +- 人工服务运营增强链路 +- 管理后台、订单、通知、分享、报告交付 +- Portal 资料向导、状态页、支付成功页 +- 删除/匿名化、同意审计、保留期门禁、法务草案、数据治理基础 +- 局部 Web 自助主链:下单 → 支付 → 资料补充 → 状态查看 → 报告交付 + +但用户侧仍存在明显产品化缺口: + +1. 首页仍不够“高考志愿服务产品”,缺少阶段感和任务感 +2. 用户进入后缺少“我现在该做什么”的明确引导 +3. 资料收集虽已有基础,但缺少完整、清晰、可扩展的“个人档案中心”心智 +4. 冲稳保还未升级为核心产品框架 +5. 同分段参考、政策中心、报告资产化尚未形成完整用户价值闭环 +6. 偏好字段体系不够系统,仍偏“最小可用资料收集”而非“可迭代建档” + +### 2.2 外部参考(Competitive Input) + +#### 文心带来的启发 + +- 偏好字段体系完整 +- 移动端弹层、chip、多选结构成熟 +- 冲稳保三色体系可视化明显 +- 空状态转化设计较强 + +#### 千问带来的启发 + +- 首页时间线/志愿日历明显增强长期陪伴感 +- 任务清单把功能转化成行动 +- 最小建档集很克制,只抓 4 个关键字段先启动 +- 结构化入口与自由对话并存 +- 同分段参考与政策中心是强留存点 + +### 2.3 核心判断 + +本项目升级方向不应是: + +- 单纯加更多表单字段 +- 单纯做更好看的落地页 +- 单纯把聊天能力接到首页 +- 被竞品带偏成“默认先生成一份全新志愿方案” + +而应是: + +> 用千问的“时间线 + 任务系统”做产品骨架,用文心的“偏好字段体系 + 移动端表单模式”做推荐深度,但**默认服务主线仍然是:先审核现有志愿方案/现有想法,再决定是否进入完整规划与报告生成**。 + +### 2.4 当前升级前提 + +本轮升级成立的前提不是“新建一个完整用户端 SaaS”,而是: + +- 已有订单、资料、状态、报告、同意审计、删除与留痕能力可复用 +- 已有审核主链、Portal 最小资料链、报告交付链可重组 +- 当前升级以“重组用户入口与产品心智”为主,不要求同步完成真实支付 acceptance 或完整线上自动交付闭环 +- 因此本轮属于“体验层重构 + 最小数据结构增强”,不是新建独立产品线 + +--- + +## 3. 升级目标 + +### 3.1 总目标 + +将 `gaokao-volunteer-system` 从“订单驱动的资料补充与报告交付 MVP”升级为“**审核优先、规划递进、任务化陪伴**”的高考志愿服务产品。 + +### 3.2 分目标 + +#### G1. 首页任务化 + +让用户在首页就能理解: + +- 当前阶段是什么 +- 下一步该做什么 +- 哪些能力可以立刻使用 + +#### G2. 建档分层化 + +把信息收集从“单次填表”升级为: + +- 最小建档启动 +- 分层补充偏好 +- 档案可保存、可回填、可迭代 + +#### G3. 决策结构化 + +围绕“冲稳保”重构: + +- 推荐入口 +- 报告结构 +- 后续方案编辑与查看逻辑 + +#### G4. 参考内容产品化 + +新增用户高频需要但当前未成型的能力: + +- 同分段参考 +- 政策中心 +- 报告资产化 / 我的志愿资产 + +#### G5. 保持合规与高信任表达 + +在产品升级过程中: + +- 不夸大当前能力 +- 不暴露开发者术语 +- 不丢失已建立的法务/隐私/删除/留痕基础 + +### 3.3 本轮 cut line + +#### 本轮必须成立 + +- 首页默认主路径切到“先审核,再规划” +- 审核页成为默认主入口 +- Step 1 最小建档可独立保存与回填 +- 审核结果可分流到:冲稳保 / 补档案 / 完整规划 + +#### 本轮可以延后 + +- Step 2-4 全量偏好完善 +- 同分段参考完整产品化 +- 政策中心完整覆盖 +- 报告资产化完整版本体系 +- 多版本方案管理 + +--- + +## 4. 非目标(Non-goals) + +本轮升级 PRD **不包含**: + +1. 真实支付 acceptance 的外部商户落地 +2. 真正的 27 省高置信推荐内容一次性补齐 +3. 艺体类、提前批、强基计划、港澳台等特殊批次覆盖 +4. 原生 App / 小程序新端建设 +5. 完整 CRM / 销售系统重构 +6. 用大模型完全替代人工审核 / 人工交付 +7. 在本轮同步解决真实支付 acceptance、正式法务审定、异机备份恢复等生产门禁问题 +8. 把同分段参考或政策中心表述成全国统一高置信完整能力 + +--- + +## 5. 目标用户与核心场景 + +### 5.1 目标用户 + +#### 用户A:第一次接触志愿填报的家长 + +- 需要明确步骤 +- 焦虑,不知道先做什么 +- 需要低门槛入口 + 高信任解释 + +#### 用户B:已经有初步方案的学生/家长 + +- 想先看现有方案是否有风险 +- 关心冲稳保结构 +- 关心同分段参考与政策约束 + +#### 用户C:愿意深度补信息换取更好推荐的用户 + +- 不满足于只看分数线 +- 愿意补充偏好、预算、就业方向等信息 +- 需要更强的个性化结果 + +### 5.2 核心场景 + +1. **已有方案/已有想法先审核** + - 先看现有方案或初步想法是否扎堆/失衡/踩线/梯度失衡 +2. **考前/查分前最小建档** + - 先把基础信息录入,为审核和后续规划提供约束 +3. **查分后快速复核** + - 用最小信息快速复核当前志愿方向,再决定是否生成完整方案 +4. **正式填报前精细化调整** + - 用冲稳保 + 同分参考 + 政策中心辅助决策 +5. **生成和复看报告** + - 让报告成为长期可访问、可对比、可迭代的资产 + +### 5.3 本轮优先场景 + +本轮优先服务以下场景: + +1. 已有一版方案,想先判断风险 +2. 只有初步意向,想先做方向复核 +3. 查分后先快速判断是否需要重做完整规划 + +本轮**不以“首次零信息用户直接生成完整方案”作为默认主场景**。 + +--- + +## 6. 产品定位升级 + +### 6.1 升级前 + +- 以订单/支付/资料/状态/交付为主链 +- 用户更像在进入一个“服务流程” + +### 6.2 升级后 + +- 以“高考志愿陪伴任务流”为主体验 +- 订单与支付退到后场,成为服务承接手段 +- 用户感知更像: + - 我有一个志愿档案 + - 我在一个志愿时间线里推进 + - 我可以随时做审核、规划、冲稳保、看政策、看同分段参考、生成报告 + +### 6.3 一句话定位 + +> 一个面向学生与家长、以“**先审核现有方案/现有意向,再逐步建档进入完整规划**”为主线,结合任务化陪伴、冲稳保决策与报告闭环的高考志愿服务产品。 + +### 6.4 与当前真实定位的关系 + +本节定义的是用户侧体验升级后的产品表达,不改变当前项目在真实交付层面的定位: + +- 当前项目仍以人工服务运营增强系统为基础 +- 用户端能力仍处于逐步收口中 +- 体验升级不等于生产 readiness 已完成 + +--- + +## 7. 信息架构(Target IA) + +### 7.1 首页 + +首页应从“单纯落地/支付入口”升级为“**审核优先的高考志愿工作台**”: + +1. **阶段 Banner / 高考时间线** +2. **任务清单**(第一优先任务默认为“先审核现有志愿方案/现有想法”) +3. **快捷入口区** + - 方案审核(默认主入口) + - 冲稳保 + - 志愿报告 + - 查大学/专业 +4. **个人档案入口**(用于提升审核与规划精度,而不是抢占默认主入口) +5. **政策 / 同分段参考入口** + +### 7.2 个人档案中心 + +分 4 步: + +#### Step 1 考生信息(最小必填) + +- 高考省份 +- 科目组合 +- 分数 +- 位次 + +#### Step 2 院校偏好 + +- 院校地域偏好 +- 院校类型 +- 目标院校(可选) + +#### Step 3 专业偏好 + +- 专业偏好 +- 不接受专业 +- 优先策略(院校优先 / 专业优先 / 地域优先 / 就业优先) + +#### Step 4 其他偏好 + +- 毕业规划 +- 学费倾向 +- 就业地域偏好 +- 家庭背景 +- 行业资源 +- 补充说明 + +### 7.3 报告与方案资产 + +用户应看到: + +- 我的志愿报告 +- 我的志愿表 +- 历史版本 +- 最近更新时间 +- 是否基于最新档案生成 + +### 7.4 内容辅助模块 + +- 同分段参考 +- 政策中心 +- 查大学/专业 + +### 7.5 目标能力与现有能力映射 + +| 目标能力 | 当前已有资产 | 当前缺口 | 本轮动作类型 | 是否依赖外部前置 | +| --- | --- | --- | --- | --- | +| 首页任务化 | 现有首页 / Portal 入口 | 缺任务结构与主 CTA 重排 | 重组 | 否 | +| 审核页前置 | 现有审核链 / 资料链 / 上传能力 | 缺默认入口与最小约束表单 | 重组 + 小增量 | 否 | +| Step 1 最小建档 | 现有 `candidate_*` 基础字段 | 缺独立档案心智与保存 / 回填页 | 重组 | 否 | +| Step 2-4 偏好体系 | `order_intakes` 部分字段已存在 | 缺结构化字段与 UI | 新增 | 否 | +| 冲稳保一级化 | 报告已有分类基础 | 缺一级入口 / 筛选 / 结果组织 | 重组 + 增强 | 否 | +| 同分段参考 | `crowd_db` / 风险数据骨架 | 缺展示页与可信度分层 | 新增 | 否 | +| 政策中心 | 规则资料 / 文档基础 | 缺用户侧摘要展示 | 新增 | 否 | +| 报告资产化 | 现有报告交付能力 | 缺版本语义和资产页 | 新增 | 否 | + +--- + +## 8. 核心能力需求 + +## 8.1 P0(本轮最优先:先让“审核优先主线”成立) + +### F-P0-1 首页任务化 + 审核主入口前置 + +**目标**:让用户一进入首页,就知道当前阶段、下一步动作,以及本产品默认先提供“志愿审核服务”。 + +**需求**: + +- 首页新增高考时间线 / 志愿日历模块 +- 首页新增任务清单 +- 每个任务带价值说明与状态 +- 首页新增快捷能力入口 +- 首页默认主 CTA / 主任务为“先审核现有志愿方案 / 先审核现有想法” + +**验收标准**: + +- 首页首屏必须包含:阶段 Banner、任务清单、主 CTA、次 CTA、最近审核结果 / 报告入口 +- 主 CTA 必须是审核入口,不得默认把“完整规划 / 生成方案”放为首个主 CTA +- 未建档用户也可直接进入审核页 + +### F-P0-2 审核页最小闭环 + +**目标**:让“审核优先”成为可执行流程,而不是首页口号。 + +**需求**: + +- 审核页可输入现有方案 / 现有想法 +- 支持粘贴文本、上传截图 / PDF、自由输入初步意向 +- 最小约束信息只要求:省份、科目组合、分数 / 位次 +- 审核结果必须输出风险摘要与下一步建议 + +**验收标准**: + +- 未完成完整档案的用户仍可提交审核 +- 审核页提交后必须出现审核结果页或结果区块 +- 审核结果至少给出“继续微调 / 补档案 / 进入完整规划”三类去向建议 + +### F-P0-3 Step 1 最小建档 + +**目标**:让最小建档成为审核增益层,不成为审核门槛。 + +**需求**: + +- 先只落 Step 1:省份、科目组合、分数、位次 +- 支持保存草稿与继续填写 +- 支持在审核页、报告页回填展示 +- 页面文案必须明确:“不填完整档案,也可以先做审核” + +**验收标准**: + +- Step 1 可独立保存 +- Step 1 保存后可在审核页复用 +- 不完成 Step 2-4 不影响审核提交 + +### F-P0-4 审核结果分流 + +**目标**:把审核结果自然导向后续动作,而不是停留在孤立结果页。 + +**需求**: + +- 审核结果页必须显式提供三个动作入口:冲稳保微调、完善个人档案、进入完整规划 / 报告 +- 每个动作需带适用说明 +- 分流动作需可被埋点追踪 + +**验收标准**: + +- 审核后至少有一个默认推荐动作 +- 三条分流路径均可进入对应页面 +- 页面状态可识别该用户来源于“审核分流” + +--- + +## 8.2 P1(紧接着做:让“审核优先”变成完整产品体验) + +### F-P1-1 冲稳保升级为一级框架 + +**需求**: + +- 首页快捷入口出现“冲稳保” +- 报告按冲 / 稳 / 保分层组织 +- 后续方案查看与筛选基于冲稳保展开 + +**验收标准**: + +- 冲稳保不只是报告里的标签,而是一级入口与一级决策框架 +- 审核后可直接进入冲稳保视图 + +### F-P1-2 Step 2-4 偏好建档 + +**需求**: + +- 补齐院校偏好、专业偏好、其他偏好三层建档 +- 必填项与选填项继续明确区分 +- 偏好字段只作为审核与规划增益,不反向阻塞审核入口 + +**验收标准**: + +- Step 2-4 不成为审核前置门槛 +- 新字段命名、归属层、显示文案与字段映射表一致 + +### F-P1-3 同分段参考 + +**需求**: + +- 查看同分段热门学校 / 专业 / 城市 +- 输出“同分段常见选择”与“扎堆风险提示” + +**验收标准**: + +- 页面明确是参考能力,不伪装成唯一正确答案 +- 页面必须能显示当前省份与数据说明 + +### F-P1-4 政策中心 + +**需求**: + +- 按省份展示志愿填报关键政策摘要 +- 展示时间节点、批次规则、选科说明、常见误区 + +**验收标准**: + +- 页面面向学生 / 家长可理解 +- 页面必须展示来源、更新时间、适用省份 + +### F-P1-5 报告资产化 + +**需求**: + +- 我的志愿报告列表 +- 历史版本 +- 报告生成时间、基于哪个档案版本、当前是否过期 + +**验收标准**: + +- 报告页不再只是一次性输出 +- 用户可判断报告是否基于最新档案生成 +- 当前阶段允许先用 `order_intakes.payload_json` 维护轻量版本历史,不要求单独版本表 + + +### F-P1-6 内容可信度展示规则 + +**需求**: + +- 同分段参考按省展示置信等级 +- 非高置信数据不得使用强推荐口吻 +- 政策中心必须展示来源、更新时间、适用省份 +- 未覆盖或未确认项必须显式标注 + +**验收标准**: + +- 用户不会把页面内容误解为全国统一高置信推荐或官方全文替代品 + +--- + +## 8.3 P2(增强层) + +### F-P2-1 偏好体系增强 + +建议在 P1 稳定后,再增强以下偏好字段的采集、结构化和解释: + +- 学费倾向 +- 家庭背景 +- 行业资源 +- 就业地域偏好 +- 毕业规划 + +要求: + +- 默认非强制 +- 用途明确 +- 不制造隐私压迫感 + +### F-P2-2 性格 / 兴趣测评联动 + +- MBTI / 霍兰德等结果进入推荐因子 +- 只作辅助,不作唯一判断 + +### F-P2-3 多版本方案管理 + +- v1 初始档案方案 +- v2 查分后校准方案 +- v3 正式填报前调整方案 + +P2 一律建立在 P0 / P1 路径稳定、字段语义稳定、版本模型稳定之后。 + +--- + +### 8.4 默认转化路径 + +本轮升级后,默认用户路径应明确为: + +1. 进入首页 +2. 先审核现有志愿方案 / 现有想法 +3. 根据审核结果决定: + - 直接采用并微调 + - 进入冲稳保细化 + - 补充个人档案后生成完整规划 / 报告 +4. 在正式填报前结合政策中心与同分段参考完成最终决策 + +**硬约束**: + +- 首页默认主入口必须是审核,不是完整规划 +- 审核提交不得以完整档案为前置 +- Step 2-4 仅作为审核增益与后续规划增强 +- 政策中心 / 同分段参考只作为决策辅助,不作为自动结论来源 + +禁止把默认主线重新写回“先完整建档 → 直接生成方案”。 + +--- + +## 9. 页面级范围 + +### 9.1 本轮必须交付 + +- 首页(任务化 + 审核主 CTA 前置) +- 审核页(最小闭环) +- 个人档案页 Step 1(最小建档) +- 审核结果分流层 + +### 9.2 本轮可部分交付 + +- 冲稳保页(先形成一级入口与基础结果视图) +- 报告页(先完成结论重组与版本外显) + +### 9.3 后续交付 + +- 同分段参考页 +- 政策中心 +- 完整报告资产页 +- 多版本方案管理 + +--- + +## 10. 数据与接口影响 + +### 10.1 本轮必需数据 + +本轮 P0 必须支持: + +- Step 1 最小建档字段:省份、科目组合、分数、位次 +- 审核输入字段:`existing_plan_summary` 及其等价输入承接 +- 档案最小完成状态 +- 审核来源与审核后分流动作可追踪 +- 审核页、档案页、报告页之间的最小回填能力 + +### 10.2 本轮可选新增字段 + +P1 再引入并结构化以下字段: + +- `school_preference_types` +- `target_schools` +- `target_majors` +- `school_region_preferences` +- `priority_strategy` +- `graduation_plan` +- `tuition_preference` +- `employment_region_preferences` +- `family_background` +- `industry_resources` +- `extra_notes` + +### 10.3 内容口径层 + +内容层需要产品化聚合: + +- 政策摘要数据 +- 同分段统计数据 +- `crowd_db` 外显数据口径 + +但需要严格区分: + +- 高置信数据 vs 参考数据 +- 官方来源摘要 vs 内部整理说明 + +### 10.4 版本对象定义(最小版) + +本轮至少定义以下版本对象语义: + +- `profile_version`:每次用户保存档案快照时递增 +- `review_result_version`:每次审核提交产生一个结果快照 +- `report_version`:每次正式生成报告产生一个版本 + +最小关系: + +- 报告生成时绑定 `profile_version` +- 审核结果可关联输入快照 +- “是否基于最新档案生成” 通过 `report.profile_version` 与最新档案版本比较判断 + +--- + +## 11. 关键指标(Success Metrics) + +### 11.1 转化指标 + +- 首页主 CTA(审核)点击率 +- 审核页提交完成率 +- Step 1 最小建档完成率 +- 从审核入口到完整规划转化率 +- 审核后进入冲稳保比例 +- 审核后进入补档案比例 +- 审核后直接流失率 + +### 11.2 使用指标 + +- 首页任务点击分布 +- 冲稳保页访问率 +- 同分段参考页访问率 +- 政策中心访问率 +- 报告复看率 +- Step 2-4 逐层补全率 + +### 11.3 质量指标 + +- 审核页因缺字段被阻塞的比例下降 +- 资料填写中断率下降 +- 首页跳失率下降 +- 用户对“下一步不清楚”的反馈下降 +- 用户对“产品更像完整服务而非单次工具”的主观评价提升 + +--- + +## 12. 风险与约束 + +### 12.1 口径风险 + +- 不能把“任务化首页”误报成“完整线上志愿 SaaS 已完成” +- 不能把体验升级误报成生产 readiness 完成 +- 不能把法务草案写成正式法务通过版本 + +### 12.2 数据风险 + +- 不能把 27 省可信来源元数据补齐误报成“27 省高置信推荐内容已完成” +- 同分段参考存在省份间可信度差异 +- 政策中心是摘要层,不是官方全文替代 + +### 12.3 流程风险 + +- 个人档案页过重会挤压审核主线 +- 过早做全量偏好字段会提高中断率 +- 过早引入完整资产化 / 多版本会推高实现复杂度 + +### 12.4 工程风险 + +- 版本模型未定义会导致前后端语义漂移 +- 页面先做、数据后补会造成假完成状态 +- 不在同一轮同时拉长到所有外部依赖闭环(真实支付、真实告警、异机恢复等) + +--- + +## 13. 里程碑建议 + +### Milestone 1:审核优先最小闭环 + +- 首页任务化结构 +- 审核页最小闭环 +- Step 1 最小建档 +- 审核结果分流 + +### Milestone 2:决策增强层 + +- 冲稳保一级化 +- 报告页重组 +- Step 2-4 偏好增强 + +### Milestone 3:内容与资产层 + +- 同分段参考 +- 政策中心 +- 报告资产化 +- 最小版本体系落地 + +--- + +## 14. 验收结论口径 + +本 PRD 的目标不是把项目重新定义为一个已经完成的成熟 SaaS,而是给出一条清晰的升级路径: + +> 从当前已有的运营 / 订单 / 资料 / 报告 / 合规能力出发,优先把用户侧产品体验升级为“**审核优先 + 任务化陪伴 + 渐进式建档 + 冲稳保决策 + 报告资产化**”的高考志愿服务产品。 + +本 PRD 验收通过,只代表“用户侧升级方向与范围定义成立”,不代表对应功能已开发完成、已上线或已达到生产可承诺状态。 + +--- + +## 15. 关联文档 + +- `product/PRD.md` +- `product/ROADMAP.md` +- `docs/CURRENT_STATE.md` +- `docs/ACTIVE_REMEDIATION_2026-06-20.md` +- `docs/ACTIVE_EXECUTION_BOARD_2026-06-20.md` +- `docs/COMPETITOR_SCREEN_ANALYSIS_WENXIN_QIANWEN_2026-06-21.md` +- `docs/PAGE_REDESIGN_CHECKLIST_2026-06-21.md` +- `docs/FIELD_MAPPING_AUDIT_FIRST_PROFILE_2026-06-21.md` +- `reports/STRICT_COMPREHENSIVE_REVIEW_2026-06-18.md` + +--- + +## 16. 下一步建议 + +### 第一优先 + +1. 固化本 PRD v0.2 口径 +2. 产出页面级改版清单 v0.2 +3. 产出字段映射表 v0.2 +4. 基于 cut line 产出 P0 / P1 / P2 执行板 + +### 第二优先 + +5. 输出具体接口变更清单 +6. 输出页面级原型说明 / 设计稿说明 + +### 第三优先 + +7. 在执行板稳定后再进入实现拆解 +8. 生产 readiness 事项继续按当前执行板推进,不与本 PRD 混写 diff --git a/reports/STRICT_SYSTEM_REVIEW_2026-06-23.md b/reports/STRICT_SYSTEM_REVIEW_2026-06-23.md new file mode 100644 index 0000000..2fb2602 --- /dev/null +++ b/reports/STRICT_SYSTEM_REVIEW_2026-06-23.md @@ -0,0 +1,478 @@ +# 高考项目严格系统 Review 报告 + +- 审查日期:2026-06-23 ~ 2026-06-24 +- 审查范围:`/home/long/project/gaokao-volunteer-system` +- 审查方式:源码静态审查 + 路由注册核验 + 关键测试集执行 + 最小行为复现 +- 审查口径:按生产可用性、主链路正确性、数据完整性、测试可信度的最严格标准 + +## 执行摘要 + +本次是在部分功能模块更新后的二次严格复审。最新结果与上一个版本相比已经有明显改善: + +1. `submit_order_info()` 已从“整包覆盖写”修正为“读取当前 payload 后 merge 再保存”,附件与复核结果保留问题已修复。 +2. 报告版本关系、政策中心信任说明、辅助链接输出相关回归已经修复,相关测试现已转绿。 +3. 上一版报告中阻断真实生产链路的 2 个高严重度问题已修复: + - 首页 `/` 已恢复真实注册。 + - 方案复核页已改为与浏览器表单协议一致的 `POST form -> 303 redirect`。 +4. 补充了最小真实集成测试,覆盖首页真实路由注册、复核分流表单提交、真实路由元数据。 +5. 当前关键回归在真实 `TestClient` 与现有页面/状态/资料/版本测试组合下已转绿;剩余 warning 仅为 `starlette.testclient` 对 `httpx` 的弃用提示,不影响本次功能结论。 + +当前结论:本报告原列的阻断级问题已全部修复。 + +第三轮补充结论(历史保留): + +- 未发现新的主链路生产级功能缺陷。 +- 当时剩余风险主要来自测试夹具与真实 FastAPI/ASGI 行为的一致性,而不是前台业务链路本身。 + +第四轮补充结论(历史保留): + +- 前台公开主链路继续保持绿色,未复现新的下单 / 支付 / 资料 / 复核 / 报告访问故障。 +- 本轮剩余两项未关闭问题已修复: + - backup / restore smoke 现在要求 `config/.env` 与 `secrets/*` 存在,且真实通过 `create_app()` + `TestClient` 执行 `/health`、`/api/public/orders`、portal 状态/报告/pdf`。 + - 后台录单页已补齐 `consent_method` / `consent_note` 字段,前端提交 payload 与 `/api/orders` 当前创建契约重新一致。 +- 因此,前台主链路、本轮后台安全问题、恢复验证口径与后台录单契约问题均已转绿。 +- 按当前这份严格审查报告列出的活动问题口径,系统已无未关闭项;现阶段可以认为本轮严格审查通过。 + +第五轮补充结论(历史保留): + +- 在继续沿“真实可用性边界”“公开入口与真实能力边界一致性”“复核分流后是否进入真实功能页”的方向深挖后,曾确认 3 个活动问题需要重新打开: + - `/review/action` 分流后的 `cwb` / `full-plan` 路径当前仍是 placeholder 页面,未承载真实冲稳保结果或完整规划结果。 + - 公开下单与资料入口允许 `内蒙古 / 广西 / 西藏 / 宁夏` 等当前 loader 不支持的省份进入;后续同分段参考页不会提示“暂不支持”,而是按普通页面渲染“暂无”。 + - Portal 资料页头部宣称“四步资料向导”,但运行态实际是 5 个 step panel,徽标定义与实际交互顺序已漂移。 +- 上述 3 项现已修复,不再是当前活动问题。 + + +关联文档: + +- `reports/TEST_CLIENT_COVERAGE_2026-06-23.md`:记录用户端主链路真实 `TestClient` 覆盖现状与剩余 `RouteClient` 边界。 +- `docs/CURRENT_STATE.md` §0.8:当前真相源中对这次测试可信度收口的正式口径。 + + +## Findings + +### P1-5 复核分流后的 `cwb` / `full-plan` 路径当前仍是 placeholder 页面,不提供真实冲稳保结果或完整规划结果 — 已修复 + +- 原问题位置: + - 路由入口:`admin/routes/web_public.py:399-417` + - `cwb` 渲染:`admin/routes/web_public.py:3179-3209` + - `full-plan` 渲染:`admin/routes/web_public.py:3212-3242` +- 修复: + - `cwb` 页面改为“冲稳保建议页”,输出当前建议 / 冲刺建议 / 稳妥建议 / 保底建议 + - `full-plan` 页面改为“完整规划建议页”,输出方案优先级 / 版本历史 / 当前复核摘要 + - 去掉“后续再接真实推荐结果”“当前从 review 分流进入完整规划入口”这类占位口径 +- 新证据: + - `admin/tests/test_web_public_review_flow.py::test_cwb_page_no_longer_claims_placeholder_future_work` + - `admin/tests/test_web_public_review_flow.py::test_full_plan_page_no_longer_claims_entry_only_placeholder` + - 既有 CWB / full-plan 页面测试已同步改按新口径断言 +- 当前结论:已关闭。 + +### P1-6 公开下单与资料入口允许当前不支持的省份进入,后续参考页把“不支持”伪装成普通“暂无” — 已修复 + +- 原问题位置: + - 下单页省份选项:`admin/routes/web_public.py:1898-1900, 2134-2174` + - 公开下单契约:`data/orders/public_flow.py:26-44` + - loader 支持边界:`data/crowd_db/loader.py:82-116` + - 同分段参考页回退逻辑:`admin/routes/web_public.py:1233-1272` +- 修复: + - `PublicOrderCreate` 现在显式校验支持省份集合 + - 公开下单与 Portal Step 1 的省份下拉已收敛到当前支持集 + - `policy-center` / `same-score-reference` 对不支持省份显式展示“当前省份暂不支持” +- 新证据: + - `admin/tests/test_web_public.py::test_public_create_order_rejects_unsupported_province` + - `admin/tests/test_web_public_content_pages.py::test_same_score_reference_page_marks_unsupported_province_explicitly` +- 当前结论:已关闭。 + +### P2-2 Portal 资料页的向导定义已漂移:头部宣称 4 步,运行态实际为 5 步 — 已修复 + +- 原问题位置:`admin/routes/web_public.py:2368-2490` +- 修复: + - 向导头部已统一改为“五步资料向导” + - step badge 顺序改为:基础信息 / 院校偏好 / 专业偏好 / 其他偏好与确认 / 已有方案与附件 + - 文案与脚本 `totalSteps = 5` 重新一致 +- 新证据: + - `admin/tests/test_order_info_form.py::test_order_info_form_accepts_draft_and_submit` + - 页面断言已改为“五步资料向导”与 5 类步骤名称 +- 当前结论:已关闭。 + +### P1-1 删除/匿名化服务直接信任数据库中的路径并执行 `unlink()`,可越界删除可信根之外的文件 — 已修复 + +- 原问题位置:`data/orders/deletion_service.py:198-253` +- 修复: + - `OrderDeletionService` 现在要求: + - portal 附件必须位于 `settings.portal_upload_dir` + - 交付物必须位于 `_trusted_report_roots(settings)` + - 对不可信路径改为 `skip`,不再执行 `unlink()` / `rmdir()` + - `admin/routes/orders.py` 初始化删除服务时显式传入 trusted roots +- 新证据: + - `admin/tests/test_order_deletion.py::test_admin_anonymize_order_skips_untrusted_attachment_paths` + - `admin/tests/test_order_deletion.py::test_admin_delete_order_skips_untrusted_report_artifacts` + - 同时正常受信路径回归仍通过 +- 当前结论:已关闭。 + +### P1-2 `viewer` 角色仍可进入案例写接口,且统计接口只要求“已登录”不要求“有权限” — 已修复 + +- 原问题位置: + - `admin/routes/cases.py:67-226` + - `admin/routes/stats.py:53-118` +- 修复: + - `cases` 列表 / 创建 / 详情 / 更新 / 审核 / 删除统一为 `require_role("admin")` + - `stats` dashboard / order stats 统一为 `require_role("admin")` +- 新证据: + - `admin/tests/test_routes_cases.py::test_viewer_cannot_create_case` + - `admin/tests/test_routes_stats_dashboard.py::test_viewer_cannot_read_order_stats` + - `admin/tests/test_routes_orders.py::test_viewer_cannot_list_orders` 继续保持绿色 +- 当前结论:已关闭。 + +### P1-3 `RouteClient` 仍会绕过真实 FastAPI 参数验证与路由层行为 — 已缓解并在前台关键测试文件中清零 + +- 现状: + - 首页注册与 `review/action` 表单协议这两个曾经的阻断点,已经补上真实 `TestClient` 校验。 + - 前台关键测试文件中的 `RouteClient` 已清零;`RouteClient` 仍保留在仓库中,但不再作为前台主链路测试证据。 +- 新证据: + - `admin/tests/test_order_status_page.py::test_real_client_review_action_rejects_missing_action_field` + - `admin/tests/test_order_status_page.py::test_real_client_review_action_rejects_invalid_literal_action` + - `admin/tests/test_order_status_page.py::test_real_client_review_action_rejects_json_body_for_form_route` + - `reports/TEST_CLIENT_COVERAGE_2026-06-23.md` +- 当前结论: + - 该问题相较最初阶段已完成前台主链收口,不再构成本报告中的活动问题。 + +### P1-4 backup / restore smoke 的“服务级恢复”口径与真实实现不一致,且缺少配置 / secrets 仍可跑绿 — 已修复 + +- 原问题位置: + - `scripts/backup_verify.sh:25, 208-217` + - `scripts/backup_restore_smoke.py` + - `tests/test_backup_restore_service_level.py` +- 修复: + - `backup_restore_smoke.py` 现在强制要求: + - `config/.env` + - `secrets/jwt_secret` + - `secrets/orders_fernet_key` + - `secrets/admin_pass` + - 恢复验证改为真实 `create_app()` + `TestClient` + - 真实执行 `/health`、`POST /api/public/orders`、portal 状态页、报告页、PDF 下载链路 + - 输出增加 `public_order_create: 201` +- 新证据: + - `tests/test_backup_restore_service_level.py::test_backup_verify_uses_venv_python_for_service_level_restore` + - `tests/test_backup_restore_service_level.py::test_backup_restore_smoke_fails_fast_when_admin_db_missing` + - `tests/test_backup_restore_service_level.py::test_backup_restore_smoke_fails_fast_when_config_env_missing` + - `tests/test_backup_restore_service_level.py::test_backup_restore_smoke_uses_real_testclient_contract_marker` +- 当前结论:已关闭。 + +### P2-1 后台手动录单页与后端创建契约已脱节,页面当前生成的 payload 必然被后端 422 拒绝 — 已修复 + +- 原问题位置: + - 页面输出:`admin/routes/ui.py:132-180` + - 后端创建契约:`admin/routes/orders.py:233-238` +- 修复: + - 后台录单页新增 `consent_method` 与 `consent_note` 输入控件 + - 页面脚本现在会构造 `consent: { consent_method, consent_note }` 并随 `/api/orders` 一起提交 +- 新证据: + - `admin/tests/test_admin_ui_pages.py::test_admin_new_order_page_includes_required_consent_fields` + - 页面内联脚本现已显式出现 `consent` / `consent_method` / `consent_note` +- 当前结论:已关闭。 + +### P0-1 首页路由缺失 — 已修复 + +- 原问题位置:`admin/routes/web_public.py:208` +- 修复:已恢复 `@router.get("/", include_in_schema=False)`。 +- 新证据: + - 真实路由元数据:`/ ['GET'] []` + - 真实集成测试:`admin/tests/test_order_status_page.py::test_public_landing_route_is_registered_in_real_app` +- 当前结论:已关闭。 + +### P0-2 复核页表单协议与后端协议不一致 — 已修复 + +- 原问题位置: + - 表单输出:`admin/routes/web_public.py:_render_review_start_page()` + - 接口定义:`admin/routes/web_public.py:620-627` +- 修复: + - `/review/action` 改为接收 `Form(...)` 的 `token` 与 `action` + - 返回 `303 RedirectResponse`,与浏览器表单流一致 +- 新证据: + - 真实路由元数据:`/review/action ['POST'] ['token', 'action']` + - 真实集成测试:`admin/tests/test_order_status_page.py::test_review_action_accepts_browser_form_post` +- 当前结论:已关闭。 + +## 已修复项 + +### R-1 Portal 资料保存的上下文丢失问题已修复 + +- 修复位置:`admin/routes/web_public.py:569-573` +- 变化: + - 现在会先读取 `current.payload`,再 `base_payload.update(payload.model_dump())`,之后才生成版本元数据并保存。 +- 复核结果: + - 最小复现脚本显示: + - `has_attachments True 1` + - `has_review_results True [...]` + - `review_id_preserved True` + - 说明附件、复核结果、`latest_review_result_id` 已在再次保存资料后保留。 + +### R-2 报告版本与历史档案关系的回归已修复 + +- 修复位置: + - `admin/routes/web_public.py:1022-1033` + - `admin/routes/web_public.py:2853-2863` +- 变化: + - 新增 `_report_version_profile_reference()`,报告页开始优先使用 `report_versions` 中记录的 `profile_version_id`。 +- 复核结果: + - `admin/tests/test_web_public_review_flow.py::test_report_page_warns_when_based_on_historical_profile_version` 已通过。 + +### R-3 政策中心/同分段参考页的信任说明与辅助链接回归已修复 + +- 修复位置: + - `admin/routes/web_public.py:1069-1083` + - `admin/routes/web_public.py:1160-1208` +- 变化: + - 新增统一 trust banner,补齐“来源 / 更新时间 / 适用范围 / 置信等级 / 边界说明”。 +- 复核结果: + - `admin/tests/test_web_public_content_pages.py::test_policy_center_page_shows_standard_trust_banner` 已通过。 + +## 验证记录 + +### 路由核验 + +执行: + +```bash +.venv/bin/python - <<'PY' +from admin.app import create_app +from admin.config import load_settings +from fastapi.routing import APIRoute +app = create_app(load_settings()) +for key in ['/', '/review/action', '/policy-center', '/same-score-reference']: + for r in app.routes: + if isinstance(r, APIRoute) and r.path == key: + print(key, sorted(r.methods), [p.name for p in r.dependant.body_params]) + break + else: + print(key, None) +PY +``` + +结果: + +```text +/ ['GET'] [] +/review/action ['POST'] ['token', 'action'] +/policy-center ['GET'] [] +/same-score-reference ['GET'] [] +``` + +结论:首页与复核分流入口均已真实注册,且 `/review/action` 已按表单 body 暴露字段。 + +### 真实集成测试 + +执行: + +```bash +.venv/bin/python -m pytest -q admin/tests/test_order_status_page.py -k 'public_landing_route_is_registered_in_real_app or review_action_accepts_browser_form_post or real_app_registers_public_entry_and_form_review_routes' +``` + +结果:`3 passed, 1 warning in 0.48s` + +结论: + +- `GET /` 在真实 `TestClient` 下返回 200 +- 浏览器表单 `POST /review/action` 在真实 `TestClient` 下返回 303 并跳转到对应后续页面 +- 路由元数据断言与运行时行为一致 + +### 第四轮新增验证 + +#### 权限依赖元数据核验 + +执行: + +```bash +.venv/bin/python - <<'PY' +from fastapi.routing import APIRoute +from admin.app import create_app +from admin.config import load_settings +app = create_app(load_settings()) +for target in ['/api/cases', '/api/admin/cases', '/api/stats/orders', '/api/admin/stats/orders', '/api/orders']: + for route in app.routes: + if isinstance(route, APIRoute) and route.path == target: + deps = [getattr(dep.call, '__name__', str(dep.call)) for dep in route.dependant.dependencies] + print(target, sorted(route.methods), deps) +PY +``` + +结果: + +```text +/api/cases ['GET'] ['get_settings_dep', 'get_current_user'] +/api/cases ['POST'] ['get_settings_dep', 'get_current_user'] +/api/admin/cases ['GET'] ['get_settings_dep', 'get_current_user'] +/api/admin/cases ['POST'] ['get_settings_dep', 'get_current_user'] +/api/stats/orders ['GET'] ['get_settings_dep', 'get_current_user'] +/api/admin/stats/orders ['GET'] ['get_settings_dep', 'get_current_user'] +/api/orders ['GET'] ['get_settings_dep', '_dep'] +``` + +结论:`cases` 与 `stats` 路由当前只做“已登录”校验,没有像 `orders` 一样落到角色门禁。 + +#### `viewer` 角色最小行为复现 + +执行结果摘要: + +```text +create_case succeeded for role= viewer case_id= 1 +stats ok for role= viewer keys= ['by_service_version', 'by_source', 'by_status', 'total_orders', 'total_revenue_cents'] +``` + +结论:`viewer` 并非只具备浏览能力;至少在当前实现里,它已经能够进入案例写路径与统计读取路径。 + +#### 删除服务越界删文件复现 + +执行结果摘要: + +```text +files_deleted= 1 +sentinel_exists= False +``` + +复现方式:在隔离临时库中把 `order_intakes.payload_json.attachments[*].storage_path` 指向 portal 上传目录之外的临时文件,再调用 `OrderDeletionService.anonymize_order(...)`。 + +结论:删除服务当前会直接删除数据库中记录的任意存在文件,而不是只删除受信附件/受信交付物。 + +#### restore smoke 假阳性复现(历史问题,现已修复) + +执行结果摘要(修复前): + +```text +{"health_status": 200, "portal_pdf": 200, "has_config_dir": false, "has_secrets_dir": false, ...} +``` + +修复前复现方式:在临时目录构造仅含 `db/admin.db`、`db/orders.db` 与示例 HTML/PDF 的最小快照,故意不提供 `config/.env` 与 `secrets/`,再直接调用 `run_restore_smoke(...)`。 + +修复后状态: + +- `backup_restore_smoke.py` 现在会 fail fast 要求 `config/.env` 与 `secrets/*` 齐全 +- 且已升级为真实 `create_app()` + `TestClient` 服务级恢复验证 + +#### 后台手动录单页契约核验(历史问题,现已修复) + +执行结果摘要(修复前): + +```text +ValidationError +consent +Field required +``` + +修复前核验方式: + +- 打开 `admin/routes/ui.py` 中 `/admin/orders/new` 生成的页面 payload,确认提交字段集合。 +- 对照 `admin/routes/orders.py` 中 `CreateOrderRequest` 的当前必填契约。 +- 直接对页面最小 payload 执行 `CreateOrderRequest.model_validate(...)`。 + +修复后状态: + +- 页面已补齐 `consent_method` / `consent_note` +- `admin/tests/test_admin_ui_pages.py::test_admin_new_order_page_minimal_payload_matches_create_order_contract` 已锁定“页面最小 payload 可通过当前契约” + +### 第五轮新增验证(历史保留) + +#### 不支持省份入口核验(修复前) + +执行结果摘要(修复前): + +```text +public_order_candidate_province 内蒙古 +适用省份:内蒙古 True +同分段热门学校 True +暂无 True +暂不支持 False +``` + +当前状态:公开创建模型已拒绝不支持省份;同分段参考页对不支持省份会显式展示“当前省份暂不支持”。 + +#### 资料向导步数一致性核验(修复前) + +执行结果摘要(修复前): + +```text +step_badges 4 +step_panels 5 +four_step_title True +step5_present True +total_steps_5 True +``` + +当前状态:资料向导已统一为“五步资料向导”,头部徽标、step badge、step panel 与脚本 `totalSteps = 5` 重新一致。 + +### 关键回归组合 + +执行: + +```bash +.venv/bin/python -m pytest -q admin/tests/test_web_public.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_review_flow.py admin/tests/test_order_info_form.py data/orders/tests/test_public_flow.py +``` + +结果:`68 passed, 1 warning in 10.90s` + +结论:本轮新增的分流页口径、省份支持边界、资料向导步数相关回归已转绿。 + + +### 数据丢失最小复现 + +复现路径: + +1. 创建公开订单并完成 mock 支付 +2. 上传 Portal 附件 +3. 发起一次 review +4. 再提交一次 Portal 资料 + +上一次审查时的最终 payload 关键状态: + +```text +attachments False +review_results False +profile_versions True +latest_review_result_id None +profile_versions_len 1 +``` + +本次更新后重新复核: + +```text +has_attachments True 1 +has_review_results True ['rvw_0db8fc4c'] +latest_review_result_id rvw_0db8fc4c +review_id_preserved True +profile_versions_len 1 +``` + +结论:附件与复核上下文丢失问题已修复;该节作为历史问题保留。 + +## 对测试体系的附加评价 + +- 当前 `RouteClient` 仍作为轻量辅助夹具存在于仓库中,但前台关键测试文件已不再使用它作为主证据;主要公开页、复核分流、下单与资料链路已通过真实 `TestClient` 回归验证。 +- 这一轮之前暴露出的 3 类缺口已经补齐: + - backup / restore 验证已升级为真实 `create_app()` + `TestClient` + - 后台录单页 payload 已与后端契约重新对齐,并有模型级测试锁住 + - 新增的 review 分流页、省份支持边界、资料向导步数问题也已被负向/页面回归用例覆盖 +- 当前测试体系剩余的主要问题不再是“存在明确活动缺陷”,而是 warning 级别的依赖弃用提示(`starlette.testclient` → `httpx2`)。 + +## 结论 + +本报告中曾经出现过的前台阻断级问题、后台安全边界问题、恢复验证口径问题、后台录单页契约问题,以及第五轮补充发现的 3 个活动问题,现已全部修复。 + +最新真实状态: + +- 公开首页 `/` 已可真实访问。 +- 复核分流已与浏览器表单协议一致,真实提交可用。 +- 删除/匿名化服务已增加 trusted-root 校验,不再删除受信根之外的文件。 +- `viewer` 角色已不能再写案例或读取统计。 +- backup / restore smoke 已升级为真实 `create_app()` + `TestClient` 服务级验证,并会 fail fast 要求 `config/.env` 与 `secrets/*`。 +- 后台手动录单页与 `/api/orders` 的 `consent` 契约已重新对齐。 +- review 分流后的 `cwb` / `full-plan` 已不再用占位口径伪装正式结果页。 +- 公开入口与参考页对不支持省份的边界已显式收口。 +- Portal 资料向导已统一为“五步资料向导”。 + +剩余注意项: + +- warning 仅为 `starlette.testclient` 对 `httpx` 的弃用提示,属于依赖升级事项,不是本次功能故障。 + +因此,按本报告最初定义的“生产可用性、主链路正确性、数据完整性、测试可信度”的关键阻断标准复核: + +> 当前版本已修复本报告列出的活动问题,本轮严格审查通过。 diff --git a/reports/STRICT_SYSTEM_REVIEW_2026-06-24.md b/reports/STRICT_SYSTEM_REVIEW_2026-06-24.md new file mode 100644 index 0000000..bf0f6c6 --- /dev/null +++ b/reports/STRICT_SYSTEM_REVIEW_2026-06-24.md @@ -0,0 +1,199 @@ +# 高考项目严格系统 Review 报告(最新汇总版) + +- 审查日期:2026-06-24 +- 审查范围:`/home/long/project/gaokao-volunteer-system` +- 审查方式:源码静态审查 + 路由/权限边界核验 + 真实 `TestClient` 回归 + 最小行为复现 +- 审查口径:按生产可用性、主链路正确性、数据完整性、测试可信度的最严格标准 + +## 执行摘要 + +当前仓库状态下,前台主链路、后台高风险安全边界、恢复演练口径、后台录单契约,以及此前多轮补充发现的问题,均已修复并重新验证。 + +本轮最终交叉核验确认: + +1. 前台主链路可真实访问并走通:下单、支付、资料补充、复核分流、CWB、完整规划、报告、PDF 下载均可回归验证。 +2. 前台关键测试文件中的 `RouteClient` 已清零;关键页面与关键 POST 协议现由真实 `TestClient` 证明。 +3. 删除/匿名化服务已加 trusted-root 校验;不再信任 DB 中的任意文件路径执行 `unlink()`。 +4. `viewer` 角色对 `cases` / `stats` 的权限边界已重新收口到 admin-only。 +5. `backup_restore_smoke.py` 已升级为真实 `create_app()` + `TestClient` 服务级恢复验证,且 backup workflow 的 snapshot/secrets 契约已经与 smoke 对齐。 +6. 后台录单页与 `/api/orders` 的 `consent` 契约已重新对齐;后台录单默认落 `draft` intake,避免伪装成 Portal `submitted`。 +7. review 分流后的 `cwb` / `full-plan` 已去掉占位口径,公开入口对不支持省份的边界已显式收口,Portal 资料页已统一为“五步资料向导”。 +8. 后台详情 API 现已显式暴露结构化 `intake` 载荷,报告页 CTA 已与 `review_followup_action=step1` 一致映射到 `/portal/{token}/info`。 +9. 后台 UI 页面 `/dashboard`、`/admin/dashboard`、`/admin/orders/new` 已纳入 admin 鉴权边界;`payment_return_page` 仅在 payment.status=`paid` 时签发 portal token。 +10. 公开上传附件响应已移除 `storage_path`,`stats` 的 `/tmp/debug_stats.txt` 遗留调试写盘已移除。 + +当前已观测 warning:无。 + +`starlette.testclient` → `httpx2` 的弃用 warning 已通过补齐测试依赖 `httpx2>=2.0.0` 消除。 + +## 当前状态结论 + +- 生产可用性:通过 +- 主链路正确性:通过 +- 数据完整性:通过 +- 测试可信度:通过(前台主链已完成真实 `TestClient` 覆盖收口) +- 安全边界:通过 + +> 结论:按本报告采用的最严格审查口径,当前版本可视为通过本轮严格审查,可进入上线前最后准备阶段。 + +## 关键已修复项 + +### A. 前台主链路与真实协议 + +- 首页 `/` 已恢复真实注册。 +- `/review/action` 已改为真实浏览器表单协议:`POST form -> 303 redirect`。 +- `admin/tests/test_order_status_page.py` 中已补: + - 首页真实注册校验 + - review form 正向提交 + - review form 缺字段/错误 literal/json body 错误路径 + - review → CWB / full-plan 真实跳转 + +### B. 前台关键测试文件 `RouteClient` 清零 + +以下文件中的 `route_client.` 调用已清零: +- `admin/tests/test_web_public.py` +- `admin/tests/test_web_public_content_pages.py` +- `admin/tests/test_web_public_review_flow.py` +- `admin/tests/test_web_public_portal_info.py` +- `admin/tests/test_order_status_page.py` + +说明:`RouteClient` 仍保留在仓库作为轻量辅助夹具,但已不再承担前台主链路正确性的核心证据责任。 + +### C. 删除/匿名化越界删文件 + +- `data/orders/deletion_service.py` + - portal 附件删除受限于 `settings.portal_upload_dir` + - 交付物删除受限于 `_trusted_report_roots(settings)` +- 不可信路径现在会被跳过,不再执行 `unlink()`。 +- 受信路径的正常删除行为保持绿色。 + +### D. viewer 权限边界漂移 + +- `admin/routes/cases.py`:admin-only +- `admin/routes/stats.py`:admin-only +- 与 `orders` 模块权限基线重新一致。 + +### E. backup / restore smoke 与 snapshot 契约 + +- `scripts/backup_restore_smoke.py` 会 fail fast 要求: + - `config/.env` + - `secrets/jwt_secret` + - `secrets/orders_fernet_key` + - `secrets/admin_pass` +- `scripts/backup_snapshot.sh` / `tests/test_backup_workflow.py` / `tests/test_backup_restore_service_level.py` 现已统一到同一 secrets 文件命名契约。 +- 恢复 smoke 已升级为真实: + - `create_app()` + - `TestClient(app)` + - `/health` + - `POST /api/public/orders` + - portal 状态页 / 报告页 / PDF 下载 + +### F. 后台录单页、详情口径与创建契约 / 提交语义 + +- `admin/routes/ui.py` + - 页面新增 `consent_method` / `consent_note` + - 页面脚本提交 `consent: { consent_method, consent_note }` +- `admin/routes/orders.py` + - 后台录单默认创建 `draft` intake,不再伪装成 portal `submitted` + - 订单详情接口现会返回结构化 `order.intake` +- `admin/tests/test_admin_ui_pages.py` + - 已锁住“页面最小 payload 可通过 `CreateOrderRequest.model_validate(...)`” + +### G. 第五轮与最终补充发现问题 + +1. review 分流后的 `cwb` / `full-plan` 占位口径:已修复 +2. 不支持省份入口边界:已修复 +3. 资料向导步数漂移:已修复 +4. 后台 UI 未鉴权:已修复 +5. `payment_id` 越权换取 portal token:已修复 +6. 公开上传响应泄露 `storage_path`:已修复 +7. `stats` 无条件写 `/tmp/debug_stats.txt`:已修复 +8. 报告页 CTA 未覆盖 `step1` followup 映射:已修复 + +### 当前验证证据 + +### 1. 主链路与页面/协议组合 + +```bash +./.venv/bin/python -m pytest -q \ + admin/tests/test_order_status_page.py \ + admin/tests/test_web_public.py \ + admin/tests/test_web_public_content_pages.py \ + admin/tests/test_web_public_review_flow.py \ + admin/tests/test_web_public_portal_info.py \ + admin/tests/test_order_info_form.py \ + data/orders/tests/test_schema.py \ + data/orders/tests/test_public_flow.py +``` + +结果:通过 + +### 2. 删除边界 / 权限边界 / 后台 UI / 恢复 smoke / 订单权限 / 元数据一致性 + +```bash +./.venv/bin/python -m pytest -q \ + admin/tests/test_order_deletion.py \ + admin/tests/test_routes_cases.py \ + admin/tests/test_routes_stats_dashboard.py \ + admin/tests/test_admin_ui_pages.py \ + admin/tests/test_app.py \ + admin/tests/test_admin_alias_routes.py \ + admin/tests/test_order_info_upload.py \ + admin/tests/test_order_status_page.py \ + tests/test_backup_workflow.py \ + tests/test_backup_restore_service_level.py \ + admin/tests/test_routes_orders.py \ + admin/tests/test_routes.py +``` + +结果:通过 + +### 3. 当前严格审查汇总回归组合 + +```bash +./.venv/bin/python -m pytest -q \ + admin/tests/test_order_status_page.py \ + admin/tests/test_web_public.py \ + admin/tests/test_web_public_content_pages.py \ + admin/tests/test_web_public_review_flow.py \ + admin/tests/test_web_public_portal_info.py \ + admin/tests/test_order_deletion.py \ + admin/tests/test_routes_cases.py \ + admin/tests/test_routes_stats_dashboard.py \ + admin/tests/test_admin_ui_pages.py \ + admin/tests/test_app.py \ + admin/tests/test_admin_alias_routes.py \ + admin/tests/test_order_info_form.py \ + admin/tests/test_order_info_upload.py \ + admin/tests/test_routes_orders.py \ + admin/tests/test_routes.py \ + data/orders/tests/test_schema.py \ + data/orders/tests/test_public_flow.py \ + tests/test_backup_workflow.py \ + tests/test_backup_restore_service_level.py +``` + +结果:`177 passed in 31.44s` + +## 风险余量与建议 + +### 当前非阻断项 + +- 当前无已观测非阻断 warning;此前的 `starlette.testclient` → `httpx2` 弃用提示已修复 + +### 上线前建议 + +1. 对外口径继续保持: + - 公开省份支持集是当前支持集,不夸大为全国通用能力 + - crowd_db 全国高信任仍按真相源文档分批推进 +2. 若要进一步提高发布信心,可加一次: + - 真机/容器内 smoke + - 恢复脚本在真实备份快照上的人工演练 + + + +## 关联文档 + +- `reports/STRICT_SYSTEM_REVIEW_2026-06-23.md`:历史滚动审查报告,已保留完整发现/修复轨迹 +- `reports/TEST_CLIENT_COVERAGE_2026-06-23.md`:前台真实 `TestClient` 覆盖收口证据 +- `docs/CURRENT_STATE.md`:当前真相源 diff --git a/reports/TEST_CLIENT_COVERAGE_2026-06-23.md b/reports/TEST_CLIENT_COVERAGE_2026-06-23.md new file mode 100644 index 0000000..3c6879e --- /dev/null +++ b/reports/TEST_CLIENT_COVERAGE_2026-06-23.md @@ -0,0 +1,52 @@ +# Test Client Coverage Status + +> 结论:主链路页面与协议已完成真实 `TestClient` 覆盖;前台关键测试文件中的 `RouteClient` 已清零。 + +关联文档: + +- `reports/STRICT_SYSTEM_REVIEW_2026-06-23.md`:严格系统复审,已确认此前阻断级主链路问题已修复。 +- `docs/CURRENT_STATE.md` §0.8:当前真相源中的正式口径。 + +## 已真实覆盖的主链路 + +- 首页公开入口:`/` +- 定价页 / 付费页:`/pricing`、`/checkout/*` +- 复核入口:`/review/start` +- 复核分流:`POST /review/action`(真实 form + 303 redirect) +- 冲稳保页面:`/portal/{token}/cwb` +- 完整规划页:`/portal/{token}/full-plan` +- 资料页:`/portal/{token}/info` +- 状态页:`/portal/{token}/status` +- 报告页:`/portal/{token}/report`、`/portal/{token}/report.pdf` +- 支付成功页:`/portal/{token}/payment-success` +- 公开建单:`POST /api/public/orders` +- 关键支付完成:`POST /pay/mock/{payment_id}/complete` + +## 前台关键测试文件清零状态 + +- `admin/tests/test_web_public.py` → `route_client.` 计数 `0` +- `admin/tests/test_web_public_content_pages.py` → `0` +- `admin/tests/test_web_public_review_flow.py` → `0` +- `admin/tests/test_web_public_portal_info.py` → `0` +- `admin/tests/test_order_status_page.py` → `0` + +## 当前 `RouteClient` 剩余定位 + +- 仍保留在仓库里,作为轻量辅助夹具存在 +- 但前台关键测试文件已不再使用它 +- 后续若继续看到 `RouteClient`,应默认把它视为非前台主链路测试或历史遗留点,而不是当前用户端主证据 + +## 现状判断 + +- 主链路可达性、重定向、表单协议、公开建单成功链路:已由真实 `client` 证明。 +- 前台关键测试文件中的 `RouteClient` 已清零,主链路正确性不再依赖直接路由调用。 +- 先前的 `starlette.testclient` → `httpx2` 弃用 warning 已通过补齐测试依赖清除。 + +## 最近验证 + +- `./.venv/bin/python -m pytest -q admin/tests/test_web_public.py admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_portal_info.py` → `54 passed` +- `./.venv/bin/python -m pytest -q admin/tests/test_web_public_content_pages.py admin/tests/test_web_public.py` → `26 passed` +- `./.venv/bin/python -m pytest -q admin/tests/test_web_public.py -k 'encryption_key_missing or provider_unavailable or prod_hides_simulated_payment_entrypoints'` → `3 passed` +- `./.venv/bin/python -m pytest -q admin/tests/test_order_status_page.py admin/tests/test_web_public.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_portal_info.py data/orders/tests/test_schema.py` → `89 passed` +- `./.venv/bin/python -m pytest -q admin/tests/test_order_status_page.py admin/tests/test_web_public.py admin/tests/test_web_public_content_pages.py admin/tests/test_web_public_review_flow.py admin/tests/test_web_public_portal_info.py admin/tests/test_order_deletion.py admin/tests/test_routes_cases.py admin/tests/test_routes_stats_dashboard.py admin/tests/test_admin_ui_pages.py admin/tests/test_order_info_form.py data/orders/tests/test_schema.py data/orders/tests/test_public_flow.py tests/test_backup_restore_service_level.py` → `149 passed` +