瀏覽代碼

牛人管理筛选

Xiao_123 11 月之前
父節點
當前提交
96a2806dbb

+ 15 - 0
src/api/enterprise.js

@@ -53,4 +53,19 @@ export const enterpriseClick = async (data) => {
     url: '/app-api/menduner/system/enterprise/click',
     data
   })
+}
+
+// 牛人管理-列表
+export const getPersonCvPage = async (params) => {
+  return await request.get({
+    url: '/app-admin-api/menduner/system/person-cv/page',
+    params
+  })
+}
+
+// 牛人管理-获取发布的职位列表
+export const getJobAdvertised = async () => {
+  return await request.get({
+    url: '/app-admin-api/menduner/system/job-advertised/list'
+  })
 }

+ 27 - 25
src/views/enterprise/personnelManagement/components/screen.vue

@@ -21,29 +21,29 @@
 <script setup>
 defineOptions({ name: 'screen-page'})
 import { ref, defineProps, defineEmits, watch } from 'vue'
+import { getJobAdvertised } from '@/api/enterprise'
 import { getDict } from '@/hooks/web/useDictionaries'
+import { dealDictArrayData } from '@/views/recruit/position/components/dict'
 import CommonStyle from './commonStyle.vue'
 
-const emit = defineEmits(['search'])
+const emit = defineEmits(['search', 'reset'])
 const props = defineProps({
-  tab: {
-    type: Number,
-    default: 0
-  }
+  tab: String
 })
 
 const list = ref([
   {
     title: '应聘岗位',
     defaultTitle: '应聘岗位',
+    key: 'jobId',
     selected: [],
-    items: [
-      { label: 'Java_广州 150-200元/天', value: '0' }
-    ]
+    api: getJobAdvertised,
+    items: []
   },
   {
     title: '学历',
     defaultTitle: '学历',
+    key: 'eduType',
     dictTypeName: 'menduner_education_type',
     selected: [],
     items: []
@@ -51,25 +51,15 @@ const list = ref([
   {
     title: '工作经验',
     defaultTitle: '工作经验',
+    key: 'expType',
     dictTypeName: 'menduner_exp_type',
     selected: [],
     items: []
   },
-  // {
-  //   title: '年龄',
-  //   defaultTitle: '年龄',
-  //   selected: [],
-  //   items: [
-  //     { label: '16-20岁', value: '0' },
-  //     { label: '21-25岁', value: '1' },
-  //     { label: '26-30岁', value: '2' },
-  //     { label: '31-35岁', value: '3' },
-  //     { label: '35岁以上', value: '4' }
-  //   ]
-  // },
   {
     title: '求职状态',
     defaultTitle: '求职状态',
+    key: 'jobStatus',
     dictTypeName: 'menduner_job_status',
     selected: [],
     items: []
@@ -78,11 +68,22 @@ const list = ref([
 
 // 获取字典数据
 list.value.forEach(k => {
-  if (!k.dictTypeName) return
+  if (k.dictTypeName) {
     getDict(k.dictTypeName).then(({ data }) => {
-    data = data?.length && data || []
-    k.items = data
-  })
+      data = data?.length && data || []
+      k.items = data
+    })
+  }
+  if (k.api) {
+    k.api().then(data => {
+      if (data.length) {
+        const list = dealDictArrayData([], data)
+        k.items = list.map(e => {
+          return { label: `${e.name}_${e.areaName} ${e.payFrom}-${e.payTo}/${e.payName}`, value: e.id }
+        })
+      }
+    })
+  }
 })
 
 // 单击
@@ -90,7 +91,7 @@ const handleClick = (item, val) => {
   const obj = val.selected.includes(item.value)
   val.selected = obj ? val.selected.filter(i => i !== item.value) : [item.value]
   val.title = obj ? val.defaultTitle : item.label
-  emit('search', item.value)
+  emit('search', { key: val.key, value: obj ? '' : item.value })
 }
 
 // 重置
@@ -100,6 +101,7 @@ const handleReset = () => {
     e.title = e.defaultTitle
     return e
   })
+  emit('reset')
 }
 
 watch(

+ 47 - 57
src/views/enterprise/personnelManagement/components/table.vue

@@ -4,83 +4,72 @@
       <v-btn color="primary" :disabled="selected.length ? false : true" variant="tonal" @click="handleInappropriate">不合适</v-btn>
     </div>
     <v-data-table
+      class="mt-3"
       v-model="selected"
       :items="items"
-      class="mt-3"
       :headers="headers"
-      show-select
-      item-value="id"
       hover
+      show-select
       height="60vh"
-      hide-default-footer
+      item-value="id"
     >
       <template #bottom></template>
-      <template v-slot:item.actions>
+      <template v-slot:item.name="{ item }">
+        <div class="d-flex align-center">
+          <v-badge
+            bordered
+            offset-y="6"
+            :color="badgeColor(item)"
+            :icon="badgeIcon(item)">
+            <v-avatar size="40" :image="item.person.avatar || 'https://minio.citupro.com/dev/menduner/7.png'"></v-avatar>
+          </v-badge>
+          <span class="defaultLink ml-3">{{ item?.person?.name }}</span>
+        </div>
+      </template>
+      <template v-slot:item.exp="{ item }">
+        <span v-if="Object.keys(item?.jobExperience)">{{ item.jobExperience.positionName }} {{ item.jobExperience.enterpriseName }}</span>
+        <span v-else>未填写工作经历</span>
+      </template>
+      <template v-slot:item.edu="{ item }">
+        <span v-if="Object.keys(item?.eduExperience)">{{ timesTampChange(item.eduExperience.startTime).slice(0, 4) }}-{{ timesTampChange(item.eduExperience.endTime).slice(0, 4) }} {{ item.eduExperience.schoolName }}</span>
+        <span v-else></span>
+      </template>
+      <template v-slot:item.actions="{ item }">
+        <v-btn v-if="tab === '0'" color="primary" variant="text" @click="previewFile(item.url)">附件</v-btn>
         <v-btn color="primary" variant="text">不合适</v-btn>
       </template>
     </v-data-table>
-    <CtPagination
-      v-if="total > 0"
-      :total="total"
-      :page="query.pageNo"
-      :limit="query.pageSize"
-      @handleChange="handleChangePage"
-    ></CtPagination>
   </div>
 </template>
 
 <script setup>
 defineOptions({ name: 'table-page'})
-import { ref } from 'vue'
+import { ref, computed } from 'vue'
+import { previewFile } from '@/utils'
+import { timesTampChange } from '@/utils/date'
 
-const selected = ref([])
-const total = ref(3)
-const query = ref({
-  pageNo: 1,
-  pageSize: 10
+defineProps({
+  tab: String,
+  items: Array
+})
+
+const badgeColor = computed(() => (item) => {
+  return (item.person && item.person.sex) ? (item.person.sex === '1' ? '#1867c0' : 'error') : 'error'
+})
+
+const badgeIcon = computed(() => (item) => {
+  return (item.person && item.person.sex) ? (item.person.sex === '1' ? 'mdi-gender-male' : 'mdi-gender-female') : 'mdi-gender-female'
 })
+
+const selected = ref([])
 const headers = [
   { title: '牛人', value: 'name' },
-  { title: '基本信息', value: 'info' },
-  { title: '最近工作经历', value: 'work' },
-  { title: '教育经历', key: 'school', value: item => `${item.startYear}-${item.endYear} ${item.school}` },
-  { title: '应聘职位', value: 'jobName' },
+  { title: '基本信息', key: 'info', value: item => `${item.eduName}·${ item.expName }` },
+  { title: '最近工作经历', value: 'exp' },
+  { title: '教育经历', key: 'edu' },
+  { title: '应聘职位', value: 'job.name' },
   { title: '操作', value: 'actions' }
 ]
-const items = [
-  {
-    name: '黄桐奕',
-    info: '本科·21岁·25年应届生·5-8K',
-    work: 'Java 江门市天天生活科技有限公司',
-    school: '五邑大学',
-    jobName: 'Java',
-    startYear: '2021',
-    id: 1,
-    endYear: '2025'
-  },
-  {
-    name: '黄桐奕',
-    info: '本科·21岁·25年应届生·5-8K',
-    work: 'Java 江门市天天生活科技有限公司',
-    school: '五邑大学',
-    jobName: 'Java',
-    startYear: '2021',
-    endYear: '2025',
-    id: 2
-  },
-  {
-    name: '黄桐奕',
-    info: '本科·21岁·25年应届生·5-8K',
-    work: 'Java 江门市天天生活科技有限公司',
-    school: '五邑大学',
-    jobName: 'Java',
-    startYear: '2021',
-    endYear: '2025',
-    id: 3
-  }
-]
-
-const handleChangePage = () => {}
 
 const handleInappropriate = () => {
   console.log(selected.value, 'handleInappropriate')
@@ -92,6 +81,7 @@ const handleInappropriate = () => {
   background-color: #f7f8fa !important;
 }
 :deep(.v-selection-control__input) {
-  color: var(--v-primary-base) !important;
+  // color: var(--v-primary-base) !important;
+  color: #767778;
 }
 </style>

+ 84 - 14
src/views/enterprise/personnelManagement/index.vue

@@ -3,20 +3,21 @@
   <v-card class="pa-5 card-box">
     <div class="d-flex justify-space-between">
       <v-tabs v-model="tab" align-tabs="start" color="primary" bg-color="#f7f8fa" @update:model-value="handleChangeTab">
-        <v-tab :value="1">新简历</v-tab>
-        <v-tab :value="2">已查看</v-tab>
-        <v-tab :value="3">已邀约</v-tab>
-        <v-tab :value="4">已发offer</v-tab>
-        <v-tab :value="5">已入职</v-tab>
-        <v-tab :value="6">不合适</v-tab>
+        <v-tab v-for="k in tabList" :value="k.value" :key="k.value">{{ k.label }}</v-tab>
       </v-tabs>
       <TextInput v-model="textItems.value" :item="textItems" @appendInnerClick="handleSearch" @enter="handleSearch"></TextInput>
     </div>
-    <Screen :tab="tab" @search="handleChange"></Screen>
+    <Screen :tab="tab" @search="handleScreen" @reset="handleScreenReset"></Screen>
 
     <v-window v-model="tab" class="mt-1">
-      <v-window-item :value="1">
-        <TablePage></TablePage>
+      <v-window-item v-for="k in tabList" :value="k.value" :key="k.value">
+        <TablePage :items="items" :tab="k.value"></TablePage>
+        <CtPagination
+          :total="total"
+          :page="query.pageNo"
+          :limit="query.pageSize"
+          @handleChange="handleChangePage"
+        ></CtPagination>
       </v-window-item>
     </v-window>
   </v-card>
@@ -25,10 +26,20 @@
 <script setup>
 defineOptions({ name: 'enterprise-personnelManagement-management'})
 import { ref } from 'vue'
+import { getPersonCvPage } from '@/api/enterprise'
+import { getDict } from '@/hooks/web/useDictionaries'
+import { dealDictObjData } from '@/views/recruit/position/components/dict'
 import TablePage from './components/table.vue'
 import Screen from './components/screen.vue'
 
-const tab = ref(1)
+const total = ref(0)
+const query = ref({
+  pageNo: 1,
+  pageSize: 1,
+  status: 0
+})
+const tab = ref('0')
+const tabList = ref([])
 const textItems = ref({
   type: 'text',
   value: '',
@@ -37,13 +48,72 @@ const textItems = ref({
   appendInnerIcon: 'mdi-magnify'
 })
 
-const handleChangeTab = () => {}
+// 获取tab列表项
+const getTabData = () => {
+  getDict('menduner_job_cv_status').then(({ data }) => {
+    data = data?.length && data || []
+    tabList.value = data
+  })
+}
+getTabData()
+
+// 获取牛人列表
+const items = ref([])
+const getList = async () => {
+  const { list, total: number } = await getPersonCvPage(query.value)
+  if (!list.length) {
+    items.value = []
+    total.value = 0
+    return
+  }
+  total.value = number
+  items.value = list.map(e => {
+    let obj = e
+    if (e.person) {
+      obj = Object.assign(obj, dealDictObjData({}, e.person))
+      if (e.person.workExpList && e.person.workExpList.length > 0) obj.jobExperience = e.person.workExpList[0]
+      if (e.person.eduExpList && e.person.eduExpList.length > 0) obj.eduExperience = e.person.eduExpList[0]
+    }
+    return obj
+  })
+}
+getList()
+
+const handleChangeTab = () => {
+  query.value.status = tab.value
+  getList()
+}
 
+// 分页
+const handleChangePage = (i) => {
+  query.value.pageNo = i
+  getList()
+}
+
+// 牛人姓名检索
 const handleSearch = () => {
-  console.log(textItems.value.value, 'search')
+  if (textItems.value.value) query.value.name = textItems.value.value
+  else delete query.value.name
+  query.value.pageNo = 1
+  getList()
 }
-const handleChange = (e) => {
-  console.log(e, 'change')
+
+// 下拉筛选
+const handleScreen = ({ value, key }) => {
+  if (value) query.value[key] = value
+  else delete query.value[key]
+  getList()
+}
+
+// 下拉筛选重置
+const handleScreenReset = () => {
+  query.value = {
+    pageSize: 10,
+    pageNo: 1,
+    status: tab.value
+  }
+  if (textItems.value.value) query.value.name = textItems.value.value
+  getList()
 }
 </script>