Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-lab
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-lab
Commits
ac5e09be
提交
ac5e09be
authored
11月 27, 2024
作者:
lhh
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
11.27需求修改
上级
5cd99fb3
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
796 行增加
和
197 行删除
+796
-197
ScoreDialog.vue
src/modules/admin/contest/check/components/ScoreDialog.vue
+9
-5
SyncExamDialog.vue
...modules/admin/contest/check/components/SyncExamDialog.vue
+1
-1
Index.vue
src/modules/admin/contest/dashboard/views/Index.vue
+19
-18
Index.vue
src/modules/admin/contest/experts/views/Index.vue
+1
-0
ContestantDialog.vue
...dules/admin/contest/items/components/ContestantDialog.vue
+1
-0
FormDialog copy.vue
...odules/admin/contest/items/components/FormDialog copy.vue
+490
-0
FormDialog.vue
src/modules/admin/contest/items/components/FormDialog.vue
+185
-149
ScoringExpertsDialog.vue
...s/admin/contest/items/components/ScoringExpertsDialog.vue
+1
-0
index.ts
src/modules/admin/contest/items/index.ts
+2
-1
types.ts
src/modules/admin/contest/items/types.ts
+2
-1
Edit.vue
src/modules/admin/contest/items/views/Edit.vue
+55
-0
Index.vue
src/modules/admin/contest/items/views/Index.vue
+26
-18
View.vue
src/modules/admin/contest/items/views/View.vue
+4
-4
没有找到文件。
src/modules/admin/contest/check/components/ScoreDialog.vue
浏览文件 @
ac5e09be
...
@@ -21,7 +21,7 @@ watchEffect(() => {
...
@@ -21,7 +21,7 @@ watchEffect(() => {
...
item
,
...
item
,
old_score
:
parseFloat
(
item
.
old_score
),
old_score
:
parseFloat
(
item
.
old_score
),
ratio
:
parseFloat
(
item
.
ratio
),
ratio
:
parseFloat
(
item
.
ratio
),
score
:
isNaN
(
parseFloat
(
item
.
score
))
?
null
:
parseFloat
(
item
.
score
)
score
:
isNaN
(
parseFloat
(
item
.
score
))
?
'null'
:
parseFloat
(
item
.
score
)
}
}
})
})
})
})
...
@@ -43,7 +43,9 @@ const score = $computed(() => {
...
@@ -43,7 +43,9 @@ const score = $computed(() => {
// 提交
// 提交
function
handleSubmit
()
{
function
handleSubmit
()
{
const
scores
=
tableList
.
map
((
item
:
any
)
=>
{
const
scores
=
tableList
.
map
((
item
:
any
)
=>
{
if
(
item
.
type
===
'2'
)
{
item
.
score
=
0
}
if
(
item
.
type
===
'2'
)
{
item
.
score
=
0
}
return
{
id
:
item
.
id
,
score
:
item
.
score
}
return
{
id
:
item
.
id
,
score
:
item
.
score
}
})
})
const
params
=
{
id
:
detail
.
id
,
scores
:
JSON
.
stringify
(
scores
)
}
const
params
=
{
id
:
detail
.
id
,
scores
:
JSON
.
stringify
(
scores
)
}
...
@@ -75,7 +77,7 @@ const handleScoreRule = function () {
...
@@ -75,7 +77,7 @@ const handleScoreRule = function () {
<el-form-item
label=
"选手姓名"
>
{{
detail
.
student_name
}}
</el-form-item>
<el-form-item
label=
"选手姓名"
>
{{
detail
.
student_name
}}
</el-form-item>
<el-form-item
label=
"选手ID"
>
{{
detail
.
login_id
}}
</el-form-item>
<el-form-item
label=
"选手ID"
>
{{
detail
.
login_id
}}
</el-form-item>
<div
style=
"display: flex; justify-content: space-between"
>
<div
style=
"display: flex; justify-content: space-between"
>
<el-form-item
label=
"报告"
>
<el-form-item
label=
"报告"
v-if=
"reportList.length"
>
<el-dropdown>
<el-dropdown>
<el-button
text
>
<el-button
text
>
查看报告
<el-icon
class=
"el-icon--right"
><arrow-down
/></el-icon>
查看报告
<el-icon
class=
"el-icon--right"
><arrow-down
/></el-icon>
...
@@ -89,7 +91,7 @@ const handleScoreRule = function () {
...
@@ -89,7 +91,7 @@ const handleScoreRule = function () {
</
template
>
</
template
>
</el-dropdown>
</el-dropdown>
</el-form-item>
</el-form-item>
<el-button
type=
"primary"
@
click=
"handleScoreRule"
>
查看评分规则
</el-button>
<el-button
type=
"primary"
style=
"margin-bottom: 20px"
@
click=
"handleScoreRule"
>
查看评分规则
</el-button>
</div>
</div>
</el-form>
</el-form>
<el-table
:data=
"tableList"
:header-cell-style=
"{ background: '#ededed' }"
>
<el-table
:data=
"tableList"
:header-cell-style=
"{ background: '#ededed' }"
>
...
@@ -100,6 +102,7 @@ const handleScoreRule = function () {
...
@@ -100,6 +102,7 @@ const handleScoreRule = function () {
<el-table-column
label=
"评分"
prop=
"score"
align=
"center"
>
<el-table-column
label=
"评分"
prop=
"score"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-input-number
<el-input-number
:disabled=
"row.type === '2'"
:controls=
"false"
:controls=
"false"
v-model=
"row.score"
v-model=
"row.score"
step-strictly
step-strictly
...
@@ -107,10 +110,11 @@ const handleScoreRule = function () {
...
@@ -107,10 +110,11 @@ const handleScoreRule = function () {
:min=
"0"
:min=
"0"
:max=
"row.old_score"
:max=
"row.old_score"
style=
"width: 100%"
style=
"width: 100%"
placeholder=
"--"
/>
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
>
<el-table-column
label=
"操作"
align=
"center"
v-if=
"false"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-button
text
type=
"primary"
v-if=
"row.type === '2'"
>
<el-button
text
type=
"primary"
v-if=
"row.type === '2'"
>
<a
:href=
"`$
{qaURL}/exam/markingPaper?exam_id=${row.exam_id}
&
id_number=${detail.id_number}`" target="_blank"
<a
:href=
"`$
{qaURL}/exam/markingPaper?exam_id=${row.exam_id}
&
id_number=${detail.id_number}`" target="_blank"
...
...
src/modules/admin/contest/check/components/SyncExamDialog.vue
浏览文件 @
ac5e09be
...
@@ -29,7 +29,7 @@ function scoreMethodText(value: string) {
...
@@ -29,7 +29,7 @@ function scoreMethodText(value: string) {
</
script
>
</
script
>
<
template
>
<
template
>
<el-dialog
title=
"同步1+
X
考试成绩"
:close-on-click-modal=
"false"
>
<el-dialog
title=
"同步1+
同步线上
考试成绩"
:close-on-click-modal=
"false"
>
<el-form>
<el-form>
<el-form-item
label=
"赛项名称"
>
<el-form-item
label=
"赛项名称"
>
<el-select
v-model=
"form.competition"
value-key=
"id"
>
<el-select
v-model=
"form.competition"
value-key=
"id"
>
...
...
src/modules/admin/contest/dashboard/views/Index.vue
浏览文件 @
ac5e09be
...
@@ -29,10 +29,10 @@ onMounted(() => {
...
@@ -29,10 +29,10 @@ onMounted(() => {
fetchCompetition
()
fetchCompetition
()
})
})
const
platformKey
=
ref
(
'
career_data_analysis
'
)
const
platformKey
=
ref
(
'
data_marketing
'
)
const
platformKeys
=
ref
([
const
platformKeys
=
ref
([
{
platform_key
:
'career_data_analysis'
,
name
:
'商业数据分析实验'
},
{
platform_key
:
'career_data_analysis'
,
name
:
'商业数据分析实验'
},
{
platform_key
:
'data_marketing'
,
name
:
'数据营销实操'
}
,
{
platform_key
:
'data_marketing'
,
name
:
'数据营销实操'
}
])
])
// async function fetchPlatformKeys(competition_id: string) {
// async function fetchPlatformKeys(competition_id: string) {
// const res = await getPlatformKeys({ competition_id })
// const res = await getPlatformKeys({ competition_id })
...
@@ -62,7 +62,7 @@ onUnmounted(() => {
...
@@ -62,7 +62,7 @@ onUnmounted(() => {
const
statistics
=
reactive
({
const
statistics
=
reactive
({
competitor_count
:
0
,
competitor_count
:
0
,
complete_answer_competitor_count
:
0
,
complete_answer_competitor_count
:
0
,
starting_answer_competitor_count
:
0
,
starting_answer_competitor_count
:
0
})
})
async
function
fetchStatistics
(
competition_id
:
string
,
platform_key
=
'career_data_analysis'
)
{
async
function
fetchStatistics
(
competition_id
:
string
,
platform_key
=
'career_data_analysis'
)
{
const
res
=
await
getCompetitionStatistics
({
competition_id
,
platform_key
})
const
res
=
await
getCompetitionStatistics
({
competition_id
,
platform_key
})
...
@@ -97,8 +97,8 @@ const submittedListOptions = {
...
@@ -97,8 +97,8 @@ const submittedListOptions = {
{
label
:
'所在专业'
,
prop
:
'student.specialty_name'
},
{
label
:
'所在专业'
,
prop
:
'student.specialty_name'
},
{
label
:
'所在班级'
,
prop
:
'student.class_name'
},
{
label
:
'所在班级'
,
prop
:
'student.class_name'
},
{
label
:
'提交时间'
,
prop
:
'commit_time'
},
{
label
:
'提交时间'
,
prop
:
'commit_time'
},
{
label
:
'作答用时'
,
prop
:
'answer_time'
}
,
{
label
:
'作答用时'
,
prop
:
'answer_time'
}
]
,
]
}
}
const
submittedLis
=
computed
(()
=>
{
const
submittedLis
=
computed
(()
=>
{
return
competitorsTableData
.
value
.
filter
((
item
:
any
)
=>
item
.
commit_status
==
3
)
return
competitorsTableData
.
value
.
filter
((
item
:
any
)
=>
item
.
commit_status
==
3
)
...
@@ -114,9 +114,9 @@ const answeringListOptions = {
...
@@ -114,9 +114,9 @@ const answeringListOptions = {
{
label
:
'所在班级'
,
prop
:
'student.class_name'
},
{
label
:
'所在班级'
,
prop
:
'student.class_name'
},
{
{
label
:
'作答用时'
,
label
:
'作答用时'
,
prop
:
'answer_time'
,
prop
:
'answer_time'
}
,
}
]
,
]
}
}
const
answeringList
=
computed
(()
=>
{
const
answeringList
=
computed
(()
=>
{
return
competitorsTableData
.
value
.
filter
((
item
:
any
)
=>
item
.
commit_status
==
2
||
item
.
commit_status
==
4
)
return
competitorsTableData
.
value
.
filter
((
item
:
any
)
=>
item
.
commit_status
==
2
||
item
.
commit_status
==
4
)
...
@@ -137,44 +137,44 @@ const listOptions = {
...
@@ -137,44 +137,44 @@ const listOptions = {
prop
:
'module_1'
,
prop
:
'module_1'
,
computed
({
row
}:
{
row
:
any
})
{
computed
({
row
}:
{
row
:
any
})
{
return
getModuleStatus
(
row
,
0
)
return
getModuleStatus
(
row
,
0
)
}
,
}
},
},
{
{
label
:
'模块二'
,
label
:
'模块二'
,
prop
:
'module_2'
,
prop
:
'module_2'
,
computed
({
row
}:
{
row
:
any
})
{
computed
({
row
}:
{
row
:
any
})
{
return
getModuleStatus
(
row
,
1
)
return
getModuleStatus
(
row
,
1
)
}
,
}
},
},
{
{
label
:
'模块三'
,
label
:
'模块三'
,
prop
:
'module_3'
,
prop
:
'module_3'
,
computed
({
row
}:
{
row
:
any
})
{
computed
({
row
}:
{
row
:
any
})
{
return
getModuleStatus
(
row
,
2
)
return
getModuleStatus
(
row
,
2
)
}
,
}
},
},
{
{
label
:
'模块四'
,
label
:
'模块四'
,
prop
:
'module_4'
,
prop
:
'module_4'
,
computed
({
row
}:
{
row
:
any
})
{
computed
({
row
}:
{
row
:
any
})
{
return
getModuleStatus
(
row
,
3
)
return
getModuleStatus
(
row
,
3
)
}
,
}
},
},
{
{
label
:
'模块五'
,
label
:
'模块五'
,
prop
:
'module_5'
,
prop
:
'module_5'
,
computed
({
row
}:
{
row
:
any
})
{
computed
({
row
}:
{
row
:
any
})
{
return
getModuleStatus
(
row
,
4
)
return
getModuleStatus
(
row
,
4
)
}
,
}
},
},
{
{
label
:
'模块六'
,
label
:
'模块六'
,
prop
:
'module_6'
,
prop
:
'module_6'
,
computed
({
row
}:
{
row
:
any
})
{
computed
({
row
}:
{
row
:
any
})
{
return
getModuleStatus
(
row
,
5
)
return
getModuleStatus
(
row
,
5
)
}
,
}
}
,
}
]
,
]
}
}
function
getModuleStatus
(
row
:
any
,
index
:
number
)
{
function
getModuleStatus
(
row
:
any
,
index
:
number
)
{
try
{
try
{
...
@@ -201,12 +201,13 @@ function getModuleStatus(row: any, index: number) {
...
@@ -201,12 +201,13 @@ function getModuleStatus(row: any, index: number) {
<el-select
v-model=
"currentCompetition"
value-key=
"id"
size=
"large"
style=
"margin-right: 20px"
>
<el-select
v-model=
"currentCompetition"
value-key=
"id"
size=
"large"
style=
"margin-right: 20px"
>
<el-option
v-for=
"item in competitionList"
:key=
"item.id"
:value=
"item"
:label=
"item.name"
></el-option>
<el-option
v-for=
"item in competitionList"
:key=
"item.id"
:value=
"item"
:label=
"item.name"
></el-option>
</el-select>
</el-select>
<el-select
v-model=
"platformKey"
size=
"large"
>
<el-select
v-model=
"platformKey"
size=
"large"
v-if=
"false"
>
<el-option
<el-option
v-for=
"item in platformKeys"
v-for=
"item in platformKeys"
:key=
"item.platform_key"
:key=
"item.platform_key"
:value=
"item.platform_key"
:value=
"item.platform_key"
:label=
"item.name"
></el-option>
:label=
"item.name"
></el-option>
</el-select>
</el-select>
</el-row>
</el-row>
<ul
class=
"statistics"
>
<ul
class=
"statistics"
>
...
...
src/modules/admin/contest/experts/views/Index.vue
浏览文件 @
ac5e09be
...
@@ -37,6 +37,7 @@ const listOptions = $computed(() => {
...
@@ -37,6 +37,7 @@ const listOptions = $computed(() => {
columns
:
[
columns
:
[
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'专家姓名'
,
prop
:
'name'
},
{
label
:
'专家姓名'
,
prop
:
'name'
},
{
label
:
'电话'
,
prop
:
'mobile'
},
{
label
:
'所在单位'
,
prop
:
'company'
},
{
label
:
'所在单位'
,
prop
:
'company'
},
{
{
label
:
'性别'
,
label
:
'性别'
,
...
...
src/modules/admin/contest/items/components/ContestantDialog.vue
浏览文件 @
ac5e09be
...
@@ -20,6 +20,7 @@ const listOptions = {
...
@@ -20,6 +20,7 @@ const listOptions = {
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'选手姓名'
,
prop
:
'student.name'
},
{
label
:
'选手姓名'
,
prop
:
'student.name'
},
{
label
:
'参赛ID'
,
prop
:
'login_id'
},
{
label
:
'参赛ID'
,
prop
:
'login_id'
},
{
label
:
'电话'
,
prop
:
'mobile'
},
{
{
label
:
'性别'
,
label
:
'性别'
,
prop
:
'student.gender'
,
prop
:
'student.gender'
,
...
...
src/modules/admin/contest/items/components/FormDialog copy.vue
0 → 100644
浏览文件 @
ac5e09be
<
script
setup
lang=
"ts"
>
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
ContestItem
,
ContestCreateParams
,
ContestUpdateParams
}
from
'../types'
import
{
ElMessage
}
from
'element-plus'
import
{
pick
}
from
'lodash-es'
import
dayjs
from
'dayjs'
import
isBetween
from
'dayjs/plugin/isBetween'
import
{
createContest
,
updateContest
,
getExamList
}
from
'../api'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useGetTeacherList
}
from
'../composables/useGetTeacherList'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
const
appConfig
=
useAppConfig
()
interface
Props
{
data
?:
ContestItem
|
null
}
const
props
=
defineProps
<
Props
>
()
const
emit
=
defineEmits
<
{
(
e
:
'update'
):
void
(
e
:
'update:modelValue'
,
visible
:
boolean
):
void
}
>
()
dayjs
.
extend
(
isBetween
)
// 赛项类型
const
types
=
useMapStore
().
getMapValuesByKey
(
'competition_type'
)
// 主办单位
const
hostUnitList
=
useMapStore
().
getMapValuesByKey
(
'host_unit'
)
// 承办单位
const
organizerList
=
useMapStore
().
getMapValuesByKey
(
'organizer'
)
// 技术支持单位
const
technicalSupportUnitList
=
useMapStore
().
getMapValuesByKey
(
'technical_support_unit'
)
// 数据状态
const
status
=
useMapStore
().
getMapValuesByKey
(
'system_status'
)
// 指导老师
const
{
teachers
}
=
useGetTeacherList
()
const
formRef
=
$ref
<
FormInstance
>
()
const
form
=
reactive
({
id
:
''
,
name
:
''
,
client_id
:
''
,
host_unit_id
:
''
,
organizer_ids
:
[],
technical_support_unit_id
:
''
,
type
:
'1'
,
teacher_ids
:
[],
apply_expiration_date
:
''
,
status
:
'1'
,
logo
:
''
,
cover
:
''
,
train_platform_uri
:
''
,
competition_uri
:
''
,
dateRange
:
undefined
,
date
:
undefined
,
datetimeRange
:
undefined
,
datetimeRange2
:
undefined
,
is_switchable_theory_practice
:
0
,
train_platform_configs
:
[
{
name
:
appConfig
.
xTrainLabel
||
'1+X理论考试'
,
is_show
:
'1'
,
type
:
'1'
,
url
:
''
,
platform_key
:
'x_exam'
},
{
name
:
appConfig
.
labTrainLabel
||
'商业数据分析实验'
,
is_show
:
'0'
,
type
:
'2'
,
url
:
''
,
platform_key
:
'career_data_analysis'
},
{
name
:
'数据营销实操'
,
is_show
:
'0'
,
type
:
'2'
,
url
:
''
,
platform_key
:
'data_marketing'
}
],
competition_platform_configs
:
[
{
name
:
appConfig
.
xExamLabel
||
'1+X理论考试'
,
is_show
:
'1'
,
type
:
'1'
,
url
:
''
,
exam_id
:
''
,
platform_key
:
'x_exam'
},
// {
// name: appConfig.labExamLabel || '商业数据分析实验',
// is_show: '0',
// type: '2',
// url: '',
// platform_key: 'career_data_analysis'
// },
{
name
:
'数据营销实操'
,
is_show
:
'0'
,
type
:
'2'
,
url
:
''
,
platform_key
:
'data_marketing'
}
]
})
watchEffect
(()
=>
{
if
(
!
props
.
data
)
return
const
host_unit_id
=
props
.
data
.
host_unit
.
id
const
organizer_ids
=
props
.
data
.
organizers
.
map
(
item
=>
item
.
id
)
const
technical_support_unit_id
=
props
.
data
.
technical_support_unit
.
id
const
teacher_ids
=
props
.
data
.
teachers
.
map
(
item
=>
item
.
id
)
const
dateRange
=
[
new
Date
(
props
.
data
.
start_range
*
1000
),
new
Date
(
props
.
data
.
end_range
*
1000
)]
const
date
=
new
Date
(
props
.
data
.
start_at
*
1000
)
const
datetimeRange
=
[
new
Date
(
props
.
data
.
start_at
*
1000
),
new
Date
(
props
.
data
.
end_at
*
1000
)]
const
datetimeRange2
=
[
new
Date
(
props
.
data
.
operational_start_time
*
1000
),
new
Date
(
props
.
data
.
operational_end_time
*
1000
)
]
const
is_switchable_theory_practice
=
parseInt
(
props
.
data
.
is_switchable_theory_practice
)
const
apply_expiration_date
=
props
.
data
.
apply_expiration_date
*
1000
Object
.
assign
(
form
,
props
.
data
,
{
host_unit_id
,
organizer_ids
,
technical_support_unit_id
,
teacher_ids
,
dateRange
,
date
,
datetimeRange
,
datetimeRange2
,
apply_expiration_date
,
is_switchable_theory_practice
})
})
const
checkApplyExpirationDate
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
if
(
!
value
)
{
callback
(
new
Error
(
'请选择报名截止日期'
))
}
else
{
const
[
firstDate
,
secondDate
]
=
form
.
dateRange
||
[]
if
(
!
dayjs
(
value
).
isBetween
(
firstDate
,
secondDate
,
'date'
,
'[]'
)
||
!
dayjs
(
value
).
isBefore
(
dayjs
(
form
.
date
),
'date'
)
)
{
callback
(
new
Error
(
'请选择赛项周期内的日期,且必须早于正式比赛日期'
))
}
callback
()
}
}
const
checkTrainPlatformConfigs
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
const
findItem
=
function
(
a
:
any
,
b
:
any
)
{
return
form
.
train_platform_configs
.
find
((
item
:
any
)
=>
item
[
a
]
===
b
)
}
// 判断最少选择一项目
if
(
!
findItem
(
'is_show'
,
'1'
))
{
callback
(
new
Error
(
'最少选择一项'
))
}
else
{
form
.
train_platform_configs
.
forEach
((
item
:
any
)
=>
{
if
(
item
.
is_show
===
'1'
)
{
if
(
item
.
type
===
'1'
)
{
if
(
item
.
exam_id
===
''
)
{
callback
(
new
Error
(
`请选择
${
item
.
name
}
`
))
}
else
{
callback
()
}
}
else
{
if
(
item
.
url
===
''
)
{
callback
(
new
Error
(
`请填写
${
item
.
name
}
的链接`
))
}
else
{
callback
()
}
}
}
})
}
}
const
checkCompetitionPlatformConfigs
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
const
findItem
=
function
(
a
:
any
,
b
:
any
)
{
return
form
.
competition_platform_configs
.
find
((
item
:
any
)
=>
item
[
a
]
===
b
)
}
// 判断最少选择一项目
if
(
!
findItem
(
'is_show'
,
'1'
))
{
callback
(
new
Error
(
'最少选择一项'
))
}
else
{
form
.
competition_platform_configs
.
forEach
((
item
:
any
)
=>
{
if
(
item
.
is_show
===
'1'
)
{
if
(
item
.
type
===
'1'
)
{
if
(
item
.
exam_id
===
''
)
{
callback
(
new
Error
(
`请选择
${
item
.
name
}
`
))
}
else
{
callback
()
}
}
else
{
if
(
item
.
url
===
''
)
{
callback
(
new
Error
(
`请填写
${
item
.
name
}
的链接`
))
}
else
{
callback
()
}
}
}
})
}
}
const
rules
=
ref
<
FormRules
>
({
name
:
[{
required
:
true
,
message
:
'请输入赛项名称'
}],
host_unit_id
:
[{
required
:
true
,
message
:
'请选择主办单位'
}],
organizer_ids
:
[{
type
:
'array'
,
required
:
true
,
message
:
'请选择承办单位'
}],
technical_support_unit_id
:
[{
required
:
true
,
message
:
'请选择技术支持单位'
}],
type
:
[{
required
:
true
,
message
:
'请选择赛项类型'
}],
teacher_ids
:
[{
type
:
'array'
,
required
:
true
,
message
:
'请选择指导教师'
,
trigger
:
'change'
}],
dateRange
:
[{
type
:
'array'
,
required
:
true
,
message
:
'请选择赛项周期'
,
trigger
:
'change'
}],
date
:
[{
required
:
true
,
message
:
'请选择正式比赛日期'
,
trigger
:
'change'
}],
datetimeRange
:
[{
type
:
'array'
,
required
:
true
,
message
:
'正式比赛理论答题时间'
,
trigger
:
'change'
}],
datetimeRange2
:
[{
type
:
'array'
,
required
:
true
,
message
:
'正式比赛实操答题时间'
,
trigger
:
'change'
}],
apply_expiration_date
:
[
{
required
:
true
,
message
:
'请选择报名截止日期'
},
{
validator
:
checkApplyExpirationDate
,
message
:
'请选择赛项周期内的日期,且必须早于正式比赛日期'
}
],
// train_platform_uri: [{ required: true, message: '请输入训练平台地址' }],
// competition_uri: [{ required: true, message: '请输入正式比赛地址' }],
status
:
[{
required
:
true
,
message
:
'请选择有效状态'
}],
is_switchable_theory_practice
:
[{
required
:
true
,
message
:
'请选择'
}],
logo
:
[{
required
:
true
,
message
:
'请上传赛项LOGO'
}],
cover
:
[{
required
:
true
,
message
:
'请上传赛项封面'
}],
train_platform_configs
:
[{
required
:
true
,
message
:
''
},
{
validator
:
checkTrainPlatformConfigs
}],
competition_platform_configs
:
[{
required
:
true
,
message
:
''
},
{
validator
:
checkCompetitionPlatformConfigs
}]
})
const
isUpdate
=
$computed
(()
=>
{
return
!!
form
.
id
})
const
title
=
$computed
(()
=>
{
return
isUpdate
?
'编辑赛项'
:
'新增赛项'
})
// 是否禁用赛项周期
// const disabledRange = $computed(() => {
// const [firstDate, secondDate] = form.dateRange || []
// return isUpdate && dayjs().isBetween(firstDate, secondDate, 'date', '[]')
// })
// 提交
function
handleSubmit
()
{
function
containsNumber
(
A
:
number
,
B
:
number
):
boolean
{
// 将数字A和B转换成字符串,并检查A的字符串是否包含B的字符串
return
A
.
toString
().
includes
(
B
.
toString
())
}
formRef
?.
validate
().
then
(()
=>
{
const
[
firstDate
,
secondDate
]
=
form
.
dateRange
||
[]
const
[
firstDatetime
,
secondDatetime
]
=
form
.
datetimeRange
||
[]
const
[
firstDatetime2
,
secondDatetime2
]
=
form
.
datetimeRange2
||
[]
const
year
=
dayjs
(
form
.
date
).
year
()
const
month
=
dayjs
(
form
.
date
).
month
()
const
date
=
dayjs
(
form
.
date
).
date
()
const
mergedForm
=
{
...
form
,
organizer_ids
:
JSON
.
stringify
(
form
.
organizer_ids
),
// teacher_ids: form.teacher_ids.join(','),
start_range
:
dayjs
(
firstDate
).
unix
(),
end_range
:
dayjs
(
secondDate
).
endOf
(
'date'
).
unix
(),
start_at
:
dayjs
(
firstDatetime
).
year
(
year
).
month
(
month
).
date
(
date
).
unix
(),
end_at
:
dayjs
(
secondDatetime
).
year
(
year
).
month
(
month
).
date
(
date
).
unix
(),
operational_start_time
:
dayjs
(
firstDatetime2
).
year
(
year
).
month
(
month
).
date
(
date
).
unix
(),
operational_end_time
:
dayjs
(
secondDatetime2
).
year
(
year
).
month
(
month
).
date
(
date
).
unix
(),
apply_expiration_date
:
dayjs
(
form
.
apply_expiration_date
).
endOf
(
'date'
).
unix
()
}
// 判断正式比赛理论答题时间和选择的考试
const
findExam
=
examList
.
find
(
item
=>
item
.
exam_id
===
form
.
competition_platform_configs
[
0
].
exam_id
)
const
examStartTime
=
new
Date
(
findExam
?.
start_time
||
''
).
getTime
()
const
examEndTime
=
new
Date
(
findExam
?.
end_time
||
''
).
getTime
()
// console.log(containsNumber(examStartTime, mergedForm.start_at), containsNumber(examEndTime, mergedForm.end_at))
const
findXItem
=
form
.
competition_platform_configs
.
find
(
item
=>
item
.
type
===
'1'
)
console
.
log
(
findXItem
,
'findXItem'
,
form
.
competition_platform_configs
)
if
(
findXItem
?.
is_show
===
'1'
)
{
if
(
containsNumber
(
examStartTime
,
mergedForm
.
start_at
)
!==
true
||
containsNumber
(
examEndTime
,
mergedForm
.
end_at
)
!==
true
)
{
ElMessage
({
message
:
`正式比赛理论答题时间与
${
findExam
?.
name
}
的考试时间不符
`, type: 'warning' })
return false
}
}
const params: ContestUpdateParams = pick(mergedForm, [
'operational_start_time',
'operational_end_time',
'id',
'name',
'client_id',
'host_unit_id',
'organizer_ids',
'technical_support_unit_id',
'type',
'start_range',
'end_range',
'start_at',
'end_at',
'apply_expiration_date',
'status',
'logo',
'cover',
// 'train_platform_uri',
// 'competition_uri',
'teacher_ids',
'train_platform_configs',
'competition_platform_configs',
'is_switchable_theory_practice'
])
console.log(isUpdate, 'isUpdate')
isUpdate ? handleUpdate(params) : handleCreate(params)
})
}
// 新增
function handleCreate(params: ContestCreateParams) {
// console.log(params, 'aaa')
createContest(params).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 修改
function handleUpdate(params: ContestUpdateParams) {
updateContest(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
// 赛项周期改变
function handleDateRangeChange(value: any) {
if (value) {
const [, secondDate] = form.dateRange || []
form.date = secondDate
}
}
const clientList = [
{ label: '商务数据分析师赛项', value: 'business_data_analyst' },
{ label: '全媒体运营师赛项', value: 'all_media_operator' },
{ label: '网络主播赛项', value: 'network_anchor_competition' }
]
let examList = $ref<Record<string, any>[]>([])
// 获取关联考试列表
function fetchExamList() {
getExamList({ project: 'x1', 'per-page': 1000 }).then(res => {
examList = res.data.list || []
})
}
onMounted(() => {
fetchExamList()
})
</
script
>
<
template
>
<el-dialog
:title=
"title"
:close-on-click-modal=
"false"
align-center
width=
"600px"
@
update:modelValue=
"value => $emit('update:modelValue', value)"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
label-width=
"165px"
>
<el-form-item
label=
"客户端标识"
prop=
"client_id"
>
<el-select
v-model=
"form.client_id"
style=
"width: 100%"
clearable
>
<el-option
v-for=
"item in clientList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"赛项名称"
prop=
"name"
>
<el-input
v-model=
"form.name"
:disabled=
"isUpdate"
/>
</el-form-item>
<el-form-item
label=
"主办单位"
prop=
"host_unit_id"
>
<el-select
v-model=
"form.host_unit_id"
style=
"width: 100%"
>
<el-option
v-for=
"item in hostUnitList"
:key=
"item.id"
:label=
"item.label"
:value=
"item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"承办单位"
prop=
"organizer_ids"
>
<el-select
v-model=
"form.organizer_ids"
multiple
style=
"width: 100%"
>
<el-option
v-for=
"item in organizerList"
:key=
"item.id"
:label=
"item.label"
:value=
"item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"技术支持单位"
prop=
"technical_support_unit_id"
>
<el-select
v-model=
"form.technical_support_unit_id"
style=
"width: 100%"
>
<el-option
v-for=
"item in technicalSupportUnitList"
:key=
"item.id"
:label=
"item.label"
:value=
"item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"赛项类型"
prop=
"type"
>
<el-radio-group
v-model=
"form.type"
>
<el-radio
v-for=
"item in types"
:key=
"item.id"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"指导教师"
prop=
"teacher_ids"
>
<el-select
v-model=
"form.teacher_ids"
multiple
style=
"width: 100%"
>
<el-option
v-for=
"item in teachers"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"赛项周期"
prop=
"dateRange"
>
<el-date-picker
type=
"daterange"
range-separator=
"至"
v-model=
"form.dateRange"
style=
"width: 100%"
@
change=
"handleDateRangeChange"
/>
</el-form-item>
<el-form-item
label=
"正式比赛日期"
prop=
"date"
>
<el-date-picker
type=
"date"
v-model=
"form.date"
style=
"width: 100%"
/>
</el-form-item>
<el-form-item
label=
"正式比赛理论答题时间"
prop=
"datetimeRange"
>
<el-time-picker
is-range
range-separator=
"至"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
v-model=
"form.datetimeRange"
style=
"width: 100%"
/>
</el-form-item>
<el-form-item
label=
"正式比赛实操答题时间"
prop=
"datetimeRange2"
>
<el-time-picker
is-range
range-separator=
"至"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
v-model=
"form.datetimeRange2"
style=
"width: 100%"
/>
</el-form-item>
<el-form-item
label=
"报名截止日期"
prop=
"apply_expiration_date"
>
<el-date-picker
type=
"date"
v-model=
"form.apply_expiration_date"
style=
"width: 100%"
/>
</el-form-item>
<el-form-item
label=
"训练平台地址"
prop=
"train_platform_configs"
>
<el-checkbox
true-label=
"1"
false-label=
"0"
style=
"margin-bottom: 10px"
v-model=
"item.is_show"
v-for=
"item in form.train_platform_configs"
:key=
"item.platform_key"
>
<div
style=
"display: flex; align-items: center"
>
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
<el-input
v-model=
"item.url"
style=
"width: 200px"
/>
</div>
</el-checkbox>
</el-form-item>
<el-form-item
label=
"正式比赛地址"
prop=
"competition_platform_configs"
>
<el-checkbox
true-label=
"1"
false-label=
"0"
style=
"margin-bottom: 10px"
v-model=
"item.is_show"
v-for=
"item in form.competition_platform_configs"
:key=
"item.platform_key"
>
<div
style=
"display: flex; align-items: center"
>
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
<el-input
v-model=
"item.url"
v-if=
"item.type === '2'"
style=
"width: 200px"
/>
<el-select
v-model=
"item.exam_id"
filterable
style=
"width: 200px"
v-if=
"item.type === '1'"
>
<el-option
v-for=
"item in examList"
:key=
"item.exam_id"
:label=
"item.name"
:value=
"item.exam_id"
></el-option>
</el-select>
</div>
</el-checkbox>
</el-form-item>
<el-form-item
label=
"是否允许客户端切换"
prop=
"is_switchable_theory_practice"
>
<el-radio-group
v-model=
"form.is_switchable_theory_practice"
>
<el-radio
:label=
"0"
>
否
</el-radio>
<el-radio
:label=
"1"
>
是
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"有效状态"
prop=
"status"
>
<el-radio-group
v-model=
"form.status"
>
<el-radio
v-for=
"item in status"
:key=
"item.id"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"赛项LOGO"
prop=
"logo"
>
<AppUpload
v-model=
"form.logo"
accept=
"image/*"
></AppUpload>
</el-form-item>
<el-form-item
label=
"赛项封面"
prop=
"cover"
>
<AppUpload
v-model=
"form.cover"
accept=
"image/*"
></AppUpload>
</el-form-item>
<el-row
justify=
"center"
>
<el-button
type=
"primary"
round
auto-insert-space
@
click=
"handleSubmit"
>
保存
</el-button>
<el-button
round
auto-insert-space
@
click=
"$emit('update:modelValue', false)"
>
取消
</el-button>
</el-row>
</el-form>
</el-dialog>
</
template
>
src/modules/admin/contest/items/components/FormDialog.vue
浏览文件 @
ac5e09be
...
@@ -60,6 +60,7 @@ const form = reactive({
...
@@ -60,6 +60,7 @@ const form = reactive({
datetimeRange
:
undefined
,
datetimeRange
:
undefined
,
datetimeRange2
:
undefined
,
datetimeRange2
:
undefined
,
is_switchable_theory_practice
:
0
,
is_switchable_theory_practice
:
0
,
is_customer_anti_cheat
:
0
,
train_platform_configs
:
[
train_platform_configs
:
[
{
name
:
appConfig
.
xTrainLabel
||
'1+X理论考试'
,
is_show
:
'1'
,
type
:
'1'
,
url
:
''
,
platform_key
:
'x_exam'
},
{
name
:
appConfig
.
xTrainLabel
||
'1+X理论考试'
,
is_show
:
'1'
,
type
:
'1'
,
url
:
''
,
platform_key
:
'x_exam'
},
{
{
...
@@ -104,6 +105,9 @@ watchEffect(() => {
...
@@ -104,6 +105,9 @@ watchEffect(() => {
new
Date
(
props
.
data
.
operational_end_time
*
1000
)
new
Date
(
props
.
data
.
operational_end_time
*
1000
)
]
]
const
is_switchable_theory_practice
=
parseInt
(
props
.
data
.
is_switchable_theory_practice
)
const
is_switchable_theory_practice
=
parseInt
(
props
.
data
.
is_switchable_theory_practice
)
const
is_customer_anti_cheat
=
parseInt
(
props
.
data
?.
is_customer_anti_cheat
)
||
0
const
type
=
props
.
data
?.
type
+
''
const
status
=
props
.
data
?.
status
+
''
const
apply_expiration_date
=
props
.
data
.
apply_expiration_date
*
1000
const
apply_expiration_date
=
props
.
data
.
apply_expiration_date
*
1000
Object
.
assign
(
form
,
props
.
data
,
{
Object
.
assign
(
form
,
props
.
data
,
{
host_unit_id
,
host_unit_id
,
...
@@ -115,7 +119,10 @@ watchEffect(() => {
...
@@ -115,7 +119,10 @@ watchEffect(() => {
datetimeRange
,
datetimeRange
,
datetimeRange2
,
datetimeRange2
,
apply_expiration_date
,
apply_expiration_date
,
is_switchable_theory_practice
is_switchable_theory_practice
,
is_customer_anti_cheat
,
type
,
status
})
})
})
})
const
checkApplyExpirationDate
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
const
checkApplyExpirationDate
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
...
@@ -210,6 +217,7 @@ const rules = ref<FormRules>({
...
@@ -210,6 +217,7 @@ const rules = ref<FormRules>({
// competition_uri: [{ required: true, message: '请输入正式比赛地址' }],
// competition_uri: [{ required: true, message: '请输入正式比赛地址' }],
status
:
[{
required
:
true
,
message
:
'请选择有效状态'
}],
status
:
[{
required
:
true
,
message
:
'请选择有效状态'
}],
is_switchable_theory_practice
:
[{
required
:
true
,
message
:
'请选择'
}],
is_switchable_theory_practice
:
[{
required
:
true
,
message
:
'请选择'
}],
is_customer_anti_cheat
:
[{
required
:
true
,
message
:
'请选择'
}],
logo
:
[{
required
:
true
,
message
:
'请上传赛项LOGO'
}],
logo
:
[{
required
:
true
,
message
:
'请上传赛项LOGO'
}],
cover
:
[{
required
:
true
,
message
:
'请上传赛项封面'
}],
cover
:
[{
required
:
true
,
message
:
'请上传赛项封面'
}],
train_platform_configs
:
[{
required
:
true
,
message
:
''
},
{
validator
:
checkTrainPlatformConfigs
}],
train_platform_configs
:
[{
required
:
true
,
message
:
''
},
{
validator
:
checkTrainPlatformConfigs
}],
...
@@ -218,9 +226,6 @@ const rules = ref<FormRules>({
...
@@ -218,9 +226,6 @@ const rules = ref<FormRules>({
const
isUpdate
=
$computed
(()
=>
{
const
isUpdate
=
$computed
(()
=>
{
return
!!
form
.
id
return
!!
form
.
id
})
})
const
title
=
$computed
(()
=>
{
return
isUpdate
?
'编辑赛项'
:
'新增赛项'
})
// 是否禁用赛项周期
// 是否禁用赛项周期
// const disabledRange = $computed(() => {
// const disabledRange = $computed(() => {
// const [firstDate, secondDate] = form.dateRange || []
// const [firstDate, secondDate] = form.dateRange || []
...
@@ -292,7 +297,8 @@ function handleSubmit() {
...
@@ -292,7 +297,8 @@ function handleSubmit() {
'teacher_ids',
'teacher_ids',
'train_platform_configs',
'train_platform_configs',
'competition_platform_configs',
'competition_platform_configs',
'is_switchable_theory_practice'
'is_switchable_theory_practice',
'is_customer_anti_cheat'
])
])
console.log(isUpdate, 'isUpdate')
console.log(isUpdate, 'isUpdate')
isUpdate ? handleUpdate(params) : handleCreate(params)
isUpdate ? handleUpdate(params) : handleCreate(params)
...
@@ -343,148 +349,178 @@ onMounted(() => {
...
@@ -343,148 +349,178 @@ onMounted(() => {
</
script
>
</
script
>
<
template
>
<
template
>
<el-dialog
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
label-width=
"165px"
>
:title=
"title"
<div
style=
"display: flex"
>
:close-on-click-modal=
"false"
<div
style=
"flex: 1; margin-right: 10px"
>
align-center
<el-form-item
label=
"赛项名称"
prop=
"name"
>
width=
"600px"
<el-input
v-model=
"form.name"
/>
@
update:modelValue=
"value => $emit('update:modelValue', value)"
</el-form-item>
>
<el-form-item
label=
"承办单位"
prop=
"organizer_ids"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
label-width=
"165px"
>
<el-select
v-model=
"form.organizer_ids"
multiple
style=
"width: 100%"
>
<el-form-item
label=
"客户端标识"
prop=
"client_id"
>
<el-option
v-for=
"item in organizerList"
:key=
"item.id"
:label=
"item.label"
:value=
"item.id"
></el-option>
<el-select
v-model=
"form.client_id"
style=
"width: 100%"
clearable
>
</el-select>
<el-option
v-for=
"item in clientList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
></el-option>
</el-form-item>
</el-select>
<el-form-item
label=
"赛项类型"
prop=
"type"
>
</el-form-item>
<el-radio-group
v-model=
"form.type"
>
<el-form-item
label=
"赛项名称"
prop=
"name"
>
<el-radio
v-for=
"item in types"
:key=
"item.id"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
<el-input
v-model=
"form.name"
:disabled=
"isUpdate"
/>
</el-radio-group>
</el-form-item>
</el-form-item>
<el-form-item
label=
"主办单位"
prop=
"host_unit_id"
>
<el-form-item
label=
"赛项周期"
prop=
"dateRange"
>
<el-select
v-model=
"form.host_unit_id"
style=
"width: 100%"
>
<el-date-picker
<el-option
v-for=
"item in hostUnitList"
:key=
"item.id"
:label=
"item.label"
:value=
"item.id"
></el-option>
type=
"daterange"
</el-select>
range-separator=
"至"
</el-form-item>
v-model=
"form.dateRange"
<el-form-item
label=
"承办单位"
prop=
"organizer_ids"
>
style=
"width: 100%"
<el-select
v-model=
"form.organizer_ids"
multiple
style=
"width: 100%"
>
@
change=
"handleDateRangeChange"
<el-option
v-for=
"item in organizerList"
:key=
"item.id"
:label=
"item.label"
:value=
"item.id"
></el-option>
/>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item
label=
"正式比赛日期"
prop=
"date"
>
<el-form-item
label=
"技术支持单位"
prop=
"technical_support_unit_id"
>
<el-date-picker
type=
"date"
v-model=
"form.date"
style=
"width: 100%"
/>
<el-select
v-model=
"form.technical_support_unit_id"
style=
"width: 100%"
>
</el-form-item>
<el-option
<el-form-item
label=
"正式比赛理论答题时间"
prop=
"datetimeRange"
>
v-for=
"item in technicalSupportUnitList"
<el-time-picker
:key=
"item.id"
is-range
:label=
"item.label"
range-separator=
"至"
:value=
"item.id"
start-placeholder=
"开始时间"
></el-option>
end-placeholder=
"结束时间"
</el-select>
v-model=
"form.datetimeRange"
</el-form-item>
style=
"width: 100%"
<el-form-item
label=
"赛项类型"
prop=
"type"
>
/>
<el-radio-group
v-model=
"form.type"
>
</el-form-item>
<el-radio
v-for=
"item in types"
:key=
"item.id"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
<el-form-item
label=
"训练平台地址"
prop=
"train_platform_configs"
>
</el-radio-group>
<el-checkbox
</el-form-item>
true-label=
"1"
<el-form-item
label=
"指导教师"
prop=
"teacher_ids"
>
false-label=
"0"
<el-select
v-model=
"form.teacher_ids"
multiple
style=
"width: 100%"
>
style=
"margin-bottom: 10px"
<el-option
v-for=
"item in teachers"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
v-model=
"item.is_show"
</el-select>
v-for=
"item in form.train_platform_configs"
</el-form-item>
:key=
"item.platform_key"
<el-form-item
label=
"赛项周期"
prop=
"dateRange"
>
>
<el-date-picker
<div
style=
"display: flex; align-items: center"
>
type=
"daterange"
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
range-separator=
"至"
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
v-model=
"form.dateRange"
<el-input
v-model=
"item.url"
style=
"width: 200px"
/>
style=
"width: 100%"
</div>
@
change=
"handleDateRangeChange"
</el-checkbox>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"指导教师"
prop=
"teacher_ids"
>
<el-form-item
label=
"正式比赛日期"
prop=
"date"
>
<el-select
v-model=
"form.teacher_ids"
multiple
style=
"width: 100%"
>
<el-date-picker
type=
"date"
v-model=
"form.date"
style=
"width: 100%"
/>
<el-option
v-for=
"item in teachers"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-form-item>
</el-select>
<el-form-item
label=
"正式比赛理论答题时间"
prop=
"datetimeRange"
>
</el-form-item>
<el-time-picker
<el-form-item
label=
"实操赛题标签名称"
prop=
"name"
>
is-range
<el-input
v-model=
"form.name"
/>
range-separator=
"至"
</el-form-item>
start-placeholder=
"开始时间"
<el-form-item
label=
"实操环境标签名称"
prop=
"name"
>
end-placeholder=
"结束时间"
<el-input
v-model=
"form.name"
/>
v-model=
"form.datetimeRange"
</el-form-item>
style=
"width: 100%"
<el-form-item
label=
"实操报告标签名称"
prop=
"name"
>
/>
<el-input
v-model=
"form.name"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"正式比赛实操答题时间"
prop=
"datetimeRange2"
>
<el-form-item
label=
"实操答题标签名称"
prop=
"name"
>
<el-time-picker
<el-input
v-model=
"form.name"
/>
is-range
</el-form-item>
range-separator=
"至"
<el-form-item
label=
"有效状态"
prop=
"status"
>
start-placeholder=
"开始时间"
<el-radio-group
v-model=
"form.status"
>
end-placeholder=
"结束时间"
<el-radio
v-for=
"item in status"
:key=
"item.id"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
v-model=
"form.datetimeRange2"
</el-radio-group>
style=
"width: 100%"
</el-form-item>
/>
</div>
</el-form-item>
<el-form-item
label=
"报名截止日期"
prop=
"apply_expiration_date"
>
<div
style=
"flex: 1; margin-left: 10px"
>
<el-date-picker
type=
"date"
v-model=
"form.apply_expiration_date"
style=
"width: 100%"
/>
<el-form-item
label=
"主办单位"
prop=
"host_unit_id"
>
</el-form-item>
<el-select
v-model=
"form.host_unit_id"
style=
"width: 100%"
>
<el-form-item
label=
"训练平台地址"
prop=
"train_platform_configs"
>
<el-option
v-for=
"item in hostUnitList"
:key=
"item.id"
:label=
"item.label"
:value=
"item.id"
></el-option>
<el-checkbox
</el-select>
true-label=
"1"
</el-form-item>
false-label=
"0"
<el-form-item
label=
"技术支持单位"
prop=
"technical_support_unit_id"
>
style=
"margin-bottom: 10px"
<el-select
v-model=
"form.technical_support_unit_id"
style=
"width: 100%"
>
v-model=
"item.is_show"
<el-option
v-for=
"item in form.train_platform_configs"
v-for=
"item in technicalSupportUnitList"
:key=
"item.platform_key"
:key=
"item.id"
>
:label=
"item.label"
<div
style=
"display: flex; align-items: center"
>
:value=
"item.id"
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
></el-option>
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
</el-select>
<el-input
v-model=
"item.url"
style=
"width: 200px"
/>
</el-form-item>
</div>
<!--
<el-form-item
label=
"客户端"
prop=
"type"
>
</el-checkbox>
<el-radio-group
v-model=
"form.type"
>
</el-form-item>
<el-radio
v-for=
"item in types"
:key=
"item.id"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
<el-form-item
label=
"正式比赛地址"
prop=
"competition_platform_configs"
>
</el-radio-group>
<el-checkbox
</el-form-item>
-->
true-label=
"1"
<el-form-item
label=
"客户端标识"
prop=
"client_id"
>
false-label=
"0"
<el-select
v-model=
"form.client_id"
style=
"width: 100%"
clearable
>
style=
"margin-bottom: 10px"
<el-option
v-for=
"item in clientList"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
></el-option>
v-model=
"item.is_show"
</el-select>
v-for=
"item in form.competition_platform_configs"
</el-form-item>
:key=
"item.platform_key"
<el-form-item
label=
"报名截止日期"
prop=
"apply_expiration_date"
>
>
<el-date-picker
type=
"date"
v-model=
"form.apply_expiration_date"
style=
"width: 100%"
/>
<div
style=
"display: flex; align-items: center"
>
</el-form-item>
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<el-form-item
label=
"正式比赛实操答题时间"
prop=
"datetimeRange2"
>
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
<el-time-picker
<el-input
v-model=
"item.url"
v-if=
"item.type === '2'"
style=
"width: 200px"
/>
is-range
<el-select
v-model=
"item.exam_id"
filterable
style=
"width: 200px"
v-if=
"item.type === '1'"
>
range-separator=
"至"
<el-option
start-placeholder=
"开始时间"
v-for=
"item in examList"
end-placeholder=
"结束时间"
:key=
"item.exam_id"
v-model=
"form.datetimeRange2"
:label=
"item.name"
style=
"width: 100%"
:value=
"item.exam_id"
/>
></el-option>
</el-form-item>
</el-select>
<el-form-item
label=
"正式比赛地址"
prop=
"competition_platform_configs"
>
</div>
<el-checkbox
</el-checkbox>
true-label=
"1"
</el-form-item>
false-label=
"0"
<el-form-item
label=
"是否允许客户端切换"
prop=
"is_switchable_theory_practice"
>
style=
"margin-bottom: 10px"
<el-radio-group
v-model=
"form.is_switchable_theory_practice"
>
v-model=
"item.is_show"
<el-radio
:label=
"0"
>
否
</el-radio>
v-for=
"item in form.competition_platform_configs"
<el-radio
:label=
"1"
>
是
</el-radio>
:key=
"item.platform_key"
</el-radio-group>
>
</el-form-item>
<div
style=
"display: flex; align-items: center"
>
<el-form-item
label=
"有效状态"
prop=
"status"
>
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<el-radio-group
v-model=
"form.status"
>
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
<el-radio
v-for=
"item in status"
:key=
"item.id"
:label=
"item.value"
>
{{
item
.
label
}}
</el-radio>
<el-input
v-model=
"item.url"
v-if=
"item.type === '2'"
style=
"width: 200px"
/>
</el-radio-group>
<el-select
v-model=
"item.exam_id"
filterable
style=
"width: 200px"
v-if=
"item.type === '1'"
>
</el-form-item>
<el-option
<el-form-item
label=
"赛项LOGO"
prop=
"logo"
>
v-for=
"item in examList"
<AppUpload
v-model=
"form.logo"
accept=
"image/*"
></AppUpload>
:key=
"item.exam_id"
</el-form-item>
:label=
"item.name"
<el-form-item
label=
"赛项封面"
prop=
"cover"
>
:value=
"item.exam_id"
<AppUpload
v-model=
"form.cover"
accept=
"image/*"
></AppUpload>
></el-option>
</el-form-item>
</el-select>
<el-row
justify=
"center"
>
</div>
<el-button
type=
"primary"
round
auto-insert-space
@
click=
"handleSubmit"
>
保存
</el-button>
</el-checkbox>
<el-button
round
auto-insert-space
@
click=
"$emit('update:modelValue', false)"
>
取消
</el-button>
</el-form-item>
</el-row>
<el-form-item
label=
"是否允许客户端切换"
prop=
"is_switchable_theory_practice"
>
</el-form>
<el-radio-group
v-model=
"form.is_switchable_theory_practice"
>
</el-dialog>
<el-radio
:label=
"0"
>
否
</el-radio>
<el-radio
:label=
"1"
>
是
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"客户端防作弊"
prop=
"is_customer_anti_cheat"
>
<el-radio-group
v-model=
"form.is_customer_anti_cheat"
>
<el-radio
:label=
"0"
>
否
</el-radio>
<el-radio
:label=
"1"
>
是
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"客户端切换理论与实操"
prop=
"is_switchable_theory_practice"
>
<el-radio-group
v-model=
"form.is_switchable_theory_practice"
>
<el-radio
:label=
"0"
>
否
</el-radio>
<el-radio
:label=
"1"
>
是
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label=
"赛项LOGO"
prop=
"logo"
>
<AppUpload
v-model=
"form.logo"
accept=
"image/*"
></AppUpload>
</el-form-item>
<el-form-item
label=
"赛项封面"
prop=
"cover"
>
<AppUpload
v-model=
"form.cover"
accept=
"image/*"
></AppUpload>
</el-form-item>
</div>
</div>
<el-row
justify=
"center"
>
<el-button
type=
"primary"
round
auto-insert-space
@
click=
"handleSubmit"
>
保存
</el-button>
<el-button
round
auto-insert-space
@
click=
"$emit('update:modelValue', false)"
>
取消
</el-button>
</el-row>
</el-form>
</
template
>
</
template
>
src/modules/admin/contest/items/components/ScoringExpertsDialog.vue
浏览文件 @
ac5e09be
...
@@ -43,6 +43,7 @@ const listOptions = $computed(() => {
...
@@ -43,6 +43,7 @@ const listOptions = $computed(() => {
{
type
:
'expand'
,
slots
:
'class'
},
{
type
:
'expand'
,
slots
:
'class'
},
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'专家姓名'
,
prop
:
'name'
},
{
label
:
'专家姓名'
,
prop
:
'name'
},
{
label
:
'电话'
,
prop
:
'mobile'
},
{
label
:
'所在单位'
,
prop
:
'company'
},
{
label
:
'所在单位'
,
prop
:
'company'
},
{
{
label
:
'性别'
,
label
:
'性别'
,
...
...
src/modules/admin/contest/items/index.ts
浏览文件 @
ac5e09be
...
@@ -11,7 +11,8 @@ export const routes: Array<RouteRecordRaw> = [
...
@@ -11,7 +11,8 @@ export const routes: Array<RouteRecordRaw> = [
component
:
AppLayout
,
component
:
AppLayout
,
children
:
[
children
:
[
{
path
:
''
,
component
:
()
=>
import
(
'./views/Index.vue'
)
},
{
path
:
''
,
component
:
()
=>
import
(
'./views/Index.vue'
)
},
{
path
:
':id'
,
component
:
()
=>
import
(
'./views/View.vue'
),
props
:
true
}
{
path
:
':id'
,
component
:
()
=>
import
(
'./views/View.vue'
),
props
:
true
},
{
path
:
'edit/:id'
,
component
:
()
=>
import
(
'./views/Edit.vue'
),
props
:
true
}
]
]
}
}
]
]
src/modules/admin/contest/items/types.ts
浏览文件 @
ac5e09be
...
@@ -34,7 +34,8 @@ export interface ContestItem {
...
@@ -34,7 +34,8 @@ export interface ContestItem {
expert_count
:
number
expert_count
:
number
train_platform_configs
:
any
[]
train_platform_configs
:
any
[]
competition_platform_configs
:
any
[]
competition_platform_configs
:
any
[]
is_switchable_theory_practice
:
string
is_switchable_theory_practice
:
string
,
is_customer_anti_cheat
:
string
}
}
export
interface
ContestCreateParams
{
export
interface
ContestCreateParams
{
...
...
src/modules/admin/contest/items/views/Edit.vue
0 → 100644
浏览文件 @
ac5e09be
<
script
setup
lang=
"ts"
>
import
type
{
ContestItem
}
from
'../types'
// import { ElMessage } from 'element-plus'
import
{
getContest
}
from
'../api'
const
FormDialog
=
defineAsyncComponent
(()
=>
import
(
'../components/FormDialog.vue'
))
interface
Props
{
id
:
string
}
const
props
=
defineProps
<
Props
>
()
let
detail
=
$ref
<
ContestItem
|
null
>
(
null
)
provide
(
'detail'
,
$$
(
detail
))
// 获取赛项信息
function
fetchInfo
()
{
getContest
({
id
:
props
.
id
}).
then
(
res
=>
{
detail
=
res
.
data
.
detail
})
}
onMounted
(()
=>
{
if
(
props
.
id
===
'1'
)
return
fetchInfo
()
})
</
script
>
<
template
>
<AppCard
title=
"编辑赛项"
>
<FormDialog
:data=
"detail"
></FormDialog>
</AppCard>
</
template
>
<
style
lang=
"scss"
>
.top
{
display
:
flex
;
.el-descriptions
{
flex
:
1
;
margin-top
:
30px
;
}
}
.top-cover
{
width
:
300px
;
margin-right
:
20px
;
p
{
font-weight
:
normal
;
line-height
:
30px
;
font-size
:
14px
;
}
img
{
width
:
100%
;
}
}
</
style
>
src/modules/admin/contest/items/views/Index.vue
浏览文件 @
ac5e09be
...
@@ -8,7 +8,7 @@ import { useMapStore } from '@/stores/map'
...
@@ -8,7 +8,7 @@ import { useMapStore } from '@/stores/map'
// 赛项类型
// 赛项类型
const
types
=
useMapStore
().
getMapValuesByKey
(
'competition_type'
)
const
types
=
useMapStore
().
getMapValuesByKey
(
'competition_type'
)
const
FormDialog
=
defineAsyncComponent
(()
=>
import
(
'../components/FormDialog.vue'
))
//
const FormDialog = defineAsyncComponent(() => import('../components/FormDialog.vue'))
const
appList
=
$ref
<
InstanceType
<
typeof
AppList
>
|
null
>
(
null
)
const
appList
=
$ref
<
InstanceType
<
typeof
AppList
>
|
null
>
(
null
)
...
@@ -50,31 +50,34 @@ const listOptions = {
...
@@ -50,31 +50,34 @@ const listOptions = {
]
]
}
}
let
dialogVisible
=
$ref
(
false
)
//
let dialogVisible = $ref(false)
const
rowData
=
ref
<
ContestItem
|
undefined
|
null
>
(
null
)
//
const rowData = ref
<
ContestItem
|
undefined
|
null
>
(
null
)
// 新增
// 新增
function
handleAdd
()
{
//
function handleAdd() {
rowData
.
value
=
null
//
rowData.value = null
dialogVisible
=
true
//
dialogVisible = true
}
//
}
// 编辑
//
//
编辑
function
handleUpdate
(
row
:
ContestItem
)
{
//
function handleUpdate(row: ContestItem) {
rowData
.
value
=
row
//
rowData.value = row
dialogVisible
=
true
//
dialogVisible = true
}
//
}
function
onUpdateSuccess
()
{
//
function onUpdateSuccess() {
appList
?.
refetch
()
//
appList?.refetch()
}
//
}
</
script
>
</
script
>
<
template
>
<
template
>
<AppCard
title=
"赛项管理"
>
<AppCard
title=
"赛项管理"
>
<AppList
v-bind=
"listOptions"
ref=
"appList"
>
<AppList
v-bind=
"listOptions"
ref=
"appList"
>
<template
#
header-buttons
>
<template
#
header-buttons
>
<el-button
type=
"primary"
:icon=
"CirclePlus"
v-permission=
"'competition-create'"
@
click=
"handleAdd"
>
<
!--
<
el-button
type=
"primary"
:icon=
"CirclePlus"
v-permission=
"'competition-create'"
@
click=
"handleAdd"
>
新增赛项
新增赛项
</el-button>
-->
<el-button
type=
"primary"
:icon=
"CirclePlus"
round
v-permission=
"'competition-create'"
>
<router-link
:to=
"`/admin/contest/items/edit/1`"
target=
"_blank"
>
新增赛项
</router-link>
</el-button>
</el-button>
</
template
>
</
template
>
...
@@ -82,9 +85,14 @@ function onUpdateSuccess() {
...
@@ -82,9 +85,14 @@ function onUpdateSuccess() {
<el-button
type=
"primary"
round
v-permission=
"'competition-detail'"
>
<el-button
type=
"primary"
round
v-permission=
"'competition-detail'"
>
<router-link
:to=
"`/admin/contest/items/$
{row.id}`" target="_blank">查看
</router-link>
<router-link
:to=
"`/admin/contest/items/$
{row.id}`" target="_blank">查看
</router-link>
</el-button>
</el-button>
<el-button
type=
"primary"
round
@
click=
"handleUpdate(row)"
v-permission=
"'competition-edit'"
>
编辑
</el-button>
<el-button
type=
"primary"
round
v-permission=
"'competition-detail'"
>
<router-link
:to=
"`/admin/contest/items/edit/$
{row.id}`" target="_blank" v-permission="'competition-edit'"
>编辑
</router-link
>
</el-button>
<!--
<el-button
type=
"primary"
round
@
click=
"handleUpdate(row)"
v-permission=
"'competition-edit'"
>
编辑
</el-button>
-->
</
template
>
</
template
>
</AppList>
</AppList>
</AppCard>
</AppCard>
<
FormDialog
v-model=
"dialogVisible"
:data=
"rowData"
@
update=
"onUpdateSuccess"
v-if=
"dialogVisible"
></FormDialog
>
<
!-- <FormDialog v-model="dialogVisible" :data="rowData" @update="onUpdateSuccess" v-if="dialogVisible"></FormDialog> --
>
</template>
</template>
src/modules/admin/contest/items/views/View.vue
浏览文件 @
ac5e09be
...
@@ -161,16 +161,16 @@ function handleExperts() {
...
@@ -161,16 +161,16 @@ function handleExperts() {
<AppCard
title=
"训练指导书"
>
<AppCard
title=
"训练指导书"
>
<ViewBook
:id=
"id"
></ViewBook>
<ViewBook
:id=
"id"
></ViewBook>
</AppCard>
</AppCard>
<AppCard
title=
"操作视频"
>
<AppCard
title=
"
训练
操作视频"
>
<ViewVideo
:id=
"id"
></ViewVideo>
<ViewVideo
:id=
"id"
></ViewVideo>
</AppCard>
</AppCard>
<AppCard
title=
"
大赛试
题"
>
<AppCard
title=
"
比赛实操赛
题"
>
<ViewQuestion
:id=
"id"
></ViewQuestion>
<ViewQuestion
:id=
"id"
></ViewQuestion>
</AppCard>
</AppCard>
<AppCard
title=
"
大赛
试卷"
>
<AppCard
title=
"
比赛实操
试卷"
>
<ViewExam
:id=
"id"
></ViewExam>
<ViewExam
:id=
"id"
></ViewExam>
</AppCard>
</AppCard>
<AppCard
title=
"关联实验"
>
<AppCard
title=
"关联
营销
实验"
>
<ViewExperiment
:id=
"detail?.id || ''"
:pid=
"id"
></ViewExperiment>
<ViewExperiment
:id=
"detail?.id || ''"
:pid=
"id"
></ViewExperiment>
</AppCard>
</AppCard>
<AppCard
title=
"抽签加密"
>
<AppCard
title=
"抽签加密"
>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论