فهرست منبع

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

zhengnaiwen_citu 1 سال پیش
والد
کامیت
6623df9db6

+ 7 - 0
src/api/common/index.js

@@ -81,6 +81,13 @@ export const getPositionTreeData = async (params) => {
   })
 }
 
+// 获取区域树形
+export const getAreaTreeData = async () => {
+  return await request.get({
+    url: '/app-api/menduner/system/area/get/tree'
+  })
+}
+
 // 获取行业树形
 export const getIndustryTreeData = async (params) => {
   return await request.get({

+ 8 - 0
src/api/position.js

@@ -30,4 +30,12 @@ export const getPositionDetails = async (params) => {
     url: '/app-api/menduner/system/job/advertised/get/detail',
     params
   })
+}
+
+// 职位详情-相似职位
+export const getSimilarPosition = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/job/advertised/get/acquainted',
+    params
+  })
 }

+ 102 - 0
src/components/Enterprise/info.vue

@@ -0,0 +1,102 @@
+<template>
+  <div class="info-box">
+    <h4 class="mb-3">公司信息</h4>
+    <div style="height: 50px;">
+      <v-img class="float-left" :src="props.info.enterprise.logoUrl" :width="45" height="45"></v-img>
+      <div class="ml-3 float-left">
+        <p class="enterprise-name">{{ props.info.enterprise.anotherName }}</p>
+        <v-icon color="primary" size="20">mdi-shield-check</v-icon> <!-- mdi-shield-remove -->
+        <span style="color: var(--v-primary-base);font-size: 14px;">已认证</span>
+      </div>
+    </div>
+    <div class="mt-3 border-bottom-dashed" style="font-size: 14px;">
+      <div v-for="val in dictList" :key="val.icon" class="d-flex my-2">
+        <v-icon size="20" color="#666">{{ val.icon }}</v-icon>
+        <div class="info-address ml-4">{{ val.label }}</div>
+      </div>
+    </div>
+    <div style="font-size: 12px;height: 50px; line-height: 50px">
+      <span class="float-left">共<span style="color: var(--v-primary-base)">9</span>个在招职位</span>
+      <span class="float-right more-position">查看全部职位<v-icon>mdi-chevron-right</v-icon></span>
+    </div>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-info' })
+import { reactive } from 'vue'
+import { getDict } from '@/hooks/web/useDictionaries'
+const props = defineProps({
+  info: {
+    type: Object,
+    default: () => {}
+  }
+})
+
+const dictObj = reactive({
+  scale: [],
+  financing: [],
+  industry: []
+})
+const dictList = reactive([
+  { type: 'menduner_financing_status', value: 'financing', key: 'scale', label: '', icon: 'mdi-domain' },
+  { type: 'menduner_scale', value: 'scale', key: 'financingStatus', label: '', icon: 'mdi-account-multiple' },
+  { type: 'menduner_industry_type', value: 'industry', key: 'industryId', label: '', params: {}, apiType: 'industryList', nameKey: 'nameCn', valueKey: 'id', icon: 'mdi-family-tree' }
+])
+const getDictList = async () => {
+  dictList.forEach(async (val) => {
+    const { data } = await getDict(val.type, val.params, val.apiType)
+    dictObj[val.value] = data
+  })
+}
+const dealData = () => {
+  const prise = props.info.enterprise
+  dictList.forEach(item => {
+    const valueKey = item.nameKey ? item.nameKey : 'label'
+    const idKey = item.valueKey ? item.valueKey : 'value'
+    item.label = dictObj[item.value].find(k => Number(k[idKey]) === Number(prise[item.key]))[valueKey] || ''
+  })
+}
+const getData = async () => {
+  await getDictList()
+  dealData()
+}
+getData()
+</script>
+
+<style lang="scss" scoped>
+.info-box {
+  height: 260px;
+  background-color: #f9f9f9;
+  border-radius: 8px;
+  padding: 20px 15px;
+}
+.enterprise-name {
+  width: 165px;
+  font-weight: 500;
+  max-width: 165px;
+  vertical-align: middle;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  &:hover {
+    color: var(--v-primary-base);
+  }
+}
+.info-address {
+  width: 185px;
+  font-weight: 500;
+  max-width: 185px;
+  vertical-align: middle;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  &:hover {
+    color: var(--v-primary-base);
+  }
+}
+.more-position {
+  color: var(--v-primary-base);
+  cursor: pointer;
+}
+</style>

+ 14 - 37
src/components/Position/similarPositions.vue

@@ -1,13 +1,13 @@
 <template>
   <div class="position-box">
     <h4 class="mb-3">相似职位</h4>
-    <div v-for="(item, index) in list" :key="index" class="mb-2 cursor-pointer">
-      <p class="recruit-name">{{ item.recruitName }}</p>
-      <span class="recruit-salary">{{ item.salary }}</span>
-      <div :class="['enterprise', {'borders': index !== list.length - 1}]">
-        <v-img class="float-left" src="https://img.bosszhipin.com/beijin/upload/com/logo/20230908/7b5b554d84f9729c6903b0c0cc1dcd8701d6c481534346fb7ef6001aff3ae087644bf666b1b70622.png" :width="30" style="height: 30px;"></v-img>
-        <span class="float-left enterprise-name">{{ item.enterpriseName }}</span>
-        <span class="float-right enterprise-address">{{ item.address }}</span>
+    <div v-for="(item, index) in props.list" :key="index" class="mb-2 cursor-pointer">
+      <p class="recruit-name">{{ item.name }}</p>
+      <span class="recruit-salary">{{ item.payFrom }}-{{ item.payTo }}/{{ item.payName }}</span>
+      <div :class="['enterprise', {'border-bottom-dashed': index !== list.length - 1}]">
+        <v-img class="float-left" :src="item.logoUrl" :width="30" :height="30"></v-img>
+        <span class="float-left enterprise-name">{{ item.anotherName }}</span>
+        <span class="float-right enterprise-address">{{ item.areaName }}</span>
       </div>
     </div>
     <div class="text-center more-btn">
@@ -17,32 +17,12 @@
 </template>
 
 <script setup name="similarPositions">
-const list = [
-  {
-    recruitName: '产品经理',
-    salary: '12-4k',
-    enterpriseName: '辞图科技有限公司',
-    address: '广州'
-  },
-  {
-    recruitName: '产品经理',
-    salary: '12-4k',
-    enterpriseName: '辞图科技有限公司',
-    address: '广州'
-  },
-  {
-    recruitName: '产品经理',
-    salary: '12-4k',
-    enterpriseName: '辞图科技有限公司',
-    address: '广州'
-  },
-  {
-    recruitName: '产品经理',
-    salary: '12-4k',
-    enterpriseName: '辞图科技有限公司',
-    address: '广州'
+const props = defineProps({
+  list: {
+    type: Array,
+    default: () => []
   }
-]
+})
 </script>
 
 <style lang="scss" scoped>
@@ -54,10 +34,10 @@ const list = [
   padding: 20px 15px;
 }
 .recruit-name {
-  width: 120px;
+  width: 95px;
   font-weight: 500;
   display: inline-block;
-  max-width: 120px;
+  max-width: 95px;
   vertical-align: middle;
   white-space: nowrap;
   text-overflow: ellipsis;
@@ -97,9 +77,6 @@ const list = [
   color: #555;
   font-size: 13px;
 }
-.borders {
-  border-bottom: 1px dashed #ccc;
-}
 .more-btn {
   position: absolute;
   bottom: 18px;

+ 22 - 0
src/components/areaTree/index.vue

@@ -0,0 +1,22 @@
+<template>
+  <div v-if="show">
+    <recursive v-if="items?.length" :items="items"></recursive>
+  </div>
+</template>
+<script setup>
+import recursive from './recursive'
+import { getDict } from '@/hooks/web/useDictionaries'
+import { ref } from 'vue';
+defineOptions({ name:'common-components-areaTree'})
+
+let items = ref() 
+let children = ref() 
+const show = ref(false) 
+getDict('areaTreeData', {}, 'areaTreeData').then(({ data }) => {
+  console.log(data)
+  items.value = data?.length && data || []
+  children.value = items.value[0]?.children.length && items.value[0].children || []
+  show.value = true
+})
+
+</script>

+ 41 - 0
src/components/areaTree/recursive.vue

@@ -0,0 +1,41 @@
+<template>
+  <div>
+    <span class="mr-5" v-if="currentRowType > 2">不限</span>
+    <span v-for="(item, index) in props.items" :key="item.id">
+      <span v-if="index < num" class="mr-6" style="line-height: 32px;" @click="handleClick(item)">{{ item.name }}</span>
+    </span>
+    <span v-if="props.items?.length >= num" @click="handleClick(props.items, 'other')">其他</span>
+    <recursive v-if="children" :items="children"></recursive>
+  </div>
+</template>
+<script setup>
+import { ref } from 'vue'
+import recursive from './recursive'
+defineOptions({ name:'common-components-areaTree-recursive'})
+
+const num = 15
+const props = defineProps({items: Object})
+let children = ref('')
+let currentRowType = ref(0)
+if (props.items && props.items.length) {
+  const item = props.items[0] // 首个子级
+  currentRowType.value = item.type - 0 // 当前块级数据type
+  if (currentRowType.value < 2 && item.children && item.children.length) { // 展开子级(暂时默认展示到国家级)
+    children.value = item.children
+  }
+}
+
+const handleClick = (item, btnType) => {
+  console.log(btnType, 'item', item)
+  if (btnType === 'other') {
+    return
+  } else {
+    if ((item.type - 0) === 1) children.value = item.children // 国家级
+    else if ((item.type - 0) > 1) { // 省级
+      children.value = item.children
+    }
+    console.log('children', children)
+  }
+}
+
+</script>

+ 8 - 2
src/components/headSearch/index.vue

@@ -2,7 +2,7 @@
   <div class="search d-flex align-center">
     <div style="position: relative;">
       <div class="jobBox d-flex pl-5" :class="{'drawer': drawer}" @click.stop="drawer = !drawer">
-        <span>职位类型</span>
+        <span>{{ text }}</span>
         <span class="mdi mdi-chevron-down px-2" style="font-size: 18px;"></span>
       </div>
       <jobTypeCard class="jobTypeCardBox" v-if="drawer" @click.stop=""></jobTypeCard>
@@ -28,7 +28,7 @@ import { ref, watch } from 'vue'
 // import { useRouter } from 'vue-router'
 defineOptions({ name:'common-components-headSearch'})
 // const router = useRouter()
-
+const text = ref('职位类型')
 const value = ref('')
 let drawer = ref(false)
 // 点击外部关闭职位下拉
@@ -56,6 +56,12 @@ watch(() => sharedState.layoutClickCount, () => {
     &:hover {
       color: var(--v-primary-base);
     }
+    span {
+      max-width: 150px;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
   }
   .drawer {
     color: var(--v-primary-base);

+ 2 - 1
src/hooks/web/useDictionaries.js

@@ -1,4 +1,4 @@
-import { getDictData, getIndustryListData, getAreaListData, getPositionTreeData } from '@/api/common/index'
+import { getDictData, getIndustryListData, getAreaListData, getPositionTreeData, getAreaTreeData } from '@/api/common/index'
 // 定义对应的api
 // const DICT_CITY_API = {
 //   menduner_exp_type: getDictData
@@ -23,6 +23,7 @@ export const getDict = (type, params, apiType = 'dict') => {
       const apiFn = {
         dict: getDictData,
         positionTreeData: getPositionTreeData, // 职位tree
+        areaTreeData: getAreaTreeData, // 区域tree
         industryList: getIndustryListData,
         areaList: getAreaListData
       }

+ 7 - 3
src/layout/personal/navBar.vue

@@ -48,6 +48,9 @@
 
               <v-list>
                 <v-list-item v-for="(item, index) in items" :key="index" @click="item.change">
+                  <template v-slot:prepend>
+                    <v-icon :icon="item.icon"></v-icon>
+                  </template>
                   <v-list-item-title>{{ item.title }}</v-list-item-title>
                 </v-list-item>
               </v-list>
@@ -135,9 +138,10 @@ const handleLogout = async () => {
 }
 
 const items = ref([
-  { title: '账号设置', change: () => router.push({ path: '/personalAccount/accountBinding' }) },
-  { title: '切换为招聘者', change: changeRole },
-  { title: '退出登录', change: handleLogout }
+  { title: '在线简历', icon: 'mdi-list-box-outline', change: () => router.push({ path: '/resume' }) },
+  { title: '账号设置', icon: 'mdi-cog-outline', change: () => router.push({ path: '/personalAccount/accountBinding' }) },
+  { title: '切换为招聘者', icon: 'mdi-swap-horizontal', change: changeRole },
+  { title: '退出登录', icon: 'mdi-logout', change: handleLogout }
 ])
 
 const handleLogin = () => {

+ 14 - 0
src/router/modules/personal.js

@@ -45,6 +45,20 @@ const personal = [
         ]
       }
     ]
+  },
+  {
+    path: '/resume',
+    component: Layout,
+    name: 'resume',
+    meta: {
+      title: '在线简历'
+    },
+    children: [
+      {
+        path: '/resume',
+        component: () => import('@/views/resume/index')
+      }
+    ]
   }
 ]
 export default personal

+ 4 - 0
src/styles/index.css

@@ -30,3 +30,7 @@
 .default-active {
   color: var(--v-primary-base) !important;
 }
+
+.border-bottom-dashed {
+  border-bottom: 1px dashed #ccc;
+}

+ 1 - 1
src/styles/index.min.css

@@ -1 +1 @@
-:root{--zIndex-dialog:9999;--default-bgc:#f2f4f7;--v-primary-base:#00897B;--v-error-base:#fe574a;--v-primary-lighten1:#26A69A;--v-primary-lighten2:#4DB6AC;--v-primary-lighten3:#80CBC4;--v-primary-lighten4:#B2DFDB;--default-text:#666}.buttons{height:36px;width:224px}.half-button{height:36px;width:88px}.default-width{width:1184px;min-width:1184px;max-width:1184px;margin:0 auto}.default-active{color:var(--v-primary-base) !important}
+:root{--zIndex-dialog:9999;--default-bgc:#f2f4f7;--v-primary-base:#00897B;--v-error-base:#fe574a;--v-primary-lighten1:#26A69A;--v-primary-lighten2:#4DB6AC;--v-primary-lighten3:#80CBC4;--v-primary-lighten4:#B2DFDB;--default-text:#666}.buttons{height:36px;width:224px}.half-button{height:36px;width:88px}.default-width{width:1184px;min-width:1184px;max-width:1184px;margin:0 auto}.default-active{color:var(--v-primary-base) !important}.border-bottom-dashed{border-bottom:1px dashed #ccc}

+ 3 - 0
src/styles/index.scss

@@ -30,4 +30,7 @@
 // 高亮
 .default-active {
   color: var(--v-primary-base) !important;
+}
+.border-bottom-dashed {
+  border-bottom: 1px dashed #ccc;
 }

+ 13 - 0
src/utils/date.js

@@ -0,0 +1,13 @@
+// 时间戳转换为年月日时分秒
+export const timesTampChange = (timestamp) => {
+  const date = new Date(timestamp)
+  const Y = date.getFullYear() + '-'
+  const M = (date.getMonth() + 1).toString().padStart(2, '0') + '-'
+  const D = date.getDate().toString().padStart(2, '0') + ' '
+
+  const h = date.getHours().toString().padStart(2, '0') + ':'
+  const m = date.getMinutes().toString().padStart(2, '0') + ':'
+  const s = date.getSeconds().toString().padStart(2, '0')
+  const strDate = Y + M + D + h + m + s
+  return strDate
+}

+ 3 - 3
src/views/Home/personal/components/hotJobs.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="box text-center">
     <span class="mr-2">热门职位:</span>
-    <v-btn v-for="(item, index) in jobs" :key="index" size="small" class="ml-2" color="primary" variant="tonal">{{ item }}</v-btn>
+    <v-btn v-for="(item, index) in jobs" :key="index" size="small" class="ml-2" color="primary" variant="tonal">{{ item.nameCn }}</v-btn>
   </div>
 </template>
 
@@ -15,8 +15,8 @@ let jobs = ref(null)
 const getTreeData = async () => {
   const res = await getHotPositionList()
   jobs.value = res || []
-  // 暂无数据,先假数据
-  if (!res?.length) jobs.value = ['Java','PHP','C#','.NET','会计','区块链工程师','测试', '新媒体运营','人力资源专员/助理','GIS工程师']
+  // // 暂无数据,先假数据
+  // if (!res?.length) jobs.value = ['Java','PHP','C#','.NET','会计','区块链工程师','测试', '新媒体运营','人力资源专员/助理','GIS工程师']
 }
 getTreeData()
 </script>

+ 12 - 2
src/views/Home/personal/components/hotPromotedPositions.vue

@@ -25,6 +25,7 @@
 <script setup name="hotPromotedPositions">
 import PositionCard from '@/components/Position/item.vue'
 import { ref, reactive } from 'vue'
+import { useRouter } from 'vue-router'
 import { getPromotedPosition, getLatestPosition, getUrgentPosition } from '@/api/position'
 import { getDict } from '@/hooks/web/useDictionaries'
 
@@ -55,7 +56,7 @@ const getPositionList = async () => {
     items.value = list.map(e => {
       const valueKey = item.nameKey ? item.nameKey : 'label'
       const idKey = item.valueKey ? item.valueKey : 'value'
-      e[item.label] = dictObj[item.value].find(k => Number(k[idKey]) === e[item.key])[valueKey]
+      e[item.label] = dictObj[item.value].find(k => Number(k[idKey]) === Number(e[item.key]))[valueKey] || ''
       e.active = false
       return e
     })
@@ -73,8 +74,17 @@ getDictList()
 getPositionList()
 
 // 职位详情
+const info = ref({})
+const router = useRouter()
 const handlePosition = (item) => {
-  window.open(`/recruit/position/details/${item.positionId}`)
+  info.value = item
+  let routeData = router.resolve({
+    path: `/recruit/position/details/${item.positionId}`,
+    query: {
+      positionInfo: JSON.stringify(info)
+    }
+  })
+  window.open(routeData.href)
 }
 const handleEnterprise = (item) => {
   console.log(item, 'enterprise-item')

+ 21 - 0
src/views/recruit/position/components/cityFilter.vue

@@ -0,0 +1,21 @@
+<template>
+    <div>
+      <v-tabs v-model="tab" align-tabs="start" color="primary" @click="tabClick">
+        <v-tab :value="1">城市和区域</v-tab>
+      </v-tabs>
+      <v-window v-model="tab" class="mt-3">
+        <v-window-item :value="1">
+          <areaTree></areaTree>
+        </v-window-item>
+      </v-window>
+    </div>
+</template>
+<script setup>
+import areaTree from '@/components/areaTree'
+import { ref } from 'vue'
+
+defineOptions({name: 'retrieval-components-cityFilter'})
+const tab = ref(1)
+const tabClick = () => {
+}
+</script>

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

@@ -0,0 +1,9 @@
+<template>
+  <div>
+    筛选
+  </div>
+</template>
+<script setup>
+
+defineOptions({name: 'retrieval-components-conditionFilter'})
+</script>

+ 53 - 30
src/views/recruit/position/components/details.vue

@@ -3,13 +3,13 @@
       <div class="default-width banner px-6">
         <div class="banner-title">
           <h1>{{ info.name }}</h1>
-          <span class="salary">{{ info.payFrom }}-{{ info.payTo }}/</span>
-          <span class="refresh-time">2022-10-17 11:03:59 刷新 <v-icon color="warning" size="20">mdi-alert-outline</v-icon></span>
+          <span class="salary">{{ info.payFrom }}-{{ info.payTo }}/{{ positionInfo.payName }}</span>
+          <span class="refresh-time">{{ timesTampChange(info.updateTime) }} 刷新 <v-icon color="warning" size="20">mdi-alert-outline</v-icon></span>
         </div>
         <div class="banner-tags mt-4">
           <span v-for="k in desc" :key="k.mdi" class="mr-10">
             <v-icon color="#666" size="20">{{ k.mdi }}</v-icon>
-            <span class="ml-1">{{ k.label }}</span>
+            <span class="ml-1">{{ positionInfo[k.value] }}</span>
           </span>
         </div>
         <div class="banner-tools my-4" style="height: 47px;">
@@ -25,17 +25,7 @@
         <v-divider></v-divider>
         <div class="d-flex">
           <div class="content-left">
-            <div class="left-position-detail">
-              <h4>职位详情</h4>
-              <v-container class="pa-0 mt-3">
-                <v-row no-gutters align="start">
-                  <v-col v-for="k in positionDetail" :key="k.label" cols="4" class="mb-1">
-                    <span class="label-text">{{ k.label }}<span class="value-text">{{ k.value }}</span></span>
-                  </v-col>
-                </v-row>
-              </v-container>
-            </div>
-            <div class="mt-3" v-if="Object.keys(info).length">
+            <div v-if="Object.keys(info).length">
               <div>岗位职责:</div>
               <div class="requirement" v-html="info.content.replace(/\n/g, '</br>')"></div>
               <div class="mt-3">岗位要求:</div>
@@ -67,8 +57,11 @@
               <v-btn class="half-button radius" color="primary">投递简历</v-btn>
             </div>
           </div>
-          <div class="content-right">
-            <similarPositions></similarPositions>
+          <div class="content-right" v-if="Object.keys(info).length">
+            <!-- 公司信息 -->
+            <EnterpriseInfo :info="{ ...info, position: { ...positionInfo } }"></EnterpriseInfo>
+            <!-- 相似职位 -->
+            <similarPositions class="mt-3" :list="similarList"></similarPositions>
           </div>
         </div>
       </div>
@@ -77,37 +70,68 @@
 
 <script setup>
 defineOptions({ name: 'position-details' })
-import { ref } from 'vue'
+import { ref, reactive } from 'vue'
 import { useRouter } from 'vue-router'
-import { getPositionDetails } from '@/api/position'
+import { timesTampChange } from '@/utils/date'
+import { getDict } from '@/hooks/web/useDictionaries'
+import { getPositionDetails, getSimilarPosition } from '@/api/position'
 import similarPositions from '@/components/Position/similarPositions.vue'
+import EnterpriseInfo from '@/components/Enterprise/info.vue'
 
 const router = useRouter()
 const { id } = router.currentRoute.value.params
+const { _value: positionInfo } = JSON.parse(router.currentRoute.value.query.positionInfo)
 
 // 职位详情
 const info = ref({})
 const getPositionDetail = async () => {
   const data = await getPositionDetails({ id })
   info.value = data
-  console.log(data, 'info')
 }
 getPositionDetail()
 
 const desc = [
-  { mdi: 'mdi-map-marker-outline', value: 'areaName', label: '广州' },
-  { mdi: 'mdi-school-outline', value: 'eduName', label: '本科' },
-  { mdi: 'mdi-clock-time-ten-outline', value: 'expName', label: '1-3年' }
+  { mdi: 'mdi-map-marker-outline', value: 'areaName' },
+  { mdi: 'mdi-school-outline', value: 'eduName' },
+  { mdi: 'mdi-clock-time-ten-outline', value: 'expName' }
 ]
 
-const positionDetail = [
-  { label: '招聘人数:', value: '1人' },
-  { label: '到岗时间:', value: '2周以内' },
-  { label: '年龄要求:', value: '20-35周岁' },
-  { label: '婚况要求:', value: '不限' },
-  { label: '应届生:', value: '接受应届生' },
-  { label: '语言要求:', value: '普通话' }
+// 相似职位
+const similarList = ref([])
+const getSimilarPositionList = async () => {
+  if (!Object.keys(positionInfo).length) return
+  const { list } = await getSimilarPosition({ pageNo: 1, pageSize: 4, positionId: positionInfo.positionId, expType: positionInfo.expType })
+  const items = list.splice(0, 4)
+  dictList.forEach(item => {
+    similarList.value = items.map(e => {
+      const valueKey = item.nameKey ? item.nameKey : 'label'
+      const idKey = item.valueKey ? item.valueKey : 'value'
+      e[item.label] = dictObj[item.value].find(k => Number(k[idKey]) === Number(e[item.key]))[valueKey] || ''
+      return e
+    })
+  })
+}
+
+const dictObj = reactive({
+  payUnit: [],
+  area: []
+})
+const dictList = [
+  { type: 'menduner_pay_unit', value: 'payUnit', key: 'payUnit', label: 'payName' },
+  { type: 'menduner_area_type', value: 'area', key: 'areaId', label: 'areaName', params: {}, apiType: 'areaList', nameKey: 'name', valueKey: 'id' }
 ]
+// 字典
+const getDictList = async () => {
+  dictList.forEach(async (val) => {
+    const { data } = await getDict(val.type, val.params, val.apiType)
+    dictObj[val.value] = data
+  })
+}
+const getData = async () => {
+  await getDictList()
+  getSimilarPositionList()
+}
+getData()
 </script>
 
 <style lang="scss" scoped>
@@ -159,7 +183,6 @@ const positionDetail = [
 }
 .content-right {
   flex: 1;
-  // background-color: #d5e6e8;
   padding: 20px 20px 20px 0;
 }
 .label-text {

+ 10 - 4
src/views/recruit/position/index.vue

@@ -1,10 +1,14 @@
 <!-- 检索列表页 - 职位检索 -->
 <template>
   <div class="default-width">
-    <div>
-      检索
-    </div>
-    <div>筛选条件</div>
+    <div style="width: 100%; height: 20px;"></div>
+    <v-card>
+      <div class="stickyBox my-5">
+        <headSearch></headSearch>
+      </div>
+      <!-- 城市和区域 -->
+      <cityFilter class="mx-5 mb-5"></cityFilter>
+    </v-card>
     <div>
       <div>
         左侧列表
@@ -14,6 +18,8 @@
   </div>
 </template>
 <script setup>
+import cityFilter from './components/cityFilter'
+import headSearch from '@/components/headSearch'
 import { useRoute } from 'vue-router'
 defineOptions({name: 'retrieval-position-page'})
 const route = useRoute()

+ 7 - 0
src/views/resume/index.vue

@@ -0,0 +1,7 @@
+<template>
+  <div>在线简历</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'resume-index' })
+</script>