Files
dukang/docs/杜康好客-v3.4.17-门店套餐审核快捷入口.md
T
2026-08-19 16:20:33 +08:00

6.8 KiB
Raw Blame History

杜康好客 · v3.4.17 门店套餐审核快捷入口

2026-08-16 · PRD §套餐变更审核 · admin-web / API(ops) 目标:把「套餐变更审核」能力前置到门店详情-套餐页签门店列表操作栏,让总部在不离开列表/详情流的情况下即可发现待审套餐并一键进入审核(含线上 vs 待审对照)。

范围

交付
A. 门店详情·套餐页签 待审提醒 存在 status=PENDING 的套餐变更时,页签顶部黄色 Alert + 「审核 / 对比」按钮
B. 审核 / 对比 跳转 复用现有 StorePackageAuditsPage,跳转 /store-package-audits?requestId=xxx 自动打开审核抽屉(抽屉内已含线上 vs 待审并排对照)
C. 门店列表 操作栏快捷入口 有待审套餐时显示「审核套餐」「对比」两个按钮,跳转同一地址(与详情页审核功能一致)
D. 列表接口补 pendingPackageAuditId GET /admin/stores 返回每家店当前待审套餐变更的 requestId(一次批量查询,无 schema 变更)
E. 审核后提醒自动刷新 审核完成 dispatch admin:package-audit-changed,套餐页签监听后刷新提醒

A / B. 门店详情·套餐页签

组件:apps/admin-web/src/components/AdminStorePackagesSection.tsx

  • 现有 GET /admin/stores/:storeId/packages 已返回 pendingRequest(含 id/status/packages),此前被组件丢弃;本次捕获 pendingRequest 存入 state。
  • pendingRequest.status === 'PENDING'
    • 页签顶部渲染 <Alert type="warning">:「该门店有待审核套餐」。
    • 提醒内放「审核」「对比」两个按钮,均 navigate('/store-package-audits?requestId=' + pendingRequest.id)
    • 空套餐门店同样展示该提醒(不依赖 live 是否有数据)。
  • 跳转后由 StorePackageAuditsPage 读取 ?requestId= 自动打开抽屉:抽屉内左侧「线上已审核套餐」、右侧「待审核套餐」并排 diffPackages 对照;抽屉右上「通过 / 驳回」即审核动作。两套按钮语义:审核=处置,对比=看差异,落点同一页面。

C. 门店列表·操作栏

组件:apps/admin-web/src/pages/StoresPage.tsx

  • StoreRow 增加 pendingPackageAuditId?: string | null
  • 操作列(原「详情 / 评价」)在 pendingPackageAuditId 存在时追加「审核套餐」「对比」按钮,均 navigate('/store-package-audits?requestId=' + row.pendingPackageAuditId)
  • 操作列宽度 140 → 220,允许换行,避免按钮被挤压。

D. 列表接口补 pendingPackageAuditId

后端:server/dukang-api/src/modules/ops/admin-stores.service.tslistStores

  • 取回 items 后,用一次查询批量取出待审变更: storePackageChangeRequest.findMany({ where: { storeId: { in: storeIds }, status: 'PENDING' }, select: { id, storeId } })
  • storeId -> requestId 映射,逐店附加 pendingPackageAuditId(无则 null)。
  • mapStoreCompat{ ...store } 展开透传,新字段不会被丢弃;无 Prisma schema 变更,发布可 --skip-db

E. 审核后提醒自动刷新

  • StorePackageAuditsPage 审核成功时调用 notifyPackageAuditChanged()dispatch admin:package-audit-changed)。
  • AdminStorePackagesSection 监听该事件,重新拉取 pendingRequest 并刷新提醒(仅更新 pendingRequest,不触碰正在编辑的 items,避免覆盖未保存套餐)。

关键接口 / 文件

位置 说明
GET /admin/stores 列表,新增 pendingPackageAuditIdops/admin/* 透传,无 schema 变更)
GET /admin/stores/:storeId/packages 返回 pendingRequeststore-package.service.ts,未改,仅前端消费)
GET /admin/store-package-audits/:requestId 审核详情(含 livePackages 对照)
PUT /admin/store-package-audits/:requestId/audit 通过 / 驳回
apps/admin-web/src/components/AdminStorePackagesSection.tsx 套餐页签提醒 + 按钮
apps/admin-web/src/pages/StorePackageAuditsPage.tsx ?requestId= 自动开抽屉 + 变更明细(含 fieldChanges / diffText / TextDiff
apps/admin-web/src/pages/StoresPage.tsx 列表操作栏快捷入口

F. 套餐变更对比·逐字段 / 逐字明细

组件:apps/admin-web/src/pages/StorePackageAuditsPage.tsx

需求:审核抽屉原本只给每条套餐「新增 / 删除 / 变更 / 未变」粗粒度标记,看不出具体哪里变了。本次在「待审核套餐」卡片底部新增变更明细块,逐字段列出差异;文本类字段进一步做逐字(LCS)差异定位,精确高亮哪些字被增 / 删。

  • fieldChanges(live, proposed):逐字段比对,产出 { label, old, now, kind } 明细:
    • kind: 'value'(整体替换展示 旧 → 新):价格图片(N 张 → M 张)
    • kind: 'text'(走逐字差异):套餐名称、菜品内容、可用时间、其他说明
  • diffText(a, b)LCS 动态规划(dp[i][j]+ 回溯,产出 equal / delete / insert 段落并合并相邻同类型;时间/空间 O(|a|·|b|),套餐字段长度可控,无性能风险。
  • TextDiff({ oldText, newText }):渲染两行——
    • 「原:」行用红色删除线标出被删的字(delete 段),其余正常;
    • 「新:」行用绿色标出新增的字(insert 段),其余正常。
    • 一眼定位到具体改动的字,而非整段替换。
  • 抽屉顶部汇总条:新增 X · 删除 Y · 变更 Z · 未变 W(由 diffPackageschanges 统计)。

已知局限

  • 套餐按名称(空则按位置)配对;若某条套餐改名,会误判为「删除旧名 + 新增新名」而非「变更」,改名本身不会进入逐字明细。如需把改名也识别为「变更」,需升级 packageKey 配对策略(名称变了但其余字段相近 → 视为变更)。

验收

  • 某门店有待审套餐变更时:门店详情-套餐页签顶部出现黄色「有待审核套餐」提醒,且「审核 / 对比」可点。
  • 点「审核」或「对比」均跳到套餐审核页并自动打开该门店变更抽屉,可见线上 vs 待审对照与通过/驳回。
  • 门店列表操作栏对该门店出现「审核套餐」「对比」按钮,点击同样跳转并自动打开抽屉。
  • 在审核页完成审核后,返回门店详情-套餐页签,提醒消失(或被事件即时刷新)。
  • 无待审套餐的门店:列表与详情页签均不出现上述入口。
  • 抽屉中「变更」套餐的「待审核」卡片底部出现「变更明细」:价格/图片以 旧 → 新 展示;菜品内容/可用时间/其他说明/套餐名称以逐字差异展示(原行红删、新行绿增),能精确定位到具体改动的字。