소스 검색

新增招聘会岗位

zhengnaiwen_citu 8 달 전
부모
커밋
96b369e292

+ 4 - 2
.eslintrc.js

@@ -4,9 +4,11 @@ require('@rushstack/eslint-patch/modern-module-resolution')
 module.exports = {
   root: true,
   'extends': [
-    'plugin:vue/vue3-essential',
+    'plugin:vue/vue3-recommended',  
+    '@vue/eslint-config-standard',  
+    // 'plugin:vue/vue3-essential',
     'eslint:recommended',
-    '@vue/eslint-config-prettier/skip-formatting'
+    // '@vue/eslint-config-prettier/skip-formatting'
   ],
   parserOptions: {
     ecmaVersion: 'latest'

+ 10 - 1
src/router/modules/components/recruit/enterprise.js

@@ -337,7 +337,7 @@ const enterprise = [
     path: '/recruit/enterprise/jobFair',
     component: Layout,
     name: 'jobFair',
-    show: true, // 暂时隐藏
+    // show: true, // 暂时隐藏
     meta: {
       title: '双选会',
       enName: 'Job Management',
@@ -361,6 +361,15 @@ const enterprise = [
           enName: 'Job Fair Details'
         },
         component: () => import('@/views/recruit/enterprise/jobFair/details.vue')
+      },
+      {
+        path: '/recruit/enterprise/jobFair/details/:jobFairId/edit',
+        show: true,
+        meta: {
+          title: '职位编辑',
+          enName: 'Job Fair Edit'
+        },
+        component: () => import('@/views/recruit/enterprise/jobFair/editJob.vue')
       }
     ]
   }

+ 4 - 3
src/views/recruit/enterprise/jobFair/components/job.vue

@@ -22,12 +22,13 @@ import { ref } from 'vue'
 import { getJobFairPosition } from '@/api/recruit/enterprise/jobFair'
 import { dealDictArrayData } from '@/utils/position.js'
 import JobItem from '../job/item.vue'
-// import { useRouter } from 'vue-router'
+import { useRouter, useRoute } from 'vue-router'
 import Snackbar from '@/plugins/snackbar'
 import { getEnterprisePubJobTypePermission } from '@/api/recruit/enterprise/position'
 
 const props = defineProps({ id: [String, Number]})
-// const router = useRouter()
+const router = useRouter()
+const route = useRoute()
 
 // 职位列表
 const jobList = ref([])
@@ -41,7 +42,7 @@ getJobList()
 const handleAdd = async () => {
   const data = await getEnterprisePubJobTypePermission()
   if (!data || !data.length) return Snackbar.warning('没有该操作权限,请联系平台管理员升级后再试')
-  // router.push(`/recruit/enterprise/position/add`)
+  router.push(`/recruit/enterprise/jobFair/details/${route.params.id}/edit`)
 }
 
 const showDrawer = ref(false)

+ 15 - 5
src/views/recruit/enterprise/jobFair/details.vue

@@ -1,11 +1,10 @@
 <template>
   <v-card class="card-box pa-5">
     <v-tabs v-model="tab" align-tabs="center" color="primary" bg-color="#f7f8fa" class="mb-3">
-      <v-tab :value="0">职位</v-tab>
-      <v-tab :value="1">投递简历</v-tab>
+      <v-tab v-for="(tab, index) in jobFairDetailsJob" :key="index" :value="index">{{ tab.title }}</v-tab>
+      <!-- <v-tab :value="1">投递简历</v-tab> -->
     </v-tabs>
-    <JobFairDetailsJob v-if="tab === 0" :id="id"></JobFairDetailsJob>
-    <JobFairDetailsResume v-else :id="id"></JobFairDetailsResume>
+    <component :is="jobFairDetailsJob[tab].component" :id="id"></component>
   </v-card>
 </template>
 
@@ -15,8 +14,19 @@ import { ref } from 'vue'
 import { useRouter } from 'vue-router'
 import JobFairDetailsJob from './components/job.vue'
 import JobFairDetailsResume from './components/resume.vue'
-
 const router = useRouter()
+
+const jobFairDetailsJob = ref([
+  {
+    title: '职位',
+    component: JobFairDetailsJob
+  },
+  {
+    title: '投递简历',
+    component: JobFairDetailsResume
+  }
+])
+
 const id = router.currentRoute.value.params.id
 const tab = ref(0)
 

+ 137 - 0
src/views/recruit/enterprise/jobFair/editJob.vue

@@ -0,0 +1,137 @@
+<template>
+  <add :after-add="afterAdd" :valid="validate">
+    <template #timeline>
+      <v-timeline-item
+          dot-color="light-blue darken-1"
+          icon="mdi-numeric-3"
+        >
+        <div>
+          <h2 class="mt-n1 headline font-weight-regular">{{ t('common.other') }}</h2>
+          <CtForm ref="formPageRef" class="mt-3" :items="items" style="width: 650px;">
+            <template #frequency>
+              <div class="pl-3">111</div>
+            </template>
+          </CtForm>
+        </div>
+      </v-timeline-item>
+    </template>
+  </add>
+</template>
+
+<script setup>
+defineOptions({ name: 'editJob' })
+import { ref, watch, computed } from 'vue'
+import {  useRoute, useRouter } from 'vue-router'
+import CtForm from '@/components/CtForm'
+import Add from '@/views/recruit/enterprise/positionManagement/components/add.vue'
+import { useI18n } from '@/hooks/web/useI18n'
+import { schoolMajorByName } from '@/api/recruit/personal/resume'
+import { saveJobAdvertisedExtend, joinJobFairPosition } from '@/api/recruit/enterprise/jobFair'
+import Snackbar from '@/plugins/snackbar'
+
+const { t } = useI18n()
+const route = useRoute()
+const router = useRouter()
+
+const formPageRef = ref(null)
+
+const items = ref({
+  options: [
+    {
+      type: 'text',
+      key: 'dept',
+      value: null,
+      label: '招聘部门 *',
+      rules: [v => !!v || '请选择招聘部门']
+    },
+    {
+      type: 'autocomplete',
+      key: 'majorId',
+      search: getMajorList,
+      value: null,
+      label: '专业要求 *',
+      itemText: 'nameCn',
+      itemValue: 'id',
+      rules: [v => !!v || '专业要求'],
+      noDataText: '请输入检索专业',
+      items: []
+    },
+    {
+      type: 'autocomplete',
+      key: 'frequency-dateType',
+      value: null,
+      label: '工作频率 *',
+      col: 6,
+      rules: [v => !!v || '请选择工作频率'],
+      items: [
+        { label: '每周', value: 'week' },
+        { label: '每月', value: 'month' },
+        { label: '每年', value: 'year' },
+      ]
+    },
+    {
+      type: 'number',
+      key: 'frequency-day',
+      value: null,
+      flexStyle: 'ml-3',
+      col: 6,
+      label: '出勤天数 *',
+      rules: [v => v > 0 || '请填写正确的出勤天数']
+    },
+    {
+      type: 'ifRadio',
+      key: 'hot',
+      value: 1,
+      label: '热门职位 *',
+      items: [
+        { label: '是', value: 1 },
+        { label: '否', value: 0 },
+      ],
+      rules: [v => !!v || '请选择是否热门']
+    },
+  ]
+})
+
+async function getMajorList (name) {
+  if (!name) {
+    return
+  }
+  const res = await schoolMajorByName({ name })
+  items.value.options.find(e => e.key === 'majorId').items = res
+}
+
+const validate = async () => {
+  const res = await formPageRef.value.formRef.validate()
+  return res
+}
+const afterAdd = async (jobId) => {
+  try {
+    const query = items.value.options.reduce((r, v) => {
+      if (v.key.includes('frequency')) {
+        const keys = v.key.split('-')
+        if (!r[keys[0]]) {
+          r[keys[0]] = {}
+        }
+        r[keys[0]][keys[1]] = v.type === 'number' ? +v.value : v.value
+        return r
+      }
+      r[v.key] = v.type === 'number' ? +v.value : v.value
+      return r
+    }, { jobId })
+    await saveJobAdvertisedExtend(query)
+    console.log('招聘会职位扩展信息保存成功')
+    await joinJobFairPosition({
+      jobFairId: route.params.jobFairId,
+      jobId
+    })
+    Snackbar.success(t('common.publishSuccessMsg'))
+    router.push(`/recruit/enterprise/jobFair/details/${route.params.jobFairId}`)
+  } catch (error) {
+    Snackbar.error(t('sys.api.operationFailed'))
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 39 - 22
src/views/recruit/enterprise/jobFair/index.vue

@@ -1,6 +1,6 @@
 <template>
-  <v-card class="card-box pa-5">
-    <v-card v-for="(k, i) in list" :key="i" class="elevation-3 mb-5">
+  <v-card class="card-box pa-5 ">
+    <v-card v-for="(k, i) in list" :key="i" class="elevation-3">
       <img :src="k.url" style="width: 100%; height: 300px;">
       <div class="pa-5">
         <div class="color-primary font-weight-bold font-size-18 mb-1">{{ k.title }}</div>
@@ -17,30 +17,42 @@
 defineOptions({ name: 'jobFair'})
 import { ref } from 'vue'
 import { useRouter } from 'vue-router'
-// import { getJobFairList } from '@/api/recruit/enterprise/jobFair'
+import { getJobFairList } from '@/api/recruit/enterprise/jobFair'
 
 const router = useRouter()
 const list = ref([
-  {
-    id: 1,
-    url: 'https://minio.menduner.com/dev/menduner/jobFair.jfif',
-    title: '中瑞实习双选会',
-    desc: '2024年中瑞实习双选会,旨在为毕业生提供更多的就业机会和职业发展机会。'
-  },
-  {
-    id: 2,
-    url: 'https://minio.menduner.com/dev/menduner/jobFair2.jfif',
-    title: '2025年春季校园招聘会',
-    desc: '2025年春季校园招聘会,旨在为毕业生提供更多的就业机会和职业发展机会。'
-  }
+  // {
+  //   id: 1,
+  //   url: 'https://minio.menduner.com/dev/menduner/jobFair.jfif',
+  //   title: '中瑞实习双选会',
+  //   desc: '2024年中瑞实习双选会,旨在为毕业生提供更多的就业机会和职业发展机会。'
+  // },
+  // {
+  //   id: 2,
+  //   url: 'https://minio.menduner.com/dev/menduner/jobFair2.jfif',
+  //   title: '2025年春季校园招聘会',
+  //   desc: '2025年春季校园招聘会,旨在为毕业生提供更多的就业机会和职业发展机会。'
+  // },
+  // {
+  //   id: 3,
+  //   url: 'https://minio.menduner.com/dev/menduner/jobFair2.jfif',
+  //   title: '2025年春季校园招聘会',
+  //   desc: '2025年春季校园招聘会,旨在为毕业生提供更多的就业机会和职业发展机会。'
+  // },
+  // {
+  //   id: 4,
+  //   url: 'https://minio.menduner.com/dev/menduner/jobFair2.jfif',
+  //   title: '2025年春季校园招聘会',
+  //   desc: '2025年春季校园招聘会,旨在为毕业生提供更多的就业机会和职业发展机会。'
+  // }
 ])
 
-// const getList = async () => {
-//   const data = await getJobFairList()
-//   console.log(data, 'data')
-//   list.value = data
-// }
-// getList()
+const getList = async () => {
+  const data = await getJobFairList()
+  // console.log(data, 'data')
+  list.value = data
+}
+getList()
 
 // 立即加入
 const handleBlockEnterprise = (id) => {
@@ -49,5 +61,10 @@ const handleBlockEnterprise = (id) => {
 </script>
 
 <style scoped lang="scss">
-
+.card-box {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 20px;
+  min-height: auto;
+}
 </style>

+ 20 - 2
src/views/recruit/enterprise/positionManagement/components/add.vue

@@ -14,6 +14,7 @@
             <component :is="val.path" :ref="val.ref" :itemData="itemData"></component>
           </div>
         </v-timeline-item>
+        <slot name="timeline"></slot>
       </v-timeline>
       <div class="text-center mb">
         <v-btn class="half-button mr-3" color="primary" variant="outlined" @click="handleCancel()">{{ $t('common.cancel') }}</v-btn>
@@ -35,6 +36,12 @@ import Snackbar from '@/plugins/snackbar'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useUserStore } from '@/store/user'
 
+// 添加只为之后是否需要额外操作
+const props = defineProps({
+  afterAdd: Function,
+  valid: Function,
+})
+
 const { t } = useI18n()
 const route = useRoute()
 const router = useRouter()
@@ -68,6 +75,7 @@ let submitParams = {}
 // 发布
 const handleSave = async () => {
   const baseInfo = await baseInfoRef.value[0].getQuery()
+  console.log('baseInfo', baseInfo)
   if (baseInfo === 'failed') return
   const requirement = await jobRequirementsRef.value[0].getQuery()
   if (!baseInfo.expireTime && !baseInfo.soFar) {
@@ -79,15 +87,25 @@ const handleSave = async () => {
   if (!baseInfo || !requirement) return Snackbar.warning('请将信息填写完整')
   
   submitParams = Object.assign(baseInfo, requirement, { currency_type: 0 }) // currency_type: 写死0(人民币)
+  console.log('submitParams', submitParams)
   if (route.query && route.query.id) submitParams.id = route.query.id // 有id则为编辑
-
+  if (props.valid) {
+    const { valid } = await props.valid()
+    if (!valid) {
+      return
+    }
+  }
   saveEmit(submitParams)
 }
 
 const saveEmit = async () => {
   loading.value = true
   try {
-    await saveJobAdvertised(submitParams)
+    const res = await saveJobAdvertised(submitParams)
+    if (props.afterAdd) {
+      await props.afterAdd(res)
+      return
+    }
     Snackbar.success(submitParams.id ? t('common.editSuccessMsg') : t('common.publishSuccessMsg'))
     handleCancel()
   } catch (error) {

+ 2 - 1
src/views/recruit/enterprise/positionManagement/components/baseInfo.vue

@@ -202,7 +202,8 @@ const getQuery = async () => {
   }
   
   // query = Object.assign(query, obj)
-  query = {...obj, ...query}
+  // query = {...obj, ...query}
+  Object.assign(query, obj)
   return query
 }