Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-lab
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-lab
Commits
16a0af6f
提交
16a0af6f
authored
5月 06, 2023
作者:
lhh
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update
上级
eab55605
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
323 行增加
和
4 行删除
+323
-4
api.ts
src/modules/admin/contest/items/api.ts
+20
-0
ViewQuestion.vue
src/modules/admin/contest/items/components/ViewQuestion.vue
+95
-0
ViewQuestionFormDialog.vue
...admin/contest/items/components/ViewQuestionFormDialog.vue
+177
-0
ViewQuestionPreviewDialog.vue
...in/contest/items/components/ViewQuestionPreviewDialog.vue
+19
-0
View.vue
src/modules/admin/contest/items/views/View.vue
+12
-4
没有找到文件。
src/modules/admin/contest/items/api.ts
浏览文件 @
16a0af6f
...
...
@@ -81,6 +81,7 @@ export function getContestBook(params: { competition_id: string }) {
export
function
getContestBooks
(
params
:
{
competition_id
:
string
})
{
return
httpRequest
.
get
(
'/api/resource/v1/backend/competition-book/list'
,
{
params
})
}
// 添加赛项指导书
export
function
createContestBook
(
data
:
ContestBookUpdateParams
)
{
return
httpRequest
.
post
(
'/api/resource/v1/backend/competition-book/create'
,
data
)
...
...
@@ -147,3 +148,21 @@ export function getContestantList(params?: { student_name?: string; page?: numbe
export
function
getPlatformKeys
(
params
?:
{
competition_id
:
string
})
{
return
httpRequest
.
get
(
'/api/resource/v1/backend/competition-book/platform-keys'
,
{
params
})
}
// 获取赛项试题
export
function
getQuestionList
(
params
:
{
competition_id
:
string
})
{
return
httpRequest
.
get
(
'/api/resource/v1/backend/competition-question/list'
,
{
params
})
}
// 添加大赛试题
export
function
createQuestion
(
data
:
ContestBookUpdateParams
)
{
return
httpRequest
.
post
(
'/api/resource/v1/backend/competition-question/create'
,
data
)
}
// 更新大赛试题
export
function
updateQuestion
(
data
:
ContestBookUpdateParams
)
{
return
httpRequest
.
post
(
'/api/resource/v1/backend/competition-question/update'
,
data
)
}
// 删除大赛试题
export
function
deleteQuestion
(
data
:
{
id
:
string
})
{
return
httpRequest
.
post
(
'/api/resource/v1/backend/competition-question/delete'
,
data
)
}
\ No newline at end of file
src/modules/admin/contest/items/components/ViewQuestion.vue
0 → 100644
浏览文件 @
16a0af6f
<
script
setup
lang=
"ts"
>
import
type
{
ContestBookItem
}
from
'../types'
import
{
CirclePlus
}
from
'@element-plus/icons-vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
AppList
from
'@/components/base/AppList.vue'
import
ViewQuestionPreviewDialog
from
'./ViewQuestionPreviewDialog.vue'
import
{
getQuestionList
,
deleteQuestion
}
from
'../api'
const
FormDialog
=
defineAsyncComponent
(()
=>
import
(
'./ViewQuestionFormDialog.vue'
))
interface
Props
{
id
:
string
}
const
props
=
defineProps
<
Props
>
()
const
appList
=
$ref
<
InstanceType
<
typeof
AppList
>
|
null
>
(
null
)
// 列表配置
const
listOptions
=
{
hasPagination
:
false
,
remote
:
{
httpRequest
:
getQuestionList
,
params
:
{
competition_id
:
props
.
id
},
callback
(
res
:
any
)
{
return
res
?.
items
?
{
list
:
res
?.
items
}
:
{
list
:
[]
}
}
},
columns
:
[
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'试题名称'
,
prop
:
'name'
},
{
label
:
'文件类型'
,
prop
:
'type'
},
{
label
:
'创建人'
,
prop
:
'created_operator.real_name'
},
{
label
:
'创建时间'
,
prop
:
'created_at'
},
{
label
:
'更新时间'
,
prop
:
'updated_at'
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
180
}
]
}
let
dialogVisible
=
$ref
(
false
)
const
rowData
=
ref
<
ContestBookItem
>
()
// 新增
function
handleAdd
()
{
rowData
.
value
=
undefined
dialogVisible
=
true
}
// 编辑
function
handleUpdate
(
row
:
ContestBookItem
)
{
rowData
.
value
=
row
dialogVisible
=
true
}
// 查阅
let
viewVisible
=
$ref
(
false
)
function
handleView
(
row
:
ContestBookItem
)
{
rowData
.
value
=
row
viewVisible
=
true
}
// 删除
function
handleRemoveClass
(
row
:
ContestBookItem
)
{
ElMessageBox
.
confirm
(
'确定要删除吗?'
,
'提示'
).
then
(()
=>
{
deleteQuestion
({
id
:
row
.
id
}).
then
(()
=>
{
ElMessage
({
message
:
'删除成功'
,
type
:
'success'
})
onUpdateSuccess
()
})
})
}
function
onUpdateSuccess
()
{
appList
?.
refetch
()
}
</
script
>
<
template
>
<AppList
v-bind=
"listOptions"
ref=
"appList"
>
<template
#
header-buttons
>
<el-button
type=
"primary"
:icon=
"CirclePlus"
@
click=
"handleAdd"
v-permission=
"'competition-book-create'"
>
新增
</el-button
>
</
template
>
<
template
#
table-x=
"{ row }"
>
<el-button
link
round
type=
"info"
@
click=
"handleView(row)"
v-permission=
"'competition-book-detail'"
>
查阅
</el-button
>
<el-button
link
round
type=
"primary"
@
click=
"handleUpdate(row)"
v-permission=
"'competition-book-update'"
>
编辑
</el-button
>
<el-button
link
round
type=
"danger"
@
click=
"handleRemoveClass(row)"
v-permission=
"'competition-book-delete'"
>
删除
</el-button
>
</
template
>
</AppList>
<FormDialog
v-model=
"dialogVisible"
:data=
"rowData"
@
update=
"onUpdateSuccess"
v-if=
"dialogVisible"
></FormDialog>
<ViewQuestionPreviewDialog
v-model=
"viewVisible"
:data=
"rowData"
v-if=
"viewVisible && rowData"
></ViewQuestionPreviewDialog>
</template>
src/modules/admin/contest/items/components/ViewQuestionFormDialog.vue
0 → 100644
浏览文件 @
16a0af6f
<
script
setup
lang=
"ts"
>
import
type
{
FormInstance
,
FormRules
}
from
'element-plus'
import
type
{
ContestItem
,
ContestBookItem
,
ContestBookUpdateParams
}
from
'../types'
import
{
ElMessageBox
,
ElMessage
}
from
'element-plus'
import
{
pick
}
from
'lodash-es'
import
AppUpload
from
'@/components/base/AppUpload.vue'
import
{
createQuestion
,
updateQuestion
,
getPlatformKeys
}
from
'../api'
import
{
useMapStore
}
from
'@/stores/map'
interface
Props
{
data
?:
ContestBookItem
}
const
props
=
defineProps
<
Props
>
()
const
route
=
useRoute
()
const
emit
=
defineEmits
<
{
(
e
:
'update'
):
void
(
e
:
'update:modelValue'
,
visible
:
boolean
):
void
}
>
()
const
detail
=
$ref
(
inject
(
'detail'
)
as
ContestItem
)
// 数据状态
const
status
=
useMapStore
().
getMapValuesByKey
(
'system_status'
)
const
formRef
=
$ref
<
FormInstance
>
()
const
form
=
reactive
<
any
>
({
competition_id
:
detail
.
id
,
files
:
[],
url
:
''
,
type
:
''
,
name
:
''
,
status
:
'1'
,
protocol
:
false
,
platform_key
:
''
})
watchEffect
(()
=>
{
if
(
!
props
.
data
)
return
form
.
files
=
[
JSON
.
parse
(
props
.
data
.
url
)]
Object
.
assign
(
form
,
{
protocol
:
true
},
props
.
data
)
})
const
checkProtocol
=
(
rule
:
any
,
value
:
any
,
callback
:
any
)
=>
{
if
(
!
value
)
{
return
callback
(
new
Error
(
'请阅读并同意'
))
}
else
{
callback
()
}
}
const
rules
=
ref
<
FormRules
>
({
files
:
[{
type
:
'array'
,
required
:
true
,
message
:
'请上传大赛试题'
}],
name
:
[{
required
:
true
,
message
:
'请输入大赛试题名称'
,
trigger
:
'blur'
}],
course_id
:
[{
required
:
true
,
message
:
'请选择关联训练课程'
,
trigger
:
'change'
}],
experiment_id
:
[{
required
:
true
,
message
:
'请选择关联训练'
,
trigger
:
'change'
}],
protocol
:
[{
validator
:
checkProtocol
,
message
:
'请阅读并同意'
,
trigger
:
'change'
}]
})
const
isUpdate
=
$computed
(()
=>
{
return
!!
props
.
data
?.
id
})
const
title
=
$computed
(()
=>
{
return
isUpdate
?
'编辑大赛试题'
:
'新增大赛试题'
})
function
handleBeforeUpload
()
{
if
(
form
.
files
.
length
)
{
return
ElMessageBox
.
confirm
(
'系统仅支持1个大赛试题,此操作将覆盖原有大赛试题文件,确认上传新文件吗?'
,
'提示'
)
}
return
true
}
function
handleUploadSuccess
(
file
:
any
)
{
const
[
name
,
type
]
=
file
.
name
.
split
(
'.'
)
form
.
name
=
name
form
.
type
=
type
}
// 提交
function
handleSubmit
()
{
formRef
?.
validate
().
then
(()
=>
{
const
[
file
]
=
form
.
files
const
params
=
Object
.
assign
({},
pick
(
form
,
[
'competition_id'
,
'name'
,
'type'
,
'status'
,
'platform_key'
]),
{
url
:
JSON
.
stringify
({
name
:
file
.
name
,
url
:
file
.
url
,
size
:
file
.
size
})
})
isUpdate
?
handleUpdate
(
params
)
:
handleCreate
(
params
)
})
}
// 新增
function
handleCreate
(
params
:
ContestBookUpdateParams
)
{
createQuestion
(
params
).
then
(()
=>
{
ElMessage
({
message
:
'创建成功'
,
type
:
'success'
})
emit
(
'update'
)
emit
(
'update:modelValue'
,
false
)
})
}
// 修改
function
handleUpdate
(
params
:
ContestBookUpdateParams
)
{
params
.
id
=
props
.
data
?.
id
updateQuestion
(
params
).
then
(()
=>
{
ElMessage
({
message
:
'修改成功'
,
type
:
'success'
})
emit
(
'update'
)
emit
(
'update:modelValue'
,
false
)
})
}
// 获取平台标识列表
let
platformKeys
=
$ref
<
{
platform_key
:
string
;
name
:
string
}[]
>
([])
const
getPlatformKeysList
=
function
()
{
console
.
log
(
route
,
'route'
)
getPlatformKeys
({
competition_id
:
route
.
params
?.
id
as
string
}).
then
(
res
=>
{
if
(
res
.
data
?.
items
)
{
platformKeys
=
res
.
data
?.
items
if
(
form
.
platform_key
===
''
)
{
form
.
platform_key
=
res
.
data
?.
items
[
0
]?.
platform_key
}
}
})
}
getPlatformKeysList
()
</
script
>
<
template
>
<el-dialog
:title=
"title"
:close-on-click-modal=
"false"
width=
"600px"
@
update:modelValue=
"$emit('update:modelValue')"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
label-width=
"124px"
>
<el-form-item
label=
"大赛试题文件"
prop=
"files"
>
<AppUpload
v-model=
"form.files"
:limit=
"1"
:beforeUpload=
"handleBeforeUpload"
accept=
".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,.pdf,application/pdf,.ppt,.pptx,application/vnd.ms-powerpoint,.csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
@
success=
"handleUploadSuccess"
>
<template
#
tip
>
大赛试题文件支持格式包含:doc docx xls xlsx pdf ppt pptx,大小不超过50M
</
template
>
</AppUpload>
</el-form-item>
<el-form-item
label=
"大赛试题名称"
prop=
"name"
>
<el-input
v-model=
"form.name"
></el-input>
<p
class=
"form-tips"
>
大赛试题名称自动取值于文件名称,可以进行二次修改。
</p>
</el-form-item>
<el-form-item
label=
"关联赛项"
>
<el-input
:value=
"detail.name"
disabled
></el-input>
</el-form-item>
<el-form-item
label=
"关联实验"
>
<el-radio-group
v-model=
"form.platform_key"
>
<el-radio
v-for=
"item in platformKeys"
:key=
"item.platform_key"
:label=
"item.platform_key"
>
{{
item.name
}}
</el-radio>
<!-- <el-radio :key="1" label="1">商业数据分析实验</el-radio>
<el-radio :key="1" label="2">数字营销实操</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
prop=
"protocol"
>
<el-checkbox
label=
"我已阅读并同意"
v-model=
"form.protocol"
/>
<a
href=
"https://view.officeapps.live.com/op/view.aspx?src=https://webapp-pub.ezijing.com/center_resource/%E7%B4%AB%E8%8D%86%E6%95%99%E8%82%B2%E7%94%A8%E6%88%B7%E5%85%A5%E9%A9%BB%E5%8F%8A%E7%BD%91%E7%BB%9C%E6%95%99%E5%AD%A6%E8%B5%84%E6%BA%90%E5%8D%8F%E8%AE%AE(1).docx"
target=
"_blank"
>
《紫荆教育用户入驻及网络教学资源协议》
</a
>
</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>
<
style
lang=
"scss"
scoped
>
.form-tips
{
font-size
:
12px
;
color
:
#999
;
}
</
style
>
src/modules/admin/contest/items/components/ViewQuestionPreviewDialog.vue
0 → 100644
浏览文件 @
16a0af6f
<
script
setup
lang=
"ts"
>
import
type
{
ContestBookItem
}
from
'../types'
import
Preview
from
'@/components/Preview.vue'
interface
Props
{
data
:
ContestBookItem
}
const
props
=
defineProps
<
Props
>
()
const
file
=
$computed
(()
=>
{
return
JSON
.
parse
(
props
.
data
.
url
)
})
</
script
>
<
template
>
<el-dialog
title=
"查阅训练指导书"
>
<Preview
:url=
"file.url"
style=
"height: 60vh"
></Preview>
</el-dialog>
</
template
>
src/modules/admin/contest/items/views/View.vue
浏览文件 @
16a0af6f
...
...
@@ -7,6 +7,7 @@ import dayjs from 'dayjs'
const
ViewBook
=
defineAsyncComponent
(()
=>
import
(
'../components/ViewBook.vue'
))
const
ViewVideo
=
defineAsyncComponent
(()
=>
import
(
'../components/ViewVideo.vue'
))
const
ViewQuestion
=
defineAsyncComponent
(()
=>
import
(
'../components/ViewQuestion.vue'
))
const
ScoringRulesDialog
=
defineAsyncComponent
(()
=>
import
(
'../components/ScoringRulesDialog.vue'
))
const
ScoringExpertsDialog
=
defineAsyncComponent
(()
=>
import
(
'../components/ScoringExpertsDialog.vue'
))
const
ContestantDialog
=
defineAsyncComponent
(()
=>
import
(
'../components/ContestantDialog.vue'
))
...
...
@@ -160,28 +161,35 @@ function handleExperts() {
<AppCard
title=
"操作视频"
>
<ViewVideo
:id=
"id"
></ViewVideo>
</AppCard>
<AppCard
title=
"大赛试题"
>
<ViewQuestion
:id=
"id"
></ViewQuestion>
</AppCard>
<!-- 评分规则 -->
<ScoringRulesDialog
v-model=
"scoringRulesVisible"
:disabled=
"isStarted"
@
update=
"fetchRule"
v-if=
"scoringRulesVisible && detail"
></ScoringRulesDialog>
v-if=
"scoringRulesVisible && detail"
></ScoringRulesDialog>
<!-- 评分专家 -->
<ScoringExpertsDialog
v-model=
"scoringExpertsVisible"
:disabled=
"isStarted"
@
update=
"fetchExperts"
v-if=
"scoringExpertsVisible && detail"
></ScoringExpertsDialog>
v-if=
"scoringExpertsVisible && detail"
></ScoringExpertsDialog>
<!-- 参赛选手 -->
<ContestantDialog
v-model=
"contestantVisible"
:disabled=
"isStarted"
v-if=
"contestantVisible && detail"
></ContestantDialog>
v-if=
"contestantVisible && detail"
></ContestantDialog>
<!-- 评分细则 -->
<ScoringRulesBookDialog
v-model=
"scoringRulesBookVisible"
:disabled=
"isStarted"
v-if=
"scoringRulesBookVisible && detail"
></ScoringRulesBookDialog>
v-if=
"scoringRulesBookVisible && detail"
></ScoringRulesBookDialog>
</template>
<
style
lang=
"scss"
>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论