Selaa lähdekoodia

Merge branch 'recruit-enterprise' of https://git.citupro.com/zhengnaiwen_citu/menduner-uniapp into recruit-enterprise

lifanagju_citu 23 tuntia sitten
vanhempi
commit
29a0eb9255

+ 22 - 20
components/positionItem/components/baseInfo.vue

@@ -10,15 +10,14 @@
 			<uni-forms-item required label="职位名称" name="name">
         <uni-easyinput v-model="formData.name" placeholder="请填写职位名称" @blur="handleValidName"></uni-easyinput>
 			</uni-forms-item>
-      <template v-if="!props.isFair && jobFairList?.length">
-        <!-- 设置为招聘会职位 -->
+      <!-- <template v-if="!props.isFair && jobFairList?.length">
         <uni-forms-item label="招聘会" name="bizId" >
           <view style="max-width: calc(100vw - 110px);">
             <uni-data-picker class="picker" popup-title="请选择招聘会" v-model="formData.bizId" :localdata="jobFairList" :clear-icon="false" :map="{ text: 'title', value: 'id'}"></uni-data-picker>
           </view>
           <view style="color: #777; font-size: 12px;" class="ss-m-t-8 ss-m-l-10">发布的职位会在对应的招聘会显示</view>
         </uni-forms-item>
-      </template>
+      </template> -->
       <!-- <uni-forms-item label="到期时间" name="expireTime" required>
 				<view class="d-flex">
           <picker mode="date" :value="formData.expireTime" :disabled="expireTimeDisabled" :start="startDate" @change="expireTimeChange">
@@ -139,21 +138,21 @@ const editorBlur = (key, val) => {
 }
 
 // 获取企业已加入的招聘会列表
-const jobFairList = ref(false)
-const getJobFairData = async () => {
-  if (props.isFair) return
-  const res = await getJobFairWhiteList()
-  jobFairList.value = res?.data || []
-  if (formData.value.bizId) {
-    if (!jobFairList.value?.length) {
-      formData.value.bizId = '' // 企业已经不在任何招聘会白名单中
-      return
-    }
-    const jobFairItem = jobFairList.value.find(e => e.id === formData.value.bizId)
-    if (!jobFairItem) formData.value.bizId = '' // 招聘会已经关闭 或者已被移除招聘会白名单
-  }
-}
-getJobFairData()
+// const jobFairList = ref(false)
+// const getJobFairData = async () => {
+//   if (props.isFair) return
+//   const res = await getJobFairWhiteList()
+//   jobFairList.value = res?.data || []
+//   if (formData.value.bizId) {
+//     if (!jobFairList.value?.length) {
+//       formData.value.bizId = '' // 企业已经不在任何招聘会白名单中
+//       return
+//     }
+//     const jobFairItem = jobFairList.value.find(e => e.id === formData.value.bizId)
+//     if (!jobFairItem) formData.value.bizId = '' // 招聘会已经关闭 或者已被移除招聘会白名单
+//   }
+// }
+// getJobFairData()
 
 const pushTemplate = () => {
   formData.value.content = jobTemplateRes.value.content
@@ -235,12 +234,15 @@ const getQuery = async () => {
     hirePrice: 0,
     // soFar: Boolean(soFar.value?.length),
     hire: false,
+    expireTime: null,
     ...formData.value
   }
 
-  obj.source = obj.bizId ? '2' : '0' // 职位来源(0职位管理|1众聘职位|2招聘会)
+  // obj.source = props.isFair ? '2' : '0' // 职位来源(0职位管理|1众聘职位|2招聘会)
   // obj.expireTime = obj.soFar ? null : dateToTimestamp(obj.expireTime)
-  obj && Object.keys(obj).length && Object.keys(obj).forEach(key => { if (['areaId', 'eduType', 'expType'].includes(key) && obj[key] === -1)  obj[key] = null })
+  obj && Object.keys(obj).length && Object.keys(obj).forEach(key => { 
+    if (['areaId', 'eduType', 'expType'].includes(key) && obj[key] === -1)  obj[key] = null 
+  })
 
   return obj
 }

+ 15 - 11
components/positionItem/index.vue

@@ -5,7 +5,7 @@
         <view class="decoration decoration1">1</view>
       </template>
       <!-- 基本信息 -->
-      <baseInfo ref="baseInfoRef" :isFair="Boolean(fairId)" :data="itemData"></baseInfo>
+      <baseInfo ref="baseInfoRef" :data="itemData"></baseInfo>
     </uni-section>
     <uni-section class="ss-m-y-20" title="岗位要求">
       <template v-slot:decoration>
@@ -33,27 +33,26 @@
 <script setup>
 import baseInfo from './components/baseInfo.vue'
 import requirement from './components/requirement.vue'
-import extendInfo from './components/extend.vue'
+// import extendInfo from './components/extend.vue'
 import { ref, nextTick } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
 import payPopup from '@/components/payPopup'
 import { dealDictObjData } from '@/utils/position'
 import {
   saveJobAdvertised,
-  saveJobAdvertisedExtend,
+  // saveJobAdvertisedExtend,
   getJobDetails,
-  getJobAdvertisedExtend,
+  // getJobAdvertisedExtend,
 } from '@/api/new/position'
 const props = defineProps({
   jobId: String,
   fairId: String,
+  isClone: { type: Boolean, default: false }
 })
 
 const jobId = ref('')
-const fairId = ref('')
 onLoad((options) => {
   jobId.value = options?.jobId || props.jobId || ''
-  fairId.value = options?.fairId || props.fairId || ''
   if (jobId.value) getPositionDetail(jobId.value)
   else {
     show.value = true
@@ -110,18 +109,18 @@ const getSubmitParams = async() => {
   submitParams = {
     ...baseInfo,
     ...requirement,
-    fair: Boolean(fairId.value), // fair:是否为招聘会职位编辑-必填
+    fair: props.fairId ? true : false, // fair:是否为招聘会职位编辑-必填
     currency_type: 0, // currency_type: 写死0(人民币)
-    source: fairId.value || baseInfo.bizId ? '2' : '0', // source: 0职位管理|1招聘会
-    bizId:  fairId.value || baseInfo.bizId || null,
+    source: props.fairId ? '2' : '0', // source: 职位来源(0职位管理|1众聘职位|2招聘会)
   }
+  if (props.fairId) submitParams.bizId = props.fairId // 招聘会职位添加招聘会id
   
   if (!submitParams.salary) {
     if (!submitParams.payFrom) return uni.showToast({ title: '请填写最低薪资', icon: 'none', duration: 2000 })
     if (!submitParams.payTo) return uni.showToast({ title: '请填写最高薪资', icon: 'none', duration: 2000 })
   }
   
-  if (jobId.value) submitParams.id = jobId.value  // 有id则为编辑
+  if (jobId.value && !props.isClone) submitParams.id = jobId.value  // 有id则为编辑, 职位克隆不需要id
   saveEmit()
 }
 // 
@@ -143,7 +142,12 @@ const saveEmit = async (retry) => {
       })
       return
     }
-    uni.switchTab({ url: '/pages/index/position' })
+    if (!props.fairId) uni.switchTab({ url: '/pages/index/position' })
+    else {
+      uni.reLaunch({
+        url: `/pagesB/jobFair/details?id=${props.fairId}`
+      })
+    }
     // const title = itemData.value?.status === '99' '编辑成功,请前往支付' : jobId.value ? '编辑成功' : '发布成功'
     setTimeout(() => { uni.showToast({ title: jobId.value ? '编辑成功' : '发布成功', icon: 'success' }) }, 1000)
 

+ 18 - 0
pages.json

@@ -154,6 +154,12 @@
 						"navigationBarTitleText": "新增职位"
 					}
 				},
+				{
+					"path": "positionAdd/select",
+					"style": {
+						"navigationBarTitleText": "新增职位方式选择"
+					}
+				},
 				{
 					"path": "positionEdit/index",
 					"style": {
@@ -231,6 +237,18 @@
 					"style": {
 						"navigationBarTitleText": "邀请面试"
 					}
+				},
+				{
+					"path": "jobFair/addJob",
+					"style": {
+						"navigationBarTitleText": "招聘会职位新增"
+					}
+				},
+				{
+					"path": "jobFair/editJob",
+					"style": {
+						"navigationBarTitleText": "招聘会职位编辑"
+					}
 				}
 			]
 		}

+ 2 - 2
pages/index/position.vue

@@ -76,6 +76,7 @@ const tabList = [
   // { label: '到期职位', value: 3 }
 ]
 const controlList = tabList.map(e => e.label)
+
 const tabChange = (e) => {
   tab.value = e.currentIndex
   query.value.pageNo = 1
@@ -141,7 +142,6 @@ onShow(() => {
 const publishJobCount = ref(0)
 const getPublishJobCount = async () => {
   const info = await useUserStore.getUserInfos()
-  console.log('info:', info)
   publishJobCount.value = info?.entitlement?.publishJobCount - 0 || 0
 }
 
@@ -179,7 +179,7 @@ const handleClickAdd = () => {
 		showAuthModal()
 		return
 	}
-  uni.navigateTo({ url: '/pagesB/positionAdd/index' })
+  uni.navigateTo({ url: '/pagesB/positionAdd/select' })
 }
 
 </script>

+ 7 - 1
pagesA/resume/item.vue

@@ -116,6 +116,13 @@ const handleDetail = async (val) => {
 
 // 查看附件
 const handlePreview = async (val) => {
+	// 效验企业是否有查看简历次数
+	const info = await user.getUserInfos()
+	if (info?.entitlement?.lookCvCount <= 0) {
+		uni.showToast({ title: '查看简历次数已用完,请联系门墩儿管理员', icon: 'none', duration: 2000 })
+		return
+	}
+
 	const id = props.current === 0 ? val.id : val?.cvRel?.id
 	const url = props.current === 0 ? val.url : val?.cvRel?.url
 	if (!val.userId || !id) {
@@ -278,7 +285,6 @@ const handleSettlement = async (item) => {
 
 // 入职
 const handleEnterByEnterprise = async (item) => {
-	console.log(item, '====入职====')
 	if (!item.id) {
 		uni.showToast({ title: 'ID不存在', icon: 'none' })
 		return

+ 16 - 0
pagesB/jobFair/addJob.vue

@@ -0,0 +1,16 @@
+<template>
+  <view>
+    <position :fairId="jobFairId" />
+  </view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import position from '@/components/positionItem'
+
+const jobFairId = ref('')
+onLoad((options) => {
+	jobFairId.value = options.jobFairId
+})
+</script>

+ 57 - 1
pagesB/jobFair/details.vue

@@ -18,10 +18,17 @@
 			<uni-load-more v-else status="noMore" />
 		</scroll-view>
 
+    <view class="addBtn" @tap="handleClickAdd">
+      <view class="addBox">
+        <view class="icon">+</view>
+        <view class="text">发布新职位</view>
+      </view>
+    </view>
+
 		<view class="bottom-sticky">
 			<view class="bottom-content">
 				<button class="btnStyle bgButtons ss-m-l-15" type="primary" plain="true" @tap.stop="handleToShare">我的分享海报</button>
-        <button class="buttons btnStyle" type="primary" @tap.stop="handleJoinJobFair">职位加入</button>
+        <button class="buttons btnStyle" type="primary" @tap.stop="handleJoinJobFair">克隆已有职位发布</button>
       </view>
 		</view>
 	</view>
@@ -34,6 +41,8 @@ import { getJobFair, getJobFairPosition } from '@/api/jobFair.js'
 import { getJobAdvertisedList } from '@/api/new/position'
 import { dealDictArrayData } from '@/utils/position.js'
 import JobItem from './jobItem.vue'
+import { getAccessToken } from '@/utils/request'
+import { showAuthModal } from '@/hooks/useModal'
 
 const id = ref(null)
 const tab = ref(0)
@@ -114,6 +123,19 @@ const tabChange = (e) => {
   getProgressJobList()
 }
 
+// 职位新增
+const handleClickAdd = () => {
+  if (!getAccessToken()) {
+		uni.showToast({
+			title: '请先登录',
+			icon: 'none'
+		})
+		showAuthModal()
+		return
+	}
+  uni.navigateTo({ url: '/pagesB/jobFair/addJob?jobFairId=' + id.value })
+}
+
 onLoad((options) => {
 	id.value = options.id
 	if (!id.value) {
@@ -207,4 +229,38 @@ const handleToShare = () => {
   padding-bottom: 100rpx;
   box-sizing: border-box;
 }
+.addBtn{
+  position: fixed;
+  margin-bottom: 20px;
+  right: 35rpx;
+  bottom: calc(env(safe-area-inset-bottom) + 60px);
+  width: 70px;
+  .addBox {
+    position: relative;
+    .icon {
+      font-size: 42px;
+      color: #fff;
+      background-color: #00B760;
+      width: 50px;
+      height: 50px;
+      line-height: 46px;
+      text-align: center;
+      border-radius: 50%;
+      margin: 0 auto;
+      box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
+    }
+    .text {
+      position: absolute;
+      top: 42px;
+      font-size: 12px;
+      color: #00B760;
+      background-color: #ffffffc9;
+      text-align: center;
+      padding: 2px 4px;
+      margin: 0 auto;
+      border-radius: 6px;
+      // box-shadow: 0 36px 6px rgba(0, 0, 0, 0.1);
+    }
+  }
+}
 </style>

+ 21 - 0
pagesB/jobFair/editJob.vue

@@ -0,0 +1,21 @@
+<template>
+  <view>
+    <position :jobId="jobId" :fairId="jobFairId" :isClone="isClone" />
+  </view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import position from '@/components/positionItem'
+
+const jobId = ref('')
+const jobFairId = ref('')
+const isClone = ref(false)
+
+onLoad((options) => {
+	jobFairId.value = options.jobFairId
+  jobId.value = options.jobId
+  if (options?.isClone) isClone.value = true
+})
+</script>

+ 20 - 22
pagesB/jobFair/join.vue

@@ -20,12 +20,14 @@
           </view>
           <view class="ss-m-l-20 label-text">{{ item?.hrName }}</view>
         </view>
-        <view class="list-shape">
+        <view class="list-shape" :style="{'border-radius': item?.hrName ? '0 0 12px 12px' : '12px'}">
           <view>
 						<view class="titleBox">
-							<view style="display: flex;align-items: center;">
+							<view style="display: flex; align-items: center;">
+								<image v-if="item.jobFairId" src="/static/svg/jobFair.svg" class=" ss-m-r-10" style="width: 20px; height: 20px;"></image>
 								<rich-text v-if="item.name?.indexOf('style') !== -1" class="job-name" :nodes="item.name"></rich-text>
 								<view v-else class="job-name">{{ formatName(item.name) }}</view>
+								<span v-if="item.status === '1'" class="color-error">(已关闭)</span>
 							</view>
 						</view>
 						<view class="d-flex align-center justify-space-between ss-m-t-20">
@@ -41,9 +43,12 @@
 								</span>
 							</view>
 						</view>
+						<view v-if="item.jobFairName" class="color-primary font-size-13 ss-m-t-10">
+							招聘会:{{ item.jobFairName }}
+						</view>
 					</view>
           <view class="sub-li-bottom">
-						<view class="sub-li-bottom-item" @tap.stop="handleJoin(item)">添加至招聘会</view>
+						<view class="sub-li-bottom-item" @tap.stop="handleJoin(item)">克隆加入</view>
           </view>
         </view>
       </view>
@@ -56,15 +61,14 @@
 import { ref } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
 import { formatName } from '@/utils/getText.js'
-import { joinJobFairPosition, getJobFairPositionList } from '@/api/jobFair.js'
+import { getJobAdvertisedList } from '@/api/new/position'
 import { dealDictArrayData } from '@/utils/position'
 import { getUserAvatar } from '@/utils/avatar'
 
 const query = ref({
 	pageSize: 10,
 	pageNo: 1,
-	name: null,
-	jobFairId: null
+	name: null
 })
 const items = ref([])
 const more = ref('more')
@@ -73,7 +77,7 @@ const total = ref(0)
 const getData = async () => {
   try {
 		more.value = 'loading'
-		const { data } = await getJobFairPositionList(query.value)
+		const { data } = await getJobAdvertisedList(query.value)
 
 		if (!data.list.length) {
 			more.value = 'noMore'
@@ -113,27 +117,22 @@ const loadingMore = () => {
 	getData()
 }
 
+const jobFairId = ref(null)
 onLoad(async (options) => {
-	query.value.jobFairId = options.jobFairId
+	if (options && options?.jobFairId) jobFairId.value = options.jobFairId
 
 	query.value.pageNo = 1
 	await getData()
 })
 
-// 加入职位
+// 克隆职位-跳转职位编辑
 const handleJoin = async (item) => {
-	uni.showLoading({ title: '加载中' })
-	try {
-		await joinJobFairPosition({ jobId: item.id, jobFairId: query.value.jobFairId })
-		uni.hideLoading()
-		uni.showToast({ title: '加入成功', icon: 'success' })
-
-		setTimeout(() => {
-			uni.navigateBack({ delta: 1 })
-		}, 1000)
-	} catch (e) {
-		uni.hideLoading()
-	}
+	if (!item.id) return uni.showToast({ title: '缺少职位ID', icon: 'none' })
+
+	const url = jobFairId.value ? 
+	`/pagesB/jobFair/editJob?jobId=${item.id}&jobFairId=${jobFairId.value}&isClone=1`
+	: `/pagesB/positionEdit/index?jobId=${item.id}&isClone=1`
+	uni.navigateTo({ url })
 }
 </script>
 
@@ -210,7 +209,6 @@ const handleJoin = async (item) => {
 
 .list-shape {
   background-color: #fff;
-  border-radius: 0 0 12px 12px;
 	padding: 30rpx;
   .titleBox {
     display: flex;

+ 40 - 0
pagesB/positionAdd/select.vue

@@ -0,0 +1,40 @@
+<template>
+  <view class="ss-p-50">
+    <uni-card class="ss-m-t-30" @tap="handleToAdd">
+      <view class="d-flex flex-column align-center ss-p-y-50">
+        <image src="https://minio.citupro.com/dev/static/clone.png" class="svg ss-m-l-10"></image>
+        <view class="color-primary text-center MiSans-Medium" style="font-size: 24px">填写职位信息发布</view>
+      </view>
+    </uni-card>
+    <uni-card class="ss-m-t-80" @tap="handleToClone">
+      <view class="d-flex flex-column align-center ss-p-y-50">
+        <image src="https://minio.citupro.com/dev/static/edit.png" class="svg ss-m-l-10"></image>
+        <view class="color-primary text-center MiSans-Medium" style="font-size: 24px">克隆已有职位发布</view>
+      </view>
+    </uni-card>
+  </view>
+</template>
+
+<script setup>
+// 克隆职位发布
+const handleToClone = () => {
+	uni.navigateTo({
+		url: '/pagesB/jobFair/join'
+	})
+}
+
+// 填写职位信息发布
+const handleToAdd = () => {
+	uni.reLaunch({
+		url: '/pagesB/positionAdd/index'
+	})
+}
+</script>
+
+<style lang="scss" scoped>
+.svg {
+  width: 80px;
+  height: 80px;
+  margin-bottom: 30px;
+}
+</style>

+ 8 - 2
pagesB/positionDetail/index.vue

@@ -156,10 +156,15 @@ async function getPositionDetail () {
 
 // 职位编辑
 const handleEdit = async () => {
-  if (!isEdit.value) {
+  if (!isJobFair.value && !isEdit.value) {
     uni.showToast({ title: '职位发布时间超过24小时的不支持编辑', icon: 'none', duration: 2000 })
     return
   }
+  // 已关闭的招聘会职位不支持编辑
+  if (isJobFair.value && info.value.status === '1') {
+    uni.showToast({ title: '职位已关闭', icon: 'none', duration: 2000 })
+    return
+  }
   uni.showLoading({ title: '加载中 . . . ' })
   try {
     const res = await getEnterprisePubJobTypePermission()
@@ -167,7 +172,8 @@ const handleEdit = async () => {
       uni.showToast({ title: '没有该操作权限,请联系平台管理员升级后再试', icon: 'none', duration: 2000 })
       return
     }
-    uni.navigateTo({ url: `/pagesB/positionEdit/index?jobId=${jobId}` })
+    const url = isJobFair.value ? `/pagesB/jobFair/editJob?jobId=${jobId}&jobFairId=${info.value.bizId}` : `/pagesB/positionEdit/index?jobId=${jobId}`
+    uni.navigateTo({ url })
     // 跳转编辑页面
   } finally {
     uni.hideLoading()

+ 4 - 1
pagesB/positionEdit/index.vue

@@ -1,6 +1,6 @@
 <template>
   <view>
-    <position :jobId="jobId"></position>
+    <position :jobId="jobId" :isClone="isClone"></position>
   </view>
 </template>
 <script setup>
@@ -9,12 +9,15 @@ import { onLoad } from '@dcloudio/uni-app'
 import position from '@/components/positionItem'
 
 const jobId = ref('')
+const isClone = ref(false)
 const props = defineProps({
   jobId: String
 })
 
 onLoad((options) => {
   jobId.value = options?.jobId || props.jobId || ''
+
+  if (options?.isClone) isClone.value = true
 })
 
 </script>