提交 290131a3 authored 作者: 王鹏飞's avatar 王鹏飞

chore: 优化移动端显示

上级 856de07b
...@@ -66,6 +66,13 @@ onMounted(() => { ...@@ -66,6 +66,13 @@ onMounted(() => {
</svg> </svg>
</div> </div>
</div> </div>
<button
v-if="!isLeftShow && isMobile"
type="button"
class="panel-mobile-toggle"
@click="leftPanelVisible = !leftPanelVisible">
{{ leftPanelVisible ? '收起试题' : '展开试题' }}
</button>
<div class="drag-panel-right"> <div class="drag-panel-right">
<div class="drag-cover" v-if="dragFlag"></div> <div class="drag-cover" v-if="dragFlag"></div>
<slot name="right"></slot> <slot name="right"></slot>
...@@ -123,6 +130,9 @@ onMounted(() => { ...@@ -123,6 +130,9 @@ onMounted(() => {
cursor: pointer; cursor: pointer;
} }
} }
.panel-mobile-toggle {
display: none;
}
.drag-panel-left-content { .drag-panel-left-content {
overflow: hidden; overflow: hidden;
height: 100%; height: 100%;
...@@ -147,16 +157,46 @@ onMounted(() => { ...@@ -147,16 +157,46 @@ onMounted(() => {
.drag-panel { .drag-panel {
flex-direction: column; flex-direction: column;
height: auto; height: auto;
gap: 12px;
} }
.drag-panel-left { .drag-panel-left {
width: 100% !important; width: 100% !important;
padding: 12px; padding: 12px;
margin-right: 0; margin-right: 0;
height: 50vh;
min-height: 320px;
overflow: hidden;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
&.is-hidden {
height: 0;
min-height: 0;
padding: 0;
margin: 0;
overflow: hidden;
.drag-panel-left-content {
display: none;
}
}
}
.panel-mobile-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 44px;
margin-top: 0;
margin-bottom: 12px;
border: 0;
border-radius: 0 0 16px 16px;
background: #fff;
color: var(--main-color);
font-size: 14px;
line-height: 1;
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.06);
} }
.drag-panel-left-content { .drag-panel-left-content {
height: auto; height: 100%;
overflow: visible; overflow: auto;
} }
.drag-panel-right { .drag-panel-right {
width: 100%; width: 100%;
......
...@@ -232,6 +232,7 @@ export function saveCompetitionRule(data: { ...@@ -232,6 +232,7 @@ export function saveCompetitionRule(data: {
end_time: string end_time: string
questions: string questions: string
competition: string competition: string
config?: string
}) { }) {
return httpRequest.post('/api/resource/v1/backend/experiment-competition-rule/save', data) return httpRequest.post('/api/resource/v1/backend/experiment-competition-rule/save', data)
} }
...@@ -3,6 +3,7 @@ import { ElMessage } from 'element-plus' ...@@ -3,6 +3,7 @@ import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue' import { Plus } from '@element-plus/icons-vue'
import { useMediaQuery } from '@vueuse/core' import { useMediaQuery } from '@vueuse/core'
import { getCompetitionRule, saveCompetitionRule } from '../api' import { getCompetitionRule, saveCompetitionRule } from '../api'
import AppEditor from '@/components/base/AppEditor.vue'
interface Props { interface Props {
id: string id: string
...@@ -22,6 +23,7 @@ const gradeRuleList = [ ...@@ -22,6 +23,7 @@ const gradeRuleList = [
] ]
const defaultConfig = { const defaultConfig = {
min_submit_time: '', min_submit_time: '',
practical_question: '',
rules: [] as any[], rules: [] as any[],
} }
const formRef = ref() const formRef = ref()
...@@ -40,6 +42,7 @@ const rules = ref({ ...@@ -40,6 +42,7 @@ const rules = ref({
end_time: [{ required: true, message: '请选择' }], end_time: [{ required: true, message: '请选择' }],
questions: [{ required: true, message: '请选择' }], questions: [{ required: true, message: '请选择' }],
competition: [{ required: true, message: '请选择' }], competition: [{ required: true, message: '请选择' }],
'config.practical_question': [{ required: true, message: '请输入实操试题' }],
}) })
const options = ref([ const options = ref([
...@@ -178,7 +181,7 @@ function disabledMinSubmitDate(time: Date) { ...@@ -178,7 +181,7 @@ function disabledMinSubmitDate(time: Date) {
<template> <template>
<el-button type="primary" @click="dialogVisible = true">编辑大赛规则</el-button> <el-button type="primary" @click="dialogVisible = true">编辑大赛规则</el-button>
<el-dialog title="编辑大赛规则" :close-on-click-modal="false" width="800px" v-model="dialogVisible" append-to-body> <el-dialog title="编辑大赛规则" :close-on-click-modal="false" width="1000px" v-model="dialogVisible" append-to-body>
<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="100px"> <el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="100px">
<el-form-item label="大赛名称" prop="name"> <el-form-item label="大赛名称" prop="name">
<el-input v-model="form.name" placeholder="请输入大赛名称" /> <el-input v-model="form.name" placeholder="请输入大赛名称" />
...@@ -222,6 +225,12 @@ function disabledMinSubmitDate(time: Date) { ...@@ -222,6 +225,12 @@ function disabledMinSubmitDate(time: Date) {
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="实操试题" prop="config.practical_question">
<AppEditor
v-model="form.config.practical_question"
:height="320"
placeholder="请输入实操试题内容" />
</el-form-item>
<el-divider /> <el-divider />
<el-form-item label-width="0"> <el-form-item label-width="0">
<el-row justify="space-between" style="width: 100%"> <el-row justify="space-between" style="width: 100%">
......
...@@ -14,6 +14,7 @@ interface Competition { ...@@ -14,6 +14,7 @@ interface Competition {
student_status: StudentStatus student_status: StudentStatus
competition: string competition: string
questions: string questions: string
config?: string | Record<string, any>
} }
export function useCompetition() { export function useCompetition() {
......
...@@ -10,9 +10,7 @@ import { useEventListener } from '@vueuse/core' ...@@ -10,9 +10,7 @@ import { useEventListener } from '@vueuse/core'
const appConfig = useAppConfig() const appConfig = useAppConfig()
const Case = defineAsyncComponent(() => import('../components/Case.vue')) const { experimentId, competition, submit, examURL, biURL } = useCompetition()
const { courseId, experimentId, competition, submit, examURL, biURL } = useCompetition()
const LAB_URL = computed<string>(() => { const LAB_URL = computed<string>(() => {
if (competition.value?.competition == '2') { if (competition.value?.competition == '2') {
...@@ -67,6 +65,19 @@ const handleSubmit = async () => { ...@@ -67,6 +65,19 @@ const handleSubmit = async () => {
} }
const tabActive = ref('bi') const tabActive = ref('bi')
const practicalQuestionHtml = computed(() => {
const rawConfig = competition.value?.config
if (!rawConfig) return ''
try {
const config = typeof rawConfig === 'string' ? JSON.parse(rawConfig) : rawConfig
return config?.practical_question || ''
} catch (error) {
console.error(error)
return ''
}
})
useEventListener(window, 'message', async (event) => { useEventListener(window, 'message', async (event) => {
console.log(event) console.log(event)
const { data } = event const { data } = event
...@@ -82,7 +93,8 @@ useEventListener(window, 'message', async (event) => { ...@@ -82,7 +93,8 @@ useEventListener(window, 'message', async (event) => {
<div class="left-box"> <div class="left-box">
<h2 class="left-box-title">实操试题</h2> <h2 class="left-box-title">实操试题</h2>
<div class="left-box-content"> <div class="left-box-content">
<Case :course_id="courseId" :experiment_id="experimentId" /> <div class="practical-question" v-if="practicalQuestionHtml" v-html="practicalQuestionHtml"></div>
<el-empty description="暂无数据" v-else />
</div> </div>
</div> </div>
</template> </template>
...@@ -151,6 +163,36 @@ useEventListener(window, 'message', async (event) => { ...@@ -151,6 +163,36 @@ useEventListener(window, 'message', async (event) => {
.left-box-content { .left-box-content {
flex: 1; flex: 1;
min-height: 0;
overflow: auto;
}
.practical-question {
color: #303133;
line-height: 1.75;
word-break: break-word;
:deep(img) {
max-width: 100%;
height: auto;
}
:deep(table) {
width: 100% !important;
border-collapse: collapse;
display: block;
overflow-x: auto;
}
:deep(td),
:deep(th) {
border: 1px solid #dcdfe6;
padding: 8px 10px;
}
:deep(p) {
margin: 0 0 12px;
}
} }
.competition-header { .competition-header {
...@@ -217,6 +259,19 @@ useEventListener(window, 'message', async (event) => { ...@@ -217,6 +259,19 @@ useEventListener(window, 'message', async (event) => {
align-items: flex-end; align-items: flex-end;
} }
@media (max-width: 767px) {
.iframe-box {
min-height: 65vh;
margin-top: 12px;
}
.competition-header {
gap: 8px;
align-items: center;
flex-direction: row;
}
}
.welcome-box-header-content { .welcome-box-header-content {
width: 100%; width: 100%;
max-width: 1000px; max-width: 1000px;
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论