-
…lears all (REQ-USR-002)
-
源自 Codex 对 wire-frontend-backend 分支的对抗性评审 (2× high / 1× medium),三条 finding 均已复核属实。 - [HIGH] 详情未加载就保存会把 permissionCategoryIds 当成 [] → 静默清空: - 前端 ids 三态化 (number[] | null),列表态 snapshot 不带 ids 时保持 null - 编辑模式下 ids 仍为 null 时 disable 修改/保存按钮,DTO 中省略该字段 - 后端 update() 把 delete+reinsert 包到 if (ids != null),null 视为"不动权限" - [HIGH] 过滤态下表头全选越权授权:allChecked 与 onChange 改为基于 visibleCategories - [MEDIUM] selectCategoryIdsByUserId 加 INNER JOIN tPermissionCategory 过滤 bDeleted=0, 避免软删分类导致 40023 阻塞无关字段编辑
-
- Backend: add GET /usr/users/{id} detail endpoint that returns the user row plus its permissionCategoryIds - Backend: add GET /usr/permission-categories listing for the permission grid (active categories only) - Frontend: UserDetail consumes both endpoints to populate edit form and the permission grid
-
Backend: - StaffSearchVO (iIncrement / sStaffNo / sStaffName / sDepartment) - StaffMapper.searchActive(keyword, limit) — LIKE on name + staff no - StaffController GET /api/usr/staffs?keyword=&limit= - UserListVO + UserMapper.xml: expose iStaffId so edit mode preserves the binding when user doesn't change 员工名 Frontend: - api/staff.ts → searchStaff() - StaffPicker.tsx: input + dropdown with debounced search, '已绑定' badge when an iStaffId is bound, click outside to close, search icon - UserDetail: replace 员工名 PrimInput with StaffPicker; track iStaffId in form state; send to backend on save (no longer omitted)