123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- <template>
- <div>
- <CtForm ref="formPageRef" :items="items" style="width: 650px;">
- <template #positionId="{ item }">
- <v-menu :close-delay="1" :open-delay="0" v-bind="$attrs">
- <template v-slot:activator="{ props }">
- <textUI
- :modelValue="item.value"
- :item="item"
- v-bind="props"
- style="position: relative;"
- ></textUI>
- </template>
- <jobTypeCard class="jobTypeCardBox" :select="[query.positionId].filter(Boolean)" :isSingle="true" @handleJobClick="handleJobClickItem"></jobTypeCard>
- </v-menu>
- <v-btn v-if="showTemplateBtn" class="ml-3 half-button" color="primary" style="margin-top: 2px;" @click="useJobTemplate(item)">职位模板</v-btn>
- </template>
- <template #jobFairSign>
- <svg-icon name="jobFair" size="40"></svg-icon>
- </template>
- </CtForm>
- <CtDialog :visible="showDialog" :widthType="1" titleClass="text-h6" :footer="false" title="重复职位列表" @close="showDialog = false">
- <CtTable
- :items="tableItems"
- :headers="headers"
- :loading="false"
- :elevation="0"
- :isTools="false"
- :showPage="false"
- >
- <template #actions="{ item }">
- <v-btn :disabled="!item.id" color="primary" variant="text" @click="handleDetails(item)">详情</v-btn>
- </template>
- </CtTable>
- </CtDialog>
- </div>
- </template>
- <script setup>
- defineOptions({ name: 'position-add-baseInfo'})
- import CtForm from '@/components/CtForm'
- import { reactive, ref, watch } from 'vue'
- import textUI from '@/components/FormUI/TextInput'
- import jobTypeCard from '@/components/jobTypeCard'
- import { getRecruitPositionDetails } from '@/api/recruit/enterprise/position'
- import Confirm from '@/plugins/confirm'
- import Snackbar from '@/plugins/snackbar'
- import { useI18n } from '@/hooks/web/useI18n';
- import { getJobAdvertised } from '@/api/enterprise'
- import { formatName } from '@/utils/getText'
- import { dealDictArrayData } from '@/utils/position'
- import { timesTampChange } from '@/utils/date'
- const { t } = useI18n()
- const props = defineProps({
- itemData: Object,
- isFair: {
- type: Boolean,
- default: false
- }
- })
- const getValue = (key) => {
- return items.value.options.find(e => e.key === key)
- }
- const showTemplateBtn = ref(true)
- const formPageRef = ref()
- let query = reactive({})
- // 重复职位弹窗
- const showDialog = ref(false)
- const tableItems = ref([])
- const headers = [
- { title: '职位名称', key: 'name', sortable: false, value: item => formatName(item.name) },
- { title: '薪资', key: 'payTo', sortable: false, value: item => !item.payFrom && !item.payTo ? '面议' : `${item.payFrom}-${item.payTo}/${item.payName}` },
- { title: '学历要求', key: 'eduName', sortable: false },
- { title: '工作经验', key: 'expName', sortable: false },
- { title: '地区', key: 'area', sortable: false, value: item => !item.areaId ? '全国' : item.area?.str },
- { title: '状态', key: 'status', sortable: false, value: item => !item.status ? '' : item.status === '0' ? '招聘中' : '已关闭' },
- { title: '创建时间', key: 'createTime', sortable: false, value: item => timesTampChange(item.createTime) },
- { title: '更新时间', key: 'updateTime', sortable: false, value: item => timesTampChange(item.updateTime) },
- { title: '操作', key: 'actions', sortable: false }
- ]
- const handleDetails = (item) => {
- window.open(`/recruit/enterprise/position/details?id=${item.id}`)
- }
- let showConfirm = false
- // 效验职位名称是否重复
- const handleValidName = async (item, val) => {
- if (!val || showConfirm) return
- try {
- const data = await getJobAdvertised({ jobName: val })
- tableItems.value = data ? dealDictArrayData([], data) : []
- if (data && data.length > 0) {
- showConfirm = true // 避免快速点击出现多个弹窗提示
- Confirm(
- t('common.confirmTitle'),
- '该职位名称已在您的招聘职位列表中存在,是否继续发布?',
- { sureText: '查看已有职位', cancelText: '继续发布', cancelCallback: true }
- ).then(() => {
- // 弹窗查看已有职位
- showDialog.value = true
- showConfirm = false
- }).catch(() => {
- showConfirm = false
- })
- }
- } catch {}
- }
- const items = ref({
- options: [
- {
- slotName: 'positionId',
- key: 'positionId',
- value: '',
- labelKey: 'positionName',
- label: '职位类型 *',
- noParam: true,
- readonly: true,
- rules: [v => !!v || '请选择职位类型']
- },
- // 招聘会职位展示标识
- {
- slotName: 'jobFairSign',
- hide: !props.isFair,
- col: 1,
- noParam: true
- },
- {
- type: 'text',
- key: 'name',
- value: '',
- col: props.isFair ? 11 : 12,
- label: '职位名称 *',
- blur: handleValidName, // 效验职位名称是否重复
- rules: [v => !!v || '请填写职位名称']
- },
- {
- type: 'wangEditor',
- key: 'content',
- value: '',
- label: '岗位职责 *',
- maxLength: 5000,
- rules: '请填写岗位职责'
- },
- {
- type: 'wangEditor',
- key: 'requirement',
- value: '',
- label: '岗位要求 *',
- maxLength: 5000,
- rules: '请填写岗位要求'
- }
- ]
- })
- // 编辑回显
- watch(
- () => props.itemData,
- (val) => {
- if (!Object.keys(val).length) return
- items.value.options.forEach(e => {
- if (e.labelKey) {
- query[e.key] = val[e.key]
- e.value = val[e.labelKey]
- return
- }
- if (e.noParam) return
- e.value = val[e.key]
- })
- },
- { immediate: true },
- { deep: true }
- )
- // 职位类型
- const handleJobClickItem = (list, name) => {
- const positionId = getValue('positionId')
- if (!list.length) {
- delete query.positionId
- positionId.value = ''
- return
- }
- showTemplateBtn.value = true
- query.positionId = list[0]
- positionId.value = name
- }
- const useJobTemplate = async () => {
- if (!query.positionId) return Snackbar.warning('请先选择职位类型')
- // 获取职位模板内容-赋值
- const res = await getRecruitPositionDetails(query.positionId)
- if (!res || !res.content || !res.requirement) {
- Snackbar.warning('此职位类型没有可使用的模板!')
- showTemplateBtn.value = false
- return
- }
- const content = items.value.options.find(e => e.key === 'content')
- const requirement = items.value.options.find(e => e.key === 'requirement')
- if ((content && content.value) || (requirement && requirement.value)) {
- // 弹窗提示
- Confirm(t('common.confirmTitle'), '您确定要放弃目前岗位描述的内容吗?').then(() => {
- content.value = res.content
- requirement.value = res.requirement
- Snackbar.success('模板填充完成!')
- })
- } else {
- // 无内容点击默认填充
- if (content) content.value = res.content
- if (requirement) requirement.value = res.requirement
- Snackbar.success('模板填充完成!')
- }
- }
- const getQuery = async () => {
- const { valid } = await formPageRef.value.formRef.validate()
- if (!valid) return
- const obj = {
- hirePrice: 0,
- expireTime: null, // 默认为长期有效
- bizId: null, // 招聘会id
- hire: false
- }
- items.value.options.forEach(e => {
- if (e.noParam || e.value === null) return
- else obj[e.key] = e.value
- })
-
- if (!obj.content) {
- Snackbar.warning('请填写岗位职责')
- return 'failed'
- }
- if (!obj.requirement) {
- Snackbar.warning('请填写岗位要求')
- return 'failed'
- }
- obj.source = props.isFair ? '2' : '0' // 职位来源(0职位管理|1众聘职位|2招聘会)
- Object.assign(query, obj)
- return query
- }
- defineExpose({
- formPageRef,
- getQuery
- })
- </script>
- <style scoped lang="scss">
- .jobTypeCardBox {
- position: absolute;
- top: -22px;
- left: 0;
- }
- .calculation {
- display: block;
- width: 120px;
- }
- .bizTips {
- width: 650px;
- position: absolute;
- left: -460px;
- color: var(--v-error-base);
- margin-top: 8px;
- font-size: 14px;
- }
- </style>
|