分管账号继续存放在 info_user,使用新的 user_type=5 表示“商家分管账号”,并通过 merchant_owner_id 关联唯一的商家主账号。
InfoUser.userId 为中心,复用 info_user 可以保持现有认证与推送链路。userType=1,Mapper 使用 user_type = #{userType};类型 5 天然不会进入商家列表、导出和商家数量统计。user_type=4 已用于摊位商家,不能复用。user_type=1,另加角色字段:所有按 user_type=1 统计、审核和导出的查询都必须额外排除分管账号,漏改一个入口就会污染平台商家管理。info_user.status 作为平台控制状态:0=正常、1=平台停用。subaccount_status 作为主账号控制状态:0=启用、1=主账号停用,只对类型 5 生效。如果主账号和平台共用一个可写状态,主账号可以重新启用平台强制停用的账号。两个状态必须独立,并由不同接口控制。
新增 merchant_subaccount_store 多对多关联表。授权保存时同时校验:分管账号的 merchant_owner_id 等于 pos_store.user_id。
一个分管账号可负责多个店铺,一个店铺也可配置多个分管账号;JSON、逗号字符串或 info_user.store_id 都不能可靠表达该关系。
在 ruoyi-system 建立统一的 MerchantStoreAccessService,每次业务请求从数据库读取当前账号和目标数据的真实门店归属:
pos_store.user_id = 当前账号 的全部门店。pos_order.md_id、商品以 pos_food.md_id、分类和规格以其实际关联商品或门店为准。requireOwner。不把店铺集合写入 Token,也不依赖前端传入的主账号 ID,因此撤销授权后下一次请求立即生效。
不新增顶级“商家”行或独立商家审核流程。在平台 sjuser.vue 的主商家操作区增加“分管账号”入口,以对话框/抽屉展示该主账号的下属账号。
平台可以修改 info_user.status 以强制停用或恢复,但不能修改 subaccount_status、密码或店铺授权。
商家登录成功时更新 last_login_at。停用账号时删除其商家 App/PC Redis 会话;分管账号的每次业务请求仍重新检查数据库状态,不能只依赖会话存在。
InfoUserController.shanglodeing 当前允许类型 1、3、4,且没有校验 status。实现时加入类型 5,并在签发 Token 前统一执行账号可用性检查。PosStoreController.addmendian、PosFoodController.setposfood 等有效商家端写入口存在未声明 token 或信任请求体归属字段的情况。实现时按 Controller 规范补充 @RequestHeader String token,并从 Token 解析操作者。user_type=1,新增回归测试证明类型 5 不会出现或计数。user_type=4 的摊位逻辑、类型 3 的夜市逻辑保持不变;不能把分管账号塞入现有单店 store_id 规则。@RequestBody,App token 使用 @RequestHeader,不使用 Map 接收请求。