Parcourir la source

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

lifanagju_citu il y a 11 mois
Parent
commit
dc2bcbb301

+ 16 - 0
src/api/position.js

@@ -87,3 +87,19 @@ export const getJobAreaByEnterpriseId = async (params) => {
     params
   })
 }
+
+// 效验招聘职位是否投递
+export const jobCvRelCheckSend = async (params) => {
+  return await request.get({
+    url: '/app-api/menduner/system/job-cv-rel/check/send',
+    params
+  })
+}
+
+// 投递简历
+export const jobCvRelSend = async (data) => {
+  return await request.post({
+    url: '/app-api/menduner/system/job-cv-rel/send',
+    data
+  })
+}

+ 24 - 16
src/api/resume.js

@@ -3,7 +3,7 @@ import request from '@/config/axios'
 // 保存基本信息
 export const saveResumeBasicInfo = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/info',
+    url: '/app-api/menduner/system/person/resume/info/save',
     data
   })
 }
@@ -11,7 +11,7 @@ export const saveResumeBasicInfo = async (data) => {
 // 保存个人优势
 export const saveResumeAdvantage = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/advantage',
+    url: '/app-api/menduner/system/person/resume/advantage/save',
     data
   })
 }
@@ -19,7 +19,7 @@ export const saveResumeAdvantage = async (data) => {
 // 保存培训经历
 export const saveResumeTrainExp = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/train/exp',
+    url: '/app-api/menduner/system/person/resume/train/exp/save',
     data
   })
 }
@@ -27,7 +27,7 @@ export const saveResumeTrainExp = async (data) => {
 // 删除培训经历
 export const deleteResumeTrainExp = async (id) => {
   return await request.delete({
-    url: '/app-api/menduner/system/person/resume/remove/train/exp?id=' + id
+    url: '/app-api/menduner/system/person/resume/train/exp/remove?id=' + id
   })
 }
 
@@ -48,14 +48,14 @@ export const getResumeEduExp = async () => {
 // 删除-教育经历
 export const deleteResumeEduExp = async (id) => {
   return await request.delete({
-    url: '/app-api/menduner/system/person/resume/remove/edu/exp?id=' + id
+    url: '/app-api/menduner/system/person/resume/edu/exp/remove?id=' + id
   })
 }
 
 // 保存-教育经历
 export const saveResumeEduExp = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/edu/exp',
+    url: '/app-api/menduner/system/person/resume/edu/exp/save',
     data
   })
 }
@@ -70,14 +70,14 @@ export const getResumeWorkExp = async () => {
 // 删除-工作经历
 export const deleteResumeWorkExp = async (id) => {
   return await request.delete({
-    url: '/app-api/menduner/system/person/resume/remove/work/exp?id=' + id
+    url: '/app-api/menduner/system/person/resume/work/exp/remove?id=' + id
   })
 }
 
 // 保存-工作经历
 export const saveResumeWorkExp = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/work/exp',
+    url: '/app-api/menduner/system/person/resume/work/exp/save',
     data
   })
 }
@@ -85,7 +85,7 @@ export const saveResumeWorkExp = async (data) => {
 // 保存项目经历
 export const saveResumeProjectExp = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/project/exp',
+    url: '/app-api/menduner/system/person/resume/project/exp/save',
     data
   })
 }
@@ -93,7 +93,7 @@ export const saveResumeProjectExp = async (data) => {
 // 删除项目经历
 export const deleteResumeProjectExp = async (id) => {
   return await request.delete({
-    url: '/app-api/menduner/system/person/resume/remove/project/exp?id=' + id
+    url: '/app-api/menduner/system/person/resume/project/exp/remove?id=' + id
   })
 }
 
@@ -114,14 +114,14 @@ export const getResumePersonSkill = async () => {
 // 删除-职业技能
 export const deleteResumePersonSkill = async (id) => {
   return await request.delete({
-    url: '/app-api/menduner/system/person/resume/remove/person/skill?id=' + id
+    url: '/app-api/menduner/system/person/resume/person/skill/remove?id=' + id
   })
 }
 
 // 保存-职业技能
 export const saveResumePersonSkill = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/person/skill',
+    url: '/app-api/menduner/system/person/resume/person/skill/save',
     data
   })
 }
@@ -129,7 +129,7 @@ export const saveResumePersonSkill = async (data) => {
 // 保存求职意向
 export const saveResumeJobInterested = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/job/interested',
+    url: '/app-api/menduner/system/person/resume/job/interested/save',
     data
   })
 }
@@ -137,7 +137,7 @@ export const saveResumeJobInterested = async (data) => {
 // 删除求职意向
 export const deleteResumeJobInterested = async (id) => {
   return await request.delete({
-    url: '/app-api/menduner/system/person/resume/remove/job/interested?id=' + id
+    url: '/app-api/menduner/system/person/resume/job/interested/remove?id=' + id
   })
 }
 
@@ -175,7 +175,7 @@ export const enterpriseSearchByName = async (params) => {
 // 保存附件
 export const savePersonResumeCv = async (data) => {
   return await request.post({
-    url: '/app-api/menduner/system/person/resume/save/person/cv',
+    url: '/app-api/menduner/system/person/resume/person/cv/save',
     data
   })
 }
@@ -183,7 +183,7 @@ export const savePersonResumeCv = async (data) => {
 // 删除附件
 export const deletePersonResumeCv = async (id) => {
   return await request.delete({
-    url: '/app-api/menduner/system/person/resume/remove/person/cv?id=' + id
+    url: '/app-api/menduner/system/person/resume/person/cv/remove?id=' + id
   })
 }
 
@@ -193,3 +193,11 @@ export const getPersonResumeCv = async () => {
     url: '/app-api/menduner/system/person/resume/get/person/cv'
   })
 }
+
+// 修改求职类型
+export const updateJobStatus = async (data) => {
+  return await request.post({
+    url: '/app-api/menduner/system/person/resume/job/status/update',
+    data
+  })
+}

+ 1 - 1
src/components/CtDialog/index.vue

@@ -58,7 +58,7 @@
 <script setup>
 import { ref, defineEmits, computed, watch  } from 'vue'
 defineOptions({ name: 'components-ct-dialog' })
-const emits = defineEmits('update:visible', 'close', 'submit')
+const emits = defineEmits(['update:visible', 'close', 'submit'])
 
 const props = defineProps({
   bodyStyle: {

+ 3 - 3
src/components/Enterprise/info.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="info-box">
-    <h4 class="mb-3">公司信息</h4>
+    <h4 class="mb-3">{{ $t('enterprise.companyInfo') }}</h4>
     <div style="height: 50px;">
       <v-img class="float-left" :src="props.info.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'" :width="45" height="45"></v-img>
       <div class="ml-3 float-left">
@@ -16,8 +16,8 @@
       </div>
     </div>
     <div style="font-size: 12px;height: 50px; line-height: 50px">
-      <span class="float-left"><span style="color: var(--v-primary-base)">9</span>个在招职位</span>
-      <span class="float-right more-position" @click="handleEnterprise(1)">查看全部职位<v-icon>mdi-chevron-right</v-icon></span>
+      <span class="float-left"><span style="color: var(--v-primary-base)">9</span>{{ $t('position.recruitmentPosition') }}</span>
+      <span class="float-right more-position" @click="handleEnterprise(1)">{{ $t('position.allBtn') }}<v-icon>mdi-chevron-right</v-icon></span>
     </div>
   </div>
 </template>

+ 7 - 6
src/components/Position/similarPositions.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="position-box">
-    <h4 class="mb-3">相似职位</h4>
+    <h4 class="mb-3">{{ $t('position.similarPosition') }}</h4>
     <div v-for="(item, index) in props.list" :key="index" class="mb-2 cursor-pointer" @click="handlePosition(item)">
       <p class="recruit-name">{{ item.name }}</p>
       <span class="recruit-salary">{{ item.payFrom }}-{{ item.payTo }}/{{ item.payName }}</span>
@@ -11,7 +11,7 @@
       </div>
     </div>
     <div class="text-center more-btn">
-      <v-btn color="primary" variant="outlined" class="buttons" :to="`/company/details/${props.info.enterpriseId}?key=recruitmentPositions`">查看全部职位</v-btn>
+      <v-btn color="primary" variant="outlined" class="buttons" :to="`/company/details/${props.info.enterpriseId}?key=recruitmentPositions`">{{ $t('position.allBtn') }}</v-btn>
     </div>
   </div>
 </template>
@@ -34,8 +34,8 @@ const handlePosition = (item) => {
 
 <style lang="scss" scoped>
 .position-box {
-  position: relative;
-  height: 430px;
+  // position: relative;
+  // height: 430px;
   background-color: #f3f3f3;
   border-radius: 8px;
   padding: 20px 15px;
@@ -85,7 +85,8 @@ const handlePosition = (item) => {
   font-size: 13px;
 }
 .more-btn {
-  position: absolute;
-  bottom: 18px;
+  // position: absolute;
+  // bottom: 18px;
+  // margin-top: 20px;
 }
 </style>

+ 20 - 2
src/locales/en.js

@@ -6,6 +6,7 @@ export default {
     cancel: 'Cancel',
     save: 'Save',
     add: 'Add',
+    toUpload: 'Go upload',
     change: 'Change',
     complete: 'Complete',
     saveMsg: 'Save successful',
@@ -18,7 +19,8 @@ export default {
     uploadSucMsg: 'Upload successful',
     uploadErrMsg: 'Upload failed',
     fileSizeExceed: 'The file size cannot exceed 10M',
-    fileFormatIncorrect: 'The uploaded file format is incorrect'
+    fileFormatIncorrect: 'The uploaded file format is incorrect',
+    refresh: 'Refresh'
   },
   sys: {
     api: {
@@ -97,8 +99,19 @@ export default {
     screen: 'Screen',
     positionName: 'Please enter the position name',
     popularPosition: 'Popular positions',
+    submitResume: 'Submit resume',
+    communicate: 'Communicate immediately',
+    currentOnline: 'Currently online',
+    jobResponsibilities: 'Job responsibilities',
+    jobRequirements: 'Job requirements',
+    cancelFavorite: 'Cancel Favorite',
+    collection: 'Collection',
+    recruitmentPosition: 'Recruitment positions',
+    similarPosition: 'Similar positions',
+    address: 'Work address'
   },
   enterprise: {
+    companyInfo: 'Company Information',
     moreBtn: 'View More Enterprises',
     joiningEnterprise: 'Joining Enterprise',
     registeringNewEnterprise: 'Registering A New Enterprise',
@@ -125,7 +138,12 @@ export default {
     expand: 'Expand',
     retract: 'Retract',
     deleteAttachment: 'Are you sure to delete this attachment?',
-    uploadFiveCopies: 'Upload up to 5 copies'
+    uploadFiveCopies: 'Upload up to 5 copies',
+    selectResumeToSubmit: 'Please select the resume to be submitted',
+    resumeYetSubmit: 'You have not uploaded your resume yet. Please upload your resume first before submitting it',
+    alreadyResume: 'You have already submitted your resume, please do not resubmit it',
+    deliverySuccess: 'Delivery successful',
+    selectedResumeNotExist: 'The currently selected resume does not exist'
   },
   setting: {
     accountSettings: 'Account Settings',

+ 21 - 3
src/locales/zh-CN.js

@@ -6,6 +6,7 @@ export default {
     cancel: '取消',
     save: '保存',
     add: '新增',
+    toUpload: '去上传',
     change: '更改',
     complete: '完成',
     saveMsg: '保存成功',
@@ -18,7 +19,8 @@ export default {
     uploadSucMsg: '上传成功',
     uploadErrMsg: '上传失败',
     fileSizeExceed: '文件大小不能超过10M',
-    fileFormatIncorrect: '上传的文件格式不正确'
+    fileFormatIncorrect: '上传的文件格式不正确',
+    refresh: '刷新'
   },
   sys: {
     api: {
@@ -96,9 +98,20 @@ export default {
     newPositionsAdded: '新增职位',
     screen: '筛选',
     positionName: '请输入职位名称',
-    popularPosition: '热门职位'
+    popularPosition: '热门职位',
+    submitResume: '投递简历',
+    communicate: '立即沟通',
+    currentOnline: '当前在线',
+    jobResponsibilities: '岗位职责',
+    jobRequirements: '岗位要求',
+    cancelFavorite: '取消收藏',
+    collection: '收藏',
+    recruitmentPosition: '在招职位',
+    similarPosition: '相似职位',
+    address: '工作地址'
   },
   enterprise: {
+    companyInfo: '公司信息',
     moreBtn: '查看更多企业',
     joiningEnterprise: '加入已有企业',
     registeringNewEnterprise: '注册新企业',
@@ -125,7 +138,12 @@ export default {
     expand: '展开',
     retract: '收起',
     deleteAttachment: '是否确认删除此附件?',
-    uploadFiveCopies: '最多上传5份'
+    uploadFiveCopies: '最多上传5份',
+    selectResumeToSubmit: '请选择要投递的简历',
+    resumeYetSubmit: '您还未上传过简历,请先上传简历后再投递',
+    alreadyResume: '您已投递过简历,请勿重复投递',
+    deliverySuccess: '投递成功',
+    selectedResumeNotExist: '当前选择的简历不存在'
   },
   setting: {
     accountSettings: '账号设置',

+ 104 - 40
src/views/recruit/position/components/details.vue

@@ -1,41 +1,41 @@
 <template>
   <div>
-      <div class="default-width banner px-6">
-        <div class="banner-title">
-          <h1 class="ellipsis">{{ info.name }}</h1>
-          <span class="salary">{{ info.payFrom }}-{{ info.payTo }}/{{ positionInfo.payName }}</span>
-          <span class="refresh-time">{{ timesTampChange(info.updateTime) }} 刷新 <v-icon color="warning" size="20">mdi-alert-outline</v-icon></span>
-        </div>
-        <div class="banner-tags mt-4">
-          <span v-for="k in desc" :key="k.mdi" class="mr-10">
-            <v-icon color="#666" size="20">{{ k.mdi }}</v-icon>
-            <span class="ml-1">{{ positionInfo[k.value] }}</span>
-          </span>
-        </div>
-        <div class="banner-tools my-4" style="height: 47px;">
-          <div class="float-left" style="line-height: 40px;">
-            <v-chip size="small" label v-for="(k, i) in info.tagList" :key="i" class="mr-1" color="primary">{{ k }}</v-chip>
-          </div>
-          <div class="banner-tools-btns float-right">
-            <v-btn class="radius mr-2" variant="outlined" color="error" prepend-icon="mdi-share-outline" style="width: 187px; height: 36px;">分享 赚小钱赚大钱</v-btn>
-            <v-btn
-              class="button-item radius"
-              color="warning" 
-              variant="outlined" 
-              :prepend-icon="isCollection ? 'mdi-heart' : 'mdi-heart-outline'"
-              @click="handleCollection"
-            >{{ isCollection ? '取消收藏': '收藏' }}</v-btn>
-            <v-btn class="button-item mx-2 radius" color="success" variant="outlined">立即沟通</v-btn>
-            <v-btn class="button-item radius" color="primary" variant="outlined">投递简历</v-btn>
-          </div>
+    <div class="default-width banner px-6">
+      <div class="banner-title">
+        <h1 class="ellipsis">{{ info.name }}</h1>
+        <span class="salary">{{ info.payFrom }}-{{ info.payTo }}/{{ positionInfo.payName }}</span>
+        <span class="refresh-time">{{ timesTampChange(info.updateTime) }} {{ $t('common.refresh') }} <v-icon color="warning" size="20">mdi-alert-outline</v-icon></span>
+      </div>
+      <div class="banner-tags mt-4">
+        <span v-for="k in desc" :key="k.mdi" class="mr-10">
+          <v-icon color="#666" size="20">{{ k.mdi }}</v-icon>
+          <span class="ml-1">{{ positionInfo[k.value] }}</span>
+        </span>
+      </div>
+      <div class="banner-tools my-4">
+        <v-chip size="small" label v-for="(k, i) in info.tagList" :key="i" class="mr-1" color="primary">{{ k }}</v-chip>
+      </div>
+      <div class="d-flex justify-end mb-5">
+        <div class="banner-tools-btns">
+          <v-btn class="radius mr-2" variant="outlined" color="error" prepend-icon="mdi-share-outline" style="width: 187px; height: 36px;">分享 赚小钱赚大钱</v-btn>
+          <v-btn
+            class="button-item radius"
+            color="warning" 
+            variant="outlined" 
+            :prepend-icon="isCollection ? 'mdi-heart' : 'mdi-heart-outline'"
+            @click="handleCollection"
+          >{{ isCollection ? $t('position.cancelFavorite') : $t('position.collection') }}</v-btn>
+          <v-btn class="button-item mx-2 radius" color="success" variant="outlined">{{ $t('position.communicate') }}</v-btn>
+          <v-btn class="button-item radius" color="primary" variant="outlined" @click="handleDelivery">{{ $t('position.submitResume') }}</v-btn>
         </div>
-        <v-divider></v-divider>
-        <div class="d-flex">
+      </div>
+      <v-divider></v-divider>
+      <div class="d-flex">
           <div class="content-left">
             <div v-if="Object.keys(info).length">
-              <div>岗位职责:</div>
+              <div>{{ $t('position.jobResponsibilities') }}:</div>
               <div class="requirement" v-html="info.content.replace(/\n/g, '</br>')"></div>
-              <div class="mt-3">岗位要求:</div>
+              <div class="mt-3">{{ $t('position.jobRequirements') }}:</div>
               <div class="requirement" v-html="info.requirement.replace(/\n/g, '</br>')"></div>
             </div>
             <v-divider class="my-3"></v-divider>
@@ -48,20 +48,20 @@
                 </div>
               </div>
               <div class="float-right">
-                <v-chip color="primary" label>当前在线</v-chip>
+                <v-chip color="primary" label>{{ $t('position.currentOnline') }}</v-chip>
               </div>
             </div>
             <v-divider class="my-3"></v-divider>
             <div>
-              <h4>工作地址</h4>
+              <h4>{{ $t('position.address') }}</h4>
               <div class="mt-1">
                 <v-icon size="25" color="primary">mdi-map-marker</v-icon>
                 <span style="color: #666;font-size: 15px;">{{ info.address }}</span>
               </div>
             </div>
             <div class="mt-3 text-center">
-              <v-btn class="half-button mr-2 radius" color="success" variant="outlined">立即沟通</v-btn>
-              <v-btn class="half-button radius" color="primary">投递简历</v-btn>
+              <v-btn class="mr-2 radius" color="success" variant="outlined">{{ $t('position.communicate') }}</v-btn>
+              <v-btn class="radius" color="primary" @click="handleDelivery">{{ $t('position.submitResume') }}</v-btn>
             </div>
           </div>
           <div class="content-right" v-if="Object.keys(info).length">
@@ -70,8 +70,29 @@
             <!-- 相似职位 -->
             <similarPositions class="mt-3" :list="similarList" :info="info"></similarPositions>
           </div>
-        </div>
       </div>
+    </div>
+
+    <!-- 弹窗提示去上传简历 -->
+    <v-dialog v-model="dialog" max-width="400" persistent>
+      <v-card :text="$t('resume.resumeYetSubmit')" :title="$t('common.confirmTitle')">
+        <template #prepend>
+          <v-icon color="warning">mdi-alert-circle-outline</v-icon>
+        </template>
+        <template v-slot:actions>
+          <v-spacer></v-spacer>
+          <v-btn @click="dialog = false">{{ $t('common.cancel') }}</v-btn>
+          <v-btn color="success" @click="handleToUpload">{{ $t('common.toUpload') }}</v-btn>
+        </template>
+      </v-card>
+    </v-dialog>
+
+    <!-- 选择简历 -->
+    <Dialog :visible="showResume" :widthType="2" :title="$t('resume.selectResumeToSubmit')" @close="handleClose" @submit="handleSubmit">
+      <v-radio-group v-model="selectResume">
+        <v-radio v-for="val in resumeList" :key="val.id" :value="val.id" :label="val.title" color="primary"></v-radio>
+      </v-radio-group>
+    </Dialog>
   </div>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
 </template>
 
@@ -80,11 +101,16 @@ defineOptions({ name: 'position-details' })
 import { ref } from 'vue'
 import { useRouter } from 'vue-router'
 import { timesTampChange } from '@/utils/date'
-import { getPositionDetails, getSimilarPosition, getJobFavoriteCheck, getPersonJobFavorite, getPersonJobUnfavorite } from '@/api/position'
+import { getPersonResumeCv } from '@/api/resume'
+import { useI18n } from '@/hooks/web/useI18n'
+import { getPositionDetails, getSimilarPosition, getJobFavoriteCheck, getPersonJobFavorite, getPersonJobUnfavorite, jobCvRelCheckSend, jobCvRelSend } from '@/api/position'
 import { dealDictData } from '@/views/recruit/position/components/dict'
 import similarPositions from '@/components/Position/similarPositions.vue'
 import EnterpriseInfo from '@/components/Enterprise/info.vue'
+import Snackbar from '@/plugins/snackbar'
+import Dialog from '@/components/CtDialog'
 
+const { t } = useI18n()
 const router = useRouter()
 const { id } = router.currentRoute.value.params
 
@@ -129,6 +155,44 @@ const handleCollection = async () => {
   await api(isCollection.value ? id : { jobId: id })
   getCollectionStatus()
 }
+
+const dialog = ref(false)
+const showResume = ref(false)
+// 去上传附件
+const handleToUpload = () => {
+  dialog.value = false
+  window.open('/personalCenter')
+}
+
+// 效验是否有投递简历
+const resumeList = ref([])
+const selectResume = ref()
+const handleDelivery = async () => {
+  const data = await jobCvRelCheckSend({ jobId: id })
+  if (data) return Snackbar.warning(t('resume.alreadyResume'))
+  const result = await getPersonResumeCv()
+  resumeList.value = result
+  // 没有上传过简历的先去上传
+  if (!result.length) {
+    dialog.value = true
+    return
+  }
+  showResume.value = true
+}
+
+// 简历投递
+const handleClose = () => {
+  showResume.value = false
+  selectResume.value = null
+}
+const handleSubmit = async () =>{
+  if (!selectResume.value) return Snackbar.warning(t('resume.selectResumeToSubmit'))
+  const obj = resumeList.value.find(e => e.id === selectResume.value)
+  if (!obj) return Snackbar.warning(t('resume.selectedResumeNotExist'))
+  await jobCvRelSend({ jobId: id, title: obj.title, url: obj.url })
+  Snackbar.success(t('resume.deliverySuccess'))
+  handleClose()
+}
 </script>
 
 <style lang="scss" scoped>
@@ -151,7 +215,7 @@ const handleCollection = async () => {
   vertical-align: middle;
 }
 .button-item {
-  width: 110px;
+  min-width: 110px;
   height: 36px
 }
 .salary {
@@ -176,7 +240,7 @@ const handleCollection = async () => {
   border-radius: 8px;
 }
 .content-left {
-  width: 864px;
+  width: 810px;
   padding: 20px 20px;
 }
 .content-right {