fix: some

This commit is contained in:
luo
2026-09-17 12:16:20 +08:00
parent 2308d82d0f
commit 76d4e4ec02
126 changed files with 11671 additions and 294 deletions

View File

@@ -0,0 +1,54 @@
# Change: 业务用户组管理与店铺批量交接/导入AUG26-003
## Why
后台需要把平台用户账号按业务线归入"业务用户组",并基于组对店铺做筛选、批量交接负责人与 CSV 导入负责人。当前前端只有单个店铺设置平台业务员的能力,缺少业务用户组维护、成员归属、按组筛选、批量交接与导入入口;且现有 11 个新端点仅超管与平台账号可访问。
## What Changes
- 新增业务用户组管理模块API 层 + 维护页面 + 成员管理):
- GET/POST /api/admin/business-user-groups、GET/PUT/DELETE /api/admin/business-user-groups/{id}
- PUT /api/admin/business-user-groups/{id}/members、DELETE /api/admin/business-user-groups/members
- 编码创建后不可改;删除需 {"confirm": true} 且仅无成员组可删更新支持部分字段business_line 三态(缺省=不改 / ""=清空 / 枚举=设置)。
- 成员归属整批校验(全部启用平台用户 + 目标组启用),任一无效整批不生效;一账号至多一组。
- 店铺列表/详情读取侧扩展:
- GET /api/admin/shops 新增 business_user_group_id / business_line / ungrouped 筛选。
- 列表/详情响应新增 5 个只读推导字段(组 ID/编码/名称/启用/业务线);组停用仍返回组且 enabled=false不算未分组前端不缓存、不回写改组后重新拉列表。
- 勾选批量交接:
- PUT /api/admin/shops/business-owner/batchshop_ids1-500去重+ business_owner_account_id字段缺失=400null=清空ID=换绑;任一店铺无效或目标非启用业务员 -> 整批不写入,统一按 1005 提示。
- CSV 导入:
- 复用 StorageService.getUploadUrl + 预签名 PUT 直传FilePurpose 增加 shop_import
- POST /api/admin/shops/business-owner-imports 创建异步任务,轮询详情、展示行级结果;前端自带模板(表头 店铺编码,操作类型,业务员登录账号,备注,换绑/清空)。
- 入口与权限(代理/企业不渲染入口):
- 路由 meta roles ['R_SUPER', 'R_ADMIN'];按钮权限码:
- business_user_group:page / business_user_group:create / business_user_group:update / business_user_group:delete / business_user_group:members
- shop:business_owner_batch
- shop:business_owner_import
## Not In Scope
- 不实现后端接口、不改数据库。
- 业务用户组不承载角色权限/数据范围语义;前端不引入组层级与组管理员概念。
- 导入结果不支持导出,仅在页面展示行级明细。
## Impact
- Affected specs: business-user-group-management新增、shop-management扩展
- Affected code:
- src/types/api/businessUserGroup.ts新增
- src/api/modules/businessUserGroup.ts新增
- src/types/api/shop.ts、src/api/modules/shop.ts
- src/api/modules/storage.tsFilePurpose 增加 shop_import
- src/views/shop-management/business-user-groups/index.vue新增页面
- src/views/shop-management/list/index.vue
- src/router/routes/asyncRoutes.ts、src/router/routesAlias.ts、src/locales/langs/{zh,en}.json
- src/template/业务负责人导入模板.csv前端自带模板
- API contracts: 11 个端点7 个业务用户组 + 店铺筛选/字段 + 批量交接 + 导入三步)
- Dependencies:
- docs/产品迭代8月份/业务用户组.md7 个组端点 OpenAPI
- AUG26-003 前端对接说明(店铺侧端点)
## 待确认
- 成员选择器复用 GET /api/admin/shops/business-owner-candidates启用平台账号若组成员可包含非业务员平台账号需后端补充平台账号列表端点。
- 导入任务与行级结果字段名file_key、status、items[] 等)以生成文档为准,提案按对接说明先行对齐。

View File

@@ -0,0 +1,73 @@
## ADDED Requirements
### Requirement: 业务用户组维护
后台 MUST 提供业务用户组列表、详情、创建、更新与删除能力GET/POST /api/admin/business-user-groups、GET/PUT/DELETE /api/admin/business-user-groups/{id})。列表 MUST 支持 page/page_size/enabled/keyword/business_line 筛选,且每项 MUST 返回 business_line_name。创建时 code1-64与 name 必填编码未删除组内唯一且创建后不可修改business_line 可空standard/smart/othersort/enabled/remark 可选。更新 MUST 仅允许名称、业务线、排序、启停与备注,且 business_line 支持三态:字段缺失不修改、传 "" 清空、传枚举设置;删除 MUST 携带 {"confirm": true},仅无成员组可删除。
#### Scenario: 查询业务用户组列表
- **GIVEN** 用户进入业务用户组维护页
- **WHEN** 前端以 page/page_size/enabled/keyword/business_line 发起列表查询
- **THEN** 前端 MUST 展示分页结果且每项显示 business_line_name
- **AND** 下拉数据源复用该列表接口
#### Scenario: 创建时编码不可变
- **GIVEN** 用户填写名称与稳定编码创建用户组
- **WHEN** 提交成功或编码重复被后端拒绝
- **THEN** 编码在创建后 MUST NOT 出现在编辑表单中
- **AND** 编码重复时 MUST 展示后端返回的"业务用户组编码已存在"
#### Scenario: 业务线三态更新
- **GIVEN** 用户编辑某组的业务线
- **WHEN** 表单传 ""、传枚举或省略该字段
- **THEN** 前端 MUST 分别按"清空 / 设置 / 不修改"构造请求体
#### Scenario: 删除需二次确认
- **GIVEN** 用户点击删除某组
- **WHEN** 确认弹窗提交
- **THEN** 前端 MUST 携带 {"confirm": true}
- **AND** 有成员时 MUST 提示"用户组仍有成员,只能停用或先移走成员"且不做物理删除
- **AND** 无成员时删除成功并刷新列表
### Requirement: 成员归属批量维护
后台 MUST 支持按平台用户账号把成员批量设置进组PUT /api/admin/business-user-groups/{id}/members与批量清空DELETE /api/admin/business-user-groups/members携带 body account_ids。两种操作 MUST 复用同一校验:所有账号必须是启用平台用户且目标组启用,任一账号无效则整批不生效;清空后账号回到未分组;一账号至多一组。
#### Scenario: 批量设置成员
- **GIVEN** 用户在成员管理中选择多个启用平台账号
- **WHEN** 保存成员归属
- **THEN** 前端 MUST 以 account_ids 数组整体替换每个账号原归属
- **AND** 刷新后成员关系与最新分组一致
#### Scenario: 批量清空成员
- **GIVEN** 用户选择若干账号执行清空
- **WHEN** 提交清空
- **THEN** 前端 MUST 调用 DELETE /api/admin/business-user-groups/members 并携带 account_ids body
- **AND** 清空成功的账号回到未分组
#### Scenario: 停用组的成员展示
- **GIVEN** 某组被停用但仍有成员
- **WHEN** 用户在成员管理或店铺列表看到该组
- **THEN** 前端 MUST 展示"已停用"标记并提供改组/清空入口
### Requirement: 访问控制与入口
业务用户组维护入口 MUST 仅对超级管理员与平台账号可见,代理/企业账号 MUST NOT 渲染入口;所有按钮 MUST 受权限码控制。
#### Scenario: 菜单按角色隐藏
- **GIVEN** 代理或企业账号登录
- **WHEN** 系统渲染菜单
- **THEN** MUST NOT 展示业务用户组菜单项
#### Scenario: 按钮权限控制
- **GIVEN** 平台账号具备部分业务用户组权限
- **WHEN** 渲染操作按钮
- **THEN** 前端 MUST 按 business_user_group:create/update/delete/members 控制显隐

View File

@@ -0,0 +1,75 @@
## ADDED Requirements
### Requirement: 店铺列表/详情业务用户组字段与筛选
店铺列表查询 MUST 支持 business_user_group_id、business_line、ungrouped 三个新筛选;列表与详情响应 MUST 提供 5 个只读推导字段business_user_group_id可空、business_user_group_code、business_user_group_name、business_user_group_enabled、business_user_group_business_line。组停用仍返回组且 enabled=false不算未分组店铺不存组字段实时推导前端 MUST NOT 缓存或回写,改动组成员后重新拉取列表。
#### Scenario: 按业务用户组筛选
- **GIVEN** 用户在店铺列表选择业务用户组、业务线或勾选"未分组"
- **WHEN** 发起列表查询
- **THEN** 前端 MUST 提交 business_user_group_id/business_line/ungrouped 参数
- **AND** ungrouped=true 表示无负责人或负责人无分组
#### Scenario: 展示组字段
- **GIVEN** 店铺属于某启用或停用的业务用户组
- **WHEN** 渲染列表或详情
- **THEN** 前端 MUST 展示组名称/编码/业务线
- **AND** 组停用时 MUST 标记"已停用"且仍展示组归属
### Requirement: 勾选批量交接平台业务员
店铺列表 MUST 支持勾选店铺批量交接平台业务员PUT /api/admin/shops/business-owner/batchbody shop_ids 1-500 去重 + business_owner_account_id。字段缺失 MUST 按参数错误处理400传 null 表示清空负责人;传 ID 表示换绑。任一店铺不存在/已删除/越权或目标非启用业务员时整批不写入,前端 MUST 统一提示"无权限操作该资源或资源不存在";成功响应含 batch_key/shop_count/cleared。
#### Scenario: 批量换绑
- **GIVEN** 用户勾选 1-500 家店铺并选择启用业务员
- **WHEN** 提交批量交接
- **THEN** 前端 MUST 提交 shop_ids去重与 business_owner_account_id
- **AND** 成功后展示 shop_count 并刷新列表
#### Scenario: 批量清空负责人
- **GIVEN** 用户勾选店铺并选择"清空负责人"
- **WHEN** 提交批量交接
- **THEN** 前端 MUST 显式提交 business_owner_account_id: null
- **AND** MUST NOT 省略该字段
#### Scenario: 整批失败统一提示
- **GIVEN** 批量交接请求因任一店铺或目标账号不满足条件而被后端拒绝
- **WHEN** 前端收到 1005
- **THEN** 前端 MUST 展示统一文案且不写入任何店铺
### Requirement: 业务负责人 CSV 导入
店铺列表 MUST 支持通过 CSV 导入批量交接/清空业务负责人。流程 MUST 为:前端自带模板(表头 店铺编码,操作类型,业务员登录账号,备注,操作类型仅"换绑"或"清空"-> POST /api/admin/storage/upload-urlpurpose=shop_import拿预签名 URL 直传15 分钟有效)-> POST /api/admin/shops/business-owner-importsfile_key创建异步任务 -> 轮询 GET /api/admin/shops/business-owner-imports/{id} 展示结果。行级失败不等于任务失败:任务 status=3 也可能有失败行MUST 按 items[] 展示明细;表头/编码不符为任务级失败items 为空数组,只展示 error_message。
#### Scenario: 下载模板并上传
- **GIVEN** 用户进入导入界面
- **WHEN** 点击下载模板或选择文件
- **THEN** 前端 MUST 提供表头完全一致的模板文件
- **AND** 上传后 MUST 以 purpose=shop_import 获取上传地址并直传
#### Scenario: 创建任务并轮询
- **GIVEN** 文件上传成功拿到 file_key
- **WHEN** 提交创建导入任务
- **THEN** 前端 MUST 携带 file_key 调用创建接口
- **AND** MUST 轮询任务详情直到 status 为已完成(3)或失败(4)
#### Scenario: 展示行级失败明细
- **GIVEN** 任务完成但存在失败行
- **WHEN** 前端渲染结果
- **THEN** 前端 MUST 展示 total_count/success_count/fail_count
- **AND** MUST 按 items[] 展示各行的 line/shop_code/operation_type/status/reason
- **AND** 失败行保留原负责人
#### Scenario: 任务级失败提示
- **GIVEN** 表头或编码不符导致任务级失败
- **WHEN** 前端渲染结果
- **THEN** 前端 MUST 只展示 error_message 且明细为空

View File

@@ -0,0 +1,34 @@
## 1. API Contract 层
- [x] 1.1 新增 src/types/api/businessUserGroup.ts组项/分页/创建/更新/删除/成员设置与结果类型
- [x] 1.2 新增 src/api/modules/businessUserGroup.ts封装 7 个组端点DELETE 带 body需请求层支持
- [x] 1.3 扩展 src/types/api/shop.ts列表筛选 business_user_group_id/business_line/ungrouped响应只读组字段批量交接与导入任务/行级结果类型
- [x] 1.4 扩展 src/api/modules/shop.tsbatchUpdateBusinessOwner、createBusinessOwnerImport、getBusinessOwnerImportDetail、getBusinessOwnerImportList
- [x] 1.5 扩展 src/api/modules/storage.tsFilePurpose 增加 shop_import
## 2. 业务用户组页面
- [x] 2.1 新增 src/views/shop-management/business-user-groups/index.vue列表筛选/分页/启停/业务线)
- [x] 2.2 新建/编辑弹窗code 创建后不可改、business_line 三态、名称/排序/备注/启停
- [x] 2.3 删除二次确认confirm=true有成员时按后端提示处理
- [x] 2.4 成员管理(对话框/抽屉):成员选择器(复用 business-owner-candidates+ 批量设置 + 批量清空;停用组保留成员并标记"已停用"
## 3. 店铺列表扩展
- [x] 3.1 列表搜索区新增业务用户组下拉与业务线筛选、ungrouped 勾选(数据源来自组列表接口)
- [x] 3.2 列表/详情展示组字段(停用组标记,不缓存不回写)
- [x] 3.3 批量交接弹窗:勾选店铺 + 选择业务员/清空(显式 null整批失败统一 1005 文案
- [x] 3.4 导入入口:模板下载、文件校验/上传purpose=shop_import、创建任务、轮询并展示行级明细
- [x] 3.5 导入任务列表(状态筛选)
## 4. 路由/菜单/权限/i18n
- [x] 4.1 新增 /shop-management/business-user-groups 路由与菜单roles ['R_SUPER', 'R_ADMIN']
- [x] 4.2 按钮权限编码落地business_user_group*/shop:business_owner_batch/shop:business_owner_import
- [x] 4.3 中英文案 menus.shopManagement.businessUserGroups 等
## 5. 验证
- [x] 5.1 运行 npm run build含 vue-tsc --noEmit
- [x] 5.2 运行 npm run check:encoding
- [x] 5.3 运行 openspec validate add-business-user-group-management --strict