提交 0638ac83 authored 作者: 王鹏飞's avatar 王鹏飞

feat: 比赛支持全媒体运营师(网络编辑)

上级 d7faba5b
......@@ -48,6 +48,7 @@ const competitionOptions = ref([
{ label: '网络主播赛项', value: '1' },
{ label: '全媒体运营赛项', value: '2' },
{ label: '互联网营销师(直播销售)', value: '3' },
{ label: '全媒体运营师(网络编辑)', value: '4' },
])
async function fetchInfo() {
......
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 }
}
......@@ -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 #00000080;
margin: 10px 0;
}
p {
font-size: 18px;
font-family: PingFangSC-Regular, PingFang SC;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论