Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-lab
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-lab
Commits
290131a3
提交
290131a3
authored
7月 03, 2026
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: 优化移动端显示
上级
856de07b
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
114 行增加
和
8 行删除
+114
-8
DragPanel.vue
src/components/DragPanel.vue
+43
-3
api.ts
src/modules/admin/lab/experiment/api.ts
+1
-0
CompetitionRuleDialog.vue
...admin/lab/experiment/components/CompetitionRuleDialog.vue
+10
-1
useCompetition.ts
src/modules/student/lab/composables/useCompetition.ts
+1
-0
Competition.vue
src/modules/student/lab/views/Competition.vue
+59
-4
没有找到文件。
src/components/DragPanel.vue
浏览文件 @
290131a3
...
@@ -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%
;
...
...
src/modules/admin/lab/experiment/api.ts
浏览文件 @
290131a3
...
@@ -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
)
}
}
src/modules/admin/lab/experiment/components/CompetitionRuleDialog.vue
浏览文件 @
290131a3
...
@@ -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=
"
8
00px"
v-model=
"dialogVisible"
append-to-body
>
<el-dialog
title=
"编辑大赛规则"
:close-on-click-modal=
"false"
width=
"
10
00px"
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%"
>
...
...
src/modules/student/lab/composables/useCompetition.ts
浏览文件 @
290131a3
...
@@ -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
()
{
...
...
src/modules/student/lab/views/Competition.vue
浏览文件 @
290131a3
...
@@ -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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论