|
@@ -1,36 +1,251 @@
|
|
|
<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 v-for="(tab, index) in jobFairDetailsJob" :key="index" :value="index">{{ tab.title }}</v-tab>
|
|
|
- <!-- <v-tab :value="1">投递简历</v-tab> -->
|
|
|
- </v-tabs>
|
|
|
- <component :is="jobFairDetailsJob[tab].component" :id="id"></component>
|
|
|
+ <v-card class="card-box pa-4">
|
|
|
+ <div class="position-relative">
|
|
|
+ <div class="text-end mb-3">
|
|
|
+ <v-btn color="primary" @click="handleAdd">新增职位</v-btn>
|
|
|
+ <v-btn color="primary" class="mx-3" variant="outlined" @click="handleJoin">选择已发布的职位加入招聘会</v-btn>
|
|
|
+ <v-btn color="primary" v-if="bgImg" variant="outlined" prepend-icon="mdi-share-all" @click="handleShare">我的分享海报</v-btn>
|
|
|
+ </div>
|
|
|
+ <JobItem :items="jobList" @refresh="getJobList"></JobItem>
|
|
|
+
|
|
|
+ <v-navigation-drawer v-model="showDrawer" location="right" temporary width="600">
|
|
|
+ <Loading :visible="positionLoading" :contained="true"></Loading>
|
|
|
+ <div class="resume-box">
|
|
|
+ <div class="resume-header">
|
|
|
+ <div class="resume-title mr-5">已发布职位</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="px-3">
|
|
|
+ <v-text-field
|
|
|
+ v-model="positionSearch"
|
|
|
+ append-inner-icon="mdi-magnify"
|
|
|
+ density="compact"
|
|
|
+ :label="t('position.positionName')"
|
|
|
+ variant="outlined"
|
|
|
+ hide-details
|
|
|
+ color="primary"
|
|
|
+ single-line
|
|
|
+ @click:append-inner="getPositionList"
|
|
|
+ @keyup.enter="getPositionList"
|
|
|
+ ></v-text-field>
|
|
|
+ </div>
|
|
|
+ <div class="pa-3" v-if="positionItems.length">
|
|
|
+ <div v-for="val in positionItems" :key="val.id" class="itemBox mb-3" style="height: 80px;">
|
|
|
+ <div class="d-flex justify-space-between" style="padding: 10px 20px;">
|
|
|
+ <div class="position">
|
|
|
+ <div class="d-flex align-center justify-space-between">
|
|
|
+ <span class="position-name">{{ formatName(val.name) }}</span>
|
|
|
+ <div>
|
|
|
+ <v-btn size="small" color="primary" @click="handleTo(val)">添加至招聘会</v-btn>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div :class="['mt-3', 'other-info', 'ellipsis']">
|
|
|
+ <span>{{ val.areaName ? val.area?.str : '全国' }}</span>
|
|
|
+ <span class="lines" v-if="val.eduName"></span>
|
|
|
+ <span>{{ val.eduName }}</span>
|
|
|
+ <span class="lines"></span>
|
|
|
+ <span>{{ val.expName }}</span>
|
|
|
+ <span class="lines"></span>
|
|
|
+ <span v-if="!val.payFrom && !val.payTo">面议</span>
|
|
|
+ <span v-else>{{ val.payFrom ? val.payFrom + '-' : '' }}{{ val.payTo }}{{ val.payName ? '/' + val.payName : '' }}</span>
|
|
|
+ <span class="lines" v-if="val.positionName"></span>
|
|
|
+ <span>{{ val.positionName }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <CtPagination
|
|
|
+ v-if="total"
|
|
|
+ :total="positionTotal"
|
|
|
+ :page="positionPageInfo.pageNo"
|
|
|
+ :limit="positionPageInfo.pageSize"
|
|
|
+ @handleChange="handleChangePage"
|
|
|
+ ></CtPagination>
|
|
|
+ </div>
|
|
|
+ <Empty v-else :elevation="false"></Empty>
|
|
|
+ </v-navigation-drawer>
|
|
|
+
|
|
|
+ <div class="hideCanvasView">
|
|
|
+ <JobFairEntShare
|
|
|
+ :show="showShare"
|
|
|
+ :enterpriseName="enterpriseName"
|
|
|
+ :logoUrl="logoUrl"
|
|
|
+ :positionList="positionList"
|
|
|
+ :bgImg="bgImg"
|
|
|
+ @success="handlePreview"
|
|
|
+ ></JobFairEntShare>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</v-card>
|
|
|
+
|
|
|
+ <PreviewImage v-if="showPreview" :urlList="[previewSrc]" :fileName="enterpriseName" @close="showPreview = !showPreview, showShare = false" />
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-defineOptions({ name: 'jobFairDetails' })
|
|
|
-import { shallowRef, ref } from 'vue'
|
|
|
-import { useRouter } from 'vue-router'
|
|
|
-import JobFairDetailsJob from './components/job.vue'
|
|
|
-import JobFairDetailsResume from './components/resume.vue'
|
|
|
+defineOptions({ name: 'jobFairJob'})
|
|
|
+import { ref } from 'vue'
|
|
|
+import { getJobFairPosition, getJobFair } from '@/api/recruit/enterprise/jobFair'
|
|
|
+import { dealDictArrayData } from '@/utils/position.js'
|
|
|
+import JobItem from './job/item.vue'
|
|
|
+import { useRouter, useRoute } from 'vue-router'
|
|
|
+import { useI18n } from '@/hooks/web/useI18n'
|
|
|
+import Snackbar from '@/plugins/snackbar'
|
|
|
+import { getEnterprisePubJobTypePermission } from '@/api/recruit/enterprise/position'
|
|
|
+import { getJobAdvertisedList } from '@/api/position'
|
|
|
+import { formatName } from '@/utils/getText'
|
|
|
+import JobFairEntShare from '@/views/recruit/components/jobFairEntShare'
|
|
|
+
|
|
|
const router = useRouter()
|
|
|
+const route = useRoute()
|
|
|
+const { id } = route.params
|
|
|
+const { t } = useI18n()
|
|
|
+
|
|
|
+// 职位列表
|
|
|
+const jobList = ref([])
|
|
|
+
|
|
|
+const positionItems = ref([])
|
|
|
+const positionTotal = ref(0)
|
|
|
+const positionLoading = ref(false)
|
|
|
+const total = ref(0)
|
|
|
+const positionPageInfo = ref({
|
|
|
+ pageSize: 10,
|
|
|
+ pageNo: 1,
|
|
|
+})
|
|
|
+const positionSearch = ref('')
|
|
|
+
|
|
|
+// 分享海报
|
|
|
+const entBaseInfo = ref(localStorage.getItem('entBaseInfo') ? JSON.parse(localStorage.getItem('entBaseInfo')) : {})
|
|
|
+const showShare = ref(false)
|
|
|
+const showPreview = ref(false)
|
|
|
+const enterpriseName = ref(formatName(entBaseInfo.value.enterpriseAnotherName || entBaseInfo.value.enterpriseName))
|
|
|
+const logoUrl = ref(entBaseInfo.value.logoUrl)
|
|
|
+const previewSrc = ref('')
|
|
|
+const positionList = ref([])
|
|
|
+const bgImg = ref('')
|
|
|
+
|
|
|
+// 职位列表
|
|
|
+const getJobList = async () => {
|
|
|
+ const data = await getJobFairPosition(id)
|
|
|
+ if (!data || !data.length) return jobList.value = []
|
|
|
+ jobList.value = dealDictArrayData([], data)
|
|
|
+}
|
|
|
+
|
|
|
+const handleAdd = async () => {
|
|
|
+ const data = await getEnterprisePubJobTypePermission()
|
|
|
+ if (!data || !data.length) return Snackbar.warning('没有该操作权限,请联系平台管理员升级后再试')
|
|
|
+ router.push(`/recruit/enterprise/jobFair/details/${id}/edit`)
|
|
|
+}
|
|
|
|
|
|
-const jobFairDetailsJob = shallowRef([
|
|
|
- {
|
|
|
- title: '职位',
|
|
|
- component: JobFairDetailsJob
|
|
|
- },
|
|
|
- {
|
|
|
- title: '投递简历',
|
|
|
- component: JobFairDetailsResume
|
|
|
+const showDrawer = ref(false)
|
|
|
+const handleJoin = async () => {
|
|
|
+ getPositionList()
|
|
|
+ showDrawer.value = true
|
|
|
+}
|
|
|
+
|
|
|
+const handleChangePage = (index) => {
|
|
|
+ positionPageInfo.value.pageNo = index
|
|
|
+ getPositionList()
|
|
|
+}
|
|
|
+
|
|
|
+const handleTo = (val) => {
|
|
|
+ router.push(`/recruit/enterprise/jobFair/details/${id}/edit?id=${val.id}`)
|
|
|
+}
|
|
|
+
|
|
|
+// 获取职位列表
|
|
|
+const getPositionList = async () => {
|
|
|
+ positionLoading.value = true
|
|
|
+ const query = {
|
|
|
+ ...positionPageInfo.value,
|
|
|
+ status: 0,
|
|
|
+ hasExpiredData: false,
|
|
|
+ hire: false
|
|
|
+ }
|
|
|
+ if ( positionSearch.value) {
|
|
|
+ Object.assign(query, {
|
|
|
+ name: positionSearch.value,
|
|
|
+ })
|
|
|
}
|
|
|
-])
|
|
|
+ try {
|
|
|
+ const { list, total } = await getJobAdvertisedList(query)
|
|
|
+ positionTotal.value = total
|
|
|
+ positionItems.value = list.length ? dealDictArrayData([], list) : []
|
|
|
+ } finally {
|
|
|
+ positionLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+getJobList()
|
|
|
+
|
|
|
+const getJob = async () => {
|
|
|
+ const data = await getJobFair(id)
|
|
|
+ if (!data) return
|
|
|
+ bgImg.value = data.contentImg
|
|
|
+}
|
|
|
+getJob()
|
|
|
|
|
|
-const id = router.currentRoute.value.params.id
|
|
|
-const tab = ref(0)
|
|
|
+// 分享海报预览
|
|
|
+const handlePreview = (val) => {
|
|
|
+ if (!val) return
|
|
|
+ previewSrc.value = val
|
|
|
+ showPreview.value = true
|
|
|
+}
|
|
|
|
|
|
+const handleShare = () => {
|
|
|
+ positionList.value = jobList.value && jobList.value.length > 0 ? jobList.value.map(e => formatName(e.name)).slice(0, 2) : []
|
|
|
+ showShare.value = true
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
+.hideCanvasView {
|
|
|
+ position: fixed;
|
|
|
+ top: -99999px;
|
|
|
+ left: -99999px;
|
|
|
+ z-index: -99999;
|
|
|
+}
|
|
|
+.resume-box {
|
|
|
+ padding-top: 120px;
|
|
|
+}
|
|
|
+
|
|
|
+.itemBox {
|
|
|
+ position: relative;
|
|
|
+ border: 1px solid #e5e6eb;
|
|
|
+}
|
|
|
+.position-name {
|
|
|
+ color: var(--color-333);
|
|
|
+ font-size: 19px;
|
|
|
+}
|
|
|
+.position {
|
|
|
+ width: 100%;
|
|
|
+ position: relative;
|
|
|
+ .item-select {
|
|
|
+ position: absolute;
|
|
|
+ left: -8px;
|
|
|
+ top: -13px;
|
|
|
+ }
|
|
|
+}
|
|
|
+.lines {
|
|
|
+ display: inline-block;
|
|
|
+ width: 1px;
|
|
|
+ height: 17px;
|
|
|
+ vertical-align: middle;
|
|
|
+ background-color: #e0e0e0;
|
|
|
+ margin: 0 10px;
|
|
|
+}
|
|
|
+.other-info {
|
|
|
+ font-size: 15px;
|
|
|
+ color: var(--color-666);
|
|
|
+}
|
|
|
+.bottom {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 40px;
|
|
|
+ background-color: #f7f8fa;
|
|
|
+ font-size: 14px;
|
|
|
+ color: var(--color-888);
|
|
|
+}
|
|
|
+.actions:hover {
|
|
|
+ color: var(--v-primary-base);
|
|
|
+}
|
|
|
</style>
|