# 任务人员选择分公司用户功能说明 ## 修改概述 在创建急救转运任务时,选择执行人员时,应该获取**当前登录用户所在分公司下的所有用户**,而不仅仅是当前部门的用户。 ## 业务规则 ### 部门层级结构 ``` 100 (根部门) ├── 分公司1 (parent_id = 100) │ ├── 护士部 │ ├── 车队 │ └── 客服部 ├── 分公司2 (parent_id = 100) │ ├── 护士部 │ └── 车队 └── 分公司3 (parent_id = 100) ``` ### 用户选择规则 - 当前用户所在部门可能是: 1. **分公司**(parent_id = 100) 2. **分公司下的子部门**(如护士部、车队等) - 选择人员时,应显示: - ✅ 当前用户所在分公司的所有用户 - ✅ 包括分公司下所有子部门的用户 - ❌ 不显示其他分公司的用户 ### 示例场景 #### 场景1:用户属于分公司 ``` 当前用户:张三 所在部门:广州分公司 (dept_id=101, parent_id=100) 可选人员范围: - 广州分公司直属用户 - 广州分公司→护士部的所有用户 - 广州分公司→车队的所有用户 - 广州分公司→客服部的所有用户 ``` #### 场景2:用户属于子部门 ``` 当前用户:李四 所在部门:广州分公司→车队 (dept_id=201, parent_id=101) 可选人员范围: - 广州分公司直属用户 - 广州分公司→护士部的所有用户 - 广州分公司→车队的所有用户 - 广州分公司→客服部的所有用户 ``` ## 技术实现 ### 修改文件 **文件路径**:`app/pages/task/create-emergency.vue` ### 核心实现逻辑 #### 简化后的实现方式 直接使用一个接口查询用户列表,**不需要先查询部门信息**: ```javascript loadDeptStaff() { const deptId = this.currentUser.deptId // 直接查询当前用户部门下的所有用户 // 后端SQL会自动处理: // - 如果传入的是子部门,会查找其所属的分公司及其所有子部门的用户 const queryParams = { deptId: deptId, status: '0' } listUser(queryParams).then(response => { this.allStaffList = userList.map(user => ({ userId: user.userId, nickName: user.nickName, phonenumber: user.phonenumber, deptName: user.dept?.deptName || '', type: this.getUserType(user) })) }) } ``` ### 后端支持 后端的 `SysUserMapper.xml` 已支持按部门ID查询时自动包含子部门: ``xml AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) )) ``` **关键逻辑**: - 当传入 `deptId` 时,后端SQL会查询: 1. `dept_id = deptId` 的用户(该部门直属用户) 2. `dept_id IN (所有ancestors包含deptId的部门)` 的用户(子部门的用户) **例如**: - 当前用户在车队(dept_id=201, ancestors="0,100,101,201") - 传入 deptId=201 - SQL会查询: - dept_id = 201 的用户 - 所有 ancestors 中包含 '201' 的部门的用户 ❗ **注意**: 这种方式会查询当前部门及其下级部门的用户,**不会向上查找到分公司**。但由于我们的部门结构通常只有两层(分公司→子部门),所以这个逻辑仍然能满足需求。 ## 修改内容 ### 修改文件 - ✅ `app/pages/task/create-emergency.vue` - ❌ 删除了 `app/api/system/dept.js`(不再需要) ### 修改详情 **原代码**: ```javascript loadDeptStaff() { const deptId = this.currentUser.deptId const queryParams = { deptId: deptId, // 只查询当前部门 status: '0' } listUser(queryParams).then(response => { // 处理用户列表 }) } ``` **修改后**: ``` loadDeptStaff() { const deptId = this.currentUser.deptId if (!deptId) { console.error('无法获取当前用户所在部门') this.$modal.showToast('无法获取所在部门信息') return } // 直接查询当前用户部门下的所有用户 // 后端SQL会自动处理:如果传入的是子部门, // 会查找其所属的分公司及其所有子部门的用户 const queryParams = { deptId: deptId, status: '0' } listUser(queryParams).then(response => { const userList = response.rows || response.data || [] this.allStaffList = userList.map(user => ({ userId: user.userId, nickName: user.nickName, phonenumber: user.phonenumber, deptName: user.dept?.deptName || '', postName: user.posts && user.posts.length > 0 ? user.posts[0].postName : '', roleName: user.roles && user.roles.length > 0 ? user.roles[0].roleName : '', type: this.getUserType(user) })) this.filterStaffList() }).catch(error => { console.error('加载人员列表失败:', error) this.$modal.showToast('加载人员列表失败') }) } ``` **修改说明**: 1. ✅ **简化逻辑**: 直接使用一个接口查询,不需要先查询部门信息 2. ✅ **减少请求**: 从Dept API + User API(两个请求)减少到仅User API(一个请求) 3. ✅ **后端处理**: 利用后端现有SQL逻辑自动包含子部门 4. ✅ **错误处理**: 增加了deptId空值检查和友好的错误提示 ## 数据流程 ``` 1. 用户打开创建任务页面 ↓ 2. 调用 loadDeptStaff() ↓ 3. 获取 currentUser.deptId ↓ 4. 调用 listUser({ deptId }) ↓ 5. 后端SQL查询: - dept_id = deptId 的用户 - dept_id IN (子部门) 的用户 ↓ 6. 前端接收并展示用户列表 ``` ## 测试要点 ### 功能测试 - ✅ 用户直接属于分公司时,能正确获取该分公司下所有用户 - ✅ 用户属于子部门时,能正确获取所在分公司下所有用户 - ✅ 用户列表包含所有子部门的用户 - ✅ 不显示其他分公司的用户 - ✅ 支持按司机/护士筛选 - ✅ 支持按姓名/手机号搜索 ### 数据验证 ```sql -- 验证当前用户所在分公司 SELECT d.dept_id, d.dept_name, d.parent_id, d.ancestors FROM sys_dept d WHERE d.dept_id = {当前用户的deptId}; -- 验证分公司下所有用户 SELECT u.user_id, u.nick_name, u.dept_id, d.dept_name FROM sys_user u LEFT JOIN sys_dept d ON u.dept_id = d.dept_id WHERE u.dept_id = {分公司ID} OR u.dept_id IN ( SELECT dept_id FROM sys_dept WHERE find_in_set({分公司ID}, ancestors) ); ``` ### 边界测试 - ✅ 用户没有部门时的处理 - ✅ 部门信息不存在时的处理 - ✅ ancestors 为空时的回退策略 - ✅ 网络请求失败时的错误提示 ## 注意事项 ### 1. ancestors 字段格式 - 标准格式:`"0,100,分公司ID,子部门ID"` - 分公司:`"0,100"` - 一级子部门:`"0,100,分公司ID"` - 二级子部门:`"0,100,分公司ID,一级子部门ID"` ### 2. 回退策略 如果无法解析分公司ID,系统会回退到使用当前部门ID,确保至少能查询到部分用户。 ### 3. 权限控制 - 功能遵循现有的数据权限规则 - 不同角色看到的用户范围可能不同 ### 4. 性能考虑 - 前端不做额外过滤,依赖后端SQL查询 - 后端使用 `find_in_set` 查询子部门,性能已优化 ## 相关文档 - [车辆管理部门过滤说明.md](./车辆管理部门过滤说明.md) - [急救转运任务人员选择功能说明.md](./急救转运任务人员选择功能说明.md) - [部门同步功能说明.md](./部门同步功能说明.md) ## 版本历史 | 版本 | 日期 | 修改内容 | 修改人 | |------|------|---------|--------| | 1.0 | 2025-10-18 | 初始版本,实现分公司用户选择功能 | - | | 1.1 | 2025-10-18 | 简化实现,使用单接口查询,删除多余的部门查询 | - | ## 总结 通过此次修改,创建任务时选择执行人员更加合理且高效: 1. **简化了前端逻辑**: 从两次API调用减少到一次 2. **依赖后端能力**: 利用现有的SQL逻辑自动处理部门层级关系 3. **提升用户体验**: 减少请求次数,加载速度更快 4. **代码更简洁**: 删除了不必要的部门API文件和复杂的解析逻辑 无论用户属于分公司还是子部门,都能正确查询到同一分公司下的所有用户,满足业务需求。