Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-lab
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-lab
Commits
0638ac83
提交
0638ac83
authored
12月 08, 2025
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 比赛支持全媒体运营师(网络编辑)
上级
d7faba5b
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
82 行增加
和
22 行删除
+82
-22
CompetitionRuleDialog.vue
...admin/lab/experiment/components/CompetitionRuleDialog.vue
+1
-0
useCompetition.ts
src/modules/student/lab/composables/useCompetition.ts
+28
-2
Competition.vue
src/modules/student/lab/views/Competition.vue
+53
-20
没有找到文件。
src/modules/admin/lab/experiment/components/CompetitionRuleDialog.vue
浏览文件 @
0638ac83
...
...
@@ -48,6 +48,7 @@ const competitionOptions = ref([
{
label
:
'网络主播赛项'
,
value
:
'1'
},
{
label
:
'全媒体运营赛项'
,
value
:
'2'
},
{
label
:
'互联网营销师(直播销售)'
,
value
:
'3'
},
{
label
:
'全媒体运营师(网络编辑)'
,
value
:
'4'
},
])
async
function
fetchInfo
()
{
...
...
src/modules/student/lab/composables/useCompetition.ts
浏览文件 @
0638ac83
import
{
useGetCourseList
}
from
'./useGetCourseList'
import
type
{
ExperimentType
}
from
'../types'
import
{
getExperiment
,
getExperimentCompetition
,
submitCompetition
}
from
'../api'
import
{
getExperiment
,
getExperimentCompetition
,
submitCompetition
,
getExperimentExamList
}
from
'../api'
import
{
useCookies
}
from
'@vueuse/integrations/useCookies'
interface
StudentStatus
{
has_submitted
:
boolean
...
...
@@ -16,11 +17,16 @@ interface Competition {
}
export
function
useCompetition
()
{
const
cookies
=
useCookies
()
const
competition
=
ref
<
Competition
>
()
const
{
courses
}
=
useGetCourseList
()
const
experiments
=
ref
<
ExperimentType
[]
>
([])
const
courseId
=
ref
(
''
)
const
experimentId
=
ref
(
''
)
const
biURL
=
computed
<
string
>
(()
=>
{
return
`
${
import
.
meta
.
env
.
VITE_LAB_URL
}
&token=
${
cookies
.
get
(
'TGC'
)}
`
})
watchEffect
(()
=>
{
if
(
courses
.
value
.
length
)
{
...
...
@@ -42,6 +48,9 @@ export function useCompetition() {
const
fetchExperimentCompetition
=
async
()
=>
{
const
res
=
await
getExperimentCompetition
({
experiment_id
:
experimentId
.
value
})
competition
.
value
=
res
.
data
.
detail
if
(
res
.
data
.
detail
.
competition
==
'4'
)
{
fetchExamList
()
}
}
watchEffect
(()
=>
{
if
(
experimentId
.
value
)
{
...
...
@@ -53,5 +62,22 @@ export function useCompetition() {
await
submitCompetition
({
experiment_id
:
experimentId
.
value
})
await
fetchExperimentCompetition
()
}
return
{
competition
,
courseId
,
experimentId
,
experimentInfo
,
submit
}
const
examList
=
ref
<
any
[]
>
([])
// 考试平台 URL
const
examURL
=
computed
<
string
>
(()
=>
{
if
(
!
examList
.
value
.
length
)
return
''
const
[
first
]
=
examList
.
value
return
`
${
import
.
meta
.
env
.
VITE_EXAM_SHOW_URL
}
/exam/
${
first
?.
exam_id
}
`
// return `
https
:
//dev.ezijing.com:5173/exam/7003551966412406784?has_time=0&has_submit=0&has_save=1&show_answer=1`
}
)
const fetchExamList = async () => {
const res = await getExperimentExamList({ experiment_id: experimentId.value })
const resCookies = res.data.cookies
cookies.set(resCookies.key, resCookies.auth_key, { domain: '.ezijing.com', path: '/' })
examList.value = res.data.items
}
return { competition, courseId, experimentId, experimentInfo, submit, fetchExamList, examURL, biURL }
}
src/modules/student/lab/views/Competition.vue
浏览文件 @
0638ac83
...
...
@@ -6,12 +6,13 @@ import { useNow } from '@vueuse/core'
import
dayjs
from
'dayjs'
import
{
formatDuration
}
from
'@/utils/utils'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
useEventListener
}
from
'@vueuse/core'
const
appConfig
=
useAppConfig
()
const
Case
=
defineAsyncComponent
(()
=>
import
(
'../components/Case.vue'
))
const
{
courseId
,
experimentId
,
competition
,
submit
}
=
useCompetition
()
const
{
courseId
,
experimentId
,
competition
,
submit
,
examURL
,
biURL
}
=
useCompetition
()
const
LAB_URL
=
computed
<
string
>
(()
=>
{
if
(
competition
.
value
?.
competition
==
'2'
)
{
...
...
@@ -64,6 +65,16 @@ const handleSubmit = async () => {
}
)
}
const
tabActive
=
ref
(
'bi'
)
useEventListener
(
window
,
'message'
,
async
(
event
)
=>
{
console
.
log
(
event
)
const
{
data
}
=
event
if
(
data
.
action
===
'submitExam'
)
{
await
submit
()
isEntry
.
value
=
false
}
})
</
script
>
<
template
>
<DragPanel
v-if=
"isEntry"
>
...
...
@@ -76,24 +87,33 @@ const handleSubmit = async () => {
</div>
</
template
>
<
template
#
right
>
<AppCard>
<div
class=
"competition-header"
>
<div
class=
"time"
>
<div
class=
"label"
>
倒计时:
</div>
<div
class=
"value"
>
{{
countdown
.
value
}}
</div>
<template
v-if=
"competition?.competition == '4'"
>
<AppCard>
<el-button
:type=
"tabActive === 'bi' ? 'primary' : 'default'"
@
click=
"tabActive = 'bi'"
>
实操环境
</el-button>
<el-button
:type=
"tabActive === 'exam' ? 'primary' : 'default'"
@
click=
"tabActive = 'exam'"
>
理论试题
</el-button>
</AppCard>
<div
class=
"iframe-box"
>
<iframe
allow=
"camera; microphone"
allowfullscreen
:src=
"biURL"
frameborder=
"0"
class=
"iframe"
ref=
"iframeRef"
v-show=
"tabActive === 'bi'"
></iframe>
<iframe
allow=
"camera; microphone"
allowfullscreen
:src=
"examURL"
frameborder=
"0"
class=
"iframe"
ref=
"iframeRef"
v-show=
"tabActive === 'exam'"
></iframe>
</div>
</
template
>
<
template
v-else
>
<AppCard>
<div
class=
"competition-header"
>
<div
class=
"time"
>
<div
class=
"label"
>
倒计时:
</div>
<div
class=
"value"
>
{{
countdown
.
value
}}
</div>
</div>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
提交考试
</el-button>
</div>
<el-button
type=
"primary"
@
click=
"handleSubmit"
>
提交考试
</el-button>
</AppCard>
<div
class=
"iframe-box"
>
<iframe
allow=
"camera; microphone"
allowfullscreen
:src=
"LAB_URL"
frameborder=
"0"
class=
"iframe"
ref=
"iframeRef"
></iframe>
</div>
</AppCard>
<div
class=
"iframe-box"
>
<iframe
allow=
"camera; microphone"
allowfullscreen
:src=
"LAB_URL"
frameborder=
"0"
class=
"iframe"
ref=
"iframeRef"
></iframe>
</div>
</
template
>
</template>
</DragPanel>
<
template
v-else
>
...
...
@@ -106,9 +126,7 @@ const handleSubmit = async () => {
<p>
{{
competition
?.
start_time
}}
~
{{
competition
?.
end_time
}}
</p>
</div>
</div>
<el-button
v-if=
"canEnter"
type=
"primary"
size=
"large"
@
click=
"handleEntry"
class=
"entry-btn"
>
进入实操考试
</el-button
>
<el-button
v-if=
"canEnter"
type=
"primary"
size=
"large"
@
click=
"handleEntry"
class=
"entry-btn"
>
进入实操考试
</el-button>
<el-button
plain
v-if=
"isSubmitted"
type=
"primary"
size=
"large"
class=
"entry-btn"
>
考试已提交
</el-button>
</div>
<el-empty
description=
"暂无比赛"
v-else
/>
...
...
@@ -121,6 +139,7 @@ const handleSubmit = async () => {
display
:
flex
;
flex-direction
:
column
;
}
.left-box-title
{
font-size
:
22px
;
font-weight
:
600
;
...
...
@@ -129,22 +148,27 @@ const handleSubmit = async () => {
text-align
:
center
;
margin-bottom
:
20px
;
}
.left-box-content
{
flex
:
1
;
}
.competition-header
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
.time
{
display
:
flex
;
align-items
:
center
;
gap
:
4px
;
.label
{
font-size
:
14px
;
color
:
var
(
--
main-color
);
font-weight
:
500
;
}
.value
{
font-size
:
24px
;
font-weight
:
700
;
...
...
@@ -154,6 +178,7 @@ const handleSubmit = async () => {
}
}
}
.iframe-box
{
position
:
relative
;
flex
:
1
;
...
...
@@ -161,19 +186,23 @@ const handleSubmit = async () => {
margin-top
:
20px
;
display
:
flex
;
}
.iframe
{
width
:
100%
;
height
:
100%
;
}
.welcome-box
{
margin
:
-20px
;
height
:
calc
(
100vh
-
66px
);
.entry-btn
{
display
:
block
;
width
:
300px
;
margin
:
100px
auto
;
}
}
.welcome-box-header
{
height
:
50%
;
background
:
url('/public/images/competition_bg.jpg')
no-repeat
top
center
;
...
...
@@ -181,6 +210,7 @@ const handleSubmit = async () => {
display
:
flex
;
align-items
:
flex-end
;
}
.welcome-box-header-content
{
width
:
100%
;
max-width
:
1000px
;
...
...
@@ -196,6 +226,7 @@ const handleSubmit = async () => {
letter-spacing
:
7px
;
text-shadow
:
0px
2px
4px
rgba
(
0
,
0
,
0
,
0
.5
);
}
h2
{
margin-top
:
20px
;
font-size
:
18px
;
...
...
@@ -204,6 +235,7 @@ const handleSubmit = async () => {
line-height
:
25px
;
text-shadow
:
0px
2px
4px
rgba
(
0
,
0
,
0
,
0
.5
);
}
.line
{
width
:
24px
;
height
:
2px
;
...
...
@@ -211,6 +243,7 @@ const handleSubmit = async () => {
box-shadow
:
0
2px
4px
#000000
80
;
margin
:
10px
0
;
}
p
{
font-size
:
18px
;
font-family
:
PingFangSC-Regular
,
PingFang
SC
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论