Browse Source

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

lifanagju_citu 1 ngày trước cách đây
mục cha
commit
2d7cb999ac

+ 2 - 1
api/jobFair.js

@@ -1,10 +1,11 @@
 import request from "@/utils/request"
 
 // 获得招聘会列表
-export const getJobFairList = () => {
+export const getJobFairList = (params) => {
   return request({
     url: '/app-api/menduner/system/recruit/job-fair/list',
     method: 'GET',
+	params,
     custom: {
       showLoading: false,
       auth: true

+ 26 - 0
api/new/position.js

@@ -53,6 +53,32 @@ export const getJobDetails = (params) => {
   })
 }
 
+// 使用可发布职位数将职位更新成招聘中状态
+export const updatePositionStatus = (ids) => {
+  return request({
+    url: `/app-api/menduner/system/recruit/job-advertised/publish/job/enable?ids=${ids}`,
+    method: 'POST',
+    custom: {
+      showLoading: true,
+      openEncryption: true,
+      auth: true
+    }
+  })
+}
+
+// 删除待支付职位
+export const deletePosition = (ids) => {
+  return request({
+    url: `/app-api/menduner/system/recruit/job-advertised/del?ids=${ids}`,
+    method: 'POST',
+    custom: {
+      showLoading: true,
+      openEncryption: true,
+      auth: true
+    }
+  })
+}
+
 // 获取招聘职位扩展信息
 export const getJobAdvertisedExtend = (jobId) => {
   return request({

+ 51 - 12
components/PositionList/index.vue

@@ -40,12 +40,29 @@
           </view>
           <view class="d-flex font-size-13 color-666 ss-m-t-10">
             <!-- <view class="ss-m-t-10 ss-m-r-15">到期时间:{{ item.expireTime ? timesTampChange(item.expireTime, 'Y-M-D') : '长期有效' }}</view> -->
-            <view class="ss-m-t-10">刷新时间:{{ item.refreshTime ? timesTampChange(item.refreshTime, 'Y-M-D h:m') : '暂无' }}</view>
+            <view class="ss-m-t-10" v-if="tab !== 0">刷新时间:{{ item.refreshTime ? timesTampChange(item.refreshTime, 'Y-M-D h:m') : '暂无' }}</view>
           </view>
           <view class="sub-li-bottom ss-m-t-20">
-            <view v-if="tab === 0" class="sub-li-bottom-item color-primary" style="width: 100%;" @tap.stop="toPay(item)">发布</view>
-            <view v-if="tab !== 0" class="sub-li-bottom-item color-primary" style="width: 45%;" @tap.stop="handleToResume(item)">{{ item.count || 0 }} 已投递简历</view>
-            <view v-if="tab === 1" class="sub-li-bottom-item color-warning" @tap.stop="handleAction(item.top ? 4 : 3, '', item)">{{ item.top ? '取消置顶' : '置顶' }}</view>
+            <view 
+              v-if="tab === 0 && jobNum && +jobNum > 0" 
+              class="sub-li-bottom-item color-primary" 
+              style="width: 33%;" 
+              @tap.stop="handleRelease(item)"
+            >使用额度发布</view>
+            <view v-if="tab === 0" class="sub-li-bottom-item color-primary" style="width: 33%;" @tap.stop="toPay(item)">支付发布</view>
+            <view v-if="tab === 0" class="sub-li-bottom-item color-error" style="width: 33%;" @tap.stop="handleDelete(item)">删除</view>
+			
+            <view 
+              v-else 
+              class="sub-li-bottom-item color-primary" 
+              style="width: 45%;" 
+              @tap.stop="handleToResume(item)"
+            >{{ item.count || 0 }} 已投递简历</view>
+            <view 
+              v-if="tab === 1" 
+              class="sub-li-bottom-item color-warning" 
+              @tap.stop="handleAction(item.top ? 4 : 3, '', item)"
+            >{{ item.top ? '取消置顶' : '置顶' }}</view>
             <view v-if="tab === 1" class="sub-li-bottom-item color-666" @tap.stop="handleAction(0, '', item, item)">关闭</view>
             <view v-if="tab === 2" class="sub-li-bottom-item color-warning" @tap.stop="handleAction(1, '', item, item)">激活</view>
           </view>
@@ -76,7 +93,6 @@
 
 <script setup>
 import { ref } from 'vue'
-// import { commissionCalculation } from '@/utils/position'
 import { timesTampChange } from '@/utils/date'
 import { formatName } from '@/utils/getText'
 import payPopup from '@/components/payPopup'
@@ -86,7 +102,9 @@ import {
   topJobAdvertised,
   refreshJobAdvertised,
   closeJobAdvertised,
-  enableJobAdvertised
+  enableJobAdvertised,
+  updatePositionStatus,
+  deletePosition
 } from '@/api/new/position'
 import { getUserAvatar } from '@/utils/avatar'
 
@@ -97,20 +115,41 @@ const props = defineProps({
   noMore: { type: Boolean, default: false },
   showWelfareTag: { type: Boolean, default: true },
   payable: { type: Boolean, default: false },
+  jobNum: { type: Number, default: 0 }
 })
 
 const userInfo = ref(useUserStore?.userInfo || {})
 
+// 使用额度发布职位
+const handleRelease = async (val) => {
+  if (!val.id) return
+  try {
+    await updatePositionStatus(val.id)
+	  uni.showToast({ title: '发布成功', icon: 'success', duration: 2000 })
+    emit('refresh', { reset: true })
+  } catch {}
+}
+
+// 删除待支付职位
+const handleDelete = async (val) => {
+  if (!val.id) return
+  try {
+    await deletePosition(val.id)
+    uni.showToast({ title: '删除成功', icon: 'success', duration: 2000 })
+    emit('refresh', { reset: true })
+  } catch {}
+}
+
 const payRef = ref()
 // 支付
 const toPay = async (val) => {
   // 待发布且有额度的激活职位即可
-  if (userInfo.value.entitlement?.publishJobCount > 0) {
-    await enableJobAdvertised([val.id])
-    emit('refresh', { reset: true, updatePublishJobCount: true })
-    setTimeout(() => { uni.showToast({ title: '发布成功', icon: 'success' }) }, 1000)
-    return
-  }
+  // if (userInfo.value.entitlement?.publishJobCount > 0) {
+  //   await enableJobAdvertised([val.id])
+  //   emit('refresh', { reset: true, updatePublishJobCount: true })
+  //   setTimeout(() => { uni.showToast({ title: '发布成功', icon: 'success' }) }, 1000)
+  //   return
+  // }
   payRef.value && payRef.value.handleOpen({ spuId: val?.id||'', spuName: val?.name||'', price: 1, type: 1 })
 }
 

+ 54 - 7
pages/index/jobFair.vue

@@ -5,11 +5,22 @@
       <view class="defaultBgc" style="padding-bottom: 100px;" :style="{'height': `calc(100vh - ${(navbarHeight + 100)}px)`, 'padding-top': navbarHeight + 'px'}">
         <view v-if="items.length">
           <view class="commonBackground"></view>
-          <view v-for="val in items" :key="val.id" @tap="handleToJobFairEnterprises(val)" class="list-item default-border">
-            <image v-if="val?.previewImg" class="ss-m-t-10" :src="val.previewImg" mode="widthFix" style="width: 100%; height: auto; border-radius: 6px;"></image>
-            <view class="ss-m-t-20">活动时间:{{ timesTampChange(val.startTime, 'Y-M-D') }}至{{ timesTampChange(val.endTime, 'Y-M-D') }}</view>
-            <button class="ss-m-t-20 ss-m-b-10" style="background-color: #00B760; color: #fff;" type="primary">立即加入</button>
-          </view>
+          <scroll-view class="scrollBox" :scroll-y="true" @scrolltolower="loadingMore" style="position:relative;">
+            <view v-for="val in items" :key="val.id" @tap="handleToJobFairEnterprises(val)" class="list-item default-border">
+              <image v-if="val?.previewImg" class="ss-m-t-10" :src="val.previewImg" mode="widthFix" style="width: 100%; height: auto; border-radius: 6px;"></image>
+              <view class="ss-m-t-20 ss-m-b-10">
+                活动状态:
+                <span class="font-weight-bold" :style="{'color': val.status === '0' ? '#00b760' : '#ff5252'}">
+                  {{ val.status === '0' ? '进行中' : '已结束' }}
+                </span>
+              </view>
+              <view>活动时间:{{ timesTampChange(val.startTime, 'Y-M-D') }}至{{ timesTampChange(val.endTime, 'Y-M-D') }}</view>
+              <button class="ss-m-t-20 ss-m-b-10" style="background-color: #00B760; color: #fff;" type="primary">
+                {{ val.status === '0' ? '立即加入' : '查看详情' }}
+              </button>
+            </view>
+            <uni-load-more :status="more" />
+          </scroll-view>
         </view>
         <view v-else>
           <view class="commonBackground"></view>
@@ -39,18 +50,50 @@ import payPopup from '@/components/payPopup'
 const useUserStore = userStore()
 const items = ref([])
 const navbarHeight = ref(uni.getStorageSync('navbarHeight'))
+const total = ref(0)
+const query = ref({
+	pageNo: 1,
+	pageSize: 20
+})
+const more = ref('more')
 
 // 获得招聘会列表
 const getList = async () => {
+	if (query.value.pageNo < 1) return
+	if (query.value.pageNo === 1) items.value = []
   try {
+	  more.value = 'loading'
 	  uni.showLoading({ title: '加载中' })
-    const res = await getJobFairList()
-    items.value = res?.data || []
+    const res = await getJobFairList(query.value)
+    const list = res?.data?.list || []
+    if (!list?.length) {
+      more.value = 'noMore'
+      return
+    }
+    items.value = items.value.concat(...list)
+    total.value = res.data.total
+    more.value = 'more'
+    if (items.value.length === +total.value) {
+      more.value = 'noMore'
+      return
+    }
+  } catch (error) {
+	  query.value.pageNo--
+	  more.value = 'more'
   } finally {
     uni.hideLoading()
   }
 }
 
+// 加载更多
+const loadingMore = () => {
+  if (more.value === 'noMore') return
+
+  more.value = 'loading'
+  query.value.pageNo++
+  getList()
+}
+
 watch(() => useUserStore.refreshToken, () => {
 	if (!useUserStore.refreshToken) return items.value = []
 	getList()
@@ -117,6 +160,10 @@ const paySuccess = () => {
 </script>
 
 <style scoped lang="scss">
+.scrollBox {
+	height: 100vh;
+	box-sizing: border-box;
+}
 .list-item {
   margin: 0 30rpx 30rpx 30rpx;
   border-radius: 20rpx;

+ 9 - 8
pages/index/position.vue

@@ -32,7 +32,7 @@
                 </view>
               </view>
               <view v-else>
-                <PositionList v-if="positionListData?.length" :tab="tab" :payable="true" :list="positionListData" :noMore="false" @refresh="refresh"></PositionList>
+                <PositionList v-if="positionListData?.length" :tab="tab" :jobNum="publishJobCount" :payable="true" :list="positionListData" :noMore="false" @refresh="refresh"></PositionList>
                 <uni-load-more :status="more" />
                 <view style="padding-bottom: 20vh;"></view>
                 <view class="addBtn" @tap="handleClickAdd">
@@ -88,6 +88,7 @@ const query = ref({
   pageSize: 5, 
   pageNo: 1,
   hire: false,
+  jobFairId: 0,
   name: '',
 })
 const more = ref('more')
@@ -97,13 +98,13 @@ const getData = async () => {
   if (query.value.pageNo === 1) positionListData.value = []
   try {
     more.value = 'loading'
-    if (tab.value !== 3) {
-      query.value.status = tabList[tab.value].status
-      query.value.hasExpiredData = false
-    } else {
-      query.value.hasExpiredData = true
-      delete query.value.status
-    }
+    // if (tab.value !== 3) {
+    query.value.status = tabList[tab.value].status
+      // query.value.hasExpiredData = false
+    // } else {
+    //   query.value.hasExpiredData = true
+    //   delete query.value.status
+    // }
     const res = await getJobAdvertisedList(query.value)
     const list = res?.data?.list?.length ? res.data.list : []
     total.value = res.data.total-0

+ 71 - 7
pagesB/jobFair/details.vue

@@ -5,13 +5,15 @@
 			<rich-text class="title" :nodes="jobFairInfo?.title?.replace(/<\/?p[^>]*>/gi, '')"></rich-text>
 		</view>
 
-		<scroll-view class="scrollBox" :scroll-y="true" style="position:relative;">
+		<uni-segmented-control :current="tab" :values="controlList" @clickItem="tabChange" styleType="text" activeColor="#00B760" />
+		<scroll-view class="scrollBox" :scroll-y="true" style="position:relative;" @scrolltolower="loadingMore">
 			<JobItem 
 				v-if="jobFairPosition?.length"
 				:list="jobFairPosition"
 				:jobFairId="id"
+				:tab="tab"
 				:jobFairName="jobFairInfo?.title?.replace(/<\/?p[^>]*>/gi, '')"
-				@refresh="getJobFairPositionList"
+				@refresh="tabChange({ currentIndex: tab })"
 			/>
 			<uni-load-more v-else status="noMore" />
 		</scroll-view>
@@ -29,10 +31,13 @@
 import { ref } from 'vue'
 import { onLoad, onShow } from '@dcloudio/uni-app'
 import { getJobFair, getJobFairPosition } from '@/api/jobFair.js'
+import { getJobAdvertisedList } from '@/api/new/position'
 import { dealDictArrayData } from '@/utils/position.js'
 import JobItem from './jobItem.vue'
 
 const id = ref(null)
+const tab = ref(0)
+const controlList = ['招聘中', '已关闭']
 
 // 获取招聘会信息
 const jobFairInfo = ref({})
@@ -42,11 +47,11 @@ const getJobFairInfo = async () => {
   jobFairInfo.value = data || {}
 }
 
-// 获取招聘会职位
+// 招聘中职位
 const jobFairPosition = ref([])
-const getJobFairPositionList = async () => {
+const getJobList = async () => {
   try {
-	  uni.showLoading({ title: '加载中' })
+		uni.showLoading({ title: '加载中' })
 		const { data } = await getJobFairPosition(id.value)
 		if (!data || !data.length) {
 			jobFairPosition.value = []
@@ -58,6 +63,57 @@ const getJobFairPositionList = async () => {
   }
 }
 
+// 已关闭职位
+const more = ref('more')
+const pageTotal = ref(0)
+const pageInfo = ref({
+  pageSize: 10,
+  pageNo: 1
+})
+const getProgressJobList = async () => {
+  if (pageInfo.value.pageNo < 1) return
+  if (pageInfo.value.pageNo === 1) jobFairPosition.value = []
+  try {
+    more.value = 'loading'
+    const res = await getJobAdvertisedList({ ...pageInfo.value, status: '1', jobFairId: id.value, hire: false })
+    const list = res?.data?.list?.length ? res.data.list : []
+    pageTotal.value = res.data.total-0
+    if (!list?.length) {
+      more.value = 'noMore'
+      return
+    }
+    jobFairPosition.value.push(...dealDictArrayData([], list))
+    more.value = 'more'
+    if (jobFairPosition.value.length === pageTotal.value) {
+      more.value = 'noMore'
+      return
+    }
+  } catch (error) {
+    pageInfo.value.pageNo--
+    more.value = 'more'
+  }
+}
+
+// 加载更多
+const loadingMore = () => {
+	// 招聘中职位列表不需要加载更多,属于一次性拿回全部
+	if (tab.value === 0) return
+  if (more.value === 'noMore') return
+
+  more.value = 'loading'
+  pageInfo.value.pageNo++
+  getProgressJobList()
+}
+
+const tabChange = (e) => {
+  tab.value = e.currentIndex
+  jobFairPosition.value = []
+  
+  if (tab.value === 0) return getJobList()
+  pageInfo.value.pageNo = 1
+  getProgressJobList()
+}
+
 onLoad((options) => {
 	id.value = options.id
 	if (!id.value) {
@@ -72,11 +128,19 @@ onLoad((options) => {
 	}
 
 	getJobFairInfo()
-	getJobFairPositionList()
+	getJobList()
 })
 
 onShow(() => {
-	if (id.value) getJobFairPositionList()
+	if (id.value) {
+    jobFairPosition.value = []
+    if (tab.value) {
+      pageInfo.value.pageNo = 1
+      getProgressJobList()
+      return
+    }
+    getJobList()
+  }
 })
 
 // 加入招聘会

+ 31 - 26
pagesB/jobFair/jobItem.vue

@@ -33,21 +33,22 @@
 					</view>
           <view class="sub-li-bottom ss-m-t-20">
 						<view class="sub-li-bottom-item color-primary" @tap.stop="handleToResume(item)">{{ item.count || 0 }} 已投递简历</view>
-						<view class="sub-li-bottom-item color-error" @tap.stop="handleRemove(item)">移出招聘会</view>
+						<view v-if="tab === 0" class="sub-li-bottom-item color-error" @tap.stop="handleAction(0, item.id)">关闭</view>
+						<view v-else class="sub-li-bottom-item color-primary" @tap.stop="handleAction(1, item.id)">激活</view>
           </view>
         </view>
 			</view>
 		</view>
 
-		<uni-popup ref="removePopup" type="dialog">
+		<uni-popup ref="popup" type="dialog">
 			<uni-popup-dialog 
 				type="warn" 
 				cancelText="取消" 
 				confirmText="确定" 
 				title="系统提示" 
-				content="是否确认将此职位移出招聘会?" 
-				@confirm="handleRemoveConfirm"
-				@close="handleRemoveClose"
+				:content="`是否确认${actionType === 0 ? '关闭' : '激活'}此职位?`" 
+				@confirm="handleActionConfirm"
+				@close="handleActionClose"
 			></uni-popup-dialog>
 		</uni-popup>
   </view>
@@ -56,14 +57,15 @@
 <script setup>
 import { ref } from 'vue'
 import { formatName } from '@/utils/getText'
-import { quitJobFairPosition } from '@/api/jobFair'
 import { getUserAvatar } from '@/utils/avatar'
+import { closeJobAdvertised, enableJobAdvertised } from '@/api/new/position'
 
 const emit = defineEmits(['refresh'])
 const props = defineProps({
 	list: Array,
 	jobFairId: [String, Number],
-	jobFairName: String
+	jobFairName: String,
+	tab: Number
 })
 
 // 查看职位详情
@@ -81,32 +83,35 @@ const handleToResume = (val) => {
 	})
 }
 
-// 移出招聘会
-const removePopup = ref()
-const removeParams = ref({})
-const handleRemove = (val) => {
-	removeParams.value = val
-	removePopup.value.open()
-}
-const handleRemoveClose = () => {
-	removeParams.value = {}
-  removePopup.value.close()
-}
-const handleRemoveConfirm = async () => {
-	if (!removeParams.value.id || !props.jobFairId) {
+// 职位激活、关闭
+const popup = ref()
+const actionId = ref('')
+const actionType = ref('')
+const handleAction = (type, id) => {
+	actionId.value = id
+	actionType.value = type
+	popup.value.open()
+}
+const handleActionClose = () => {
+	actionId.value = ''
+	actionType.value = ''
+	popup.value.close()
+}
+const handleActionConfirm = async () => {
+	if (!actionId.value || !props.jobFairId) {
 		uni.showToast({ title: '正在维护中,请稍后再试', icon: 'none', duration: 2000 })
 		return
 	}
 	uni.showLoading({ title: '加载中' })
+	const api = actionType.value === 0 ? closeJobAdvertised : enableJobAdvertised
 	try {
-		await quitJobFairPosition({ jobFairId: props.jobFairId, jobId: removeParams.value.id })
-		uni.hideLoading()
-		uni.showToast({ title: '移出成功', icon: 'none' })
-		removeParams.value = {}
+		await api(actionId.value)
+		uni.showToast({ title: '操作成功', icon: 'none' })
 		emit('refresh')
-	} catch {
-		removeParams.value = {}
+	} finally {
 		uni.hideLoading()
+		actionId.value = ''
+		actionType.value = ''
 	}
 }
 </script>