提交 65745ccc authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 274b4694
{
"recommendations": ["johnsoncodehk.volar", "johnsoncodehk.vscode-typescript-vue-plugin"]
"recommendations": ["vue.volar", "vue.vscode-typescript-vue-plugin"]
}
<script setup lang="ts">
import { useArea } from '@/composables/useArea'
const { treeList } = useArea()
const props = defineProps<{ modelValue: string | null }>()
const emit = defineEmits(['update:modelValue', 'change'])
const dataValue = ref<string[]>([])
watch(
() => props.modelValue,
value => {
dataValue.value = value?.split('-') || []
},
{ immediate: true }
)
function onChange(value: string[] | string) {
if (Array.isArray(value)) {
emit('update:modelValue', value.join('-'))
emit('change', value.join('-'))
} else {
emit('update:modelValue', value)
emit('change', value)
}
}
</script>
<template>
<el-cascader v-model="dataValue" :options="treeList" separator="-" clearable @change="onChange" v-bind="$attrs" />
</template>
<script setup lang="ts">
import AppLayout from './layout/Index.vue'
// const menus = [
// { title: '发布职位', path: '/hr/posts/job' },
// { title: '校友人才', path: '/hr/alumni' }
// ]
const menus = [
{ title: '发布职位', path: '/hr/posts/job' },
{ title: '校友人才', path: '/hr/alumni' }
]
</script>
<template>
<AppLayout>
<AppContainer background="white"></AppContainer>
<AppContainer :menus="menus" background="white"></AppContainer>
</AppLayout>
</template>
......@@ -119,7 +119,7 @@ onMounted(() => {
fetchList()
})
defineExpose({ refetch, tableRef })
defineExpose({ search, refetch, tableRef })
</script>
<template>
......
......@@ -165,6 +165,8 @@ const rows: Record<string, any>[] = [
}
if (user.projects.length === 0) {
ElMessage({ message: '请联系我们完成企业注册' })
} else if (user.hasCompany) {
window.open('/hr/company/view')
} else {
window.open('/hr/company/create')
}
......
......@@ -29,6 +29,11 @@ export interface AlumniType {
workplace: string
department: string
position: string
company?: {
id: string
name: string
desc: string
}
}
export interface ClassType {
......
......@@ -87,9 +87,9 @@ const listOptions = computed(() => ({
]
}))
function handleUpdateList() {
function handleSearch() {
nextTick(() => {
appList.value?.refetch()
appList.value?.search()
})
}
......@@ -106,7 +106,7 @@ onMounted(() => {
<router-link :to="`/hr/alumni/view/${row.id}`" target="_blank" style="color: #399ee8">查看</router-link>
</template>
<template #filter-province>
<el-select filterable clearable v-model="provinceValue" @change="handleUpdateList" style="width: 250px">
<el-select filterable clearable v-model="provinceValue" @change="handleSearch" style="width: 250px">
<el-option v-for="item in provinceList" :value="item.label" :key="item.code"></el-option>
</el-select>
</template>
......@@ -115,7 +115,7 @@ onMounted(() => {
filterable
clearable
v-model="cityValue"
@change="handleUpdateList"
@change="handleSearch"
no-data-text="请先选择省份"
style="width: 250px"
>
......@@ -133,5 +133,10 @@ onMounted(() => {
.el-form-item__label {
width: 80px;
}
.el-input,
.el-select {
width: 210px !important;
}
}
</style>
......@@ -106,11 +106,14 @@ onMounted(() => {
</AppCard>
<AppCard class="company-info">
<h1>企业简介<span>Company Profile</span></h1>
<p class="tips">暂未注册企业</p>
<template v-if="data.company && data.company.id">
<article class="article" v-html="data.company.desc"></article>
</template>
<p class="tips" v-else>暂未注册企业</p>
</AppCard>
</template>
<style lang="scss">
<style lang="scss" scoped>
.alumni-info {
padding: 24px;
display: grid;
......@@ -176,4 +179,14 @@ onMounted(() => {
text-align: center;
}
}
.article {
padding: 20px 0;
font-size: 15px;
line-height: 1.8;
color: #666;
::v-deep(img) {
margin: 20px 0;
max-width: 100%;
}
}
</style>
......@@ -12,9 +12,8 @@ export const routes: Array<RouteRecordRaw> = [
component: () => import('./views/Update.vue')
},
{
path: 'view/:id',
component: () => import('./views/View.vue'),
props: true
path: 'view',
component: () => import('./views/View.vue')
}
]
}
......
<script setup lang="ts"></script>
<script setup lang="ts">
import { getMyCompany, getCompany } from '../api'
import type { CompanyType } from '../types'
const route = useRoute()
const data = reactive<CompanyType>({
id: '',
logo: '',
name: '',
desc: '',
email: '',
nature: '',
code: '',
business_licence: '',
province: '',
city: '',
industry: ''
})
// 获取我的公司信息
function fetchMyCompany() {
getMyCompany().then(res => {
const { detail } = res.data
Object.assign(data, detail)
})
}
// 获取公司信息
function fetchCompany() {
getCompany({ id: route.query.id as string }).then(res => {
const { detail } = res.data
Object.assign(data, detail)
})
}
onMounted(() => {
route.query.id ? fetchCompany() : fetchMyCompany()
})
</script>
<template>
<AppCard class="company-info">
<h1>企业简介<span>Company Profile</span></h1>
<p class="tips">暂未注册企业</p>
<article class="article" v-html="data.desc"></article>
</AppCard>
</template>
<style lang="scss">
<style lang="scss" scoped>
.company-info {
padding: 44px;
margin-top: 20px;
......@@ -27,14 +63,15 @@
color: #666666;
}
}
.tips {
padding: 100px 0;
font-size: 26px;
font-family: Lato;
font-weight: 400;
line-height: 32px;
color: #666666;
text-align: center;
}
.article {
padding: 20px 0;
font-size: 15px;
line-height: 1.8;
color: #666;
::v-deep(img) {
margin: 20px 0;
max-width: 100%;
}
}
</style>
import httpRequest from '@/utils/axios'
// 获取校友列表
export function getAlumniList(params: {
project_prefix_arr: []
workplace: string
industry: string
province: string
city: string
// 获取岗位列表
export function getJobList(params?: {
page?: number
limit?: number
name?: string
type?: number
education?: number
work_locations?: string
company_id?: string
}) {
return httpRequest.get('/api/hr/api/v1/alumni-talents', { params })
return httpRequest.get('/api/hr/api/v1/positions', { params })
}
// 获取校友详情
export function getAlumniDetail(params: { id: string }) {
return httpRequest.get(`/api/hr/api/v1/alumni-talent/${params.id}`, { params })
// 获取岗位详情
export function getJob(params: { id: string }) {
return httpRequest.get(`/api/hr/api/v1/position/${params.id}/detail`, { params })
}
// 获取当前登录的校友信息
export function getAlumniUserInfo() {
return httpRequest.get('/api/hr/api/v1/alumni-talent/login-user-info')
// 投递简历
export function submitResume(data: { id: string; resume: string }) {
return httpRequest.post(`/api/hr/api/v1/position/${data.id}/deliver`, data)
}
export interface JobType {
id?: string
name: string
education?: 1 | 2 | 3 | 4 | 5
type?: 1 | 2 | 3 | 4 | 5
work_locations: string
salary_min?: number
salary_max?: number
desc: string
status?: 1 | 2
audit_status?: 1 | 2 | 3
company?: {
id: string
name: string
logo: string
status: 1 | 2
audit_status: 1 | 2 | 3
}
}
<script setup lang="ts">
import AppList from '@/components/base/AppList.vue'
import { jobTypeList, educationList } from '@/utils/dictionary'
import AppArea from '@/components/AppArea.vue'
import { jobType, jobTypeList, education, educationList } from '@/utils/dictionary'
import { getJobList } from '../api'
import type { JobType } from '../types'
const appList = $ref<InstanceType<typeof AppList> | null>(null)
const listOptions = {
remote: {},
remote: {
httpRequest: getJobList,
params: {
name: '',
education: undefined,
type: undefined,
work_locations: ''
}
},
filters: [
{ type: 'input', label: '企业名称', prop: 'name', placeholder: '请输入' },
{ type: 'select', label: '学历要求', prop: 'education', options: educationList },
{ type: 'select', label: '工作地点', prop: 'work_locations' },
{ type: 'select', label: '工作地点', prop: 'work_locations', slots: 'filter-area' },
{ type: 'select', label: '岗位类型', prop: 'type', options: jobTypeList },
{ type: 'input', label: '岗位名称', prop: 'name', placeholder: '请输入' }
],
columns: [
{ label: '编号', prop: 'id' },
{ label: '企业名称', prop: 'name' },
{ label: '岗位类型', prop: 'type' },
{ label: '地点', prop: 'work_locations' },
{ label: '学历要求', prop: 'education' },
{ label: '薪酬范围', prop: 'education' },
{ label: '投递人数', prop: 'education' },
{ label: '状态', prop: 'status' },
{ label: '操作', slots: 'table-actions' }
],
data: [
{ id: '1', name: '企业名称', education: 1, type: 1, salary_min: 10000, salary_max: 20000, desc: '描述' },
{ id: '2', name: '企业名称', education: 1, type: 1, salary_min: 10000, salary_max: 20000, desc: '描述' },
{ id: '3', name: '企业名称', education: 1, type: 1, salary_min: 10000, salary_max: 20000, desc: '描述' },
{ id: '4', name: '企业名称', education: 1, type: 1, salary_min: 10000, salary_max: 20000, desc: '描述' },
{ id: '5', name: '企业名称', education: 1, type: 1, salary_min: 10000, salary_max: 20000, desc: '描述' }
]
columns: []
}
function handleSearch() {
appList?.search()
}
function getEducationName(educationValue: JobType['education']) {
return (educationValue && education[educationValue]) || educationValue
}
function getTypeName(typeValue: JobType['type']) {
return (typeValue && jobType[typeValue]) || typeValue
}
</script>
<template>
<AppList v-bind="listOptions" ref="appList">
<template #body="{ data }">
<div class="job-list">
<template #filter-area="{ params }">
<AppArea v-model="params.work_locations" @change="handleSearch"></AppArea>
</template>
<template #body="{ data }: { data: JobType[] }">
<div class="job-list" v-if="data.length">
<div class="job-item" v-for="item in data" :key="item.id">
<router-link :to="`/hr/job/view/${item.id}`" target="_blank" class="job-item__inner">
<div class="job-item-hd">
......@@ -44,18 +52,21 @@ const listOptions = {
<p>{{ item.salary_min }}-{{ item.salary_max }}</p>
</div>
<div class="job-item-bd">
<p>{{ item.province }}-{{ item.city }}</p>
<p>{{ item.education }}</p>
<p>{{ item.work_locations }}</p>
<p>{{ getEducationName(item.education) }}</p>
</div>
<div class="job-item-ft">
<p>
<router-link :to="`/hr/company/view/${item.id}`" target="_blank">{{ item.name }}</router-link>
<p v-if="item.company">
<router-link :to="`/hr/company/view?id=${item.company.id}`" target="_blank">
{{ item.company.name }}
</router-link>
</p>
<p>{{ item.type }}</p>
<p>{{ getTypeName(item.type) }}</p>
</div>
</router-link>
</div>
</div>
<el-empty description="暂无岗位" v-else />
</template>
<template #table-actions="{ row }">
<router-link :to="`/hr/posts/job/view/${row.id}`" target="_blank">
......
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { getJob, submitResume } from '../api'
import { jobType, education } from '@/utils/dictionary'
import type { JobType } from '../types'
const props = defineProps<{ id: string }>()
const data = reactive<JobType>({
name: '',
education: undefined,
type: undefined,
work_locations: '',
salary_min: undefined,
salary_max: undefined,
desc: ''
})
const jobTypeName = computed(() => {
return data.type && jobType[data.type]
})
const educationName = computed(() => {
return data.education && education[data.education]
})
const descHtml = computed(() => {
return data.desc.replace(/\n/g, '<br />')
})
let isUploaded = $ref(false)
const uploadButtonText = computed(() => (isUploaded ? '已投递' : '申请该职位'))
const uploadFileUrl = ref('')
function handleUploadSuccess(e: any) {
isUploaded = true
console.log(e)
function fetchData() {
if (!props.id) return
getJob({ id: props.id }).then(res => {
const { detail } = res.data
Object.assign(data, detail)
isUploaded = detail.is_delivered
})
}
const jobContent = ref(
`岗位职责
1、建立申请风险评分、欺诈评分、催收评分等系列预测模型;
2、分析模型效果,使用统计方法设计模型使用方案;
3、对各类场景下的金融产品进行客户分群、多因素模型敏感性分析;
4、对于指标波动等情况进行分析,出具分析报告,提出有效建议。
任职资格:
1、本科及以上学历,数学、应用数学、金融数学、统计学、自动化、人工智能相关专业优先。
2、1年左右建模经验(专业相关的应届毕业生也可)
3、了解风险建模相关工作内容及流程。
4、熟练使用Python、SQL、R、SAS等工具,了解各类模型分类与回归算法,有数据发掘经验。
5、工作责任心强,抗压能力强,有较好的学习能力及创新精神。`
)
const jobContentHtml = computed(() => {
return jobContent.value.replace(/\n/g, '<br />')
onMounted(() => {
fetchData()
})
const uploadFileUrl = ref('')
function handleUploadSuccess(file: any) {
submitResume({ id: props.id, resume: file.raw.url })
.then(() => {
isUploaded = true
ElMessage.success('投递成功')
})
.catch(res => {
ElMessage.error(res.message)
})
}
</script>
<template>
<AppCard>
<div class="job-info">
<div class="job-info-hd">
<h4>Java开发工程师</h4>
<p>15000-25000</p>
<h4>{{ data.name }}</h4>
<p>{{ data.salary_min }}-{{ data.salary_max }}</p>
</div>
<div class="job-info-bd">
<ul>
<li>河北-唐山</li>
<li>本科</li>
<li>{{ data.work_locations }}</li>
<li>{{ educationName }}</li>
</ul>
</div>
<div class="job-info-ft">
......@@ -45,18 +71,23 @@ const jobContentHtml = computed(() => {
v-model="uploadFileUrl"
accept="application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
@success="handleUploadSuccess"
><el-button type="primary" :disabled="isUploaded" style="border-radius: 10px">
{{ uploadButtonText }}
</el-button></AppUpload
>
<el-button type="primary" :disabled="isUploaded" style="border-radius: 10px">
{{ uploadButtonText }}
</el-button>
</AppUpload>
<p class="job-info-company">
<span>专业技术类</span>
<span><router-link to="/hr/company/view/123" target="_blank">河北唐山技术开发有限公司</router-link></span>
<span>{{ jobTypeName }}</span>
<span v-if="data.company">
<router-link :to="`/hr/company/view?id=${data.company.id}`" target="_blank">
{{ data.company.name }}
</router-link>
</span>
</p>
</div>
</div>
<h2 class="job-desc-title">职位描述</h2>
<div class="job-desc" v-html="jobContentHtml"></div>
<div class="job-desc" v-html="descHtml"></div>
</AppCard>
</template>
......
import httpRequest from '@/utils/axios'
import type { JobType } from './types'
// 获取我的岗位列表
export function getMyJobList(params?: {
page?: number
limit?: number
name?: string
type?: number
education?: number
work_locations?: string
status?: 1 | 2
audit_status?: 1 | 2 | 3
}) {
return httpRequest.get('/api/hr/api/v1/position/my-list', { params })
}
// 创建岗位
export function createCompany(data: JobType) {
return httpRequest.post('/api/psp/backend/banner/create', data)
export function createJob(data: JobType) {
return httpRequest.post('/api/hr/api/v1/position/publish', data)
}
// 更新岗位
export function updateCompany(data: JobType) {
return httpRequest.post('/api/psp/backend/banner/update', data)
export function updateJob(data: JobType) {
return httpRequest.put(`/api/hr/api/v1/position/${data.id}/update`, data)
}
// 获取岗位详情
export function getCompany(params: { id: string }) {
return httpRequest.get('/api/psp/backend/banner/view', { params })
export function getJob(params: { id: string }) {
return httpRequest.get(`/api/hr/api/v1/position/${params.id}/detail`, { params })
}
// 获取岗位简历列表
export function getJobResumeList(params: { id: string }) {
return httpRequest.get(`/api/hr/api/v1/position/${params.id}/delever-records`, { params })
}
// 启用/禁用岗位
export function enableJob(data: { id: string; status: 1 | 2 }) {
return httpRequest.post(`/api/hr/api/v1/position/${data.id}/enable`, data)
}
......@@ -9,7 +9,7 @@ export const routes: Array<RouteRecordRaw> = [
{ path: '', redirect: '/hr/posts/job' },
{ path: 'job', component: () => import('./views/Job.vue') },
{ path: 'job/create', component: () => import('./views/JobUpdate.vue') },
{ path: 'job/update/:id', component: () => import('./views/JobUpdate.vue') },
{ path: 'job/update/:id', component: () => import('./views/JobUpdate.vue'), props: true },
{
path: 'job/view/:id',
component: () => import('./views/JobView.vue'),
......
export interface JobType {
id?: string
name: string
education: number | undefined
type: number | undefined
education?: 1 | 2 | 3 | 4 | 5
type?: 1 | 2 | 3 | 4 | 5
work_locations: string
salary_min: number | undefined
salary_max: number | undefined
salary_min?: number
salary_max?: number
desc: string
status?: 1 | 2
audit_status?: 1 | 2 | 3
company?: {
id: string
name: string
logo: string
status: 1 | 2
audit_status: 1 | 2 | 3
}
project_prefix_group?: string
}
<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus'
import AppList from '@/components/base/AppList.vue'
import { jobTypeList, educationList } from '@/utils/dictionary'
import AppArea from '@/components/AppArea.vue'
import { jobType, jobTypeList, education, educationList, auditStatus } from '@/utils/dictionary'
import { getMyJobList, enableJob } from '../api'
import type { JobType } from '../types'
const appList = $ref<InstanceType<typeof AppList> | null>(null)
const listOptions = {
remote: {},
remote: {
httpRequest: getMyJobList,
params: {
name: '',
type: undefined,
education: undefined,
work_locations: '',
status: undefined,
audit_status: undefined
}
},
filters: [
{ type: 'input', label: '岗位名称', prop: 'name', placeholder: '请输入' },
{ type: 'select', label: '岗位类型', prop: 'type', options: jobTypeList },
{ type: 'select', label: '学历要求', prop: 'education', options: educationList },
{ type: 'select', label: '工作地点', prop: 'work_locations' }
{ type: 'select', label: '工作地点', prop: 'work_locations', slots: 'filter-area' }
],
columns: [
{ label: '编号', prop: 'id' },
{ label: '岗位名称', prop: 'name' },
{ label: '岗位类型', prop: 'type' },
{ label: '地点', prop: 'work_locations' },
{ label: '学历要求', prop: 'education' },
{ label: '薪酬范围', prop: 'education' },
{ label: '投递人数', prop: 'education' },
{ label: '状态', prop: 'status' },
{ label: '操作', slots: 'table-actions' }
],
data: [
{ id: '1', name: '岗位名称', education: 1, type: 1, salary_min: 10000, salary_max: 20000, desc: '描述' },
{ id: '2', name: '岗位名称', education: 1, type: 1, salary_min: 10000, salary_max: 20000, desc: '描述' }
{
label: '岗位类型',
prop: 'type',
align: 'center',
computed({ row }: { row: JobType }) {
return row.type && jobType[row.type]
}
},
{ label: '地点', prop: 'work_locations', align: 'center' },
{
label: '学历要求',
prop: 'education',
align: 'center',
computed({ row }: { row: JobType }) {
return row.education && education[row.education]
}
},
{
label: '薪酬范围',
prop: 'salary_max',
align: 'center',
computed({ row }: { row: JobType }) {
return `${row.salary_min}-${row.salary_max}`
}
},
{ label: '投递人数', prop: 'deliver_count', align: 'center' },
{ label: '启用状态', prop: 'status', align: 'center', slots: 'table-status' },
{
label: '审核状态',
prop: 'audit_status',
align: 'center',
computed({ row }: { row: JobType }) {
return row.audit_status && auditStatus[row.audit_status]
}
},
{ label: '操作', align: 'center', slots: 'table-actions' }
]
}
function handleSearch() {
appList?.search()
}
// 启用/禁用
function onEnable(row: JobType) {
if (!row.id || !row.status) return
const status = row.status === 1 ? 2 : 1
const statusText = status === 1 ? '启用' : '禁用'
ElMessageBox.confirm(`确定要${statusText}该岗位吗?`).then(() => {
enableJob({ status, id: row.id as string })
.then(() => {
ElMessage.success(`${statusText}成功`)
appList?.refetch()
})
.catch(res => {
ElMessage.error(res.message)
})
})
}
</script>
<template>
......@@ -36,15 +94,21 @@ const listOptions = {
<el-button type="primary">发布岗位</el-button>
</router-link>
</div>
<template #filter-area="{ params }">
<AppArea v-model="params.work_locations" @change="handleSearch"></AppArea>
</template>
<template #table-status="{ row }">
<el-switch :value="row.status" :active-value="1" :inactive-value="2" @change="onEnable(row)" />
</template>
<template #table-actions="{ row }">
<router-link :to="`/hr/posts/job/view/${row.id}`" target="_blank">
<el-button link>查看</el-button>
</router-link>
<el-button link>启用</el-button>
<el-button link>禁用</el-button>
<router-link :to="`/hr/posts/job/update/${row.id}`">
<el-button link>编辑</el-button>
</router-link>
<router-link :to="`/hr/posts/job/view/${row.id}`" target="_blank" style="color: #399ee8">查看</router-link>
<router-link
:to="`/hr/posts/job/update/${row.id}`"
style="margin-left: 10px; color: #399ee8"
v-if="row.audit_status !== 3"
>编辑</router-link
>
</template>
</AppList>
</template>
......@@ -54,5 +118,13 @@ const listOptions = {
padding: 30px 30px 10px;
background: #f8f8f8;
border-radius: 20px;
.el-form-item__label {
width: 80px;
}
.el-input,
.el-select {
width: 210px !important;
}
}
</style>
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import type { FormInstance } from 'element-plus'
import { createCompany, updateCompany, getCompany } from '../api'
import AppArea from '@/components/AppArea.vue'
import { createJob, updateJob, getJob } from '../api'
import type { JobType } from '../types'
import { jobTypeList, educationList } from '@/utils/dictionary'
......@@ -41,7 +42,7 @@ const onCancel = () => {
}
// 创建
const create = () => {
createCompany(form).then(() => {
createJob(form).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
router.push('/hr/posts/job')
})
......@@ -49,7 +50,7 @@ const create = () => {
// 修改
const update = () => {
const params = { ...form, id: props.id as string }
updateCompany(params).then(() => {
updateJob(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
router.push('/hr/posts/job')
})
......@@ -57,8 +58,8 @@ const update = () => {
onMounted(() => {
props.id &&
getCompany({ id: props.id }).then(res => {
Object.assign(form, res.data)
getJob({ id: props.id }).then(res => {
Object.assign(form, res.data.detail)
})
})
</script>
......@@ -87,7 +88,7 @@ onMounted(() => {
</el-select>
</el-form-item>
<el-form-item label="工作地点" prop="work_locations">
<el-input v-model="form.work_locations" placeholder="请输入" />
<AppArea v-model="form.work_locations" style="width: 100%"></AppArea>
</el-form-item>
<el-form-item label="薪酬范围" prop="salary_min">
<el-row>
......@@ -104,8 +105,8 @@ onMounted(() => {
<el-input type="textarea" v-model="form.desc" :autosize="{ minRows: 12, maxRows: 20 }" maxlength="200" />
</el-form-item>
<el-row justify="center" style="margin: 40px 0 20px">
<el-button type="primary" auto-insert-space @click="onSubmit">发布</el-button>
<el-button auto-insert-space @click="onCancel">取消</el-button>
<el-button type="primary" auto-insert-space @click="onSubmit" style="border-radius: 10px">点击发布</el-button>
<el-button auto-insert-space @click="onCancel" v-if="false">取消</el-button>
</el-row>
</el-form>
</template>
<script setup lang="ts">
import { getJob, getJobResumeList } from '../api'
import { jobType, education, projectPrefix } from '@/utils/dictionary'
import type { JobType } from '../types'
const props = defineProps<{ id?: string }>()
const data = reactive<JobType>({
name: '',
education: undefined,
type: undefined,
work_locations: '',
salary_min: undefined,
salary_max: undefined,
desc: ''
})
const jobTypeName = computed(() => {
return data.type && jobType[data.type]
})
const educationName = computed(() => {
return data.education && education[data.education]
})
const descHtml = computed(() => {
return data.desc.replace(/\n/g, '<br />')
})
function fetchData() {
if (!props.id) return
getJob({ id: props.id }).then(res => {
Object.assign(data, res.data.detail)
})
}
onMounted(() => {
fetchData()
})
const listOptions = {
remote: {},
hasPagination: false,
remote: {
httpRequest: getJobResumeList,
params: { id: props.id },
callback(data: any) {
return { data: data.items }
}
},
columns: [
{ label: '编号', prop: 'name' },
{ label: '姓名', prop: 'name' },
{ label: '已投递简历数', prop: 'type' },
{ label: '所在项目', prop: 'work_locations' },
{ label: '操作', slots: 'table-actions' }
{ label: '编号', align: 'center', slots: 'table-index' },
{ label: '姓名', prop: 'username', align: 'center' },
{ label: '已投递简历数', prop: 'deliver_counts', align: 'center' },
{
label: '所在项目',
prop: 'project_prefix_group',
align: 'center',
computed({ row }: { row: JobType }) {
return row.project_prefix_group
?.split(',')
.map(item => {
return projectPrefix[item] || item
})
.join(',')
}
},
{ label: '操作', slots: 'table-actions', align: 'center' }
]
}
// 编号
function indexName(index: number): string {
return (index + 1).toString().padStart(3, '0')
}
</script>
<template>
......@@ -17,43 +75,39 @@ const listOptions = {
<div class="job-info">
<dl>
<dt>岗位名称</dt>
<dd>北京奔驰技术工人</dd>
<dd>{{ data.name }}</dd>
</dl>
<dl>
<dt>岗位类型</dt>
<dd>技术工人</dd>
<dd>{{ jobTypeName }}</dd>
</dl>
<dl>
<dt>岗位地点</dt>
<dd>北京</dd>
<dd>{{ data.work_locations }}</dd>
</dl>
<dl>
<dt>学历要求</dt>
<dd>大专</dd>
<dd>{{ educationName }}</dd>
</dl>
<dl>
<dt>公司名称</dt>
<dd>北京奔驰技术工人某某公司</dd>
<dd>{{ data.company?.name }}</dd>
</dl>
<dl>
<dt>薪资范围</dt>
<dd>10000-13000</dd>
<dd>{{ data.salary_min }}-{{ data.salary_max }}</dd>
</dl>
<dl style="grid-column: 3; grid-row: 1/5">
<dt>岗位介绍</dt>
<dd>
中加本硕直通车项目是针对大专及本科生提升学历、移居海外的定制通道。
采用国内2.5+1.5(专升本)/3.5+2(本硕连读)年的合作模式即可分别获得加拿大卡普顿大学的本科与硕士学位,符合条件的国内院校的大专及本科生分别在国内完成2.5年及3.5年的专科和本科的学习,可直接进入加拿大卡普顿大学进行本科和硕士阶段的学习。本项目对接经教育部认证的国外名校,旨在帮助学生缩短留学周期,让学生顺利完成国外规定的学业课程,获得国外学位及移民海外的需求。
中加本硕直通车项目是针对大专及本科生提升学历、移居海外的定制通道。
采用国内2.5+1.5(专升本)/3.5+2(本硕连读)年的合作模式即可分别获得加拿大卡普顿大学的本科与硕士学位,符合条件的国内院校的大专及本科生分别在国内完成2.5年及3.5年的专科和本科的学习,可直接进入加拿大卡普顿大学进行本科和硕士阶段的学习。本项目对接经教育部认证的国外名校,旨在帮助学生缩短留学周期,让学生顺利完成国外规定的学业课程,获得国外学位及移民海外的需求。
中加本硕直通车项目是针对大专及本科生提升学历、移居海外的定制通道。
采用国内2.5+1.5(专升本)/3.5+2(本硕连读)年的合作模式即可分别获得加拿大卡普顿大学的本科与硕士学位,符合条件的国内院校的大专及本科生分别在国内完成2.5年及3.5年的专科和本科的学习,可直接进入加拿大卡普顿大学进行本科和硕士阶段的学习。本项目对接经教育部认证的国外名校,旨在帮助学生缩短留学周期,让学生顺利完成国外规定的学业课程,获得国外学位及移民海外的需求。
</dd>
<dd v-html="descHtml"></dd>
</dl>
</div>
<h2 class="subtitle" style="padding-bottom: 0">简历</h2>
<h2 class="subtitle" style="padding-bottom: 0">投递详情</h2>
<AppList v-bind="listOptions">
<template #table-actions> 查看 </template>
<template #table-index="{ $index }"> {{ indexName($index) }} </template>
<template #table-actions="{ row }">
<a :href="row.resume" target="_blank" style="color: #399ee8">查看</a>
</template>
</AppList>
</div>
</template>
......@@ -74,6 +128,7 @@ const listOptions = {
dd {
font-size: 16px;
font-weight: 400;
line-height: 34px;
color: #333333;
}
}
......
......@@ -26,7 +26,7 @@ export function getProject(params: { id: string }) {
return httpRequest.get(`/api/hr/api/v1/project/${params.id}/detail`, { params })
}
// 项目审核
export function auditProject(data: { id: string; status: 1 | 2 }) {
// 项目启用和禁用
export function enableProject(data: { id: string; status: 1 | 2 }) {
return httpRequest.post(`/api/hr/api/v1/project/${data.id}/audit`, data)
}
<script setup lang="ts">
import { Plus } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { ProjectType } from '../types'
import ProjectListItem from './ProjectListItem.vue'
import { getMyProjectList, auditProject } from '../api'
import { getMyProjectList, enableProject } from '../api'
import { useUserStore } from '@/stores/user'
const user = useUserStore()
const router = useRouter()
const dataset = reactive<{ total: number; list: ProjectType[] }>({ total: 0, list: [] })
const params = reactive({ page: 1, limit: 3 })
......@@ -33,10 +38,10 @@ onMounted(() => {
})
// 启用/禁用
function onAudit(status: 1 | 2, data: ProjectType) {
function onEnable(status: 1 | 2, data: ProjectType) {
const statusText = status === 1 ? '启用' : '禁用'
ElMessageBox.confirm(`确定要${statusText}该项目吗?`).then(() => {
auditProject({ status, id: data.id as string })
enableProject({ status, id: data.id as string })
.then(() => {
ElMessage.success(`${statusText}成功`)
fetchList()
......@@ -46,6 +51,14 @@ function onAudit(status: 1 | 2, data: ProjectType) {
})
})
}
function onAdd() {
if (!user.hasCompany) {
ElMessage({ message: '请先注册您的企业' })
} else {
router.push('/project/create')
}
}
</script>
<template>
......@@ -61,10 +74,14 @@ function onAudit(status: 1 | 2, data: ProjectType) {
</div>
<div class="project-list" v-loading="loading">
<ProjectListItem v-for="item in dataset.list" :key="item.id" :data="item" isMine @audit="onAudit"></ProjectListItem>
<div class="project-item">
<router-link to="/project/create" class="project-item__add"><Plus />发布新项目</router-link>
</div>
<ProjectListItem
v-for="item in dataset.list"
:key="item.id"
:data="item"
isMine
@enable="onEnable"
></ProjectListItem>
<div class="project-item project-item__add" @click="onAdd"><Plus />发布新项目</div>
</div>
</template>
......@@ -81,8 +98,6 @@ function onAudit(status: 1 | 2, data: ProjectType) {
row-gap: 20px;
}
.project-item__add {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
......
......@@ -3,7 +3,7 @@ import type { ProjectType } from '../types'
const props = defineProps<{ data: ProjectType; isMine?: boolean }>()
const emit = defineEmits<{
(e: 'audit', status: 1 | 2, data: ProjectType): void
(e: 'enable', status: 1 | 2, data: ProjectType): void
}>()
const descHtml = computed(() => {
......@@ -28,8 +28,8 @@ const descHtml = computed(() => {
</div>
</router-link>
<ul class="project-actions" v-if="isMine && data.audit_status === 1">
<li style="color: #60b0ea" v-if="data.status === 2" @click="emit('audit', 1, data)">启用</li>
<li style="color: #f84e46" v-if="data.status === 1" @click="emit('audit', 2, data)">禁用</li>
<li style="color: #60b0ea" v-if="data.status === 2" @click="emit('enable', 1, data)">启用</li>
<li style="color: #f84e46" v-if="data.status === 1" @click="emit('enable', 2, data)">禁用</li>
</ul>
</div>
</template>
......
<script setup lang="ts">
import MyProjectList from '../components/MyProjectList.vue'
import ProjectList from '../components/ProjectList.vue'
import { useUserStore } from '@/stores/user'
const user = useUserStore()
</script>
<template>
<AppContainer background="#fff">
<MyProjectList></MyProjectList>
<MyProjectList v-if="user.hasCompany"></MyProjectList>
<ProjectList></ProjectList>
</AppContainer>
</template>
......@@ -126,7 +126,7 @@ export const industryCategory: Record<string, string> = {
export const industryCategoryList = Object.values(industryCategory).map(item => ({ label: item, value: item }))
// 项目
export const projectPrefix = {
export const projectPrefix: Record<string, string> = {
sofia: '索菲亚',
kelley: '凯丽',
marywood: '玛丽伍德',
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论