18 KiB
18 KiB
宠小它 — P0 研发落地清单
本体对齐:任务条目引用
ontology/中的实体/规则 ID(如entity:report、rule:BR-RPT-002)。冲突以本体为准。用途:发给研发拆任务与验收;仅含 P0(本期质量与主线闭环必需,不含 P1/P2 增强)。
依据:《产品全方位优化说明 v1》《本期主线》《宠主端预约体验优化》《产品设计文档》及当前仓库实现粗对齐。
更新:2026-07-05(P0 稳定化轮次:冻结本期范围,重新标记状态并绑定 Owner 与验收命令)
关联: 产品全方位优化说明-v1 · 本期主线-下一步产品优化点 · 宠主端预约体验优化-产品说明 · 架构与产品评估报告-2026-07-05 · Cursor P0 Handoff
本期 P0 范围(冻结口径)
本期 P0 范围:
- 门店端:预约列表、开始服务、填写报告、发送报告、回访池。
- 宠主端:预约填单、公开报告页、下次服务提醒留资、报告打开基础埋点。
- 报告能力:服务前/服务后照片、服务过程素材、短片生成与下载、分享链接/二维码/话术。
不进入 P0:
- 会员、储值、套餐、复杂 CRM。
- 宠主账号内历史报告汇总。
- 完整经营分析看板。
- 「到店不排队」等无容量模型承诺,统一文案为「在线选时段,到店更省心」。
状态标记说明
- ✅ 已实现:仓库已实现且通过本次构建/验收命令。
- 🟡 部分实现:主路径已落,但仍有 gap(已列出),需按验收命令闭环。
- ❌ 未实现:本期必须补齐。
- 🧪 待测试:实现可能已存在,但缺自动化测试或人工 smoke 证据。
优先级说明
- P0:本迭代必须交付;阻塞对外口碑、数据脏读、合规提示缺失、或主线(传播/成片/留资)不可用。
- 已部分实现的项:仍保留,以下方「验收标准」为准做 gap 关闭。
A. 后端(Spring Boot)
| ID | 需求 | 验收标准 | Owner | 状态 | 验收命令 | 备注 |
|---|---|---|---|---|---|---|
| A1 | 预约状态机校验:PUT /appointment/status(及任意改状态入口)禁止非法迁移 |
仅允许:new→doing、new→cancel、doing→done、doing→cancel(与产品最终规则一致);非法迁移返回 4xx + 明确业务码(如 INVALID_STATUS、CANCEL_NOT_ALLOWED) |
Backend Core | 🟡 部分实现:AppointmentService.updateStatus/startService 已集中校验,但缺自动化测试 |
mvn -f backend/pom.xml test(待补 AppointmentServiceTest) |
与「谁点谁服务」一致;Batch D 补测试 |
| A2 | 开始服务仅当 status=new |
startService 非 new 时拒绝,勿静默改库 |
Backend Core | 🟡 部分实现:服务层已校验,需补测试 | 同 A1 | 与 A1 同一套状态机 |
| A3 | 取消预约校验:仅允许目标状态为 cancel 且前置状态符合产品规则 |
与 A1 同一套状态机;前端取消按钮仅 new 时展示则后端仍要防篡改 |
Backend Core | 🟡 部分实现:状态机已收口,需补测试 | 同 A1 | 防恶意请求 |
| A4 | 留资去重:同一 report_token + 同一手机号 |
二次提交返回成功态或「已提交」语义,不重复插库 | Report Media Backend | 🟡 部分实现:去重逻辑已存在,需补测试用例 | mvn -f backend/pom.xml test(待补 ReportLeadControllerTest) |
口径见《本期主线》C |
| A5 | 公开报告字段裁剪:GET /api/report/get?token= 不返回 top-level userId/storeId/reportToken;日志只记 token hash |
公开 token 请求只返回页面必要字段;store 对象可返回 id 用于预约跳转 |
System Architect / Report Media Backend | ✅ 已实现(Batch B) | 手工 curl + mvn test |
对应 P0-2 |
| A6 | 报告一约一份:Report.appointment_id 唯一约束;服务层拒绝同预约重复提交 |
同一 appointmentId 第二次提交返回 409 / REPORT_ALREADY_EXISTS;非 doing 预约不能创建报告;无预约提交返回 APPOINTMENT_REQUIRED |
System Architect / Data Model / Report Media Backend | ✅ 已实现(Batch B/D,含 ReportServiceTest/ReportControllerTest) |
mvn -f backend/pom.xml test |
对应 P0-3;上线前需清理重复数据 |
| A7 | 报告前后照片必填后端兜底 | 缺 before 返回 BEFORE_PHOTO_REQUIRED;缺 after 返回 AFTER_PHOTO_REQUIRED |
Report Media Backend | ✅ 已实现(Batch B,含 ReportControllerTest) |
mvn -f backend/pom.xml test |
与前端 B5 同步落地 |
| A8 | 统一鉴权上下文:HMAC session token + CurrentUserContext,protected API 不再信任请求里的身份字段 |
未登录返回 401;A 店用户访问 B 店预约/报告/线索返回 403;customer 不能用任意 userId 创建他人宠物/预约 |
System Architect / Backend Core | ✅ 已实现(Batch C,含 SessionTokenServiceTest) |
mvn -f backend/pom.xml test + 跨店/跨用户接口验证 |
对应 P0-1;不引入完整 Spring Security |
| A9 | 线索脱敏:/report/leads 默认不返回完整 wechatOpenid/wechatUnionid |
回包只有 wechatBound、wechatOpenidMasked、wechatUnionidMasked |
Report Media Backend | ✅ 已实现(Batch B) | 手工 curl + mvn test |
对应 P0-2 |
| A10 | 配置安全与启动迁移收口:application.yml 不保留真实敏感值;生产 profile 禁用 ddl-auto:update/show-sql;移除启动期 DDL/历史 UPDATE |
仓库不含真实 DB/微信密钥;生产启动只读环境变量 | Backend Ops / System Architect | ✅ 已实现(Batch D) | rg 扫描 + 启动验证 |
对应 P0-8;已暴露凭据需轮换 |
| A11 | 上传路径与类型保护:FileController 归一化路径 + 扩展名/MIME 校验 |
/api/upload/image/../...、伪装扩展名、超大文件均被拒绝 |
Backend Core / System Architect | ✅ 已实现(Batch D) | 手工 curl + mvn test |
对应 P0-9 |
| A12 | 最小测试基线:补 SessionTokenServiceTest、ReportServiceTest、ReportControllerTest、AppointmentServiceTest |
mvn test 不再输出 No tests to run,新增用例全部通过 |
Core Flow QA / System Architect | ✅ 已实现(Batch D) | mvn -f backend/pom.xml test |
对应 P0-10;持续回归数量以 Surefire 当次统计为准 |
| A13 | 预约/报告身份语义拆分:客户、创建人、服务技师、报告作者不得复用同一语义字段 | customer 自约身份从 session 派生;门店代约必须提供真实宠主;宠主报告按预约客户归属查询;legacy 字段只做兼容 | System Architect / Backend Core / Report Media Backend | ✅ 已实现(Phase 0 RC1 后) | mvn -f backend/pom.xml test + H5/小程序构建 |
迁移见 backend/db/migrations/20260801_split_service_identity.sql |
| A14 | StoreCustomer 门店客户主档:客户列表不再临时拼成无 ID 投影 | 预约/留资自动建档;同店账号与手机号唯一;API 返回 storeCustomerId 且手机脱敏;历史数据可回填 | Backend Core / Report Media Backend / Data Model | ✅ 已实现(待生产迁移) | mvn -f backend/pom.xml test + npm --prefix admin run build |
迁移见 backend/db/migrations/20260801_create_store_customer.sql |
B. 小程序 — 门店端(老板/员工)
| ID | 需求 | 验收标准 | Owner | 状态 | 验收命令 | 备注 |
|---|---|---|---|---|---|---|
| B1 | 「已完成」Tab 列表默认不含已取消 | Tab「已完成」下默认仅展示 status===done;cancel 通过次级筛选或单独子 TAB 实现 |
Store Miniapp FE | 🟡 部分实现(以现状为准做回归) | npm --prefix frontend run build:h5 + 手工 smoke |
当前 Home.vue 需对照 |
| B2 | 发送报告成功页:同屏 报告链接 + 二维码 + 两条可复制话术 | 话术支持变量:{宠物名}{服务类型}{门店名}{链接};一键复制单条话术 |
Store Miniapp FE | ✅ 已实现(ReportShareModal.vue) |
npm --prefix frontend run build:h5 + 手工 smoke |
对齐《本期主线》A |
| B3 | 报告提交锁死提示 | 提交前弹窗固定文案:「提交后不可修改,请确认照片与备注无误」 | Store Miniapp FE | 🟡 部分实现:核对文案与位置 | 手工 smoke | 与产品 v1 锁死策略一致 |
| B4 | 「我的」老板端分组标题 | 至少两组:店铺与经营 / 团队与账号;高频在上;使用 .module-title |
Store Miniapp FE | ✅ 已实现 | npm --prefix frontend run build:h5 + 手工 smoke |
见《产品全方位优化说明》§2.2 |
| B5 | 报告前后照片必填前端校验 | 无 before 提示「请至少上传1张服务前照片」;无 after 提示「请至少上传1张服务后照片」 | Store Miniapp FE / Customer Experience FE | ✅ 已实现(Batch A) | npm --prefix frontend run build:h5 + npm --prefix frontend run build:mp-weixin |
对应 A7、P0-4 |
C. 小程序 — 宠主端(customer)
| ID | 需求 | 验收标准 | Owner | 状态 | 验收命令 | 备注 |
|---|---|---|---|---|---|---|
| C1 | 单一主预约路径 | 首屏仅保留一个主级「预约服务」入口;不再同屏强并存「大按钮 + 空态大按钮 + FAB +」等效重复 | Customer Experience FE | 🟡 部分实现:需对照当前 Home.vue 复核 |
手工 smoke | 见《宠主端预约体验优化》§9 |
| C2 | 扫码 / 分享落地 storeId(含小程序码 scene 解码) |
普通 storeId query、小程序码 scene=storeId%3D1、分享 path/query 均预填门店且可「更换门店」 |
Customer Experience FE | ✅ 已实现(Batch A) | npm --prefix frontend run build:h5 + npm --prefix frontend run build:mp-weixin + 手工 smoke |
对应 P0-6、P1-1 |
| C3 | 登录时机与草稿(冻结策略:提交时登录 + guest 草稿恢复) | 未登录可填单,提交时跳登录,登录后草稿恢复;草稿 key 不依赖 userInfo.id;不会产生 userId: undefined |
Customer Experience FE / Backend Core | ✅ 已实现(Batch A) | 手工 smoke:未登录填写 → 提交跳登录 → 草稿恢复 | 与 Login.vue redirect 联动 |
| C4 | 异常可理解 | 无可用时段、网络失败、未登录:均有 toast / 空态 / 重试,禁止静默失败 | Customer Experience FE | 🟡 部分实现:需逐场景回归 | 手工 smoke | 专文 §7 |
| C5 | 报告页角色判断:isStaff 改为角色判断(boss/staff) |
customer 登录态打开公开报告页仍显示留资/预约 CTA;boss/staff 才显示内部分享/保存 | Customer Experience FE | ✅ 已实现(Batch A) | 手工 smoke | 对应 P0-7 |
D. H5 报告页(report-view / 独立 H5)
| ID | 需求 | 验收标准 | Owner | 状态 | 验收命令 | 备注 |
|---|---|---|---|---|---|---|
| D1 | 隐私提示(短期策略) | 首屏或固定条:「本页含宠物服务影像,请勿公开转发或发群」 | Customer Experience FE / Product Design | 🟡 部分实现:核对文案与位置 | 手工 smoke | 对齐《本期主线》A token 风险 |
| D2 | 短片三态与文案对齐小程序 | processing / failed / success 与 ReportHighlightBlock 一致;失败展示归类中文,不暴露堆栈 |
Customer Experience FE | 🟡 部分实现:需对照三态文案 | 手工 smoke | H5 与小程序报告页行为一致 |
| D3 | 弱网 / 失败重试 | 报告主接口失败:按钮「重新加载」;超时阈值 8~10s 后出失败态 | Customer Experience FE | 🟡 部分实现 | 手工 smoke | 与《产品全方位优化说明》§3.3 |
| D4 | 公开报告 token 使用方式:不依赖回包 reportToken,只用路由 token 做留资/分享 |
公开报告页 reminderToken = 路由 token;不读 reportData.reportToken |
Customer Experience FE | ✅ 已实现(Batch A) | 手工 smoke + 代码审查 | 与 A5 联动 |
E. 传播与埋点(P0 最小集)
| ID | 需求 | 验收标准 | Owner | 状态 | 验收命令 | 备注 |
|---|---|---|---|---|---|---|
| E1 | 分享卡片元信息规则 | 小程序 onShareAppMessage:标题「宠物名 + 服务 + 门店」;封面优先级 成片封面 > 服务后首图 > Logo |
Customer Experience FE | ✅ 已实现(reportShare.js) |
手工 smoke + 代码审查 | 见 frontend/src/utils/reportShare.js |
| E2 | 埋点:报告打开 | 上报:report_token 匿名 hash、首次/再次、时间戳;落地页 H5 亦要能报 |
Report Share QA / Backend Ops | 🟡 部分实现:日志已有,缺事件 schema 与统计落地 | 见《本期主线》埋点 schema 表 | 对应 P0-10、P1-4 |
| E3 | 埋点事件 schema(最小集) | 定义 report_open、report_reopen、highlight_success、highlight_failed、video_play、video_save、lead_submit 字段、来源、统计窗口 |
Report Share QA / Product Design | ✅ 已冻结(Batch A 文档) | 见《本期主线-下一步产品优化点》埋点 schema 表 | 对应 P1-4 |
F. 视觉与规范(工程债)
| ID | 需求 | 验收标准 | Owner | 状态 | 验收命令 | 备注 |
|---|---|---|---|---|---|---|
| F1 | 禁止业务页硬编码主色 | 主色/品牌浅底统一 var(--c-brand) 等;`rg "#16a34a |
#2db96d"业务 vue 内为 0(除global.css`/极少量渐变定义) |
Store Miniapp FE / Customer Experience FE | 🟡 部分实现 | `rg "#16a34a |
| F2 | 空态禁用 emoji 作主视觉 | 宠主空态等用 AppIcon 或插图占位,不用 📋 等作为主视觉 |
Customer Experience FE | 🟡 部分实现 | 代码审查 | 见 Home.vue 空态 slot |
G. 文案与对外承诺(配置级)
| ID | 需求 | 验收标准 | Owner | 状态 | 验收命令 | 备注 |
|---|---|---|---|---|---|---|
| G1 | 无容量模型不写「排队」 | 全局检索「排队」「不排队」;宠主副标题等改为「在线选时段,到店更省心」 | Product Design / Customer Experience FE | ✅ 已实现(Batch A 文档冻结) | `rg "到店不排队 | 不排队" docs frontend/src` |
| G2 | 对内录单表述(可选) | 门店端新建预约入口文案是否改为「代客预约」由产品拍板;若改则全局统一 | Product Design | 🟡 待产品拍板 | — | 降低「预约」歧义 |
H. 发布 RC 门禁(Batch D 收口)
| ID | 需求 | 验收标准 | Owner | 状态 | 验收命令 | 备注 |
|---|---|---|---|---|---|---|
| H1 | backend README RC 清单 | 含 ffmpeg -version、ffprobe -version、curl -I $APP_BASE_URL/api/upload/image/<known-file>、mvn test;写明 APP_BASE_URL、HIGHLIGHT_*、PETSTORE_SESSION_SECRET、上传目录权限、Nginx client_max_body_size |
Backend Ops | ✅ 已实现(Batch D) | 代码审查 | 对应 P0-10 |
| H2 | frontend README RC 清单 | 含 npm install、build:h5、build:mp-weixin;写明 VITE_API_ORIGIN、VITE_REPORT_PUBLIC_ORIGIN、微信 request/download 合法域名、报告二维码链接检查 |
Frontend Release Ops | ✅ 已实现(Batch D) | 代码审查 | 对应 P0-10 |
| H3 | P0 通过条件 | 见下方「P0 通过条件」块 | System Architect / Core Flow QA | 🟡 待人工 smoke 复核 | 见下方 | 对应 P0-10 |
建议排期顺序(供研发参考)
- A1~A3(后端状态机)— 防脏数据,优先合。
- B1(已完成 Tab)— 前端小改、用户感知强。
- B2、D1、D2、E1(传播与报告体验)— 主线门面。
- C1~C5(宠主)— 与登录/路由并行可排。
- E2、E3、F1、F2、G1 — 可并行或插空。
- A5~A12(后端边界、隐私、配置、上传、测试)— Batch B/C/D。
- H1~H3(发布 RC 门禁)— Batch D 收口。
P0 通过条件(最终门禁)
- 后端
mvn -f backend/pom.xml test有实际测试用例并通过(不再No tests to run)。 - 前端
npm --prefix frontend run build:h5与npm --prefix frontend run build:mp-weixin均通过。 - 公开报告页 token 匿名可打开,且不返回 top-level
userId/storeId/reportToken。 - boss/staff 登录后可生成报告、发送报告、查看回访池。
- customer 登录态打开报告仍显示留资和预约 CTA。
- 同一
appointmentId第二次提交报告返回REPORT_ALREADY_EXISTS。 - 报告前后照片缺失返回对应业务码。
- A 店 boss/staff 不能查 B 店 leads/list/report;customer 不能用任意
userId创建他人宠物/预约。 - 生产配置扫描不含真实 DB/微信密钥,无
ddl-auto:update,无宽 CORS。 - 文档口径扫描:
rg "到店不排队|会员储值 \| 路线图 P0|宠主通过微信查看服务报告(v2)|无限制,随便选" docs无命中。
不在 P0(勿与本清单混排)
- 会员卡 / 储值 / 次卡 / 套餐(P1/P2)
- 宠主账号内历史报告汇总(P2)
- 报告 token 作废重发(中期,见 D3 决策)
- 多技师分成、排班深度联动
- 复杂数据看板、漏斗大屏
- 分包优化(可 P1)
评审后可将本页 ID 勾进看板;与专文冲突以迭代评审为准。