编辑 | blame | 历史 | 原始文档

StaffSelector 组件分公司用户加载功能说明

📋 功能概述

优化 StaffSelector 组件,支持通过外部传入分公司ID列表来加载指定分公司的用户,提供更灵活的人员选择功能。


🔄 修改内容

1. 后端接口新增

文件: SysUserController.java

新增接口: GET /system/user/branch/users/by-dept-ids

/**
 * 根据分公司ID列表获取用户(小程序端专用)
 * 支持外部传入分公司ID数组,查询这些分公司及其所有子部门的用户
 */
@GetMapping("/branch/users/by-dept-ids")
public AjaxResult listUsersByBranchDeptIds(Long[] branchDeptIds)

参数:
- branchDeptIds: 分公司ID数组,例如 [101, 102]

返回数据:
json { "code": 200, "msg": "操作成功", "data": [ { "userId": 1, "nickName": "张三", "phonenumber": "13800138000", "dept": { "deptId": 201, "deptName": "广州分公司-车队A" }, "posts": [...], "roles": [...] } ] }


2. 前端API扩展

文件: app/api/system/user.js

新增方法:
javascript // 根据分公司ID列表查询用户(小程序端专用) export function listUsersByBranchDeptIds(branchDeptIds) { return request({ url: '/system/user/branch/users/by-dept-ids', method: 'get', params: { branchDeptIds: branchDeptIds } }) }


3. StaffSelector 组件升级

文件: app/pagesTask/components/StaffSelector.vue

新增 Props:
```javascript
props: {
// ... 其他 props

// 分公司ID列表(外部传入,用于指定加载哪些分公司的用户)
branchDeptIds: {
type: Array,
default: null
}
}
```

核心逻辑:
javascript loadStaffList() { // 如果传入了分公司ID,使用指定的分公司 if (this.branchDeptIds && this.branchDeptIds.length > 0) { this.loadStaffByBranchDeptIds(this.branchDeptIds) } else { // 否则使用当前用户的分公司 this.loadStaffByCurrentUser() } }

监听变化:
javascript watch: { branchDeptIds: { handler(newVal, oldVal) { if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) { this.loadStaffList() } }, deep: true } }


📖 使用方式

方式一: 默认加载(使用当前用户的分公司)

<template>
  <staff-selector 
    v-model="selectedStaff"
    label="执行任务人员"
    :required="true"
  />
</template>

<script>
import StaffSelector from '@/components/StaffSelector.vue'

export default {
  components: { StaffSelector },
  data() {
    return {
      selectedStaff: []
    }
  }
}
</script>

行为:
- 自动调用 /system/user/branch/users 接口
- 加载当前登录用户所属分公司及其子部门的所有用户


方式二: 指定分公司ID(外部传入)

<template>
  <view>
    <!-- 分公司选择器 -->
    <view class="form-item">
      <view class="form-label">选择分公司</view>
      <picker 
        mode="multiSelector" 
        @change="onBranchChange"
        :value="selectedBranchIndex"
        :range="branchList"
        range-key="deptName"
      >
        <view class="picker-value">
          {{ selectedBranchNames || '请选择分公司' }}
        </view>
      </picker>
    </view>
    
    <!-- 人员选择器 -->
    <staff-selector 
      v-model="selectedStaff"
      label="执行任务人员"
      :required="true"
      :branch-dept-ids="selectedBranchIds"
    />
  </view>
</template>

<script>
import StaffSelector from '@/components/StaffSelector.vue'
import { listBranchCompany } from '@/api/system/dept'

export default {
  components: { StaffSelector },
  data() {
    return {
      branchList: [],           // 所有分公司列表
      selectedBranchIds: [],    // 选中的分公司ID数组
      selectedBranchNames: '',  // 选中的分公司名称
      selectedStaff: []         // 选中的人员
    }
  },
  mounted() {
    this.loadBranchList()
  },
  methods: {
    // 加载分公司列表
    loadBranchList() {
      listBranchCompany().then(response => {
        this.branchList = response.data || []
      })
    },
    
    // 分公司选择变化
    onBranchChange(e) {
      const indices = e.detail.value
      const selected = indices.map(index => this.branchList[index])
      
      this.selectedBranchIds = selected.map(dept => dept.deptId)
      this.selectedBranchNames = selected.map(dept => dept.deptName).join('、')
      
      console.log('选中的分公司ID:', this.selectedBranchIds)
    }
  }
}
</script>

行为:
- 用户选择分公司后,selectedBranchIds 更新
- StaffSelector 监听到 branchDeptIds 变化
- 自动调用 /system/user/branch/users/by-dept-ids?branchDeptIds=101,102
- 加载指定分公司及其子部门的所有用户


方式三: 动态切换分公司

<template>
  <view>
    <!-- Tab 切换分公司 -->
    <view class="tabs">
      <view 
        class="tab-item"
        :class="{ active: currentBranchId === branch.deptId }"
        v-for="branch in branchList"
        :key="branch.deptId"
        @click="switchBranch(branch)"
      >
        {{ branch.deptName }}
      </view>
    </view>
    
    <!-- 人员选择器 -->
    <staff-selector 
      v-model="selectedStaff"
      label="执行任务人员"
      :branch-dept-ids="[currentBranchId]"
    />
  </view>
</template>

<script>
import StaffSelector from '@/components/StaffSelector.vue'
import { listBranchCompany } from '@/api/system/dept'

export default {
  components: { StaffSelector },
  data() {
    return {
      branchList: [],
      currentBranchId: null,
      selectedStaff: []
    }
  },
  mounted() {
    this.loadBranchList()
  },
  methods: {
    loadBranchList() {
      listBranchCompany().then(response => {
        this.branchList = response.data || []
        if (this.branchList.length > 0) {
          // 默认选中第一个分公司
          this.currentBranchId = this.branchList[0].deptId
        }
      })
    },
    
    switchBranch(branch) {
      this.currentBranchId = branch.deptId
      // branchDeptIds 变化会自动触发 StaffSelector 重新加载
    }
  }
}
</script>

🔑 Props 说明

Props 类型 默认值 说明
value Array [] 已选择的人员列表(v-model)
label String '执行任务人员' 标签文本
required Boolean false 是否必填
autoAddCurrentUser Boolean true 是否自动添加当前用户
currentUserRemovable Boolean false 当前用户是否可移除
branchDeptIds Array null 分公司ID列表(新增)

📊 数据流程

默认模式(不传 branchDeptIds)

1. 组件 mounted
   ↓
2. loadStaffList()
   ↓
3. 判断 branchDeptIds 为空
   ↓
4. 调用 listBranchUsers()
   ↓
5. 后端根据当前用户的 oaOrderClass 或 deptId 查询分公司
   ↓
6. 返回该分公司及其子部门的所有用户
   ↓
7. processUserList() 处理数据
   ↓
8. 展示用户列表

指定模式(传入 branchDeptIds)

1. 组件 mounted
   ↓
2. loadStaffList()
   ↓
3. 判断 branchDeptIds 有值
   ↓
4. 调用 listUsersByBranchDeptIds(branchDeptIds)
   ↓
5. 后端根据传入的分公司ID列表查询
   ↓
6. 返回指定分公司及其子部门的所有用户
   ↓
7. processUserList() 处理数据
   ↓
8. 展示用户列表

动态切换

1. 父组件修改 branchDeptIds
   ↓
2. StaffSelector 监听到变化(watch)
   ↓
3. 重新执行 loadStaffList()
   ↓
4. 根据新的 branchDeptIds 加载用户
   ↓
5. 更新用户列表

⚡ 性能优化

1. 避免重复加载

watch: {
  branchDeptIds: {
    handler(newVal, oldVal) {
      // 只有真正变化时才重新加载
      if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
        this.loadStaffList()
      }
    },
    deep: true
  }
}

2. 前端缓存

可以在父组件层面缓存用户列表:
javascript data() { return { userCache: {} // { '101': [...users], '102': [...users] } } }


✅ 测试用例

测试1: 默认加载

输入: 不传 branchDeptIds
预期: 加载当前用户的分公司用户
验证: 检查用户列表是否符合预期

测试2: 单个分公司

输入: branchDeptIds: [101]
预期: 只加载 ID=101 的分公司及其子部门用户
验证: 检查用户部门是否都属于该分公司

测试3: 多个分公司

输入: branchDeptIds: [101, 102]
预期: 加载两个分公司及其子部门的用户
验证: 检查用户部门是否都属于这两个分公司

测试4: 动态切换

操作: 先传 [101],再改为 [102]
预期: 用户列表实时更新
验证: 检查两次加载的用户是否不同

测试5: 空数组

输入: branchDeptIds: []
预期: 返回空列表
验证: 用户列表为空


💡 使用建议

场景1: 跨分公司协作任务

当任务需要多个分公司的人员协作时:
vue <staff-selector :branch-dept-ids="[101, 102, 103]" label="跨区域协作人员" />

场景2: 区域筛选

提供区域选择器,用户自选分公司:
vue <region-selector v-model="selectedRegions" /> <staff-selector :branch-dept-ids="selectedRegions.map(r => r.deptId)" />

场景3: 权限控制

根据用户权限动态限制可选分公司:
javascript computed: { allowedBranchIds() { // 根据用户角色返回允许的分公司ID return this.currentUser.allowedBranches.map(b => b.deptId) } }


📌 注意事项

  1. 数组传递: branchDeptIds 必须是数组类型,即使只有一个ID也要用数组 [101]
  2. 动态更新: 修改 branchDeptIds 会自动触发重新加载,无需手动调用
  3. 空值处理: 传入 null 或不传时,使用默认的当前用户分公司
  4. 权限校验: 后端会根据用户权限过滤数据,前端无需额外处理

🔗 相关文件

后端

  • SysUserController.java - 用户控制器
  • SysUserService.java - 用户服务接口
  • SysUserServiceImpl.java - 用户服务实现
  • SysUserMapper.xml - SQL映射文件

前端

  • app/api/system/user.js - 用户API
  • app/pagesTask/components/StaffSelector.vue - 人员选择器组件
  • app/api/system/dept.js - 部门API

📝 版本历史

版本 日期 说明
1.0 2025-12-04 初始版本,新增按分公司ID加载用户功能