260609-自定义组件使用说明.md 7.9 KB

人员选择器组件使用说明

概述

为满足其他页面(如面试不通过原因登记、重点关注人员管理、岗位推荐等)需要选择人员的场景,基于人员信息列表的查询表单和数据表格,封装了一套可复用的人员选择器组件,支持单选/多选,并通过 v-model 将选中的完整人员记录返回给父组件。

涉及文件

文件路径(相对于项目根目录 zjrs-jeecgBoot 操作 说明
jeecgboot-vue3/src/views/recruitment/personal/components/PersonalInfoSelectorModal.vue 新建 选择器弹窗组件,包含查询表单和 BasicTable 表格,支持单/多选行,通过 @select 事件返回选中记录
jeecgboot-vue3/src/views/recruitment/personal/components/PersonalInfoSelector.vue 新建 带输入框载体的组合组件,封装了触发输入框 + 弹窗的完整交互,通过 v-model 双向绑定选中数据

组件层级

PersonalInfoSelector.vue         ← 对外暴露的入口组件
  └─ 输入框(只读,点击触发弹窗)
  └─ PersonalInfoSelectorModal.vue  ← 内部弹窗
       ├─ 查询表单(姓名、性别、学历、户口所在地、现居住地、年龄范围、求职人员类别、求职状态、数据来源)
       └─ BasicTable(含字典渲染、行选择、分页)

快速使用

在任意父页面引入 PersonalInfoSelector.vue 即可:

<template>
  <!-- 多选 -->
  <PersonalInfoSelector v-model="selectedPersons" selectionType="multiple" width="360" />

  <!-- 单选 -->
  <PersonalInfoSelector v-model="selectedPerson" selectionType="single" width="300" placeholder="请选择单个人员" />
</template>

<script setup>
  import PersonalInfoSelector from '/@/views/recruitment/personal/components/PersonalInfoSelector.vue';

  // 多选:v-model 绑定的值为人员记录数组
  const selectedPersons = ref([]);

  // 单选:v-model 绑定的值为人员记录对象或 null
  const selectedPerson = ref(null);
</script>

实际使用示例

以下为面试不通过原因登记表单中的使用方式(单选模式,选择人员后自动填充关联字段):

<template>
  <a-col :span="12">
    <a-form-item label="姓名" name="fullName">
      <PersonalInfoSelector
        v-model:value="selectedPerson"
        selectionType="single"
        placeholder="请选择人员"
        :allowClear="false"
      />
    </a-form-item>
  </a-col>
</template>

<script setup>
  import PersonalInfoSelector from '/@/views/recruitment/personal/components/PersonalInfoSelector.vue';
  import { useDict } from '/@/hooks/dictionary/useDict';

  const { getDictText } = useDict(['Gender']);

  // 人员选择器绑定值(单选模式,值为人员记录对象或 null)
  const selectedPerson = ref(null);

  // 监听人员选择,自动填充性别、年龄、户口所在地等字段
  watch(selectedPerson, (val) => {
    if (val) {
      formData.fullName = val.fullName || '';
      formData.gender = getDictText('Gender', val.gender) || '';
      formData.age = calcAge(val.birthDate);
      formData.householdAreaName = val.householdAreaName || '';
      formData.personalId = val.id || '';
    } else {
      formData.fullName = '';
      formData.gender = '';
      formData.age = '';
      formData.householdAreaName = '';
      formData.personalId = '';
    }
  });

  // 编辑时恢复已选人员状态
  // 在 edit() 方法中根据已有数据构造 selectedPerson 对象,组件会自动回显
  if (formData.fullName) {
    selectedPerson.value = {
      id: formData.personalId || '',
      fullName: formData.fullName,
      gender: formData.gender || '',
      age: formData.age || '',
      householdAreaName: formData.householdAreaName || '',
    };
  }
</script>

完整实现参见 jeecgboot-vue3/src/views/interviewfail/reason/components/InterviewFailReasonForm.vue

PersonalInfoSelector.vue(推荐使用者用)

带触发输入框的完整选择器,直接用于表单中。

Props

参数 类型 默认值 说明
modelValue any v-model 绑定值(标准写法)。单选传对象 { id, fullName, ... },多选传数组
value any v-model:value 绑定值(兼容命名写法),与 modelValue 二选一
selectionType 'single' \| 'multiple' 'multiple' 选择模式
placeholder string '请选择人员' 输入框占位文本
width string \| number 输入框宽度(如 '300px'300
allowClear boolean true 是否允许输入框右侧一键清除已选项

Events

事件 参数 说明
update:modelValue value: any v-model 更新事件
update:value value: any v-model:value 更新事件(兼容写法)
change records: any[] 选中记录变化时触发,始终返回数组

交互流程

  1. 点击输入框 → 打开选择弹窗
  2. 弹窗中可通过查询条件筛选人员
  3. 勾选行后点"确认选择"
  4. 弹窗关闭,输入框中显示选中人员的姓名(多选以中文逗号分隔)
  5. 点输入框右侧清除图标可清空已选
  6. 再次打开弹窗时,已选人员会自动回显为选中状态(通过传入 selectedKeysselectedRecords 实现)

PersonalInfoSelectorModal.vue(低层弹窗)

仅供 PersonalInfoSelector.vue 内部使用,也可单独引用以自定义触发方式。

暴露方法

方法 参数 说明
open(config) { selectionType?: 'single' \| 'multiple', selectedKeys?: (string \| number)[], selectedRecords?: any[] } 打开弹窗。selectionType 默认 'multiple'selectedKeys 用于回显勾选状态;selectedRecords 用于回显勾选并提供完整的选中数据

Events

事件 参数 说明
select records: any[] 确认选择时触发,返回选中行的完整记录数组

单独使用示例

<template>
  <a-button @click="openSelector">选择人员</a-button>
  <PersonalInfoSelectorModal ref="selectorModal" @select="handleSelect" />
</template>

<script setup>
  import PersonalInfoSelectorModal from './components/PersonalInfoSelectorModal.vue';
  const selectorModal = ref();

  function openSelector() {
    selectorModal.value.open({ selectionType: 'single' });
  }

  function handleSelect(records) {
    console.log('选中的人员:', records);
  }
</script>

设计要点

  • 查询表单完整复用了人员信息列表的字段,包含姓名、性别、学历、户口所在地(行政区划树)、年龄范围等。
  • 字典渲染通过 useDict 预加载,表格中性别、学历、民族、求职状态等字段自动转为中文显示。
  • 行选择通过 computed 动态计算 rowSelection,根据 selectionType 切换为 checkbox(多选)或 radio(单选)。
  • 自定义选择列兼容:项目使用 useCustomSelection 自封装选择列(非 ant-design-vue 原生 rowSelection),弹窗打开时通过 useTable 返回的 setSelectedRowKeys API 程序化设置选中行,确保自定义选择列正确回显。
  • onChange 合并处理:行选择变更时保留不在当前页的已选记录,替换当前页的选中记录,支持跨页选择场景。
  • 已选回显:再次打开弹窗时,将已选记录的 selectedKeysselectedRecords 一并传入,确保勾选状态和确认数据完整。
  • 年龄查询beforeFetch 钩子中自动将输入的年龄范围转换为出生日期范围传给后端。
  • 输入框清除allowCleartrue 时,清除按钮将 v-model 重置为空值(单选为 null,多选为 [])。
  • 弹窗渲染时序open() 中先设置 visible = true,再通过 nextTick 等待弹窗 DOM 渲染完成后执行 reload()setSelectedRowKeys(),避免表格实例未就绪导致报错。