lifanagju_citu 2 ヶ月 前
コミット
889cf6cb2a
4 ファイル変更156 行追加100 行削除
  1. 14 0
      api/new/position.js
  2. 82 47
      components/PositionList/index.vue
  3. 58 52
      pages/index/position.vue
  4. 2 1
      utils/position.js

+ 14 - 0
api/new/position.js

@@ -0,0 +1,14 @@
+import request from "@/utils/request"
+
+// 招聘端-职位列表
+export const getJobAdvertisedList = (params) => {
+  return request({
+    url: '/app-api/menduner/system/recruit/job-advertised/page',
+    method: 'GET',
+    params,
+    custom: {
+      showLoading: true,
+      auth: true
+    }
+  })
+}

+ 82 - 47
components/PositionList/index.vue

@@ -1,66 +1,59 @@
 <template>
   <view class="ss-m-x-20">
     <!-- 岗位列表 -->
-    <view v-if="list.length > 0" class="ss-p-b-30 ss-p-t-20">
-      <view v-for="(item, index) in list" :key="index" class="mList" :class="{ 'disable': !jobFairId && item.job?.status === '1'}" @click="toDetail(item)">
+    <view v-if="data?.length" class="ss-p-b-30 ss-p-t-20">
+      <view v-for="(item, index) in data" :key="index" class="mList">
         <!-- 职位信息 -->
-        <view class="list-shape" :style="`border-radius: ${props.showEntInfo ? '12px 12px 0 0' : '12px'};`">
+        <view class="list-shape" style="border-radius: 12px;">
           <!-- 职位 -->
           <view class="titleBox my-5">
             <view style="display: flex;align-items: center;">
-              <view v-if="item.job?.hire" class="iconfont icon-a-1_zhaopin ss-m-r-10" style="color: #e03506; font-size: 25px;"></view>
-              <image v-if="props.jobFairId" src="/static/svg/jobFair.svg" class=" ss-m-r-10" style="width: 20px; height: 20px;"></image>
-              <rich-text v-if="item.job?.name?.indexOf('style') !== -1" class="job-name" :nodes="item.job.name"></rich-text>
-              <view v-else class="job-name">{{ formatName(item.job?.name) }}</view>
+              <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>
             </view>
           </view>
           <!-- 薪酬、工作地、学历、工作经验 -->
+          <view class="font-size-13 ellipsis ss-m-5" style="color: #808080;">
+            <span>{{item.positionName }}</span>
+          </view>
           <view class="d-flex align-center justify-space-between">
             <view class="font-size-13 ellipsis" style="flex: 1;">
               <span class="tag-gap" style="color: #808080;">
-                <span>{{item.job?.area?.str ?? '全国' }}</span>
-                <span class="divider-mx" v-if="item.job?.eduName">|</span>
-                <span>{{item.job?.eduName }}</span>
-                <span class="divider-mx" v-if="item.job?.expName">|</span>
-                <span>{{item.job?.expName }}</span>
+                <span>{{item.area?.str ?? '全国' }}</span>
+                <span class="divider-mx" v-if="item.eduName">|</span>
+                <span>{{item.eduName }}</span>
+                <span class="divider-mx" v-if="item.expName">|</span>
+                <span>{{item.expName }}</span>
                 <span class="divider-mx">|</span>
-                <span>{{!item.job?.payFrom && !item.job?.payTo ? '面议' : `${item.job?.payFrom}-${item.job?.payTo}${item.job?.payName ? '/' + item.job?.payName : ''}` }}</span>
+                <span>{{!item.payFrom && !item.payTo ? '面议' : `${item.payFrom}-${item.payTo}${item.payName ? '/' + item.payName : ''}` }}</span>
               </span>
+              <view class="font-size-13 ss-m-t-10" style="color: #808080;">
+                <view>刷新时间:{{ item.refreshTime ? timesTampChange(item.refreshTime, 'Y-M-D h:m') : '暂无' }}</view>
+              </view>
             </view>
-            <view class="d-flex flex-column align-center justify-center resumeCount">
-              <view style="font-size: 14px;">{{ item.job?.payFrom || 0 }}</view>
+            <view class="d-flex flex-column align-center justify-center resumeCount" @tap="handleToResume(item)">
+              <view style="font-size: 14px;">{{ item.payFrom || 0 }}</view>
               <view>已投递简历</view>
             </view>
           </view>
-          <!-- 岗位tag  -->
-          <view class="mt" v-if="showWelfareTag">
-            <uni-tag 
-              v-for="(tag,i) in item.job?.tagList || []"
-              :key="i"
-              class="tag-gap"
-              :text="tag"
-              inverted="false"
-              size="mini"
-              custom-style="background-color: #ececec;color:#666;border-color:#ececec;display: inline-block;"
-            />
-          </view>
-          <view style="text-align: end;" v-if="item.job?.hire">
-            <uni-tag
-              class="ss-m-l-10"
-              v-if="item?.job?.hirePrice && item?.job?.hirePrice > 0" 
-              :text="`赏金:${commissionCalculation(item.job.hirePrice / 100, 1)}元`"
-              inverted="false"
-              size="default"
-              custom-style="background-color: #e2f0ef; color:#00B760; border-color:#e2f0ef;"
-            />
-          </view>
-          <view class="font-size-13 color-999 ss-m-t-10">
-            <span>刷新时间:{{ item?.job?.refreshTime || item.job?.updateTime ? timesTampChange(item.job?.refreshTime || item.job.updateTime, 'Y-M-D h:m') : '暂无' }}</span>
-            <span class="divider-mx" v-if="item.job?.expName">|</span>
-            <span>到期时间:{{ item?.job?.expireTime ? timesTampChange(item.job.expireTime, 'Y-M-D') : '长期有效' }}</span>
+          <view class="font-size-13 color-666 ss-m-t-10">
+            <view class="ss-m-t-10">到期时间:{{ item.expireTime ? timesTampChange(item.expireTime, 'Y-M-D') : '长期有效' }}</view>
           </view>
           <view class="sub-li-bottom">
-            <span></span>
+            <!-- <view v-if="tab === 1">
+              <span class="cursor-pointer" @tap="handleAction(item.top ? 4 : 3, '', item)">{{ item.top ? '取消置顶' : $t('common.topping') }}</span>
+              <span class="divider-mx">|</span>
+              <span class="cursor-pointer" @tap="handleAction(0, '', item)">{{ $t('common.close') }}</span>
+            </view> -->
+            <!-- <span v-if="(item.status-0) === 99 && tab === 0" class="cursor-pointer color-primary" @tap="toPay(item)">发布</span> -->
+            <!-- <span class="divider-mx" v-if="tab !== 2 && tab !== 3">|</span> -->
+            <span v-if="tab === 2" class="cursor-pointer" @tap="handleAction(1, '', item, item)">激活</span>
+            <span class="divider-mx" v-if="tab === 2"></span>
+            <span class="cursor-pointer" @tap="handleDetail(item)">详情</span>  
+            <!-- <view v-if="tab !== 3">
+              <span class="divider-mx">|</span>
+              <span class="cursor-pointer" :style="{'color': item.edit ? '#333' : '#999'}" @tap="handleEdit(item)">{{ $t('common.edit') }}</span>
+            </view> -->
           </view>
         </view>
       </view>
@@ -74,24 +67,63 @@
 </template>
 
 <script setup>
-import { commissionCalculation } from '@/utils/position'
+// import { commissionCalculation } from '@/utils/position'
 import { timesTampChange } from '@/utils/date'
 import { formatName } from '@/utils/getText'
+import { ref, watch } from 'vue'
 const emit = defineEmits(['entClick'])
 
 const props = defineProps({
+  tab: { type: Number, default: 0 },
   list: { type: Array, default: () => [] },
   noMore: { type: Boolean, default: false },
   showWelfareTag: { type: Boolean, default: true }
 })
 
-//岗位详情
-const toDetail = (item) => {
-  if (!item?.job?.id) return
-  let url = `/pagesB/positionDetail/index?id=${item.job.id}&area=${item.job.areaName}`
+const data = ref()
+watch(
+  () => props.list, 
+  (newVal) => {
+    data.value = newVal?.length ? newVal : []
+  },
+  { immediate: true },
+  { deep: true }
+)
+
+// 职位关闭、激活、刷新、置顶
+const handleAction = async (index, type, { id }, item) => {
+}
+
+// 职位关闭、激活、刷新、置顶
+const handleEdit = async (val) => {
+  if (!val.id || !val.edit) {
+    uni.showToast({
+      title: '职位发布时间超过24小时的不支持编辑',
+      icon: 'none',
+      duration: 2000
+    })
+    return
+  } 
+}
+
+// 支付
+const toPay = async (val) => {
+}
+
+// 职位详情
+const handleDetail = (item) => {
+  if (!item.id) return
+  let url = `/pagesB/positionDetail/index?id=${item.id}&area=${item.areaName}`
   uni.navigateTo({ url })
 }
 
+// 查看职位投递简历
+const handleToResume = (val) => {
+  let path = `/recruit/enterprise/invite/resume?id=${val.id}`
+  if (val.bizId) path += `&jobFairId=${val.bizId}`
+  router.push(path)
+}
+
 </script>
 
 <style scoped lang="scss">
@@ -132,6 +164,9 @@ const toDetail = (item) => {
   text-align: right;
   border-top: 1px dashed #eee;
   margin-top: 10px;
+  padding-top: 10px;
+  font-size: 13px;
+  color: #666;
 }
 
 .salary-text {

+ 58 - 52
pages/index/position.vue

@@ -1,17 +1,17 @@
 <template>
   <view class="box defaultBgc">
-    <uni-segmented-control :current="current" :values="controlList" @clickItem="handleChange" styleType="text" activeColor="#00B760" style="background-color: #fff"></uni-segmented-control>
+    <uni-segmented-control :current="tab" :values="controlList" @clickItem="tabChange" styleType="text" activeColor="#00B760" style="background-color: #fff"></uni-segmented-control>
     <scroll-view class="scrollBox" :scroll-y="true" @scrolltolower="loadingMore" style="position:relative;">
       <view>
         <!-- -->
         <view class="white-bgc stick ss-p-t-20" style="border-radius: 5px;">
-          <view class="defaultBgc d-flex ss-m-x-20">
-            <view class="stickBtn" @click="handleClick(0)">待发布(<text class="ss-m-x-2">{{ unpublished }}</text>)</view>
-            <view class="stickBtn newPositionBtn" @click="handleClick(1)">发布新职位</view>
-          </view>
+          <!-- <view class="defaultBgc d-flex ss-m-x-20">
+            <view class="stickBtn" :style="`color: ${query.status==='99' ? '#00B760' :''}`" @tap=""><uni-icons v-if="query.status==='99'" class="ss-m-t-6 ss-m-r-4" color="#00B760" type="checkmarkempty" size="14"/>待发布(<text class="ss-m-x-2">{{ unpublishedCount }}</text>)</view>
+            <view class="stickBtn newPositionBtn" @tap="">发布新职位</view>
+          </view> -->
           <!-- 搜索条 -->
           <uni-search-bar
-            v-model="query.content"
+            v-model="query.name"
             radius="5"
             placeholder="输入关键字"
             cancelButton="none"
@@ -19,17 +19,17 @@
             @confirm="onSearch"
           ></uni-search-bar>
         </view>
-        <view v-if="noData" class="d-flex flex-column align-center justify-center" style="height: 80vh;">
+        <view v-if="!positionListData?.length && more !== 'loading'" class="d-flex flex-column align-center justify-center ss-m-t-30">
           <view class="nodata-img-parent">
             <image src="https://minio.citupro.com/dev/static/nodata.png" mode="widthFix" style="width: 100vw;height: 100vh;"></image>
           </view>
           <view class="color-999">暂无职位</view>
           <view class="f-horizon-center">
-            <button type="primary" size="default" class="ss-m-t-50" style="width: 60vw;" @click="fabClick">发布新职位</button>
+            <button type="primary" size="default" class="ss-m-t-50" style="width: 60vw;" @click="handleClick">发布新职位</button>
           </view>
         </view>
         <view v-else>
-          <PositionList v-if="positionListData?.length || more !== 'loading'" :list="positionListData" :noMore="false" :showJobFairEntrance="false"></PositionList>
+          <PositionList v-if="positionListData?.length" :tab="tab" :list="positionListData" :noMore="false"></PositionList>
           <uni-load-more :status="more" />
         </view>
       </view>
@@ -38,61 +38,68 @@
 </template>
 
 <script setup>
-import { ref, reactive } from 'vue'
+import { ref } from 'vue'
 import PositionList from '@/components/PositionList'
-import { dealDictObjData } from '@/utils/position'
-import { getJobAdvertisedSearch } from '@/api/position'
+import { dealDictArrayData } from '@/utils/position'
+import { getJobAdvertisedList } from '@/api/new/position'
 import { onShow } from '@dcloudio/uni-app'
 
+const tab = ref(2)
+const tabList = [
+  { label: '待发布', value: 0, status: 99 },
+  { label: '招聘中', value: 1, status: 0 },
+  { label: '已关闭', value: 2, status: 1 },
+  { label: '到期职位', value: 3 }
+]
+const controlList = tabList.map(e => e.label)
+const tabChange = (e) => {
+  tab.value = e.currentIndex
+  query.value.pageNo = 1
+  getData()
+}
 
-const more = ref('more')
-const noData = ref(false)
-const unpublished = ref(0)
-
+const total = ref(0)
 const positionListData = ref([])
-const query = reactive({
-  pageSize: 20, 
+const query = ref({
+  pageSize: 5, 
   pageNo: 1,
+  name: '',
 })
+const more = ref('more')
+
 const getData = async () => {
-  if (query.pageNo === 1) positionListData.value = []
-  if (query.pageNo <= 0) return
+  if (query.value.pageNo < 1) return
+  if (query.value.pageNo === 1) positionListData.value = []
   try {
     more.value = 'loading'
-    const res = await getJobAdvertisedSearch(query)
-    const list = res?.data?.list || []
+    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
     if (!list?.length) {
       more.value = 'noMore'
       return
     }
-    positionListData.value.push(...list.map(e => {
-      if (!e) {
-        return e
-      }
-      e.job = { ...e.job, ...dealDictObjData({}, e.job) }
-      e.enterprise = { ...e.enterprise, ...dealDictObjData({}, e.enterprise)}
-      return e
-    }))
-    if (positionListData.value.length === +res.data.total) {
+    // positionListData.value.concat(dealDictArrayData([], list))
+    positionListData.value.push(...dealDictArrayData([], list))
+    console.log('positionListData.value:', positionListData.value)
+    more.value = 'more'
+    if (positionListData.value.length === total.value) {
       more.value = 'noMore'
       return
     }
   } catch (error) {
-    query.pageNo--
+    query.value.pageNo--
     more.value = 'more'
-  } finally {
-    if (!positionListData.value?.length) {
-      noData.value = true
-    }
   }
 }
-
-const current = ref(0)
-const controlList = ['招聘中', '已关闭']
-
-const handleChange = (e) => {
-  current.value = e.currentIndex
-}
+getData()
 
 // 设置自定义tabbar选中值
 onShow(() => {
@@ -101,30 +108,25 @@ onShow(() => {
 
   // 设置当前tab页的下标index
   currentTabBar?.setData({ selected: 1 })
-  getData()
 })
 
 const onSearch = () => {
-  query.pageNo = 1
-  positionListData.value = []
+  query.value.pageNo = 1
   getData()
 }
 
 // 加载更多
 const loadingMore = () => {
   more.value = 'loading'
-  query.pageNo++
+  query.value.pageNo++
   getData()
 }
 
-const handleClick = (type) => {
-  let url = type ? '' : ''
-  if (!type && !unpublished.value) return
-  // 
+const handleClick = () => {
+  let url = ''
   if (url) {
     uni.navigateTo({ url })
   }
-
 }
 
 </script>
@@ -181,6 +183,10 @@ const handleClick = (type) => {
   border-left: 1px solid #c3c3c3;
 }
 
+.actColor{
+  color: #00B760;
+}
+
 // :deep(.uni-searchbar) {
 //   padding: 10px 30rpx;
 // }

+ 2 - 1
utils/position.js

@@ -58,7 +58,8 @@ export const dealDictArrayData = (res, list) => {
       const valueKey = data.nameKey ? data.nameKey : 'label'
       const idKey = data.valueKey ? data.valueKey : 'value'
       if (!dictObj[data.value] || !Object.keys(dictObj[data.value]).length) return
-      const result = ['expType', 'eduType'].includes(e) && !item[e] ? { label: `${e === 'expType' ? '工作经验' : '学历'}不限` } : dictObj[data.value].find(val => val[idKey] === item[e])
+      // 工作经验、学历为null则是不限
+      const result = ['expType', 'eduType'].includes(e) && !item[e] ? { label: `${e === 'expType' ? '工作经验' : '学历' }不限` } : dictObj[data.value].find(val => val[idKey] === item[e])
       if (!result) return
       item[data.label] = result[valueKey] || ''
     })