Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas
Commits
65745ccc
提交
65745ccc
authored
6月 23, 2022
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: update
上级
274b4694
显示空白字符变更
内嵌
并排
正在显示
25 个修改的文件
包含
514 行增加
和
179 行删除
+514
-179
extensions.json
.vscode/extensions.json
+1
-1
AppArea.vue
src/components/AppArea.vue
+31
-0
HRLayout.vue
src/components/HRLayout.vue
+5
-5
AppList.vue
src/components/base/AppList.vue
+1
-1
Index.vue
src/modules/home/views/Index.vue
+2
-0
types.ts
src/modules/hr/alumni/types.ts
+5
-0
List.vue
src/modules/hr/alumni/views/List.vue
+9
-4
View.vue
src/modules/hr/alumni/views/View.vue
+15
-2
index.ts
src/modules/hr/company/index.ts
+2
-3
View.vue
src/modules/hr/company/views/View.vue
+48
-11
api.ts
src/modules/hr/job/api.ts
+16
-14
types.ts
src/modules/hr/job/types.ts
+19
-0
Index.vue
src/modules/hr/job/views/Index.vue
+39
-28
View.vue
src/modules/hr/job/views/View.vue
+60
-29
api.ts
src/modules/hr/posts/api.ts
+29
-6
index.ts
src/modules/hr/posts/index.ts
+1
-1
types.ts
src/modules/hr/posts/types.ts
+14
-4
Job.vue
src/modules/hr/posts/views/Job.vue
+95
-23
JobUpdate.vue
src/modules/hr/posts/views/JobUpdate.vue
+9
-8
JobView.vue
src/modules/hr/posts/views/JobView.vue
+77
-22
api.ts
src/modules/project/api.ts
+2
-2
MyProjectList.vue
src/modules/project/components/MyProjectList.vue
+25
-10
ProjectListItem.vue
src/modules/project/components/ProjectListItem.vue
+3
-3
Index.vue
src/modules/project/views/Index.vue
+5
-1
dictionary.ts
src/utils/dictionary.ts
+1
-1
没有找到文件。
.vscode/extensions.json
浏览文件 @
65745ccc
{
"recommendations"
:
[
"
johnsoncodehk.volar"
,
"johnsoncodehk
.vscode-typescript-vue-plugin"
]
"recommendations"
:
[
"
vue.volar"
,
"vue
.vscode-typescript-vue-plugin"
]
}
src/components/AppArea.vue
0 → 100644
浏览文件 @
65745ccc
<
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
>
src/components/HRLayout.vue
浏览文件 @
65745ccc
<
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
>
src/components/base/AppList.vue
浏览文件 @
65745ccc
...
...
@@ -119,7 +119,7 @@ onMounted(() => {
fetchList
()
})
defineExpose
({
refetch
,
tableRef
})
defineExpose
({
search
,
refetch
,
tableRef
})
</
script
>
<
template
>
...
...
src/modules/home/views/Index.vue
浏览文件 @
65745ccc
...
...
@@ -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'
)
}
...
...
src/modules/hr/alumni/types.ts
浏览文件 @
65745ccc
...
...
@@ -29,6 +29,11 @@ export interface AlumniType {
workplace
:
string
department
:
string
position
:
string
company
?:
{
id
:
string
name
:
string
desc
:
string
}
}
export
interface
ClassType
{
...
...
src/modules/hr/alumni/views/List.vue
浏览文件 @
65745ccc
...
...
@@ -87,9 +87,9 @@ const listOptions = computed(() => ({
]
}))
function
handle
UpdateList
()
{
function
handle
Search
()
{
nextTick
(()
=>
{
appList
.
value
?.
refet
ch
()
appList
.
value
?.
sear
ch
()
})
}
...
...
@@ -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=
"handle
UpdateList
"
style=
"width: 250px"
>
<el-select
filterable
clearable
v-model=
"provinceValue"
@
change=
"handle
Search
"
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=
"handle
UpdateList
"
@
change=
"handle
Search
"
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
>
src/modules/hr/alumni/views/View.vue
浏览文件 @
65745ccc
...
...
@@ -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
>
src/modules/hr/company/index.ts
浏览文件 @
65745ccc
...
...
@@ -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'
)
}
]
}
...
...
src/modules/hr/company/views/View.vue
浏览文件 @
65745ccc
<
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
>
src/modules/hr/job/api.ts
浏览文件 @
65745ccc
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-talent
s'
,
{
params
})
return
httpRequest
.
get
(
'/api/hr/api/v1/
position
s'
,
{
params
})
}
// 获取
校友
详情
export
function
get
AlumniDetail
(
params
:
{
id
:
string
})
{
return
httpRequest
.
get
(
`/api/hr/api/v1/
alumni-talent/
${
params
.
id
}
`
,
{
params
})
// 获取
岗位
详情
export
function
get
Job
(
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
)
}
src/modules/hr/job/types.ts
0 → 100644
浏览文件 @
65745ccc
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
}
}
src/modules/hr/job/views/Index.vue
浏览文件 @
65745ccc
<
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">
...
...
src/modules/hr/job/views/View.vue
浏览文件 @
65745ccc
<
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
?
'已投递'
:
'申请该职位'
))
function
fetchData
()
{
if
(
!
props
.
id
)
return
getJob
({
id
:
props
.
id
}).
then
(
res
=>
{
const
{
detail
}
=
res
.
data
Object
.
assign
(
data
,
detail
)
isUploaded
=
detail
.
is_delivered
})
}
onMounted
(()
=>
{
fetchData
()
})
const
uploadFileUrl
=
ref
(
''
)
function
handleUploadSuccess
(
e
:
any
)
{
function
handleUploadSuccess
(
file
:
any
)
{
submitResume
({
id
:
props
.
id
,
resume
:
file
.
raw
.
url
})
.
then
(()
=>
{
isUploaded
=
true
console
.
log
(
e
)
ElMessage
.
success
(
'投递成功'
)
})
.
catch
(
res
=>
{
ElMessage
.
error
(
res
.
message
)
})
}
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 />'
)
})
</
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=
"
jobContent
Html"
></div>
<div
class=
"job-desc"
v-html=
"
desc
Html"
></div>
</AppCard>
</
template
>
...
...
src/modules/hr/posts/api.ts
浏览文件 @
65745ccc
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
create
Company
(
data
:
JobType
)
{
return
httpRequest
.
post
(
'/api/
psp/backend/banner/create
'
,
data
)
export
function
create
Job
(
data
:
JobType
)
{
return
httpRequest
.
post
(
'/api/
hr/api/v1/position/publish
'
,
data
)
}
// 更新岗位
export
function
update
Company
(
data
:
JobType
)
{
return
httpRequest
.
p
ost
(
'/api/psp/backend/banner/update'
,
data
)
export
function
update
Job
(
data
:
JobType
)
{
return
httpRequest
.
p
ut
(
`/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
)
}
src/modules/hr/posts/index.ts
浏览文件 @
65745ccc
...
...
@@ -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'
),
...
...
src/modules/hr/posts/types.ts
浏览文件 @
65745ccc
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
}
src/modules/hr/posts/views/Job.vue
浏览文件 @
65745ccc
<
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
>
src/modules/hr/posts/views/JobUpdate.vue
浏览文件 @
65745ccc
<
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
=
()
=>
{
create
Company
(
form
).
then
(()
=>
{
create
Job
(
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
}
update
Company
(
params
).
then
(()
=>
{
update
Job
(
params
).
then
(()
=>
{
ElMessage
({
message
:
'修改成功'
,
type
:
'success'
})
router
.
push
(
'/hr/posts/job'
)
})
...
...
@@ -57,8 +58,8 @@ const update = () => {
onMounted
(()
=>
{
props
.
id
&&
get
Company
({
id
:
props
.
id
}).
then
(
res
=>
{
Object
.
assign
(
form
,
res
.
data
)
get
Job
({
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
>
src/modules/hr/posts/views/JobView.vue
浏览文件 @
65745ccc
<
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
;
}
}
...
...
src/modules/project/api.ts
浏览文件 @
65745ccc
...
...
@@ -26,7 +26,7 @@ export function getProject(params: { id: string }) {
return
httpRequest
.
get
(
`/api/hr/api/v1/project/
${
params
.
id
}
/detail`
,
{
params
})
}
// 项目
审核
export
function
audit
Project
(
data
:
{
id
:
string
;
status
:
1
|
2
})
{
// 项目
启用和禁用
export
function
enable
Project
(
data
:
{
id
:
string
;
status
:
1
|
2
})
{
return
httpRequest
.
post
(
`/api/hr/api/v1/project/
${
data
.
id
}
/audit`
,
data
)
}
src/modules/project/components/MyProjectList.vue
浏览文件 @
65745ccc
<
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
on
Audit
(
status
:
1
|
2
,
data
:
ProjectType
)
{
function
on
Enable
(
status
:
1
|
2
,
data
:
ProjectType
)
{
const
statusText
=
status
===
1
?
'启用'
:
'禁用'
ElMessageBox
.
confirm
(
`确定要
${
statusText
}
该项目吗?`
).
then
(()
=>
{
audit
Project
({
status
,
id
:
data
.
id
as
string
})
enable
Project
({
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
;
...
...
src/modules/project/components/ProjectListItem.vue
浏览文件 @
65745ccc
...
...
@@ -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>
...
...
src/modules/project/views/Index.vue
浏览文件 @
65745ccc
<
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
>
src/utils/dictionary.ts
浏览文件 @
65745ccc
...
...
@@ -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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论