# 连锁门店「复制商品」功能说明 > 版本:v1.1 | 日期:2026-09-03 | 状态:设计已评审定稿 > 适用读者:需求、测试 --- ## 一、功能背景 连锁商家(如麦当劳)一个账号下开了多家门店,各家门店的商品菜单基本一致。目前分类和商品都挂在单个门店下,商家新开一家门店只能在商家端逐条重新录入,30 个商品的菜单录入要 1 小时以上,还容易漏录、录错价格。 本功能提供「复制商品」:把一家门店的菜单一键复制到另一家门店,开新店的菜单初始化 1 分钟内完成。 ## 二、功能范围 - **复制的内容**:全部分类 + 全部商品,包括价格、图片、商品介绍、属性(加料等)、规格(大小杯/温度等)、排序、是否推荐 - **不复制**:门店资料(店名、地址、统编、税号、客服电话、营业时间)——每家门店这些必然不同 - **实现范围**:商家 PC 端(本期);商家 App 后续复用同一功能 ## 三、怎么用(交互) ### 入口 商家 PC 端「商品管理」页: - 顶部是门店切换按钮(现状已有),**当前选中的门店就是复制目标** - 「添加商品」按钮旁边新增「**复制商品**」按钮 - 商家名下门店不足 2 家时,按钮自动隐藏(单店商家完全无感知) ### 操作流程 ``` 点「复制商品」 ↓ ① 选源门店(下拉框,自动排除当前门店) ↓ 选定后自动显示差异概览 ② 查看差异概览;如有"内容不同"的商品,选择处理方式 ↓ ③ 点「确定复制」→ 完成提示 → 商品列表自动刷新 ``` ### 弹窗示意 ``` ┌─ 复制商品 ──────────────────────┐ │ 从「台北忠孝店」复制到「台北信义店」 │ │ │ │ 新增分类 1(同名合并 4) │ │ 新增商品 12 │ │ 同名且内容一致,跳过 23 │ │ │ │ ▸ 同名但内容不同:3 个(点击展开) │ │ 麦辣鸡腿堡 价格 65 → 75 │ │ 薯条(大) 图片已更换 │ │ 可乐(大) 介绍已修改 │ │ │ │ 这 3 个商品怎么处理? │ │ ○ 保留本店版本(默认) │ │ ● 用源店版本覆盖 │ │ │ │ [取消] [确定复制] │ └────────────────────────────────┘ ``` ### 特殊状态 | 场景 | 弹窗表现 | |---|---| | 两店菜单完全一致 | 显示「已是最新,无新增」,确定按钮不可点 | | 源门店没有任何商品 | 提示「该门店没有可复制的商品」,确定按钮不可点 | | 复制完成 | 提示「新增分类 X、新增商品 Y、跳过 Z、覆盖 W」 | ## 四、业务规则(测试依据) 先记住两条判定规则: - **同一个分类** = 名字 + 语言相同 - **同一个商品** = 名字 + 语言相同(同名但语言不同算**不同**商品,会作为新增补进来——比如本店只有中文「可乐」,源店还有英文「Cola」,复制后英文版也补上) ### 复制时对每个分类/商品的处理 | 情况 | 系统行为 | |---|---| | 目标店没有这个分类 | 新建分类 | | 目标店已有同名分类 | 复用已有分类,新商品挂进去(**不会出现两个"汉堡"分类**) | | 目标店没有这个商品 | 新增,内容照搬源店,**上下架、审核状态跟源店一致**(复制完即可营业) | | 同名且内容一致 | 跳过,不动 | | 同名但内容不同 | **商家选择**:保留本店版本(默认)或 用源店版本覆盖 | 「内容」指:价格、图片、商品介绍、属性(加料等)、规格、排序、是否推荐。 ### 覆盖的边界(重要) 选「用源店版本覆盖」时: - **更新**:价格、图片、介绍、属性、排序、推荐、规格关联 - **不动**:本店的**上下架状态**——例:目标店「薯条」今日临时下架,覆盖后价格图片对齐源店,但**仍是下架** - **不动**:本店的审核状态 - **不动**:本店已有规格模板里的加价——例:本店「大小杯」模板"大杯+5"是本店自改价,覆盖后**仍是+5**(规格模板全店共享,改它会连带影响本店其他商品,所以不覆盖) ### 其他规则 - 源门店和目标门店不能选同一家 - 权限:主账号可复制自己名下任意两家门店;分管账号只能复制授权范围内的门店 - **可以反复执行**:菜单有变化后再复制一次,只补缺的;显示「新增 0、覆盖 0」就代表两边已一致 - 复制要么全部完成、要么全部不做,不会出现复制一半的情况 ## 五、测试用例建议 ### 1. 主流程 | 用例 | 前置 | 步骤 | 预期 | |---|---|---|---| | TC01 空店全量复制 | 商家有店 X(5 分类 38 商品,含带规格、带属性商品)、空店 Y | X→Y 复制(默认保留) | Y 生成 5 分类 38 商品,内容一致;规格可选且加价正确;图片正常显示 | | TC02 上下架状态继承 | 源店商品一半上架一半下架 | 复制到空店 | 新店商品上下架状态与源店一致;上架商品顾客端可下单 | | TC03 重复执行 | TC01 完成后 | 再执行一次相同复制 | 提示新增 0、覆盖 0;数据无变化 | | TC04 预览与执行一致 | X 有 38 商品,Y 已有 26 个(23 个一致 3 个差异) | 打开预览后确认复制 | 预览计数=新增 12、跳过 23、差异 3;实际执行结果与预览一致 | ### 2. 差异与覆盖 | 用例 | 前置 | 步骤 | 预期 | |---|---|---|---| | TC05 差异-保留(默认) | Y 的「麦辣鸡腿堡」价格 65,X 为 75 | 选保留复制 | Y 该商品价格仍 65,其余新增正常 | | TC06 差异-覆盖内容 | 同上 | 选覆盖复制 | Y 该商品价格变 75,图片/介绍/属性/排序/推荐对齐 X | | TC07 覆盖不动上下架 | Y 的「薯条」已下架 | 选覆盖复制 | 薯条内容对齐 X,但**仍为下架** | | TC08 覆盖不动审核 | Y 的商品审核状态与 X 不同 | 选覆盖复制 | Y 审核状态不变 | | TC09 覆盖不动规格加价 | Y 的「大小杯」模板"大杯+5",X 为"大杯+3" | 选覆盖复制 | Y 模板仍"大杯+5";若 X 多关联了「温度」规格,Y 商品补挂「温度」 | ### 3. 匹配规则 | 用例 | 前置 | 预期 | |---|---|---| | TC10 分类合并 | Y 已有「汉堡」分类 | 不产生第二个「汉堡」,新增商品挂入已有分类 | | TC11 多语言独立匹配 | Y 只有中文「可乐」,X 有中英两行 | 英文行新增、中文行按一致/差异规则处理 | | TC12 源店同名分类脏数据 | X 有两个同名分类 | 与第一个合并,不报错 | | TC13 名字不同内容相同 | X「麦辣鸡腿堡」、Y「辣鸡腿堡」价格相同 | 判定为不同商品,X 的作为新增 | ### 4. 权限与边界 | 用例 | 前置 | 预期 | |---|---|---| | TC14 单店隐藏入口 | 商家只有 1 家门店 | 商品管理页无「复制商品」按钮 | | TC15 源=目标 | 两个下拉选到同一家(或构造请求) | 系统拒绝,提示错误 | | TC16 分管账号越权 | 分管账号甲授权 A、B,未授权 C | A→B 成功;伪造参数 A→C 被拒绝,C 数据不变 | | TC17 源店为空 | 源店无分类无商品 | 提示无可复制,无任何写入 | | TC18 中途失败 | 模拟复制过程中出错 | 目标店无任何新增(不留半个菜单) | | TC19 大菜单性能 | 源店 100 商品 | 复制 10 秒内完成,无超时 | | TC20 多语言界面 | 分别切简中/繁中/英文/越南文打开弹窗 | 文案全部正确翻译,无乱码或显示 key |