Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
R
recruit-sys
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李文光
recruit-sys
Commits
a730e3ab
Commit
a730e3ab
authored
Sep 10, 2026
by
李文光
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(jobs): 简化岗位编辑流程并优化 JD 与内约束表单
parent
3e6bc5e4
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
202 additions
and
84 deletions
+202
-84
JobEdit.vue
vue-app/src/components/jobs/JobEdit.vue
+202
-84
No files found.
vue-app/src/components/jobs/JobEdit.vue
View file @
a730e3ab
...
@@ -12,8 +12,6 @@ import {
...
@@ -12,8 +12,6 @@ import {
JOB_STATUS
,
JOB_STATUS
,
JOB_STATUS_OPTIONS
,
JOB_STATUS_OPTIONS
,
JD_STATUS
,
JD_STATUS
,
JD_STATUS_EDITABLE_OPTIONS
,
APPROVAL_STATUS
,
PRIORITY_OPTIONS
,
PRIORITY_OPTIONS
,
HIRE_REASON_OPTIONS
,
HIRE_REASON_OPTIONS
,
RECRUIT_TYPE
,
RECRUIT_TYPE
,
...
@@ -22,7 +20,6 @@ import {
...
@@ -22,7 +20,6 @@ import {
LEVEL_OPTIONS
,
LEVEL_OPTIONS
,
LOCATION_OPTIONS
,
LOCATION_OPTIONS
,
}
from
'@/utils/jobStatus'
}
from
'@/utils/jobStatus'
import
JdGrillModal
from
'./JdGrillModal.vue'
import
JdGeneratePanel
from
'./JdGeneratePanel.vue'
import
JdGeneratePanel
from
'./JdGeneratePanel.vue'
import
JdImportModal
from
'./JdImportModal.vue'
import
JdImportModal
from
'./JdImportModal.vue'
...
@@ -72,6 +69,19 @@ function parseSalaryRange(text) {
...
@@ -72,6 +69,19 @@ function parseSalaryRange(text) {
return
{
min
:
null
,
max
:
null
}
return
{
min
:
null
,
max
:
null
}
}
}
function
parseAgeRange
(
text
)
{
const
raw
=
String
(
text
||
''
).
trim
()
const
range
=
raw
.
match
(
/^
(\d{1,2})\s
*
[
-~至到
]\s
*
(\d{1,2})
/
)
if
(
range
)
return
{
min
:
Number
(
range
[
1
]),
max
:
Number
(
range
[
2
])
}
const
above
=
raw
.
match
(
/^
(\d{1,2})\s
*岁
?(?:
及以上|以上|起
)
/
)
if
(
above
)
return
{
min
:
Number
(
above
[
1
]),
max
:
null
}
const
below
=
raw
.
match
(
/^
(\d{1,2})\s
*岁
?(?:
及以下|以下
)
/
)
if
(
below
)
return
{
min
:
null
,
max
:
Number
(
below
[
1
])
}
const
single
=
raw
.
match
(
/^
(\d{1,2})\s
*岁
?
$/
)
if
(
single
)
return
{
min
:
Number
(
single
[
1
]),
max
:
Number
(
single
[
1
])
}
return
{
min
:
null
,
max
:
null
}
}
const
form
=
reactive
({
const
form
=
reactive
({
jobId
:
''
,
jobId
:
''
,
title
:
''
,
title
:
''
,
...
@@ -173,6 +183,81 @@ const clearSalaryRange = () => {
...
@@ -173,6 +183,81 @@ const clearSalaryRange = () => {
form
.
salaryRange
=
''
form
.
salaryRange
=
''
}
}
// 年龄要求同样用「最低/最高」成对选择,单位为岁;空值表示不限
const
AGE_YEAR_OPTIONS
=
Array
.
from
({
length
:
43
},
(
_
,
index
)
=>
18
+
index
)
const
ageLow
=
ref
(
null
)
const
ageHigh
=
ref
(
null
)
const
ageRangeSet
=
computed
(()
=>
Boolean
(
String
(
form
.
internal
.
ageRestriction
||
''
).
trim
()))
const
syncAgePair
=
()
=>
{
const
{
min
,
max
}
=
parseAgeRange
(
form
.
internal
.
ageRestriction
)
ageLow
.
value
=
min
ageHigh
.
value
=
max
??
min
}
const
writeAgeRange
=
()
=>
{
const
low
=
ageLow
.
value
const
high
=
ageHigh
.
value
if
(
low
===
null
&&
high
===
null
)
{
form
.
internal
.
ageRestriction
=
''
return
}
if
(
low
!==
null
&&
high
===
null
)
{
form
.
internal
.
ageRestriction
=
`
${
low
}
岁及以上`
return
}
if
(
low
===
null
&&
high
!==
null
)
{
form
.
internal
.
ageRestriction
=
`
${
high
}
岁及以下`
return
}
form
.
internal
.
ageRestriction
=
low
===
high
?
`
${
low
}
岁`
:
`
${
low
}
-
${
high
}
岁`
}
const
onAgeLowChange
=
()
=>
{
if
(
ageLow
.
value
===
null
||
ageLow
.
value
===
''
)
{
ageLow
.
value
=
null
ageHigh
.
value
=
null
form
.
internal
.
ageRestriction
=
''
return
}
if
(
ageHigh
.
value
!==
null
&&
Number
(
ageHigh
.
value
)
<
Number
(
ageLow
.
value
))
{
ageHigh
.
value
=
ageLow
.
value
}
writeAgeRange
()
}
const
onAgeHighChange
=
()
=>
{
if
(
ageHigh
.
value
===
null
||
ageHigh
.
value
===
''
)
return
writeAgeRange
()
}
const
clearAgeRange
=
()
=>
{
ageLow
.
value
=
null
ageHigh
.
value
=
null
form
.
internal
.
ageRestriction
=
''
}
const
PROBATION_MONTH_OPTIONS
=
[
3
,
4
,
5
,
6
]
const
normalizeGenderValue
=
(
value
)
=>
{
const
raw
=
String
(
value
||
''
).
trim
()
if
([
'不限'
,
'男'
,
'女'
].
includes
(
raw
))
return
raw
if
(
raw
===
'男女不限'
||
raw
===
'不限性别'
)
return
'不限'
return
raw
}
const
normalizeProbationPeriod
=
(
value
)
=>
{
const
raw
=
String
(
value
||
''
).
trim
()
const
match
=
raw
.
match
(
/^
(\d{1,2})\s
*个月
?
$/
)
return
match
?
`
${
Number
(
match
[
1
])}
个月`
:
raw
}
const
normalizeNonCompeteValue
=
(
value
)
=>
{
const
raw
=
String
(
value
||
''
).
trim
()
return
raw
===
'不需要'
?
'无需签'
:
raw
}
// 新建岗位必填项:与表单里 required 标记保持一致,缺失时阻止提交并跳到对应 Tab
// 新建岗位必填项:与表单里 required 标记保持一致,缺失时阻止提交并跳到对应 Tab
const
REQUIRED_CREATE_FIELDS
=
[
const
REQUIRED_CREATE_FIELDS
=
[
{
key
:
'title'
,
label
:
'岗位名称'
,
tab
:
'base'
},
{
key
:
'title'
,
label
:
'岗位名称'
,
tab
:
'base'
},
...
@@ -212,67 +297,26 @@ const syncForm = () => {
...
@@ -212,67 +297,26 @@ const syncForm = () => {
form
.
startDate
=
job
?.
startDate
||
''
form
.
startDate
=
job
?.
startDate
||
''
form
.
reportTo
=
job
?.
reportTo
||
''
form
.
reportTo
=
job
?.
reportTo
||
''
form
.
internal
=
{
form
.
internal
=
{
genderRestriction
:
job
?.
genderRestriction
||
''
,
genderRestriction
:
normalizeGenderValue
(
job
?.
genderRestriction
)
,
ageRestriction
:
job
?.
ageRestriction
||
''
,
ageRestriction
:
job
?.
ageRestriction
||
''
,
probationPeriod
:
job
?.
probationPeriod
||
''
,
probationPeriod
:
normalizeProbationPeriod
(
job
?.
probationPeriod
)
,
probationCriteria
:
job
?.
probationCriteria
||
''
,
probationCriteria
:
job
?.
probationCriteria
||
''
,
nonCompete
:
job
?.
nonCompete
||
''
,
nonCompete
:
normalizeNonCompeteValue
(
job
?.
nonCompete
)
,
verification
:
job
?.
verification
||
''
,
verification
:
job
?.
verification
||
''
,
}
}
syncSalaryPair
()
syncSalaryPair
()
syncAgePair
()
}
}
syncForm
()
syncForm
()
watch
(()
=>
form
.
salaryRange
,
syncSalaryPair
)
watch
(()
=>
form
.
salaryRange
,
syncSalaryPair
)
watch
(()
=>
form
.
internal
.
ageRestriction
,
syncAgePair
)
const
back
=
()
=>
{
const
back
=
()
=>
{
if
(
existing
.
value
)
router
.
push
(
`/jobs/
${
existing
.
value
.
id
}
`
)
if
(
existing
.
value
)
router
.
push
(
`/jobs/
${
existing
.
value
.
id
}
`
)
else
router
.
push
(
'/jobs'
)
else
router
.
push
(
'/jobs'
)
}
}
// AI 辅助创建:新建岗位直接进访谈逐题问清,完成后自动把采集的结构化岗位信息回填表单。
// 这里返回的是访谈累积的 jd/职责/要求等字段,缺的字段由生成器在后续创建时推断。
const
aiAssistCreate
=
async
()
=>
{
if
(
!
form
.
title
.
trim
())
{
showToast
(
'请先填写岗位名称,AI 才能基于它追问补全'
,
'warning'
)
return
}
const
baseJob
=
{
title
:
form
.
title
,
department
:
form
.
department
,
recruitType
:
form
.
recruitType
,
jobType
:
form
.
jobType
,
headcount
:
form
.
headcount
,
owner
:
form
.
owner
,
salaryRange
:
form
.
salaryRange
,
priority
:
form
.
priority
,
}
try
{
// assist 直接进访谈逐题问清;完成后 store 内部已 force 生成完整 JD 并带回 draft
const
result
=
await
store
.
openJdGrill
(
baseJob
,
'assist'
)
if
(
!
result
)
return
const
accumulatedJob
=
result
.
job
||
baseJob
const
fields
=
[
[
'jd'
,
'jd'
],
[
'responsibilities'
,
'responsibilities'
],
[
'requirements'
,
'requirements'
],
[
'mustHave'
,
'mustHave'
],
[
'niceToHave'
,
'niceToHave'
],
[
'knockout'
,
'knockout'
],
[
'matchKeywords'
,
'matchKeywords'
],
[
'competency'
,
'competency'
],
]
for
(
const
[
formKey
,
draftKey
]
of
fields
)
{
const
value
=
result
[
draftKey
]
??
accumulatedJob
[
draftKey
]
if
(
value
&&
!
form
[
formKey
])
form
[
formKey
]
=
value
}
showToast
(
'AI 已补全岗位信息,可直接检查后创建'
,
'success'
)
}
catch
(
error
)
{
if
(
error
?.
message
===
'已取消追问'
||
error
?.
message
===
'已取消生成'
)
return
// 用户主动取消,不提示错误
showToast
(
error
.
message
||
'AI 辅助创建失败'
,
'error'
)
}
}
const
submit
=
async
(
saveMode
=
'update'
)
=>
{
const
submit
=
async
(
saveMode
=
'update'
)
=>
{
if
(
!
form
.
title
.
trim
())
{
if
(
!
form
.
title
.
trim
())
{
showToast
(
'请填写岗位名称'
,
'warning'
)
showToast
(
'请填写岗位名称'
,
'warning'
)
...
@@ -404,6 +448,16 @@ const copyVersion = (version) => {
...
@@ -404,6 +448,16 @@ const copyVersion = (version) => {
const
activeTab
=
ref
(
'base'
)
const
activeTab
=
ref
(
'base'
)
const
nextStep
=
()
=>
{
if
(
activeTab
.
value
===
'base'
)
{
activeTab
.
value
=
'jd'
}
else
if
(
activeTab
.
value
===
'jd'
)
{
activeTab
.
value
=
'status'
}
else
{
submit
(
'update'
)
}
}
// 需求 9:粘贴 JD 自动结构化 / 需求模板(JdImportModal)
// 需求 9:粘贴 JD 自动结构化 / 需求模板(JdImportModal)
const
importOpen
=
ref
(
false
)
const
importOpen
=
ref
(
false
)
const
importMode
=
ref
(
'paste'
)
const
importMode
=
ref
(
'paste'
)
...
@@ -459,7 +513,10 @@ const applyParsed = ({ fields = {}, mode = 'fill' }) => {
...
@@ -459,7 +513,10 @@ const applyParsed = ({ fields = {}, mode = 'fill' }) => {
if
(
!
value
)
return
if
(
!
value
)
return
const
current
=
String
(
form
.
internal
[
key
]
||
''
).
trim
()
const
current
=
String
(
form
.
internal
[
key
]
||
''
).
trim
()
if
(
mode
===
'overwrite'
||
!
current
)
{
if
(
mode
===
'overwrite'
||
!
current
)
{
form
.
internal
[
key
]
=
value
if
(
key
===
'genderRestriction'
)
form
.
internal
[
key
]
=
normalizeGenderValue
(
value
)
else
if
(
key
===
'probationPeriod'
)
form
.
internal
[
key
]
=
normalizeProbationPeriod
(
value
)
else
if
(
key
===
'nonCompete'
)
form
.
internal
[
key
]
=
normalizeNonCompeteValue
(
value
)
else
form
.
internal
[
key
]
=
value
applied
+=
1
applied
+=
1
}
}
})
})
...
@@ -644,14 +701,14 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
...
@@ -644,14 +701,14 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
</div>
</div>
<el-form
label-position=
"top"
>
<el-form
label-position=
"top"
>
<el-form-item
label=
"岗位说明 / JD"
required
>
<el-form-item
label=
"岗位说明 / JD"
required
>
<el-input
v-model=
"form.jd"
type=
"textarea"
:
rows=
"4
"
/>
<el-input
v-model=
"form.jd"
type=
"textarea"
:
autosize=
"
{ minRows: 5, maxRows: 28 }
" />
</el-form-item>
</el-form-item>
<div
class=
"form two"
>
<div
class=
"form two"
>
<el-form-item
label=
"核心职责"
required
>
<el-form-item
label=
"核心职责"
required
class=
"jd-long-text"
>
<el-input
v-model=
"form.responsibilities"
type=
"textarea"
:
rows=
"3
"
/>
<el-input
v-model=
"form.responsibilities"
type=
"textarea"
:
autosize=
"
{ minRows: 9, maxRows: 40 }
" />
</el-form-item>
</el-form-item>
<el-form-item
label=
"任职要求"
required
>
<el-form-item
label=
"任职要求"
required
class=
"jd-long-text"
>
<el-input
v-model=
"form.requirements"
type=
"textarea"
:
rows=
"3
"
/>
<el-input
v-model=
"form.requirements"
type=
"textarea"
:
autosize=
"
{ minRows: 9, maxRows: 40 }
" />
</el-form-item>
</el-form-item>
<el-form-item
label=
"硬性条件(逗号分隔)"
>
<el-form-item
label=
"硬性条件(逗号分隔)"
>
<el-input
v-model=
"form.mustHave"
placeholder=
"如 本科, 5年经验, 电气专业"
/>
<el-input
v-model=
"form.mustHave"
placeholder=
"如 本科, 5年经验, 电气专业"
/>
...
@@ -665,8 +722,8 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
...
@@ -665,8 +722,8 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
<el-form-item
label=
"匹配关键词(逗号分隔)"
>
<el-form-item
label=
"匹配关键词(逗号分隔)"
>
<el-input
v-model=
"form.matchKeywords"
/>
<el-input
v-model=
"form.matchKeywords"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"胜任力框架"
>
<el-form-item
label=
"胜任力框架"
class=
"jd-span-full"
>
<el-input
v-model=
"form.competency"
type=
"textarea"
:
rows=
"3
"
/>
<el-input
v-model=
"form.competency"
type=
"textarea"
:
autosize=
"
{ minRows: 4, maxRows: 18 }
" />
</el-form-item>
</el-form-item>
</div>
</div>
</el-form>
</el-form>
...
@@ -674,27 +731,74 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
...
@@ -674,27 +731,74 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
<div
class=
"internal-card"
>
<div
class=
"internal-card"
>
<div
class=
"internal-card-head"
>
<div
class=
"internal-card-head"
>
<b>
对内约束(不对外发布)
</b>
<b>
对内约束(不对外发布)
</b>
<span>
性别 / 年龄 / 试用期 / 竞业 / 验证只做对内执行,对外 JD 由系统自动剥离
</span>
<span>
性别 / 年龄 / 试用期 / 竞业 /
转正 /
验证只做对内执行,对外 JD 由系统自动剥离
</span>
</div>
</div>
<el-form
label-position=
"top"
class=
"form two"
>
<el-form
label-position=
"top"
class=
"form two"
>
<el-form-item
label=
"性别要求"
>
<el-form-item
label=
"性别要求"
>
<el-input
v-model=
"form.internal.genderRestriction"
placeholder=
"不限 / 男 / 女"
/>
<el-select
v-model=
"form.internal.genderRestriction"
clearable
placeholder=
"不限"
>
<el-option
label=
"不限"
value=
"不限"
/>
<el-option
label=
"男"
value=
"男"
/>
<el-option
label=
"女"
value=
"女"
/>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"年龄要求"
>
<el-form-item
label=
"年龄要求"
>
<el-input
v-model=
"form.internal.ageRestriction"
placeholder=
"不限 或 如 30-40"
/>
<div
class=
"salary-range-field"
>
<div
class=
"salary-range-pair"
>
<div
class=
"salary-pick"
>
<el-select
v-model=
"ageLow"
class=
"salary-pick-select"
placeholder=
"选择下限"
clearable
@
change=
"onAgeLowChange"
>
<el-option
v-for=
"year in AGE_YEAR_OPTIONS"
:key=
"year"
:label=
"`$
{year}岁`" :value="year" />
</el-select>
</div>
<span
class=
"salary-range-sep"
>
—
</span>
<div
class=
"salary-pick"
>
<el-select
v-model=
"ageHigh"
class=
"salary-pick-select"
placeholder=
"选择上限"
clearable
:disabled=
"ageLow === null"
@
change=
"onAgeHighChange"
>
<el-option
v-for=
"year in AGE_YEAR_OPTIONS"
:key=
"year"
:label=
"`$
{year}岁`" :value="year" />
</el-select>
</div>
</div>
<div
v-if=
"ageRangeSet"
class=
"salary-range-readout"
>
<span
class=
"salary-range-value"
>
{{
form
.
internal
.
ageRestriction
}}
</span>
<el-button
class=
"salary-range-clear"
link
type=
"primary"
size=
"small"
@
click=
"clearAgeRange"
>
清除
</el-button>
</div>
</div>
</el-form-item>
</el-form-item>
<el-form-item
label=
"试用期"
>
<el-form-item
label=
"试用期"
>
<el-input
v-model=
"form.internal.probationPeriod"
placeholder=
"如 3 个月"
/>
<el-select
v-model=
"form.internal.probationPeriod"
clearable
placeholder=
"请选择"
>
</el-form-item>
<el-option
<el-form-item
label=
"转正标准"
>
v-for=
"month in PROBATION_MONTH_OPTIONS"
<el-input
v-model=
"form.internal.probationCriteria"
placeholder=
"转正看什么 / 交付什么"
/>
:key=
"month"
:label=
"`$
{month}个月`"
:value="`${month}个月`"
/>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"竞业协议"
>
<el-form-item
label=
"竞业协议"
>
<el-input
v-model=
"form.internal.nonCompete"
placeholder=
"需签 / 不需要 / 竞对范围说明"
/>
<el-select
v-model=
"form.internal.nonCompete"
clearable
placeholder=
"请选择"
>
<el-option
label=
"需签"
value=
"需签"
/>
<el-option
label=
"无需签"
value=
"无需签"
/>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"入职验证方式"
>
<el-form-item
label=
"入职验证方式"
>
<el-input
v-model=
"form.internal.verification"
placeholder=
"简历看什么 / 面试怎么验 / 是否背调"
/>
<el-input
v-model=
"form.internal.verification"
placeholder=
"简历看什么 / 面试怎么验 / 是否背调"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"转正标准"
>
<el-input
v-model=
"form.internal.probationCriteria"
placeholder=
"转正看什么 / 交付什么"
/>
</el-form-item>
</el-form>
</el-form>
</div>
</div>
</el-tab-pane>
</el-tab-pane>
...
@@ -707,16 +811,6 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
...
@@ -707,16 +811,6 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
<el-option
v-for=
"option in JOB_STATUS_OPTIONS"
:key=
"option"
:label=
"option"
:value=
"option"
/>
<el-option
v-for=
"option in JOB_STATUS_OPTIONS"
:key=
"option"
:label=
"option"
:value=
"option"
/>
</el-select>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"JD 状态"
>
<el-select
v-model=
"form.jdStatus"
>
<el-option
v-for=
"option in JD_STATUS_EDITABLE_OPTIONS"
:key=
"option"
:label=
"option"
:value=
"option"
/>
</el-select>
<div
class=
"field-hint"
>
「已生效」需在岗位详情页走审批流程,此处不可直选。
</div>
</el-form-item>
<el-form-item
label=
"审批状态"
>
<el-input
:model-value=
"existing?.approvalStatus || APPROVAL_STATUS.NOT_STARTED"
readonly
/>
<div
class=
"field-hint"
>
在岗位详情页「JD 流程」中推进确认与审批。
</div>
</el-form-item>
<el-form-item
label=
"当前 JD 版本"
>
<el-form-item
label=
"当前 JD 版本"
>
<el-input
v-model=
"form.jdVersion"
readonly
/>
<el-input
v-model=
"form.jdVersion"
readonly
/>
</el-form-item>
</el-form-item>
...
@@ -748,16 +842,14 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
...
@@ -748,16 +842,14 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
<span>
{{
existing
?
'需要单独保留修改记录时,再创建新的 JD 版本。'
:
''
}}
</span>
<span>
{{
existing
?
'需要单独保留修改记录时,再创建新的 JD 版本。'
:
''
}}
</span>
</div>
</div>
<div
class=
"actions-btns"
>
<div
class=
"actions-btns"
>
<el-button
v-if=
"!existing"
type=
"primary"
plain
@
click=
"aiAssistCreate
"
>
<el-button
type=
"primary"
@
click=
"isNew ? nextStep() : submit('update')
"
>
<span
class=
"ai-spark"
>
✦
</span>
AI 辅助创建
{{
existing
?
'保存修改'
:
activeTab
===
'status'
?
'创建岗位'
:
'下一步'
}}
</el-button>
</el-button>
<el-button
type=
"primary"
@
click=
"submit('update')"
>
{{
existing
?
'保存修改'
:
'创建岗位'
}}
</el-button>
<el-button
v-if=
"existing"
@
click=
"submit('iterate')"
>
保存为新 JD 版本
</el-button>
<el-button
v-if=
"existing"
@
click=
"submit('iterate')"
>
保存为新 JD 版本
</el-button>
</div>
</div>
</div>
</div>
</section>
</section>
<JdGrillModal
/>
<JdGeneratePanel
/>
<JdGeneratePanel
/>
<JdImportModal
v-model=
"importOpen"
:initial-mode=
"importMode"
:job=
"form"
@
applied=
"applyParsed"
/>
<JdImportModal
v-model=
"importOpen"
:initial-mode=
"importMode"
:job=
"form"
@
applied=
"applyParsed"
/>
</div>
</div>
...
@@ -809,6 +901,37 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
...
@@ -809,6 +901,37 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
}
}
}
}
// JD / 对内约束等表单的左右两列布局;内容较长时在窄屏折回单列
.form.two
{
display
:
grid
;
grid-template-columns
:
repeat
(
2
,
minmax
(
0
,
1fr
));
column-gap
:
18px
;
align-items
:
start
;
:deep
(
.el-form-item
)
{
min-width
:
0
;
}
:deep
(
.el-select
),
:deep
(
.el-input-number
)
{
width
:
100%
;
}
:deep
(
.jd-span-full
)
{
grid-column
:
1
/
-1
;
}
@media
(
max-width
:
960px
)
{
grid-template-columns
:
minmax
(
0
,
1fr
);
}
}
.jd-long-text
{
:deep
(
.el-textarea__inner
)
{
line-height
:
1
.7
;
}
}
.form-note
{
.form-note
{
margin-top
:
16px
;
margin-top
:
16px
;
padding
:
12px
14px
;
padding
:
12px
14px
;
...
@@ -994,9 +1117,4 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
...
@@ -994,9 +1117,4 @@ if (isNew.value && ['paste', 'template'].includes(String(route.query.import || '
gap
:
8px
;
gap
:
8px
;
}
}
}
}
.ai-spark
{
color
:
var
(
--
violet
,
#8b5cf6
);
margin-right
:
2px
;
}
</
style
>
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment