Browse Source

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

zhengnaiwen_citu 7 months ago
parent
commit
ec974192f9
32 changed files with 706 additions and 205 deletions
  1. 16 0
      src/api/enterprise.js
  2. BIN
      src/assets/headerBg.jpg
  3. BIN
      src/assets/headerBg.png
  4. 1 1
      src/layout/enterprise.vue
  5. 1 1
      src/layout/index.vue
  6. 4 4
      src/layout/personal/navBar.vue
  7. 1 1
      src/router/modules/common.js
  8. 14 0
      src/router/modules/recruit.js
  9. 2 2
      src/styles/personal/navBar.css
  10. 0 0
      src/styles/personal/navBar.min.css
  11. 3 2
      src/styles/personal/navBar.scss
  12. 17 2
      src/utils/headhuntingData.js
  13. 168 0
      src/views/about/index.vue
  14. 21 21
      src/views/headhunting/components/content.vue
  15. 1 9
      src/views/headhunting/components/serviceContent.vue
  16. 2 2
      src/views/recruit/enterprise/entInfoSetting/informationSettingsComponents/basicInfo.vue
  17. 2 2
      src/views/recruit/enterprise/search/index.vue
  18. 134 1
      src/views/recruit/enterprise/search/recommend/index.vue
  19. 6 3
      src/views/recruit/enterprise/search/retrieval/components/area.vue
  20. 1 1
      src/views/recruit/enterprise/search/retrieval/components/position.vue
  21. 141 19
      src/views/recruit/enterprise/search/retrieval/index.vue
  22. 16 3
      src/views/recruit/enterprise/talentPool/components/details/dict.js
  23. 1 1
      src/views/recruit/personal/home/components/advertisement/index.vue
  24. 0 61
      src/views/recruit/personal/home/components/headCarousel.vue
  25. 2 2
      src/views/recruit/personal/home/components/homeJobTypeCard/index.vue
  26. 8 2
      src/views/recruit/personal/home/index.vue
  27. 58 6
      src/views/recruit/personal/position/components/conditionFilter.vue
  28. 37 23
      src/views/recruit/personal/position/components/conditionFilter/commonPath.vue
  29. 5 0
      src/views/recruit/personal/position/components/conditionFilter/commonStyle.vue
  30. 42 34
      src/views/recruit/personal/position/components/dict.js
  31. 1 1
      src/views/recruit/personal/position/index.vue
  32. 1 1
      src/views/recruit/personal/recommend/index.vue

+ 16 - 0
src/api/enterprise.js

@@ -185,4 +185,20 @@ export const checkRecruiterPassword = async () => {
   return await request.get({
   return await request.get({
     url: '/app-api/menduner/system/recruit/user/check/password'
     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
+  })
+}
+
+// 找人-推荐
+export const getPersonRecommendPage = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/recruit/person-recommend/page',
+    params
+  })
 }
 }

BIN
src/assets/headerBg.jpg


BIN
src/assets/headerBg.png


+ 1 - 1
src/layout/enterprise.vue

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

+ 1 - 1
src/layout/index.vue

@@ -19,7 +19,7 @@ defineOptions({ name: 'personal-layout-index' })
 
 
 // 不展示侧边栏名单
 // 不展示侧边栏名单
 const whiteList = ['/login', '/privacyPolicy', '/userAgreement', '/register', '/recruit/personal/advertisement/introduce']
 const whiteList = ['/login', '/privacyPolicy', '/userAgreement', '/register', '/recruit/personal/advertisement/introduce']
-const footerWhiteList = ['/recruit/personal/message', '/recruit/personal/advertisement/introduce']
+const footerWhiteList = ['/recruit/personal/message', '/recruit/personal/advertisement/introduce', '/about']
 const router = useRouter()
 const router = useRouter()
 
 
 const sharedState = useSharedState()
 const sharedState = useSharedState()

+ 4 - 4
src/layout/personal/navBar.vue

@@ -175,12 +175,12 @@ const navList = [
   //   ]
   //   ]
   // },
   // },
   { title: '直聘', path: '/recruit/personal/recommend', noLeaving: true },
   { title: '直聘', path: '/recruit/personal/recommend', noLeaving: true },
-  { title: '甄选', path: '/mall' },
-  { title: '猎', path: '/headhunting' },
+  { title: '商城', path: '/mall' },
+  { title: '猎', path: '/headhunting' },
   { title: '火苗儿' },
   { title: '火苗儿' },
   { title: '联合会' },
   { title: '联合会' },
-  { title: '数据' },
-  { title: '了解门墩儿' }
+  // { title: '数据' },
+  { title: '了解门墩儿', path: '/about' }
 ]
 ]
 
 
 const handleClick = (e, status) => {
 const handleClick = (e, status) => {

+ 1 - 1
src/router/modules/common.js

@@ -77,7 +77,7 @@ const common = [
       title: '集团介绍'
       title: '集团介绍'
     },
     },
     component: () => import('@/views/recruit/personal/home/components/advertisement/dynamic/intercontinental.vue')
     component: () => import('@/views/recruit/personal/home/components/advertisement/dynamic/intercontinental.vue')
-  },
+  }
 ]
 ]
 
 
 export default common
 export default common

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

@@ -45,6 +45,20 @@ const recruit = [
       }
       }
     ]
     ]
   },
   },
+  {
+    path: '/about',
+    component: Layout,
+    children: [
+      {
+        path: '/about',
+        component: () => import('@/views/about/index'),
+        name: 'about',
+        meta: {
+          title: '了解门墩儿'
+        }
+      }
+    ]
+  },
   {
   {
     path: '/recruit/personal/position',
     path: '/recruit/personal/position',
     component: Layout,
     component: Layout,

+ 2 - 2
src/styles/personal/navBar.css

@@ -52,7 +52,7 @@
   width: 100vw;
   width: 100vw;
   margin: 0 auto;
   margin: 0 auto;
   align-items: center;
   align-items: center;
-  padding: 30px;
+  padding: 0 30px;
 }
 }
 
 
 .nav-logo {
 .nav-logo {
@@ -153,7 +153,7 @@
 .menuList {
 .menuList {
   display: flex;
   display: flex;
   height: 50px;
   height: 50px;
-  align-items: center;
+  line-height: 55px;
 }
 }
 
 
 .menuList div {
 .menuList div {

File diff suppressed because it is too large
+ 0 - 0
src/styles/personal/navBar.min.css


+ 3 - 2
src/styles/personal/navBar.scss

@@ -49,7 +49,7 @@
   // max-width: 1184px;
   // max-width: 1184px;
   margin: 0 auto;
   margin: 0 auto;
   align-items: center;
   align-items: center;
-  padding: 30px;
+  padding: 0 30px;
 }
 }
 .nav-logo {
 .nav-logo {
   float: left;
   float: left;
@@ -146,7 +146,8 @@
 .menuList {
 .menuList {
   display: flex;
   display: flex;
   height: 50px;
   height: 50px;
-  align-items: center;
+  line-height: 55px;
+  // align-items: center;
   div {
   div {
     margin-left: 10px;
     margin-left: 10px;
   }
   }

+ 17 - 2
src/utils/headhuntingData.js

@@ -70,6 +70,21 @@ export const serviceData = [
       '6. 法律合规性:我们的服务严格遵守相关法律法规,确保调查过程的合法性、合规性,保护候选人的隐私权益。'
       '6. 法律合规性:我们的服务严格遵守相关法律法规,确保调查过程的合法性、合规性,保护候选人的隐私权益。'
     ]
     ]
   },
   },
+  {
+    title: '多样化的人才网络',
+    id: 'diversified-talent-network',
+    startDesc: '门墩儿猎头深知企业在招募高级管理人员时,高管信誉与资质的重要性。为此,我们推出了高管信誉与资质验证服务,这是一项专业的背景调查和资质审核服务,旨在为企业提供准确、可靠的高管候选人评估,确保企业能够招募到具备优秀职业道德和过硬专业能力的高层领导。',
+    startTitle: '以下是高管信誉与资质验证服务的详细描述:',
+    endDesc: '门墩儿猎头的高管信誉与资质验证服务,为企业招募高管提供了坚实的安全保障,帮助企业规避了因高管个人问题带来的风险,确保了企业高层管理的稳定性和企业声誉的完整性。通过我们的专业服务,企业能够更加放心地选拔和任用高层管理人才,为企业的长远发展保驾护航。',
+    children: [
+      '1. 信誉调查:门墩儿猎头通过严格的调查流程,对高管候选人的职业背景、个人声誉、法律记录等进行深入调查,包括但不限于工作经历、教育背景、信用记录、社会关系等,以确保候选人的信誉良好。',
+      '2. 资质审核:我们对候选人的专业资质进行详细审核,包括专业资格证书、行业认证、荣誉奖项等,确保候选人的专业能力符合企业的要求。',
+      '3. 工作表现评估:门墩儿猎头通过与候选人前任雇主、同事、下属的沟通,了解其在以往工作中的表现和领导风格,为企业的决策提供参考。',
+      '4. 道德风险评估:我们评估候选人是否存在潜在的商业道德风险,如利益冲突、不正当竞争等,为企业规避潜在的风险。',
+      '5. 综合报告:门墩儿猎头根据调查和审核结果,提供一份详尽的综合报告,为企业决策提供客观、全面的参考依据。',
+      '6. 法律合规性:我们的服务严格遵守相关法律法规,确保调查过程的合法性、合规性,保护候选人的隐私权益。'
+    ]
+  },
   {
   {
     title: '酒店集团总部',
     title: '酒店集团总部',
     id: 'hotel-group-headquarters',
     id: 'hotel-group-headquarters',
@@ -227,8 +242,8 @@ export const consultantData = [
     ]
     ]
   },
   },
   {
   {
-    id: 'julie',
-    title: '姚嘉庆女士(Julie)',
+    id: 'julia',
+    title: '姚嘉庆女士(Julia)',
     job: '猎头顾问',
     job: '猎头顾问',
     country: '北京',
     country: '北京',
     avatar: 'https://minio.citupro.com/dev/menduner/consultant/julie.png',
     avatar: 'https://minio.citupro.com/dev/menduner/consultant/julie.png',

+ 168 - 0
src/views/about/index.vue

@@ -0,0 +1,168 @@
+<template>
+  <div style="width: 100%; height: 100%;" class="">
+    <div class="banner"></div>
+    <div class="default-width white-bgc px-10 my-3">
+      <div class="pb-15 pt-10">
+        <h1 class="title">公司简介</h1>
+        <p class="mb-5 mt-10">门墩儿是聚焦酒店及现代服务业人力资源技术与人才数据服务的互联网科技公司。</p>
+        <p>通过一体化的人力资源运营技术平台,致力于为企业提供人力资源数据服务支持,同时基于数据与技术,为企业提供线上招聘、猎头、实习生及知识付费等全方位人力资源解决方案。</p>
+      </div>
+      <div class="d-flex box mt-5">
+        <div class="box-item" v-for="(val, i) in list" :key="i" :style="{'background-image': `url('${val.url}')`}">
+          <p class="font-size-19 mb-3">{{ val.title }}</p>
+          <p class="font-size-14 pt-3" style="border-top: 1px solid rgba(255, 255, 255, .5)">{{ val.desc }}</p>
+        </div>
+      </div>
+      <div class="py-15">
+        <v-divider></v-divider>
+        <h1 class="title mt-15">学术和行业之声</h1>
+        <div class="mt-10">
+          <div v-for="(val, i) in introduce" :key="i" :style="{'text-align': i % 2 === 0 ? 'left' : 'right'}" class="py-15 bole-item">
+            <div class="left">
+              <v-img :src="val.avatar" width="250" height="250"></v-img>
+            </div>
+            <div class="right" :style="{'right': i % 2 === 0 ? '0' : ''}">
+              <p class="font-size-18">{{ val.name }}</p>
+              <p class="font-size-14 my-1">{{ val.job }}</p>
+              <p class="font-size-14">{{ val.company }}</p>
+              <p class="font-size-14 mt-5">{{ val.desc }}</p>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'about-index'})
+
+const list = [
+  { title: '公司使命', desc: '成为中国酒店行业可信赖的人力资源科技公司。', url: 'https://minio.citupro.com/dev/menduner/home/introduct-bg-01.png' },
+  { title: '公司愿景', desc: '人力数据技术赋能人才发现,助力酒店企业提质增效,实现业务可持续成长。', url: 'https://minio.citupro.com/dev/menduner/home/introduct-bg-02.png' }
+]
+
+const introduce = [
+  {
+    name: 'Professor Kaye Chon',
+    job: 'Dean and Chair Professor, and Walter Kwok Foundation Professor in International Hospitality Management,School of Hotel and Tourism Management',
+    company: 'The Hong Kong Polytechnic University',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%871.png',
+    desc: 'The unprecedented growth of hotel industry in China creates a huge demand for qualified workers for the industry. This platform is very much welcomed because it will provide a win-win solution to both the demand and supply side of the hospitality industry human capital.'
+  },
+  {
+    name: 'Benjamin Yan 严竹明',
+    job: 'Chairman',
+    company: 'Ruiyee Hospitality',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%872.png',
+    desc: '恭喜门墩儿成功上线。如何遴选优质酒店业人才一直是我们的一大难题,人才关乎企业未来,而门墩儿的人工智能、大数据等技术必将助我们一臂之力,用人问题从此迎刃而解。'
+  },
+  {
+    name: 'Thierry Brinte',
+    job: 'General Manager',
+    company: 'Gran Hotel Bristol by Kempinski',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%873.png',
+    desc: 'I wish to offer my congratulations to Simon and his teammates in launching this fully-dedicated talent career service and development social platform for the hotel industry in China. The platform will benefit both hotel professionals and hotel employers in their endeavors to find the right and qualified hotel talents to ensure successful hotel business operations.'
+  },
+  {
+    name: 'Emily Zhu 竺丽萍',
+    job: '总经理',
+    company: '杭州新侨饭店',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%874.png',
+    desc: '“有所为,有所不为”,只做专业领域,且只做专业领域的金字塔市场, 这是“门墩儿”平台的特点。既深谙买方市场的需求,又有卖方市场的广阔人脉,这是“门墩儿”平台的特长。“千军好买,一将难求”,作为酒店业主方,我们需要像“门墩儿”这样能提供“私人定制”服务的合作伙伴。我个人非常看好“门墩儿”平台的发展前景,Bravo !!'
+  },
+  {
+    name: 'Antony Platford',
+    job: 'Seasoned Hotelier',
+    company: 'Hotel and Tourism Consulting',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%875.png',
+    desc: 'I wish to congratulate Simon Tian on the establishment of Menduner. There is no doubt of the future success for this enterprise and its clients given the proven ability, skills and professional experience that Simon and his team can provide.'
+  },
+  {
+    name: 'Jack Xiao 肖君',
+    job: '高级副总裁',
+    company: '美好生活第三方酒店管理 (深圳) 有限公司',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%876.png',
+    desc: '门墩儿是专属于酒店行业的职业发展社交平台。希望能在这里携手更多志同道合的伙伴,追求我们共同的梦想。'
+  },
+  {
+    name: 'Nelson Li 李可',
+    job: '助理总经理兼武汉费尔蒙酒店业主代表',
+    company: '泛海酒店投资管理有限公司',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%877.png',
+    desc: '世界每时每刻都在发生变化,唯一不变的是我们对于这个行业的初心和热情。很高兴看到一群有梦想的酒店人为了遇见更好的自己,为了中国酒店业的未来勇敢的迈出了这一步…“精诚所至 金石为开”,愿“门墩儿”与中国酒店人共同成长,加油!'
+  },
+  {
+    name: 'Gerhard H. Zimmer',
+    job: 'President',
+    company: 'ZYG INC.',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%878.png',
+    desc: 'Simon, a very talented Hotelier who has made good use of his technical skills, combined with excellent human relations to provide a solid foundation for a most successful operation.'
+  },
+  {
+    name: 'Ann Leung 梁旭君',
+    job: '创始人',
+    company: '禾禾木文化发展有限公司',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%879.png',
+    desc: '找到对的门,认识对的人. 门墩儿,比酒店人更懂酒店人,从这里开启不同的圈层,打开职业生涯你不敢想象的可能!'
+  },
+  {
+    name: 'Henry Sun 孙伟杰',
+    job: '创始人',
+    company: 'Mentor共享教室',
+    avatar: 'https://minio.citupro.com/dev/menduner/home/about/%E5%9B%BE%E7%89%8710.png',
+    desc: 'What a day and milestone for Chinese hospitality industry! Congratulations to Simon and his team on providing this great platform to hoteliers, where we will no longer feel alone when building our careers. Knowing someone experienced and knowledgeable is there for us, our fellow hoteliers, is fantastic and extremely helpful. Go Menduner!'
+  }
+]
+</script>
+
+<style scoped lang="scss">
+.banner {
+  width: 100%;
+  height: 390px;
+  background-image: url('https://minio.citupro.com/dev/menduner/home/about-bg.jpg');
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: cover;
+}
+.title {
+  font-weight: 400;
+  text-align: center;
+}
+.box {
+  width: 100%;
+  &-item {
+    width: 50%;
+    height: 150px;
+    border-radius: 8px;
+    background-position: center center;
+    background-repeat: no-repeat;
+    background-size: cover;
+    padding: 30px;
+    color: #fff;
+    &:nth-child(2n) {
+      margin-left: 40px;
+    }
+  }
+}
+.bole-item {
+  padding: 30px 0;
+  position: relative;
+}
+.left {
+  display: inline-block;
+  width: 300px;
+}
+.right {
+  position: absolute;
+  top: 50%;
+  transform: translateY(-50%);
+  font-size: 14px;
+  color: #666;
+  line-height: 2;
+  text-align: center;
+  vertical-align: middle;
+  width: 598px;
+}
+</style>
+

+ 21 - 21
src/views/headhunting/components/content.vue

@@ -17,7 +17,7 @@
     </div>
     </div>
     <!-- 服务 -->
     <!-- 服务 -->
     <div class="service-link">
     <div class="service-link">
-      <div class="service-link-box common-width">
+      <div class="service-link-box" style="width: 199%; max-width: 1200px;">
         <ul>
         <ul>
           <li 
           <li 
             v-for="(val, index) in service" 
             v-for="(val, index) in service" 
@@ -60,10 +60,10 @@
         </li>
         </li>
       </ul>
       </ul>
     </div>
     </div>
-    <!-- 我们的见解 -->
+    <!-- 行业的观点 -->
     <div class="articles common-width">
     <div class="articles common-width">
       <div class="line"></div>
       <div class="line"></div>
-      <h2 class="text-center">我们的见解</h2>
+      <h2 class="text-center">行业的观点</h2>
       <div class="d-flex article-box">
       <div class="d-flex article-box">
         <div v-for="(val, i) in articles" :key="i" class="article-box-item" @click="handleClick('article', val.id)">
         <div v-for="(val, i) in articles" :key="i" class="article-box-item" @click="handleClick('article', val.id)">
           <div class="sshr__article__flyout-placeholder"></div>
           <div class="sshr__article__flyout-placeholder"></div>
@@ -89,16 +89,16 @@
         <div class="left">
         <div class="left">
           <h2>欢迎关注,了解门墩儿的新动态。</h2>
           <h2>欢迎关注,了解门墩儿的新动态。</h2>
           <p class="mt-3" style="font-size: .9rem;">门墩儿在所有主流社交媒体都有账号。欢迎关注我们,以便了解关于发展趋势和领导力问题的最新见解。</p>
           <p class="mt-3" style="font-size: .9rem;">门墩儿在所有主流社交媒体都有账号。欢迎关注我们,以便了解关于发展趋势和领导力问题的最新见解。</p>
-          <div class="social-contact">
-            <div v-for="(item, index) in social" :key="index" class="d-flex" :class="{'mb-5': index !== social.length - 1}">
-              <v-img :src="item.url" width="52" height="48" class="cursor-pointer"></v-img>
-              <v-tooltip v-if="item.showTooltip" :text="item.tips" location="start" activator="parent">
-                <div class="ma-3" style="text-align: center">
-                  <v-img class="ml-2" cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/static/mendunerCode.jpg" width="120" height="120"></v-img>
-                  <span class="tips-text">关注门墩儿微信公众号</span>
-                </div>
-              </v-tooltip>
-              <p class="ml-5">{{ item.desc }}</p>
+          <div class="social-contact mt-5">
+            <p class="mb-2">联系方式</p>
+            <p>猎头顾问: 姚嘉庆 Julia</p>
+            <p>邮&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱:Julia.yao@menduner.com</p>
+            <p>手&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;机:18501626969</p>
+            <div class="mt-5 text-center">
+              <div style="width: 120px; height: 120px; margin: auto;">
+                <v-img class="ml-2" cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/static/mendunerCode.jpg" width="120" height="120"></v-img>
+              </div>
+              <span class="tips-text ml-6">关注门墩儿微信公众号</span>
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
@@ -128,7 +128,8 @@ const service = [
   { title: '人才发展储备策略', id: 'talent-development-reserve-strategy' },
   { title: '人才发展储备策略', id: 'talent-development-reserve-strategy' },
   { title: '管理者能力提升方案', id: 'manager-capability-enhancement-plan' },
   { title: '管理者能力提升方案', id: 'manager-capability-enhancement-plan' },
   { title: '卓越成长轨迹', id: 'excellent-growth-trajectory' },
   { title: '卓越成长轨迹', id: 'excellent-growth-trajectory' },
-  { title: '高管信誉与资质验证', id: 'senior-management-elite-verification' }
+  { title: '高管信誉与资质验证', id: 'senior-management-elite-verification' },
+  { title: '多样化的人才网络', id: 'diversified-talent-network' }
 ]
 ]
 // 办公地点
 // 办公地点
 const countryOffice = [
 const countryOffice = [
@@ -140,7 +141,7 @@ const countryOffice = [
 const consultant = [
 const consultant = [
   { country: '苏州', enName: '田森先生(Simon Tian)', id: 'simon', avatar: 'https://minio.citupro.com/dev/menduner/consultant/simon.png' },
   { country: '苏州', enName: '田森先生(Simon Tian)', id: 'simon', avatar: 'https://minio.citupro.com/dev/menduner/consultant/simon.png' },
   { country: '北京', enName: '潘青海先生(Peter Pan)', id: 'peter', avatar: 'https://minio.citupro.com/dev/menduner/consultant/peter.png' },
   { country: '北京', enName: '潘青海先生(Peter Pan)', id: 'peter', avatar: 'https://minio.citupro.com/dev/menduner/consultant/peter.png' },
-  { country: '北京', enName: '姚嘉庆女士(Julie)', id: 'julie', avatar: 'https://minio.citupro.com/dev/menduner/consultant/julie.png' }
+  { country: '北京', enName: '姚嘉庆女士(Julia)', id: 'julia', avatar: 'https://minio.citupro.com/dev/menduner/consultant/julie.png' }
 ]
 ]
 // 我们的见解
 // 我们的见解
 const articles = [
 const articles = [
@@ -149,10 +150,10 @@ const articles = [
   { title: '全球视角下的CFO角色演变:跨领域高管的洞察与应对策略', id: 'the-evolution-of-the-cfo-role-from-a-global-perspective', url: 'https://cn.spencerstuart.com/-/media/search-images/placeholder-hdr.jpg' }
   { title: '全球视角下的CFO角色演变:跨领域高管的洞察与应对策略', id: 'the-evolution-of-the-cfo-role-from-a-global-perspective', url: 'https://cn.spencerstuart.com/-/media/search-images/placeholder-hdr.jpg' }
 ]
 ]
 // 联系我们
 // 联系我们
-const social = [
-  { desc: '敬请查询我们的领英账号以关注最新的研究报告和职业机会。', url: 'https://cn.spencerstuart.com/-/media/linkedin-logo.png?h=50&amp;w=50&amp;la=zh-CN&amp;hash=80E76CEDF468709061F46EE02219B4DA' },
-  { showTooltip: true, desc: '关注门墩儿官方微信公众号,获悉热点资讯和行业洞见。', url: 'https://cn.spencerstuart.com/-/media/wechat.jpg?h=75&amp;w=75&amp;la=zh-CN&amp;hash=B9D5E58A097630C3C5A878D5ED49B4A6' }
-]
+// const social = [
+//   { desc: '敬请查询我们的领英账号以关注最新的研究报告和职业机会。', url: 'https://cn.spencerstuart.com/-/media/linkedin-logo.png?h=50&amp;w=50&amp;la=zh-CN&amp;hash=80E76CEDF468709061F46EE02219B4DA' },
+//   { showTooltip: true, desc: '关注门墩儿官方微信公众号,获悉热点资讯和行业洞见。', url: 'https://cn.spencerstuart.com/-/media/wechat.jpg?h=75&amp;w=75&amp;la=zh-CN&amp;hash=B9D5E58A097630C3C5A878D5ED49B4A6' }
+// ]
 
 
 const handleClick = (type, id) => {
 const handleClick = (type, id) => {
   if (!type && !id) return
   if (!type && !id) return
@@ -251,7 +252,7 @@ const handleClick = (type, id) => {
       margin: 0;
       margin: 0;
       padding: 0;
       padding: 0;
       li {
       li {
-        width: 20%;
+        width: 16.6%;
         padding: 13px;
         padding: 13px;
         text-align: center;
         text-align: center;
         vertical-align: middle;
         vertical-align: middle;
@@ -520,7 +521,6 @@ const handleClick = (type, id) => {
     .social-contact {
     .social-contact {
       padding: 28px 26px;
       padding: 28px 26px;
       background-color: #f5f7f9;
       background-color: #f5f7f9;
-      margin-top: 40px;
     }
     }
   }
   }
   .right {
   .right {

+ 1 - 9
src/views/headhunting/components/serviceContent.vue

@@ -9,9 +9,6 @@
           <p>Advice to new CEOs for establishing</p>
           <p>Advice to new CEOs for establishing</p>
           <p>a high-performing top team</p>
           <p>a high-performing top team</p>
         </div>
         </div>
-        <div class="sshr__hero-slide__actions">
-          <div class="sshr__hero-slide__read-more">Read More</div>
-        </div>
       </div>
       </div>
     </div>
     </div>
     <div class="common-width service">
     <div class="common-width service">
@@ -31,7 +28,6 @@
           <div v-else class="service-desc">{{ item.desc }}</div>
           <div v-else class="service-desc">{{ item.desc }}</div>
         </div>
         </div>
       </div>
       </div>
-      <div class="common-button">查看所有能力</div>
     </div>
     </div>
     <div class="common-width" style="margin: auto; color: #4c4c4b;">
     <div class="common-width" style="margin: auto; color: #4c4c4b;">
       <div class="common-line" v-for="(k, i) in list" :key="i">
       <div class="common-line" v-for="(k, i) in list" :key="i">
@@ -39,7 +35,6 @@
         <div class="d-flex industry">
         <div class="d-flex industry">
           <div class="industry-item mt-5">
           <div class="industry-item mt-5">
             <p class="font-size-16">{{ k.desc }}</p>
             <p class="font-size-16">{{ k.desc }}</p>
-            <div class="common-button">{{ k.btnTitle }}</div>
           </div>
           </div>
           <div class="industry-item mt-5 industry-right ml-15 d-flex">
           <div class="industry-item mt-5 industry-right ml-15 d-flex">
             <ul style="list-style-type: none; width: 50%;">
             <ul style="list-style-type: none; width: 50%;">
@@ -69,10 +64,7 @@ const service = ref([
   { title: '管理者能力提升方案', desc: '我们在CEO继任领域拥有数十年的顾问经验,致力于协助董事会制定、规划和执行CEO继任的全过程。', id: 'manager-capability-enhancement-plan' },
   { title: '管理者能力提升方案', desc: '我们在CEO继任领域拥有数十年的顾问经验,致力于协助董事会制定、规划和执行CEO继任的全过程。', id: 'manager-capability-enhancement-plan' },
   { title: '卓越成长轨迹', desc: '我们的综合评估方法能提供翔实数据和深入见解,从而评价和预测领导者的表现、契合度和影响力。', active: false, id: 'excellent-growth-trajectory' },
   { title: '卓越成长轨迹', desc: '我们的综合评估方法能提供翔实数据和深入见解,从而评价和预测领导者的表现、契合度和影响力。', active: false, id: 'excellent-growth-trajectory' },
   { title: '高管信誉与资质验证', desc: '我们提供甄选和培养领导者、优化团队效能,以及评估和改进企业文化所需的见解。', active: false, id: 'senior-management-elite-verification' },
   { title: '高管信誉与资质验证', desc: '我们提供甄选和培养领导者、优化团队效能,以及评估和改进企业文化所需的见解。', active: false, id: 'senior-management-elite-verification' },
-  { title: '董事会服务', desc: '我们提供的高管和董事人选,能够制定明确的数字化战略,并驾驭企业转型所需的人才、运营及文化变革。', active: false, id: 'senior-management-elite-verification' },
-  { title: '中国业务部', desc: '我们的中国业务部为中国企业进入德国和欧洲拓展业务提供高管寻聘和领导力咨询服务,同时陪伴德国企业在中国市场的发展。', active: false, id: 'senior-management-elite-verification' },
-  { title: '多样性', desc: '我们致力于广泛发展关于多文化问题的专业基础,确保我们能为客户提供当前候选人名单中最具资格的人才。', active: false, id: 'senior-management-elite-verification' },
-  { title: '家族业务', desc: '作为家族控股公司和家族支配公司的受托顾问,我们具有家族客户所注重的敏感、谨慎和灵活的特征', active: false, id: 'senior-management-elite-verification' }
+  { title: '多样化的人才网络', desc: '我们提供的高管和董事人选,能够制定明确的数字化战略,并驾驭企业转型所需的人才、运营及文化变革。', active: false, id: 'diversified-talent-network' }
 ])
 ])
 
 
 const list = [
 const list = [

+ 2 - 2
src/views/recruit/enterprise/entInfoSetting/informationSettingsComponents/basicInfo.vue

@@ -143,11 +143,11 @@ const formItems = ref({
       key: 'openTime',
       key: 'openTime',
       dateType: 'date', // 时间类型 year month date time
       dateType: 'date', // 时间类型 year month date time
       value: null,
       value: null,
-      label: '开业时间 *',
+      label: '开业时间',
       col: 6,
       col: 6,
       flexStyle: 'mr-3',
       flexStyle: 'mr-3',
       outlined: true,
       outlined: true,
-      rules: [v => !!v || '请选择开业时间']
+      // rules: [v => !!v || '请选择开业时间']
       // options: {},
       // options: {},
     },
     },
     {
     {

+ 2 - 2
src/views/recruit/enterprise/search/index.vue

@@ -2,7 +2,7 @@
   <v-card class="card-box pa-5">
   <v-card class="card-box pa-5">
     <v-tabs v-model="tab" align-tabs="center" color="primary" bg-color="#f7f8fa">
     <v-tabs v-model="tab" align-tabs="center" color="primary" bg-color="#f7f8fa">
       <v-tab :value="0">推荐</v-tab>
       <v-tab :value="0">推荐</v-tab>
-      <v-tab :value="1">索</v-tab>
+      <v-tab :value="1">索</v-tab>
     </v-tabs>
     </v-tabs>
     <searchRecommend v-if="tab === 0"></searchRecommend>
     <searchRecommend v-if="tab === 0"></searchRecommend>
     <searchRetrieval v-else></searchRetrieval>
     <searchRetrieval v-else></searchRetrieval>
@@ -15,7 +15,7 @@ import { ref } from 'vue'
 import searchRecommend from './recommend/index.vue'
 import searchRecommend from './recommend/index.vue'
 import searchRetrieval from './retrieval/index.vue'
 import searchRetrieval from './retrieval/index.vue'
 
 
-const tab = ref(1)
+const tab = ref(0)
 </script>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">

+ 134 - 1
src/views/recruit/enterprise/search/recommend/index.vue

@@ -1,9 +1,142 @@
 <template>
 <template>
-  <div>searchRecommend</div>
+  <div>
+    <div class="d-flex align-center mt-5" style="width: 600px; margin: auto;">
+      <Autocomplete v-model="query.jobId" :item="selectItems" @change="handleChange"></Autocomplete>
+    </div>
+    <CtTable
+      class="mt-3"
+      :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 mt-2">{{ item?.name }}</span>
+        </div>
+      </template>
+      <template #actions="{ item }">
+        <v-btn color="primary" variant="text" @click="handleCommunicate(item)">立即沟通</v-btn>
+      </template>
+    </CtTable>
+  </div>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
 defineOptions({ name: 'searchRecommend' })
 defineOptions({ name: 'searchRecommend' })
+import { ref, computed } from 'vue'
+import { getPersonRecommendPage, getJobAdvertised } from '@/api/enterprise'
+import { timesTampChange } from '@/utils/date'
+import { talkToUser, defaultTextEnt } from '@/hooks/web/useIM'
+import { useRouter } from 'vue-router'
+import { dealDictArrayData } from '@/utils/position'
+import { getUserAvatar } from '@/utils/avatar'
+
+const router = useRouter()
+const query = ref({
+  pageNo: 1,
+  pageSize: 10,
+  jobId: null
+})
+const selectItems = ref({
+  label: '推荐的职位',
+  placeholder: '请选择要进行推荐的职位',
+  clearable: true,
+  width: 600,
+  items: []
+})
+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: 'actions', sortable: false }
+])
+
+// 职位列表
+const getJobList = async () => {
+  const data = await getJobAdvertised({})
+  if (data.length) {
+    const list = dealDictArrayData([], data)
+    selectItems.value.items = list.map(e => {
+      return { label: `${e.name}${e.areaName ? '_' + e.areaName : ''} ${e.payFrom ? e.payFrom + '-' : ''}${e.payTo}${e.payName ? '/' + e.payName : ''}`, value: e.id }
+    })
+  }
+}
+getJobList()
+
+// 列表
+const getData = async () => {
+  loading.value = true
+  try {
+    const res = await getPersonRecommendPage(query.value)
+    if (!res.list.length) {
+      items.value = []
+      total.value = 0
+      return
+    }
+    items.value = dealDictArrayData([], res.list)
+    total.value = res.total
+  } finally {
+    loading.value = false
+  }
+}
+getData()
+
+// 推荐
+const handleChange = () => {
+  query.value.pageNo = 1
+  getData()
+}
+
+// 分页
+const handleChangePage = (e) =>{
+  query.value.pageNo = e
+  getData()
+}
+
+// 立即沟通
+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>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">

+ 6 - 3
src/views/recruit/enterprise/search/retrieval/components/area.vue

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

+ 141 - 19
src/views/recruit/enterprise/search/retrieval/index.vue

@@ -1,29 +1,76 @@
 <template>
 <template>
-  <div class="mt-3">
+  <div class="mt-4">
     <div class="d-flex justify-center">
     <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>
     </div>
-    <Industry :selectData="industry" @select="val => industry = val"></Industry>
-    <Area></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 style="margin: auto; text-align: center; width: 70%"> -->
     <div>
     <div>
+      <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>
+        <div>
+          <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="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 class="half-button" color="primary" @click="handleConfirm">搜 索</v-btn>
       </div>
       </div>
-      <div v-if="industry.length" class="text-end font-size-15 color-999 cursor-pointer tips" @click="handleClear">清除选择</div>
     </div>
     </div>
   </div>
   </div>
+
+  <div class="mt-10">
+    <v-divider></v-divider>
+    <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 mt-2">{{ item?.name }}</span>
+        </div>
+      </template>
+      <template #actions="{ item }">
+        <v-btn color="primary" variant="text" @click="handleCommunicate(item)">立即沟通</v-btn>
+      </template>
+    </CtTable>
+  </div>
 </template>
 </template>
 
 
 <script setup>
 <script setup>
 defineOptions({ name: 'searchRetrieval' })
 defineOptions({ name: 'searchRetrieval' })
-import { ref } from 'vue'
+import { ref, computed } from 'vue'
 import CommonPage from '../components/common.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({
 const textItem = ref({
   type: 'text',
   type: 'text',
   width: 600,
   width: 600,
@@ -32,23 +79,98 @@ const textItem = ref({
   clearable: true,
   clearable: true,
   appendInnerIcon: 'mdi-magnify'
   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)
+    total.value = res.total
+  } finally {
+    loading.value = false
+  }
+}
+
+// 分页
+const handleChangePage = (e) =>{
+  query.value.pageNo = e
+  getData()
+}
+
+const position = ref([])
 const handleSearch = (key, value) => {
 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) => {
 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 = () => {
 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>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">
-.tips:hover {
-  color: var(--v-primary-base)
-}
 </style>
 </style>

+ 16 - 3
src/views/recruit/enterprise/talentPool/components/details/dict.js

@@ -38,6 +38,16 @@ const dictList = [
     value: 'jobTypeData',
     value: 'jobTypeData',
     itemKey: 'value',
     itemKey: 'value',
     itemText: 'label'
     itemText: 'label'
+  },
+  { 
+    type: 'menduner_area_type', 
+    apiType: 'areaList', 
+    key: 'interestedAreaIdList', 
+    label: 'interestedArea', 
+    isArray: true, 
+    value: 'areaTypeData', 
+    itemKey: 'id', 
+    itemText: 'name' 
   }
   }
 ]
 ]
 
 
@@ -60,9 +70,12 @@ export const dealJobData = (list) => {
     res = list.map(e => {
     res = list.map(e => {
       let obj = {}
       let obj = {}
       if (item.isArray) {
       if (item.isArray) {
-        e[item.label] = e[item.key].map(val => {
-          return obj = dictObj[item.value].find(i => i[item.itemKey] === val)
-        })
+        if (e[item.key] && e[item.key].length) {
+          const result = e[item.key].map(val => {
+            return obj = dictObj[item.value].find(i => i[item.itemKey] === val)
+          })
+          e[item.label] = result && result.length ? result.filter(Boolean) : []
+        }
       } else {
       } else {
         obj = dictObj[item.value].find(k => Number(k[item.itemKey]) === Number(e[item.key]))
         obj = dictObj[item.value].find(k => Number(k[item.itemKey]) === Number(e[item.key]))
         if (!obj) return
         if (!obj) return

+ 1 - 1
src/views/recruit/personal/home/components/advertisement/index.vue

@@ -3,7 +3,7 @@
   <div class="contentBox py-10 px-3">
   <div class="contentBox py-10 px-3">
     <div class="d-flex align-center justify-center">
     <div class="d-flex align-center justify-center">
       <div class="home-title">
       <div class="home-title">
-        优质企业
+        优选集团
         <div class="home-title-line"></div>
         <div class="home-title-line"></div>
       </div>
       </div>
     </div>
     </div>

+ 0 - 61
src/views/recruit/personal/home/components/headCarousel.vue

@@ -1,61 +0,0 @@
-<template>
-  <div>
-    <v-carousel height="80" :show-arrows="false" hide-delimiters cycle>
-      <!-- <template v-slot:prev="{ props }">
-        <v-btn
-          tonal
-          plain
-          size="x-small"
-          icon="$prev"
-          variant="elevated"
-          @click="props.onClick"
-        ></v-btn>
-      </template>
-      <template v-slot:next="{ props }">
-        <v-btn
-          tonal
-          plain
-          size="x-small"
-          icon="$next"
-          variant="elevated"
-          @click="props.onClick"
-        ></v-btn>
-      </template> -->
-      <v-carousel-item src="@/assets/headerBg.png" cover style="position: relative;">
-        <div class="tips">专属职位推荐,助力职业发展</div>
-      </v-carousel-item>
-      <!-- <v-carousel-item
-        v-for="(item,i) in items"
-        :key="i"
-        :src="item.src"
-        cover
-      ></v-carousel-item> -->
-    </v-carousel>
-  </div>
-</template>
-
-<script setup>
-// import { ref } from 'vue'
-
-defineOptions({ name:'personal-headCarousel'})
-
-// const items = ref([
-//   // { src: 'https://cdn.vuetifyjs.com/images/carousel/squirrel.jpg', },
-//   // { src: 'https://cdn.vuetifyjs.com/images/carousel/sky.jpg', },
-//   // { src: 'https://cdn.vuetifyjs.com/images/carousel/bird.jpg', },
-//   { src: 'https://cdn.vuetifyjs.com/images/carousel/planet.jpg', },
-// ])
-</script>
-
-<style lang="scss" scoped>
-.tips {
-  color: #fff;
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  font-size: 22px;
-  font-weight: 100;
-  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
-}
-</style>

+ 2 - 2
src/views/recruit/personal/home/components/homeJobTypeCard/index.vue

@@ -126,8 +126,8 @@ const handleMouseLeave = () => { // 鼠标移出
 }
 }
 // 轮播图片
 // 轮播图片
 const carouselList = ref([
 const carouselList = ref([
-  { src: 'https://img.kinpan.com/Files/design/detailimages/20161228/6361853956839262507798973.jpg', },
-  { src: 'https://img0.baidu.com/it/u=3769341087,3426515789&fm=253&fmt=auto&app=138&f=JPEG?w=1180&h=472', },
+  { src: 'https://minio.citupro.com/dev/menduner/home/%E6%82%A6%E6%A6%95.jpg' },
+  { src: 'https://minio.citupro.com/dev/menduner/home/%E6%B4%B2%E9%99%85%E5%81%87%E6%97%A5.jpg' }
 ])
 ])
 </script>
 </script>
 
 

+ 8 - 2
src/views/recruit/personal/home/index.vue

@@ -1,6 +1,7 @@
 <template>
 <template>
   <div>
   <div>
-    <headCarousel></headCarousel>
+    <!-- 顶部广告图 -->
+    <div class="banner"></div>
     <div class="stickyBox py-5">
     <div class="stickyBox py-5">
       <headSearch @handleSearch="handleSearch"></headSearch>
       <headSearch @handleSearch="handleSearch"></headSearch>
     </div>
     </div>
@@ -23,7 +24,6 @@
 <script setup>
 <script setup>
 defineOptions({ name:'personal-index'})
 defineOptions({ name:'personal-index'})
 import simplePage from '@/views/recruit/personal/shareJob/sendResume/simple.vue'
 import simplePage from '@/views/recruit/personal/shareJob/sendResume/simple.vue'
-import headCarousel from './components/headCarousel.vue'
 import headSearch from '@/components/headSearch'
 import headSearch from '@/components/headSearch'
 import hotJobs from './components/hotJobs.vue'
 import hotJobs from './components/hotJobs.vue'
 import homeJobTypeCard from './components/homeJobTypeCard'
 import homeJobTypeCard from './components/homeJobTypeCard'
@@ -100,4 +100,10 @@ const handleOpenAdvertise = () => {
 .content-box {
 .content-box {
   margin-top: -360px;
   margin-top: -360px;
 }
 }
+.banner {
+  width: 100%;
+  height: 110px;
+  background: url("@/assets/headerBg.jpg") no-repeat;
+  background-size: contain;
+}
 </style>
 </style>

+ 58 - 6
src/views/recruit/personal/position/components/conditionFilter.vue

@@ -1,23 +1,26 @@
 <template>
 <template>
   <div>
   <div>
-    <div class="d-flex">
+    <div class="d-flex" style="flex-wrap: wrap;">
       <template v-for="item in list" :key="item.key">
       <template v-for="item in list" :key="item.key">
         <component
         <component
+          v-if="!item.hide"
           :is="item.path"
           :is="item.path"
           :idName="item.key"
           :idName="item.key"
           :title="item.title"
           :title="item.title"
           :isSingle="item.isSingle"
           :isSingle="item.isSingle"
           :isSlot="item.isSlot"
           :isSlot="item.isSlot"
+          :itemKey="item.itemKey"
+          :itemText="item.itemText"
           :displayDictName="item.displayDictName"
           :displayDictName="item.displayDictName"
           :provideData="item.provideData || []"
           :provideData="item.provideData || []"
-          :info="item"
+          btnClass="mt-1"
           @inputChange="inputChange"
           @inputChange="inputChange"
         ></component>
         ></component>
       </template>
       </template>
     </div>
     </div>
     <div v-if="showSelectList?.length">
     <div v-if="showSelectList?.length">
       <div style="margin-top: 20px; border-top: 1px solid #eee;">
       <div style="margin-top: 20px; border-top: 1px solid #eee;">
-        <div v-for="item in showSelectList" :key="item.key" style="margin: 4px 8px 4px 0px;">
+        <div v-for="item in showSelectList" :key="item.key" style="margin: 4px 8px 4px 0px;" :style="`display: ${item.key.includes('cityId_') ? 'inline-block' : 'block'};`">
           <template v-if="item.checkedItems?.length">
           <template v-if="item.checkedItems?.length">
             <span style="color: #999;">{{ item.title }}:</span>
             <span style="color: #999;">{{ item.title }}:</span>
             <v-btn
             <v-btn
@@ -41,7 +44,7 @@
 </template>
 </template>
 <script setup>
 <script setup>
 import { useRoute } from 'vue-router'; const route = useRoute()
 import { useRoute } from 'vue-router'; const route = useRoute()
-import { watch, ref, shallowRef } from 'vue'
+import { watch, ref, shallowRef, nextTick } from 'vue'
 import { filterList, getItemObj } from './dict'
 import { filterList, getItemObj } from './dict'
 defineOptions({name: 'retrieval-components-conditionFilter'})
 defineOptions({name: 'retrieval-components-conditionFilter'})
 const emits = defineEmits(['change', 'reset'])
 const emits = defineEmits(['change', 'reset'])
@@ -56,9 +59,54 @@ const list = shallowRef(props.showFilterList === 'all' ? filterList : props.show
   return item ? { ...item, ...e } : ''
   return item ? { ...item, ...e } : ''
 }).filter(Boolean) : [])
 }).filter(Boolean) : [])
 
 
-const inputChange = ({ idName: key, values }) => {
+// 城市处理
+const cityDelete = (cityLevel) => {
+  list.value.forEach(e => {
+    if (e.key.includes('cityId_') && e.cityLevel > cityLevel) {
+      emits('change', e.key, '')
+      e.del = true
+    }
+  })
+  list.value = list.value.filter(e => !e.del)
+}
+// 城市处理
+const cityDeal = (str, key, clickItem) => {
+  if (str === '10000') { // 全国
+    cityDelete(1)
+    return
+  } 
+  const i = list.value.findIndex(e => e.key === key)
+  if (i !== -1) {
+    cityDelete(list.value[i].cityLevel) // 去掉当前选中层级后面的市区
+    if (str && clickItem?.children?.length) { // 选中-添加下级
+      let noProvince = false
+      if (clickItem.children[0][list.value[i].itemText] === clickItem[list.value[i].itemText] && clickItem.children[0].children?.length) { // 直辖市
+        clickItem = clickItem.children[0]
+        noProvince = true
+      }
+      const obj = {
+        ...list.value[i], // 复制其他属性
+        toFilterDictName: null, toFilterApiType: null, displayDictName: null, displayApiType: null,
+        isSingle: Boolean(clickItem.children[0]?.children?.length),
+        provideData: clickItem.children, // 赋值下拉数据
+        toFilterDictDataList: clickItem.children // 回显使用
+      }
+      obj.cityLevel++ // 层级
+      if (noProvince) obj.cityLevel++ // 直辖市
+      obj.key = 'cityId_' + obj.cityLevel
+      obj.title = obj.cityLevel === 2 ? '市' : '区'
+      nextTick(() => {
+        list.value.splice(i+1, 0, obj)
+      })
+    }
+  }
+}
+
+const inputChange = ({ idName: key, values, clickItem }) => {
   const str = values.length ? values.join('_') : ''
   const str = values.length ? values.join('_') : ''
   if (!key) return
   if (!key) return
+  if (key.includes('cityId_')) cityDeal(str, key, clickItem) // 城市处理
+  //
   emits('change', key, str)
   emits('change', key, str)
 }
 }
 
 
@@ -74,7 +122,7 @@ const showSelectList = ref([])
 // 添加
 // 添加
 const assembleList = ({ key, idsStr }) => {
 const assembleList = ({ key, idsStr }) => {
   const ids = idsStr.split('_') || []
   const ids = idsStr.split('_') || []
-  const obj = getItemObj({ key, ids })
+  const obj = getItemObj({ key, ids, dictArr: list.value })
   if (!obj) return
   if (!obj) return
   const index = showSelectList.value.findIndex(i => i.key === key)
   const index = showSelectList.value.findIndex(i => i.key === key)
   if (index === -1) showSelectList.value.push(obj)
   if (index === -1) showSelectList.value.push(obj)
@@ -102,6 +150,10 @@ watch(
       // showSelectList去掉newVal里面没有的key
       // showSelectList去掉newVal里面没有的key
       showSelectList.value = showSelectList.value.filter(item => Object.keys(newVal).includes(item.key))
       showSelectList.value = showSelectList.value.filter(item => Object.keys(newVal).includes(item.key))
     }
     }
+    showSelectList.value = [ // 城市放在一起展示
+      ...showSelectList.value.filter(item => item.key.includes('cityId_')),
+      ...showSelectList.value.filter(item => !item.key.includes('cityId_')),
+    ]
   },
   },
   { immediate: true },
   { immediate: true },
   { deep: true }
   { deep: true }

+ 37 - 23
src/views/recruit/personal/position/components/conditionFilter/commonPath.vue

@@ -1,20 +1,22 @@
 <template>
 <template>
-  <commonStyle :btnTitle="btnTitle" :close-on-content-click="props.isSingle" v-if="show">
+  <commonStyle :btnTitle="btnTitle" v-bind="$attrs" :close-on-content-click="props.isSingle" v-if="show">
+    <!-- 工作城市 -->
+    <!-- <workCity v-if="idName === 'city'" :select="selectIdArr" @handleClickIndustry="handle"></workCity> -->
     <!-- 行业类型 -->
     <!-- 行业类型 -->
-    <industryTypeCard v-if="idName === 'industryIds'" :select="selectedItems" @handleClickIndustry="handle"></industryTypeCard>
+    <industryTypeCard v-if="idName === 'industryIds'" :select="selectIdArr" @handleClickIndustry="handle"></industryTypeCard>
     <!-- 职位类型 -->
     <!-- 职位类型 -->
-    <jobTypeCard v-else-if="idName === 'positionId'" :select="selectedItems" isSingle echo clearable @handleJobClick="handle"></jobTypeCard>
+    <jobTypeCard v-else-if="idName === 'positionId'" :select="selectIdArr" isSingle echo clearable @handleJobClick="handle"></jobTypeCard>
     <v-list v-else>
     <v-list v-else>
       <v-list-item
       <v-list-item
-        v-for="item in items" :key="item.id" :value="item.value"
-        :active="selectedItems.includes(item.value)"
+        v-for="item in items" :key="item.id" :value="item[itemKey]"
+        :active="selectIdArr.includes(item[itemKey])"
         color="primary"
         color="primary"
-        @click="handle(item.value)"
+        @click="handle(item, item[itemKey])"
       >
       >
-        <template v-if="selectedItems.includes(item.value)" v-slot:append>
+        <template v-if="selectIdArr.includes(item[itemKey])" v-slot:append>
           <v-icon icon="mdi-check"></v-icon>
           <v-icon icon="mdi-check"></v-icon>
         </template>
         </template>
-        <v-list-item-title>{{ item.label }}</v-list-item-title>
+        <v-list-item-title>{{ item[itemText] }}</v-list-item-title>
       </v-list-item>
       </v-list-item>
     </v-list>
     </v-list>
   </commonStyle>
   </commonStyle>
@@ -24,6 +26,7 @@ import commonStyle from './commonStyle.vue'
 import industryTypeCard from '@/components/industryTypeCard'
 import industryTypeCard from '@/components/industryTypeCard'
 import jobTypeCard from '@/components/jobTypeCard'
 import jobTypeCard from '@/components/jobTypeCard'
 import { getDict } from '@/hooks/web/useDictionaries'
 import { getDict } from '@/hooks/web/useDictionaries'
+import { useRoute } from 'vue-router'; const route = useRoute()
 import { ref, computed, watch } from 'vue';
 import { ref, computed, watch } from 'vue';
 
 
 defineOptions({name: 'conditionFilter-JobType'})
 defineOptions({name: 'conditionFilter-JobType'})
@@ -45,6 +48,14 @@ const props = defineProps({
     type: String,
     type: String,
     default: ''
     default: ''
   },
   },
+  itemKey: {
+    type: String,
+    default: 'value'
+  },
+  itemText: {
+    type: String,
+    default: 'label'
+  },
   displayDictName: {
   displayDictName: {
     type: [String, Number],
     type: [String, Number],
     default: '' // 1: 插槽使用会返回数组
     default: '' // 1: 插槽使用会返回数组
@@ -60,33 +71,36 @@ const props = defineProps({
 })
 })
 
 
 const btnTitle = computed(() => {
 const btnTitle = computed(() => {
-  return selectedItems.value?.length ? `${props.title}(${selectedItems.value.length})` : props.title
+  return selectIdArr.value?.length ? `${props.title}(${selectIdArr.value.length})` : props.title
 })
 })
 
 
 let show = ref(false)
 let show = ref(false)
 let items = ref()
 let items = ref()
-const selectedItems = ref([])
+const selectIdArr = ref([])
 
 
-const handle = (value) => {
+const handle = (item) => {
+  const value = item[props.itemKey]
   if (props.isSlot) {
   if (props.isSlot) {
-    selectedItems.value = value
+    selectIdArr.value = value
   } else {
   } else {
-    if (selectedItems.value.includes(value)) {
-      selectedItems.value = selectedItems.value.filter(i => i !== value)
+    if (selectIdArr.value.includes(value)) {
+      selectIdArr.value = selectIdArr.value.filter(i => i !== value)
     } else {
     } else {
-      if (props.idName === 'expType') selectedItems.value = value === '2' ? [value] : (selectedItems.value.push(value) && selectedItems.value.filter(i => i !== '2')) // 选中经验不限时清空其它选中项,选中其他的咬去掉经验不限
-      else if (props.isSingle) selectedItems.value = [value] // 单选
-      else selectedItems.value.push(value)
+      if (props.idName === 'expType') selectIdArr.value = value === '2' ? [value] : (selectIdArr.value.push(value) && selectIdArr.value.filter(i => i !== '2')) // 选中经验不限时清空其它选中项,选中其他的咬去掉经验不限
+      else if (props.isSingle) selectIdArr.value = [value] // 单选
+      else selectIdArr.value.push(value)
     }
     }
   }
   }
   emits('inputChange', {
   emits('inputChange', {
     idName: props.idName,
     idName: props.idName,
+    clickItem: item,
     // title: props.title,
     // title: props.title,
-    values: selectedItems.value,
+    values: selectIdArr.value,
     isEmit: props.positionIndexPage
     isEmit: props.positionIndexPage
   })
   })
 }
 }
 
 
+
 // 字典
 // 字典
 if (props.isSlot) show.value = true // 插槽使用
 if (props.isSlot) show.value = true // 插槽使用
 else if (props.provideData?.length) { // 自定义下拉数据
 else if (props.provideData?.length) { // 自定义下拉数据
@@ -94,23 +108,23 @@ else if (props.provideData?.length) { // 自定义下拉数据
   show.value = true
   show.value = true
 }
 }
 else if (props.displayDictName) {
 else if (props.displayDictName) {
-  getDict(props.displayDictName).then(({ data }) => {
+  getDict(props.displayDictName, props.displayParams, props.displayApiType).then(({ data }) => {
     data = data?.length && data || []
     data = data?.length && data || []
     items.value = data
     items.value = data
     show.value = true
     show.value = true
   })
   })
 } else console.log('error->字典参数未传递!!')
 } else console.log('error->字典参数未传递!!')
 
 
-import { useRoute } from 'vue-router'; const route = useRoute()
+
 watch(
 watch(
   () => route.query, 
   () => route.query, 
   (newVal, oldVal) => {
   (newVal, oldVal) => {
-    if (!newVal) selectedItems.value = []
+    if (!newVal) selectIdArr.value = []
     const str = newVal[props.idName]?.split(',')[0]
     const str = newVal[props.idName]?.split(',')[0]
     const arr = str ? str.split('_') : []
     const arr = str ? str.split('_') : []
-    selectedItems.value = arr?.length? arr : []
+    selectIdArr.value = arr?.length? arr : []
     if (!oldVal) { // 仅刷新时触发
     if (!oldVal) { // 仅刷新时触发
-      if (props.isRefreshEmit) emits('inputChange', { values: selectedItems.value, isEmit: true })
+      if (props.isRefreshEmit) emits('inputChange', { values: selectIdArr.value, isEmit: true })
     }
     }
   },
   },
   { immediate: true },
   { immediate: true },

+ 5 - 0
src/views/recruit/personal/position/components/conditionFilter/commonStyle.vue

@@ -11,6 +11,7 @@
     <template v-slot:activator="{ isActive, props }">
     <template v-slot:activator="{ isActive, props }">
       <v-btn
       <v-btn
         class="mr-3 py-0 px-2"
         class="mr-3 py-0 px-2"
+        :class="defineProps.btnClass"
         density="comfortable"
         density="comfortable"
         :append-icon="isActive ? 'mdi mdi-menu-up' : 'mdi mdi-menu-down'"
         :append-icon="isActive ? 'mdi mdi-menu-up' : 'mdi mdi-menu-down'"
         color="primary" variant="tonal"
         color="primary" variant="tonal"
@@ -33,6 +34,10 @@ const defineProps = defineProps({
   closeOnContentClick: {
   closeOnContentClick: {
     type: Boolean,
     type: Boolean,
     default: true
     default: true
+  },
+  btnClass: {
+    type: String,
+    default: ''
   }
   }
 })
 })
 </script>
 </script>

+ 42 - 34
src/views/recruit/personal/position/components/dict.js

@@ -5,40 +5,46 @@ import commonPath from './conditionFilter/commonPath.vue'
 // toFilterDictName: 查数据回显(一维数组字典),dictShow: 用户操作的字典(用户看到的数据)
 // toFilterDictName: 查数据回显(一维数组字典),dictShow: 用户操作的字典(用户看到的数据)
 // 当type是tree类型的数据的时候需要提供dictType
 // 当type是tree类型的数据的时候需要提供dictType
 const dictList = [
 const dictList = [
+  // {
+  //   toFilterDictName: 'menduner_area_type',
+  //   toFilterApiType: 'areaList',
+  //   displayDictName: 'areaTreeData',
+  //   displayApiType: 'areaTreeData',
+  //   displayParams: {},
+  //   key: 'cityId_1',
+  //   cityLevel: 1,
+  //   itemKey: 'id',
+  //   itemText: 'name',
+  //   title: '工作城市',
+  //   isSingle: true,
+  //   path: commonPath,
+  //   toFilterDictDataList: []
+  // },
   {
   {
-    displayDictName: 'menduner_area_type',
-    apiType: 'areaList',
-    key: 'areaIds',
-    itemKey: 'id',
-    itemText: 'name',
-    title: '工作地点',
-    path: commonPath,
-    data: []
-  },
-  {
-    displayDictName: 'menduner_area_type',
-    apiType: 'areaList',
-    key: 'areaIds',
+    toFilterDictName: 'menduner_area_type',
+    toFilterApiType: 'areaList',
+    key: 'city',
+    isSlot: true,
     itemKey: 'id',
     itemKey: 'id',
-    itemText: 'name',
-    title: '工作地点',
+    itemText: 'nameCn',
+    title: '工作城市',
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
   {
   {
     toFilterDictName: 'menduner_industry_type',
     toFilterDictName: 'menduner_industry_type',
-    apiType: 'industryList',
+    toFilterApiType: 'industryList',
     key: 'industryIds',
     key: 'industryIds',
     isSlot: true,
     isSlot: true,
     itemKey: 'id',
     itemKey: 'id',
     itemText: 'nameCn',
     itemText: 'nameCn',
     title: '行业类型',
     title: '行业类型',
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
   {
   {
     toFilterDictName: 'positionData',
     toFilterDictName: 'positionData',
-    apiType: 'positionData',
+    toFilterApiType: 'positionData',
     key: 'positionId',
     key: 'positionId',
     isSlot: true,
     isSlot: true,
     itemKey: 'id',
     itemKey: 'id',
@@ -46,7 +52,7 @@ const dictList = [
     title: '职位类型',
     title: '职位类型',
     isSingle: true,
     isSingle: true,
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
   {
   {
     displayDictName: 'menduner_job_type',
     displayDictName: 'menduner_job_type',
@@ -55,7 +61,7 @@ const dictList = [
     itemText: 'label',
     itemText: 'label',
     title: '求职类型',
     title: '求职类型',
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
   {
   {
     displayDictName: 'menduner_exp_type',
     displayDictName: 'menduner_exp_type',
@@ -64,7 +70,7 @@ const dictList = [
     itemText: 'label',
     itemText: 'label',
     title: '工作经验',
     title: '工作经验',
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
   {
   {
     displayDictName: 'menduner_pay_scope',
     displayDictName: 'menduner_pay_scope',
@@ -73,9 +79,8 @@ const dictList = [
     itemText: 'label',
     itemText: 'label',
     title: '薪资待遇',
     title: '薪资待遇',
     isSingle: true,
     isSingle: true,
-    isString: true,
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
   {
   {
     displayDictName: 'menduner_education_type',
     displayDictName: 'menduner_education_type',
@@ -84,7 +89,7 @@ const dictList = [
     itemText: 'label',
     itemText: 'label',
     title: '学历要求',
     title: '学历要求',
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
   {
   {
     displayDictName: 'menduner_scale',
     displayDictName: 'menduner_scale',
@@ -93,7 +98,7 @@ const dictList = [
     itemText: 'label',
     itemText: 'label',
     title: '公司规模',
     title: '公司规模',
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
   {
   {
     displayDictName: 'menduner_financing_status',
     displayDictName: 'menduner_financing_status',
@@ -102,7 +107,7 @@ const dictList = [
     itemText: 'label',
     itemText: 'label',
     title: '融资阶段',
     title: '融资阶段',
     path: commonPath,
     path: commonPath,
-    data: []
+    toFilterDictDataList: []
   },
   },
 ]
 ]
 export const filterList = dictList
 export const filterList = dictList
@@ -111,8 +116,9 @@ export const filterList = dictList
 const getDictList = async () => {
 const getDictList = async () => {
   dictList.forEach(async (dictListItem) => {
   dictList.forEach(async (dictListItem) => {
     const toFilterDictName = dictListItem.toFilterDictName || dictListItem.displayDictName
     const toFilterDictName = dictListItem.toFilterDictName || dictListItem.displayDictName
-    const { data } = await getDict(toFilterDictName, dictListItem.params, dictListItem.apiType)
-    dictListItem.data = data
+    if (!toFilterDictName) return
+    const { data } = await getDict(toFilterDictName, dictListItem.params, dictListItem.toFilterApiType)
+    dictListItem.toFilterDictDataList = data
   })
   })
 }
 }
 
 
@@ -121,13 +127,15 @@ const getData = async () => {
 }
 }
 getData()
 getData()
 
 
-export const getItemObj = ({ key, ids = [] }) => {
-  const item = dictList.find(dictListItem => dictListItem.key === key)
+export const getItemObj = ({ key, ids = [], dictArr = [] }) => {
+  if (!dictArr?.length) dictArr = dictList
+  //
+  const item = dictArr.find(dictListItem => dictListItem.key === key)
   const checkedItems = ids.map(id => {
   const checkedItems = ids.map(id => {
-    if (!item?.data?.length) return ''
-    const obj = item.data.find(e => e[item.itemKey] === id)
+    if (!item?.toFilterDictDataList?.length) return ''
+    const obj = item.toFilterDictDataList.find(e => e[item.itemKey] === id)
     return obj ? { text: obj[item.itemText], value: obj[item.itemKey] } : ''
     return obj ? { text: obj[item.itemText], value: obj[item.itemKey] } : ''
   }).filter(Boolean)
   }).filter(Boolean)
 
 
-  return checkedItems?.length ? { key, title: item.title, checkedItems, ref: item.ref } : ''
+  return checkedItems?.length ? { key, title: item.title, checkedItems } : ''
 }
 }

+ 1 - 1
src/views/recruit/personal/position/index.vue

@@ -49,7 +49,7 @@ const route = useRoute(); const router = useRouter()
 const cityFilterRef = ref()
 const cityFilterRef = ref()
 const conditionFilterRef = ref()
 const conditionFilterRef = ref()
 const showFilterList = [
 const showFilterList = [
-  // { key: 'cityId' },
+  // { key: 'cityId_1' },
   { key: 'industryIds' },
   { key: 'industryIds' },
   { key: 'positionId', isSingle: true },
   { key: 'positionId', isSingle: true },
   { key: 'jobType' },
   { key: 'jobType' },

+ 1 - 1
src/views/recruit/personal/recommend/index.vue

@@ -37,7 +37,7 @@ import recommendDetails from '@/views/recruit/personal/position/components/detai
 const jobId = ref('')
 const jobId = ref('')
 const showRecommendDetails = ref(false)
 const showRecommendDetails = ref(false)
 const selectChange = (item) => {
 const selectChange = (item) => {
-  jobId.value = item.job.id
+  jobId.value = item.id
   showRecommendDetails.value = false
   showRecommendDetails.value = false
   nextTick(() => showRecommendDetails.value = true)
   nextTick(() => showRecommendDetails.value = true)
 }
 }

Some files were not shown because too many files changed in this diff