Xiao_123 7 tháng trước cách đây
mục cha
commit
1e82b1c492

+ 8 - 0
src/api/enterprise.js

@@ -185,4 +185,12 @@ export const checkRecruiterPassword = async () => {
   return await request.get({
     url: '/app-api/menduner/system/recruit/user/check/password'
   })
+}
+
+// 分页检索人才信息
+export const getPersonSearchPage = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/recruit/person-search/page',
+    params
+  })
 }

+ 1 - 1
src/layout/enterprise.vue

@@ -44,7 +44,7 @@ const key = computed(() => {
 
 const whiteList = [
   '/recruit/enterprise/resumeManagement/talentPool/details/details',
-  '/recruit/enterprise/talentPool/details/details',
+  '/recruit/enterprise/talentPool/details',
   '/recruit/enterprise/purchasePackage',
   '/recruit/enterprise/systemManagement/groupAccount/invite/0',
   '/recruit/enterprise/systemManagement/groupAccount/invite/1'

+ 5 - 2
src/views/recruit/enterprise/search/retrieval/components/area.vue

@@ -1,14 +1,14 @@
 <template>
   <div class="font-size-15 d-flex align-center color-666">
     <span style="display: block; width: 71px; text-align: end;">地区:</span>
-    <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs" :close-on-content-click="true">
+    <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs" :close-on-content-click="false">
       <template v-slot:activator="{  props }">
         <div>
           <v-chip v-for="k in areaSelect" :key="k.id" class="mr-3" closable label size="small" @click:close="handleAreaClear(k)">{{ k.name }}</v-chip>
           <v-btn icon="mdi-plus" v-bind="props" variant="outlined" size="x-small"></v-btn>
         </div>
       </template>
-      <AreaSelect :select="select" :currentData="areaSelect" :limit="1" @handleClick="handleArea"></AreaSelect>
+      <AreaSelect :select="select" :currentData="areaSelect" :limit="false" showSelect @handleClick="handleArea"></AreaSelect>
     </v-menu>
   </div>
 </template>
@@ -17,18 +17,21 @@
 defineOptions({ name: 'search-retrieval-area' })
 import { ref } from 'vue'
 
+const emit = defineEmits(['select'])
 const select = ref([])
 const areaSelect = ref([])
 
 const handleArea = (list, arr) => {
   select.value = list
   areaSelect.value = arr
+  emit('select', list)
 }
 
 const handleAreaClear = (k) => {
   select.value = select.value.filter(item => item !== k.id)
   const index = areaSelect.value.findIndex(item => item.id === k.id)
   if (index !== -1) areaSelect.value.splice(index, 1)
+  emit('select', select.value)
 }
 </script>
 

+ 1 - 1
src/views/recruit/enterprise/search/retrieval/components/industry.vue → src/views/recruit/enterprise/search/retrieval/components/position.vue

@@ -2,7 +2,7 @@
   <div class="d-flex font-size-14">
     <div v-for="val in items" :key="val.id" class="mr-5 cursor-pointer" :class="{'active': val.active}" @click="handleFirst(val)">{{ val.nameCn }}</div>
   </div>
-  <div class="mt-5 font-size-14">
+  <div class="mt-5 font-size-14 mb-3">
     <span 
       v-for="k in children" 
       :key="k.id" 

+ 134 - 15
src/views/recruit/enterprise/search/retrieval/index.vue

@@ -1,29 +1,72 @@
 <template>
   <div class="mt-3">
     <div class="d-flex justify-center">
-      <TextInput :item="textItem" @enter="val => handleSearch('content', val)" @appendInnerClick="val => handleSearch('content', val)"></TextInput>
+      <TextInput v-model="query.content" :item="textItem" @enter="handleConfirm" @appendInnerClick="handleConfirm"></TextInput>
     </div>
-    <Industry :selectData="industry" @select="val => industry = val"></Industry>
-    <Area></Area>
+    <Position :selectData="position" @select="val => position = val"></Position>
+    <Area @select="val => handleSearch('areaIds', val)"></Area>
     <CommonPage class="my-3" dictType="menduner_education_type" title="最高学历" @select="val => handleSearch('eduType', val)"></CommonPage>
     <CommonPage dictType="menduner_exp_type" title="工作经验" @select="val => handleSearch('expType', val)"></CommonPage>
     <v-divider class="mt-1 mb-3"></v-divider>
     <div>
       <div>
-        <v-chip v-for="k in industry" :key="k.id" label class="mr-3" closable @click:close="handleClose(k)">{{ k.nameCn }}</v-chip>
+        <v-chip v-for="k in position" :key="k.id" label class="mr-3" closable @click:close="handleClose(k)">{{ k.nameCn }}</v-chip>
       </div>
-      <div v-if="industry.length" class="text-end font-size-15 color-999 cursor-pointer tips" @click="handleClear">清除选择</div>
+      <div v-if="position.length" class="text-end font-size-15 color-999 cursor-pointer color-primary" @click="handleClear">清除选择</div>
     </div>
+    <div class="text-center mt-3">
+      <v-btn color="primary" @click="handleConfirm">确认</v-btn>
+    </div>
+  </div>
+
+  <div class="mt-10">
+    <CtTable
+      :items="items"
+      :headers="headers"
+      :loading="loading"
+      :elevation="0"
+      :isTools="false"
+      :showPage="true"
+      :total="total"
+      :page-info="query"
+      itemKey="id"
+      @pageHandleChange="handleChangePage"
+    >
+      <template #name="{ item }">
+        <div class="d-flex align-center cursor-pointer" @click="handleToPersonDetail(item)">
+          <v-badge
+            v-if="item?.sex === '1' || item?.sex === '2'"
+            bordered
+            offset-y="6"
+            :color="badgeColor(item)"
+            :icon="badgeIcon(item)">
+            <v-avatar size="40" :image="getUserAvatar(item.avatar, item.sex)"></v-avatar>
+          </v-badge>
+          <v-avatar v-else size="40" :image="getUserAvatar(item.avatar, item.sex)"></v-avatar>
+          <span class="defaultLink ml-3">{{ item?.name }}</span>
+        </div>
+      </template>
+      <template #actions="{ item }">
+        <v-btn color="primary" variant="text" @click="handleCommunicate(item)">立即沟通</v-btn>
+      </template>
+    </CtTable>
   </div>
 </template>
 
 <script setup>
 defineOptions({ name: 'searchRetrieval' })
-import { ref } from 'vue'
+import { ref, computed } from 'vue'
 import CommonPage from '../components/common.vue'
-import Industry from './components/industry.vue'
-import Area from './components/area.vue';
+import Position from './components/position.vue'
+import Area from './components/area.vue'
+import { getPersonSearchPage } from '@/api/enterprise.js'
+import { dealDictArrayData } from '@/utils/position'
+import { timesTampChange } from '@/utils/date'
+import { getUserAvatar } from '@/utils/avatar'
+import { talkToUser, defaultTextEnt } from '@/hooks/web/useIM'
+import { useRouter } from 'vue-router'
 
+const router = useRouter()
 const textItem = ref({
   type: 'text',
   width: 600,
@@ -32,23 +75,99 @@ const textItem = ref({
   clearable: true,
   appendInnerIcon: 'mdi-magnify'
 })
+const query = ref({
+  pageNo: 1,
+  pageSize: 10,
+  content: null,
+  positionIds: [],
+  areaIds: [],
+  expType: '',
+  eduType: ''
+})
+
+const total = ref(0)
+const items = ref([])
+const loading = ref(false)
+const headers = ref([
+  { title: '姓名', key: 'name', sortable: false },
+  { title: '求职状态', key: 'jobStatusName', sortable: false },
+  { title: '工作年限', key: 'expName', sortable: false },
+  { title: '最高学历', key: 'eduName', sortable: false },
+  { title: '所在城市', key: 'areaName', sortable: false },
+  { title: '户籍地', key: 'regName', sortable: false },
+  { title: '婚姻状况', key: 'maritalStatusName', sortable: false },
+  { title: '首次工作时间', key: 'firstWorkTime', sortable: false, value: item => timesTampChange(item.firstWorkTime, 'Y-M-D') },
+  { title: '联系电话', key: 'phone', sortable: false },
+  { title: '常用邮箱', key: 'email', sortable: false },
+  { title: '操作', key: 'actions', sortable: false }
+])
 
-const industry = ref([])
+const getData = async () => {
+  loading.value = true
+  try {
+    const res = await getPersonSearchPage(query.value)
+    if (!res.list.length) {
+      items.value = []
+      total.value = 0
+      return
+    }
+    items.value = dealDictArrayData([], res.list)
+    console.log(items.value, 'items-data')
+    total.value = res.total
+  } finally {
+    loading.value = false
+  }
+}
+
+// 分页
+const handleChangePage = (e) =>{
+  query.value.pageNo = e
+  getData()
+}
+
+const position = ref([])
 const handleSearch = (key, value) => {
-  console.log(key, value, 'search')
+  query.value.pageNo = 1
+  if (value === -1) query.value[key] = null
+  else query.value[key] = value
+}
+
+const handleConfirm = () => {
+  const positionIds = position.value.map(k => k.id)
+  query.value.positionIds = positionIds || []
+  query.value.pageNo = 1
+  getData()
 }
 
 const handleClose = (item) => {
-  industry.value = industry.value.filter(k => k.id !== item.id)
+  position.value = position.value.filter(k => k.id !== item.id)
 }
 
 const handleClear = () => {
-  industry.value = []
+  position.value = []
+}
+
+// 立即沟通
+const handleCommunicate = async (item) => {
+  const userId = item.userId
+  await talkToUser({userId, text: defaultTextEnt})
+  let url = `/recruit/enterprise/chatTools?id=${userId}`
+  router.push(url)
+}
+
+// 人才详情
+const handleToPersonDetail = ({ userId, id }) => {
+  if (!userId || !id) return
+  window.open(`/recruit/enterprise/talentPool/details/${userId}?id=${id}`)
 }
+
+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'
+})
 </script>
 
 <style scoped lang="scss">
-.tips:hover {
-  color: var(--v-primary-base)
-}
 </style>