Sfoglia il codice sorgente

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

zhengnaiwen_citu 7 mesi fa
parent
commit
bda31a1848
63 ha cambiato i file con 801 aggiunte e 328 eliminazioni
  1. 1 1
      .env.development
  2. 1 1
      .env.localDev
  3. 7 3
      src/components/AreaSelect/index.vue
  4. 1 1
      src/components/CtTable/index.vue
  5. 16 1
      src/components/Enterprise/components/positions.vue
  6. 13 0
      src/components/Enterprise/details.vue
  7. 1 1
      src/components/Enterprise/hotPromoted.vue
  8. 14 0
      src/components/Position/longStrip.vue
  9. 1 1
      src/components/Upload/img.vue
  10. 2 2
      src/components/personalRecharge/index.vue
  11. 8 0
      src/config/axios/service.js
  12. 2 2
      src/layout/company/slider.vue
  13. 1 1
      src/layout/personal/footer.vue
  14. 12 8
      src/layout/personal/navBar.vue
  15. 3 3
      src/layout/personal/slider.vue
  16. 8 8
      src/views/about/index.vue
  17. 2 2
      src/views/entrances/components/slider.vue
  18. 1 1
      src/views/entrances/list/index.vue
  19. 14 12
      src/views/headhunting/components/content.vue
  20. 4 4
      src/views/headhunting/components/serviceContent.vue
  21. 38 38
      src/views/login/components/privacyPolicy.vue
  22. 44 44
      src/views/login/components/userAgreement.vue
  23. 6 0
      src/views/login/index.vue
  24. 1 0
      src/views/mall/components/table.vue
  25. 1 0
      src/views/mall/purchasePackage/index.vue
  26. 1 0
      src/views/publicRecruitment/components/integralTable.vue
  27. 1 0
      src/views/publicRecruitment/components/table.vue
  28. 4 4
      src/views/recruit/entRegister/inReview.vue
  29. 11 10
      src/views/recruit/entRegister/register.vue
  30. 4 2
      src/views/recruit/enterprise/hirePosition/components/item.vue
  31. 10 8
      src/views/recruit/enterprise/hirePosition/components/jobRequirements.vue
  32. 3 1
      src/views/recruit/enterprise/interviewManagement/components/invite.vue
  33. 1 1
      src/views/recruit/enterprise/membershipPackage/components/package.vue
  34. 3 1
      src/views/recruit/enterprise/personnelManagement/components/invite.vue
  35. 1 0
      src/views/recruit/enterprise/personnelManagement/components/table.vue
  36. 4 1
      src/views/recruit/enterprise/positionManagement/components/item.vue
  37. 13 11
      src/views/recruit/enterprise/positionManagement/components/jobRequirements.vue
  38. 3 1
      src/views/recruit/enterprise/resume/components/invite.vue
  39. 10 10
      src/views/recruit/enterprise/resume/components/table.vue
  40. 15 15
      src/views/recruit/enterprise/search/recommend/index.vue
  41. 12 12
      src/views/recruit/enterprise/search/retrieval/index.vue
  42. 1 0
      src/views/recruit/enterprise/systemManagement/groupAccount/components/record.vue
  43. 1 1
      src/views/recruit/enterprise/systemManagement/groupAccount/inviteConfirm.vue
  44. 1 1
      src/views/recruit/enterprise/systemManagement/groupAccount/inviteConfirmEnt.vue
  45. 1 1
      src/views/recruit/enterprise/systemManagement/postManagement/index.vue
  46. 2 2
      src/views/recruit/enterprise/systemManagement/postManagement/save.vue
  47. 1 0
      src/views/recruit/enterprise/systemManagement/userManagement/index.vue
  48. 152 51
      src/views/recruit/enterprise/talentMap/index.vue
  49. 35 17
      src/views/recruit/enterprise/talentPool/components/details.vue
  50. 2 5
      src/views/recruit/enterprise/talentPool/index.vue
  51. 206 0
      src/views/recruit/enterprise/talentRecommendation/components/filter.vue
  52. 48 16
      src/views/recruit/enterprise/talentRecommendation/index.vue
  53. 2 2
      src/views/recruit/enterprise/tradingOrder/components/pointsAndBalance.vue
  54. 4 2
      src/views/recruit/personal/home/components/advertisement/index.vue
  55. 1 0
      src/views/recruit/personal/home/components/homeJobTypeCard/index.vue
  56. 4 4
      src/views/recruit/personal/home/components/hotJobs.vue
  57. 2 1
      src/views/recruit/personal/home/components/popularEnterprises.vue
  58. 12 6
      src/views/recruit/personal/home/index.vue
  59. 13 5
      src/views/recruit/personal/position/components/details.vue
  60. 9 0
      src/views/recruit/personal/position/components/dict.js
  61. 1 1
      src/views/recruit/personal/recommend/components/positionList.vue
  62. 2 0
      src/views/recruit/personal/shareJob/form/simpleInfo.vue
  63. 3 2
      src/views/register/company.vue

+ 1 - 1
.env.development

@@ -1,6 +1,6 @@
 NODE_ENV = 'development'
 
-VITE_APP_TITLE = 门墩儿
+VITE_APP_TITLE = 门墩儿
 
 # 访问路径
 # VITE_ACCESS_BASE_URL = 'http://localhost:3000'

+ 1 - 1
.env.localDev

@@ -1,6 +1,6 @@
 NODE_ENV = 'localDev'
 
-VITE_APP_TITLE = 门墩儿
+VITE_APP_TITLE = 门墩儿
 
 # 访问路径
 # VITE_ACCESS_BASE_URL = 'http://menduner.citupro.com:7878'

+ 7 - 3
src/components/AreaSelect/index.vue

@@ -13,7 +13,7 @@
           @click:close="handleClick(k)"
         >{{ k.name }}</v-chip>
       </div>
-      <div class="rightCard">
+      <div class="rightCard" :style="{'width': isMobile ? '100%' : '786px', 'height': isMobile ? '300px' : '384px'}">
         <div v-for="item in items" :key="item.id">
           <div class="rowItem d-flex">
             <div class="categoryName2">{{ item.name }}</div>
@@ -55,6 +55,10 @@ const props = defineProps({
   currentData: {
     type: Array,
     default: () => []
+  },
+  isMobile: {
+    type: Boolean,
+    default: false
   }
 })
 
@@ -102,8 +106,8 @@ const handleClick = (val) => {
 .card { border-radius: 12px; }
 .rightCard {
   position: relative;
-  height: 384px;
-  width: 786px;
+  // height: 384px;
+  // width: 786px;
   margin: 4px 0;
   padding: 0 16px;
   overflow-y: auto;

+ 1 - 1
src/components/CtTable/index.vue

@@ -116,7 +116,7 @@ defineProps({
   },
   noDataText: {
     type: String,
-    default: 'No data available'
+    default: '暂无数据'
   },
   showSelect: {
     type: Boolean,

+ 16 - 1
src/components/Enterprise/components/positions.vue

@@ -71,6 +71,9 @@
       ></MPagination>
     </div>
     <Empty v-else :elevation="false"></Empty>
+
+    <!-- 快速登录 -->
+    <login-page v-if="showLogin" @loginSuccess="loginSuccess" @close="loginClose"></login-page>
   </div>
 </template>
 
@@ -86,6 +89,7 @@ import { getUserAvatar } from '@/utils/avatar'
 import { getJobAdvertisedPositionCount, getJobAreaByEnterpriseId, getJobAdvertisedSearch } from '@/api/position'
 import MPagination from '@/components/CtPagination'
 import conditionFilter from '@/views/recruit/personal/position/components/conditionFilter'
+import loginPage from '@/views/common/loginDialog.vue'
 
 const props = defineProps({
   info: {
@@ -94,6 +98,16 @@ const props = defineProps({
   }
 })
 
+import { getToken } from '@/utils/auth'
+import Snackbar from '@/plugins/snackbar'
+const showLogin = ref(false)
+// 打开快速登录
+const quickLogonOpen = () => {
+  Snackbar.warning('您还未登录,请先登录后再试')
+  showLogin.value = true
+}
+
+
 const total = ref(0)
 const pageInfo = ref({
   pageSize: 10,
@@ -126,7 +140,7 @@ const showFilterList = ref([
   { key: 'payScope', isSingle: true },
 ])
 const getProvideData = (list) => {
-  if (!list?.length) return
+  if (!list?.length) return show.value = true
   getDict('menduner_area_type', {}, 'areaList').then(({ data }) => {
     data = data?.length && data || []
     const arr = list.map(e => {
@@ -242,6 +256,7 @@ const desc = [
 
 // 立即沟通
 const toDetails = async (info) => {
+  if (!getToken()) return quickLogonOpen()
   const userId = info.contact.userId
   const enterpriseId = info.contact.enterpriseId
   const textObj = {

+ 13 - 0
src/components/Enterprise/details.vue

@@ -69,6 +69,9 @@
         </div>
       </div>
     </div>
+
+    <!-- 快速登录 -->
+    <login-page v-if="showLogin" @loginSuccess="loginSuccess" @close="loginClose"></login-page>
   </div>
 </template>
 
@@ -83,6 +86,8 @@ import { timesTampChange } from '@/utils/date'
 import { dealDictObjData } from '@/utils/position'
 import { useRoute, useRouter } from 'vue-router'
 import { getToken } from '@/utils/auth'
+import Snackbar from '@/plugins/snackbar'
+import loginPage from '@/views/common/loginDialog.vue'
 
 const props = defineProps({
   id: {
@@ -91,6 +96,13 @@ const props = defineProps({
   }
 })
 
+const showLogin = ref(false)
+// 打开快速登录
+const quickLogonOpen = () => {
+  Snackbar.warning('您还未登录,请先登录后再试')
+  showLogin.value = true
+}
+
 const route = useRoute()
 const router = useRouter()
 const tab = ref(1)
@@ -149,6 +161,7 @@ const getCollectionStatus = async (id) => {
 
 // 关注&取消关注企业
 const handleFollow = async () => {
+  if (!getToken()) return quickLogonOpen()
   const api = isCollection.value ? getEnterpriseUnsubscribe : getEnterpriseSubscribe
   await api(isCollection.value ? props.id : { enterpriseId: props.id })
   getCollectionStatus(props.id)

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

@@ -115,7 +115,7 @@ const handleMoreEnterprise = (item) => {
 .company-info {
   float: left;
   margin-left: 16px;
-  width: 282px;
+  width: 262px;
 }
 .company-info-top {
   display: flex;

+ 14 - 0
src/components/Position/longStrip.vue

@@ -46,6 +46,9 @@
         </div>
       </div>
     </div>
+
+    <!-- 快速登录 -->
+    <login-page v-if="showLogin" @loginSuccess="loginSuccess" @close="loginClose"></login-page>
   </div>
 </template>
 
@@ -56,7 +59,9 @@ import { useI18n } from '@/hooks/web/useI18n'
 import Snackbar from '@/plugins/snackbar'
 import { getUserAvatar } from '@/utils/avatar'
 import { useRouter } from 'vue-router'
+import { ref } from 'vue'
 import { prologue, defaultText } from '@/hooks/web/useIM'
+import loginPage from '@/views/common/loginDialog.vue'
 
 const emits = defineEmits(['refresh'])
 const { t } = useI18n()
@@ -71,6 +76,14 @@ const props = defineProps({
   }
 })
 
+import { getToken } from '@/utils/auth'
+const showLogin = ref(false)
+// 打开快速登录
+const quickLogonOpen = () => {
+  Snackbar.warning('您还未登录,请先登录后再试')
+  showLogin.value = true
+}
+
 const router = useRouter()
 
 const desc = ['industryName', 'financingName', 'scaleName']
@@ -95,6 +108,7 @@ const handleToEnterprise = (item) => {
 
 // 立即沟通
 const toDetails = async (info) => {
+  if (!getToken()) return  quickLogonOpen()
   const userId = info.contact.userId
   const enterpriseId = info.contact.enterpriseId
   const textObj = {

+ 1 - 1
src/components/Upload/img.vue

@@ -41,7 +41,7 @@ const src = ref('')
 
 watch(() => props.value, (newVal) => {
   src.value = newVal
-})
+}, { immediate: true }, { deep: true })
 
 // 选择文件
 const fileInput = ref()

+ 2 - 2
src/components/personalRecharge/index.vue

@@ -31,10 +31,10 @@
               <input
                 v-model="inputValue" 
                 type="text"
-                class="custom-input-num"
+                class="custom-input-num mr-1"
                 :placeholder="item.placeholder"
                 :style="{'color': current === (index + 1) ? '#ff4747' : '#000'}" 
-              >
+              >
             </span>
             <span v-else>¥{{ FenYuanTransform(item.payPrice) }}</span>
           </div>

+ 8 - 0
src/config/axios/service.js

@@ -10,6 +10,7 @@ import { enterpriseRefreshToken, userRefreshToken } from '@/api/common'
 import { getToken, getRefreshToken, setToken, setRefreshToken, getIsEnterprise } from '@/utils/auth'
 import { rewardEventTrackClick } from '@/api/integral'
 import errorCode from './errorCode'
+// import router from '@/router'
 
 import { useI18n } from '@/hooks/web/useI18n'
 
@@ -246,7 +247,14 @@ const handleAuthorized = () => {
   const { t } = useI18n()
   const user = useUserStore()
   user.handleClearStorage() // 清除缓存
+
+  // const path = router.currentRoute.value.fullPath
+  // const hasRecommendedPath = path.includes('/recruit/enterprise/talentRecommendation')
+  // console.log(hasRecommendedPath, router.currentRoute.value, '登录过期')
+
   if (!isReLogin.show) {
+    // 人才推荐页面不需要弹窗提示
+    // if (hasRecommendedPath) return
     // 如果已经到重新登录页面则不进行弹窗提示
     if (window.location.href.includes('login?redirect=')) {
       return

+ 2 - 2
src/layout/company/slider.vue

@@ -5,7 +5,7 @@
         <v-icon class="icons" size="30">{{ item.mdi }}</v-icon>
         <v-tooltip :text="item.tips" location="start" activator="parent">
           <div v-if="item.showImg" class="ma-3" style="text-align: center">
-            <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/static/mendunerCode.jpg" :width="170" style="height: 170px;"></v-img>
+            <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/menduner/official-account-code4.jpg" :width="170" style="height: 170px;"></v-img>
             <span class="tips-text">关注门墩儿微信公众号</span>
           </div>
           <span v-else>{{ item.tips }}</span>
@@ -22,7 +22,7 @@ import { useRouter } from 'vue-router'
 const router = useRouter()
 const list = [
   { mdi: 'mdi-arrow-up-bold', tips: '返回顶部' },
-  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/static/mendunerCode.jpg' },
+  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/menduner/official-account-code4.jpg' },
   { mdi: 'mdi-bell-outline', tips: '消息', path: '/recruit/enterprise/chatTools' }
 ]
 

+ 1 - 1
src/layout/personal/footer.vue

@@ -19,7 +19,7 @@
       </div>
       <div class="right size d-flex">
         <div>
-          <v-img :width="100" cover aspect-ratio="16/9" src="https://minio.citupro.com/dev/static/mendunerCode.jpg" style="height: 100px;"></v-img>
+          <v-img :width="100" cover aspect-ratio="16/9" src="https://minio.citupro.com/dev/menduner/official-account-code4.jpg" style="height: 100px;"></v-img>
           <div class="mt-2" style="text-align: center;">微信公众号</div>
         </div>
         <div class="ml-5">

+ 12 - 8
src/layout/personal/navBar.vue

@@ -31,7 +31,7 @@
         </div>
         
         <div class="d-flex user-nav">
-          <div class="btns d-flex align-center" v-if="!getToken()">
+          <div class="btns d-flex align-center" v-if="!getToken() && showLoginBtn">
             <v-btn class="half-button" border color="primary" size="small" @click="handleLogin">{{ $t('login.loginOrRegister') }}</v-btn>
           </div>
           
@@ -132,6 +132,10 @@ import defineListPage from '@/views/entrances/navBar/components/defineListPage'
 defineOptions({ name: 'personal-navbar' })
 
 defineProps({
+  showLoginBtn: {
+    type: Boolean,
+    default: true
+  },
   sticky: {
     type: Boolean,
     default: true
@@ -164,21 +168,21 @@ const paths = [ // 有选中样式-路由列表
 
 const navList = [
   // {
-  //   title: '聘',
+  //   title: '聘',
   //   children: [
   //     {
-  //       title: '门墩儿聘',
+  //       title: '门墩儿聘',
   //       appList: [
   //         [{ title: '职位', path: paths[1] }, { title: '公司', path: paths[2] }]
   //       ]
   //     }
   //   ]
   // },
-  { title: '聘', path: '/recruit/personal/recommend', noLeaving: true },
-  { title: '商城', path: '/mall' },
-  { title: '猎头', path: '/headhunting' },
-  { title: '火苗儿' },
-  { title: '联合会' },
+  { title: '门墩儿招聘', path: '/recruit/personal/recommend', noLeaving: true },
+  { title: '门墩儿猎头', path: '/headhunting' },
+  { title: '门墩儿商城', path: '/mall' },
+  { title: '火苗儿校企' },
+  // { title: '产业联合会' },
   // { title: '数据' },
   { title: '了解门墩儿', path: '/about' }
 ]

+ 3 - 3
src/layout/personal/slider.vue

@@ -5,7 +5,7 @@
         <v-icon class="icons" size="30">{{ item.mdi }}</v-icon>
         <v-tooltip :text="item.tips" location="start" activator="parent">
           <div v-if="item.showImg" class="ma-3" style="text-align: center">
-            <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/static/mendunerCode.jpg" :width="170" style="height: 170px;"></v-img>
+            <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/menduner/official-account-code4.jpg" :width="170" style="height: 170px;"></v-img>
             <span class="tips-text">关注门墩儿微信公众号</span>
           </div>
           <span v-else>{{ item.tips }}</span>
@@ -23,11 +23,11 @@ import { getToken } from '@/utils/auth'
 const router = useRouter()
 const defaultList = [
   { mdi: 'mdi-arrow-up-bold', tips: '返回顶部' },
-  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/static/mendunerCode.jpg' }
+  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/menduner/official-account-code4.jpg' }
 ]
 const hasTokenList = [
   { mdi: 'mdi-arrow-up-bold', tips: '返回顶部' },
-  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/static/mendunerCode.jpg' },
+  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/menduner/official-account-code4.jpg' },
   { mdi: 'mdi-bell-outline', tips: '消息', path: '/recruit/personal/message' },
   { mdi: 'mdi-list-box-outline', tips: '在线简历', path: '/recruit/personal/personalCenter/resume/online' }
 ]

+ 8 - 8
src/views/about/index.vue

@@ -15,7 +15,7 @@
       </div>
       <div class="py-15">
         <v-divider></v-divider>
-        <h1 class="title mt-15">学术和行业之声</h1>
+        <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">
@@ -106,13 +106,13 @@ const introduce = [
     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!'
-  }
+  // {
+  //   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>
 

+ 2 - 2
src/views/entrances/components/slider.vue

@@ -5,7 +5,7 @@
         <v-icon class="icons" size="30">{{ item.mdi }}</v-icon>
         <v-tooltip :text="item.tips" location="start" activator="parent">
           <div v-if="item.showImg" class="ma-3" style="text-align: center">
-            <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/static/mendunerCode.jpg" :width="170" style="height: 170px;"></v-img>
+            <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/menduner/official-account-code4.jpg" :width="170" style="height: 170px;"></v-img>
             <span class="tips-text">关注门墩儿微信公众号</span>
           </div>
           <span v-else>{{ item.tips }}</span>
@@ -22,7 +22,7 @@ import { useRouter } from 'vue-router'
 const router = useRouter()
 const list = [
   // { mdi: 'mdi-arrow-up-bold', tips: '返回顶部' },
-  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/static/mendunerCode.jpg' },
+  { mdi: 'mdi-qrcode', tips: '微信公众号', showImg: 'https://minio.citupro.com/dev/menduner/official-account-code4.jpg' },
   { mdi: 'mdi-face-agent', tips: '客服' },
   { mdi: 'mdi-application-settings', tips: '预约演示', path: '/' }
 ]

+ 1 - 1
src/views/entrances/list/index.vue

@@ -42,7 +42,7 @@ const smallTitle = [
   '尽享海量VIP特权',
 ]
 const menuList = ref([
-  { icon: 'mdi-account-group-outline', title: '门墩儿聘', to: '/personal', bg: 'https://minio.citupro.com/dev/menduner/home/1.png' },
+  { icon: 'mdi-account-group-outline', title: '门墩儿聘', to: '/personal', bg: 'https://minio.citupro.com/dev/menduner/home/1.png' },
   { icon: 'mdi-shopping-outline', title: '甄选商城', to: '/mall', bg: 'https://minio.citupro.com/dev/menduner/home/2.png' },
   { icon: 'mdi-school-outline', title: '火苗儿校企', to: '', bg: 'https://minio.citupro.com/dev/menduner/home/3.png' },
   { icon: 'mdi-account-search', title: '门墩儿猎寻服务', to: '/headhunting', bg: 'https://minio.citupro.com/dev/menduner/home/4.png' },

+ 14 - 12
src/views/headhunting/components/content.vue

@@ -5,7 +5,7 @@
       <div class="carousel-desc common-width">
         <h1>门墩儿猎头</h1>
         <hr class="carousel-desc-line" />
-        <div class="carousel-desc-text">门墩儿猎头深知卓越的领导力是企业业绩增长的关键。我们专注于为企业提供精准的人才洞见,助力企业在人才招聘、培养和晋升方面做出明智选择,从而优化高管团队的整体表现,推动企业持续发展。</div>
+        <div class="carousel-desc-text">我们深知卓越的领导力是企业业绩增长的关键。我们专注于为企业提供精准的人才洞见,助力企业在人才招聘、培养和晋升方面做出明智选择,从而优化高管团队的整体表现,推动企业持续发展。</div>
       </div>
     </div>
     <!-- 数值示例 -->
@@ -89,21 +89,23 @@
         <div class="left">
           <h2>欢迎关注,了解门墩儿的新动态。</h2>
           <p class="mt-3" style="font-size: .9rem;">门墩儿在所有主流社交媒体都有账号。欢迎关注我们,以便了解关于发展趋势和领导力问题的最新见解。</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 class="d-flex align-center social-contact mt-5 justify-space-between">
+            <div>
+              <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>
+            <div class="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>
+                <v-img class="ml-2" cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/menduner/official-account-code4.jpg" width="120" height="120"></v-img>
               </div>
-              <span class="tips-text ml-6">关注门墩儿微信公众号</span>
+              <div class="tips-text ml-4">门墩儿公众号</div>
             </div>
           </div>
         </div>
         <div class="right text-end">
-          <img src="https://cn.spencerstuart.com/-/media/2019/november/homepagesocial_1039.jpg?h=770&amp;w=1093&amp;la=en&amp;hash=FA4B0309C1DDFD2FC1648005B9232838" height="324" width="460" alt="" />
+          <img src="https://minio.citupro.com/dev/menduner/headhunting/concact-bg.jpg" height="324" width="460" alt="" />
         </div>
       </div>
     </div>
@@ -182,10 +184,10 @@ const handleClick = (type, id) => {
     margin: 0 auto;
     text-align: center;
     h1 {
-      padding: 32px 0;
+      padding: 32px 0 10px 0;
     }
     &-line {
-      background-color: #fbcc11;
+      background-color: #30ffed;
       width: 42px;
       height: 5px;
       margin: 0 auto;

+ 4 - 4
src/views/headhunting/components/serviceContent.vue

@@ -141,9 +141,9 @@ const handleClick = (type, id) => {
 }
 .carousel-box {
   width: 100%;
-  height: 748px;
+  height: 500px;
   color: #fff;
-  background-image: url('https://www.spencerstuart.com/-/media/2024/04/ceo-acceleration-building-team/thmb-ceoacceleration-dec2023-1600x900.jpg');
+  background-image: url('https://minio.citupro.com/dev/menduner/headhunting/service-bg.jpg');
   background-size: cover;
   background-repeat: no-repeat;
   background-position: center center;
@@ -152,11 +152,11 @@ const handleClick = (type, id) => {
   .carousel-desc {
     height: 100%;
     margin: auto;
-    padding: 95px 0 165px 0;
+    padding: 55px 0 95px 0;
     h2 {
       margin: auto;
       text-align: center;
-      max-width: 870px;
+      max-width: 673px;
       font-size: 80px;
       font-weight: 500;
       line-height: 1.136364;

+ 38 - 38
src/views/login/components/privacyPolicy.vue

@@ -4,7 +4,7 @@
       <h1
         class="segment"
         style="margin-top:20px;font-size:26px;margin-bottom:20px;"
-      >门墩儿聘隐私保护政策</h1>
+      >门墩儿聘隐私保护政策</h1>
       <div style="word-break: break-word;">
         <p>尊敬的用户,欢迎您使用门墩儿产品和服务!
 门墩儿致力于为您提供高质量的招聘服务,我们深知个人信息的重要性,并承诺严格遵守相关法律法规,保护您的隐私和个人信息安全。本隐私政策旨在向您说明我们在收集、使用、处理、存储和分享您的个人信息时的做法,以帮助您更好地了解我们的服务并作出明智的决策。
@@ -13,7 +13,7 @@
 
         </p>
         <p>
-          依据《网络安全法》《互联网用戶账号信息管理规定》等法律法规的要求 ,您在门墩儿直聘注册页面完成手机短信 验证并勾选同意门墩儿直聘《用戶协议》等相关协议 ,即表示您已经阅读并且同意与门墩儿直聘公司达成本协议 , 成为门墩儿直聘的用戶 ,并接受本协议中的全部注册条款以及门墩儿直聘《隐私政策》和本平台内公布的包括但不  限于《招聘行为管理规范》《门墩儿聘增值服务协议》等各项协议或规则(统称“平台协议”或“平台规则”) 的所   有条款的约束 ,包括真有解决条款(详见本协议第十五条)。
+          依据《网络安全法》《互联网用戶账号信息管理规定》等法律法规的要求 ,您在门墩儿招聘注册页面完成手机短信 验证并勾选同意门墩儿招聘《用戶协议》等相关协议 ,即表示您已经阅读并且同意与门墩儿招聘公司达成本协议 , 成为门墩儿招聘的用戶 ,并接受本协议中的全部注册条款以及门墩儿招聘《隐私政策》和本平台内公布的包括但不  限于《招聘行为管理规范》《门墩儿聘增值服务协议》等各项协议或规则(统称“平台协议”或“平台规则”) 的所   有条款的约束 ,包括真有解决条款(详见本协议第十五条)。
         </p>
         <p>
           一、 引言</p>
@@ -29,11 +29,11 @@
         <p>十一、 争议解决方式</p>
         <p>&nbsp;</p>
         <p><span style="color: --var(--v-primary-base);"><strong>一、引言</strong></span></p>
-        <p>为切实保护门墩儿直聘用户隐私权,优化用户体验,门墩儿直聘根据现行法规及政策,制定本《隐私保护政策》。本《隐私保护政策》将详细说明门墩儿聘在获取、管理及保护用户个人信息方面的政策及措施。本《隐私保护政策》适用于门墩儿聘向您提供的所有服务,无论您是通过计算机设备、移动终端或其他设备获得的门墩儿聘服务。</p>
-        <p>本《隐私保护政策》旨在帮助您了解我们会收集哪些数据、为什么收集这些数据,会利用这些数据做些什么及如何保护这些数据。我们希望您在使用门墩儿聘服务前仔细阅读并明确您已经充分理解、接受本《隐私保护政策》的内容,希望您可以根据自己的理解做出合适的选择。您一旦开始使用门墩儿聘平台服务,即表示您认同我们在本《隐私保护政策》中所述内容。在我们更新本《隐私保护政策》后,您继续使用我们的产品与/或服务,即意味着您同意本《隐私保护政策》(含更新版本)内容,并且同意我们按照本《隐私保护政策》收集、使用、保存和共享您的相关信息。此外,在将您的信息用于本《隐私保护政策》未涵盖的用途时,我们会事先征求您的同意。</p>
+        <p>为切实保护门墩儿招聘用户隐私权,优化用户体验,门墩儿招聘根据现行法规及政策,制定本《隐私保护政策》。本《隐私保护政策》将详细说明门墩儿聘在获取、管理及保护用户个人信息方面的政策及措施。本《隐私保护政策》适用于门墩儿聘向您提供的所有服务,无论您是通过计算机设备、移动终端或其他设备获得的门墩儿聘服务。</p>
+        <p>本《隐私保护政策》旨在帮助您了解我们会收集哪些数据、为什么收集这些数据,会利用这些数据做些什么及如何保护这些数据。我们希望您在使用门墩儿聘服务前仔细阅读并明确您已经充分理解、接受本《隐私保护政策》的内容,希望您可以根据自己的理解做出合适的选择。您一旦开始使用门墩儿聘平台服务,即表示您认同我们在本《隐私保护政策》中所述内容。在我们更新本《隐私保护政策》后,您继续使用我们的产品与/或服务,即意味着您同意本《隐私保护政策》(含更新版本)内容,并且同意我们按照本《隐私保护政策》收集、使用、保存和共享您的相关信息。此外,在将您的信息用于本《隐私保护政策》未涵盖的用途时,我们会事先征求您的同意。</p>
         <p>&nbsp;</p>
         <p><strong><span style="color: --var(--v-primary-base);">二、我们如何收集和使用您的个人信息</span></strong></p>
-        <p>我们深知个人信息对您的重要性,也深知为您的信息提供有效保护是我们业务健康可持续发展的基石。感谢您对门墩儿聘平台的使用和信任!我们致力于维持您对我们的信任,恪守适用法律和我们对您的承诺,尽全力保证您的个人信息安全和合理使用。我们郑重承诺,我们已按业界成熟的安全标准,采取相应的安全保护措施来保护您的个人信息。我们承诺将坚持合法、正当、“最小必要化”原则收集、使用、存储和传输用户信息,不会收集与业务无关的信息或采取不正当的方式收集信息,并通过用户协议和隐私保护政策告知您相关信息的使用目的和范围。</p>
+        <p>我们深知个人信息对您的重要性,也深知为您的信息提供有效保护是我们业务健康可持续发展的基石。感谢您对门墩儿聘平台的使用和信任!我们致力于维持您对我们的信任,恪守适用法律和我们对您的承诺,尽全力保证您的个人信息安全和合理使用。我们郑重承诺,我们已按业界成熟的安全标准,采取相应的安全保护措施来保护您的个人信息。我们承诺将坚持合法、正当、“最小必要化”原则收集、使用、存储和传输用户信息,不会收集与业务无关的信息或采取不正当的方式收集信息,并通过用户协议和隐私保护政策告知您相关信息的使用目的和范围。</p>
         <p><br></p>
         <p><strong>(一)个人信息的定义</strong></p>
         <p>个人信息,是指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息,在本隐私保护政策中涉及的个人信息包括但不限于:</p>
@@ -97,11 +97,11 @@
         <p><strong>(三)平台如何收集和使用个人信息</strong></p>
         <p>在您使用平台基本功能服务的过程中,需要您主动或经您授权向平台提供与您必要的信息,平台将根据您提供的信息合法留存,以供平台为您提供服务。如果您不提供相关信息,您将无法使用平台的服务具体功能。请您注意,您在使用平台服务功能时所提供的所有个人信息,除非您删除或通过系统设置拒绝我们收集,否则将在您使用我们的产品与或服务期间持续授权我们使用。部分个人信息的收集,需要您同意调取所使用设备的相应系统权限,具体参见第本条款第(四)部分需要您授权同意调取系统权限的情形。平台搜集、使用个人信息的方式如下:</p>
         <p>1.用户注册</p>
-        <p>您首先需要注册一个门墩儿直聘帐号成为门墩儿直聘用户。当您注册时,您至少需要向我们提供您本人的手机号码,我们将通过发送短信验证码的方式来验证您的身份是否有效。如果您不提供这些信息,不影响您进行浏览、搜索。您可以自主设置您的帐号密码,并选择完善帐号信息,如绑定邮箱地址、第三方帐号(如微信、QQ、新浪微博、Apple账号)</p>
+        <p>您首先需要注册一个门墩儿招聘帐号成为门墩儿招聘用户。当您注册时,您至少需要向我们提供您本人的手机号码,我们将通过发送短信验证码的方式来验证您的身份是否有效。如果您不提供这些信息,不影响您进行浏览、搜索。您可以自主设置您的帐号密码,并选择完善帐号信息,如绑定邮箱地址、第三方帐号(如微信、QQ、新浪微博、Apple账号)</p>
         <p><br></p>
         <p>2.找工作</p>
         <p>为了更好地为您匹配并推荐职位信息并让企业招聘负责人更好地发现您,我们将收集您的基本信息、个人上网记录、个人位置信息。通过收集这些信息,平台将为您推荐更符合您的职位(例如与您所在城市、所在行业相匹配的职位)。</p>
-        <p>关于简历:由于门墩儿聘是连接候选人与用人者的中介信息招聘平台,如您作为求职者,您必须先完善您的个人在线简历后方可投递本网站上招聘企业发布的职位。个人在线简历包括生日、年龄、开始工作时间、过往工作经历(公司名称、担任职务、在职时间段、工作内容描述)、过往教育经历(毕业学校、学历、在校时间段、在校经历描述)、联系方式(手机、电子邮箱)、期望工作(期望城市、期望薪资、期望行业、期望职位以及其他因找工作所需提供的信息。当您向门墩儿聘传附件简历或编辑在线简历,并选择了公开您的简历时,您已经同意使用门墩儿聘相应服务的招聘单位(及人员)可以通过我们的系统功能(如职位、行业、从业时间等关键词)发现您。购买了相应服务的招聘企业(及人员)拥有法律上许可的对您的简历进行查询、浏览、下载、使用、存储的权利;但是你仍然拥有通过系统隐私设置功能,选择是否完全公开您的简历或屏蔽某些招聘企业发现您的信息的权利。对于因此而引起的任何法律纠纷(包括但不限于招聘企业或人员错误或非法使用前述简历信息),门墩儿聘不承担任何法律责任。</p>
+        <p>关于简历:由于门墩儿聘是连接候选人与用人者的中介信息招聘平台,如您作为求职者,您必须先完善您的个人在线简历后方可投递本网站上招聘企业发布的职位。个人在线简历包括生日、年龄、开始工作时间、过往工作经历(公司名称、担任职务、在职时间段、工作内容描述)、过往教育经历(毕业学校、学历、在校时间段、在校经历描述)、联系方式(手机、电子邮箱)、期望工作(期望城市、期望薪资、期望行业、期望职位以及其他因找工作所需提供的信息。当您向门墩儿聘传附件简历或编辑在线简历,并选择了公开您的简历时,您已经同意使用门墩儿聘相应服务的招聘单位(及人员)可以通过我们的系统功能(如职位、行业、从业时间等关键词)发现您。购买了相应服务的招聘企业(及人员)拥有法律上许可的对您的简历进行查询、浏览、下载、使用、存储的权利;但是你仍然拥有通过系统隐私设置功能,选择是否完全公开您的简历或屏蔽某些招聘企业发现您的信息的权利。对于因此而引起的任何法律纠纷(包括但不限于招聘企业或人员错误或非法使用前述简历信息),门墩儿聘不承担任何法律责任。</p>
         <p>&nbsp;</p>
         <p>3.招聘</p>
         <p>您在代表公司注册招聘人员帐号并入驻平台时需要完成招聘者身份认证</p>
@@ -116,10 +116,10 @@
         <p>为了让您快速地找到您所需要职位或求职用户,我们可能会收集您使用我们的产品与或服务的设备信息(包括设备名称、设备型号、设备识别码、操作系统和应用程序版本、分辨率、服务提供商网络、浏览器类型来为您提供信息展示的最优方式。我们也会为了不断改进和优化上述的功能来使用您的上述信息。您也可以通过搜索来精准地找到您所需要的工作信息或求职用户。我们会保留您的搜索内容以方便您重复输入或为您展示与您搜索内容相关岗位或求职用户。请您注意,您的搜索关键词信息无法单独识别您的身份,不属于您的个人信息,我们有权以任何的目的对其进行使用;只有当您的搜索关键词信息与您的其他信息相互结合使用并可以识别您的身份时,则在结合使用期间,我们会将您的搜索关键词信息作为您的个人信息,与您的搜索历史记录一同按照本《隐私保护政策》对其进行处理与保护。</p>
         <p><br></p>
         <p>5.在线沟通</p>
-        <p>门墩儿聘为招聘企业及候选人之间提供了在线沟通的功能,为此平台需要使用双方的帐号信息。</p>
+        <p>门墩儿聘为招聘企业及候选人之间提供了在线沟通的功能,为此平台需要使用双方的帐号信息。</p>
         <p>&nbsp;</p>
         <p>6.视频面试功能</p>
-        <p>门墩儿聘为招聘企业及候选人之间提供了在视频面试的功能,为此平台需要使用双方的帐号信息。</p>
+        <p>门墩儿聘为招聘企业及候选人之间提供了在视频面试的功能,为此平台需要使用双方的帐号信息。</p>
         <p>&nbsp;</p>
         <p>7.购买服务</p>
         <p>在您选择购买我们的增值服务时,您可以选择第三方支付机构所提供的支付服务。支付功能本身并不收集您的个人信息,但我们需要将您的订单号与交易金额信息与这些支付机构共享以实现其确认您的支付指令并完成支付。关联方指一方现在或将来控制、受控制或与其处于共同控制下的任何公司、机构以及上述公司或机构的法定代表人。控制是指直接或间接地拥有影响所提及公司管理的能力,无论是通过所有权、有投票权的股份、合同或其他被人民法院认定的方式。</p>
@@ -128,8 +128,8 @@
         <p>您在使用服务的过程中,可能会向客服渠道提出任何问题、意见、建议、投诉、举报等需求。为此我们需收集、使用上述个人信息中的部分/全部相关内容。有关向第三方披露、共享您的个人信息的情况,将遵循下文中的具体约定。</p>
         <p><br></p>
         <p>9.改进产品与或服务所必须的功能</p>
-        <p>当您登录门墩儿聘的网页或使用平台时,我们的服务器会自动记录您的日志信息,例如您的登录记录、输入的搜索关键词信息、点击的内容,您发布的报错信息、反馈和评论信息,您上传的图片信息、您的地址、浏览器的类型和使用的语言、硬件设备信息、操作系统的版本、网络运营商的信息、您访问服务的日期、时间、时长。为了给您带来更便捷的服务,我们可能会收集您设备上的信息并进行本地存储。我们会:</p>
-        <p>(1)基于前述信息以及您的求职意向、对您的偏好、习惯、位置作特征分析和用户画像,以便为您提供更适合您的定制化服务,例如向您展现或推荐相关程度更高(而非普遍推送)的展示结果、搜索结果、信息流或者推广信息结果,或向您发送短信、电话邀约等营销内容、广告以及您可能感兴趣的其他信息(包括与本平台、本平台的合作伙伴活动及服务相关的信息)。如果您不希望平台提供上述服务,您可以关闭相应功能(如您未登录门墩儿聘平台帐号,我们不提供个性化推荐功能,您无须关闭)。您可以在APP端点击“我的-设置-关闭首页推荐”来关闭个性化推荐功能(温馨提示:本功能默认开启),则平台不会再提供基于用户画像展现的个性化推荐结果。对于短信的推送信息,您可以根据短信内容提示进行退订服务。对于商业性广告电话,您可以在电话中明确表示拒绝接收。</p>
+        <p>当您登录门墩儿聘的网页或使用平台时,我们的服务器会自动记录您的日志信息,例如您的登录记录、输入的搜索关键词信息、点击的内容,您发布的报错信息、反馈和评论信息,您上传的图片信息、您的地址、浏览器的类型和使用的语言、硬件设备信息、操作系统的版本、网络运营商的信息、您访问服务的日期、时间、时长。为了给您带来更便捷的服务,我们可能会收集您设备上的信息并进行本地存储。我们会:</p>
+        <p>(1)基于前述信息以及您的求职意向、对您的偏好、习惯、位置作特征分析和用户画像,以便为您提供更适合您的定制化服务,例如向您展现或推荐相关程度更高(而非普遍推送)的展示结果、搜索结果、信息流或者推广信息结果,或向您发送短信、电话邀约等营销内容、广告以及您可能感兴趣的其他信息(包括与本平台、本平台的合作伙伴活动及服务相关的信息)。如果您不希望平台提供上述服务,您可以关闭相应功能(如您未登录门墩儿聘平台帐号,我们不提供个性化推荐功能,您无须关闭)。您可以在APP端点击“我的-设置-关闭首页推荐”来关闭个性化推荐功能(温馨提示:本功能默认开启),则平台不会再提供基于用户画像展现的个性化推荐结果。对于短信的推送信息,您可以根据短信内容提示进行退订服务。对于商业性广告电话,您可以在电话中明确表示拒绝接收。</p>
         <p>(2)用于产品功能改进:如统计我们产品的用户数量、分析产品的使用状况、网页升级改版、浏览器兼容性检测、排查崩溃原因、减少崩溃情况、监测广告投放情况、改进产品BUG、优化产品的稳定性及功能性。</p>
         <p>&nbsp;</p>
         <p>10.使用第三方收集、使用您的个人信息</p>
@@ -144,18 +144,18 @@
           >https://terms.aliyun.com/legal-agreement/terms/suit_bu1_ali_cloud/suit_bu1_ali_cloud202107281509_18386.html?spm=a2c4g.11186623.0.0.37c330e5MGyLy7</a></p>
         <p><br></p>
         <p>11.保障求职招聘安全所必须的功能</p>
-        <p>为了增强门墩儿聘平台求职招聘信息发布服务的安全性,保护您或其他用户在招聘求职过程中的人身、财产安全免遭侵害,更好地预防求职诈骗等安全风险,更准确地识别违反法律法规或门墩儿聘相关协议规则的情况。我们可能使用或整合您的帐号信息、设备信息、软件使用信息以及我们关联公司、合作伙伴取得您授权或依据法律共享的信息,用于判断您的帐号风险、进行身份验证、检测我们认为有风险的行为以及防范平台安全事件,并采取必要的记录、审计、分析、处置措施。</p>
+        <p>为了增强门墩儿聘平台求职招聘信息发布服务的安全性,保护您或其他用户在招聘求职过程中的人身、财产安全免遭侵害,更好地预防求职诈骗等安全风险,更准确地识别违反法律法规或门墩儿聘相关协议规则的情况。我们可能使用或整合您的帐号信息、设备信息、软件使用信息以及我们关联公司、合作伙伴取得您授权或依据法律共享的信息,用于判断您的帐号风险、进行身份验证、检测我们认为有风险的行为以及防范平台安全事件,并采取必要的记录、审计、分析、处置措施。</p>
         <p>&nbsp;</p>
         <p>12.其他使用</p>
-        <p>您通过门墩儿聘与他人在线沟通、拨打电话以及视频面试等商务场景下产生的文字、语音及视频等形式的沟通信息,为响应维护网络秩序和防欺诈的要求,本平台将会根据《网络安全法》等法律相关规定存储,且仅用于投诉举报的处理、安全风控及离线暂存功能的实现。本平台对该信息的采集、传输及存储均会采取加密、防泄露等相关措施。</p>
+        <p>您通过门墩儿聘与他人在线沟通、拨打电话以及视频面试等商务场景下产生的文字、语音及视频等形式的沟通信息,为响应维护网络秩序和防欺诈的要求,本平台将会根据《网络安全法》等法律相关规定存储,且仅用于投诉举报的处理、安全风控及离线暂存功能的实现。本平台对该信息的采集、传输及存储均会采取加密、防泄露等相关措施。</p>
         <p><br></p>
         <p><br></p>
         <p style="white-space: normal;"><strong>(四)自启动和关联启动说明</strong></p>
         <p>1.为确保本应用处于关闭或后台运营状态下可正常接收到客户端推送的广播信息,本应用须使用(自启动)能力,将存在一定频率通过形同发送广播唤醒本应用自启动或关联启动行为,是因实现功能及服务所必要的。</p>
-        <p>2.当您打开门墩儿直聘APP内容类推送消息,在征得您的明确同意后,会跳转门墩儿直聘APP打开相关内容。在未征得您同意的情况下,则不会有关联启动。</p>
+        <p>2.当您打开门墩儿招聘APP内容类推送消息,在征得您的明确同意后,会跳转门墩儿招聘APP打开相关内容。在未征得您同意的情况下,则不会有关联启动。</p>
         <p><strong><br></strong></p>
         <p><strong>(五)需要您授权同意调取系统权限的情形</strong><br></p>
-        <p>在为您提供前述基本功能/服务,改进产品与/或服务或使用第三方SDK收集使用您的个人信息时,部分场景的实现依赖于您同意平台(APP)调取您所使用设备的相应系统权限。您可通过门墩儿聘APP上的“我的-设置-权限设置”逐项查看具体的个人信息访问权限及其开启状态,并决定开启或关闭这些权限。请您注意,您开启这些权限即代表您授权我们可以收集和使用这些个人信息来实现上述的功能,您关闭权限即代表您取消了这些授权,则我们将不再继续收集和使用您的这些个人信息,也无法为您提供上述与这些授权所对应的功能。您关闭权限的决定不会影响此前基于您的授权所进行的个人信息的处理:</p>
+        <p>在为您提供前述基本功能/服务,改进产品与/或服务或使用第三方SDK收集使用您的个人信息时,部分场景的实现依赖于您同意平台(APP)调取您所使用设备的相应系统权限。您可通过门墩儿聘APP上的“我的-设置-权限设置”逐项查看具体的个人信息访问权限及其开启状态,并决定开启或关闭这些权限。请您注意,您开启这些权限即代表您授权我们可以收集和使用这些个人信息来实现上述的功能,您关闭权限即代表您取消了这些授权,则我们将不再继续收集和使用您的这些个人信息,也无法为您提供上述与这些授权所对应的功能。您关闭权限的决定不会影响此前基于您的授权所进行的个人信息的处理:</p>
         <ol
           class=" list-paddingleft-2"
           style="list-style-type: decimal;"
@@ -193,7 +193,7 @@
         </ol>
         <p>&nbsp;</p>
         <p><strong>(六)无需征得授权的情形</strong></p>
-        <p>根据国家法律法规的相关规定及特定事项的需求,门墩儿聘在以下情况无需经过您的授权即可收集并使用您的个人信息,您知晓并充分理解此等情形:</p>
+        <p>根据国家法律法规的相关规定及特定事项的需求,门墩儿聘在以下情况无需经过您的授权即可收集并使用您的个人信息,您知晓并充分理解此等情形:</p>
         <ol
           class=" list-paddingleft-2"
           style="list-style-type: decimal;"
@@ -234,7 +234,7 @@
         </ol>
         <p>&nbsp;</p>
         <p><strong>(七) 从第三方获取您的个人信息</strong></p>
-        <p>我们可能从第三方获取您授权共享的帐号信息(头像、昵称),并在您同意本隐私保护政策后将您的第三方帐号与您的门墩儿聘帐号绑定,使您可以通过第三方帐号直接登录并使用我们的产品与/或服务。我们会将依据与第三方的约定、对个人信息来源的合法性进行确认后,在符合相关法律和法规规定的前提下,使用您的这些个人信息。</p>
+        <p>我们可能从第三方获取您授权共享的帐号信息(头像、昵称),并在您同意本隐私保护政策后将您的第三方帐号与您的门墩儿聘帐号绑定,使您可以通过第三方帐号直接登录并使用我们的产品与/或服务。我们会将依据与第三方的约定、对个人信息来源的合法性进行确认后,在符合相关法律和法规规定的前提下,使用您的这些个人信息。</p>
         <p>&nbsp;</p>
         <p><strong>(八)个人信息去标识化后的使用</strong></p>
         <p>在收集您的个人信息后,我们可以通过技术手段对数据进行去标识化处理,去标识化处理的信息将无法识别主体。您了解并同意,在此情况下我们有权使用已经去标识化的信息;并对您的个人信息进行脱敏处理的前提下,我们有权对用户数据库进行分析并予以商业化的利用。比如,我们会对我们服务使用情况进行统计,并可能会与公众或第三方共享这些统计信息,以展示互联网行业及招聘领域发展趋势等,但这些统计信息不包含您的任何身份识别信息。</p>
@@ -242,7 +242,7 @@
         <p>如果您对我们收集和使用您的个人信息有任何疑问或需要提供进一步的信息,请通过本《隐私保护政策》公布的联系方式与我们联系。</p>
         <p>&nbsp;</p>
         <p><span style="color: --var(--v-primary-base);"><strong>三、我们如何使用Cookie和同类技术</strong></span></p>
-        <p>为确保网站正常运转,我们会在您的计算机或移动设备上存储名为 Cookie 的小数据文件。Cookie 通常包含用户身份标识符、城市名称以及一些字符。Cookie主要的功能是能够存储您的偏好,便于您使用网站产品和服务,以及帮助网站统计独立访客数量。运用Cookie技术,我们能够为您提供更加周到的服务。我们不会将 Cookie 用于本《隐私保护政策》所述目的之外的任何用途。您可根据自己的偏好管理或删除 Cookie。有关详情,请参见 【AboutCookies.org】。您可以清除计算机上保存的所有 Cookie,大部分网络浏览器都设有阻止 Cookie 的功能。但如果您这么做,则需要在每一次访问我们的网站时亲自更改用户设置,但您可能因为该修改,无法登录或使用依赖于Cookie的百度提供的服务或功能。 您可以通过更改您的浏览器设置限制门墩儿聘对Cookie的使用。以【Chrome】浏览器为例,您可以在【Chrome】浏览器右上方的下拉菜单的“浏览器设置”中,通过“【设置-高级-清楚浏览数据】”,选择清除您的Cookie。</p>
+        <p>为确保网站正常运转,我们会在您的计算机或移动设备上存储名为 Cookie 的小数据文件。Cookie 通常包含用户身份标识符、城市名称以及一些字符。Cookie主要的功能是能够存储您的偏好,便于您使用网站产品和服务,以及帮助网站统计独立访客数量。运用Cookie技术,我们能够为您提供更加周到的服务。我们不会将 Cookie 用于本《隐私保护政策》所述目的之外的任何用途。您可根据自己的偏好管理或删除 Cookie。有关详情,请参见 【AboutCookies.org】。您可以清除计算机上保存的所有 Cookie,大部分网络浏览器都设有阻止 Cookie 的功能。但如果您这么做,则需要在每一次访问我们的网站时亲自更改用户设置,但您可能因为该修改,无法登录或使用依赖于Cookie的百度提供的服务或功能。 您可以通过更改您的浏览器设置限制门墩儿聘对Cookie的使用。以【Chrome】浏览器为例,您可以在【Chrome】浏览器右上方的下拉菜单的“浏览器设置”中,通过“【设置-高级-清楚浏览数据】”,选择清除您的Cookie。</p>
         <p>&nbsp;</p>
         <p><span style="color: --var(--v-primary-base);"><strong>四、我们如何共享、转让、公开披露您的个人信息</strong></span></p>
         <p>我们不会向任何第三方共享、转让您的个人信息,除非经过您本人事先授权同意,或者共享、转让的个人信息是去标识化处理后的信息,且共享第三方无法重新识别此类信息的自然人主体。</p>
@@ -250,13 +250,13 @@
         <p><br></p>
         <p>当【软件服务提供商、智能设备提供商或系统服务提供商】与我们联合为您提供服务时,当您需要使用地理位置功能时,为实现这一功能,我们可能会收集您的位置信息及相关设备信息(包括硬件型号、操作系统版本号、国际移动设备身份识别码(IMEI)、网络设备硬件地址(MAC))经过去标识化后并提供给前述提供商。</p>
         <p>目前,我们的授权合作伙伴包括以下类型:</p>
-        <p>• 服务平台或服务提供商。门墩儿聘各产品接入了丰富的第三方服务。当您选择使用该第三方服务时,您授权我们将该信息提供给第三方服务平台或服务提供商,以便其基于相关信息为您提供服务,包括认证服务提供商,当您绑定门墩儿聘与认证平台帐号时,我们将弹出授权确认页面,在向您告知收集上述信息并得到您授权的情况下,我们会将您的简历信息提供给认证平台,用于评价您的信用分。</p>
-        <p>• 软硬件/系统服务提供商。当第三方软硬件/系统产品或服务与门墩儿聘的产品或服务结合为您提供服务时,经您授权,我们会向第三方软硬件/系统服务提供商提供您必要的个人信息,以便您使用服务,或用于我们分析产品和服务使用情况,来提升您的使用体验。</p>
+        <p>• 服务平台或服务提供商。门墩儿聘各产品接入了丰富的第三方服务。当您选择使用该第三方服务时,您授权我们将该信息提供给第三方服务平台或服务提供商,以便其基于相关信息为您提供服务,包括认证服务提供商,当您绑定门墩儿聘与认证平台帐号时,我们将弹出授权确认页面,在向您告知收集上述信息并得到您授权的情况下,我们会将您的简历信息提供给认证平台,用于评价您的信用分。</p>
+        <p>• 软硬件/系统服务提供商。当第三方软硬件/系统产品或服务与门墩儿聘的产品或服务结合为您提供服务时,经您授权,我们会向第三方软硬件/系统服务提供商提供您必要的个人信息,以便您使用服务,或用于我们分析产品和服务使用情况,来提升您的使用体验。</p>
         <p>• 广告、咨询类服务商/广告主。未经您授权,我们不会将您的个人信息与提供广告、咨询类服务商共享。但我们可能会将经处理无法识别您的身份且接收方无法复原的信息,包括经匿名化处理的用户画像,与广告或咨询类服务商或广告主共享,以帮助其在不识别您个人的前提下,提升广告有效触达率,以及分析我们的产品和服务使用情况。<br><br></p>
         <p>1.3 对我们与之共享个人信息的公司、组织和个人,我们会与其签署严格的保密协定,并要求第三方以不低于本《隐私保护政策》所要求的保密和安全措施来处理该些信息。<br></p>
         <p><br></p>
         <p>2. 转让</p>
-        <p>我们不会将您的个人信息转让给除门墩儿聘及其关联公司外的任何公司、组织和个人,但以下情形除外:</p>
+        <p>我们不会将您的个人信息转让给除门墩儿聘及其关联公司外的任何公司、组织和个人,但以下情形除外:</p>
         <p>2.1 事先获得您的明确授权或同意;</p>
         <p>2.2 满足法律法规、法律程序的要求或强制性的政府要求或司法裁定;</p>
         <p>2.3 如果我们或我们的关联公司涉及合并、分立、清算、资产或业务的收购或出售等交易,您的个人信息有可能作为此类交易的一部分而被转移,我们将确保该等信息在转移时的机密性,并要求新的持有您个人信息的公司、组织继续受此隐私保护政策的约束,否则我们将要求该公司、组织重新向您征求授权同意。<br></p>
@@ -281,7 +281,7 @@
         <p>&nbsp;</p>
         <p><span style="color: --var(--v-primary-base);"><strong>五、我们如何保存及保护您的个人信息</strong></span></p>
         <p>1.保存期限</p>
-        <p>您在使用门墩儿聘产品及服务期间,我们将持续为您保存您的个人信息。如果您注销帐户或主动删除上述信息,我们将依据网络安全法等法律法规规定保存您的信息。在您注销帐户或主动删除上述信息后,我们不会再对您的个人信息进行商业化使用,但我们可能会对您的个人信息进行删除或匿名化处理后使用。</p>
+        <p>您在使用门墩儿聘产品及服务期间,我们将持续为您保存您的个人信息。如果您注销帐户或主动删除上述信息,我们将依据网络安全法等法律法规规定保存您的信息。在您注销帐户或主动删除上述信息后,我们不会再对您的个人信息进行商业化使用,但我们可能会对您的个人信息进行删除或匿名化处理后使用。</p>
         <p>&nbsp;</p>
         <p>2. 保存地域</p>
         <p>您的个人信息均储存于中华人民共和国境内。如部分产品或服务涉及跨境,我们需要向境外传输您的个人信息,我们会严格按照法律法规的规定执行,并保证您的个人信息安全。<br></p>
@@ -294,29 +294,29 @@
         <p>当我们的产品或服务发生停止运营的情形时,我们将采取例如,推送通知、公告等形式通知您,并在合理的期限内删除或匿名化处理您的个人信息。<br></p>
         <p><br></p>
         <p>4. 保护措施</p>
-        <p>4.1 我们已采取符合业界标准、合理可行的安全防护措施保护您的信息,防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。平台会采取一切合理可行的措施,保护您的个人信息。例如,在您的浏览器与服务器之间交换数据时受SSL协议加密保护;我们同时对门墩儿聘网站提供HTTPS协议安全浏览方式;我们会使用加密技术提高个人信息的安全性;我们会使用受信赖的保护机制防止个人信息遭到恶意攻击;我们会部署访问控制机制,尽力确保只有授权人员才可访问个人信息;以及我们会举办安全培训课程,加强员工对于保护个人信息重要性的认识。</p>
+        <p>4.1 我们已采取符合业界标准、合理可行的安全防护措施保护您的信息,防止个人信息遭到未经授权访问、公开披露、使用、修改、损坏或丢失。平台会采取一切合理可行的措施,保护您的个人信息。例如,在您的浏览器与服务器之间交换数据时受SSL协议加密保护;我们同时对门墩儿聘网站提供HTTPS协议安全浏览方式;我们会使用加密技术提高个人信息的安全性;我们会使用受信赖的保护机制防止个人信息遭到恶意攻击;我们会部署访问控制机制,尽力确保只有授权人员才可访问个人信息;以及我们会举办安全培训课程,加强员工对于保护个人信息重要性的认识。</p>
         <p><br></p>
         <p>4.2 我们从组织建设、制度设计、人员管理、产品技术等方面多维度提升整个系统的安全性。目前,我们的重要信息系统已经通过网络安全等级保护的测评。<br><br></p>
         <p>4.3 请您理解,由于技术的限制以及可能存在的各种恶意手段,有可能出现平台无法合理预见、防范、避免、控制的以外情况。我们会采取合理可行的措施,尽力避免收集无关的个人信息。我们只会在达成本《隐私保护政策》所述目的所需的期限内保留您的个人信息(除非法律有强制的存留要求)。<br><br></p>
-        <p>4.4 互联网并非绝对安全的环境,使用门墩儿直聘平台服务时,我们强烈建议您不要使用非门墩儿直聘平台推荐的通信方式发送您的信息。您可以通过我们的服务建立联系和相互分享。当您通过我们的服务创建交流、分享时,您可以自主选择沟通、分享的对象,作为能够看到您的联络方式、交流信息或分享内容等相关信息的第三方。<br><br></p>
-        <p>4.5 在使用门墩儿聘服务进行沟通时,请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息尤其是您的帐号或密码发生泄露,请您立即通过第十章公布的联系方式联络我们,以便我们根据您的申请采取相应措施。<br><br></p>
+        <p>4.4 互联网并非绝对安全的环境,使用门墩儿招聘平台服务时,我们强烈建议您不要使用非门墩儿招聘平台推荐的通信方式发送您的信息。您可以通过我们的服务建立联系和相互分享。当您通过我们的服务创建交流、分享时,您可以自主选择沟通、分享的对象,作为能够看到您的联络方式、交流信息或分享内容等相关信息的第三方。<br><br></p>
+        <p>4.5 在使用门墩儿聘服务进行沟通时,请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息尤其是您的帐号或密码发生泄露,请您立即通过第十章公布的联系方式联络我们,以便我们根据您的申请采取相应措施。<br><br></p>
         <p>4.6请注意,您在使用我们服务时自愿共享甚至公开分享的信息,可能会涉及您或他人的个人信息甚至个人敏感信息,如您在评论、沟通时选择上传包含个人信息的图片。请您更加谨慎地考虑,是否在使用我们的服务时共享甚至公开分享相关信息。请使用复杂密码,协助我们保证您的帐号安全。我们将尽力保障您发送给我们的任何信息的安全性。<br></p>
         <p><br></p>
         <p>5. 安全事件通知</p>
         <p>5.1 我们会制定网络安全事件应急预案,及时处置系统漏洞、计算机病毒、网络攻击、网络侵入等安全风险,在发生危害网络安全的事件时,我们会立即启动应急预案,采取相应的补救措施,并按照规定向有关主管部门报告。<br><br></p>
         <p>5.2 个人信息泄露、毁损、丢失属于公司级特大安全事件,我们会负责定期组织工作组成员进行安全预案演练,防止此类安全事件发生。若一旦不幸发生,我们将按照最高优先级启动应急预案,由安全部、政府关系部、法务部等多个部门组成应急响应小组,在最短时间内追溯原因并减少损失。<br><br></p>
         <p>5.3 在不幸发生个人信息安全事件后,我们将按照法律法规的要求,及时通过软件内部提醒、邮件、短信或电话等方式向您告知安全事件的基本情况和可能的影响、我们已采取或将要采取的处理措施、您可自主防范和降低的风险的建议、对您的补救措施等。我们将及时将事件相关情况通过上述方式告知您,难以逐一告知时我们会采取合理、有效的方式发布公告。同时,我们还将按照监管部门要求,主动上报个人信息安全事件的处置情况。</p>
-        <p>我们将不定期更新并公开安全风险、个人信息安全影响评估报告等有关内容,您可通过门墩儿聘公告方式获得。</p>
+        <p>我们将不定期更新并公开安全风险、个人信息安全影响评估报告等有关内容,您可通过门墩儿聘公告方式获得。</p>
         <p>&nbsp;</p>
         <p><span style="color: --var(--v-primary-base);"><strong>六、您控制个人信息的权利</strong></span></p>
         <p>按照中国相关的法律、法规、标准,以及其他国家、地区的通行做法,我们保障您对自己的个人信息行使以下权利:1. 访问和修改您的个人信息<br>(1) 访问修改姓名</p>
-        <p>可以在【我的门墩儿聘&gt;编辑简历&gt;基本信息】中显示和修改</p>
+        <p>可以在【我的门墩儿聘&gt;编辑简历&gt;基本信息】中显示和修改</p>
         <p>(2) 访问和修改性别</p>
-        <p>可以在【我的门墩儿聘&gt;编辑简历&gt;基本信息】中显示和修改</p>
+        <p>可以在【我的门墩儿聘&gt;编辑简历&gt;基本信息】中显示和修改</p>
         <p>(3) 访问和修改简历内容</p>
-        <p>可以在【我的门墩儿聘&gt;编辑简历&gt;】中显示和修改</p>
+        <p>可以在【我的门墩儿聘&gt;编辑简历&gt;】中显示和修改</p>
         <p>(4) 访问和修改手机号</p>
-        <p>可以在【我的门墩儿聘&gt;编辑简历&gt;基本信息】中更换手机号</p>
+        <p>可以在【我的门墩儿聘&gt;编辑简历&gt;基本信息】中更换手机号</p>
         <p>如果您无法通过上述链接访问该等个人信息,您可以通过本《隐私保护政策》公布的联系方式与我们联系。</p>
         <p>您在使用我们的产品和服务过程中产生的其他个人信息,只要我们不需要过多投入,我们会向您提供。如果您想行使数据访问权,请通过本《隐私保护政策》的“十、如何联系我们”中公布的联系方式与我们联系。</p>
         <p>您发现我们处理的关于您的个人信息有错误时,您有权对错误或不完整的信息作出更正或更新,您可以通过上述段落中列明的方式提出更正或补充申请。为保障安全,我们将在您行使更正权前对您的身份进行验证。<br></p>
@@ -327,7 +327,7 @@
         <p>2.2 如果我们违反法律法规规定或与您的约定,公开披露您的个人信息,您有权要求我们立即停止公开披露的行为,并发布通知要求相关接收方删除相应的信息</p>
         <p>2.3 我们没有征求您的明确同意,收集了您的个人信息&nbsp;</p>
         <p>2.4 我们违反了与您的约定来使用和处理您的个人信息</p>
-        <p>2.5 您注销了门墩儿聘帐号、卸载或者不再使用我们的产品(或服务)</p>
+        <p>2.5 您注销了门墩儿聘帐号、卸载或者不再使用我们的产品(或服务)</p>
         <p>2.6 我们停止对您提供服务<br></p>
         <p><br></p>
         <p>3. 改变授权范围</p>
@@ -339,10 +339,10 @@
         <p><br></p>
         <p>4. 注销您的帐号</p>
         <p>4.2 如您需注销企业帐号,可联系客服 400-826-0101,我们将在核实信息后3个工作日内完成注销。</p>
-        <p>您注销帐号的行为是不可逆的,一旦您的帐号被注销,我们将不再为您提供门墩儿聘产品与/或服务,并根据法律的要求删除您的个人信息,或对其进行匿名化处理。</p>
+        <p>您注销帐号的行为是不可逆的,一旦您的帐号被注销,我们将不再为您提供门墩儿聘产品与/或服务,并根据法律的要求删除您的个人信息,或对其进行匿名化处理。</p>
         <p><br></p>
         <p>5. 提前获知产品和服务停止运营</p>
-        <p>门墩儿直聘愿一直陪伴您,若因特殊原因导致门墩儿直聘平台被迫停止运营,我们将按照法律法规的要求,在产品和/或服务的主页面或站内信或向您发送电子邮件或其他合适的能触达您的方式通知您,并将停止对您个人信息的收集,同时会按照法律规定对所持有的您的个人信息进行删除或匿名化处理。</p>
+        <p>门墩儿招聘愿一直陪伴您,若因特殊原因导致门墩儿招聘平台被迫停止运营,我们将按照法律法规的要求,在产品和/或服务的主页面或站内信或向您发送电子邮件或其他合适的能触达您的方式通知您,并将停止对您个人信息的收集,同时会按照法律规定对所持有的您的个人信息进行删除或匿名化处理。</p>
         <p><br></p>
         <p>6. 响应您的上述请求</p>
         <p>6.1 为保障安全,您需要提供书面请求,或以其他方式证明您的身份。我们可能会先要求您验证自己的身份,然后再处理您的请求。</p>
@@ -358,7 +358,7 @@
         <p>(6)涉及商业秘密的。</p>
         <p>&nbsp;</p>
         <p><span style="color: --var(--v-primary-base);"><strong>七、我们如何处理未成年人的个人信息</strong></span></p>
-        <p>门墩儿聘非常重视对未成年人信息的保护。</p>
+        <p>门墩儿聘非常重视对未成年人信息的保护。</p>
         <p>基于我们的产品、网站和服务的性质,我们不向16周岁以下的未成年人提供服务,因此无法收集相关信息。若您是已满16周岁不满18周岁的未成年人,建议您请您的监护人仔细阅读本《隐私保护政策》,并在征得您的监护人同意的前提下使用我们的产品和/或服务或向我们提供信息。</p>
         <p>如您的监护人不同意您按照本《隐私保护政策》使用我们的服务或向我们提供信息,请您立即终止使用我们的服务并及时通知我们,以便我们采取相应的措施。</p>
         <p>如果监护人发现我们在未获监护人同意的情况下收集了未成年人的个人信息,请通过本《隐私保护政策》公布的联系方式联系我们,我们会尽快删除相关数据。</p>
@@ -368,7 +368,7 @@
         <p>&nbsp;</p>
         <p><span style="color: --var(--v-primary-base);"><strong>九、本《隐私保护政策》如何更新</strong></span></p>
         <p>我们可能根据国家法律法规变化或服务运营需要适时修订本《隐私保护政策》内容。如该等变更会导致您在本《隐私保护政策》项下权利的实质变化,我们将在变更生效前,通过【推送站内通知、电子邮件、短信或网站公告】等方式通知您。在此期间,您应不时关注相关公告、提示信息及协议、规则等相关内容的变动。</p>
-        <p>若您不同意该等变更应停止使用门墩儿聘平台产品和服务,或通过本《隐私保护政策》公布的联系方式要求暂时封停、注销您的帐号,平台将停止收集您的相关个人信息;若您继续使用我们的产品和/或服务,即表示您同意受修订后的本《隐私保护政策》的约束。</p>
+        <p>若您不同意该等变更应停止使用门墩儿聘平台产品和服务,或通过本《隐私保护政策》公布的联系方式要求暂时封停、注销您的帐号,平台将停止收集您的相关个人信息;若您继续使用我们的产品和/或服务,即表示您同意受修订后的本《隐私保护政策》的约束。</p>
         <p><br></p>
         <p>本《隐私保护政策》所指的重大变更包括但不限于:</p>
         <ol
@@ -417,16 +417,16 @@
           style="list-style-type: decimal;"
         >
           <li>
-            <p>“我们”或“平台”或“门墩儿聘公司”,指杭州东方网升科技股份有限公司。</p>
+            <p>“我们”或“平台”或“门墩儿聘公司”,指杭州东方网升科技股份有限公司。</p>
           </li>
           <li>
             <p>&nbsp;“您”或“用户”,指使用我们的产品或服务的注册用户以及收费服务的购买方。</p>
           </li>
           <li>
-            <p>“门墩儿直聘平台”、“门墩儿直聘软件”或“门墩儿直聘”,指门墩儿直聘网站(https://www.veryeast.cn)及门墩儿直聘手机客户端、门墩儿直聘微信小程序。</p>
+            <p>“门墩儿招聘平台”、“门墩儿招聘软件”或“门墩儿招聘”,指门墩儿招聘网站(https://www.veryeast.cn)及门墩儿招聘手机客户端、门墩儿招聘微信小程序。</p>
           </li>
           <li>
-            <p>“门墩儿聘关联方、合作方”,指我们的关联公司(包括先之教育、乔邦猎头)、投资公司、合作伙伴及其他受信任的第三方供应商、服务商及代理商。</p>
+            <p>“门墩儿聘关联方、合作方”,指我们的关联公司(包括先之教育、乔邦猎头)、投资公司、合作伙伴及其他受信任的第三方供应商、服务商及代理商。</p>
           </li>
           <li>
             <p>“个人信息”,指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息。个人信息包括个人基本信息、个人身份信息、个人生物识别信息、网络身份标识信息、个人健康生理信息、个人教育工作信息、个人财产信息、个人通信信息、联系人信息、个人上网记录、个人常用设备信息、个人位置信息。为免疑义,个人信息包括但不限于个人敏感信息。</p>

File diff suppressed because it is too large
+ 44 - 44
src/views/login/components/userAgreement.vue


+ 6 - 0
src/views/login/index.vue

@@ -1,5 +1,6 @@
 <template>
   <div class="login-box">
+    <navBar :showLoginBtn="false" class="navBar"></navBar>
     <div class="login-content">
       <!-- <div class="text-end pr-5 pt-5">
         <span class="color-error cursor-pointer text-decoration-underline" @click="router.push('/register/selected')">还没有登录账户?去注册</span>
@@ -56,6 +57,7 @@ import { useI18n } from '@/hooks/web/useI18n'
 import { getEnterpriseRegisterApply } from '@/api/common'
 import Snackbar from '@/plugins/snackbar'
 import Confirm from '@/plugins/confirm'
+import navBar from '@/layout/personal/navBar.vue'
 
 const { t } = useI18n()
 const router = useRouter()
@@ -128,6 +130,10 @@ const handleLogin = async () => {
   background-image: url('https://www.mendunerhr.com/images/userfiles/92d7e4a755e2428b94aab3636d5047f3/images/recruitment/adImages/2018/11/1920x940.jpg');
   background-size: cover;
 }
+.navBar {
+  position: absolute;
+  top: 0;
+}
 .login-content {
   position: absolute;
   top: 50%;

+ 1 - 0
src/views/mall/components/table.vue

@@ -7,6 +7,7 @@
     hover
     height="60vh"
     item-value="id"
+    no-data-text="暂无数据"
   >
     <template #bottom></template>
   </v-data-table>

+ 1 - 0
src/views/mall/purchasePackage/index.vue

@@ -28,6 +28,7 @@
       <v-data-table
         :items="!type ? personalItems : enterpriseItems"
         :headers="headers"
+        no-data-text="暂无数据"
       > 
         <template v-slot:[`item.equity`]="{ item }">
           <span class="font-weight-bold font-size-14">{{ item.equity }}</span>

+ 1 - 0
src/views/publicRecruitment/components/integralTable.vue

@@ -7,6 +7,7 @@
     hover
     height="60vh"
     item-value="id"
+    no-data-text="暂无数据"
   >
     <template #bottom></template>
   </v-data-table>

+ 1 - 0
src/views/publicRecruitment/components/table.vue

@@ -6,6 +6,7 @@
     :headers="headers"
     hover
     item-value="id"
+    no-data-text="暂无数据"
   >
     <template #bottom></template>
     <template v-slot:item.name="{ item }">

+ 4 - 4
src/views/recruit/entRegister/inReview.vue

@@ -1,7 +1,7 @@
 <!-- 注册企业进度 -->
 <template>
   <div class="my-5">
-    <div :class="isMobile? 'mobileBox' : 'default-width'">
+    <div v-if="!isMobile">
       <v-btn v-if="query?.noLogin" class="my-2" color="primary" variant="text" size="large" @click="router.push('/login')">{{ `<< 回到登录页` }}</v-btn>
       <v-btn v-else class="my-2" color="primary" variant="text" size="large" @click="router.push('/recruitHome')">{{ `<< 回到首页` }}</v-btn>
     </div>
@@ -44,9 +44,9 @@
         <div v-else-if="applyInfo.status === '1'">
           <span>审核通过</span>
         </div>
-        <div class="text-center" v-if="!isMobile">
-          <v-btn class="mt-16 buttons" color="primary" to="/recruitHome">{{ $t('common.toHome') }}</v-btn>
-          <v-btn v-if="applyInfo.status === '2'" class="mt-16 ml-12 buttons" color="primary" @click="handleConfirm">{{ $t('common.resubmit') }}</v-btn>
+        <div class="text-center">
+          <v-btn v-if="!isMobile" class="mt-16 mr-12 buttons" color="primary" to="/recruitHome">{{ $t('common.toHome') }}</v-btn>
+          <v-btn v-if="applyInfo.status === '2'" class="mt-16 buttons" color="primary" @click="handleConfirm">{{ $t('common.resubmit') }}</v-btn>
         </div>
       </div>
     </v-card>

+ 11 - 10
src/views/recruit/entRegister/register.vue

@@ -2,7 +2,7 @@
   <div class="login-box py-5">
     <v-card class="pa-5" :class="isMobile? 'mobileBox' : 'default-width'" :elevation="isMobile? '0' : '3'">
       <!-- 标题 -->
-      <div class="mt-3">
+      <div class="mt-3" v-if="!isMobile">
         <v-btn v-if="pageType !== 'noLoginToRegister'" color="primary" variant="text" @click="router.push('/recruitHome')">{{ `<< 回到首页` }}</v-btn>
         <div v-else style="height: 30px;"></div>
       </div>
@@ -13,7 +13,7 @@
           <span>原因:{{ failureReason }}</span>
         </div>
         <!-- 标题 -->
-        <div class="mb-10 mt-n8" style="font-size: 22px; font-weight: bold; text-align: center;">{{ $t('enterprise.registeringNewEnterprise') }}</div>
+        <div class="mb-10" :class="isMobile ? 'mt-0': 'mt-n8'" style="font-size: 22px; font-weight: bold; text-align: center;">{{ $t('enterprise.registeringNewEnterprise') }}</div>
         <CtForm ref="CtFormRef" :items="formItems" style="width: 100%;">
           <template #businessLicense>
             <!-- 上传照片 -->
@@ -26,8 +26,8 @@
               <div class="file-box">
                 <Img 
                   class="mt-3" 
-                  v-model="licenseUrl" 
                   tips="上传图片" 
+                  :value="licenseUrl" 
                   :showSnackbar="false" 
                   @imgClick="showPreview = !showPreview" 
                   :showCursor="true" 
@@ -149,21 +149,21 @@ const formItems = ref({
     {
       type: 'text',
       key: 'contactName',
-      value: '林小姐',
+      value: '',
       label: '联系人姓名 *',
       rules: [v => !!v || '请输入联系人姓名']
     },
     {
       type: 'phoneNumber',
       key: 'phone',
-      value: '13229740091',
+      value: '',
       label: '联系电话 *',
       rules: [v => !!v || '请输入联系电话']
     },
     {
       type: 'text',
       key: 'email',
-      value: email ? email : 'lin@qq.com',
+      value: email ? email : '',
       label: '企业邮箱 *',
       rules: [
         value => {
@@ -179,7 +179,7 @@ const formItems = ref({
     {
       type: 'password',
       key: 'password',
-      value: 'Citu123456',
+      value: '',
       appendInnerIcon: 'mdi-eye-off-outline',
       label: '账户登录密码 *',
       placeholder: '请输入账户登录密码',
@@ -198,7 +198,7 @@ const formItems = ref({
     {
       type: 'password',
       key: 'passwordConfirm',
-      value: 'Citu123456',
+      value: '',
       appendInnerIcon: 'mdi-eye-off-outline',
       label: '请再次输入账户登录密码 *',
       placeholder: '请再次输入账户登录密码',
@@ -290,11 +290,11 @@ if (info && Object.keys(info).length && info.status === '2') {
   failureReason.value = info?.reason || ''
   licenseUrl.value = info?.businessLicenseUrl
   // prepareValue.value = info?.prepare || false
-  isPrepareChange()
   formItems.value.options.forEach(e => {
     if (e.key === 'passwordConfirm') e.value = info.password
     else e.value = info[e.key]
   })
+  isPrepareChange()
 }
 
 </script>
@@ -352,7 +352,8 @@ if (info && Object.keys(info).length && info.status === '2') {
   margin-left: 32px;
 }
 .mobileBox {
-  width: 100vw;
+  width: calc(100vw - 16px);
+  margin: 0 auto;
   .resume-header {
     margin-bottom: 12px;
   }

+ 4 - 2
src/views/recruit/enterprise/hirePosition/components/item.vue

@@ -32,11 +32,13 @@
       <div class="bottom pa-5 d-flex justify-space-between align-center">
         <div>
           {{ $t('position.refreshTime') }} :{{ timesTampChange(val.updateTime, 'Y-M-D') }}
-          <span v-if="val.expireDay && Number(val.expireDay) > 0">({{ val.expireDay }}天后到期)</span>
+          <span v-if="val.expireTime">
+            <span class="septal-line"></span>
+            到期时间:{{ timesTampChange(val.expireTime, 'Y-M-D') }}
+          </span>
         </div>
         <div class="d-flex align-center">
           <span v-if="(val.status-0) === 99" class="cursor-pointer color-primary" @click="toPay(val)">去支付</span>
-          <span v-if="(val.status-0) === 99" class="lines"></span>
           <span v-if="(val.status - 0) !== 99 && val.status !== '1'" class="cursor-pointer actions" @click="handleAction(0, val)">{{ $t('common.close') }}</span>
           <span v-if="(val.status - 0) !== 99 && val.status !== '1'" class="lines"></span>
           <span v-if="tab === 1" class="cursor-pointer" @click="handleEdit(val)">编辑</span>

+ 10 - 8
src/views/recruit/enterprise/hirePosition/components/jobRequirements.vue

@@ -83,13 +83,13 @@ const items = ref({
       type: 'autocomplete',
       key: 'eduType',
       value: null,
-      label: '最高学历 *',
+      label: '要求学历 *',
       itemText: 'label',
       itemValue: 'value',
       col: 4,
       flexStyle: 'mx-3',
       dictTypeName: 'menduner_education_type',
-      rules: [v => !!v || '请选择最高学历'],
+      rules: [v => !!v || '请选择要求学历'],
       items: []
     },
     {
@@ -121,8 +121,9 @@ const items = ref({
           return '数额不得小于1'
         },
         value => {
-          if (value < items.value.options.find(e => e.key === 'payTo').value) return true
-          return '不得大于最高薪资'
+          const payTo = items.value.options.find(e => e.key === 'payTo').value
+          if (Number(value) < payTo ? Number(payTo) : 0) return true
+          return '应低于最高薪资'
         }
       ]
     },
@@ -144,8 +145,9 @@ const items = ref({
           return '数额不得小于1'
         },
         value => {
-          if (value > items.value.options.find(e => e.key === 'payFrom').value) return true
-          return '不得小于最高薪资'
+          const payFrom = items.value.options.find(e => e.key === 'payFrom').value
+          if (Number(value) > payFrom ? Number(payFrom) : 0) return true
+          return '应高于最低薪资'
         }
       ]
     },
@@ -153,12 +155,12 @@ const items = ref({
       type: 'autocomplete',
       key: 'payUnit',
       value: null,
-      label: '薪酬单位 *',
+      label: '计薪时段 *',
       itemText: 'label',
       itemValue: 'value',
       col: 4,
       dictTypeName: 'menduner_pay_unit',
-      rules: [v => !!v || '请选择薪酬单位'],
+      rules: [v => !!v || '请选择计薪时段'],
       items: []
     },
     {

+ 3 - 1
src/views/recruit/enterprise/interviewManagement/components/invite.vue

@@ -34,7 +34,9 @@ const props = defineProps({
 
 // 过去的日期不可选
 const disabledDates = (date) => {
-  return date.getTime() < new Date().getTime()
+  const currentDate = new Date()
+  currentDate.setDate(currentDate.getDate() - 1)
+  return date.getTime() < currentDate.getTime()
 }
 
 const CtFormRef = ref()

+ 1 - 1
src/views/recruit/enterprise/membershipPackage/components/package.vue

@@ -34,7 +34,7 @@
     <div class="scan color-666 d-flex flex-column align-center mt-5">
       <div class="font-weight-bold">微信扫一扫</div>
       <div class="font-size-15 my-3">高级客户经理为您报价(扫码后可电话联系)</div>
-      <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/static/mendunerCode.jpg" width="170" height="170"></v-img>
+      <v-img cover aspect-ratio="1/1" src="https://minio.citupro.com/dev/menduner/official-account-code4.jpg" width="170" height="170"></v-img>
     </div>
   </div>
 

+ 3 - 1
src/views/recruit/enterprise/personnelManagement/components/invite.vue

@@ -30,7 +30,9 @@ const props = defineProps({
 
 // 过去的日期不可选
 const disabledDates = (date) => {
-  return date.getTime() < new Date().getTime()
+  const currentDate = new Date()
+  currentDate.setDate(currentDate.getDate() - 1)
+  return date.getTime() < currentDate.getTime()
 }
 
 const CtFormRef = ref()

+ 1 - 0
src/views/recruit/enterprise/personnelManagement/components/table.vue

@@ -7,6 +7,7 @@
       hover
       :disable-sort="true"
       height="60vh"
+      no-data-text="暂无数据"
       item-value="id"
     >
       <template #bottom></template>

+ 4 - 1
src/views/recruit/enterprise/positionManagement/components/item.vue

@@ -46,7 +46,10 @@
       <div class="bottom pa-5 d-flex justify-space-between align-center">
         <div>
           {{ $t('position.refreshTime') }} :{{ timesTampChange(val.updateTime, 'Y-M-D') }}
-          <span v-if="val.expireDay && Number(val.expireDay) > 0">({{ val.expireDay }}天后到期)</span>
+          <span v-if="val.expireTime">
+            <span class="septal-line"></span>
+            到期时间:{{ timesTampChange(val.expireTime, 'Y-M-D') }}
+          </span>
         </div>
         <div class="d-flex">
           <div class="ml-10 d-flex">

+ 13 - 11
src/views/recruit/enterprise/positionManagement/components/jobRequirements.vue

@@ -83,13 +83,13 @@ const items = ref({
       type: 'autocomplete',
       key: 'eduType',
       value: null,
-      label: '最高学历 *',
+      label: '学历要求 *',
       itemText: 'label',
       itemValue: 'value',
       col: 4,
       flexStyle: 'mx-3',
       dictTypeName: 'menduner_education_type',
-      rules: [v => !!v || '请选择最高学历'],
+      rules: [v => !!v || '请选择学历要求'],
       items: []
     },
     {
@@ -105,7 +105,7 @@ const items = ref({
       items: []
     },
     {
-      type: 'text',
+      type: 'number',
       key: 'payFrom',
       value: '',
       col: 4,
@@ -121,15 +121,16 @@ const items = ref({
           return '数额不得小于1'
         },
         value => {
-          if (value < items.value.options.find(e => e.key === 'payTo').value) return true
-          return '不得大于最高薪资'
+          const payTo = items.value.options.find(e => e.key === 'payTo').value
+          if (Number(value) < payTo ? Number(payTo) : 0) return true
+          return '应低于最高薪资'
         }
       ]
     },
     {
-      type: 'text',
+      type: 'number',
       key: 'payTo',
-      value: '10',
+      value: '',
       col: 4,
       label: '最高薪资 *',
       flexStyle: 'mx-3',
@@ -144,8 +145,9 @@ const items = ref({
           return '数额不得小于1'
         },
         value => {
-          if (value > items.value.options.find(e => e.key === 'payFrom').value) return true
-          return '不得小于最高薪资'
+          const payFrom = items.value.options.find(e => e.key === 'payFrom').value
+          if (Number(value) > payFrom ? Number(payFrom) : 0) return true
+          return '应高于最低薪资'
         }
       ]
     },
@@ -153,12 +155,12 @@ const items = ref({
       type: 'autocomplete',
       key: 'payUnit',
       value: null,
-      label: '薪酬单位 *',
+      label: '计薪时段 *',
       itemText: 'label',
       itemValue: 'value',
       col: 4,
       dictTypeName: 'menduner_pay_unit',
-      rules: [v => !!v || '请选择薪酬单位'],
+      rules: [v => !!v || '请选择计薪时段'],
       items: []
     },
     {

+ 3 - 1
src/views/recruit/enterprise/resume/components/invite.vue

@@ -32,7 +32,9 @@ const props = defineProps({
 
 // 过去的日期不可选
 const disabledDates = (date) => {
-  return date.getTime() < new Date().getTime()
+  const currentDate = new Date()
+  currentDate.setDate(currentDate.getDate() - 1)
+  return date.getTime() < currentDate.getTime()
 }
 
 const CtFormRef = ref()

+ 10 - 10
src/views/recruit/enterprise/resume/components/table.vue

@@ -8,6 +8,7 @@
       :disable-sort="true"
       height="60vh"
       item-value="id"
+      no-data-text="暂无数据"
     >
       <template #bottom></template>
       <template v-slot:[`item.name`]="{ item }">
@@ -93,20 +94,18 @@ const headers = ref([
   { title: '状态', key: 'status', sortable: false },
   { title: '操作', value: 'actions', sortable: false }
 ])
-const unfit = { title: '类型', key: 'unfitType', sortable: false, value: item => item.type === '0' ? '简历不适合' : '面试不适合' }
-const delivery = { title: '类型', key: 'deliveryType', sortable: false, value: item => item.type === '0' ? '普通职位' : '赏金职位' }
+const unfit = { title: '类型', key: 'unfitType', sortable: false, value: item => item.type && item.type === '0' ? '简历不适合' : '面试不适合' }
+const delivery = { title: '类型', key: 'deliveryType', sortable: false, value: item => item?.job?.hire ? '赏金职位' : '普通职位' }
 
-const list = [0, 4]
 watch(
   () => props.tab,
   (val) => {
-    if (list.indexOf(val) !== -1) {
-      headers.value.splice(-1, 0, val === 0 ? delivery : unfit)
-    } else {
-      const index = headers.value.indexOf(item => item.key === val === 0 ? 'deliveryType' : 'unfitType')
-      if (index !== -1) headers.value.splice(index, 1)
-    }
-  // 不合适不需要展示状态
+    const obj = val !== 4 ? delivery : unfit
+    const index = headers.value.indexOf(obj)
+    if (index === -1) headers.value.splice(-1, 0, obj)
+    else headers.value.splice(index, 1)
+
+    // 不合适不需要展示状态
     if (val === 4) {
       const obj = headers.value.find(e => e.key === 'status')
       const i = headers.value.indexOf(obj)
@@ -164,6 +163,7 @@ const handleCancelEliminate = async (item) => {
 const handlePreviewResume = async ({ url, id }) => {
   if (!url || !id) return
   await personJobCvLook(id)
+  emit('refresh')
   previewFile(url)
 }
 

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

@@ -30,9 +30,9 @@
           <span class="defaultLink ml-3 mt-2">{{ item?.name }}</span>
         </div>
       </template>
-      <template #actions="{ item }">
+      <!-- <template #actions="{ item }">
         <v-btn color="primary" variant="text" @click="handleCommunicate(item)">立即沟通</v-btn>
-      </template>
+      </template> -->
     </CtTable>
   </div>
 </template>
@@ -42,20 +42,20 @@ 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 { 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 router = useRouter()
 const query = ref({
   pageNo: 1,
   pageSize: 10,
   jobId: null
 })
 const selectItems = ref({
-  label: '推荐的职位',
-  placeholder: '请选择要进行推荐的职位',
+  label: '已发布职位',
+  placeholder: '请选择已发布职位',
   clearable: true,
   width: 600,
   items: []
@@ -72,7 +72,7 @@ const headers = ref([
   { 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 }
+  // { title: '操作', key: 'actions', sortable: false }
 ])
 
 // 职位列表
@@ -103,7 +103,7 @@ const getData = async () => {
     loading.value = false
   }
 }
-getData()
+// getData()
 
 // 推荐
 const handleChange = () => {
@@ -118,12 +118,12 @@ const handleChangePage = (e) =>{
 }
 
 // 立即沟通
-const handleCommunicate = async (item) => {
-  const userId = item.userId
-  await talkToUser({userId, text: defaultTextEnt})
-  let url = `/recruit/enterprise/chatTools?id=${userId}`
-  router.push(url)
-}
+// 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 }) => {

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

@@ -50,9 +50,9 @@
           <span class="defaultLink ml-3 mt-2">{{ item?.name }}</span>
         </div>
       </template>
-      <template #actions="{ item }">
+      <!-- <template #actions="{ item }">
         <v-btn color="primary" variant="text" @click="handleCommunicate(item)">立即沟通</v-btn>
-      </template>
+      </template> -->
     </CtTable>
   </div>
 </template>
@@ -67,10 +67,10 @@ 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'
+// import { talkToUser, defaultTextEnt } from '@/hooks/web/useIM'
+// import { useRouter } from 'vue-router'
 
-const router = useRouter()
+// const router = useRouter()
 const textItem = ref({
   type: 'text',
   width: 600,
@@ -103,7 +103,7 @@ const headers = ref([
   { 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 }
+  // { title: '操作', key: 'actions', sortable: false }
 ])
 
 const getData = async () => {
@@ -151,12 +151,12 @@ const handleClear = () => {
 }
 
 // 立即沟通
-const handleCommunicate = async (item) => {
-  const userId = item.userId
-  await talkToUser({userId, text: defaultTextEnt})
-  let url = `/recruit/enterprise/chatTools?id=${userId}`
-  router.push(url)
-}
+// 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 }) => {

+ 1 - 0
src/views/recruit/enterprise/systemManagement/groupAccount/components/record.vue

@@ -6,6 +6,7 @@
       color="#00897B"
       :items="tableData"
       :headers="headers"
+      no-data-text="暂无数据"
     >
       <template #bottom>
         <CtPagination

+ 1 - 1
src/views/recruit/enterprise/systemManagement/groupAccount/inviteConfirm.vue

@@ -2,7 +2,7 @@
   <div style="background-color: #f0f0f0;">
     <div class="inviteView text-center" :style="{'width': isMobile ? '100%' : '750px'}">
       <div class="invite-title">
-        <div style="color: var(--v-primary-base);" class="mb-3">【门墩儿聘企业邀请】</div>
+        <div style="color: var(--v-primary-base);" class="mb-3">【门墩儿聘企业邀请】</div>
         <div style="font-size: 24px">
           <span class="color-333">{{ enterpriseInfo.name }}</span>
           <span class="color-333"> 邀请您加入 </span>

+ 1 - 1
src/views/recruit/enterprise/systemManagement/groupAccount/inviteConfirmEnt.vue

@@ -2,7 +2,7 @@
   <div style="background-color: #f0f0f0;">
     <div class="inviteView text-center" :style="{'width': isMobile ? '100%' : '750px'}">
       <div class="invite-title">
-        <div style="color: var(--v-primary-base);" class="mb-3">【门墩儿聘集团邀请】</div>
+        <div style="color: var(--v-primary-base);" class="mb-3">【门墩儿聘集团邀请】</div>
         <div style="font-size: 24px">
           <span class="color-333">{{ enterpriseInfo.name }}</span>
           <span class="color-333"> 邀请您加入 </span>

+ 1 - 1
src/views/recruit/enterprise/systemManagement/postManagement/index.vue

@@ -41,7 +41,7 @@ const headers = [
   { title: '岗位名称', key: 'nameCn', sortable: false },
   { title: '英文名称', key: 'nameEn', sortable: false },
   { title: '岗位缩写', key: 'code', sortable: false },
-  { title: '显示顺序', key: 'sort', sortable: false },
+  { title: '岗位级别', key: 'sort', sortable: false },
   { title: '状态', key: 'status', value: item => item.status === '1' ? '停用' : '正常', sortable: false },
   { title: '备注', key: 'remark', sortable: false },
   { title: '更新时间', key: 'updateTime', value: item => timesTampChange(item.updateTime), sortable: false },

+ 2 - 2
src/views/recruit/enterprise/systemManagement/postManagement/save.vue

@@ -58,8 +58,8 @@ const items = ref({
       type: 'number',
       key: 'sort',
       value: null,
-      label: '显示顺序 *',
-      rules: [v => !!v || '请填写显示顺序']
+      label: '岗位级别 *',
+      rules: [v => !!v || '请填写岗位级别']
     },
     {
       type: 'text',

+ 1 - 0
src/views/recruit/enterprise/systemManagement/userManagement/index.vue

@@ -11,6 +11,7 @@
       hide-default-header
       height="70vh"
       item-value="id"
+      no-data-text="暂无数据"
     >
       <template #bottom></template>
       <template v-slot:item.actions="{ item }">

+ 152 - 51
src/views/recruit/enterprise/talentMap/index.vue

@@ -1,19 +1,65 @@
 <template>
   <v-card class="card-box pa-5" style="height: 100%;">
-    <div class="d-flex justify-center">
-      <TextUI v-model="query.content" :item="textItem" @click="openDrawer" @appendInnerClick="openDrawer"></TextUI>
-      <!-- <v-btn color="primary" class="half-button" variant="tonal" @click="openDrawer">职位匹配</v-btn> -->
+    <div class="d-flex flex-column align-center" :class="{'v-center': init}">
+      <TextUI
+        v-model="content"
+        :item="textItem"
+        @keyup.enter="handleConfirm"
+        @appendInnerClick="handleConfirm"
+      ></TextUI>
+      <div class="align-center">
+        <template v-if="init && defaultLabelsShow?.length">
+          <v-btn
+            v-for="(val, index) in defaultLabelsShow" :key="val + index"
+            class="mr-3 my-2 py-0 px-2"
+            density="comfortable"
+            color="primary" variant="tonal"
+            v-bind="props"
+            @click="clickChip(index)"
+          >
+            {{ val }}
+          </v-btn>
+          <!-- <v-btn class="ml-0 my-1 py-0 px-2" density="comfortable" variant="tonal" color="error" @click="moreLabels">
+            更多人才标签...
+          </v-btn> -->
+        </template>
+      </div>
     </div>
+    <template v-if="!init">
+      <span class="mr-2 color-666" style="width: 68px; min-width: 68px;">人才标签:</span>
+      <v-btn
+        v-for="(val, index) in chosenLabels" :key="val + index"
+        class="mr-3 my-2 py-0 px-2"
+        density="comfortable"
+        color="primary" variant="tonal"
+        v-bind="props"
+      >
+        {{ val }}
+        <v-icon class="ml-1" style="margin-top: 1px;" @click="deleteChip(index)">mdi-close</v-icon>
+      </v-btn>
+      <v-btn
+        class="mr-3 my-2 py-0 px-0"
+        density="comfortable"
+        color="primary" variant="tonal"
+        @click="moreLabels"
+      >
+        <!-- {{ chosenLabels?.length ? '选择其他人才标签' : '人才标签'}} -->
+        <v-icon>mdi-plus-box</v-icon>
+      </v-btn>
+      <span v-if="chosenLabels?.length" class="my-2" style="font-size: 14px;cursor: pointer;color: var(--color-999);" @click="resetLabel">清空标签</span>
+    </template>
     <!-- 人员信息表单 -->
     <v-data-table
+      v-if="dataList?.length"
       class="mt-3"
       :items="dataList"
       :headers="headers"
       hover
       :disable-sort="true"
       :loading="loading"
-      loading-text="Loading... Please wait"
+      loading-text="加载中..."
       item-value="id"
+      no-data-text="暂无数据"
     >
       <template #bottom></template>
       <template v-slot:[`item.name`]="{ item }">
@@ -30,11 +76,6 @@
           <span class="defaultLink ml-3">{{ item?.name }}</span>
         </div>
       </template>
-      <template v-slot:[`item.advantage`]="{ item }">
-        <template v-if="item.advantage">
-          <v-btn color="primary" variant="text" @click="advantageDetail(item.advantage)">查看TA的优势</v-btn>
-        </template>
-      </template>
       <template v-slot:[`item.actions`]="{ item }">
         <v-btn color="primary" variant="text" @click="talentPoolDetails(item)">查看</v-btn>
       </template>
@@ -46,40 +87,30 @@
       :limit="pageInfo.pageSize"
       @handleChange="handleChangePage"
     ></CtPagination>
-    <!-- <Empty v-else :message="tipsText" :elevation="false" class="mt-15"></Empty> -->
-    <v-navigation-drawer v-model="screen" location="right" absolute temporary width="700">
-      <FilterPage
-        ref="FilterPageRef"
-        @confirm="handleConfirm"
-        @cancel="screen = false"
-      ></FilterPage>
-    </v-navigation-drawer>
-    <v-navigation-drawer v-model="advantageShow" location="right" absolute temporary width="800">
-      <div class="pa-3">
-        <div class="resume-header">
-          <div class="resume-title">个人优势</div>
-        </div>
-        <div class="requirement" v-html="advantageText?.replace(/\n/g, '</br>')"></div>
-      </div>
-    </v-navigation-drawer>
+    <Empty v-if="!init && !total" :message="tipsText" :elevation="false" class="mt-15"></Empty>
   </v-card>
+  <CtDialog :visible="showMore" titleClass="text-h6" title="选择人才标签" @close="showMore = false" @submit="handleSubmit">
+    <div style="width: 80%; margin: 0 auto; min-height: 400px;">
+      <CtForm :items="formItems" style="width: 100%;"></CtForm>
+    </div>
+  </CtDialog>
 </template>
 
 <script setup>
 defineOptions({ name: 'enterprise-talent-map'})
 import { getRecruitPersonMapPage } from '@/api/recruit/enterprise/resumeManagement/talentMap'
+import { getRocketLabelList } from '@/api/recruit/enterprise/resumeManagement/talentMap'
 import { dealDictArrayData } from '@/utils/position'
 import { getUserAvatar } from '@/utils/avatar'
 import { timesTampChange } from '@/utils/date'
-import FilterPage from './components/filter.vue'
 import TextUI from '@/components/FormUI/TextInput'
+import Snackbar from '@/plugins/snackbar'
 
 import { computed, reactive, ref } from 'vue'
 
-const screen = ref(false)
 const loading = ref(false)
 
-let query = {}
+const content = ref('')
 const pageInfo = reactive({ pageNo: 1, pageSize: 10 })
 const dataList = ref([])
 const total = ref(0)
@@ -95,23 +126,91 @@ const headers = [
   { title: '所在城市', key: 'areaName', sortable: false },
   { title: '户籍地', key: 'regName', sortable: false },
   { title: '首次工作时间', key: 'firstWorkTime', sortable: false, value: item =>  timesTampChange(item.firstWorkTime, 'Y-M-D') },
-  { title: '个人优势', key: 'advantage', sortable: false },
+  // { title: '个人优势', key: 'advantage', sortable: false },
   { title: '工作年限', key: 'expName', sortable: false },
   { title: '最高学历', key: 'eduName', sortable: false },
   { title: '操作', value: 'actions', sortable: false }
 ]
 
+const init = ref(true)
+const labelList = ref([])
+const chosenLabels = ref([])
+const defaultLabelsShow = ref([])
+// 人才标签
+const getLabelData = async () => {
+  const res = await getRocketLabelList({ current: 1, size:9999, type: 'person' }) //type: job  enterprise person
+  labelList.value = res?.records?.length ? res.records : []
+  defaultLabelsShow.value = labelList.value?.length ? labelList.value.slice(0, 15) : [] // 默认展示且没有删除按钮
+  //
+  const labelsItem = formItems.value.options.find(f => f.key === 'labels')
+  if (labelsItem) {
+    labelsItem.items = labelList.value?.length ? labelList.value.map(e => ({ label: e, value: e })) : []
+  }
+}
+getLabelData()
+
+const showMore = ref(false)
+const moreLabels = () => {
+  const labelsItem = formItems.value.options.find(f => f.key === 'labels')
+  if (labelsItem) {
+    labelsItem.value = chosenLabels.value
+  }
+  showMore.value = true
+}
+
+const clickChip = (index) => {
+  chosenLabels.value = [labelList.value[index]]
+  handleConfirm()
+}
+
+const deleteChip = (index) => {
+  chosenLabels.value.splice(index, 1)
+  handleConfirm()
+}
+
+const resetLabel = () => {
+  chosenLabels.value = []
+  handleConfirm()
+}
+
+const formItems = ref({
+  options: [
+    {
+      type: 'autocomplete',
+      key: 'labels',
+      value: null,
+      label: '人才标签 ',
+      multiple: true,
+      outlined: true,
+      itemText: 'label',
+      itemValue: 'value',
+      clearable: true,
+      items: [
+        // { label: '标签', value: '0' },
+      ]
+    },
+  ]
+})
+const handleSubmit = () => {
+  const labelsItem = formItems.value.options.find(f => f.key === 'labels')
+  chosenLabels.value = labelsItem?.value?.length ? labelsItem.value : []
+  showMore.value = false
+  handleConfirm()
+}
+
 // 获取数据
 const getData = async () => {
-  const obj = { ...pageInfo, ...query }
-  // console.log('obj', obj)
   loading.value = true
+  init.value = false
+  const obj = { ...pageInfo, content: content.value }
+  if (chosenLabels.value?.length) obj.labels = chosenLabels.value
+  //
   const res = await getRecruitPersonMapPage(obj)
   total.value = res?.total ? res.total-0 : 0
   dataList.value = res?.list?.length ? dealDictArrayData([], res?.list) : []
   loading.value = false
 }
-getData()
+// getData()
 
 const handleChangePage = (e) => {
   pageInfo.pageNo = e
@@ -119,26 +218,17 @@ const handleChangePage = (e) => {
 }
 
 // 筛选
-const handleConfirm = (params) => {
-  screen.value = false
+const handleConfirm = () => {
+  if (!chosenLabels.value?.length && !content.value) { // && init.value
+    Snackbar.warning('请先输入内容或选择人才标签!')
+    init.value = true
+    dataList.value = []; total.value = 0
+    return
+  }
   pageInfo.pageNo = 1
-  query = { ...params }
   getData()
 }
 
-const advantageShow = ref(false)
-let advantageText = ''
-const advantageDetail = (advantage) => {
-  advantageText = advantage
-  advantageShow.value = true
-}
-
-const FilterPageRef = ref()
-const openDrawer = () => {
-  screen.value = true
-  FilterPageRef.value?.open(query)
-}
-
 const badgeColor = computed(() => (item) => {
   return (item && item.sex) ? (item.sex === '1' ? '#1867c0' : 'error') : 'error'
 })
@@ -149,11 +239,13 @@ const badgeIcon = computed(() => (item) => {
 
 const textItem = ref({
   type: 'text',
-  width: 600,
+  width: 1000,
   value: '',
-  label: '职位匹配',
+  // label: '职位匹配',
+  label: '请输入职位匹配相关内容',
+  placeholder: '回车开始人才匹配',
   clearable: false,
-  readonly: true,
+  // readonly: true,
   appendInnerIcon: 'mdi-magnify'
 })
 
@@ -172,6 +264,15 @@ const talentPoolDetails = ({ userId, id }) => {
 :deep(.v-selection-control__input) {
   color: var(--v-primary-base) !important;
 }
+.card-box {
+  position: relative;
+  .v-center {
+    position: absolute;
+    top: 40%;
+    left: 50%;
+    translate: -50% -50%;
+  }
+}
 .requirementBox {
   width: 150px;
   height: 28px;

+ 35 - 17
src/views/recruit/enterprise/talentPool/components/details.vue

@@ -39,25 +39,20 @@
         <span class="mr-6">{{ $t('resume.educationExp') }}</span>
         <educationExp style="flex: 1;" :data="cvData.eduList"></educationExp>
       </div>
-      <!-- 附件简历 -->
-      <!-- <div class="d-flex mt-8">
-        <span class="mr-6">{{ $t('resume.attachmentResume') }}</span>
-        <attachmentResume style="flex: 1;"></attachmentResume>
-      </div> -->
     </div>
-    <!-- <div class="operate pa-3">
+    <div class="operate pa-3">
       <v-list>
-        <v-list-subheader class="title">简历助手</v-list-subheader>
+        <v-list-subheader class="title">操作</v-list-subheader>
         <v-list-item
-          v-for="(item, i) in operateItems" :key="'简历助手' + i"
+          v-for="(item, i) in operateItems" :key="'操作' + i"
           color="primary"
           :prepend-icon="item.icon"
           :title="item.text"
-          @click="{}"
+          @click="handleCommunicate(item)"
         >
         </v-list-item>
       </v-list>
-    </div> -->
+    </div>
   </div>
 </template>
 
@@ -73,17 +68,20 @@ import educationExp from './details/educationExp.vue'
 // import attachmentResume from './details/attachmentResume.vue'
 import { getPersonCvDetail } from '@/api/enterprise'
 import { ref } from 'vue'
+import { talkToUser, defaultTextEnt } from '@/hooks/web/useIM'
 import { useRouter, useRoute } from 'vue-router'
+import { getJobAdvertisedList } from '@/api/position'
+import Snackbar from '@/plugins/snackbar'
 
 const route = useRoute()
 const router = useRouter()
-// const operateItems = [
-//   { text: '邀请面试', icon: 'mdi-account-check' },
-//   { text: '不合适', icon: 'mdi-close-circle-outline' },
-//   { text: '发起对话', icon: 'mdi-chat-processing-outline' },
-//   { text: '加入人才库', icon: 'mdi-tab-plus' },
-//   { text: '操作记录', icon: 'mdi-clock-edit-outline' },
-// ]
+const operateItems = [
+  // { text: '邀请面试', icon: 'mdi-account-check' },
+  // { text: '不合适', icon: 'mdi-close-circle-outline' },
+  { text: '立即沟通', icon: 'mdi-chat-processing-outline' },
+  // { text: '加入人才库', icon: 'mdi-tab-plus' },
+  // { text: '操作记录', icon: 'mdi-clock-edit-outline' },
+]
 
 // 获取人才详情
 const cvData = ref({})
@@ -96,6 +94,26 @@ const getCvDetail = async () => {
 }
 getCvDetail()
 
+// 职位列表
+const jobNum = ref(0)
+const getJobList = async () => {
+  const { total } = await getJobAdvertisedList({ pageNo: 1, pageSize: 10, hasExpiredData: false, status: 0 })
+  jobNum.value = total
+}
+getJobList()
+
+// 立即沟通
+const handleCommunicate = async (item) => {
+  if (item.text !== '立即沟通') return
+  // 企业必须有招聘中的职位才能发起沟通
+  if (jobNum.value === 0) return Snackbar.warning('请先发布职位')
+  const userId = cvData.value.person.userId
+  if (!userId) return
+  await talkToUser({userId, text: defaultTextEnt})
+  let url = `/recruit/enterprise/chatTools?id=${userId}`
+  router.push(url)
+}
+
 </script>
 <style lang="scss" scoped>
 .operate {

+ 2 - 5
src/views/recruit/enterprise/talentPool/index.vue

@@ -4,7 +4,6 @@
       <div></div>
       <v-btn color="primary" prependIcon="mdi-filter-multiple-outline" class="half-button" variant="tonal" @click="openDrawer">筛选</v-btn>
     </div>
-    <div v-if="dataList?.length" class="mt-3">
       <v-data-table
         class="mt-3"
         :items="dataList"
@@ -12,6 +11,7 @@
         hover
         :disable-sort="true"
         item-value="id"
+        no-data-text="暂无数据"
       >
         <template #bottom></template>
         <template v-slot:[`item.name`]="{ item }">
@@ -35,17 +35,15 @@
         </template>
         <template v-slot:[`item.actions`]="{ item }">
           <v-btn color="primary" variant="text" @click="handleRemove(item)">移除</v-btn>
-          <v-btn color="primary" variant="text" @click="talentPoolDetails(item)">人才详情</v-btn>
         </template>
       </v-data-table>
       <CtPagination
+        v-if="total > 0"
         :total="total"
         :page="pageInfo.pageNo"
         :limit="pageInfo.pageSize"
         @handleChange="handleChangePage"
       ></CtPagination>
-    </div>
-    <Empty v-else :message="tipsText" :elevation="false" class="mt-15"></Empty>
 
     <v-navigation-drawer v-model="screen" location="right" absolute temporary width="700">
       <FilterPage
@@ -76,7 +74,6 @@ let query = {}
 const screen = ref(false)
 const dataList = ref([])
 // dataList.value = [] // 暂定无数据展示
-const tipsText = ref('暂无数据')
 const total = ref(2)
 const pageInfo = reactive({ pageNo: 1, pageSize: 10 })
 

+ 206 - 0
src/views/recruit/enterprise/talentRecommendation/components/filter.vue

@@ -0,0 +1,206 @@
+<template>
+  <div style="max-height: 80vh;">
+    <div class="d-flex align-center mt-5">
+      <TextInput v-model="textItem.value" :item="textItem" @appendInnerClick="handleSearch"></TextInput>
+      <span class="pl-6 color-666" style="width: 60px; min-width: 60px;" @click="emit('close')">取消</span>
+    </div>
+    <v-divider class="my-3"></v-divider>
+    <!-- 地区 -->
+    <!-- <div>
+      <div class="mb-2 font-size-20">地区</div>
+      <div class="color-666">
+        <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs" :close-on-content-click="false">
+          <template v-slot:activator="{  props }">
+            <div>
+              <v-chip v-for="k in areaSelect" :key="k.id" class="mr-3 mb-1" 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>
+            </div>
+          </template>
+          <AreaSelect :isMobile="true" :select="areaSelectData" :currentData="areaSelect" :limit="false" showSelect @handleClick="handleArea"></AreaSelect>
+        </v-menu>
+      </div>
+    </div> -->
+    <!-- 职位 -->
+    <div class="my-3">
+      <div class="mb-2 font-size-20">职位</div>
+      <div class="d-flex font-size-14 flex-wrap">
+        <div v-for="val in items" :key="val.id" class="mr-2 tag mb-2" :class="{'active': val.active}" @click="handleFirst(val)">{{ val.nameCn }}</div>
+      </div>
+      <div v-if="children.length" class="mt-1 font-size-14 d-flex flex-wrap triangle-container pa-3">
+        <div 
+          v-for="k in children" 
+          :key="k.id" 
+          class="second-tag mr-2 mb-2" 
+          :class="{'active': select.findIndex(e => e.id === k.id) !== -1}"
+          @click="handleSecond(k)"
+        >{{ k.nameCn }}</div>
+      </div>
+    </div>
+    <!-- 最高学历、工作经验 -->
+    <div v-for="val in list" :key="val.key" class="mb-3">
+      <div class="mb-2 font-size-20">{{ val.title }}</div>
+      <v-chip-group v-model="val.value" selected-class="text-primary" mandatory @update:modelValue="e => val.value = e" class="flex-wrap color-666">
+        <v-chip v-for="val in val.items" :key="val.id" :text="val.label" :value="val.value" label filter></v-chip>
+      </v-chip-group>
+    </div>
+    <div class="white-bgc pb-5" style="position: sticky; bottom: 0;">
+      <v-divider class="mb-5"></v-divider>
+      <div class="d-flex align-center">
+        <v-btn color="primary" variant="outlined" style="width: 100px;" @click="handleReset">重 置</v-btn>
+        <v-btn class="ml-5" color="primary" style="flex: 1;" @click="handleConfirm">确 定</v-btn>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'filterPage'})
+import { ref } from 'vue'
+import { getDict } from '@/hooks/web/useDictionaries'
+
+const emit = defineEmits(['close', 'search'])
+const textItem = ref({
+  type: 'text',
+  value: '',
+  label: '请输入关键词搜索',
+  clearable: false,
+  hideDetails: true,
+  appendInnerIcon: 'mdi-magnify'
+})
+const query = ref({
+  content: '',
+  positionIds: [],
+  areaIds: [],
+  expType: '',
+  eduType: ''
+})
+const list = ref([
+  {
+    title: '最高学历',
+    dictTypeName: 'menduner_education_type',
+    items: [],
+    value: -1,
+    key: 'eduType'
+  },
+  {
+    title: '工作经验',
+    dictTypeName: 'menduner_exp_type',
+    items: [],
+    value: -1,
+    key: 'expType'
+  }
+])
+list.value.forEach(e => {
+  getDict(e.dictTypeName).then(({ data }) => {
+    e.items = [{ value: -1, label: '不限' }, ...data] || []
+  })
+})
+
+// 职位树状
+const items = ref([])
+getDict('positionTreeData', {}, 'positionTreeData').then(({ data }) => {
+  if (!data) return
+  items.value = data.map(e => {
+    e.active = false
+    return e
+  })
+})
+const children = ref([])
+const handleFirst = (val) => {
+  if (val.active) {
+    val.active = false
+    children.value = []
+    select.value = select.value.filter(e => e.parentId !== val.id)
+    return
+  }
+  items.value.forEach(e => e.active = false)
+  val.active = !val.active
+  children.value = val.children || []
+}
+const handleSearch = () => {
+  query.value.content = textItem.value.value
+  emit('search', query.value)
+}
+const select = ref([])
+const handleSecond = (val) => {
+  const index = select.value.findIndex(e => e.id === val.id)
+  if (index !== -1) {
+    select.value.splice(index, 1)
+  } else select.value.push(val)
+  console.log(select.value, 'select')
+  // emit('select', select.value)
+}
+
+// 地区
+// const areaSelect = ref([])
+// const areaSelectData = ref([])
+// const handleArea = (list, arr) => {
+//   areaSelectData.value = list
+//   areaSelect.value = arr
+// }
+// const handleAreaClear = (k) => {
+//   areaSelectData.value = areaSelectData.value.filter(item => item !== k.id)
+//   const index = areaSelect.value.findIndex(item => item.id === k.id)
+//   if (index !== -1) areaSelect.value.splice(index, 1)
+// }
+
+// 重置
+const handleReset = () => {
+  query.value = {
+    content: '',
+    positionIds: [],
+    areaIds: [],
+    expType: '',
+    eduType: ''
+  }
+  // areaSelectData.value = []
+  // areaSelect.value = []
+  select.value = []
+  list.value.forEach(e => e.value = -1)
+  items.value.forEach(e => e.active = false)
+  emit('search', query.value)
+}
+const handleConfirm = () => {
+  query.value.content = textItem.value.value
+  // query.value.areaIds = areaSelectData.value
+  query.value.positionIds = select.value.map(e => e.id)
+  list.value.forEach(e => query.value[e.key] = e.value === -1 ? '' : e.value)
+  emit('search', query.value)
+}
+</script>
+
+<style scoped lang="scss">
+.active {
+  border: 1px solid var(--v-primary-base) !important;
+  color: var(--v-primary-base) !important;
+}
+.tag {
+  padding: 5px 15px;
+  border: 1px solid #d3d0d0;
+  border-radius: 5px;
+}
+.second-tag {
+  background-color: #fff;
+  color: #666;
+  padding: 5px 15px;
+  border-radius: 5px;
+}
+.triangle-container {
+  position: relative;
+  background-color: #f2f2f2;
+  &::after {  
+    content: "";  
+    position: absolute;  
+    left: 10%;
+    top: -19px;
+    margin-left: -5px;
+    border-width: 10px 10px 10px 10px;
+    border-style: solid;  
+    border-color: transparent transparent #f2f2f2 transparent;
+  }
+}
+:deep(.v-slide-group__content) {
+  width: 100% !important;
+  flex-wrap: wrap !important;
+}
+</style>

+ 48 - 16
src/views/recruit/enterprise/talentRecommendation/index.vue

@@ -2,7 +2,7 @@
   <div>
     <div v-if="!getToken(1)" class="login-content">
       <div class="login-content-box pa-10">
-        <div class="login-content-box-title text-center mt-4">请登录您的企业账号</div>
+        <div class="login-content-box-title text-center mt-4">请登录您的企业账号</div>
         <passwordFrom class="mt-10" ref="passRef" placeholder="请输入企业邮箱" :validEmail="true"></passwordFrom>
         <v-btn :loading="loading" color="primary" class="white--text mt-5" min-width="340" @click="handleLogin">登录</v-btn>
       </div>
@@ -10,7 +10,8 @@
     <div v-else class="content py-3" @scroll="handleScroll">
       <v-card class="py-3 px-5" :style="{'width': isMobile ? '100%' : '750px'}" style="min-height: calc(100vh - 24px); box-sizing: border-box; margin: 0 auto;">
         <div class="d-flex align-center" style="width: 340px; margin: auto;">
-          <Autocomplete v-model="query.jobId" :item="selectItems" @change="handleChange"></Autocomplete>
+          <!-- <Autocomplete v-model="query.jobId" :item="selectItems" @change="handleChange"></Autocomplete> -->
+          <TextInput v-model="textItem.value" :item="textItem" @click="openDrawer" @appendInnerClick="openDrawer"></TextInput>
         </div>
         <v-divider></v-divider>
         <div v-if="items.length">
@@ -23,21 +24,25 @@
                 <p class="font-size-20">{{ val.name }}</p>
                 <p class="color-999 font-size-16">
                   {{ val.jobStatusName }}
-                  <span v-if="val.jobStatusName && val.expType" class="septal-line"></span>
-                  {{ val.expType }}
-                  <span v-if="val.eduType" class="septal-line"></span>
-                  {{ val.eduType }}
+                  <span v-if="val.jobStatusName && val.expName" class="septal-line"></span>
+                  {{ val.expName }}
+                  <span v-if="val.eduName" class="septal-line"></span>
+                  {{ val.eduName }}
                 </p>
               </div>
             </div>
             <div class="bg-box" v-if="index !== items.length - 1"></div>
           </div>
         </div>
-        <Empty v-else :elevation="false" message="暂无数据,请更换搜索条件后再试"></Empty>
+        <Empty v-else :elevation="false" message="暂无数据"></Empty>
       </v-card>
     </div>
 
     <Loading :visible="loading"></Loading>
+
+    <v-navigation-drawer v-model="screen" location="top" temporary class="px-5" style="border-radius: 0 0 10px 10px;">
+      <FilterPage ref="filterRef" @close="screen = false" @search="handleSearch"></FilterPage>
+    </v-navigation-drawer>
   </div>
 </template>
 
@@ -49,10 +54,11 @@ import passwordFrom from '@/views/login/components/passwordPage.vue'
 import Snackbar from '@/plugins/snackbar'
 import { useUserStore } from '@/store/user'
 import { passwordLogin } from '@/api/common'
-import { getPersonRecommendPage, getJobAdvertised } from '@/api/enterprise'
+import { getJobAdvertised, getPersonSearchPage } from '@/api/enterprise'
 import { dealDictArrayData } from '@/utils/position'
 import { getUserAvatar } from '@/utils/avatar'
 import { useRouter } from 'vue-router'
+import FilterPage from './components/filter.vue'
 
 const router = useRouter()
 const loading = ref(false)
@@ -62,7 +68,7 @@ const total = ref(0)
 const query = ref({
   pageNo: 1,
   pageSize: 20,
-  jobId: null
+  // jobId: null
 })
 const selectItems = ref({
   label: '已发布职位',
@@ -71,6 +77,15 @@ const selectItems = ref({
   width: 600,
   items: []
 })
+const textItem = ref({
+  type: 'text',
+  width: 600,
+  value: '',
+  label: '输入关键词搜索',
+  clearable: false,
+  readonly: true,
+  appendInnerIcon: 'mdi-magnify'
+})
 
 // 已发布职位列表
 const getJobList = async () => {
@@ -97,7 +112,7 @@ const getData = async (isEmpty) => {
   // isEmpty:是否清空列表
   loading.value = true
   try {
-    const res = await getPersonRecommendPage(query.value)
+    const res = await getPersonSearchPage(query.value)
     const list = res.list || []
     items.value = list.length ? !isEmpty ? [...items.value, ...dealDictArrayData([], list)] : dealDictArrayData([], list) : []
     total.value = res.total
@@ -107,7 +122,7 @@ const getData = async (isEmpty) => {
     loading.value = false
   }
 }
-getData()
+// if (getToken(1)) getData()
 
 // 底部加载
 const handleScroll = (e) => {
@@ -120,10 +135,10 @@ const handleScroll = (e) => {
 }
 
 // 选择发布职位
-const handleChange = () => {
-  query.value.pageNo = 1
-  getData(true)
-}
+// const handleChange = () => {
+//   query.value.pageNo = 1
+//   getData(true)
+// }
 
 // 登录
 const handleLogin = async () => {
@@ -134,7 +149,7 @@ const handleLogin = async () => {
     const data = await passwordLogin({ ...passRef.value.loginData, account: passRef.value.loginData.phone })
     await useUserStore().changeRole({ ...data, type: 'emailLogin', noJump: true })
     await getJobList()
-    await getData()
+    // await getData()
   } catch (err) {
     Snackbar.warning(err.msg)
   } finally {
@@ -147,6 +162,23 @@ const handleDetail = ({ userId, id }) => {
   if (!userId || !id) return
   router.push(`/recruit/enterprise/talentRecommendation/details/${userId}?id=${id}`)
 }
+
+// 筛选
+const filterRef = ref()
+const screen = ref(false)
+const openDrawer = () => {
+  if (!getToken(1)) return
+  screen.value = true
+}
+
+const handleSearch = (val) => {
+  // console.log(val, 'search')
+  screen.value = false
+  textItem.value.value = val.content
+  query.value.pageNo = 1
+  query.value = Object.assign(query.value, val)
+  getData(true)
+}
 </script>
 
 <style scoped lang="scss">

+ 2 - 2
src/views/recruit/enterprise/tradingOrder/components/pointsAndBalance.vue

@@ -20,9 +20,9 @@
               <input
                 v-model="inputValue" 
                 type="text"
-                class="custom-input-num"
+                class="custom-input-num mr-1"
                 :placeholder="item.placeholder"
-              >
+              >
             </span>
             <span class="font28" v-else>¥{{ FenYuanTransform(item.payPrice) }}</span>
           </div>  

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

@@ -9,7 +9,7 @@
     </div>
 
     <div no-gutters class="mt-5 d-flex flex-wrap" style="width: 100%;">
-      <v-card v-for="(k, i) in list" :key="i" class="col-item" @click="handleOpen">
+      <v-card v-for="(k, i) in list" :key="i" class="col-item" @click="handleOpen(i)">
         <v-img :src="k.url"/>
       </v-card>
     </div>
@@ -25,7 +25,9 @@ const list = [
   { url: 'https://minio.citupro.com/dev/menduner/preferredGroup/Yifei.jpg' }
 ]
 
-const handleOpen = () => {
+const handleOpen = (index) => {
+  // 目前只有洲际有集团展示页面
+  if (index !== 1) return
   const id = 1
   window.open(`/recruit/personal/advertisement/introduce/${id}`)
 }

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

@@ -129,6 +129,7 @@ const carouselList = ref([
   { src: 'https://minio.citupro.com/dev/menduner/preferredGroup/IHG-banner-new.gif' },
   { 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' },
+  { src: 'https://minio.citupro.com/dev/menduner/preferredGroup/SWISS-HOTEL-MANAGEMENT-SCHOOL-MBA.jpg'},
   { src: 'https://minio.citupro.com/dev/menduner/preferredGroup/Hong-Kong-Polytechnic-University-banner.jpg' }
 ])
 </script>

+ 4 - 4
src/views/recruit/personal/home/components/hotJobs.vue

@@ -1,8 +1,8 @@
 <template>
-  <div class="default-width text-center mb-6 d-flex align-center">
-    <span class="mr-2 color-666" style="width: 100px;">{{ $t('position.popularPosition') }}:</span>
-    <div style="flex: 1; overflow: hidden; height: 40px; ">
-      <span v-for="(item, index) in jobs" :key="index" label size="small" class="ml-2 my-1 tag"  @click="handleClick(item)">{{ item.nameCn }}</span>
+  <div class="default-width mb-6 d-flex align-center justify-center">
+    <span class="mr-2 color-666" style="width: 68px; min-width: 68px;">{{ $t('position.popularPosition') }}:</span>
+    <div style="overflow: hidden; height: 40px; ">
+      <span v-for="(item, index) in jobs" :key="index" label size="small" class="mr-2 my-1 tag"  @click="handleClick(item)">{{ item.nameCn }}</span>
     </div>
   </div>
 </template>

+ 2 - 1
src/views/recruit/personal/home/components/popularEnterprises.vue

@@ -6,7 +6,8 @@
         <div class="home-title-line"></div>
       </div>
     </div>
-    <HotPromoted class="mt-5" :items="items"></HotPromoted>
+    <HotPromoted v-if="items.length" class="mt-5" :items="items"></HotPromoted>
+    <Empty v-else :elevation="false" class="mt-3" message="暂无精选企业"></Empty>
     <div v-if="items.length" class="text-center">
       <v-btn class="buttons btnColor" color="primary" to="/recruit/personal/company">{{ $t('enterprise.moreBtn') }}</v-btn>
     </div>

+ 12 - 6
src/views/recruit/personal/home/index.vue

@@ -6,12 +6,12 @@
       <headSearch @handleSearch="handleSearch"></headSearch>
     </div>
     <hotJobs></hotJobs>
-    <div class="advertise ml-3">
+    <div class="advertise">
       <div class="advertise-title">广告</div>
       <img class="advertise-img cursor-pointer" :src="advertiseUrl" @click="handleOpenAdvertise">
     </div>
-    <div class="default-width content-box">
-      <homeJobTypeCard></homeJobTypeCard>
+    <div class="common-width">
+      <homeJobTypeCard class="content-box"></homeJobTypeCard>
       <advertisementPage class="my-3"></advertisementPage>
       <hotPromotedPositions></hotPromotedPositions>
       <PopularEnterprises class="mt-10"></PopularEnterprises>
@@ -80,8 +80,8 @@ const handleOpenAdvertise = () => {
   position: sticky;
   top: 128px;
   z-index: 999;
-  width: 180px; 
-  height: 360px;
+  width: 120px; 
+  height: 310px;
   &-title {
     color: #000;
     font-size: 14px;
@@ -98,7 +98,7 @@ const handleOpenAdvertise = () => {
   }
 }
 .content-box {
-  margin-top: -360px;
+  margin-top: -310px;
 }
 .banner {
   width: 100%;
@@ -106,4 +106,10 @@ const handleOpenAdvertise = () => {
   background: url("@/assets/headerBg.jpg") no-repeat;
   background-size: contain;
 }
+.common-width {
+  width: 1160px;
+  max-width: 1160px;
+  min-width: 1160px;
+  margin: 0 auto;
+}
 </style>

+ 13 - 5
src/views/recruit/personal/position/components/details.vue

@@ -235,6 +235,15 @@ const formItems = ref({
   ]
 })
 
+// 打开快速登录
+const quickLogonOpen = () => {
+  // if (close) {
+  // } else {
+  // }
+  Snackbar.warning('您还未登录,请先登录后再试')
+  showLogin.value = true
+}
+
 const share = ref()
 // 生成图片
 const generateAndDownloadImage = async () => {
@@ -325,11 +334,7 @@ const shareUrl = ref('')
 const userInfo = ref(localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : {})
 const handleShare = async () => {
   // 分享链接携带参数: 用户id、职位id
-  if (!getToken()) {
-    Snackbar.warning('您还未登录,请先登录后再试')
-    showLogin.value = true
-    return
-  }
+  if (!getToken()) return quickLogonOpen()
   generateAndDownloadImage()
   shareUrl.value = '/shareJob?' + new URLSearchParams({
     jobId: id,
@@ -340,6 +345,7 @@ const handleShare = async () => {
 
 // 收藏&取消收藏职位
 const handleCollection = async () => {
+  if (!getToken()) return quickLogonOpen()
   const api = isCollection.value ? getPersonJobUnfavorite : getPersonJobFavorite
   await api(isCollection.value ? id : { jobId: id })
   await getCollectionStatus()
@@ -384,6 +390,7 @@ const showResume = ref(false)
 const resumeList = ref([])
 const selectResume = ref()
 const handleDelivery = async () => {
+  if (!getToken()) return quickLogonOpen()
   if (delivery.value) return Snackbar.warning(t('resume.alreadyResume'))
   const result = await getPersonResumeCv()
   resumeList.value = result
@@ -418,6 +425,7 @@ const handleSubmit = async (val) =>{
 
 // 沟通
 const toDetails = async (info) => {
+  if (!getToken()) return quickLogonOpen()
   try {
     const userId = info.contact.userId
     const enterpriseId = info.contact.enterpriseId

+ 9 - 0
src/views/recruit/personal/position/components/dict.js

@@ -4,6 +4,9 @@ import commonPath from './conditionFilter/commonPath.vue'
 
 // toFilterDictName: 查数据回显(一维数组字典),dictShow: 用户操作的字典(用户看到的数据)
 // 当type是tree类型的数据的时候需要提供dictType
+// isSlot插槽数据
+// provideData数据不为空时使用自定义下拉数据
+
 const dictList = [
   {
     toFilterDictName: 'menduner_area_type',
@@ -20,6 +23,12 @@ const dictList = [
     path: commonPath,
     toFilterDictDataList: []
   },
+  {
+    key: 'areaIds',
+    title: '工作城市',
+    path: commonPath,
+    provideData: []
+  },
   {
     toFilterDictName: 'menduner_industry_type',
     toFilterApiType: 'industryList',

+ 1 - 1
src/views/recruit/personal/recommend/components/positionList.vue

@@ -106,7 +106,7 @@ const handleClick = (item, index) => {
   border: 1px solid #fff;
   &:hover {
     box-shadow: 0 16px 40px 0 rgba(153, 153, 153, .3);
-    .salary { color: var(--v-primary-base) !important; }
+    .salary { color: var(--v-error-base) !important; }
   }
 }
 .job-info {

+ 2 - 0
src/views/recruit/personal/shareJob/form/simpleInfo.vue

@@ -82,8 +82,10 @@ const getDictData = async (dictTypeName) => {
   }
 }
 
+const userInfo = ref(localStorage.getItem('userInfo') ? JSON.parse(localStorage.getItem('userInfo')) : {})
 items.value.options.forEach((e) => {
   if (e.dictTypeName) getDictData(e.dictTypeName) // 查字典set options
+  e.value = userInfo.value[e.key] // 回显
   // formItems回显
   // const infoExist = baseInfo.value && Object.keys(baseInfo.value).length
   // if (infoExist && baseInfo.value[e.key]) e.value = baseInfo.value[e.key]

+ 3 - 2
src/views/register/company.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="box">
+  <div class="box" style="overflow-x: hidden;">
     <PhonePage v-if="!valid" :isCompany="true" @success="handleValidate" :isLogin="query.login ? true : false"></PhonePage>
   </div>
 </template>
@@ -24,10 +24,11 @@ const handleValidate = async () => {
   } 
   // 查看用户是否有在申请中的数据
   const data = await getUserRegisterEnterpriseApply()
-  const bool = data && Object.keys(data).length // 已经有数据说明已经申请过了
+  const bool = data && Object.keys(data).length && data.status !== '1' // 已经有数据说明已经申请过了 且申请状态如果为已通过,则跳转到注册页面让用户可以注册新的企业
   const path = bool ? '/recruit/entRegister/inReview' : '/recruit/entRegister'
   router.push({ path, query: { type: 'noLoginToRegister' } })
 }
+// handleValidate() // 测试
 
 </script>
 

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