Преглед изворни кода

Merge branch 'dev' of https://git.citupro.com/zhengnaiwen_citu/menduner into dev

lifanagju_citu пре 1 година
родитељ
комит
3150fbe44e

BIN
public/favicon.ico


+ 17 - 0
src/api/position.js

@@ -55,3 +55,20 @@ export const getJobFavoriteCheck = async (params) => {
     params
   })
 }
+
+// 根据企业id统计职位类型的数量
+export const getJobAdvertisedPositionCount = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/job/advertised/get/position/count',
+    params
+  })
+}
+
+
+// 根据企业id获取企业职位区域
+export const getJobAreaByEnterpriseId = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/job/advertised/get/area/count',
+    params
+  })
+}

+ 1 - 2
src/components/Enterprise/components/introduction.vue

@@ -37,8 +37,7 @@ const list = [
   'https://img.bosszhipin.com/beijin/upload/com/img/20190823/f01c227906f5c15554d19904cf5009944d4ba1fec2b1a061e4a46fb61ddab12d.jpg',
   'https://img.bosszhipin.com/beijin/upload/com/img/20190823/154f6a1bc139eea59bf2610c3115fc664d4ba1fec2b1a061e4a46fb61ddab12d.jpg',
   'https://img.bosszhipin.com/beijin/upload/com/img/20190823/644c82121f1d19cb120c1e4c2836d1004d4ba1fec2b1a061e4a46fb61ddab12d.jpg',
-  'https://img.bosszhipin.com/beijin/upload/com/img/20190823/4b867202f288d6512dac50856bae61194d4ba1fec2b1a061e4a46fb61ddab12d.jpg',
-  'https://zhipin-company-1251955568.file.myqcloud.com/zhipin-company/99/20240411/fp0316a40013_f2abd6bc44254064931620a9a1dbdf21-OSS11.30.go15.fmHblack.mp4?sign=8bbdf46fa8ec4f97a742edf59e559379&t=1716168952'
+  'https://img.bosszhipin.com/beijin/upload/com/img/20190823/4b867202f288d6512dac50856bae61194d4ba1fec2b1a061e4a46fb61ddab12d.jpg'
 ]
 
 const isImage = (url) => {

+ 114 - 35
src/components/Enterprise/components/positions.vue

@@ -1,43 +1,68 @@
 <template>
-  <div>
-    <!-- <div class="top">检索</div> -->
-    <div class="bottom">
-      <div 
-        v-for="(val, i) in list" 
-        :key="i" 
-        :class="['bottom-item', {'border-bottom-dashed': i !== list.length -1}, 'd-flex', 'justify-space-between', 'cursor-pointer']" 
-        @mouseenter="val.active = true"
-        @mouseleave="val.active = false"
-        @click="handlePosition(val)"
-       >
-        <div>
-          <p :class="['name', {'default-active': val.active }]">{{ val.name }}</p>
-          <div style="line-height: 40px;">
-            <span v-for="k in desc" :key="k.mdi" class="mr-5">
-              <v-icon color="#666" size="15">{{ k.mdi }}</v-icon>
-              <span class="ml-1 tag-text">{{ val[k.value] }}</span>
-            </span>
-          </div>
-        </div>
-        <div v-if="!val.active" class="text-right">
-          <p class="salary">{{ val.payFrom }}-{{ val.payTo }}k/{{ val.payName }}</p>
-          <div class="update-time">{{ timesTampChange(val.updateTime) }} 刷新</div>
-        </div>
-        <div v-else class="account-info">
-          <v-avatar image="https://cdn.vuetifyjs.com/images/john.jpg"></v-avatar>
-          <span class="account-label">陈北方 · 人事经理</span>
-          <span>
-            <v-btn class="half-button" color="primary" size="small">立即沟通</v-btn>
+  <div class="top">
+    <div class="d-flex">
+      <div class="font-weight-bold position-category-left">职位类别:</div>
+      <div class="position-category-right">
+        <span 
+          :class="['category-item', {'default-active': k.active}]" 
+          v-for="k in positionCategory" 
+          :key="k.id"
+          @mouseenter="k.active = true"
+          @mouseleave="k.active = false"
+        >{{ k.id === '-1' ? `${k.label}` : `${k.label} (${k.number})` }}</span>
+      </div>
+    </div>
+    <div class="d-flex mt-3">
+      <areaType v-if="areaList.length" :list="areaList"></areaType>
+      <expType></expType>
+      <educationType></educationType>
+      <payScope></payScope>
+      <div style="width: 200px;">
+        <v-text-field  variant="outlined" placeholder="请输入职位名称" hide-details>
+          <template #append-inner>
+            <v-btn color="primary" size="x-small">搜索</v-btn>
+          </template>
+        </v-text-field>
+      </div>
+    </div>
+  </div>
+  <v-divider class="mt-5"></v-divider>
+  <div class="bottom mt-4">
+    <div 
+      v-for="(val, i) in list" 
+      :key="i" 
+      :class="['bottom-item', {'border-bottom-dashed': i !== list.length -1}, 'd-flex', 'justify-space-between', 'cursor-pointer']" 
+      @mouseenter="val.active = true"
+      @mouseleave="val.active = false"
+      @click="handlePosition(val)"
+    >
+      <div>
+        <p :class="['name', {'default-active': val.active }]">{{ val.name }}</p>
+        <div style="line-height: 40px;">
+          <span v-for="k in desc" :key="k.mdi" class="mr-5">
+            <v-icon color="#666" size="15">{{ k.mdi }}</v-icon>
+            <span class="ml-1 tag-text">{{ val[k.value] }}</span>
           </span>
         </div>
       </div>
-      <MPagination
-        :total="total"
-        :page="pageInfo.current"
-        :limit="pageInfo.size"
-        @handleChange="handleChangePage"
-      ></MPagination>
+      <div v-if="!val.active" class="text-right">
+        <p class="salary">{{ val.payFrom }}-{{ val.payTo }}k/{{ val.payName }}</p>
+        <div class="update-time">{{ timesTampChange(val.updateTime) }} 刷新</div>
+      </div>
+      <div v-else class="account-info">
+        <v-avatar image="https://cdn.vuetifyjs.com/images/john.jpg"></v-avatar>
+        <span class="account-label">陈北方 · 人事经理</span>
+        <span>
+          <v-btn class="half-button" color="primary" size="small">立即沟通</v-btn>
+        </span>
+      </div>
     </div>
+    <MPagination
+      :total="total"
+      :page="pageInfo.current"
+      :limit="pageInfo.size"
+      @handleChange="handleChangePage"
+    ></MPagination>
   </div>
 </template>
 
@@ -45,7 +70,20 @@
 defineOptions({ name: 'recruitment-positions'})
 import { ref } from 'vue'
 import { timesTampChange } from '@/utils/date'
+import { getDict } from '@/hooks/web/useDictionaries'
+import { getJobAdvertisedPositionCount, getJobAreaByEnterpriseId } from '@/api/position'
 import MPagination from '@/components/CtVuetify/CtPagination'
+import expType from '@/views/recruit/position/components/conditionFilter/expType.vue'
+import educationType from '@/views/recruit/position/components/conditionFilter/educationType.vue'
+import payScope from '@/views/recruit/position/components/conditionFilter/payScope.vue'
+import areaType from '@/views/recruit/position/components/conditionFilter/areaType.vue'
+
+const props = defineProps({
+  info: {
+    type: Object,
+    default: () => {}
+  }
+})
 
 const total = ref(12)
 const pageInfo = ref({
@@ -61,6 +99,28 @@ const handlePosition = (val) => {
   window.open(`/recruit/position/details/${val.positionId}`)
 }
 
+// 行业列表
+const industryList = ref([])
+const getDictData = async () => {
+  const { data } = await getDict('menduner_industry_type', {}, 'industryList')
+  industryList.value = data
+}
+getDictData()
+
+// 职位类别&工作地点
+const positionCategory = ref([])
+const areaList = ref([])
+const getData = async () => {
+  const data = await getJobAdvertisedPositionCount({ enterpriseId: props.info.enterprise.id })
+  areaList.value = await getJobAreaByEnterpriseId({ enterpriseId: props.info.enterprise.id })
+  const list = data.map(val => {
+    const value = industryList.value.find(e => Number(e.id) === Number(val.key))
+    return { id: value.id, label: value.nameCn, number: val.value, active: false }
+  })
+  positionCategory.value = [{ id: '-1', label: '全部', active: true }, ...list]
+}
+getData()
+
 const list = ref([
   {
     name: '产品经理',
@@ -146,4 +206,23 @@ const desc = [
     margin: 0 10px;
   }
 }
+.position-category-left {
+  width: 80px;
+}
+.position-category-right {
+  flex: 1;
+}
+.category-item {
+  margin-right: 20px;
+  font-size: 15px;
+  color: #888;
+  font-weight: 600;
+  cursor: pointer;
+}
+:deep(.v-field__input) {
+  height: 28px;
+  padding: 0 0 0 10px;
+  font-size: 12px;
+  min-height: 28px;
+}
 </style>

+ 1 - 1
src/components/Enterprise/details.vue

@@ -34,7 +34,7 @@
       <div class="d-flex" v-if="Object.keys(info).length">
         <div class="content-left">
           <EnterpriseIntroduction v-if="tab === 1" :info="info" />
-          <recruitmentPositions v-else />
+          <recruitmentPositions v-else :info="info"/>
         </div>
         <div class="content-right">
           <div class="welfare">

+ 49 - 0
src/views/recruit/position/components/conditionFilter/areaType.vue

@@ -0,0 +1,49 @@
+<template>
+  <commonStyle :btnTitle="title">
+    <v-list :items="items">
+      <v-list-item
+        color="primary"
+        :active="selectedItems.includes(item.id)"
+        v-for="item in items" :key="item.id" :value="item.id"
+        @click="handle(item)"
+      > 
+        <template v-if="selectedItems.includes(item.id)" v-slot:append>
+          <v-icon icon="mdi-check"></v-icon>
+        </template>
+        <v-list-item-title>{{ item.label }}</v-list-item-title>
+      </v-list-item>
+    </v-list>
+  </commonStyle>
+</template>
+
+<script setup>
+import commonStyle from './commonStyle.vue'
+import { getDict } from '@/hooks/web/useDictionaries'
+import { ref, defineEmits } from 'vue';
+
+defineOptions({name: 'conditionFilter-area-type'})
+const emits = defineEmits(['selectedItems'])
+const props = defineProps({
+  list: Array
+})
+
+const title = ref('工作地点')
+let items = ref()
+let selectedItems = ref([])
+getDict('menduner_area_type', {}, 'areaList').then(({ data }) => {
+  data = data?.length && data || []
+  const arr = props.list.map(e => {
+    const { id, parentId, type, name: label } = data.find(k => Number(k.id) === Number(e.key))
+    return { id, label, number: e.value, parentId, type }
+  })
+  items.value = [{ id: -1, label: '全部' }, ...arr]
+})
+const handle = (val) => {
+  const obj = selectedItems.value.find(e => e === val.id)
+  title.value = obj ? '工作地点' : '工作地点(1)'
+  selectedItems.value = obj ? [] : [val.id]
+  emits('selectedItems', selectedItems.value)
+}
+</script>
+<style lang="scss" scoped>
+</style>