2026-05-08-REQ-USR-001.md
5.83 KB
req_id: REQ-USR-001 date: 2026-05-08
module: module_usr
Spec: REQ-USR-001 — 增加用户
目标
超级管理员在用户管理页新建用户账号,填写基本信息并分配权限组,账号保存后立即生效,可使用初始密码 666666 登录系统。
输入 / 触发
触发:超级管理员点击用户管理页「新增」按钮,弹出 Drawer,填写表单并提交。
POST /api/usr/users 请求体:
{
"userCode": "string(必填,用户号)",
"username": "string(必填,用户名,同一 brand 内唯一)",
"userType": "普通用户|超级管理员(必填)",
"language": "中文|英文|繁体(必填)",
"canEditDoc": false,
"employeeId": "string|null(可选,tStaff.sId)",
"permGroupIds": ["string"]
}
前端 Drawer 表单字段: | 字段 | 组件 | 必填 | 来源/选项 | |---|---|---|---| | 用户号 | Input | 是 | 手工输入 | | 用户名 | Input | 是 | 手工输入 | | 类型 | Select | 是 | 普通用户 / 超级管理员 | | 语言 | Select | 是 | 中文 / 英文 / 繁体 | | 单据修改权限 | Checkbox | 否 | 默认不勾 | | 员工 | Select | 否 | GET /api/usr/staffs 返回列表,label=sStaffName, value=sId | | 权限组 | Table+Checkbox | 否 | GET /api/usr/permission-groups 返回列表,列:权限分类/权限名称 |
输出 / 结果
成功响应:
{
"code": 200,
"message": "操作成功",
"data": {
"userId": "string",
"userCode": "string",
"username": "string"
}
}
前端收到成功响应后:message.success("新增用户成功") → 关闭 Drawer。
业务规则
-
权限控制:请求者 JWT 中
userType == 超级管理员,否则抛BizException(40300, "权限不足")。 -
唯一性检查(同 brand 内):
-
sUserCode全库唯一(索引uk_usr_user_usercode);重复抛BizException(40902, "用户号已存在")。 -
sUsername在同一sBrandsId内唯一(索引uk_usr_user_username_tenant);重复抛BizException(40901, "用户名已存在")。
-
-
密码初始化:
sPasswordHash = BCryptPasswordEncoder.encode("666666"),禁止存明文。 -
系统字段自动填充(Controller 或 Service 层注入
UserPrincipal):-
sId=UUID.randomUUID().toString() -
sBrandsId= JWT claimbrandId -
sCreatorUsername= JWT claimusername -
tCreateDate=LocalDateTime.now() -
bIsDisabled= 0 -
iLoginFailCount= 0
-
-
employeeId 校验:若不为 null,需验证
tStaff.sId == employeeId && tStaff.sBrandsId == brandId;不存在抛BizException(40001, "员工不存在")。 -
权限组写入:
permGroupIds非空时,批量插入usr_user_permission(sUserId=新用户 sId,sPermGroupId=item);permGroupIds为空/null 时跳过。 -
事务:
createUser()方法标注@Transactional,usr_user 插入 + usr_user_permission 批量插入在同一事务中。
边界与约束
- 初始密码仅后端生成,不通过请求体传入,前端不展示。
-
sUsername一旦创建不可修改(REQ-USR-002 约束)。 -
userType枚举只有普通用户和超级管理员两种合法值;language枚举只有中文、英文、繁体;后端用@Pattern/@NotNull+@Valid校验,违规触发40001。 - 跨模块改动:需修改
JwtAuthenticationFilter.java(config 层),将 JWT claims 包装为UserPrincipal存入 SecurityContext,使UserController可通过@AuthenticationPrincipal UserPrincipal取到brandId和username。此修改属必要基础设施扩展(CLAUDE.md S2)。
依赖的 schema 表 / 字段
写入表:
-
usr_user:sId、sBrandsId、sCreatorUsername、tCreateDate、sUserCode、sUsername、sPasswordHash、sUserType、sLanguage、bCanEditDoc、bIsDisabled、sEmployeeId、iLoginFailCount -
usr_user_permission:sId(UUID)、sBrandsId、tCreateDate、sUserId、sPermGroupId
只读表:
-
tStaff:sId、sStaffName(员工下拉列表及 employeeId 校验) -
usr_permission_group:sId、sGroupCode、sGroupName、sCategory(权限组复选列表)
依赖的接口
-
POST /api/auth/login(REQ-USR-004)— 前端登录获取 JWT,携带 Bearer Token 才可调用本接口 -
GET /api/usr/staffs(本 REQ 新增,不在 docs/05 原始清单)— 员工下拉数据源,鉴权接口- 响应:
{ "data": [{ "sId": "...", "sStaffName": "..." }] }
- 响应:
-
GET /api/usr/permission-groups(本 REQ 新增,不在 docs/05 原始清单)— 权限组复选数据源,鉴权接口- 响应:
{ "data": [{ "sId": "...", "sGroupCode": "...", "sGroupName": "...", "sCategory": "..." }] }
- 响应:
-
POST /api/usr/users(docs/05 已定义)— 本 REQ 核心创建接口
验收标准
- 超级管理员提交合法数据 → HTTP 200,
data.userId非空,数据库usr_user表新增一条记录,密码字段为 BCrypt 哈希(不含 "666666" 明文)。 - 新建用户可立即用 POST /api/auth/login(brandNo + username + "666666")登录成功。
- 重复用户名(同 brand)→ 返回
code=40901,用户名已存在。 - 重复用户号 → 返回
code=40902,用户号已存在。 - 普通用户调用本接口 → 返回
code=40300,权限不足。 - 缺必填字段(userCode / username / userType / language 为空)→ 返回
code=40001。 - 选中权限组后提交 →
usr_user_permission表有对应关联记录。 - 关联无效 employeeId → 返回
code=40001,员工不存在。 - 前端:新增 Drawer 表单加载时,员工下拉和权限组 Table 已从对应 API 拉取数据;提交成功后 Drawer 关闭并显示
message.success。 - 前端:普通用户登录后,用户管理页「新增」按钮不显示(
PermButton permission="usr:create"隐藏逻辑)。