lifanagju_citu 8 ماه پیش
والد
کامیت
a15038eb1e

+ 16 - 1
src/api/recruit/enterprise/personnel/index.js

@@ -35,4 +35,19 @@ export const personCvUnfitCancel = async (id) => {
   return await request.post({
     url: `/app-api/menduner/system/recruit/person-cv/unfit/cancellation?id=${id}`
   })
-}
+}
+
+// 招聘端-牛人管理-加入人才库
+export const joinToTalentPool = async (id) => {
+  return await request.post({
+    url: `/app-api/menduner/system/enterprise-talent-pool/add?userId=${id}`
+  })
+}
+
+// 招聘端-牛人管理-移出人才库
+export const removeFormTalentPool = async (id) => {
+  return await request.post({
+    url: `/app-api/menduner/system/enterprise-talent-pool/remove?userId=${id}`
+  })
+}
+

+ 9 - 0
src/api/recruit/enterprise/resumeManagement/talentPool/index.js

@@ -0,0 +1,9 @@
+import request from '@/config/axios'
+
+// 招聘端-牛人管理-人才库 - 分页查询企业人才库信息
+export const getTalentPoolPage = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/enterprise-talent-pool/page',
+    params
+  })
+}

+ 10 - 1
src/views/recruit/enterprise/resumeManagement/elite/components/table.vue

@@ -31,6 +31,7 @@
         <v-btn v-if="tab === 0" color="primary" variant="text" @click="handleInterviewInvite(item)">邀请面试</v-btn>
         <v-btn v-if="tab === 0" color="primary" variant="text" @click="handleToCommunicate(item)">立即沟通</v-btn>
         <v-btn v-if="tab === 0 || tab === 1" color="primary" variant="text" @click="handleEliminate(item)">不合适</v-btn>
+        <v-btn v-if="!item.inTalentPool && (tab === 1 || tab === 2 || tab === 3)" color="primary" variant="text" @click="handleJoinToTalentPool(item)">加入人才库</v-btn>
         <v-btn v-if="tab === 1 && (item.status === '3' || item.status === '4')" color="primary" variant="text" @click="handleEnterByEnterprise(item)">入职</v-btn>
         <v-btn v-if="tab === 4" color="primary" variant="text" @click="handleCancelEliminate(item)">取消不合适</v-btn>
         <v-btn v-if="tab === 2 && item?.job?.hire" color="primary" variant="text" @click="handleSettlement(item)">结算</v-btn>
@@ -49,7 +50,7 @@
 defineOptions({ name: 'table-page'})
 import { ref, computed, watch } from 'vue'
 import { previewFile } from '@/utils'
-import { personJobCvLook, joinEliminate, personEntryByEnterprise, personCvUnfitCancel } from '@/api/recruit/enterprise/personnel'
+import { personJobCvLook, joinEliminate, personEntryByEnterprise, personCvUnfitCancel, joinToTalentPool } from '@/api/recruit/enterprise/personnel'
 import { saveInterviewInvite } from '@/api/recruit/enterprise/interview'
 import { hireJobCvRelSettlement } from '@/api/recruit/public/delivery'
 import { useI18n } from '@/hooks/web/useI18n'
@@ -119,6 +120,14 @@ const handleToPersonDetail = ({ userId, id }) => {
   window.open(`/recruit/enterprise/resumeManagement/talentPool/details/${userId}?id=${id}`)
 }
 
+// 加入人才库 
+const handleJoinToTalentPool = async (item) => {
+  if (!item.userId) return Snackbar.warning('数据异常')
+  await joinToTalentPool(item.userId)
+  Snackbar.success(t('common.operationSuccessful'))
+  emit('refresh')
+}
+
 // 入职
 const handleEnterByEnterprise = async (item) => {
   if (!item.id) return

+ 4 - 2
src/views/recruit/enterprise/resumeManagement/talentMap/components/filter.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="px-5 py-3" style="position: relative;">
+  <div class="px-5 pt-1 py-15" style="position: relative;">
     <h3 class="my-3" style="color: var(--v-primary-base);">条件筛选</h3>
     <!-- <v-divider class="my-3"></v-divider>
     <div class="text-right reset-text cursor-pointer" @click="handleReset">重置筛选</div> -->
@@ -303,7 +303,9 @@ defineExpose({
   position: fixed;
   width: 96%;
   margin: 0 12px;
-  bottom: 14px;
+  bottom: 0;
   left: 0;
+  padding-bottom: 14px;
+  background-color: #fff;
 }
 </style>

+ 0 - 3
src/views/recruit/enterprise/resumeManagement/talentMap/index.vue

@@ -95,8 +95,6 @@ const getData = async () => {
   const obj = { ...pageInfo, ...query }
   // console.log('obj', obj)
   const { list, total: number } = await getRecruitPersonMapPage(obj)
-  // const { list, total: number } = dataTest
-  //
   total.value = number
   dataList.value = list?.length ? dealDictArrayData([], list) : []
 }
@@ -122,7 +120,6 @@ const advantageDetail = (advantage) => {
   advantageShow.value = true
 }
 
-
 const FilterPageRef = ref()
 const openDrawer = () => {
   screen.value = true

+ 295 - 102
src/views/recruit/enterprise/resumeManagement/talentPool/components/filter.vue

@@ -1,107 +1,189 @@
 <template>
-  <div class="px-5 py-3" style="position: relative;">
-    <h3 style="color: var(--v-primary-base);">条件筛选</h3>
-    <v-divider class="my-3"></v-divider>
-    <div class="text-right reset-text cursor-pointer" @click="handleReset">重置筛选</div>
+  <div class="px-5 pt-1 py-15" style="position: relative;">
+    <h3 class="my-3" style="color: var(--v-primary-base);">条件筛选</h3>
+    <!-- <v-divider class="my-3"></v-divider>
+    <div class="text-right reset-text cursor-pointer" @click="handleReset">重置筛选</div> -->
     <CtForm ref="CtFormRef" :items="formItems" style="width: 100%;">
-      <template #areaIds="{ item }">
+      <!-- 期望岗位 -->
+      <template #positionId="{ item }">
         <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs">
           <template v-slot:activator="{  props }">
-            <TextInput
+            <textUI
               v-model="item.value"
               :item="item"
               v-bind="props"
               style="position: relative;"
-            ></TextInput>
+              @handleClear="handleJobClickItem()"
+            ></textUI>
           </template>
-          <AreaSelect :select="[query.areaIds].filter(Boolean)" @handleAreaClick="handleArea" class="jobTypeCardBox" isSingle></AreaSelect>
-        </v-menu>
-      </template>
-      <template #residence="{ item }">
-        <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs">
-          <template v-slot:activator="{  props }">
-            <TextInput
-              v-model="item.value"
-              :item="item"
-              v-bind="props"
-              style="position: relative;"
-            ></TextInput>
-          </template>
-          <AreaSelect :select="[query.residence].filter(Boolean)" @handleAreaClick="handleResidence" class="jobTypeCardBox" isSingle></AreaSelect>
+          <jobTypeCard class="jobTypeCardBox" :select="[item[item.valueKey]].filter(Boolean)" :isSingle="true" @handleJobClick="handleJobClickItem"></jobTypeCard>
         </v-menu>
       </template>
     </CtForm>
     <div class="bottom">
       <v-divider></v-divider>
-      <div class="text-end mt-3">
-        <v-btn class="half-button mr-3" variant="tonal">取消</v-btn>
-        <v-btn class="half-button" color="primary">确定</v-btn>
+      <div class="d-flex justify-space-between mt-3">
+        <div class="ml-3">
+          <v-btn class="half-button mr-3" color="primary" @click="confirm">筛选</v-btn>
+          <v-btn class="half-button mr-3" variant="tonal" @click="emit('cancel')">取消</v-btn>
+        </div>
+        <v-btn class="half-button ml-3" variant="tonal" color="orange" @click="handleReset">重置</v-btn>
       </div>
     </div>
   </div>
 </template>
 
 <script setup>
-defineOptions({ name: 'talent-filter'})
+defineOptions({ name: 'talent-pool-filter'})
+import { getRocketLabelList } from '@/api/recruit/enterprise/resumeManagement/talentMap'
+
+import jobTypeCard from '@/components/jobTypeCard'
+import textUI from '@/components/FormUI/TextInput'
+import { getDict } from '@/hooks/web/useDictionaries'
+import Snackbar from '@/plugins/snackbar'
 import { ref } from 'vue'
+const emit = defineEmits(['cancel', 'confirm'])
 
 const CtFormRef = ref()
-const query = ref({})
 const formItems = ref({
   options: [
     {
-      type: 'ifRadio',
+      type: 'text',
+      key: 'name',
+      value: '',
+      label: '姓名 ',
+      col: 12
+    },
+    {
+      type: 'autocomplete',
       key: 'sex',
-      value: '0',
-      default: 0,
-      label: '性别',
-      width: 90,
+      value: null,
+      default: null,
+      label: '工作经验',
+      outlined: true,
+      itemText: 'label',
+      itemValue: 'value',
       dictTypeName: 'menduner_sex',
-      items: [
-        { label: '不限', value: '0' },
-        { label: '男', value: '1' },
-        { label: '女', value: '1' }
-      ]
+      items: []
     },
+    // {
+    //   type: 'ifRadio',
+    //   key: 'sex',
+    //   value: '0',
+    //   default: 0,
+    //   label: '人才分类',
+    //   width: 90,
+    //   items: [
+    //     { label: '不限', value: '0' },
+    //     { label: '默认分类', value: '1' }
+    //   ]
+    // },
+    // {
+    //   type: 'ifRadio',
+    //   key: 'type',
+    //   value: '0',
+    //   default: 0,
+    //   label: '简历状态',
+    //   width: 120,
+    //   items: [
+    //     { label: '不限', value: '0' },
+    //     { label: '已查看', value: '1' },
+    //     { label: '未查看', value: '2' },
+    //     { label: '已导出', value: '3' },
+    //     { label: '已邀请', value: '4' },
+    //     { label: '已回复', value: '5' },
+    //     { label: '有评语', value: '6' }
+    //   ],
+    // },
     {
-      type: 'ifRadio',
-      key: 'sex',
-      value: '0',
-      default: 0,
-      label: '人才分类',
-      width: 90,
-      items: [
-        { label: '不限', value: '0' },
-        { label: '默认分类', value: '1' }
-      ]
+      type: 'text',
+      key: 'email',
+      value: '',
+      label: '联系邮箱 ',
     },
     {
-      type: 'ifRadio',
-      key: 'type',
-      value: '0',
-      default: 0,
-      label: '简历状态',
-      width: 120,
-      items: [
-        { label: '不限', value: '0' },
-        { label: '已查看', value: '1' },
-        { label: '未查看', value: '2' },
-        { label: '已导出', value: '3' },
-        { label: '已邀请', value: '4' },
-        { label: '已回复', value: '5' },
-        { label: '有评语', value: '6' }
-      ],
+      type: 'phoneNumber',
+      key: 'phone',
+      value: '',
+      label: '联系手机号 ',
+    },
+    {
+      type: 'text',
+      key: 'wxCode',
+      value: '',
+      label: '微信号 ',
+    },
+    // {
+    //   type: 'text',
+    //   key: 'birthday',
+    //   value: '',
+    //   label: '出生日期 ',
+    // },
+    // {
+    //   type: 'autocomplete',
+    //   key: 'labels',
+    //   value: null,
+    //   label: '人员标签 ',
+    //   multiple: true,
+    //   outlined: true,
+    //   itemText: 'label',
+    //   itemValue: 'value',
+    //   items: [
+    //     { label: '标签', value: '0' },
+    //   ]
+    // },
+    // {
+    //   type: 'number',
+    //   key: 'age1',
+    //   value: null,
+    //   label: '年龄区间:起始',
+    // },
+    // {
+    //   type: 'number',
+    //   key: 'age2',
+    //   value: null,
+    //   label: '年龄区间:结束',
+    // },
+    // {
+    //   type: 'number',
+    //   key: 'pay1',
+    //   value: null,
+    //   suffix: '元',
+    //   label: '期望薪资:起始',
+    // },
+    // {
+    //   type: 'number',
+    //   key: 'pay2',
+    //   value: null,
+    //   suffix: '元',
+    //   label: '期望薪资:结束',
+    // },
+    {
+      type: 'areaSelect',
+      key: 'areaIds',
+      value: '',
+      // label: ' ',
+      placeholder: '所在城市', // 暂时只能使用placeholder
+      readonly: true,
+      limit: 1,
+    },
+    {
+      type: 'areaSelect',
+      key: 'regIds',
+      value: '',
+      // label: ' ',
+      placeholder: '户籍所在地', // 暂时只能使用placeholder
+      readonly: true,
+      limit: 1,
     },
     {
       type: 'autocomplete',
-      key: 'expType',
+      key: 'eduType',
       value: null,
       default: null,
       label: '学历',
-      col: 6,
       outlined: true,
       itemText: 'label',
-      flexStyle: 'mr-3',
       itemValue: 'value',
       dictTypeName: 'menduner_education_type',
       items: []
@@ -112,59 +194,168 @@ const formItems = ref({
       value: null,
       default: null,
       label: '工作经验',
-      col: 6,
       outlined: true,
       itemText: 'label',
       itemValue: 'value',
       dictTypeName: 'menduner_exp_type',
       items: []
     },
-    // {
-    //   slotName: 'residence',
-    //   key: 'residence',
-    //   value: null,
-    //   col: 6,
-    //   flexStyle: 'mr-3',
-    //   label: '户籍地'
-    // },
-    // {
-    //   slotName: 'areaIds',
-    //   key: 'areaIds',
-    //   value: null,
-    //   col: 6,
-    //   label: '期望城市'
-    // },
     {
-      type: 'vueDatePicker',
-      key: 'firstWorkTime',
+      slotName: 'positionId',
+      key: 'positionName',
+      value: '',
+      label: '职位类型 ',
+      valueKey: 'positionId', 
+      hideDetails: true,
+      readonly: true,
+      outlined: true,
+    },
+    {
+      type: 'autocomplete',
+      key: 'jobType',
+      value: null,
+      label: '求职类型 ',
+      outlined: true,
+      itemText: 'label',
+      itemValue: 'value',
+      items: [
+        { label: '全职', value: '0' },
+        { label: '兼职', value: '1' },
+        { label: '临时', value: '2' },
+        { label: '实习', value: '3' }
+      ]
+    },
+    {
+      type: 'autocomplete',
+      key: 'jobStatus',
       value: null,
       default: null,
-      class: 'mb-3',
-      options: {
-        type: '',
-        range: true,
-        format: 'timestamp',
-        placeholder: '加入日期',
-      }
+      label: '求职状态 ',
+      outlined: true,
+      itemText: 'label',
+      itemValue: 'value',
+      dictTypeName: 'menduner_job_status',
+      items: []
+    },
+    {
+      type: 'autocomplete',
+      key: 'maritalStatus',
+      value: null,
+      default: null,
+      label: '婚姻状况 ',
+      outlined: true,
+      itemText: 'label',
+      itemValue: 'value',
+      dictTypeName: 'menduner_marital_status',
+      items: []
     },
   ]
 })
 
-const handleReset = () => {}
+// 获取字典内容
+const getDictData = async (item) => {
+  if (item) {
+    const { data } = await getDict(item.dictTypeName)
+    item.items = data
+  }
+}
+
+const getLabelData = async () => {
+  const res = await getRocketLabelList({ current: 1, size:9999, type: 'person' }) //type: job  enterprise person
+  const labels = res?.records || []
+  const labelsItem = formItems.value.options.find(f => f.key === 'labels')
+  if (labelsItem) {
+    labelsItem.items = labels.map(e => ({ label: e, value: e }))
+  }
+}
+getLabelData()
+
+let flexStyle = false
+formItems.value.options.forEach(e => {
+  // 查字典set options
+  if (e.dictTypeName) getDictData(e)
+  // 清除
+  e.clearable = true
+  // 样式
+  if (!e.col) {
+    e.col = 6
+    flexStyle = !flexStyle
+  } else {
+    e.flexStyle = 'mb-3'
+  }
+  if (flexStyle) e.flexStyle = 'mr-3'
+})
+
+// const setOneValue = (key, value) => {
+//   formItems.value.options.find(e => e.key === key).value = value
+// }
 
-// 期望城市
-const handleArea = (list, name) => {
-  if (!list.length) return
-  query.value.workAreaId = list[0]
-  formItems.value.options.find(e => e.key === 'areaIds').value = name
+// 期望职位
+const positionId = ref('')
+const positionName = ref('')
+const handleJobClickItem = (list, name) => {
+  const positionItem = formItems.value.options.find(f => f.key === 'positionName')
+  if (positionItem) {
+    if (list?.length) {
+      positionItem.value = positionName.value = name || ''
+      positionItem[positionItem.valueKey] = positionId.value = list?.length ? list[0] : ''
+    } else {
+      positionItem.value = name || ''
+      positionItem[positionItem.valueKey] = list?.length ? list[0] : ''
+    }
+  }
 }
 
-// 户籍地
-const handleResidence = (list, name) => {
-  if (!list.length) return
-  query.value.residence = list[0]
-  formItems.value.options.find(e => e.key === 'residence').value = name
+const confirm = () => {
+  const obj = {}
+  formItems.value.options.forEach(e => {
+    if (e.key === 'positionName') {
+      if (e.value) {
+        obj[e.valueKey] = positionId.value || ''
+        obj[e.key] = positionName.value || ''
+      }
+    } else if (e.value !== null && e.value !== '' && e.value !== undefined) obj[e.key] = e.value
+  })
+  if (obj.age1 > obj.age2) return Snackbar.warning('年龄区间异常,前者不能大于后者!')
+  if (obj.pay2 > obj.pay1) return Snackbar.warning('期望薪资异常,前者不能大于后者!')
+  //
+  if (obj.age1 || obj.age2) obj.age = [obj.age1 || null, obj.age2 || null].filter(Boolean)
+  if (obj.pay1 || obj.pay2) obj.pay = [obj.pay1 || null, obj.pay2 || null].filter(Boolean)
+  //
+  if (!obj.labels?.length) delete obj.labels
+  emit('confirm', obj)
 }
+
+const resetValue = () => {
+  formItems.value.options.forEach(e => {
+    if (e.key === 'positionName') {
+      e[e.valueKey] = ''
+      e.value = e[e.valueKey] = positionId.value = positionName.value = ''
+    } else {
+      e.value = null
+    }
+  })
+}
+const setValue = (query) => {
+  formItems.value.options.forEach(e => {
+    if (e.key === 'positionName') {
+      e.value = positionName.value = query[e.key]
+      e[e.valueKey] = positionId.value = query[e.valueKey]
+    } else {
+      if (query[e.key] !== undefined) e.value = query[e.key]
+    }
+  })
+}
+
+const handleReset = () => {
+  resetValue()
+  emit('confirm', {})
+}
+
+defineExpose({
+  setValue,
+  resetValue,
+})
 </script>
 
 <style scoped lang="scss">
@@ -177,14 +368,16 @@ const handleResidence = (list, name) => {
 }
 .jobTypeCardBox {
   position: absolute;
-  top: -22px;
+  // top: -22px;
   left: 0;
 }
 .bottom {
   position: fixed;
   width: 96%;
   margin: 0 12px;
-  bottom: 14px;
+  bottom: 0;
   left: 0;
+  padding-bottom: 14px;
+  background-color: #fff;
 }
 </style>

+ 108 - 196
src/views/recruit/enterprise/resumeManagement/talentPool/index.vue

@@ -1,89 +1,56 @@
 <template>
   <v-card class="card-box pa-5">
     <div class="d-flex justify-space-between">
-      <TextUI :item="textItem" @enter="handleEnter" @appendInnerClick="handleEnter"></TextUI>
-      <v-btn color="primary" prependIcon="mdi-filter-multiple-outline" class="half-button" variant="tonal" @click="screen = true">筛选</v-btn>
+      <div></div>
+      <v-btn color="primary" prependIcon="mdi-filter-multiple-outline" class="half-button" variant="tonal" @click="openDrawer">筛选</v-btn>
     </div>
-    <div v-if="items.length" class="d-flex align-center" style="margin-left: 14px;">
-      <v-checkbox v-model="selectAll" :label="!selectAll ? '全选' : `已选中${selectList.length}条`" hide-details color="primary" @update:model-value="handleChangeSelectAll"></v-checkbox>
-      <v-btn class="ml-8" :disabled="!selectAll" color="primary" variant="tonal" size="small">邀请面试</v-btn>
-      <v-btn class="mx-3" :disabled="!selectAll" color="primary" variant="tonal" size="small">简历回复</v-btn>
-      <v-btn :disabled="!selectAll" color="primary" variant="tonal" size="small">批量导出</v-btn>
-      <v-btn class="mx-3" :disabled="!selectAll" color="primary" variant="tonal" size="small">踢出人才库</v-btn>
-      <v-btn :disabled="!selectAll" color="primary" variant="tonal" size="small">移动到回收站</v-btn>
-      <v-btn class="ml-3" :disabled="!selectAll" color="primary" variant="tonal" size="small">加入黑名单</v-btn>
-    </div>
-    <div v-if="items.length">
-      <div v-for="val in items" :key="val.id" class="list-item mb-3">
-        <div class="top">
-          <v-checkbox class="mr-5" v-model="val.select" color="primary" density="compact" hide-details @update:model-value="handleChangeSelect"></v-checkbox>
-          <span>应聘/意向职位:{{ val.job.name }}</span>
-          <span class="mx-10">加入时间:{{ val.createTime }}</span>
-          <span>人才分类:{{ val.type }}</span>
-        </div>
-        <div @click.stop="talentPoolDetails(val)" class="px-5 py-3 d-flex justify-space-between align-center cursor-pointer">
-          <div class="d-flex">
+    <div v-if="dataList?.length" class="mt-3">
+      <v-data-table
+        class="mt-3"
+        :items="dataList"
+        :headers="headers"
+        hover
+        :disable-sort="true"
+        item-value="id"
+      >
+        <template #bottom></template>
+        <template v-slot:[`item.name`]="{ item }">
+          <div class="d-flex align-center cursor-pointer" @click="talentPoolDetails(item)">
             <v-badge
               bordered
-              offset-x="6"
-              offset-y="44"
-              :color="val.sex ? (val.sex === '1' ? '#1867c0' : 'error') : 'error'"
-              :icon="val.sex ? (val.sex === '1' ? 'mdi-gender-male' : 'mdi-gender-female') : 'mdi-gender-female'">
-              <v-avatar size="large" :image="val.avatar || 'https://minio.citupro.com/dev/menduner/7.png'"></v-avatar>
+              offset-y="6"
+              :color="badgeColor(item)"
+              :icon="badgeIcon(item)">
+              <v-avatar size="40" :image="getUserAvatar(item.avatar, item.sex)"></v-avatar>
             </v-badge>
-            <div class="ml-5">
-              <div class="user-name">{{ val.name }}</div>
-              <div class="mt-2 user-info">
-                <span v-for="(k, i) in dict" :key="k">
-                  {{ val[k] }}
-                  <span v-if="i !== dict.length - 1" class="mx-3">|</span>
-                </span>
-              </div>
-            </div>
-          </div>
-          <div>
-            <v-btn color="primary" variant="tonal" @click.stop="{}">和TA聊聊</v-btn>
-            <v-btn class="ml-3" color="primary" @click.stop="{}">邀请面试</v-btn>
-          </div>
-        </div>
-        <div class="d-flex mx-5 bottom cursor-pointer">
-          <div class="experience" v-if="val.exp.length">
-            <div class="second-title">工作经验</div>
-            <v-timeline density="compact" align="start" side="end" truncate-line="both">
-              <v-timeline-item v-for="(j, i) in val.exp" :key="i" dot-color="primary" size="small">
-                <div class="timeline-item mt-1">
-                  <div>{{ j.startTime }}-{{ j.endTime }} ({{ j.year }})</div>
-                  <div class="timeline-item-name ellipsis">{{ j.name }}</div>
-                  <div class="timeline-item-name ellipsis">{{ j.jobName }}</div>
-                </div>
-              </v-timeline-item>
-            </v-timeline>
-          </div>
-          <div class="edu" v-if="val.edu.length">
-            <div class="second-title">教育经历</div>
-            <v-timeline density="compact" align="start" side="end" truncate-line="both">
-              <v-timeline-item v-for="(j, i) in val.edu" :key="i" dot-color="primary" size="small">
-                <div class="timeline-item mt-1">
-                  <div>{{ j.startTime }}-{{ j.endTime }}</div>
-                  <div class="timeline-item-name ellipsis">{{ j.name }}</div>
-                  <div class="timeline-item-name ellipsis">{{ j.major }}</div>
-                </div>
-              </v-timeline-item>
-            </v-timeline>
+            <span class="defaultLink ml-3">{{ item?.name }}</span>
           </div>
-        </div>
-      </div>
+        </template>
+        <template v-slot:[`item.advantage`]="{ item }">
+          <template v-if="item.advantage">
+            <v-btn color="primary" variant="tonal" @click="advantageDetail(item.advantage)">查看</v-btn>
+          </template>
+        </template>
+        <template v-slot:[`item.actions`]="{ item }">
+          <v-btn color="primary" variant="text" @click="handleRemove(item)">踢出人才库</v-btn>
+          <v-btn color="primary" variant="text" @click="talentPoolDetails(item)">人才详情</v-btn>
+        </template>
+      </v-data-table>
       <CtPagination
         :total="total"
-        :page="query.pageNo"
-        :limit="query.pageSize"
+        :page="pageInfo.pageNo"
+        :limit="pageInfo.pageSize"
         @handleChange="handleChangePage"
       ></CtPagination>
     </div>
     <Empty v-else :message="tipsText" :elevation="false" class="mt-15"></Empty>
 
     <v-navigation-drawer v-model="screen" location="right" absolute temporary width="700">
-      <FilterPage></FilterPage>
+      <FilterPage
+        ref="FilterPageRef"
+        @confirm="handleConfirm"
+        @cancel="screen = false"
+      ></FilterPage>
     </v-navigation-drawer>
   </v-card>
 </template>
@@ -92,147 +59,92 @@
 // import { useRouter } from 'vue-router'
 // const router = useRouter()
 defineOptions({ name: 'enterprise-talent-pool'})
-import { ref } from 'vue'
-import TextUI from '@/components/FormUI/TextInput'
+import { useI18n } from '@/hooks/web/useI18n'; const { t } = useI18n()
+import { computed, reactive, ref } from 'vue'
+import Snackbar from '@/plugins/snackbar'
 import FilterPage from './components/filter.vue'
+import { dealDictArrayData } from '@/utils/position'
+import { getTalentPoolPage } from '@/api/recruit/enterprise/resumeManagement/talentPool'
+import { removeFormTalentPool } from '@/api/recruit/enterprise/personnel'
+import { timesTampChange } from '@/utils/date'
+import { getUserAvatar } from '@/utils/avatar'
 
+
+let query = {}
 const screen = ref(false)
-const selectAll = ref(false)
-const selectList = ref([])
-const items = ref([
-  {
-    job: {
-      name: '客房服务员'
-    },
-    createTime: '2026-11-12',
-    type: '默认分类',
-    name: '花城',
-    age: '27岁',
-    expName: '3年经验',
-    areaName: '广州',
-    userId: '1',
-    id: '1793583467288223745',
-    sex: '2',
-    select: false,
-    eduName: '本科',
-    payName: '薪资面议',
-    avatar: 'https://cdn.vuetifyjs.com/images/john.jpg',
-    exp: [
-      {
-        startTime: '2016.05',
-        endTime: '2018.05',
-        year: '2年',
-        name: '广州辞图科技有限公司',
-        jobName: '前台'
-      },
-      {
-        startTime: '2016.05',
-        endTime: '2018.05',
-        year: '2年',
-        name: '广州辞图科技有限公司',
-        jobName: '前台'
-      }
-    ],
-    edu: [
-      {
-        startTime: '2016.05',
-        endTime: '2018.05',
-        name: '广州大学',
-        major: '酒店管理'
-      }
-    ]
-  },
-  {
-    job: {
-      name: '客房服务员'
-    },
-    createTime: '2026-11-12',
-    type: '默认分类',
-    name: '花城',
-    age: '27岁',
-    expName: '3年经验',
-    areaName: '广州',
-    userId: '1',
-    id: '1793583467288223745',
-    sex: '2',
-    select: false,
-    eduName: '本科',
-    payName: '薪资面议',
-    avatar: 'https://cdn.vuetifyjs.com/images/john.jpg',
-    exp: [
-      {
-        startTime: '2016.05',
-        endTime: '2018.05',
-        year: '2年',
-        name: '广州辞图科技有限公司',
-        jobName: '前台'
-      },
-      {
-        startTime: '2016.05',
-        endTime: '2018.05',
-        year: '2年',
-        name: '广州辞图科技有限公司',
-        jobName: '前台'
-      }
-    ],
-    edu: [
-      {
-        startTime: '2016.05',
-        endTime: '2018.05',
-        name: '广州大学',
-        major: '酒店管理'
-      }
-    ]
-  }
-])
-items.value = [] // 暂定无数据展示
+const dataList = ref([])
+// dataList.value = [] // 暂定无数据展示
 const tipsText = ref('暂无数据')
 const total = ref(2)
-const query = ref({
-  pageNo: 1,
-  pageSize: 10
-})
+const pageInfo = reactive({ pageNo: 1, pageSize: 10 })
 
-const textItem = ref({
-  type: 'text',
-  width: 600,
-  value: '',
-  label: '请输入简历姓名/职位名称',
-  appendInnerIcon: 'mdi-magnify'
-})
-const dict = ['age', 'expName', 'areaName', 'eduName', 'payName']
 
-const handleEnter = (e) => {
-  console.log(e, 'enter')
-}
+// 获取数据
+const getData = async () => {
+  const obj = { ...pageInfo, ...query }
+  console.log('obj', obj)
+  const { list, total: number } = await getTalentPoolPage(pageInfo)
+  total.value = number
+  dataList.value = list?.length ? dealDictArrayData([], list) : []
+  console.log('items.value', dataList.value)
+}
+getData()
+
 
-const dealSelect = () => {
-  selectList.value = items.value.filter(e => e.select).map(k => k.id)
+// 移出人才库 
+const handleRemove = async (item) => {
+  if (!item.userId) return Snackbar.warning('数据异常')
+  await removeFormTalentPool(item.userId)
+  Snackbar.success(t('common.operationSuccessful'))
+  getData()
 }
 
-// 全选
-const handleChangeSelectAll = () => {
-  items.value.map(k => {
-    k.select = selectAll.value
-    return k
-  })
-  dealSelect()
+const handleChangePage = (e) => {
+  pageInfo.pageNo = e
+  getData()
 }
-// 单选
-const handleChangeSelect = () => {
-  const length = items.value.filter(k => k.select).length
-  selectAll.value = length > 0 ? true : false
-  dealSelect()
+
+// 筛选
+const handleConfirm = (params) => {
+  screen.value = false
+  pageInfo.pageNo = 1
+  query = { ...params }
+  getData()
 }
 
-const handleChangePage = () => {
-  // 分页获取新数据后勾选
-  selectList.value.forEach(e => {
-    const obj = items.value.find(k => k.id === e)
-    if (obj) obj.select = true
-  })
+const FilterPageRef = ref()
+const openDrawer = () => {
+  screen.value = true
+  if (Object.keys(query).length) FilterPageRef.value?.setValue(query)
+  else FilterPageRef.value?.resetValue()
 }
 
+const headers = [
+  { title: '姓名', key: 'name', sortable: false },
+  { title: '求职状态', key: 'jobStatusName', sortable: false },
+  // { title: '求职类型', key: 'jobName', sortable: false },
+  { title: '电话号码', key: 'phone', sortable: false },
+  { title: '常用邮箱', key: 'email', sortable: false },
+  // { title: '微信二维码', key: 'wxCode', sortable: false },
+  { title: '出生日期', key: 'birthday', sortable: false, value: item =>  timesTampChange(item.birthday, 'Y-M-D') },
+  // { title: '加入时间', key: 'createTime', sortable: false, value: item =>  timesTampChange(item.createTime, 'Y-M-D') },
+  { title: '婚姻状况', key: 'maritalStatusName', sortable: false },
+  { title: '所在城市', key: 'areaName', sortable: false },
+  { title: '户籍地', key: 'regName', sortable: false },
+  { title: '首次工作时间', key: 'firstWorkTime', sortable: false, value: item =>  timesTampChange(item.firstWorkTime, 'Y-M-D') },
+  // { title: '个人优势', key: 'advantage', sortable: false },
+  { title: '工作年限', key: 'expName', sortable: false },
+  { title: '最高学历', key: 'eduName', sortable: false },
+  { title: '操作', value: 'actions', sortable: false }
+]
+const badgeColor = computed(() => (item) => {
+  return (item && item.sex) ? (item.sex === '1' ? '#1867c0' : 'error') : 'error'
+})
+
+const badgeIcon = computed(() => (item) => {
+  return (item && item.sex) ? (item.sex === '1' ? 'mdi-gender-male' : 'mdi-gender-female') : 'mdi-gender-female'
+})
+
 // 人才详情
 const talentPoolDetails = ({ userId, id }) => {
   if (!userId || !id) return