petstore-docs/门店管理后台-PhaseA-页面清单PRD.md
2026-08-01 21:56:07 +08:00

461 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 门店 Web 后台 · Phase A 页面清单 PRD
> 状态:产品草案(仅文档,未编码)
> 日期2026-07-10
> 上游:`docs/门店管理后台升级方案-对标宠老板.md`
> 本体闸门:`rule:BR-ADMIN-004`(禁止会员卡/储值/收银/库存/寄养/押金/点餐偷渡)
> 证据:本 PRD 描述的页面均为 `documented`;实现后升 `anchored`
---
## 0. 文档约定
### 0.1 目标与非目标
| 目标 | 非目标Phase A |
|------|-------------------|
| 老板用 PC 完成:看今日待办 → 管预约 → 管报告/成片链接 → 处理留资 → 改门店设置 | 收银、库存、寄养、会员升降级、次卡储值、押金、点餐、支付宝渠道、连锁同步 |
| 与小程序共用同一套业务规则与 `/api/**` | 另造第二套状态机 |
| 每页可追溯 `ontologyRefs` | 经营大盘 sparkline / 埋点统计闭环(属 Phase B |
### 0.2 角色与范围
| 规则 | 本体 |
|------|------|
| 仅门店角色进入后台;**boss 与 staff 均可读写**customer 禁止) | `rule:BR-ADMIN-001` |
| 全部数据强制 `current.storeId` | `rule:BR-ADMIN-002` |
| 后台可看公开 API 裁剪掉的内部字段;手机号默认脱敏 | `rule:BR-ADMIN-003` |
| 范围闸门 | `rule:BR-ADMIN-004` |
`staff``boss` 在 Phase A **同等可编辑**本店数据;差异仅保留现网已有规则(例:删店、部分设置仅 boss——见设置页与 `rule:BR-STORE-001` / `rule:BR-USER-001`)。
### 0.3 端分工
| 场景 | 载体 |
|------|------|
| 拍照、填报告、现场履约 | **小程序**(既有) |
| 开始服务 | **小程序与 Web 均可**(同 `POST /api/appointment/start` |
| 检索、复制链接、回访、改设置、看今日全局 | **Web 后台**(本 PRD |
### 0.4 信息架构(锁定)
```text
entity:admin_console
├── /workbench 今日工作台(登录落点)
├── /appointments 预约中心
├── /schedule 排班占用
├── /reports 服务报告
├── /leads 回访线索
├── /customers 服务客户
└── /settings 门店设置(资料 / 服务类型 / 员工)
```
侧栏不出现:收银台、库存、寄养、会员卡、次卡、积分、营销中心、微信商城。
### 0.5 全局交互范式(从对标截图借鉴)
1. 列表页:筛选区 + 查询/重置 +(可选)汇总条 + 表格
2. 搜索合一:姓名 / 手机 / 宠物名(客户页)
3. 手机号列表默认脱敏
4. 敏感操作弹窗带规则提示(若有)
5. 工作台待办可下钻并带筛选
---
## 1. 登录与壳层
**页面 ID**`A0-shell`
**路由**`/*`(布局)
**ontologyRefs**`[entity:admin_console, entity:current_user, entity:session_token, rule:BR-ADMIN-001, rule:BR-ADMIN-002, rule:BR-AUTH-001]`
| 项 | 说明 |
|----|------|
| 登录 | 复用现有 `sessionToken`(老板微信登录 / 现网登录策略);无 token → 登录页 |
| 壳层 | 左导航 + 顶栏(店名、角色、退出)+ 内容区 |
| 退出 | 清本地 token服务端吊销为 `action:logout` gapA 期不做 |
| 无权限 | customer token 访问 → 403 文案「请使用老板账号登录」 |
**API 复用**`GET /api/user/info``action:get_user_info`
---
## 2. 今日工作台
**页面 ID**`A1-workbench`
**路由**`/workbench`(默认首页)
**ontologyRefs**`[entity:workbench, entity:workbench_todo_item, action:view_workbench, action:drilldown_workbench_todo, event:workbench_viewed, rule:BR-ADMIN-001, rule:BR-ADMIN-002, rule:BR-ADMIN-004]`
### 2.1 布局
```text
顶栏 4 指标卡
今日待办条(或登录弹层关闭后的常驻摘要)
报告漏斗四格(可先占位「—」)
异常列表(成片失败 / 待回访 最近 5 条)
右侧:门店卡片(店名、营业时段摘要、员工数)+ 帮助链接
```
### 2.2 顶栏指标卡
| 卡 | 口径 | 点击下钻 |
|----|------|----------|
| 今日预约 | 今日 `appointmentTime` 落在当天的预约数(含各状态) | `/appointments?date=today` |
| 今日完成 | 今日变为 `done` 的预约数 | `/appointments?status=done&date=today` |
| 待回访 | `remind_status=pending``remindDate≤今天` | `/leads?due=today` |
| 成片失败 | 本店报告 `highlight_video_status=failed`(可限近 7 日) | `/reports?highlightStatus=failed` |
### 2.3 今日待办(弹层 + 常驻)
| kind | 文案 | count 口径 | 下钻 |
|------|------|------------|------|
| `today_appointments` | 今日预约 | 同「今日预约」卡,可分子状态:待开始 / 服务中 | 预约列表 |
| `pending_report` | 待出报告 | `status=doing` 且尚无报告 | 预约列表 `status=doing&missingReport=1` |
| `highlight_anomaly` | 成片异常 | `failed` + 可选 `processing` 超时(阈值产品定,默认 30min | 报告列表 |
| `pending_lead` | 待回访 | 同「待回访」卡 | 线索列表 |
弹层:首次进入当日可弹;勾选「今日不再提醒」写入 localStorage「确定」关闭。
**不对标宠老板**:寄养、临期商品、库存、待发货、售后。
### 2.4 报告漏斗四格(差异化)
| 格 | 口径 | A 期无埋点时 |
|----|------|----------------|
| 今日已发报告 | 今日新建报告数 | 可算 |
| 已打开 | `report_open` 去重 | 显示「—」,链到 B1 说明 |
| 已留资 | 今日新增 lead | 可算 |
| 报告转预约 | 从报告页带来的预约 | 无可靠归因则「—」 |
### 2.5 API / 聚合
优先前端或 BFF 聚合现有接口;若延迟高,再补 `GET /api/admin/workbench`(实现时同步本体)。
复用候选:`/api/appointment/list`、`/api/report/list`、`/api/report/leads`、`/api/store/get`(后台可用内部字段,`BR-ADMIN-003`)。
### 2.6 验收
- [ ] 老板登录后默认进入工作台
- [ ] 四指标与待办数字与列表下钻一致
- [ ] 待办不含库存/寄养类卡片
- [ ] customer 无法打开
- [ ] **staff 与 boss 均可进入并操作本店工作台**
---
## 3. 预约中心
**页面 ID**`A2-appointments`
**路由**`/appointments`
**ontologyRefs**`[entity:appointment, action:admin_list_appointments, action:start_service, action:transition_appointment_status, action:get_appointment_detail, rule:BR-APPT-001, rule:BR-APPT-002, rule:BR-APPT-003, rule:BR-ADMIN-001, rule:BR-ADMIN-002]`
### 3.1 筛选
| 筛选项 | 说明 |
|--------|------|
| 日期 | 单日 / 区间;支持 `today` |
| 状态 | `new` / `doing` / `done` / `cancel` / 全部 |
| 技师 | 本店 staff/boss 列表(可空=全部) |
| 关键词 | 宠主名 / 手机 / 宠物名(若现网 list 不支持A 期可先前端滤或补 query |
| 待出报告 | `doing` 且无报告(工作台下钻) |
### 3.2 列表列
| 列 | 说明 |
|----|------|
| 预约时间 | |
| 状态 | 文案:待开始 / 服务中 / 已完成 / 已取消 |
| 宠主 | 名 + 脱敏手机 |
| 宠物 | 名 / 类型 |
| 服务类型 | |
| 技师 | `assignedUser` 显示名 |
| 报告 | 无 / 有(链到报告详情或报告中心) |
| 操作 | 详情;**开始服务**`new`→调 `POST /api/appointment/start`Web 可点);`new`/`doing`→取消(规则同现网) |
> **产品决策2026-07-10**Web 上允许「开始服务」。拍照/填报告仍引导回小程序;开始服务本身不强制跳转。
### 3.3 详情抽屉/页
只读为主:预约字段、状态流转记录(若无则只显示当前状态)、关联报告入口。
**不在 Web 做拍照填报告**(回小程序)。
### 3.4 状态机(禁止另造)
仅允许:`new→doing`、`new→cancel`、`doing→done`(由提交报告触发)、`doing→cancel`(若产品允许)。
非法迁移返回现网业务码。本体:`rule:BR-APPT-001`。
### 3.5 API 复用
- `GET /api/appointment/list`
- `GET /api/appointment/detail`
- `POST /api/appointment/start`**Web 可调用**
- `PUT /api/appointment/status`
### 3.6 验收
- [ ] 筛选 + 下钻参数生效
- [ ] 跨店数据不可见
- [ ] 非法状态迁移被拒
- [ ] **staff / boss 均可在 Web 点击「开始服务」并成功 `new→doing`**
- [ ] 无「待门店确认接单」状态(与宠老板差异,保持宠小它口径)
---
## 4. 排班占用
**页面 ID**`A6-schedule`
**路由**`/schedule`
**ontologyRefs**`[entity:schedule_block, entity:appointment, action:admin_manage_schedule, action:day_agenda, action:create_schedule_block, action:delete_schedule_block, rule:BR-SCH-001, rule:BR-ADMIN-001, rule:BR-ADMIN-002]`
### 4.1 视图
- 日视图时间轴(半小时档)
- 叠加:线上预约占用 + `walk_in` / `blocked` 手动占用
- 操作:新增占用、删除本店占用;不可改他店
### 4.2 API 复用
- `GET /api/schedule/day`
- `POST /api/schedule/block`
- `DELETE` 对应删除接口
### 4.3 验收
- [ ] 与小程序号源占用一致
- [ ] staff/boss 同店可操作;跨店 403
---
## 5. 服务报告
**页面 ID**`A3-reports`
**路由**`/reports`
**ontologyRefs**`[entity:report, entity:highlight_video, entity:highlight_fail_reason, action:admin_list_reports, action:generate_highlight, action:get_report_by_token, rule:BR-RPT-002, rule:BR-RPT-005, rule:BR-RPT-006, rule:BR-HL-001, rule:BR-HL-002, rule:BR-ADMIN-001, rule:BR-ADMIN-002, rule:BR-ADMIN-003]`
### 5.1 筛选
日期、成片状态(`processing` / `done` / `failed` / 全部)、关键词(宠物名/宠主)
### 5.2 列表列
| 列 | 说明 |
|----|------|
| 提交时间 | |
| 预约时间 / 宠物 / 服务 | |
| 成片状态 | 三态 + 失败原因短标签(`HighlightFailReason` |
| 操作 | 详情;复制公开链接;失败/可重试时「重新生成」 |
### 5.3 详情
- 报告公开页预览入口(新开 H5
- 前后/过程媒体缩略图(只读)
- 成片播放(若 `done`
- 复制 `report_token` 链接(完整 token 仅后台展示,日志仍 hash`BR-RPT-007`
- **不在此页改报告正文**(报告提交后锁死,`BR-RPT-*`
### 5.4 API 复用
- `GET /api/report/list`
- `GET /api/report/get`(后台带鉴权,可内部字段)
- `POST /api/report/highlight/start`
### 5.5 验收
- [ ] 成片三态与失败文案无技术词
- [ ] 复制链接可用;公开页仍受 `BR-RPT-006` 裁剪
- [ ] 仅 boss/staff 可触发成片(`BR-HL-001`
---
## 6. 回访线索
**页面 ID**`A4-leads`
**路由**`/leads`
**ontologyRefs**`[entity:report_lead, action:admin_list_leads, rule:BR-LEAD-001, rule:BR-LEAD-002, rule:BR-LEAD-003, rule:BR-ADMIN-001, rule:BR-ADMIN-002]`
### 6.1 筛选
`remindStatus`pending / 全部)、到期(≤今天)、日期区间
### 6.2 列表列
宠物名、服务、脱敏手机、建议日期、状态、微信绑定(是/否 + 脱敏 openid 若有)、操作:查看关联报告公开页
### 6.3 不做A 期)
跟进备注 CRM、短信群发、改等级、发券
### 6.4 API 复用
- `GET /api/report/leads`
### 6.5 验收
- [ ] 无完整 openid/unionid
- [ ] 跨店 403
- [ ] 工作台「待回访」下钻数字一致
---
## 7. 服务客户
**页面 ID**`A5-customers`
**路由**`/customers`
**ontologyRefs**`[entity:store_customer, entity:pet, entity:user, action:admin_list_service_customers, rule:BR-SC-001, rule:BR-ADMIN-001, rule:BR-ADMIN-002, rule:BR-ADMIN-003, rule:BR-ADMIN-004]`
### 7.1 定位
服务经营客户投影,**不是**会员资产台账。
### 7.2 筛选与搜索
| 项 | 说明 |
|----|------|
| 来源 | 全部 / 预约 / 报告留资 |
| 有待回访 | 开关 |
| 最近到店 | 日期区间 |
| 搜索 | 姓名 / 手机 / 宠物名 |
### 7.3 汇总条
`客户数` · `待回访数` · `本月到店数`
**禁止**:总余额、押金、积分
### 7.4 列表列
客户(头像/名/脱敏手机)| 宠物(标签,多宠)| 最近到店 | 最近报告 | 留资状态 | 来源 | 操作(详情 / 报告 / 回访)
### 7.5 详情
基础信息、宠物列表、最近预约、最近报告、相关线索。
**不做**:充值、改会员等级、导入持卡会员、次卡。
### 7.6 API产品决策新 API
**新建**聚合接口(实现时同步本体 `anchored`
```text
GET /api/admin/service-customers
Query: source, hasPendingLead, lastVisitFrom, lastVisitTo, q, page, pageSize
Auth: boss | staffstoreId=current.storeId
Response: { total, summary: { customerCount, pendingLeadCount, monthVisitCount }, list: StoreCustomerView[] }
```
`StoreCustomerView` 必含稳定 `storeCustomerId`,并包含 `userId?`、`displayName`、`phoneMasked`、`originSource`、`firstContactAt`、`lastContactAt`、`pets`、`lastVisitAt`、`lastReportId`、`leadStatus`、`source`。明文手机号不得返回。
- 对应动作:`action:admin_list_service_customers`
- 对应实体:`entity:store_customer`
- **不做**前端拼装多接口作为正式方案(可临时 mock上线以新 API 为准)
可选后续:`GET /api/admin/service-customers/{storeCustomerId}` 详情。
### 7.7 验收
- [ ] 无余额/次卡/积分列与汇总
- [ ] 搜索含宠物名
- [ ] 侧栏无「会员卡/次卡」入口
---
## 8. 门店设置
**页面 ID**`A7-settings`
**路由**`/settings`Tab资料 | 服务类型 | 员工)
**ontologyRefs**`[entity:store, entity:service_type, entity:user, action:admin_update_settings, rule:BR-STORE-001, rule:BR-STORE-003, rule:BR-ST-001, rule:BR-USER-001, rule:BR-ADMIN-001, rule:BR-ADMIN-002, rule:BR-ADMIN-003]`
### 8.1 资料 Tab
字段名称、电话、地址、坐标、简介、logo、`bookingDayStart` / `bookingLastSlotStart`
后台可显示 `inviteCode``BR-ADMIN-003`);公开 `GET /api/store/get` 仍裁剪(`BR-STORE-003`
API`GET/PUT` 现有 store 接口
### 8.2 服务类型 Tab瘦身表单
| 字段 | 必填 |
|------|------|
| 名称 | ✓ |
| 适用宠物:不限/猫/犬 | 若字段未上线A 期可先只做名称+排序+启用 |
| 排序 | |
| 预约可选(启用) | |
| 备注 | |
**不做**:多规格、价格、条码、押金、商城上架、富文本(见对标 §11.8
系统默认类型不可改删(`BR-ST-001`
API现有 `service-type/*`
### 8.3 员工 Tab
列表、创建员工、删除(仅 boss同店
展示邀请码(来自门店)供复制
API`user/staff-list`、`create-staff`、删除接口
### 8.4 验收
- [ ] 改营业时段后号源边界变化(与小程序一致)
- [ ] 公开门店接口仍无 inviteCode
- [ ] 服务类型表单无价格字段
---
## 9. 页面—本体—API 总表
| 页面 | 主 Action | 主 Entity | 主要复用 API |
|------|-----------|-----------|--------------|
| A0 壳层 | `get_user_info` | `admin_console` | `/api/user/info` |
| A1 工作台 | `view_workbench` | `workbench` | list 聚合 |
| A2 预约 | `admin_list_appointments` | `appointment` | `/api/appointment/*` |
| A6 排班 | `admin_manage_schedule` | `schedule_block` | `/api/schedule/*` |
| A3 报告 | `admin_list_reports` | `report` / `highlight_video` | `/api/report/*` |
| A4 线索 | `admin_list_leads` | `report_lead` | `/api/report/leads` |
| A5 客户 | `admin_list_service_customers` | `store_customer` | **已实现** `GET /api/admin/service-customers` |
| A7 设置 | `admin_update_settings` | `store` / `service_type` / `user` | store/service-type/user |
---
## 10. 实现分期建议(仍属 Phase A 内)
| 迭代 | 交付 | 说明 |
|------|------|------|
| A.1 | 壳层 + 工作台 + 预约列表/详情 | 登录落点可用 |
| A.2 | 报告中心 + 线索 | 差异化闭环 |
| A.3 | 客户瘦身列表 + 排班 + 设置 | MVP 验收全集 |
编码前须:声明 Owner`Store Admin FE` + `Backend Core`、Service Lock、Paired QA、写入 `.agents` 角色锁。
---
## 11. 验收剧本(端到端)
1. 老板登录 → 默认工作台,见今日待办
2. 点「待出报告」→ 预约列表仅 doing 且无报告
3. 打开某已完成单的报告 → 复制公开链接 → 无痕浏览器打开,字段符合公开裁剪
4. 线索页处理一条待回访(至少能打开关联报告)
5. 设置里改营业结束时间并保存 → 小程序号源反映变化
6. 全程无会员余额/收银/库存入口
---
## 12. 开放问题(已决策)
| # | 问题 | 决策2026-07-10 |
|---|------|-------------------|
| Q1 | staff 是否可登录后台? | **可进且可编辑**(与 boss 同店读写;删店等仍仅 boss |
| Q2 | Web 上是否允许「开始服务」? | **允许**;拍照/填报告仍回小程序 |
| Q3 | 客户列表前端聚合还是新 API | **新 API**`GET /api/admin/service-customers` |
| Q4 | `processing` 超时多久算异常? | **30 分钟**(已锁定) |
| Q5 | 技术选型Vue/React admin | **推荐** Vue3+Vite+Element Plus + `admin/`,见 `docs/门店管理后台-技术选型草案.md`(编码前口头确认) |
---
## 13. 修订记录
| 日期 | 说明 |
|------|------|
| 2026-07-10 | 首版:基于本体 admin 预录入 + 宠老板对标结论 |
| 2026-07-10 | 决策落地staff 可编辑Web 可开始服务;客户列表新 API |
| 2026-07-10 | 线框/选型/编码 brief 已出Q4=30minQ5 推荐 Vue3 admin |
| 2026-07-10 | 编码启动:`admin/` MVP + `GET /api/admin/service-customers` |