Files
dukang/杜康好客-门店套餐功能开发文档-v3.4.10.md
T
2026-08-04 21:38:49 +08:00

373 lines
12 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.
# 杜康好客 · 门店套餐功能开发文档
> **版本**3.4.10
> **日期**2026-08-03
> **状态**:需求已定 / 待实现
> **关联**[`杜康好客-v3-PRD.md`](./杜康好客-v3-PRD.md) §3.9 · REQ-P-027 / REQ-S-021 / REQ-H-025 / REQ-U-027
## 变更记录
| 版本 | 日期 | 说明 |
|------|------|------|
| **3.4.10** | 2026-08-03 | 新增门店套餐需求与开发设计 |
---
## 目录
1. [背景与目标](#1-背景与目标)
2. [数据模型](#2-数据模型)
3. [API 草案](#3-api-草案)
4. [四端 UI](#4-四端-ui)
5. [审核与展示状态机](#5-审核与展示状态机)
6. [客服「套餐异议」](#6-客服套餐异议)
7. [验收清单(ACC](#7-验收清单acc)
8. [实现分期建议](#8-实现分期建议)
### 流程概览
```mermaid
flowchart LR
partnerEdit[PartnerOrShopEdit]
draft[PackageChangeRequest]
hqReview[HqApproveOrReject]
live[LiveStorePackages]
mini[MiniStoreDetail]
dispute[PackageDisputeTicket]
partnerEdit --> draft
draft --> hqReview
hqReview -->|APPROVED| live
live --> mini
mini --> dispute
hqDirect[HqDirectSave] --> live
```
---
## 1. 背景与目标
门店可向 C 端用户展示餐饮套餐信息,帮助用户在核销前了解可核销内容。套餐与酒水 SKU 无关,需独立数据模型与审核流。
### 1.1 需求原文(10 条)
1. **合伙人新建门店**:在现有拓店流程(基本信息 / 照片 / 结算资质)后增加「套餐」页;可不填、可跳过。
2. **套餐字段**:套餐名称、价格(元)、菜品、使用时间、其他说明。
3. **C 端门店详情**:在「门店详情」区块附近,以纵向列表展示套餐;每条为「标题 + 内容」形式。
4. **数量约束**:可不填;可多条;**同一门店最多 10 条**。
5. **门店端**:新增套餐列表页,可编辑并**提交审核**。
6. **合伙人端**:选择门店 → 套餐列表 → 编辑 → **提交审核**
7. **总部端**:门店详情新增「套餐」Tab,**直接保存生效、无需审核**。
8. **审核流**:合伙/门店提交 → 总部通过/驳回;**通过后自动替换生效套餐**。
9. **C 端展示**:仅展示**已审核通过(生效中)**的套餐。
10. **客服异议**:用户对核销中套餐有异议 → 客服申诉类型新增 **套餐异议**
### 1.2 现状对齐
| 现状 | 影响 |
|------|------|
| 无门店套餐实体;`Store.tags` Json 未承载套餐 | 需新建表,不复用酒水 SKU |
| 合伙人拓店三步:基本信息 / 照片 / 结算资质 | 新增「套餐」页(第 4 步或独立页) |
| 门店端仅改营业状态,**无资料编辑 API** | 需新增门店端套餐 CRUD + 提审 API |
| 门店审核仅 `NEW`/`RESUBMIT` 整店审,**无「套餐变更」独立审核** | 需独立「套餐变更审核」模型 |
| 售后工单四类型无「套餐异议」 | 扩展工单/客服类型 |
| C 端详情已有 intro / 权益规则 / 环境图 | 在「门店详情」区块附近增加套餐纵向列表 |
### 1.3 明确不做(本文档阶段)
- 不改 Prisma / 不写 API / 不改四端业务代码(本文档仅设计)
- 不把套餐挂到商品目录 `CommonProductItem`
- 不合并进整店 `Store.auditStatus`(套餐变更独立提审)
---
## 2. 数据模型
### 2.1 生效数据 `StorePackage`(表名 `store_package`
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String (cuid) | 主键 |
| `storeId` | String | 门店 IDFK → `Store` |
| `name` | String | 套餐名称,如「套餐A」 |
| `price` | Decimal | 价格(元) |
| `dishes` | Text | 菜品文案;前端按顿号/换行展示;或 Json 字符串数组 |
| `usableTime` | String? | 使用时间,如「节假日除外」 |
| `otherNotes` | String? | 其他说明,如「不可叠加」 |
| `sortOrder` | Int | 展示序 0~9 |
| `createdAt` | DateTime | |
| `updatedAt` | DateTime | |
**约束**
- 同一 `storeId` 下生效套餐 **≤ 10** 条
- 删除/替换由审核通过或总部直存事务完成
### 2.2 变更提审 `StorePackageChangeRequest`(表名 `store_package_change_request`
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | String (cuid) | 主键 |
| `storeId` | String | 门店 ID |
| `status` | Enum | `PENDING` / `APPROVED` / `REJECTED` |
| `packagesJson` | Json | 提审快照(完整套餐数组,最多 10 条) |
| `submitterType` | Enum | `PARTNER` / `SHOP` |
| `submitterId` | String | 提交人 ID |
| `rejectReason` | String? | 驳回原因 |
| `reviewedAt` | DateTime? | |
| `reviewerId` | String? | 总部审核人 |
| `createdAt` | DateTime | |
**规则**
- 同门店同时仅允许 **一条 `PENDING`**
- 审核 **通过**:事务内删除该店全部 `StorePackage`,按 `packagesJson` 重建
- 审核 **驳回**:不改动生效表;提审方可修改后再提
### 2.3 提审快照 JSON 结构(`packagesJson` 数组元素)
```json
{
"name": "套餐A",
"price": "198.00",
"dishes": "红烧肉、红烧鱼、油焖茄子",
"usableTime": "节假日除外",
"otherNotes": "不可叠加",
"sortOrder": 0
}
```
### 2.4 总部直存
-`StorePackage`**不写** `StorePackageChangeRequest`
- 可选记 `CommonEvent`(如 `STORE_PACKAGE_UPDATE`)留痕
### 2.5 枚举(建议写入 `packages/shared-types`
```typescript
enum StorePackageChangeStatus {
PENDING = 'PENDING',
APPROVED = 'APPROVED',
REJECTED = 'REJECTED',
}
enum StorePackageSubmitterType {
PARTNER = 'PARTNER',
SHOP = 'SHOP',
}
// 扩展工单类型
enum TicketType {
// ...existing
PACKAGE_DISPUTE = 'PACKAGE_DISPUTE',
}
```
---
## 3. API 草案
> 路径前缀均为 `/api/v1`;响应 `{ code, message, data }`。
### 3.1 合伙人端
| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/partner/stores/:storeId/packages` | 读草稿/生效套餐(见实现约定) | 管辖门店 |
| PUT | `/partner/stores/:storeId/packages` | 提交套餐变更审核(body=套餐数组) | 管辖门店 |
| GET | `/partner/stores/:storeId/package-change-requests` | 历史提审记录 | 管辖门店 |
**拓店草稿**:新建流程中套餐可先写入 `storeDraft.packages`,门店创建成功后随首次提审或总部审核入库。
### 3.2 门店端(新增能力)
| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/shop/store/packages` | 当前门店套餐(草稿+生效) | 门店主账号/店员 |
| PUT | `/shop/store/packages` | 提交套餐变更审核 | 门店主账号 |
> 现状:门店端无资料编辑 API,本模块为 **新增** Shop Store API。
### 3.3 总部端
| 方法 | 路径 | 说明 | 权限 |
|------|------|------|------|
| GET | `/admin/stores/:storeId/packages` | 读生效套餐 | HQ |
| PUT | `/admin/stores/:storeId/packages` | **直存**生效(无需审核) | HQ |
| GET | `/admin/store-package-audits` | 待审/历史列表 | HQ |
| PUT | `/admin/store-package-audits/:requestId/audit` | 通过/驳回 | HQ |
**审核 body 示例**
```json
{
"action": "APPROVE"
}
```
```json
{
"action": "REJECT",
"rejectReason": "价格描述不清晰"
}
```
### 3.4 C 端(公开)
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | `/stores/:storeId` | 门店详情 **嵌入** `packages[]`(仅生效) |
| GET | `/stores/:storeId/packages` | 可选独立接口,仅返回生效套餐 |
**响应字段(单条)**
```json
{
"name": "套餐A",
"price": "198.00",
"dishes": "红烧肉、红烧鱼、油焖茄子",
"usableTime": "节假日除外",
"otherNotes": "不可叠加",
"sortOrder": 0
}
```
### 3.5 客服异议
扩展创建售后/客服工单:
| 字段 | 说明 |
|------|------|
| `ticketType` | `PACKAGE_DISPUTE` |
| `storeId` | 必填 |
| `redeemRecordId` | 可选,关联核销单 |
---
## 4. 四端 UI
### 4.1 合伙人端(H5
| 页面 | 路径建议 | 说明 |
|------|----------|------|
| 拓店·套餐 | `/stores/create/packages` | 第 4 步;可跳过;数据进 `storeDraft` |
| 门店详情·套餐入口 | 门店详情页 | 跳转套餐列表 |
| 套餐列表 | `/stores/:id/packages` | 展示当前生效 + 待审状态 |
| 套餐编辑 | `/stores/:id/packages/edit` | 表单:名称/价格/菜品/时间/说明;最多 10 条 |
| 提交审核 | 编辑页底部 | PUT 提审;同店有 PENDING 时禁用 |
参考:`apps/h5-partner/src/pages/StoreCreatePage.tsx`
### 4.2 门店端(H5
| 页面 | 路径建议 | 说明 |
|------|----------|------|
| 套餐列表 | `/packages` | 新入口(门店信息 Tab 或独立菜单) |
| 套餐编辑 | `/packages/edit` | 同合伙人表单 |
| 提交审核 | 编辑页底部 | PUT `/shop/store/packages` |
### 4.3 总部端(admin-web
| 页面 | 说明 |
|------|------|
| 门店详情 Drawer · Tab「套餐」 | 在 `StoresPage.tsx` Drawer 增加 Tab;表单直存 |
| 套餐变更审核列表 | 独立页或门店内待审提示;通过/驳回 |
参考:`apps/admin-web/src/pages/StoresPage.tsx`
### 4.4 用户端(mini-user
| 位置 | 说明 |
|------|------|
| 门店详情 · 「门店详情」区块上方或下方 | 纵向卡片列表 |
| 单条样式 | 标题 = 套餐名;内容 = 价格 / 菜品 / 使用时间 / 其他说明 |
| 空态 | 无生效套餐时不展示该区块 |
参考:`apps/mini-user/src/pages/store-detail/index.tsx`
### 4.5 C 端展示示例
```
套餐A
198 元 · 红烧肉、红烧鱼、油焖茄子
使用时间:节假日除外
说明:不可叠加
```
---
## 5. 审核与展示状态机
```mermaid
stateDiagram-v2
[*] --> NoLive: 从未通过
NoLive --> Live: 首次审核通过 / 总部直存
Live --> Pending: 合伙/门店提审
Pending --> Live: 审核通过(覆盖)
Pending --> Live: 审核驳回(保留旧 Live
Live --> Live: 总部直存(覆盖)
```
| 状态 | C 端展示 | 编辑方可见 |
|------|----------|------------|
| 无生效套餐 | 不展示套餐区块 | 可编辑、可提审 |
| 有生效 + 无待审 | 展示生效版 | 可编辑、可提审 |
| 有生效 + 待审中 | **仍展示上一版生效** | 显示「审核中」;不可重复提审 |
| 审核通过 | 展示新版 | 可再次编辑提审 |
| 审核驳回 | 仍展示旧版 | 可修改后再提;展示驳回原因 |
---
## 6. 客服「套餐异议」
| 项 | 说明 |
|----|------|
| 类型文案 | 套餐异议 |
| 枚举 | `PACKAGE_DISPUTE` |
| 入口 | C 端核销相关页 / 门店详情 / 客服页可选该类型 |
| 关联 | `storeId` 必填;可选 `redeemRecordId` |
| 总部 | 客服工单列表可按类型筛选处理 |
与现有四类型工单并列,不替换原有类型。
---
## 7. 验收清单(ACC
| ID | 对应需求 | 验收项 |
|----|----------|--------|
| ACC-PKG-01 | #1 | 合伙人拓店流程有「套餐」页,可跳过;跳过后门店可无套餐 |
| ACC-PKG-02 | #2 | 单条套餐含名称、价格、菜品、使用时间、其他说明五字段 |
| ACC-PKG-03 | #3 | C 端门店详情以纵向标题+内容展示套餐 |
| ACC-PKG-04 | #4 | 同一门店生效套餐 ≤10;第 11 条保存/提审被拒绝 |
| ACC-PKG-05 | #5 | 门店端可列表、编辑、提交审核 |
| ACC-PKG-06 | #6 | 合伙人可选门店、编辑套餐、提交审核 |
| ACC-PKG-07 | #7 | 总部门店详情「套餐」Tab 直存后 C 端立即可见(无需审核) |
| ACC-PKG-08 | #8 | 合伙/门店提审 → 总部通过后生效表被完整替换;驳回后生效表不变 |
| ACC-PKG-09 | #9 | C 端 never 展示未通过/待审套餐;提审中仍展示旧版 |
| ACC-PKG-10 | #10 | 用户可创建「套餐异议」工单;总部可按类型筛选 |
| ACC-PKG-11 | — | 同门店仅一条 PENDING;重复提审返回业务错误 |
| ACC-PKG-12 | — | 空套餐数组提审合法;通过后 C 端不展示套餐区块 |
| ACC-PKG-13 | — | 总部直存记事件或审计日志(若启用 CommonEvent |
---
## 8. 实现分期建议
| 阶段 | 范围 | 交付 |
|------|------|------|
| **M1** | 表结构 + 总部直存 + C 端展示 | Prisma 迁移、`StorePackage` CRUDadmin)、mini-user 展示 |
| **M2** | 合伙人新建/编辑提审 + 总部审核 | `StorePackageChangeRequest`、partner 页面、admin 审核 |
| **M3** | 门店端提审 | Shop API + h5-shop 页面 |
| **M4** | 套餐异议工单类型 | `PACKAGE_DISPUTE` 枚举、C 端入口、admin 筛选 |
---
## 附录:REQ 映射
| REQ | 端 | 内容 |
|-----|----|------|
| REQ-P-027 | 合伙人 | 拓店套餐页 + 门店套餐列表/编辑/提审 |
| REQ-S-021 | 门店 | 套餐列表/编辑/提审 |
| REQ-H-025 | 总部 | 门店详情套餐 Tab 直存;套餐变更审核通过/驳回 |
| REQ-U-027 | 用户 | 门店详情展示生效套餐;套餐异议申诉入口 |