Xiao_123 10 ヶ月 前
コミット
d236db6c94

+ 40 - 0
src/api/recruit/enterprise/statistics/index.js

@@ -38,4 +38,44 @@ export const getRecentConversations = async (data) => {
     url: '/app-api/im/recent/conversations/statistics',
     data
   })
+}
+
+// 获取发布职位浏览量统计分析明细
+export const getJobBrowseNumPage = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/recruit/analysis/get/job/browse/num/page',
+    params
+  })
+}
+
+// 获取新投递简历统计分析明细
+export const getJobCvNewPage = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/recruit/analysis/get/job/cv/new/page',
+    params
+  })
+}
+
+// 获取已查看简历统计分析明细
+export const getJobCvLookPage = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/recruit/analysis/get/job/cv/look/page',
+    params
+  })
+}
+
+// 获取待面试统计分析明细
+export const getInterviewWaitPage = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/recruit/analysis/get/interview/wait/page',
+    params
+  })
+}
+
+// 获取完成面试统计分析明细
+export const getInterviewCompletePage = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/recruit/analysis/get/interview/complete/page',
+    params
+  })
 }

+ 53 - 0
src/utils/statisticsHeaders.js

@@ -0,0 +1,53 @@
+import { timesTampChange } from './date'
+import { getDict } from '@/hooks/web/useDictionaries'
+
+// 求职状态
+let jobStatus = []
+getDict('menduner_job_status').then(({data}) => {
+  jobStatus = data
+})
+
+export default {
+  // 职位浏览量
+  0: [
+    { title: '招聘职位', key: 'name', sortable: false },
+    { title: '薪酬', key: 'payFrom', sortable: false, value: item => `${item.payFrom}-${item.payTo}/${item.payName}` },
+    { title: '工作地区', key: 'areaName', sortable: false },
+    { title: '工作经验', key: 'expName', sortable: false },
+    { title: '学历要求', key: 'eduName', sortable: false },
+    { title: '浏览量', key: 'num', sortable: false }
+  ],
+  // 收到的简历
+  1: [
+    { title: '投递人', key: 'person.name', sortable: false },
+    { title: '求职状态', key: 'person.jobStatus', sortable: false, value: item => jobStatus.find(i => i.value === item.person.jobStatus)?.label },
+    { title: '薪酬', key: 'job.payFrom', sortable: false, value: item => `${item.job.payFrom}-${item.job.payTo}/${item.job.payName}` },
+    { title: '工作地区', key: 'job.areaName', sortable: false },
+    { title: '工作经验', key: 'job.expName', sortable: false },
+    { title: '学历要求', key: 'job.eduName', sortable: false },
+  ],
+  // 已查看简历
+  2: [
+    { title: '简历标题', key: 'title', sortable: false },
+    { title: '投递人', key: 'person.name', sortable: false },
+    { title: '投递类型', key: 'type', sortable: false, value: item => item.type === 0 ? '平台投递': '赏金投递' },
+    { title: '推荐人', key: 'recommendPerson.name', sortable: false },
+  ],
+  // 已邀面试
+  3: [
+    { title: '求职者', key: 'person.name', sortable: false },
+    { title: '面试岗位', key: 'job.name', sortable: false },
+    { title: '面试类型', key: 'type', sortable: false, value: item => item.type === 0 ? '线上面试': '线下面试' },
+    { title: '面试时间', key: 'time', sortable: false, value: item => timesTampChange(item.time, 'Y-M-D h:m') },
+    { title: '面试地点', key: 'address', sortable: false },
+  ],
+  // 面试完成
+  4: [
+    { title: '求职者', key: 'person.name', sortable: false },
+    { title: '面试岗位', key: 'job.name', sortable: false },
+    { title: '面试类型', key: 'type', sortable: false, value: item => item.type === 0 ? '线上面试': '线下面试' },
+    { title: '面试时间', key: 'time', sortable: false, value: item => timesTampChange(item.time, 'Y-M-D h:m') },
+    { title: '面试地点', key: 'address', sortable: false },
+    { title: '反馈评价', key: 'evaluate', sortable: false },
+  ]
+}

+ 94 - 37
src/views/recruit/enterprise/statistics/components/overview.vue

@@ -10,56 +10,113 @@
             </template>
           </v-tooltip>
         </div>
-        <div class="overview-item-value my-3 cursor-pointer">{{ overviewData[val.key] }}</div>
-        <div class="font-size-14">
-          环比
-          <span class="color-error">{{ typeof val.ratio === 'number' ? val.ratio : overviewData[val.ratio] }}% ↑</span>
-        </div>
+        <div class="overview-item-value my-3 cursor-pointer" @click.stop="handleDetails(val, i)">{{ val.value }}</div>
       </div>
     </div>
   </div>
+
+  <CtDialog :visible="show" :widthType="1" titleClass="text-h6" :footer="false" :title="title" @close="handleClose">
+    <CtTable
+      :items="data"
+      :headers="headersList[current]"
+      :loading="false"
+      :elevation="0"
+      :isTools="false"
+      :showPage="true"
+      :total="total"
+      :page-info="queryParams"
+      itemKey="id"
+      @pageHandleChange="handleChangePage"
+    >
+    </CtTable>
+  </CtDialog>
 </template>
 
 <script setup>
 defineOptions({ name: 'overview-page'})
-import { ref } from 'vue'
-// import { getRecentConversations } from '@/api/recruit/enterprise/statistics'
-// const props = defineProps({
-//   query: Object
-// })
+import { reactive, ref, watch, onMounted } from 'vue'
+import { getJobBrowseNumPage, getJobCvNewPage, getJobCvLookPage, getInterviewWaitPage, getInterviewCompletePage } from '@/api/recruit/enterprise/statistics'
+import headersList from '@/utils/statisticsHeaders'
+import { dealDictArrayData, dealDictObjData } from '@/utils/position'
+
+const props = defineProps({
+  query: Object
+})
 
-const overviewData = ref({
-  position: 0,
-  resume: 0,
-  viewResume: 0,
-  interview: 0,
-  interviewFinish: 0
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10
 })
+const show = ref(false)
+const total = ref(0)
+const current = ref(0)
+const title = ref('')
+const data = ref([])
 // 数据概况
 const overview = ref([
-  { title: '职位浏览量', key: 'position', ratio: 0, desc: '指全部职位被候选人查看的人数总和' },
-  { title: '收到简历量', key: 'resume', ratio: 0, desc: '指全部职位收到简历的总数' },
-  { title: '查看收到简历', key: 'viewResume', ratio: 0, desc: '指查看候选人主动发送的简历数量' },
-  { title: '面试-已邀约', key: 'interview', ratio: 0, desc: '已邀约的面试人数' },
-  { title: '面试-已完成', key: 'interviewFinish', ratio: 0, desc: '已完成面试的人数' },
+  { title: '职位浏览量', value: 0, desc: '指全部职位被候选人查看的人数总和', items: [], api: getJobBrowseNumPage, deal: true },
+  { title: '收到的简历', value: 0, desc: '指全部职位收到简历的总数', items: [], api: getJobCvNewPage, isDeal: true },
+  { title: '已查看简历', value: 0, desc: '指查看候选人主动发送的简历数量', items: [], api: getJobCvLookPage },
+  { title: '已邀面试', value: 0, desc: '已邀约的面试人数', items: [], api: getInterviewWaitPage },
+  { title: '面试完成', value: 0, desc: '已完成面试的人数', items: [], api: getInterviewCompletePage }
 ])
 
-// 主动联系我的、我主动联系的人
-// const accountInfo = localStorage.getItem('accountInfo') ? JSON.parse(localStorage.getItem('accountInfo')) : {}
-// const getRecent = async () => {
-//   if (!accountInfo || !accountInfo.userId) return
-//   const data = await getRecentConversations({ userId: accountInfo.userId, ...props.query })
-//   overviewData.value = Object.assign(overviewData.value, data)
-// }
-// getRecent()
+// 钻取
+const handleDetails = (val, index) => {
+  show.value = true
+  current.value = index
+  total.value = val.value
+  title.value = val.title + '明细'
+  data.value = val.items
+}
+
+const handleClose = () => {
+  show.value = false
+  total.value = 0
+  current.value = 0
+  title.value = ''
+  data.value = []
+  queryParams.pageNo = 1
+}
+
+const handleChangePage = (val) => {
+  queryParams.pageNo = val
+  getData(current.value)
+}
+
+// 统计数值
+const getData = async (index) => {
+  if (index !== null && index !== undefined) {
+    const obj = overview.value[index]
+    const res = await obj.api({ ...props.query, ...queryParams })
+    total.value = res.total
+    data.value = obj.deal ? dealDictArrayData([], res.list) : obj.isDeal ? res.list.map(e => {
+      e.job = dealDictObjData({}, e.job)
+      return e
+    }) : res.list
+    return
+  }
+  overview.value.forEach(async (item) => {
+    const { list, total } = await item.api({ ...props.query, ...queryParams })
+    item.value = total
+    item.items = item.deal ? dealDictArrayData([], list) : item.isDeal ? list.map(e => {
+      e.job = dealDictObjData({}, e.job)
+      return e
+    }) : list
+  })
+}
+
+onMounted(() => {
+  getData()
+})
 
-// watch(
-//   () => props.query,
-//   (val) => {
-//     if (val) getRecent()
-//   },
-//   { deep: true }
-// )
+watch(
+  () => props.query,
+  (val) => {
+    if (val) getData()
+  },
+  { deep: true }
+)
 </script>
 
 <style scoped lang="scss">
@@ -74,7 +131,7 @@ const overview = ref([
   max-width: calc((100% - 48px) / 5);
   // min-width: 200px;
   margin: 0 12px 12px 0;
-  height: 175px;
+  height: 140px;
   border-radius: 12px;
   overflow: hidden;
   transition: all .2s linear;

+ 0 - 32
src/views/recruit/enterprise/statistics/components/resume.vue

@@ -55,38 +55,6 @@ const barCommonOption = {
   ]
 }
 
-// 期望月薪柱状图
-// const option = {
-//   title: {
-//     text: '期望月薪'
-//   },
-//   xAxis: {
-//     type: 'category',
-//     name: '范围',
-//     data: ['3-5k', '5-8k', '8-12k', '12-15k', '15-20k', '20-30k', '面议']
-//   },
-//   yAxis: {
-//     type: 'value'
-//   },
-//   grid: {
-//     left: '0',
-//     top: '60',
-//     right: '50',
-//     bottom: '10',
-//     containLabel: true
-//   },
-//   series: [
-//     {
-//       data: [120, 200, 150, 80, 70, 110, 130],
-//       type: 'bar',
-//       barWidth: 40,
-//       label: {
-//         show: true
-//       }
-//     }
-//   ]
-// }
-
 const list = ref([
   {
     api: getJobCvSexCount,

+ 21 - 1
src/views/recruit/enterprise/statistics/overallAnalysis.vue

@@ -13,6 +13,9 @@
           <date-picker v-model="date" :options="{ range: true, clearable: true, placeholder: '请选择要查看的时间范围', change: handleChangeDate, format: 'timestamp' }"></date-picker>
         </div>
       </div>
+      <div class="ml-15" style="width: 300px;">
+        <Autocomplete v-model="query.jobId" :item="selectItems"></Autocomplete>
+      </div>
     </div>
     <div class="mt-10">
       <v-tabs v-model="tab" align-tabs="start" color="primary" bg-color="#f7f8fa">
@@ -32,6 +35,7 @@
 <script setup>
 defineOptions({ name: 'overallAnalysis'})
 import { reactive, ref } from 'vue'
+import { getJobAdvertised } from '@/api/enterprise'
 import Overview from './components/overview.vue'
 import ResumeAnalysis from './components/resume.vue'
 import { convertTimestampsToDayRange } from '@/utils/date'
@@ -41,13 +45,29 @@ const date = ref(null)
 const current = ref(0)
 const query = reactive({
   type: 0,
-  time: null
+  time: null,
+  jobId: null
 })
 const list = [
   { label: '最近7天', value: 0 },
   { label: '上个月', value: 1 },
   { label: '上季度', value: 2 }
 ]
+const selectItems = ref({
+  label: '请选择要查看的职位',
+  itemText: 'name',
+  itemValue: 'id',
+  clearable: true,
+  hireDetails: true,
+  items: []
+})
+
+// 获取职位列表
+const getJobList = async () => {
+  const data = await getJobAdvertised()
+  selectItems.value.items = data
+}
+getJobList()
 
 // 类型选择
 const handleClickType = (i) => {