浏览代码

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

lifanagju_citu 7 月之前
父节点
当前提交
15460f89c6

+ 2 - 1
src/components/PositionLongStrip/item.vue

@@ -140,7 +140,8 @@ const handleEnterprise = (item) => {
 }
 .textColor666 { color: var(--color-666); }
 .positionItem {
-  width: 850px;
+  // width: 850px;
+  width: 100%;
   margin-bottom: 12px;
   border-radius: 12px;
   padding: 0;

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

@@ -174,7 +174,7 @@ const navList = [
   //     }
   //   ]
   // },
-  { title: '直聘', path: '/recruit/personal/position', noLeaving: true },
+  { title: '直聘', path: '/recruit/personal/recommend', noLeaving: true },
   { title: '甄选', path: '/mall' },
   { title: '猎寻', path: '/headhunting' },
   { title: '火苗儿' },

+ 17 - 10
src/router/modules/components/recruit/enterprise.js

@@ -22,7 +22,7 @@ const enterprise = [
   },
   {
     path: '/recruit/enterprise/talentRecruitment',
-    redirect: '/recruit/enterprise/resume',
+    redirect: '/recruit/enterprise/search',
     component: Layout,
     name: 'Talent Recruitment',
     meta: {
@@ -32,27 +32,34 @@ const enterprise = [
     },
     children: [
       {
-        path: '/recruit/enterprise/resume',
+        path: '/recruit/enterprise/search',
         meta: {
-          title: '简历管理',
-          enName: 'Resume Management'
+          title: '找人',
+          enName: 'Search People',
         },
-        component: () => import('@/views/recruit/enterprise/resume/index.vue')
+        component: () => import('@/views/recruit/enterprise/search/index.vue')
       },
       {
         path: '/recruit/enterprise/chatTools',
         meta: {
-          title: '在线沟通',
-          enName: 'Online Communication',
+          title: '沟通',
+          enName: 'Communication',
         },
         component: () => import('@/views/recruit/enterprise/chatTools/index.vue')
       },
+      {
+        path: '/recruit/enterprise/resume',
+        meta: {
+          title: '简历',
+          enName: 'Resume'
+        },
+        component: () => import('@/views/recruit/enterprise/resume/index.vue')
+      },
       {
         path: '/recruit/enterprise/interviewManagement',
         meta: {
-          title: '面试管理',
-          enName: 'Interview management',
-          // icon: 'mdi-account-multiple-check'
+          title: '面试',
+          enName: 'Interview'
         },
         component: () => import('@/views/recruit/enterprise/interviewManagement/index.vue')
       }

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

@@ -50,6 +50,14 @@ const recruit = [
     component: Layout,
     name: 'recruit',
     children: [
+      {
+        path: '/recruit/personal/recommend',
+        component: () => import('@/views/recruit/personal/recommend'),
+        name: 'recommendedPositions',
+        meta: {
+          title: '推荐'
+        }
+      },
       {
         path: '/recruit/personal/position',
         component: () => import('@/views/recruit/personal/position'),

+ 1 - 1
src/views/recruit/components/message/components/chatting.vue

@@ -42,7 +42,7 @@
           <span>联系电话:{{ val.invitePhone }}</span>
         </div>
         <div class="mt-2 d-flex justify-space-between align-center">
-          <div class="tipsText" @click="handleToCenter">在“个人中心-面试”中管理我的面试</div>
+          <div class="tipsText" @click="handleToCenter">在“个人中心-求职反馈”中管理我的面试</div>
           <div v-if="val.status === '0'">
             <v-btn class="mr-3" variant="outlined" color="error" size="small" @click="handleRefuse(val)">拒绝邀请</v-btn>
             <v-btn variant="outlined" color="primary" size="small" @click="handleAgree(val)">接受邀请</v-btn>

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

@@ -0,0 +1,19 @@
+<template>
+  <v-card class="card-box pa-5">
+    <v-tabs v-model="tab" align-tabs="center" color="primary" bg-color="#f7f8fa">
+      <v-tab :value="0">推荐</v-tab>
+      <v-tab :value="1">检索</v-tab>
+    </v-tabs>
+  </v-card>
+</template>
+
+<script setup>
+defineOptions({ name: 'enterprise-personal-search'})
+import { ref } from 'vue'
+
+const tab = ref(0)
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 28 - 23
src/views/recruit/personal/company/index.vue

@@ -1,28 +1,27 @@
 <template>
   <div class="default-width">
-    <div style=" background-color: #fff">
-      <buttons mr="491"></buttons>
-    </div>
-    <div class="white-bgc pb-3">
-      <headSearch placeholder="搜索公司" tipsText="公司关键字搜索" @handleSearch="val => handleSearch(val, 'name')"></headSearch>
-      <div class="px-5 mt-3 clear-parent">
-        <areaType :isClear="clear" @handleClick="handleSearch"></areaType>
-        <!-- <industryType :isClear="clear" @handleClick="handleSearch"></industryType> -->
-        <financingStatus class="my-5" :isClear="clear" @clear="clear = false" @handleClick="handleSearch"></financingStatus>
-        <scaleType :isClear="clear" @clear="clear = false" @handleClick="handleSearch"></scaleType>
-        <div class="clear" @click="handleClear">清空筛选条件</div>
+    <buttons :current="2" style="position: sticky;"></buttons>
+    <div class="company-content">
+      <div class="white-bgc pb-3 pt-5">
+        <headSearch placeholder="搜索公司" tipsText="公司关键字搜索" @handleSearch="val => handleSearch(val, 'name')"></headSearch>
+        <div class="px-5 mt-3 clear-parent">
+          <areaType :isClear="clear" @handleClick="handleSearch"></areaType>
+          <financingStatus class="my-5" :isClear="clear" @clear="clear = false" @handleClick="handleSearch"></financingStatus>
+          <scaleType :isClear="clear" @clear="clear = false" @handleClick="handleSearch"></scaleType>
+          <div class="clear" @click="handleClear">清空筛选条件</div>
+        </div>
       </div>
+      <div v-if="items.length">
+        <companyItem class="mt-3" :list="items"></companyItem>
+        <MPagination
+          :total="total"
+          :page="query.pageNo"
+          :limit="query.pageSize"
+          @handleChange="handleChangePage"
+        ></MPagination>
+      </div>
+      <Empty v-else class="mt-3"></Empty>
     </div>
-    <div v-if="items.length">
-      <companyItem class="mt-3" :list="items"></companyItem>
-      <MPagination
-        :total="total"
-        :page="query.pageNo"
-        :limit="query.pageSize"
-        @handleChange="handleChangePage"
-      ></MPagination>
-    </div>
-    <Empty v-else class="mt-3"></Empty>
   </div>
 </template>
 
@@ -36,7 +35,6 @@ import { dealDictArrayData } from '@/utils/position'
 import headSearch from '@/components/headSearch'
 import scaleType from './components/scaleType'
 import financingStatus from './components/financingStatus.vue'
-// import industryType from './components/industryType'
 import areaType from './components/areaType'
 import companyItem from './components/companyItem'
 import MPagination from '@/components/CtPagination'
@@ -99,7 +97,6 @@ const handleClear = () => {
 if (Object.keys(route.query).length) {
   const objData = {}
   Object.keys(route.query).map(e => {
-    // if (e === 'areaIds' || e === 'industryIds') return objData[e] = [route.query[e]]
     if (e === 'areaIds') return objData[e] = [route.query[e]]
     else objData[e] = route.query[e]
   })
@@ -132,4 +129,12 @@ const handleChangePage = (index) => {
     color: var(--v-primary-base);
   }
 }
+.company-content {
+  height: calc(100vh - 100px);
+  overflow-y: auto;
+}
+::-webkit-scrollbar {
+  width: 0;
+  height: 0;
+}
 </style>

+ 19 - 45
src/views/recruit/personal/components/buttons.vue

@@ -1,60 +1,34 @@
 <!--  -->
 <template>
-  <div v-if="list?.length" class="btnBox" :style="`margin-right: ${props.mr}px;`">
-    <div
-      v-for="(item, index) in list" :key="item.title"
-      :class="{'rl': !index, 'rr': index === list.length-1, 'active': item.path === route?.path}"
-      @click="handleUpdate(item)"
-    >
-      {{ item.title }}
-    </div>
-  </div>
+  <v-tabs v-model="tab" align-tabs="start" color="primary" @update:modelValue="handleUpdate" bg-color="#f7f8fa">
+    <v-tab v-for="k in tagList" :key="k.value" :value="k.value">{{ k.title }}</v-tab>
+  </v-tabs>
 </template>
 
 <script setup>
-import { useRoute } from 'vue-router'
-const route = useRoute()
 defineOptions({name: 'defineOptions-buttons'})
+import { ref } from 'vue'
+import { useRouter } from 'vue-router'
+
+const router = useRouter()
 const props = defineProps({
-  mr: {
-    type: [String],
-    default: '413'
+  current: {
+    type: Number,
+    default: 0
   }
 })
+const tab = ref(props.current)
 
-const list = [
-  { title: '职位', path:'/recruit/personal/position' },
-  { title: '推荐', path:'' },
-  { title: '公司', path:'/recruit/personal/company' },
+const tagList = [
+  { title: '推荐', path:'/recruit/personal/recommend', value: 0 },
+  { title: '职位', path:'/recruit/personal/position', value: 1 },
+  { title: '公司', path:'/recruit/personal/company', value: 2 }
 ]
-const handleUpdate = (item) => {
-  // if (item.path) router.push(item.path)
-  if (item.path) window.open(item.path)
+
+const handleUpdate = (e) => {
+  router.push(tagList[e].path)
 }
 </script>
+
 <style lang="scss" scoped>
-.btnBox {
-  display: flex;
-  justify-content: center;
-  padding-top: 12px;
-  border-radius: 5px 5px 0 0;
-  div {
-    cursor: pointer;
-    padding: 6px 20px;
-    color: #004e46;
-    background: linear-gradient(to right, rgba(18, 235, 177, 0.2), rgb(47 139 119 / 15%));
-    &:hover {
-      // color: #004e46;
-      color: #004e46;
-      background: linear-gradient(to right, rgba(18, 235, 177, 0.742), rgb(47 139 119 / 32%));
-    }
-  }
-}
-.rl { border-radius: 5px 0 0 0; border: none; }
-.rr { border-radius: 0 5px 0 0; }
-.active {
-  font-weight: 500 !important;
-  color: #004e46 !important;
-  background: linear-gradient(to right, rgba(18, 235, 177, 0.742), rgb(47 139 119 / 32%)) !important;
-}
 </style>

+ 23 - 19
src/views/recruit/personal/position/index.vue

@@ -1,24 +1,22 @@
 <!-- 检索列表页 - 职位检索 -->
 <template>
   <div class="default-width">
-    <div style=" background-color: #fff">
-      <buttons></buttons>
-    </div>
-    <div class="pb-3" style="z-index: 998; background-color: #fff">
-      <div class="stickyBox mb-5">
-        <headSearch
-          tipsText="职位/公司关键字搜索"
-          v-model="headSearchText"
-          @handleSearch="val => handleQueryChange('content', val)"
-        ></headSearch>
-      </div>
-      <cityFilter class="mx-5 mb-3" ref="cityFilterRef" @change="handleQueryChange"></cityFilter>
-      <div class="d-flex justify-space-between mx-5 mb-3">
-        <conditionFilter ref="conditionFilterRef" :showFilterList="showFilterList" @reset="handleReset" @change="handleQueryChange"></conditionFilter>
+    <buttons :current="1" style="position: sticky;"></buttons>
+    <div class="position-content">
+      <div class="pb-3 pt-5" style="z-index: 998; background-color: #fff">
+        <div class="stickyBox mb-5">
+          <headSearch
+            tipsText="职位/公司关键字搜索"
+            v-model="headSearchText"
+            @handleSearch="val => handleQueryChange('content', val)"
+          ></headSearch>
+        </div>
+        <cityFilter class="mx-5 mb-3" ref="cityFilterRef" @change="handleQueryChange"></cityFilter>
+        <div class="d-flex justify-space-between mx-5 mb-3">
+          <conditionFilter ref="conditionFilterRef" :showFilterList="showFilterList" @reset="handleReset" @change="handleQueryChange"></conditionFilter>
+        </div>
       </div>
-    </div>
-    <div class="d-flex mt-3">
-      <div class="mr-3" style="min-width: 850px;">
+      <div class="mt-3">
         <Empty v-if="!items?.length"></Empty>
         <PositionLongStrip v-else :items="items"></PositionLongStrip>
         <CtPagination
@@ -29,14 +27,12 @@
           @handleChange="handleChangePage"
         ></CtPagination>
       </div>
-      <rightRecommend></rightRecommend>
     </div>
   </div>
 </template>
 
 <script setup>
 import buttons from '@/views/recruit/personal/components/buttons.vue'
-import rightRecommend from './components/rightRecommend'
 import cityFilter from './components/cityFilter'
 import conditionFilter from './components/conditionFilter'
 import headSearch from '@/components/headSearch'
@@ -145,4 +141,12 @@ const handleChangePage = (index) => {
 </script>
 
 <style lang="scss" scoped>
+.position-content {
+  height: calc(100vh - 100px);
+  overflow-y: auto;
+}
+::-webkit-scrollbar {
+  width: 0;
+  height: 0;
+}
 </style>

+ 11 - 0
src/views/recruit/personal/recommend/components/details.vue

@@ -0,0 +1,11 @@
+<template>
+  <div>xxx</div>
+</template>
+
+<script setup>
+defineOptions({ name: 'recommendDetails'})
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 178 - 0
src/views/recruit/personal/recommend/components/item.vue

@@ -0,0 +1,178 @@
+<template>
+  <div class="d-flex">
+    <div class="position-box">
+      <div class="sub-li" v-for="(item, index) in list" :key="index">
+        <div class="job-info" @click="handlePosition(item)" @mouseenter="item.active = true" @mouseleave="item.active = false">
+          <div class="sub-li-top">
+            <div class="sub-li-info">
+              <p :class="['name', {'default-active': item.active }]">{{ item.job.name }}</p>
+              <svg-icon v-if="item.job.hire" name="pin" size="30"></svg-icon>
+            </div>
+            <p v-if="!item.job.payFrom && !item.job.payTo" class="salary">面议</p>
+            <p v-else class="salary">{{ item.job.payFrom ? item.job.payFrom + '-' : '' }}{{ item.job.payTo }}{{ item.job.payName ? '/' + item.job.payName : '' }}</p>
+          </div>
+          <div class="d-flex justify-space-between align-center">
+            <div>
+              <span v-for="(j, i) in desc" :key="i" class="font-size-13" style="color: #808080;">
+                <span v-if="item.job[j.value]" class="mr-1 d-inline-block">{{ item.job[j.value] }}</span>
+                <span v-if="i !== desc.length - 1 && item.job[j.value] && item.job[desc[i + 1].value]" class="septal-line ml-1"></span>
+              </span>
+            </div>
+          </div>
+          <div class="ellipsis" style="height: 24px;overflow: hidden;">
+            <span v-for="(j, i) in item.job.tagList" :key="i" class="mr-3 tags" style="color: #345768;">{{ j }}</span>
+          </div>
+        </div>
+        <div class="sub-li-bottom" @click="handleEnterprise(item)">
+          <div class="user-info">
+            <div class="d-flex align-center">
+              <v-avatar size="35">
+                <v-img :src="item.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'" />
+              </v-avatar>
+              <span class="names ml-2 font-size-14 ellipsis" style="max-width: 88%;">
+                {{ item.enterprise.anotherName }}
+                <span class="color-999 font-size-13 ml-3">
+                  <span>{{ item.enterprise.industryName }}</span>
+                  <span class="septal-line" v-if="item.enterprise.industryName && item.enterprise.scaleName"></span>
+                  <span>{{ item.enterprise.scaleName }}</span>
+                </span>
+              </span>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'position-card-item' })
+import { ref, watch } from 'vue'
+
+const props = defineProps({
+  items: {
+    type: Array,
+    default: () => []
+  }
+})
+const list = ref([])
+watch(
+  () => props.items, 
+  (newVal) => {
+    list.value = newVal
+  },
+  { immediate: true },
+  { deep: true }
+)
+const desc = [
+  { mdi: 'mdi-map-marker-outline', value: 'areaName' },
+  { mdi: 'mdi-school-outline', value: 'eduName' },
+  { mdi: 'mdi-clock-time-ten-outline', value: 'expName' }
+]
+
+const handlePosition = (item) => {
+  console.log(item, 'iiiiiiii')
+}
+const handleEnterprise = (item) => {
+  window.open(`/recruit/personal/company/details/${item.enterprise.id}?key=briefIntroduction`)
+}
+</script>
+
+<style lang="scss" scoped>
+.position-box {
+  width: 100%;
+  height: 100%;
+}
+.sub-li {
+  position: relative;
+  width: 384px;
+  height: 149px;
+  margin-bottom: 12px;
+  border-radius: 12px;
+  padding: 0;
+  overflow: hidden;
+  cursor: pointer;
+  transition: all .2s linear;
+  background-color: #fff;
+  &:hover {
+    box-shadow: 0 16px 40px 0 rgba(153, 153, 153, .3);
+  }
+}
+.job-info {
+  position: relative;
+  padding: 16px 20px;
+}
+.recommend {
+  position: absolute;
+  left: 0;
+  top: 0;
+}
+.sub-li-top {
+  display: flex;
+  width: 100%;
+  align-items: center;
+}
+.sub-li-info {
+  display: flex;
+  align-items: center;
+  flex-wrap: wrap;
+  height: 31%;
+  overflow: hidden;
+  flex: 1;
+}
+.salary {
+  font-size: 16px;
+  font-weight: 700;
+  color: #CEC149;
+  line-height: 22px;
+  flex: none;
+}
+.tags {
+  font-size: 12px;
+  color: #666;
+  display: inline-block;
+}
+.job-text {
+  white-space: normal;
+  padding-right: 0;
+  height: 22px;
+  line-height: 22px;
+  overflow: hidden;
+  word-break: break-all;
+  max-width: none;
+}
+.sub-li-info .name {
+  position: relative;
+  max-width: 140px;
+  margin-right: 8px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  font-weight: 600;
+  color: #345768;
+  &:hover {
+    color: var(--v-primary-base);
+  }
+}
+.sub-li-bottom {
+  position: absolute;
+  width: 100%;
+  height: 54px;
+  bottom: 1px;
+  left: 0;
+  margin-top: 10px;
+  padding-top: 0;
+  display: block;
+  border: none;
+}
+.user-info {
+  padding: 12px 20px;
+}
+.names {
+  font-weight: 500;
+  color: #404040;
+  &:hover {
+    color: var(--v-primary-base);
+  }
+}
+</style>

+ 53 - 0
src/views/recruit/personal/recommend/index.vue

@@ -0,0 +1,53 @@
+<template>
+  <div class="default-width">
+    <div style="background-color: #fff; position: sticky;">
+      <buttons :current="0"></buttons>
+    </div>
+    <div class="d-flex recommend-content">
+      <div class="mt-3">
+        <PositionList v-if="items.length" :items="items"></PositionList>
+      </div>
+      <div style="flex: 1;" class="ml-3">right-details</div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+defineOptions({ name: 'personalPositionRecommend'})
+import buttons from '@/views/recruit/personal/components/buttons.vue'
+import { ref, reactive } from 'vue'
+import { getJobAdvertisedSearch } from '@/api/position'
+import { dealDictObjData } from '@/utils/position'
+import PositionList from './components/item'
+
+const query = reactive({
+  pageNum: 1,
+  pageSize: 10
+})
+const items = ref([])
+
+const getData = async () => {
+  const { list } = await getJobAdvertisedSearch(query)
+  if (!list.length) return
+  items.value = list.map(e => {
+    e.job = { ...e.job, ...dealDictObjData({}, e.job) }
+    e.enterprise = { ...e.enterprise, ...dealDictObjData({}, e.enterprise) }
+    return e
+  })
+  if (items.value.length) {
+    items.value[0].active = true
+  }
+}
+getData()
+</script>
+
+<style scoped lang="scss">
+.recommend-content {
+  height: calc(100vh - 100px);
+  overflow-y: auto;
+}
+::-webkit-scrollbar {
+  width: 0;
+  height: 0;
+}
+</style>