Browse Source

冲突合并

Xiao_123 2 months ago
parent
commit
f885b77c84
5 changed files with 170 additions and 700 deletions
  1. 14 0
      api/new/position.js
  2. 82 47
      components/PositionList/index.vue
  3. 58 52
      pages/index/position.vue
  4. 14 600
      pagesB/positionDetail/index.vue
  5. 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;
 // }

+ 14 - 600
pagesB/positionDetail/index.vue

@@ -27,15 +27,6 @@
             </view>
           </view>
           <view class="d-flex justify-space-between mt-5 align-center">
-            <!-- 收藏职位 -->
-            <view @click="handleCollection" style="width: 36px;">
-              <uni-icons
-                :type="isCollection ? 'heart-filled' : 'heart'"
-                color="#fc6d5e"
-                class="mr"
-                size="25"
-              ></uni-icons>
-            </view>
             <!-- 薪资 -->
             <view>
               <span v-if="!info.payFrom && !info.payTo" class="salary w-600">面议</span>
@@ -49,16 +40,6 @@
               {{ tag }}
             </view>
           </view>
-          <!-- 企业信息 -->
-          <view class="topLine mt-5 d-flex" @click="jumpToEnterpriseDetail(info.enterprise.id)">
-            <view class="avatarBox">
-              <image style="width: 40px; height: 40px;" :src="info.enterprise?.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'"></image>
-            </view>
-            <view >
-              <view class="contact-name">{{ info.contact?.name }}</view>
-              <view class="contact-info">{{ formatName(info.enterprise?.anotherName || info.enterprise?.name) }} {{ info.contact?.postNameCn ? '· ' + info.contact?.postNameCn : '' }}</view>
-            </view>
-          </view>
           <!-- 岗位职责 -->
           <view class="topLine fs14 mt-5">
             <view class="fs15 w-600 my5">岗位职责</view>
@@ -71,6 +52,16 @@
             <view v-if="!info.requirement"></view>
             <rich-text v-else class="htmlCss" :nodes="cleanedHtml(info.requirement)"></rich-text>
           </view>
+          <!-- HR信息 -->
+          <view class="topLine mt-5 d-flex">
+            <view class="avatarBox">
+              <image style="width: 40px; height: 40px;" :src="info.enterprise?.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'"></image>
+            </view>
+            <view >
+              <view class="contact-name">{{ info.contact?.name }}</view>
+              <view class="contact-info">{{ formatName(info.enterprise?.anotherName || info.enterprise?.name) }} {{ info.contact?.postNameCn ? '· ' + info.contact?.postNameCn : '' }}</view>
+            </view>
+          </view>
           <!-- 工作地址 -->
           <view class="topLine mt-5">
             <view class="fs15 w-600 my5">工作地址</view>
@@ -87,186 +78,29 @@
         </view>
       </view>
     </scroll-view>
-    <!-- 分享 投递 -->
-    <view class="bottom-sticky" v-if="!loading && jobId">
-      <view class="bottom-content">
-        <!-- 已登录可以分享 -->
-        <button v-if="beenLogin" class="bottom-content-tool shareButtonCss" open-type="share">
-          <uni-icons type="redo-filled" size="24" color="#00B760" style="line-height: 24px;"/>
-          <span style="color:#00B760;font-weight:bold;line-height: 22px;">分享</span>
-        </button>
-        <!-- 未登录点击分享拉起登录 -->
-        <view v-else @click="handleClickShare" class="bottom-content-tool">
-          <uni-icons type="redo-filled" size="24" color="#00B760"/>
-          <span style="color:#00B760;font-weight:bold;">分享</span>
-        </view>
-        <button class="btnStyle bgButtons" type="primary" plain="true" @tap="handleSend">立即沟通</button>
-        <button v-if="delivery" :disabled="true" class="buttons btnStyle disable">我已投递</button>
-        <button v-else class="buttons btnStyle" type="primary" @click="handleDelivery">我要投递</button>
-      </view>
-    </view>
-    <uni-popup
-        ref="poster"
-        type="center"
-        class="f-straight"
-        style="position: relative;"
-    >
-        <canvas
-          :style="{
-            width:`${appInfo.windowWidth}px;`,
-            height:`${appInfo.windowHeight}px;margin-left:-9999px; margin-top:-99.5vh;`
-          }" canvas-id="firstCanvas" id="firstCanvas"></canvas>
-        <image
-          :style="{ width:`${appInfo.windowWidth}px;`, height:`${appInfo.windowHeight*.9}px;`}"
-          :src="imgSrc"
-          mode="aspectFit"
-        />
-        <!-- <uni-icons v-if="!!imgSrc" type="clear" size="35" color="#FFF" style="position: absolute;top: 10px;right: 28px;" @click="posterClose"></uni-icons> -->
-    </uni-popup>
-    
-    <!-- 选择简历 -->
-    <uni-popup ref="popup" background-color="#fff" :mask-click="false" >
-      <view class="dialogBox" style="width: 86vw;">
-        <view class="dialog-title">
-          <view class="title">选择简历</view>
-          <uni-icons type="close" color="grey" size="26" @click="popupClose" />
-        </view>
-        <view style="height: 1px; margin: 0 20rpx; background-color: #dedede;"></view>
-        <scroll-view class="dialog-content" scroll-y="true" style="max-height: 50vh; width: auto;">
-          <uni-card
-            v-for="(item, index) in resumeList"
-            :key="index"
-            shadow="0px 0px 3px 1px rgba(0,0,0,0.1)"
-            :is-shadow="true"
-            :border='false'
-             background-color="red"
-            :class="{'selected': selectIndex === index}"
-            @click="selectIndex = index"
-          >
-            <view class="d-flex align-center">
-              <view style="flex: 1;">
-                <view style="font-weight: bold;">
-                  <uni-icons v-if="selectIndex === index" color="green" type="checkmarkempty" size="18"></uni-icons>
-                  {{ item.title }}
-                </view>
-                <view>上传时间:{{ timesTampChange(item.createTime, 'Y-M-D') }}</view>
-              </view>
-              <view class="ss-m-l-30" style="width: 60rpx;">
-                <uni-icons @click="preview(item.url)" type="eye" size="24"></uni-icons>
-              </view>
-            </view>
-          </uni-card>
-          <view class="selectOnline" @click="handleUpload">选取微信聊天文件</view>
-        </scroll-view>
-        <view class="dialog-bottom" @click="deliverySubmit()">确认投递</view>
-      </view>
-    </uni-popup>
-
-    <!-- 实习到岗时间 -->
-    <uni-popup ref="practicePopup" background-color="#fff" :mask-click="false" >
-      <view class="dialogBox">
-        <view class="dialog-title">
-          <view class="title">实习到岗信息</view>
-          <uni-icons type="close" color="grey" size="26" @click="practicePopupClose" />
-        </view>
-        <scroll-view class="dialog-content" scroll-y="true" style="max-height: 50vh; width: auto;">
-          <view v-if="isStudent" class="ss-p-x-50">
-            <studentDeliveryForm ref="studentDeliveryFormRef" />
-          </view>
-        </scroll-view>
-        <view class="dialog-bottom" @click="beforeHandleUploadSubmit()">确认</view>
-      </view>
-    </uni-popup>
-
-    <!-- 上传简历 -->
-    <uni-popup ref="uploadPopup" type="dialog">
-			<uni-popup-dialog
-        type="warn"
-        cancelText="取消"
-        confirmText="确定"
-        title="系统提示"
-        content="您还未上传过简历,是否选取微信聊天文件投递?"
-        @confirm="handleUpload"
-				@close="uploadPopup.close()"
-      ></uni-popup-dialog>
-		</uni-popup>
-
-    <!-- 职位分享 -->
-    <uni-popup ref="sharePopup" type="share">
-      <uni-popup-share title="分享到">
-        <view class="share-pop">
-          <button class="f-straight" open-type="share">
-            <view class="share-round share-round-1" >
-              <uni-icons type="weixin" color="#FFF" size="30" />
-            </view>
-            <view style="font-size:12px;">微信</view>
-          </button>
-        </view>
-      </uni-popup-share>
-    </uni-popup>
-
-    <!-- 当前是赏金职位时,询问是否登录,不登录则没有赏金 -->
-    <uni-popup ref="loginPopup" type="dialog">
-			<uni-popup-dialog 
-        type="warn" 
-        cancelText="取消" 
-        confirmText="登录" 
-        title="系统提示" 
-        content="当前为赏金职位,不登录进行分享将无法获得赏金,是否登录?" 
-        @confirm="handleLoginConfirm"
-				@close="handleLoginClose" />
-		</uni-popup>
-
-    <view class="hideCanvasView">
-      <canvas class="shareCanvas" canvas-id="shareCanvas" style="width: 452px; height: 362px;"></canvas>
-    </view>
   </layout-page>
 </template>
 
 <script setup>
-import { commissionCalculation, jumpToEnterpriseDetail } from '@/utils/position'
+import { commissionCalculation } from '@/utils/position'
 import { timesTampChange } from '@/utils/date'
-import { preview } from '@/utils/preview'
-import { uploadFile } from '@/api/file'
 import layoutPage from '@/layout'
-import { ref, watch, computed } from 'vue';
-import {
-  jobCvRelSend,
-  getPositionDetails,
-  jobCvRelCheckSend,
-  jobFairCvRelCheckSend,
-  getPersonJobUnfavorite, // 取消收藏
-  getPersonJobFavorite, // 收藏
-  getJobFavoriteCheck,
-  jobCvRelHireSend,
-  getShareDetail
-} from '@/api/position'
-import { getPersonResumeCv, saveResume } from '@/api/user'
+import { ref, watch } from 'vue';
+import { getPositionDetails } from '@/api/position'
 import { dealDictObjData } from '@/utils/position'
-import { getAccessToken, showNecessaryInfoPopup } from '@/utils/request'
-import { onLoad, onShareAppMessage } from '@dcloudio/uni-app'
-import { prologue, defaultText } from '@/hooks/useIM'
+import { onLoad } from '@dcloudio/uni-app'
 import { userStore } from '@/store/user'
 import { formatName } from '@/utils/getText'
-import studentDeliveryForm from '@/components/studentDeliveryForm'
-// import { getShareQueryById } from '@/api/jobFair.js'
 
 const useUserStore = userStore()
-const sharePopup = ref()
 const loading = ref(false)
 const loadingText = ref('加载中 . . . ')
 
 // 职位详情
 const info = ref({})
 const positionInfo = ref({})
-const isEmployment = ref(null)
-const imgSrc = ref('')
-const appInfo = ref({})
-const poster = ref()
 const beenLogin = ref(false)
-const isStudent = ref(false) // 已测试,待开放上线 const isStudent = computed(() => useUserStore.baseInfo?.type && Boolean(Number(useUserStore.baseInfo.type) === 1))
 const areaName = ref('')
-const canvasToTempFilePath = ref('')
 
 // 监听登录状态
 watch(() => useUserStore.refreshToken, (newVal) => {
@@ -274,182 +108,20 @@ watch(() => useUserStore.refreshToken, (newVal) => {
 }, { immediate: true }, { deep: true })
 
 let jobId = ''
-let jobFairId = ''
 const isJobFair = ref(false) // 是否是通过招聘会进入的岗位
 let obj = {}
 onLoad(async (options) => {
-  console.log(options, 'options')
   areaName.value = options?.area || ''
-
-  // 网站二维码分享
-  if (options.scene) {
-    const scene = decodeURIComponent(options.scene)
-    const str = scene.split('=')
-    const res = await getShareDetail({ id: str[1] })
-    obj = res.data
-  }
-
-  // 是否众聘
-  isEmployment.value = options?.sharedById || obj?.sharedById
-
   jobId = options?.id || options?.jobId || obj?.jobId || ''
-  jobFairId = options?.jobFairId !== 'undefined' && options.jobFairId !== 'null' && options.jobFairId || obj?.jobFairId || ''
-  // console.log(`${jobFairId?'是':'不是'}招聘会职位`, ',jobFairId:', jobFairId)
-  isJobFair.value = Boolean(jobFairId)
-  deliveryCheck()
-
   if (jobId) {
     loading.value = true
     loadingText.value = '加载中 . . . '
-    getCollectionStatus()
     getPositionDetail()
   } else {
     loadingText.value = '加载失败 . . . '
   }
 })
 
-// onShow(() => {
-//   if (!jobId) {
-//     return
-//   }
-// })
-
-const getImageTempRatio = (url) => {
-  return new Promise((req, rej)=>{
-    wx.getImageInfo({
-      src:url,
-      success:(res) =>{
-        req(res)
-      }
-    })
-  })
-}
-
-
-/**
-  ctx: 画布的上下文环境
-  fontSize: 文字大小
-  text: 绘制文本
-  maxWidth: 一行文字最大宽度
-  x:文本在x轴显示的位置
-  y:文本在y轴显示的位置
-  maxLine:最多绘制的行数
-**/
-//处理文字多出省略号显示
-const enterpriseNameLines = ref(0)
-const dealWords = (ctx, fontSize, text, maxWidth, x, y, maxLine, isEnterpriseName) => {
-  ctx.setFontSize(fontSize);//设置字体大小
-  var allRow = Math.ceil(ctx.measureText(text).width / maxWidth);//实际总共能分多少行
-  enterpriseNameLines.value = allRow
-  var count = allRow >= maxLine ? maxLine : allRow;//实际能分多少行与设置的最大显示行数比,谁小就用谁做循环次数
-  var endPos = 0;//当前字符串的截断点
-  for (var j = 0; j < count; j++) {
-    var nowStr = text.slice(endPos);//当前剩余的字符串
-    var rowWid = 0;//每一行当前宽度  
-    if (ctx.measureText(nowStr).width > maxWidth) {//如果当前的字符串宽度大于最大宽度,然后开始截取
-      for (var m = 0; m < nowStr.length; m++) {
-        rowWid += ctx.measureText(nowStr[m]).width;//当前字符串总宽度
-        if (rowWid > maxWidth) {            
-          if (j === maxLine - 1) { //如果是最后一行
-            ctx.fillText(nowStr.slice(0, m - 1) + '...', x, y + (j + 1) * 30);  //(j+1)*18这是每一行的高度    
-          } else {
-            ctx.fillText(nowStr.slice(0, m), x, y + (j + 1) * 30);
-          }
-          endPos += m;//下次截断点
-          break;
-        }
-      }
-    } else {
-      //如果当前的字符串宽度小于最大宽度就直接输出
-      ctx.fillText(nowStr.slice(0), x, (isEnterpriseName ? y + 2 : y) + (j + 1) * 30);
-    }
-  }
-}
-
-// 职位分享图片绘制
-const createPoster = async () => {
-  var context = uni.createCanvasContext('shareCanvas')
-
-  //清空画布
-  context.clearRect(0, 0, 452, 362);
-
-  //背景图片
-  context.drawImage('../../static/img/share-cover-border.jpg', 0, 0, 452, 362);
-  
-  // 岗位名称
-  context.setFillStyle('#333333')
-  dealWords(context, 25, formatName(positionInfo.value?.name), 350, 40, 30, 2)
-
-  // 工作地区、工作经验、学历要求
-  context.setFillStyle('#6c6e7b')
-  const area = areaName.value + ' | '
-  const combinationText = area + (positionInfo.value.expName || '') + (positionInfo.value.eduName ? ' | ' + positionInfo.value.eduName : '')
-  dealWords(context, 20, combinationText, 350, 40, 100, 1) // 上下文、字号、文本、最大宽度、x、y、行数
-
-  // 薪资
-  context.setFontSize(22)
-  context.setFillStyle('#f67272')
-  const { payFrom, payTo, payName } = positionInfo.value
-  const salary = payFrom && payTo ? payFrom + '-' + payTo + (payName ? '元/'+ payName : '') : '面议'
-  context.fillText(salary, 40, 170)
-
-  // 间隔线
-  context.setLineDash([2, 4], 1)
-  context.beginPath()
-  context.moveTo(40, 195)
-  context.lineTo(412, 195)
-  context.setStrokeStyle('#00B760')
-  context.stroke()
-
-  // 企业头像
-  const { logoUrl, anotherName, industryName, scaleName, name } = positionInfo.value.enterprise
-  const {path : headImg} = await getImageTempRatio(logoUrl ? logoUrl : 'https://minio.citupro.com/dev/menduner/company-avatar.png')
-  context.drawImage(headImg, 40, 220, 90, 90)
-
-  // 企业名称
-  context.setFillStyle('#000000')
-  dealWords(context, 25, formatName(anotherName || name), 250, 150, 210, 2, true)
-
-  // 企业行业类型、规模
-  context.setFontSize(20)
-  let industry = industryName && industryName.length > 6 ? `${industryName.slice(0, 7)}...` : industryName
-  context.setFillStyle('#6c6e7b')
-  context.fillText(`${industry || ''}${scaleName ? ' | ' + scaleName : ''}`, 150, enterpriseNameLines.value === 1 ? 280 : 310)
-
-  context.draw(false, () =>{
-    wx.canvasToTempFilePath({ 
-      canvasId: 'shareCanvas',
-      success:(res)=>{
-        canvasToTempFilePath.value = res.tempFilePath
-        console.log('canvas-success', canvasToTempFilePath.value)
-      },
-      fail:(err)=>{
-        console.log('canvasToTemp-fail', err)
-      }
-    })
-  })
-}
-
-//在点击open-type="share"按钮后会触发以下函数,可以在函数中写需要的逻辑,当然函数的返回值必须是一个对象,用于设置分享卡片的展示形式
-//发送给微信好友  
-onShareAppMessage((res) => {
-  let path = `/pagesB/positionDetail/index?jobId=${info.value.id}`
-  if (info.value.hire) {
-    path += `&sharedById=${useUserStore.accountInfo.userId}`
-  }
-  if (jobFairId) {
-    path += `&jobFairId=${jobFairId}`
-  }
-  if(!canvasToTempFilePath.value){
-		setTimeout(() => {},1000)
-	}
-  return {
-    title: '我发现了一个好职位,快来看看吧',
-    path,
-    imageUrl: canvasToTempFilePath.value
-  }
-})
-
 // 富文本内容处理,去除多余的换行空格等
 const cleanedHtml = (text) => {
   const cleaned = text.replace(/\n/g, '<br>')
@@ -471,268 +143,10 @@ async function getPositionDetail () {
     positionInfo.value = { ...dealDictObjData({}, info.value), ...info.value, enterprise: dealDictObjData({}, data.enterprise) }
     loading.value = false
     areaName.value = positionInfo.value.area?.str ?? '全国'
-    // 生成分享图片
-    createPoster()
-  } finally {
-  }
-}
-// 效验是否有投递过简历
-const delivery = ref(false) // 是否已投递简历
-async function deliveryCheck () {
-  try {
-    if (!getAccessToken() || !jobId) return delivery.value = false
-    const params = { jobId, ...(jobFairId && { jobFairId }) }
-    const api =  params.jobFairId ? jobFairCvRelCheckSend : jobCvRelCheckSend
-    const { data } = await api(params)
-    delivery.value = Boolean(data)
   } finally {
   }
 }
 
-import { showAuthModal } from '@/hooks/useModal'
-const popup = ref()
-const uploadPopup = ref()
-const resumeList = ref([])
-const selectIndex = ref(null)
-
-const practicePopupClose = () => {
-  practicePopup.value.close()
-}
-const beforeHandleUpload = async () => {
-  practicePopup.value.open()
-}
-
-const practicePopup = ref()
-let practiceData = null
-const beforeHandleUploadSubmit = async () => {
-  practiceData = await studentDeliveryFormRef.value.getQueryParams()
-  if (!practiceData) {
-    return
-  }
-  practicePopupClose()
-  handleOpen(true)
-}
-
-const handleOpen = async (retry) => {
-  if (isStudent.value && !retry) {
-    beforeHandleUpload()
-    return
-  }
-
-  // 未上传简历
-  if (!resumeList.value?.length) {
-    return uploadPopup.value.open()
-  }
-  popup.value.open()
-}
-
-const handleDelivery = async () => {
-  // 未登录
-  if (!getAccessToken()) {
-    uni.showToast({
-      title:'请先登录',
-      icon: 'none'
-    })
-    showAuthModal()
-    return
-  }
-  if (showNecessaryInfoPopup()) {
-		uni.showToast({
-			title: '请先完善基本信息',
-			icon: 'none'
-		})
-		showAuthModal('necessaryInfo')
-		return
-	}
-  // 已投递
-  if (delivery.value) {
-    uni.showToast({ title: '您已投递过该职位!', icon: 'none', duration: 2000, })
-    return
-  }
-
-  // 获取附件简历
-  const { data } = await getPersonResumeCv()
-  resumeList.value = data
-
-  // 消息订阅
-  const tmplIds = ['2KOkuFsB-2MrvnQa_45OvqMJ9ik37Xz43YXPApiQ9es', 'tUTwKQTdWnZsen7Nhtu0ksMQj0lkEuMt2nBzCrm_7vY']
-  wx.requestSubscribeMessage({
-    tmplIds,
-    success:(res)=>{
-      console.log(res, 'uni.requestSubscribeMessage-res')
-      if (res[tmplIds[0]] === 'accept' || res[tmplIds[1]] === 'accept') {
-        console.log('订阅成功', res)
-        handleOpen()
-      }
-    },
-    fail:(err)=>{
-      console.log('订阅失败', err)
-      handleOpen()
-    }
-  })
-}
-
-const studentDeliveryFormRef = ref()
-const deliverySubmit = async (uploadFile) => {
-  const resume = uploadFile ? uploadFile : resumeList.value[selectIndex.value]
-  if (!resume) {
-    selectIndex.value = null
-    uni.showToast({ title: '请选择简历', icon: 'none', duration: 2000, })
-    return
-  }
-
-  let params = {
-    jobId,
-    url: resume.url,
-    ...(jobFairId && { jobFairId })
-  }
-  if (isStudent.value) {
-    if (!practiceData) {
-      handleOpen()
-      return
-    }
-    params = Object.assign(params, practiceData)
-  }
-
-  if (isEmployment.value) {
-    params.recommendUserId = isEmployment.value
-    await jobCvRelHireSend(params)
-  } else {
-    params.type = info.value.hire ? 1 : 0
-    params.title = resume.title
-    await jobCvRelSend(params)
-  }
-  
-  uni.showToast({ title: '投递成功', icon: 'none', duration: 2000, })
-  deliveryCheck()
-  popup.value.close()
-}
-
-const popupClose = () => {
-  selectIndex.value = null
-  popup.value.close()
-}
-
-// 发起聊天
-async function handleSend () {
-  if (!getAccessToken()) {
-    showAuthModal()
-    return
-  }
-  if (showNecessaryInfoPopup()) {
-		uni.showToast({
-			title: '请先完善基本信息',
-			icon: 'none'
-		})
-		showAuthModal('necessaryInfo')
-		return
-	}
-  const userId = info.value.contact.userId
-  const enterpriseId = info.value.contact.enterpriseId
-  const textObj = {
-    text: defaultText,
-    positionInfo: positionInfo.value,
-    
-  }
-  const channel = await prologue({userId, enterpriseId, text: JSON.stringify(textObj)})
-  // 跳转
-  const query = {
-		id: userId,
-    isEmployment: isEmployment.value ? isEmployment.value : '-1',
-		name: info.value?.contact?.name,
-		postName: info.value?.contact?.postNameCn,
-		enterpriseName: info.value?.enterprise?.anotherName,
-		enterpriseId: info.value?.enterpriseId,
-		channelID: channel.channelID,
-		channelType: channel.channelType,
-		avatar: info.value?.contact?.avatar,
-		sex: info.value?.contact?.sex,
-    // ...(jobFairId && { jobFairId }),
-	}
-	const queryStr = Object.keys(query).reduce((r, v) => {
-		return r += `${v}=${encodeURIComponent(query[v])}&`
-	}, '?')
-	uni.navigateTo({
-    url: `/pagesA/chart/index${queryStr.slice(0, -1)}`
-  })
-}
-
-// 效验求职者是否有收藏该职位
-const isCollection = ref(false)
-const getCollectionStatus = async () => {
-  if (!getAccessToken()) return isCollection.value = false
-  const { data } = await getJobFavoriteCheck({ jobId })
-  isCollection.value = Boolean(data)
-}
-
-// 操作 收藏&取消收藏职位
-const handleCollection = async () => {
-  const api = isCollection.value ? getPersonJobUnfavorite : getPersonJobFavorite
-  await api(isCollection.value ? jobId : { jobId })
-  await getCollectionStatus()
-}
-
-// 选取微信聊天文件
-// 上传附件
-const handleUpload = () => {
-  wx.chooseMessageFile({
-    count: 1,
-    type: 'file',
-    success (res) {
-      // 限制文件上传大小
-      const size = res.tempFiles[0].size
-      if (size / (1024*1024) > 20) {
-        uni.showToast({ icon: 'none', title: '文件大小不能超过20M' })
-        return
-      }
-
-      const title = res.tempFiles[0].name
-      const path = res.tempFiles[0].path
-      //效验是否为支持的文件格式
-      if(/\.(pdf|docx|doc)$/.test(title)){
-        uploadFile(path, 'attachment').then(async (res) => {
-          if (!res.data) {
-            uni.showToast({
-              title: '上传失败',
-              icon: 'none'
-            })
-            return
-          }
-          await saveResume({ title, url: res.data })
-          uni.showToast({
-            title: '上传成功',
-            icon: 'success'
-          })
-          deliverySubmit({ title, url: res.data })
-        })
-      }else{
-        uni.showToast({
-          icon: 'none',
-          title: '请上传pdf、doc、docx类型的文件',
-          duration: 2000
-        })
-        return
-      }
-    }
-  })
-}
-
-// 分享
-const loginPopup = ref()
-const handleClickShare = () => {
-  // 如果当前职位是赏金职位且没有登录的状态,则弹窗询问是否需要登录;普通职位登录与不登录都可直接分享
-  if (!getAccessToken() && info.value.hire) return loginPopup.value.open()
-  sharePopup.value.open()
-}
-
-// 取消则直接弹窗分享
-const handleLoginClose = () => {
-  sharePopup.value.open()
-}
-// 确认则弹窗登录
-const handleLoginConfirm = () => {
-  showAuthModal()
-}
 </script>
 
 <style scoped lang="scss">

+ 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] || ''
     })