功能标识:022-merchant-store-subaccounts | 日期:2026-08-28 | 规格:spec.md
目标:为商家主账号提供可分配多个店铺的独立分管账号,使其按授权门店操作订单、商品和退款,并将店铺通知发送给所有可接收分管账号,同时保持平台商家管理只统计主账号。
架构:分管账号复用 info_user 认证主键并使用独立 user_type=5,通过 merchant_subaccount_store 表表达多店授权。后端用集中式门店访问服务校验真实数据归属,通知通过门店接收者路由服务选择在线分管账号或主账号兜底。平台以主商家下级视图呈现分管账号,商家端新增账号管理页。
技术栈:Java 21、Spring Boot、MyBatis/MyBatis-Plus、MySQL、Redis、JUnit 5、Mockito、Vue 2、Element UI、vue-i18n。
ruoyi-admin -> ruoyi-system,系统模块不得导入 com.ruoyi.app.*。@RequestBody、@RequestHeader String token 和显式查询参数,不使用 Map 入参。updatesql/sql.md,不直接执行。存储:info_user 增加所属主账号、主账号控制状态和最后登录时间;新增账号门店关联表。
认证:沿用商家端 JWT 与 Redis 会话,类型 5 使用商家 App/PC token 前缀。
授权:每次请求按数据库当前状态与目标实体真实 mdId 校验,不把店铺权限缓存进 Token。
推送:沿用 iOS msdstore 和 PushEvent -> push_message,不新增 Android FCM。
兼容性:类型 1、3、4 原有业务保持;无分管账号时通知继续发主账号。
ruoyi-system/src/main/java/com/ruoyi/system/domain/MerchantSubaccountStore.java
ruoyi-system/src/main/java/com/ruoyi/system/domain/constants/MerchantAccountConstants.java
ruoyi-system/src/main/java/com/ruoyi/system/mapper/MerchantSubaccountStoreMapper.java
ruoyi-system/src/main/resources/mapper/infouser/MerchantSubaccountStoreMapper.xml
ruoyi-system/src/main/java/com/ruoyi/system/service/IMerchantSubaccountStoreService.java
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/MerchantSubaccountStoreServiceImpl.java
ruoyi-system/src/main/java/com/ruoyi/system/service/MerchantStoreAccessService.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/MerchantSubaccountController.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/MerchantSubaccountAdminController.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/MerchantSubaccountApplicationService.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/MerchantSubaccountCreateRequest.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/MerchantSubaccountUpdateRequest.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/MerchantSubaccountPasswordRequest.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/MerchantSubaccountStatusRequest.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/dto/MerchantSubaccountView.java
ruoyi-admin/src/main/java/com/ruoyi/app/order/MerchantNotificationRouter.java
MerchantStoreAccessService 只处理账号、店铺和实体归属授权;MerchantSubaccountApplicationService 负责创建、状态、密码、授权事务及 Redis 会话撤销;MerchantNotificationRouter 留在 admin 模块以使用 PayPush 和 PushEventService。
ruoyi-system/src/main/java/com/ruoyi/system/domain/InfoUser.java
ruoyi-system/src/main/resources/mapper/infouser/InfoUserMapper.xml
ruoyi-system/src/main/java/com/ruoyi/system/mapper/InfoUserMapper.java
ruoyi-admin/src/main/java/com/ruoyi/app/user/InfoUserController.java
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreController.java
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosFoodController.java
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosFenleiController.java
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/FoodSpecController.java
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderShOprateController.java
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderController.java
ruoyi-admin/src/main/java/com/ruoyi/app/order/UserOrderController.java
ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderQsOprateController.java
ruoyi-admin/src/main/java/com/ruoyi/app/order/DeliveryOrderNotificationService.java
ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
ruoyi-admin/src/main/resources/i18n/messages_zh_TW.properties
ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
ruoyi-admin/src/main/resources/i18n/messages_vi.properties
updatesql/sql.md
E:/QtwCode/foodie/foodie-store/src/api/subaccount.js
E:/QtwCode/foodie/foodie-store/src/views/MerchantSubaccount.vue
E:/QtwCode/foodie/foodie-store/src/router/index.js
E:/QtwCode/foodie/foodie-store/src/components/Aside.vue
E:/QtwCode/foodie/foodie-store/src/components/Header.vue
E:/QtwCode/foodie/foodie-store/src/views/AcidrollingCapacity.vue
E:/QtwCode/foodie/foodie-store/src/api/store.js
E:/QtwCode/foodie/foodie-store/src/api/food.js
E:/QtwCode/foodie/foodie-store/src/lang/zh.js
E:/QtwCode/foodie/foodie-store/src/lang/tw.js
E:/QtwCode/foodie/foodie-store/src/lang/en.js
E:/QtwCode/foodie/foodie-store/src/lang/vi.js
主账号显示分管账号菜单;类型 5 只显示订单、授权店铺和商品相关入口。店铺页面对类型 5 隐藏新增和删除,但后端仍强制校验。现有缺少 token 的店铺/商品请求补齐 isToken: true。
E:/QtwCode/foodie/foodie-admin-vue/src/views/infouser/user/sjuser.vue
E:/QtwCode/foodie/foodie-admin-vue/src/api/infouser/user.js
E:/QtwCode/foodie/foodie-admin-vue/src/api/language/language.zh_CN.js
E:/QtwCode/foodie/foodie-admin-vue/src/api/language/language.zh_TW.js
E:/QtwCode/foodie/foodie-admin-vue/src/api/language/language.en_US.js
E:/QtwCode/foodie/foodie-admin-vue/src/api/language/language.vi.js
平台商家行新增“分管账号”按钮和对话框,不新增顶级菜单;只提供查看和平台启停。
InfoUser 补齐三个字段和 MyBatis 映射,建立类型 5 常量,SQL 追加迁移语句。MerchantStoreAccessService 的 requireOwner、getAccessibleStoreIds、requireStoreAccess、requireOrderAccess 和 requireFoodAccess。shanglodeing 支持类型 5,签发 Token 前检查自身与主账号状态,更新最后登录时间。userType=1 列表、导出和统计,证明类型 5 不出现、不计数、不进入审核。@Auth 支持显式启用 Redis 会话认证;商家业务接口在认证切面统一完成 JWT 与 JTI 校验,Controller 不再调用会话服务二次认证。getmystorelist 对主账号按所有权查询,对分管账号按授权集合查询。addmendian 增加 token 并强制主账号;店铺详情、修改、营业状态和营业时间校验实际店铺。mdId 再授权。mdId 集合查询;详情、接单后操作、取消和退款在状态流转前执行订单门店授权。PushEvent;CID 去重外部推送,单账号异常隔离。mdId。ruoyi-admin 及依赖模块。foodie-store 与 foodie-admin-vue。quickstart.md 执行越权、双重停用、通知全发和主账号兜底场景。ruoyi-system/src/test/java/com/ruoyi/system/service/MerchantStoreAccessServiceTest.java
ruoyi-system/src/test/java/com/ruoyi/system/mapper/MerchantSubaccountStoreMapperXmlTest.java
ruoyi-admin/src/test/java/com/ruoyi/app/user/MerchantSubaccountControllerTest.java
ruoyi-admin/src/test/java/com/ruoyi/app/user/MerchantSubaccountAdminControllerTest.java
ruoyi-admin/src/test/java/com/ruoyi/app/order/MerchantNotificationRouterTest.java
ruoyi-admin/src/test/java/com/ruoyi/app/mendian/PosFoodControllerAccessTest.java
并扩展现有:
ruoyi-admin/src/test/java/com/ruoyi/app/user/InfoUserControllerTest.java
ruoyi-admin/src/test/java/com/ruoyi/app/mendian/PosStoreControllerTest.java
ruoyi-admin/src/test/java/com/ruoyi/app/order/PosOrderShOprateControllerTest.java
ruoyi-admin/src/test/java/com/ruoyi/app/order/DeliveryOrderNotificationServiceTest.java
| 复杂度 | 必要性 | 未采用的简单方案 |
|---|---|---|
info_user 类型 5 + 关联表 |
同时复用认证并隔离平台商家统计,支持账号与店铺多对多 | 类型 1 加角色容易污染所有商家查询;单独账号表复制认证体系 |
| 双重状态 | 平台强制停用不能被主账号覆盖 | 共用一个状态无法区分操作者和恢复权限 |
| 集中权限服务 | 多个旧 Controller 的归属规则不同,必须统一防止 IDOR | 仅前端隐藏或各 Controller 手写条件容易漏改 |
| 通知路由服务 | 同店多接收者、消息逐账号归属、主账号兜底需要统一行为 | 在每个订单入口复制循环会产生规则漂移 |
@Auth 可选会话认证 |
在不改变骑手、普通用户认证行为的前提下,把商家 JWT 与 Redis 会话校验集中到 Controller 之前 | 全局强制 Redis 校验会扩大兼容性影响;Controller 手工调用会产生重复认证和遗漏风险 |