Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-lab
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-lab
Commits
ac045689
提交
ac045689
authored
7月 01, 2026
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 页面响应式设计
上级
608dd550
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
78 个修改的文件
包含
1839 行增加
和
228 行删除
+1839
-228
base.css
src/assets/styles/base.css
+15
-0
DragPanel.vue
src/components/DragPanel.vue
+26
-3
Preview.vue
src/components/Preview.vue
+57
-2
AppList.vue
src/components/base/AppList.vue
+0
-0
Aside.vue
src/components/layout/Aside.vue
+13
-0
Footer.vue
src/components/layout/Footer.vue
+3
-0
Header.vue
src/components/layout/Header.vue
+84
-1
Index.vue
src/components/layout/Index.vue
+25
-6
Main.vue
src/components/layout/Main.vue
+3
-0
ImportExamDialog.vue
...dules/admin/contest/check/components/ImportExamDialog.vue
+18
-4
ImportScoreDialog.vue
...ules/admin/contest/check/components/ImportScoreDialog.vue
+18
-4
ReportDialog.vue
src/modules/admin/contest/check/components/ReportDialog.vue
+46
-9
ScoreDialog.vue
src/modules/admin/contest/check/components/ScoreDialog.vue
+82
-2
ScoreViewPicturesDialog.vue
...dmin/contest/check/components/ScoreViewPicturesDialog.vue
+17
-1
SyncExamDialog.vue
...modules/admin/contest/check/components/SyncExamDialog.vue
+64
-4
ViewLiveDialog.vue
...modules/admin/contest/check/components/ViewLiveDialog.vue
+1
-0
Detail.vue
src/modules/admin/contest/check/views/Detail.vue
+33
-4
ImportDialog.vue
...les/admin/contest/contestants/components/ImportDialog.vue
+1
-1
Index.vue
src/modules/admin/contest/dashboard/views/Index.vue
+5
-3
DiscussItem.vue
src/modules/admin/contest/discuss/components/DiscussItem.vue
+7
-0
ImportDialog.vue
...modules/admin/contest/experts/components/ImportDialog.vue
+1
-1
FormDialog copy.vue
...odules/admin/contest/items/components/FormDialog copy.vue
+5
-5
FormDialog.vue
src/modules/admin/contest/items/components/FormDialog.vue
+5
-5
ViewExperimentFormDialog.vue
...min/contest/items/components/ViewExperimentFormDialog.vue
+1
-1
Edit.vue
src/modules/admin/contest/items/views/Edit.vue
+2
-1
View.vue
src/modules/admin/contest/items/views/View.vue
+2
-1
ScorePublishDialog.vue
...les/admin/contest/score/components/ScorePublishDialog.vue
+17
-5
index.ts
src/modules/admin/lab/book/index.ts
+0
-4
Index.vue
src/modules/admin/lab/book/views/Index.vue
+2
-0
Index.vue
src/modules/admin/lab/case-auth/views/Index.vue
+2
-2
index.ts
src/modules/admin/lab/case/index.ts
+0
-4
Index.vue
src/modules/admin/lab/case/views/Index.vue
+2
-0
History.vue
src/modules/admin/lab/dashboard/components/History.vue
+4
-4
Live.vue
src/modules/admin/lab/dashboard/components/Live.vue
+4
-4
DiscussItem.vue
src/modules/admin/lab/discuss/components/DiscussItem.vue
+7
-0
index.ts
src/modules/admin/lab/example/index.ts
+0
-4
CompetitionRuleDialog.vue
...admin/lab/experiment/components/CompetitionRuleDialog.vue
+82
-1
GradeRulesDialog.vue
...ules/admin/lab/experiment/components/GradeRulesDialog.vue
+136
-4
GroupQuestion.vue
...min/lab/experiment/components/Questions/GroupQuestion.vue
+2
-1
JourneyQuestion.vue
...n/lab/experiment/components/Questions/JourneyQuestion.vue
+2
-1
MaterialQuestion.vue
.../lab/experiment/components/Questions/MaterialQuestion.vue
+2
-1
TagQuestion.vue
...admin/lab/experiment/components/Questions/TagQuestion.vue
+2
-1
ReportDesignAttachment.vue
...dmin/lab/experiment/components/ReportDesignAttachment.vue
+4
-4
ReportDesignContent.vue
...s/admin/lab/experiment/components/ReportDesignContent.vue
+4
-4
ReportDesignPaper.vue
...les/admin/lab/experiment/components/ReportDesignPaper.vue
+4
-4
ReportDesignQuestion.vue
.../admin/lab/experiment/components/ReportDesignQuestion.vue
+4
-4
ReportPreview.vue
...modules/admin/lab/experiment/components/ReportPreview.vue
+10
-10
Questions.vue
src/modules/admin/lab/experiment/views/Questions.vue
+1
-0
Report.vue
src/modules/admin/lab/experiment/views/Report.vue
+5
-5
View.vue
src/modules/admin/lab/experiment/views/View.vue
+13
-0
ImportDialog.vue
src/modules/admin/lab/score/components/ImportDialog.vue
+1
-1
Question.vue
src/modules/admin/lab/score/components/Question.vue
+48
-1
ScoreDialog.vue
src/modules/admin/lab/score/components/ScoreDialog.vue
+119
-8
ScoreViewPicturesDialog.vue
...es/admin/lab/score/components/ScoreViewPicturesDialog.vue
+21
-1
Report.vue
src/modules/admin/lab/score/views/Report.vue
+94
-11
Index.vue
src/modules/admin/lab/video/views/Index.vue
+3
-0
Index.vue
src/modules/ai/views/Index.vue
+9
-3
Index.vue
src/modules/drawLots/views/Index.vue
+129
-4
AdminHome.vue
src/modules/home/components/AdminHome.vue
+24
-5
StudentHome.vue
src/modules/home/components/StudentHome.vue
+19
-5
TeacherHome.vue
src/modules/home/components/TeacherHome.vue
+24
-5
Total.vue
src/modules/home/components/Total.vue
+22
-0
Game.vue
src/modules/home/views/Game.vue
+16
-3
Index.vue
src/modules/register/views/Index.vue
+22
-9
DiscussItem.vue
src/modules/student/contest/components/DiscussItem.vue
+7
-0
Index.vue
src/modules/student/contest/views/Index.vue
+2
-0
Join.vue
src/modules/student/contest/views/Join.vue
+1
-1
Score.vue
src/modules/student/contest/views/Score.vue
+63
-5
BindCaptureDialog.vue
src/modules/student/lab/components/BindCaptureDialog.vue
+58
-1
DiscussItem.vue
src/modules/student/lab/components/DiscussItem.vue
+7
-0
Info.vue
src/modules/student/lab/components/Info.vue
+5
-5
ReportFilePreview.vue
src/modules/student/lab/components/ReportFilePreview.vue
+6
-6
ReportPreview.vue
src/modules/student/lab/components/ReportPreview.vue
+84
-10
Result.vue
src/modules/student/lab/components/Result.vue
+34
-0
ResultScoreDialog.vue
src/modules/student/lab/components/ResultScoreDialog.vue
+80
-7
Competition.vue
src/modules/student/lab/views/Competition.vue
+26
-1
Index.vue
src/modules/student/lab/views/Index.vue
+0
-0
Report.vue
src/modules/student/lab/views/Report.vue
+72
-11
没有找到文件。
src/assets/styles/base.css
浏览文件 @
ac045689
...
@@ -83,3 +83,18 @@ textarea:focus {
...
@@ -83,3 +83,18 @@ textarea:focus {
margin-right
:
0
!important
;
margin-right
:
0
!important
;
border-bottom
:
1px
solid
#e6e6e6
;
border-bottom
:
1px
solid
#e6e6e6
;
}
}
/* ========== 全局响应式 ========== */
img
,
video
{
max-width
:
100%
;
height
:
auto
;
}
@media
(
max-width
:
767px
)
{
.el-dialog
{
width
:
92%
!important
;
max-width
:
500px
;
margin-top
:
10vh
!important
;
}
.el-message-box
{
width
:
90%
!important
;
max-width
:
420px
;
}
.el-drawer
{
width
:
90%
!important
;
}
.el-form--inline
.el-form-item
{
margin-right
:
0
;
}
.el-table
{
font-size
:
13px
;
}
}
@media
(
min-width
:
768px
)
{
.hide-on-desktop
{
display
:
none
!important
;
}
}
@media
(
max-width
:
767px
)
{
.hide-on-mobile
{
display
:
none
!important
;
}
}
src/components/DragPanel.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
useStorage
}
from
'@vueuse/core'
import
{
use
MediaQuery
,
use
Storage
}
from
'@vueuse/core'
const
emit
=
defineEmits
<
{
const
emit
=
defineEmits
<
{
(
e
:
'resize'
):
void
(
e
:
'resize'
):
void
}
>
()
}
>
()
defineProps
<
{
isLeftShow
?:
boolean
}
>
()
defineProps
<
{
isLeftShow
?:
boolean
}
>
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
leftPanelVisible
=
$ref
<
boolean
>
(
true
)
const
leftPanelVisible
=
$ref
<
boolean
>
(
true
)
const
leftPanelWidth
=
useStorage
(
'leftPanelWidth'
,
400
)
const
leftPanelWidth
=
useStorage
(
'leftPanelWidth'
,
400
)
...
@@ -17,6 +18,7 @@ const leftPanelWidthText = $computed(() => {
...
@@ -17,6 +18,7 @@ const leftPanelWidthText = $computed(() => {
// 因为鼠标移动文档和iframe影响不能move
// 因为鼠标移动文档和iframe影响不能move
let
dragFlag
=
$ref
(
false
)
let
dragFlag
=
$ref
(
false
)
function
useDrag
()
{
function
useDrag
()
{
if
(
isMobile
.
value
)
return
const
dragDom
=
document
.
getElementById
(
'panel-resize'
)
const
dragDom
=
document
.
getElementById
(
'panel-resize'
)
if
(
dragDom
)
{
if
(
dragDom
)
{
dragDom
.
addEventListener
(
'mousedown'
,
(
e
)
=>
{
dragDom
.
addEventListener
(
'mousedown'
,
(
e
)
=>
{
...
@@ -47,8 +49,8 @@ onMounted(() => {
...
@@ -47,8 +49,8 @@ onMounted(() => {
<div
class=
"drag-panel-left-content"
>
<div
class=
"drag-panel-left-content"
>
<slot
name=
"left"
></slot>
<slot
name=
"left"
></slot>
</div>
</div>
<div
class=
"panel-resize"
id=
"panel-resize"
></div>
<div
class=
"panel-resize"
id=
"panel-resize"
v-if=
"!isMobile"
></div>
<div
class=
"panel-icon"
@
click=
"leftPanelVisible = !leftPanelVisible"
>
<div
class=
"panel-icon"
@
click=
"leftPanelVisible = !leftPanelVisible"
v-if=
"!isMobile"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 16 86"
aria-hidden=
"true"
width=
"16"
height=
"86"
>
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 16 86"
aria-hidden=
"true"
width=
"16"
height=
"86"
>
<g
fill=
"none"
fill-rule=
"evenodd"
>
<g
fill=
"none"
fill-rule=
"evenodd"
>
<path
<path
...
@@ -141,4 +143,25 @@ onMounted(() => {
...
@@ -141,4 +143,25 @@ onMounted(() => {
z-index
:
999
;
z-index
:
999
;
opacity
:
0
;
opacity
:
0
;
}
}
@media
(
max-width
:
767px
)
{
.drag-panel
{
flex-direction
:
column
;
height
:
auto
;
gap
:
12px
;
}
.drag-panel-left
{
width
:
100%
!
important
;
padding
:
12px
;
margin-right
:
0
;
}
.drag-panel-left-content
{
height
:
auto
;
overflow
:
visible
;
}
.drag-panel-right
{
width
:
100%
;
height
:
auto
;
min-width
:
0
;
}
}
</
style
>
</
style
>
src/components/Preview.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
useMediaQuery
}
from
'@vueuse/core'
interface
Props
{
interface
Props
{
url
:
string
url
:
string
}
}
const
props
=
defineProps
<
Props
>
()
const
props
=
defineProps
<
Props
>
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
// 文件扩展名
// 文件扩展名
const
fileExtensionName
=
$computed
(()
=>
{
const
fileExtensionName
=
$computed
(()
=>
{
return
props
.
url
.
split
(
'.'
).
pop
()
||
''
return
props
.
url
.
split
(
'.'
).
pop
()
||
''
})
})
const
isOfficeFile
=
$computed
(()
=>
{
return
[
'pptx'
,
'doc'
,
'docx'
,
'xls'
,
'xlsx'
].
includes
(
fileExtensionName
)
})
// office文件
// office文件
const
officeUrl
=
$computed
(()
=>
{
const
officeUrl
=
$computed
(()
=>
{
return
[
'pptx'
,
'doc'
,
'docx'
,
'xls'
,
'xlsx'
].
includes
(
fileExtensionName
)
return
isOfficeFile
?
`https://view.officeapps.live.com/op/view.aspx?src=
${
props
.
url
}
`
?
`https://view.officeapps.live.com/op/view.aspx?src=
${
props
.
url
}
`
:
''
:
''
})
})
const
fileName
=
$computed
(()
=>
{
const
[
path
]
=
props
.
url
.
split
(
'?'
)
return
decodeURIComponent
(
path
.
split
(
'/'
).
pop
()
||
'文档'
)
})
</
script
>
</
script
>
<
template
>
<
template
>
<iframe
allowfullscreen
:src=
"officeUrl"
:key=
"officeUrl"
frameborder=
"0"
style=
"width: 100%; height: 100%"
v-if=
"officeUrl"
></iframe>
<div
v-if=
"isMobile && officeUrl"
class=
"preview-mobile-office"
>
<div
class=
"preview-mobile-office__title"
>
{{
fileName
}}
</div>
<div
class=
"preview-mobile-office__desc"
>
移动端不内嵌 Office 文档预览,点击后在新页面打开
</div>
<a
:href=
"officeUrl"
target=
"_blank"
rel=
"noopener noreferrer"
class=
"preview-mobile-office__link"
>
打开文档
</a>
</div>
<iframe
allowfullscreen
:src=
"officeUrl"
:key=
"officeUrl"
frameborder=
"0"
style=
"width: 100%; height: 100%"
v-else-if=
"officeUrl"
></iframe>
<object
:data=
"url"
style=
"width: 100%; height: 100%; object-fit: none"
v-else
></object>
<object
:data=
"url"
style=
"width: 100%; height: 100%; object-fit: none"
v-else
></object>
</
template
>
</
template
>
<
style
lang=
"scss"
scoped
>
.preview-mobile-office
{
height
:
100%
;
min-height
:
240px
;
padding
:
24px
16px
;
background
:
#fff
;
border-radius
:
12px
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
text-align
:
center
;
}
.preview-mobile-office__title
{
font-size
:
16px
;
font-weight
:
600
;
line-height
:
24px
;
color
:
#333
;
word-break
:
break-word
;
}
.preview-mobile-office__desc
{
margin-top
:
8px
;
font-size
:
14px
;
line-height
:
22px
;
color
:
#666
;
}
.preview-mobile-office__link
{
margin-top
:
16px
;
min-width
:
120px
;
padding
:
10px
20px
;
border-radius
:
999px
;
background
:
var
(
--
main-color
);
color
:
#fff
;
line-height
:
20px
;
}
</
style
>
src/components/base/AppList.vue
浏览文件 @
ac045689
差异被折叠。
点击展开。
src/components/layout/Aside.vue
浏览文件 @
ac045689
...
@@ -82,6 +82,13 @@ function handleClick(path: string) {
...
@@ -82,6 +82,13 @@ function handleClick(path: string) {
flex
:
0
0
200px
;
flex
:
0
0
200px
;
box-sizing
:
content-box
;
box-sizing
:
content-box
;
}
}
// 移动端 overlay
.app-aside--overlay
{
position
:
fixed
;
top
:
0
;
left
:
0
;
bottom
:
0
;
z-index
:
2000
;
width
:
220px
;
flex
:
none
;
transform
:
translateX
(
-100%
);
transition
:
transform
0
.3s
ease
;
&
.app-aside--visible
{
transform
:
translateX
(
0
);
}
}
.nav
{
.nav
{
position
:
fixed
;
position
:
fixed
;
width
:
200px
;
width
:
200px
;
...
@@ -132,4 +139,10 @@ function handleClick(path: string) {
...
@@ -132,4 +139,10 @@ function handleClick(path: string) {
// border-radius: 8px;
// border-radius: 8px;
// }
// }
}
}
// 平板收缩
@media
(
max-width
:
1024px
)
{
.app-aside
:not
(
.app-aside--overlay
)
{
width
:
180px
;
flex
:
0
0
180px
;
}
.nav
{
width
:
180px
;
}
}
</
style
>
</
style
>
src/components/layout/Footer.vue
浏览文件 @
ac045689
...
@@ -17,4 +17,7 @@ export default { name: 'AppFooter' }
...
@@ -17,4 +17,7 @@ export default { name: 'AppFooter' }
text-align
:
center
;
text-align
:
center
;
background-color
:
#fff
;
background-color
:
#fff
;
}
}
@media
(
max-width
:
767px
)
{
.app-footer
{
padding
:
8px
12px
;
font-size
:
12px
;
line-height
:
20px
;
}
}
</
style
>
</
style
>
src/components/layout/Header.vue
浏览文件 @
ac045689
...
@@ -4,7 +4,7 @@ export default { name: 'AppHeader' }
...
@@ -4,7 +4,7 @@ export default { name: 'AppHeader' }
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
type
{
IMenuItem
}
from
'@/types'
import
type
{
IMenuItem
}
from
'@/types'
import
{
CaretBottom
}
from
'@element-plus/icons-vue'
import
{
CaretBottom
,
Expand
}
from
'@element-plus/icons-vue'
import
{
useUserStore
}
from
'@/stores/user'
import
{
useUserStore
}
from
'@/stores/user'
import
{
useMenuStore
}
from
'@/stores/menu'
import
{
useMenuStore
}
from
'@/stores/menu'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
...
@@ -12,6 +12,10 @@ const appConfig = useAppConfig()
...
@@ -12,6 +12,10 @@ const appConfig = useAppConfig()
const
route
=
useRoute
()
const
route
=
useRoute
()
const
router
=
useRouter
()
const
router
=
useRouter
()
const
mobileMenuVisible
=
ref
(
false
)
const
toggleMobileMenu
=
()
=>
{
mobileMenuVisible
.
value
=
!
mobileMenuVisible
.
value
}
const
closeMobileMenu
=
()
=>
{
mobileMenuVisible
.
value
=
false
}
const
userStore
=
useUserStore
()
const
userStore
=
useUserStore
()
const
userInfo
=
userStore
.
user
const
userInfo
=
userStore
.
user
...
@@ -60,6 +64,9 @@ function handleClick(path: string) {
...
@@ -60,6 +64,9 @@ function handleClick(path: string) {
<
template
>
<
template
>
<header
class=
"app-header"
>
<header
class=
"app-header"
>
<div
class=
"app-header-left"
>
<div
class=
"app-header-left"
>
<button
class=
"sidebar-toggle"
@
click=
"toggleMobileMenu"
>
<el-icon
:size=
"22"
><Expand
/></el-icon>
</button>
<template
v-if=
"appConfig.logo"
>
<template
v-if=
"appConfig.logo"
>
<div
class=
"logo"
>
<div
class=
"logo"
>
<router-link
to=
"/"
><img
:src=
"appConfig.logo"
/></router-link>
<router-link
to=
"/"
><img
:src=
"appConfig.logo"
/></router-link>
...
@@ -125,6 +132,28 @@ function handleClick(path: string) {
...
@@ -125,6 +132,28 @@ function handleClick(path: string) {
</el-dropdown>
</el-dropdown>
</div>
</div>
</header>
</header>
<el-drawer
v-model=
"mobileMenuVisible"
direction=
"ltr"
:size=
"260"
:with-header=
"false"
:z-index=
"2100"
>
<div
class=
"mobile-drawer"
>
<div
class=
"mobile-drawer-hd"
>
<img
v-if=
"appConfig.logo"
:src=
"appConfig.logo"
class=
"mobile-drawer-logo"
/>
<span
class=
"mobile-drawer-title"
>
{{ appConfig.title }}
</span>
</div>
<div
class=
"mobile-drawer-bd"
>
<
template
v-for=
"item in menus"
:key=
"item.path"
>
<div
class=
"mobile-nav-group"
v-permission=
"item.tag"
>
<div
class=
"mobile-nav-parent"
@
click=
"handleClick(item.path)"
>
{{
item
.
name
}}
</div>
<template
v-if=
"item.children"
>
<div
class=
"mobile-nav-child"
v-for=
"subitem in item.children"
:key=
"subitem.path"
v-permission=
"subitem.tag"
:class=
"
{ 'is-active': route.path.includes(subitem.path) }"
@click="handleClick(subitem.path); closeMobileMenu()">
{{
subitem
.
name
}}
</div>
</
template
>
</div>
</template>
</div>
</div>
</el-drawer>
</template>
</template>
<
style
lang=
"scss"
>
<
style
lang=
"scss"
>
...
@@ -280,4 +309,58 @@ function handleClick(path: string) {
...
@@ -280,4 +309,58 @@ function handleClick(path: string) {
.app-header-user-buttons
{
.app-header-user-buttons
{
padding-top
:
16px
;
padding-top
:
16px
;
}
}
// ========== 响应式 ==========
.sidebar-toggle
{
display
:
none
;
align-items
:
center
;
justify-content
:
center
;
width
:
36px
;
height
:
36px
;
margin-right
:
12px
;
border
:
none
;
border-radius
:
6px
;
background
:
transparent
;
color
:
#333
;
cursor
:
pointer
;
flex-shrink
:
0
;
&
:hover
{
background
:
#f0f0f0
;
}
}
// 平板 (≤1024px)
@media
(
max-width
:
1024px
)
{
.app-header
{
padding
:
0
12px
;
}
.app-header-left
.app-name
{
font-size
:
22px
;
}
.app-header-nav
{
margin
:
0
20px
;
--el-menu-item-font-size
:
14px
;
.el-menu--horizontal
>
.el-menu-item
{
margin-right
:
24px
;
}
}
}
// 移动端 (≤767px)
@media
(
max-width
:
767px
)
{
.sidebar-toggle
{
display
:
flex
;
}
.app-header
{
padding
:
0
12px
;
height
:
52px
;
}
.app-header-left
{
.logo
{
height
:
32px
;
}
.line
{
margin
:
0
10px
;
height
:
22px
;
}
.app-name
{
font-size
:
16px
;
line-height
:
22px
;
}
}
.app-header-nav
{
display
:
none
;
}
.app-header-right
.user
{
height
:
36px
;
p
{
display
:
none
;
}
}
.app-header-right
.avatar
{
width
:
32px
;
height
:
32px
;
}
}
// 移动端抽屉
.mobile-drawer
{
display
:
flex
;
flex-direction
:
column
;
height
:
100%
;
}
.mobile-drawer-hd
{
display
:
flex
;
align-items
:
center
;
gap
:
10px
;
padding
:
16px
;
border-bottom
:
1px
solid
#eee
;
}
.mobile-drawer-logo
{
height
:
36px
;
}
.mobile-drawer-title
{
font-size
:
18px
;
font-weight
:
600
;
color
:
#333
;
}
.mobile-drawer-bd
{
flex
:
1
;
overflow-y
:
auto
;
padding
:
8px
0
;
}
.mobile-nav-group
{
border-bottom
:
1px
solid
#f5f5f5
;
&
:last-child
{
border-bottom
:
none
;
}
}
.mobile-nav-parent
{
padding
:
14px
20px
;
font-size
:
15px
;
font-weight
:
600
;
color
:
#333
;
cursor
:
pointer
;
&
:active
{
background
:
#f5f5f5
;
}
}
.mobile-nav-child
{
padding
:
12px
20px
12px
36px
;
font-size
:
14px
;
color
:
#666
;
cursor
:
pointer
;
border-top
:
1px
solid
#fafafa
;
&
:active
{
background
:
#f5f5f5
;
}
&
.is-active
{
color
:
var
(
--
main-color
);
background
:
#fef5f7
;
}
}
</
style
>
</
style
>
src/components/layout/Index.vue
浏览文件 @
ac045689
...
@@ -7,20 +7,30 @@ import AppHeader from './Header.vue'
...
@@ -7,20 +7,30 @@ import AppHeader from './Header.vue'
import
AppAside
from
'./Aside.vue'
import
AppAside
from
'./Aside.vue'
import
AppMain
from
'./Main.vue'
import
AppMain
from
'./Main.vue'
import
AppFooter
from
'./Footer.vue'
import
AppFooter
from
'./Footer.vue'
import
{
useMediaQuery
}
from
'@vueuse/core'
withDefaults
(
defineProps
<
{
sidebar
?:
boolean
;
footer
?:
boolean
;
header
?:
boolean
}
>
(),
{
const
props
=
withDefaults
(
defineProps
<
{
sidebar
?:
boolean
;
footer
?:
boolean
;
header
?:
boolean
}
>
(),
{
header
:
true
,
header
:
true
,
sidebar
:
false
,
sidebar
:
false
,
footer
:
false
footer
:
false
})
})
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
sidebarVisible
=
ref
(
false
)
const
closeSidebar
=
()
=>
{
sidebarVisible
.
value
=
false
}
const
showOverlaySidebar
=
computed
(()
=>
isMobile
.
value
&&
sidebarVisible
.
value
&&
props
.
sidebar
)
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"app-layout"
>
<div
class=
"app-layout"
:class=
"
{ 'app-layout--mobile': isMobile }"
>
<AppHeader
v-if=
"header"
></AppHeader>
<AppHeader
v-if=
"header"
></AppHeader>
<div
class=
"app-layout-container"
>
<div
class=
"app-layout-container"
>
<AppAside
v-if=
"sidebar"
></AppAside>
<div
v-if=
"showOverlaySidebar"
class=
"sidebar-overlay"
@
click=
"closeSidebar"
></div>
<AppMain></AppMain>
<AppAside
v-if=
"sidebar"
:class=
"
{ 'app-aside--overlay': isMobile, 'app-aside--visible': sidebarVisible }">
</AppAside>
<AppMain
@
click=
"closeSidebar"
></AppMain>
</div>
</div>
<AppFooter
v-if=
"footer"
></AppFooter>
<AppFooter
v-if=
"footer"
></AppFooter>
</div>
</div>
...
@@ -28,7 +38,6 @@ withDefaults(defineProps<{ sidebar?: boolean; footer?: boolean; header?: boolean
...
@@ -28,7 +38,6 @@ withDefaults(defineProps<{ sidebar?: boolean; footer?: boolean; header?: boolean
<
style
lang=
"scss"
>
<
style
lang=
"scss"
>
.app-layout
{
.app-layout
{
min-width
:
1000px
;
min-height
:
100vh
;
min-height
:
100vh
;
margin
:
0
auto
;
margin
:
0
auto
;
background-color
:
#ecf2f7
;
background-color
:
#ecf2f7
;
...
@@ -36,8 +45,18 @@ withDefaults(defineProps<{ sidebar?: boolean; footer?: boolean; header?: boolean
...
@@ -36,8 +45,18 @@ withDefaults(defineProps<{ sidebar?: boolean; footer?: boolean; header?: boolean
flex-direction
:
column
;
flex-direction
:
column
;
}
}
.app-layout-container
{
.app-layout-container
{
// min-height: calc(100vh - 66px);
flex
:
1
;
flex
:
1
;
display
:
flex
;
display
:
flex
;
position
:
relative
;
}
.sidebar-overlay
{
display
:
none
;
}
.app-layout--mobile
.sidebar-overlay
{
display
:
block
;
position
:
fixed
;
inset
:
0
;
background
:
rgba
(
0
,
0
,
0
,
0
.45
);
z-index
:
1999
;
}
}
</
style
>
</
style
>
src/components/layout/Main.vue
浏览文件 @
ac045689
...
@@ -16,6 +16,7 @@ export default { name: 'AppMain' }
...
@@ -16,6 +16,7 @@ export default { name: 'AppMain' }
flex
:
1
;
flex
:
1
;
padding
:
20px
;
padding
:
20px
;
overflow
:
hidden
;
overflow
:
hidden
;
min-width
:
0
;
}
}
.app-main-inner
{
.app-main-inner
{
height
:
100%
;
height
:
100%
;
...
@@ -26,4 +27,6 @@ export default { name: 'AppMain' }
...
@@ -26,4 +27,6 @@ export default { name: 'AppMain' }
display
:
table
;
display
:
table
;
clear
:
both
;
clear
:
both
;
}
}
@media
(
max-width
:
1024px
)
{
.app-main
{
padding
:
16px
;
}
}
@media
(
max-width
:
767px
)
{
.app-main
{
padding
:
12px
;
}
}
</
style
>
</
style
>
src/modules/admin/contest/check/components/ImportExamDialog.vue
浏览文件 @
ac045689
...
@@ -39,12 +39,12 @@ watchEffect(() => {
...
@@ -39,12 +39,12 @@ watchEffect(() => {
<
template
>
<
template
>
<el-dialog
title=
"批量导入考试成绩"
:close-on-click-modal=
"false"
width=
"400px"
>
<el-dialog
title=
"批量导入考试成绩"
:close-on-click-modal=
"false"
width=
"400px"
>
<el-form
label-width=
"70px"
>
<el-form
label-width=
"70px"
class=
"import-form"
>
<el-form-item
label=
"赛项名称"
>
<el-form-item
label=
"赛项名称"
>
<el-select
v-model=
"form.competition_id"
>
<el-select
v-model=
"form.competition_id"
class=
"import-form__select"
>
<el-option
v-for=
"item in competitions"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
<el-option
v-for=
"item in competitions"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-select>
</el-select>
<a
:href=
"templateUrl"
download
style=
"margin-left: 10px
"
v-if=
"templateUrl"
>
下载模板
</a>
<a
:href=
"templateUrl"
download
class=
"import-form__link
"
v-if=
"templateUrl"
>
下载模板
</a>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
<el-button
...
@@ -53,10 +53,24 @@ watchEffect(() => {
...
@@ -53,10 +53,24 @@ watchEffect(() => {
:icon=
"Upload"
:icon=
"Upload"
@
click=
"handleImport"
@
click=
"handleImport"
:disabled=
"!form.competition_id"
:disabled=
"!form.competition_id"
style=
"width: 195px"
style=
"width: 1
00%; max-width: 1
95px"
>
本地上传
</el-button
>
本地上传
</el-button
>
>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
</el-dialog>
</el-dialog>
</
template
>
</
template
>
<
style
scoped
>
@media
(
max-width
:
767px
)
{
.import-form
:deep
(
.el-form-item__content
)
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
stretch
;
gap
:
8px
;
}
.import-form__select
{
width
:
100%
;
}
}
</
style
>
src/modules/admin/contest/check/components/ImportScoreDialog.vue
浏览文件 @
ac045689
...
@@ -39,12 +39,12 @@ watchEffect(() => {
...
@@ -39,12 +39,12 @@ watchEffect(() => {
<
template
>
<
template
>
<el-dialog
title=
"批量导入完整评分"
:close-on-click-modal=
"false"
width=
"400px"
>
<el-dialog
title=
"批量导入完整评分"
:close-on-click-modal=
"false"
width=
"400px"
>
<el-form
label-width=
"70px"
>
<el-form
label-width=
"70px"
class=
"import-form"
>
<el-form-item
label=
"赛项名称"
>
<el-form-item
label=
"赛项名称"
>
<el-select
v-model=
"form.competition_id"
>
<el-select
v-model=
"form.competition_id"
class=
"import-form__select"
>
<el-option
v-for=
"item in competitions"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
<el-option
v-for=
"item in competitions"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
></el-option>
</el-select>
</el-select>
<a
:href=
"templateUrl"
download
style=
"margin-left: 10px
"
v-if=
"templateUrl"
>
下载模板
</a>
<a
:href=
"templateUrl"
download
class=
"import-form__link
"
v-if=
"templateUrl"
>
下载模板
</a>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
<el-button
...
@@ -53,10 +53,24 @@ watchEffect(() => {
...
@@ -53,10 +53,24 @@ watchEffect(() => {
:icon=
"Upload"
:icon=
"Upload"
@
click=
"handleImport"
@
click=
"handleImport"
:disabled=
"!form.competition_id"
:disabled=
"!form.competition_id"
style=
"width: 195px"
style=
"width: 1
00%; max-width: 1
95px"
>
本地上传
</el-button
>
本地上传
</el-button
>
>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
</el-dialog>
</el-dialog>
</
template
>
</
template
>
<
style
scoped
>
@media
(
max-width
:
767px
)
{
.import-form
:deep
(
.el-form-item__content
)
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
stretch
;
gap
:
8px
;
}
.import-form__select
{
width
:
100%
;
}
}
</
style
>
src/modules/admin/contest/check/components/ReportDialog.vue
浏览文件 @
ac045689
...
@@ -26,15 +26,15 @@ const getUrl = (url: string) => {
...
@@ -26,15 +26,15 @@ const getUrl = (url: string) => {
<
template
>
<
template
>
<el-dialog
title=
"查看报告"
width=
"500px"
>
<el-dialog
title=
"查看报告"
width=
"500px"
>
<ul>
<ul
class=
"report-list"
>
<li
v-for=
"item in reportList"
:key=
"item.id"
style=
"line-height: 24px
"
>
<li
v-for=
"item in reportList"
:key=
"item.id"
class=
"report-list__item
"
>
<
a
:href=
"getUrl(item.url)"
target=
"_blank"
>
<
div
class=
"report-list__name"
>
{{
item
.
name
}}
</div
>
{{
item
.
name
}}
<div
class=
"report-list__actions"
>
<
el-button
size=
"small"
type=
"primary"
style=
"margin-left: 10px"
>
查看
</el-button
>
<
a
:href=
"getUrl(item.url)"
target=
"_blank"
>
</a
>
<el-button
size=
"small"
type=
"primary"
>
查看
</el-button
>
<el-button
size=
"small"
type=
"primary"
style=
"margin-left: 10px"
@
click=
"saveAs(item.url, item.name)"
</a>
>
下载
</el-button
<el-button
size=
"small"
type=
"primary"
@
click=
"saveAs(item.url, item.name)"
>
下载
</el-button>
>
</div
>
</li>
</li>
</ul>
</ul>
<template
#
footer
>
<template
#
footer
>
...
@@ -44,3 +44,40 @@ const getUrl = (url: string) => {
...
@@ -44,3 +44,40 @@ const getUrl = (url: string) => {
</
template
>
</
template
>
</el-dialog>
</el-dialog>
</template>
</template>
<
style
scoped
>
.report-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.report-list__item
{
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
12px
14px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
}
.report-list__name
{
min-width
:
0
;
line-height
:
1.6
;
word-break
:
break-word
;
}
.report-list__actions
{
display
:
flex
;
gap
:
8px
;
flex-shrink
:
0
;
}
@media
(
max-width
:
767px
)
{
.report-list__item
{
flex-direction
:
column
;
align-items
:
stretch
;
}
.report-list__actions
{
justify-content
:
flex-end
;
flex-wrap
:
wrap
;
}
}
</
style
>
src/modules/admin/contest/check/components/ScoreDialog.vue
浏览文件 @
ac045689
...
@@ -2,10 +2,12 @@
...
@@ -2,10 +2,12 @@
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
{
ArrowDown
}
from
'@element-plus/icons-vue'
import
{
ArrowDown
}
from
'@element-plus/icons-vue'
import
{
usePrecision
}
from
'@vueuse/math'
import
{
usePrecision
}
from
'@vueuse/math'
import
{
useMediaQuery
}
from
'@vueuse/core'
import
type
{
ReportItem
}
from
'../types'
import
type
{
ReportItem
}
from
'../types'
import
{
submitScore
}
from
'../api'
import
{
submitScore
}
from
'../api'
defineProps
<
{
reportList
:
ReportItem
[]
}
>
()
defineProps
<
{
reportList
:
ReportItem
[]
}
>
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
emit
=
defineEmits
<
{
const
emit
=
defineEmits
<
{
(
e
:
'update'
):
void
(
e
:
'update'
):
void
...
@@ -76,7 +78,7 @@ const handleScoreRule = function () {
...
@@ -76,7 +78,7 @@ const handleScoreRule = function () {
<el-form-item
label=
"赛项名称"
>
{{
detail
.
competition_id_name
}}
</el-form-item>
<el-form-item
label=
"赛项名称"
>
{{
detail
.
competition_id_name
}}
</el-form-item>
<el-form-item
label=
"选手姓名"
>
{{
detail
.
student_name
}}
</el-form-item>
<el-form-item
label=
"选手姓名"
>
{{
detail
.
student_name
}}
</el-form-item>
<el-form-item
label=
"选手ID"
>
{{
detail
.
login_id
}}
</el-form-item>
<el-form-item
label=
"选手ID"
>
{{
detail
.
login_id
}}
</el-form-item>
<div
style=
"display: flex; justify-content: space-between
"
>
<div
class=
"score-dialog-toolbar
"
>
<el-form-item
label=
"报告"
v-if=
"reportList.length"
>
<el-form-item
label=
"报告"
v-if=
"reportList.length"
>
<el-dropdown>
<el-dropdown>
<el-button
text
>
<el-button
text
>
...
@@ -94,7 +96,31 @@ const handleScoreRule = function () {
...
@@ -94,7 +96,31 @@ const handleScoreRule = function () {
<el-button
type=
"primary"
style=
"margin-bottom: 20px"
@
click=
"handleScoreRule"
>
查看评分规则
</el-button>
<el-button
type=
"primary"
style=
"margin-bottom: 20px"
@
click=
"handleScoreRule"
>
查看评分规则
</el-button>
</div>
</div>
</el-form>
</el-form>
<el-table
:data=
"tableList"
:header-cell-style=
"{ background: '#ededed' }"
>
<div
v-if=
"isMobile"
class=
"score-card-list"
>
<div
class=
"score-card"
v-for=
"row in tableList"
:key=
"row.id"
>
<div
class=
"score-card__row"
><span>
评分规则
</span><strong>
{{ row.name || '-' }}
</strong></div>
<div
class=
"score-card__row"
><span>
评分方法
</span><strong>
{{ row.type_name || '-' }}
</strong></div>
<div
class=
"score-card__row"
><span>
分值
</span><strong>
{{ row.old_score || '-' }}
</strong></div>
<div
class=
"score-card__row"
><span>
占比(%)
</span><strong>
{{ row.ratio || '-' }}
</strong></div>
<div
class=
"score-card__row score-card__row--field"
>
<span>
评分
</span>
<div
class=
"score-card__field"
>
<el-input-number
:disabled=
"row.type === '2'"
:controls=
"false"
v-model=
"row.score"
step-strictly
:step=
"0.1"
:min=
"0"
:max=
"row.old_score"
style=
"width: 100%"
placeholder=
"--"
/>
</div>
</div>
</div>
</div>
<el-table
v-else
:data=
"tableList"
:header-cell-style=
"{ background: '#ededed' }"
>
<el-table-column
label=
"评分规则"
prop=
"name"
align=
"center"
></el-table-column>
<el-table-column
label=
"评分规则"
prop=
"name"
align=
"center"
></el-table-column>
<el-table-column
label=
"评分方法"
prop=
"type_name"
align=
"center"
></el-table-column>
<el-table-column
label=
"评分方法"
prop=
"type_name"
align=
"center"
></el-table-column>
<el-table-column
label=
"分值"
prop=
"old_score"
align=
"center"
></el-table-column>
<el-table-column
label=
"分值"
prop=
"old_score"
align=
"center"
></el-table-column>
...
@@ -146,4 +172,58 @@ const handleScoreRule = function () {
...
@@ -146,4 +172,58 @@ const handleScoreRule = function () {
color
:
var
(
--
main-color
);
color
:
var
(
--
main-color
);
}
}
}
}
.score-dialog-toolbar
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
}
.score-card-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.score-card
{
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
}
.score-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
}
.score-card__row
:last-of-type
{
border-bottom
:
none
;
}
.score-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.score-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
word-break
:
break-word
;
}
.score-card__row--field
{
align-items
:
center
;
}
.score-card__field
{
width
:
120px
;
max-width
:
100%
;
}
@media
(
max-width
:
767px
)
{
.score-dialog-toolbar
{
flex-direction
:
column
;
align-items
:
flex-start
;
}
.result
{
padding
:
24px
0
;
span
{
font-size
:
30px
;
}
}
}
</
style
>
</
style
>
src/modules/admin/contest/check/components/ScoreViewPicturesDialog.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
type
{
RecordItem
,
FileItem
}
from
'../types'
import
type
{
RecordItem
,
FileItem
}
from
'../types'
import
{
useMediaQuery
}
from
'@vueuse/core'
interface
Props
{
interface
Props
{
data
:
RecordItem
data
:
RecordItem
}
}
const
props
=
defineProps
<
Props
>
()
const
props
=
defineProps
<
Props
>
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
// 实验过程截图
// 实验过程截图
const
pictures
=
$computed
<
FileItem
[]
>
(()
=>
{
const
pictures
=
$computed
<
FileItem
[]
>
(()
=>
{
...
@@ -24,7 +26,7 @@ const srcList = computed(() => {
...
@@ -24,7 +26,7 @@ const srcList = computed(() => {
<
template
>
<
template
>
<el-dialog
title=
"查看实验截图"
width=
"800px"
append-to-body
>
<el-dialog
title=
"查看实验截图"
width=
"800px"
append-to-body
>
<ul
class=
"picture-list"
>
<ul
class=
"picture-list"
:class=
"
{ 'picture-list--mobile': isMobile }"
>
<li
v-for=
"(item, index) in pictures"
:key=
"item.url"
>
<li
v-for=
"(item, index) in pictures"
:key=
"item.url"
>
<p
class=
"t1"
>
<p
class=
"t1"
>
<el-image
style=
"width: 100%"
:src=
"item.url"
:preview-src-list=
"srcList"
:initial-index=
"index"
/>
<el-image
style=
"width: 100%"
:src=
"item.url"
:preview-src-list=
"srcList"
:initial-index=
"index"
/>
...
@@ -45,6 +47,7 @@ const srcList = computed(() => {
...
@@ -45,6 +47,7 @@ const srcList = computed(() => {
width
:
100%
;
width
:
100%
;
li
{
li
{
line-height
:
30px
;
line-height
:
30px
;
margin-bottom
:
16px
;
}
}
a
{
a
{
color
:
var
(
--
main-color
);
color
:
var
(
--
main-color
);
...
@@ -53,4 +56,17 @@ const srcList = computed(() => {
...
@@ -53,4 +56,17 @@ const srcList = computed(() => {
text-align
:
center
;
text-align
:
center
;
}
}
}
}
.picture-list--mobile
{
li
{
padding
:
12px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
}
.t2
{
margin-top
:
8px
;
font-size
:
13px
;
color
:
#909399
;
}
}
</
style
>
</
style
>
src/modules/admin/contest/check/components/SyncExamDialog.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
{
useMediaQuery
}
from
'@vueuse/core'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useFilterList
}
from
'../composables/useFilterList'
import
{
useFilterList
}
from
'../composables/useFilterList'
import
{
syncExam
}
from
'../api'
import
{
syncExam
}
from
'../api'
...
@@ -10,6 +11,7 @@ const emit = defineEmits<{
...
@@ -10,6 +11,7 @@ const emit = defineEmits<{
// 评分方法
// 评分方法
const
scoreMethods
=
useMapStore
().
getMapValuesByKey
(
'scoring_manner'
)
const
scoreMethods
=
useMapStore
().
getMapValuesByKey
(
'scoring_manner'
)
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
{
competitions
}
=
useFilterList
(
1
)
const
{
competitions
}
=
useFilterList
(
1
)
const
form
=
reactive
<
any
>
({
const
form
=
reactive
<
any
>
({
...
@@ -30,16 +32,25 @@ function scoreMethodText(value: string) {
...
@@ -30,16 +32,25 @@ function scoreMethodText(value: string) {
<
template
>
<
template
>
<el-dialog
title=
"同步1+同步线上考试成绩"
:close-on-click-modal=
"false"
>
<el-dialog
title=
"同步1+同步线上考试成绩"
:close-on-click-modal=
"false"
>
<el-form>
<el-form
class=
"sync-form"
>
<el-form-item
label=
"赛项名称"
>
<el-form-item
label=
"赛项名称"
>
<el-select
v-model=
"form.competition"
value-key=
"id"
>
<el-select
v-model=
"form.competition"
value-key=
"id"
class=
"sync-form__select"
>
<el-option
v-for=
"item in competitions"
:key=
"item.id"
:label=
"item.name"
:value=
"item"
></el-option>
<el-option
v-for=
"item in competitions"
:key=
"item.id"
:label=
"item.name"
:value=
"item"
></el-option>
</el-select>
</el-select>
<el-button
type=
"primary"
:disabled=
"!form.competition"
@
click=
"handleSync"
>
一键同步成绩
</el-button>
<el-button
type=
"primary"
:disabled=
"!form.competition"
@
click=
"handleSync"
>
一键同步成绩
</el-button>
</el-form-item>
</el-form-item>
</el-form>
</el-form>
<el-table
:data=
"form.competition?.rules"
>
<div
v-if=
"isMobile"
class=
"sync-card-list"
>
<div
class=
"sync-card"
v-for=
"row in form.competition?.rules || []"
:key=
"row.id || row.exam_name"
>
<div
class=
"sync-card__row"
><span>
评分方法
</span><strong>
{{
scoreMethodText
(
row
.
type
)
}}
</strong></div>
<div
class=
"sync-card__row"
><span>
考试名称
</span><strong>
{{
row
.
exam_name
||
'-'
}}
</strong></div>
<div
class=
"sync-card__row"
><span>
实考人数/应考人数
</span><strong>
{{
row
.
finish_count
}}
/
{{
row
.
all_count
}}
</strong></div>
<div
class=
"sync-card__actions"
>
<el-button
round
type=
"primary"
@
click=
"handleSync(row)"
>
同步导入成绩
</el-button>
</div>
</div>
</div>
<el-table
v-else
:data=
"form.competition?.rules"
>
<el-table-column
label=
"评分方法"
prop=
"type"
align=
"center"
width=
"200"
>
<el-table-column
label=
"评分方法"
prop=
"type"
align=
"center"
width=
"200"
>
<template
#
default=
"
{ row }">
{{
scoreMethodText
(
row
.
type
)
}}
</
template
>
<template
#
default=
"
{ row }">
{{
scoreMethodText
(
row
.
type
)
}}
</
template
>
</el-table-column>
</el-table-column>
...
@@ -55,3 +66,52 @@ function scoreMethodText(value: string) {
...
@@ -55,3 +66,52 @@ function scoreMethodText(value: string) {
</el-table>
</el-table>
</el-dialog>
</el-dialog>
</template>
</template>
<
style
scoped
>
.sync-card-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.sync-card
{
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
}
.sync-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
}
.sync-card__row
:last-of-type
{
border-bottom
:
none
;
}
.sync-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.sync-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
word-break
:
break-word
;
}
.sync-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
10px
;
}
@media
(
max-width
:
767px
)
{
.sync-form
:deep
(
.el-form-item__content
)
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
stretch
;
gap
:
10px
;
}
.sync-form__select
{
width
:
100%
;
}
}
</
style
>
src/modules/admin/contest/check/components/ViewLiveDialog.vue
浏览文件 @
ac045689
...
@@ -55,6 +55,7 @@ const listOptions = $computed(() => {
...
@@ -55,6 +55,7 @@ const listOptions = $computed(() => {
},
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
130
},
{
label
:
'操作'
,
slots
:
'table-x'
,
width
:
130
},
],
],
mobileCards
:
true
,
}
}
})
})
const
handleViewLive
=
function
(
row
:
any
)
{
const
handleViewLive
=
function
(
row
:
any
)
{
...
...
src/modules/admin/contest/check/views/Detail.vue
浏览文件 @
ac045689
...
@@ -75,7 +75,7 @@ function handleResize() {
...
@@ -75,7 +75,7 @@ function handleResize() {
</
template
>
</
template
>
<
template
#
right
v-if=
"detail"
>
<
template
#
right
v-if=
"detail"
>
<AppCard>
<AppCard>
<el-row
justify=
"space-between"
>
<el-row
justify=
"space-between"
class=
"detail-toolbar"
>
<div
class=
"info"
>
<div
class=
"info"
>
<p>
<p>
赛项名称:
<span>
{{
detail
.
competition_id_name
}}
</span>
赛项名称:
<span>
{{
detail
.
competition_id_name
}}
</span>
...
@@ -87,11 +87,11 @@ function handleResize() {
...
@@ -87,11 +87,11 @@ function handleResize() {
选手ID:
<span>
{{
detail
.
login_id
}}
</span>
选手ID:
<span>
{{
detail
.
login_id
}}
</span>
</p>
</p>
</div>
</div>
<div>
<div
class=
"detail-toolbar__actions"
>
<el-select
v-model=
"platformUrl"
>
<el-select
v-model=
"platformUrl"
class=
"detail-toolbar__select"
>
<el-option
v-for=
"item in platformList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.url"
></el-option>
<el-option
v-for=
"item in platformList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.url"
></el-option>
</el-select>
</el-select>
<el-dropdown
style=
"margin: 0 10px
"
>
<el-dropdown
class=
"detail-toolbar__dropdown
"
>
<el-button
plain
>
<el-button
plain
>
查看报告
<el-icon
class=
"el-icon--right"
><arrow-down
/></el-icon>
查看报告
<el-icon
class=
"el-icon--right"
><arrow-down
/></el-icon>
</el-button>
</el-button>
...
@@ -169,4 +169,33 @@ function handleResize() {
...
@@ -169,4 +169,33 @@ function handleResize() {
margin-right
:
40px
;
margin-right
:
40px
;
}
}
}
}
.detail-toolbar__actions
{
display
:
flex
;
align-items
:
center
;
gap
:
10px
;
flex-wrap
:
wrap
;
}
@media
(
max-width
:
767px
)
{
.detail-toolbar
{
gap
:
12px
;
}
.info
{
width
:
100%
;
p
{
margin-right
:
0
;
width
:
100%
;
line-height
:
1
.6
;
word-break
:
break-word
;
}
}
.detail-toolbar__actions
{
width
:
100%
;
}
.detail-toolbar__select
{
width
:
100%
;
}
.detail-toolbar__dropdown
{
margin
:
0
!
important
;
}
}
</
style
>
</
style
>
src/modules/admin/contest/contestants/components/ImportDialog.vue
浏览文件 @
ac045689
...
@@ -50,7 +50,7 @@ watchEffect(() => {
...
@@ -50,7 +50,7 @@ watchEffect(() => {
align-items
:
center
;
align-items
:
center
;
justify-content
:
center
;
justify-content
:
center
;
.el-button
{
.el-button
{
width
:
220px
;
max-width
:
220px
;
width
:
100%
;
}
}
p
{
p
{
color
:
#999
;
color
:
#999
;
...
...
src/modules/admin/contest/dashboard/views/Index.vue
浏览文件 @
ac045689
...
@@ -234,11 +234,11 @@ function getModuleStatus(row: any, index: number) {
...
@@ -234,11 +234,11 @@ function getModuleStatus(row: any, index: number) {
</li>
</li>
</ul>
</ul>
<el-row
:gutter=
"20"
>
<el-row
:gutter=
"20"
>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<h2
class=
"h2-title"
>
已提交选手
</h2>
<h2
class=
"h2-title"
>
已提交选手
</h2>
<AppList
border
v-bind=
"submittedListOptions"
:data=
"submittedLis"
ref=
"appList"
></AppList
<AppList
border
v-bind=
"submittedListOptions"
:data=
"submittedLis"
ref=
"appList"
></AppList
></el-col>
></el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<h2
class=
"h2-title"
>
正在作答选手
</h2>
<h2
class=
"h2-title"
>
正在作答选手
</h2>
<AppList
border
v-bind=
"answeringListOptions"
:data=
"answeringList"
ref=
"appList"
></AppList
<AppList
border
v-bind=
"answeringListOptions"
:data=
"answeringList"
ref=
"appList"
></AppList
></el-col>
></el-col>
...
@@ -255,8 +255,9 @@ function getModuleStatus(row: any, index: number) {
...
@@ -255,8 +255,9 @@ function getModuleStatus(row: any, index: number) {
justify-content
:
center
;
justify-content
:
center
;
column-gap
:
140px
;
column-gap
:
140px
;
margin
:
90px
0
;
margin
:
90px
0
;
flex-wrap
:
wrap
;
row-gap
:
20px
;
li
{
li
{
width
:
212px
;
flex
:
0
0
212px
;
height
:
212px
;
height
:
212px
;
background-color
:
rgba
(
247
,
247
,
247
,
1
);
background-color
:
rgba
(
247
,
247
,
247
,
1
);
border-radius
:
50%
;
border-radius
:
50%
;
...
@@ -353,4 +354,5 @@ function getModuleStatus(row: any, index: number) {
...
@@ -353,4 +354,5 @@ function getModuleStatus(row: any, index: number) {
font-size
:
30px
;
font-size
:
30px
;
}
}
}
}
@media
(
max-width
:
767px
)
{
.statistics
{
justify-content
:
center
;
margin
:
40px
0
;
}
.statistics
li
{
flex
:
0
0
140px
;
height
:
140px
;
}
}
</
style
>
</
style
>
src/modules/admin/contest/discuss/components/DiscussItem.vue
浏览文件 @
ac045689
...
@@ -53,6 +53,8 @@ defineEmits<{
...
@@ -53,6 +53,8 @@ defineEmits<{
.discuss-box-user
{
.discuss-box-user
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
flex-wrap
:
wrap
;
min-width
:
0
;
.button-comment
{
.button-comment
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
...
@@ -112,6 +114,7 @@ defineEmits<{
...
@@ -112,6 +114,7 @@ defineEmits<{
font-weight
:
400
;
font-weight
:
400
;
line-height
:
24px
;
line-height
:
24px
;
color
:
#333333
;
color
:
#333333
;
word-break
:
break-word
;
}
}
.discuss-comment
{
.discuss-comment
{
...
@@ -134,12 +137,16 @@ defineEmits<{
...
@@ -134,12 +137,16 @@ defineEmits<{
margin-left
:
10px
;
margin-left
:
10px
;
color
:
#333
;
color
:
#333
;
overflow
:
hidden
;
overflow
:
hidden
;
word-break
:
break-word
;
}
}
.discuss-comment__username
{
.discuss-comment__username
{
font-size
:
16px
;
font-size
:
16px
;
line-height
:
20px
;
line-height
:
20px
;
color
:
var
(
--
main-color
);
color
:
var
(
--
main-color
);
}
}
@media
(
max-width
:
767px
)
{
.discuss-item
{
padding
:
12px
8px
;
}
}
.discuss-comment-time
{
.discuss-comment-time
{
margin-top
:
10px
;
margin-top
:
10px
;
font-size
:
14px
;
font-size
:
14px
;
...
...
src/modules/admin/contest/experts/components/ImportDialog.vue
浏览文件 @
ac045689
...
@@ -48,7 +48,7 @@ watchEffect(() => {
...
@@ -48,7 +48,7 @@ watchEffect(() => {
align-items
:
center
;
align-items
:
center
;
justify-content
:
center
;
justify-content
:
center
;
.el-button
{
.el-button
{
width
:
220px
;
max-width
:
220px
;
width
:
100%
;
}
}
p
{
p
{
color
:
#999
;
color
:
#999
;
...
...
src/modules/admin/contest/items/components/FormDialog copy.vue
浏览文件 @
ac045689
...
@@ -435,8 +435,8 @@ onMounted(() => {
...
@@ -435,8 +435,8 @@ onMounted(() => {
>
>
<div
style=
"display: flex; align-items: center"
>
<div
style=
"display: flex; align-items: center"
>
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px
; width: 100%
"
/>
<el-input
v-model=
"item.url"
style=
"
width: 200px
"
/>
<el-input
v-model=
"item.url"
style=
"
max-width: 200px; width: 100%
"
/>
</div>
</div>
</el-checkbox>
</el-checkbox>
</el-form-item>
</el-form-item>
...
@@ -451,9 +451,9 @@ onMounted(() => {
...
@@ -451,9 +451,9 @@ onMounted(() => {
>
>
<div
style=
"display: flex; align-items: center"
>
<div
style=
"display: flex; align-items: center"
>
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px
; width: 100%
"
/>
<el-input
v-model=
"item.url"
v-if=
"item.type === '2'"
style=
"
width: 200px
"
/>
<el-input
v-model=
"item.url"
v-if=
"item.type === '2'"
style=
"
max-width: 200px; width: 100%
"
/>
<el-select
v-model=
"item.exam_id"
filterable
style=
"
width: 200px
"
v-if=
"item.type === '1'"
>
<el-select
v-model=
"item.exam_id"
filterable
style=
"
max-width: 200px; width: 100%
"
v-if=
"item.type === '1'"
>
<el-option
<el-option
v-for=
"item in examList"
v-for=
"item in examList"
:key=
"item.exam_id"
:key=
"item.exam_id"
...
...
src/modules/admin/contest/items/components/FormDialog.vue
浏览文件 @
ac045689
...
@@ -432,8 +432,8 @@ onMounted(() => {
...
@@ -432,8 +432,8 @@ onMounted(() => {
>
>
<div
style=
"display: flex; align-items: center"
>
<div
style=
"display: flex; align-items: center"
>
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px
; width: 100%
"
/>
<el-input
v-model=
"item.url"
style=
"
width: 200px
"
/>
<el-input
v-model=
"item.url"
style=
"
max-width: 200px; width: 100%
"
/>
</div>
</div>
</el-checkbox>
</el-checkbox>
</el-form-item>
</el-form-item>
...
@@ -514,9 +514,9 @@ onMounted(() => {
...
@@ -514,9 +514,9 @@ onMounted(() => {
>
>
<div
style=
"display: flex; align-items: center"
>
<div
style=
"display: flex; align-items: center"
>
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<!--
<span
style=
"margin-right: 10px; width: 180px"
>
{{
item
.
name
}}
</span>
-->
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px"
/>
<el-input
v-model=
"item.name"
style=
"margin-right: 10px; max-width: 130px
; width: 100%
"
/>
<el-input
v-model=
"item.url"
v-if=
"item.type === '2'"
style=
"
width: 200px
"
/>
<el-input
v-model=
"item.url"
v-if=
"item.type === '2'"
style=
"
max-width: 200px; width: 100%
"
/>
<el-select
v-model=
"item.exam_id"
filterable
style=
"
width: 200px
"
v-if=
"item.type === '1'"
>
<el-select
v-model=
"item.exam_id"
filterable
style=
"
max-width: 200px; width: 100%
"
v-if=
"item.type === '1'"
>
<el-option
<el-option
v-for=
"item in examList"
v-for=
"item in examList"
:key=
"item.exam_id"
:key=
"item.exam_id"
...
...
src/modules/admin/contest/items/components/ViewExperimentFormDialog.vue
浏览文件 @
ac045689
...
@@ -63,7 +63,7 @@ function handleSubmit() {
...
@@ -63,7 +63,7 @@ function handleSubmit() {
remote-show-suffix
remote-show-suffix
:remote-method=
"fetchExamList"
:remote-method=
"fetchExamList"
:loading=
"loading"
:loading=
"loading"
style=
"width: 340px"
style=
"width:
100%; max-width:
340px"
>
>
<el-option
v-for=
"item in list"
:key=
"item.value"
:label=
"item.name"
:value=
"item.id"
/>
<el-option
v-for=
"item in list"
:key=
"item.value"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-select>
...
...
src/modules/admin/contest/items/views/Edit.vue
浏览文件 @
ac045689
...
@@ -41,7 +41,8 @@ onMounted(() => {
...
@@ -41,7 +41,8 @@ onMounted(() => {
}
}
}
}
.top-cover
{
.top-cover
{
width
:
300px
;
max-width
:
300px
;
width
:
100%
;
margin-right
:
20px
;
margin-right
:
20px
;
p
{
p
{
font-weight
:
normal
;
font-weight
:
normal
;
...
...
src/modules/admin/contest/items/views/View.vue
浏览文件 @
ac045689
...
@@ -213,7 +213,8 @@ function handleExperts() {
...
@@ -213,7 +213,8 @@ function handleExperts() {
}
}
}
}
.top-cover
{
.top-cover
{
width
:
300px
;
max-width
:
300px
;
width
:
100%
;
margin-right
:
20px
;
margin-right
:
20px
;
p
{
p
{
font-weight
:
normal
;
font-weight
:
normal
;
...
...
src/modules/admin/contest/score/components/ScorePublishDialog.vue
浏览文件 @
ac045689
...
@@ -32,9 +32,9 @@ function handleSubmit() {
...
@@ -32,9 +32,9 @@ function handleSubmit() {
</p>
</p>
<br
/>
<br
/>
<p>
<p>
<span>
报名人数:
{{
data
.
all_competitor_count
}}
</span>
<span
class=
"content__metric"
>
报名人数:
{{
data
.
all_competitor_count
}}
</span>
<span>
完赛人数:
{{
data
.
complete_competitor_count
}}
</span>
<span
class=
"content__metric"
>
完赛人数:
{{
data
.
complete_competitor_count
}}
</span>
<span>
已评分人数:
{{
data
.
checked_competitor_count
}}
</span>
<span
class=
"content__metric"
>
已评分人数:
{{
data
.
checked_competitor_count
}}
</span>
</p>
</p>
<br
/>
<br
/>
<p>
请确认是否发布成绩!
</p>
<p>
请确认是否发布成绩!
</p>
...
@@ -55,8 +55,20 @@ function handleSubmit() {
...
@@ -55,8 +55,20 @@ function handleSubmit() {
b
{
b
{
color
:
var
(
--
main-color
);
color
:
var
(
--
main-color
);
}
}
span
+
span
{
}
margin-left
:
40px
;
.content__metric
{
display
:
inline-block
;
}
.content__metric
+
.content__metric
{
margin-left
:
40px
;
}
@media
(
max-width
:
767px
)
{
.content__metric
{
display
:
block
;
margin
:
6px
0
;
}
.content__metric
+
.content__metric
{
margin-left
:
0
;
}
}
}
}
</
style
>
</
style
>
src/modules/admin/lab/book/index.ts
浏览文件 @
ac045689
...
@@ -2,10 +2,6 @@ import type { RouteRecordRaw } from 'vue-router'
...
@@ -2,10 +2,6 @@ import type { RouteRecordRaw } from 'vue-router'
import
AppLayout
from
'@/components/layout/Index.vue'
import
AppLayout
from
'@/components/layout/Index.vue'
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
{
path
:
'/admin/lab'
,
redirect
:
'/admin/lab/book'
},
{
{
path
:
'/admin/lab/book'
,
path
:
'/admin/lab/book'
,
component
:
AppLayout
,
component
:
AppLayout
,
...
...
src/modules/admin/lab/book/views/Index.vue
浏览文件 @
ac045689
...
@@ -85,4 +85,6 @@ function onUpdateSuccess() {
...
@@ -85,4 +85,6 @@ function onUpdateSuccess() {
grid-template-columns
:
repeat
(
4
,
1fr
);
grid-template-columns
:
repeat
(
4
,
1fr
);
gap
:
20px
;
gap
:
20px
;
}
}
@media
(
max-width
:
1024px
)
{
.list-card
{
grid-template-columns
:
repeat
(
2
,
1fr
);
gap
:
16px
;
}
}
@media
(
max-width
:
767px
)
{
.list-card
{
grid-template-columns
:
1fr
;
gap
:
12px
;
}
}
</
style
>
</
style
>
src/modules/admin/lab/case-auth/views/Index.vue
浏览文件 @
ac045689
...
@@ -288,10 +288,10 @@ async function handleBatchAuthorize() {
...
@@ -288,10 +288,10 @@ async function handleBatchAuthorize() {
<
template
>
<
template
>
<AppCard
title=
"案例授权"
>
<AppCard
title=
"案例授权"
>
<div
class=
"case-auth-toolbar"
>
<div
class=
"case-auth-toolbar"
>
<el-select
v-model=
"selectedCourse"
placeholder=
"请选择课程"
filterable
clearable
style=
"width: 200px"
>
<el-select
v-model=
"selectedCourse"
placeholder=
"请选择课程"
filterable
clearable
style=
"width:
100%; max-width:
200px"
>
<el-option
v-for=
"item in courses"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
<el-option
v-for=
"item in courses"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-select>
<el-select
v-model=
"selectedExperiment"
placeholder=
"请选择实验"
filterable
clearable
style=
"width: 200px"
>
<el-select
v-model=
"selectedExperiment"
placeholder=
"请选择实验"
filterable
clearable
style=
"width:
100%; max-width:
200px"
>
<el-option
v-for=
"item in experiments"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
<el-option
v-for=
"item in experiments"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-select>
<el-button
type=
"primary"
:loading=
"submitting"
@
click=
"handleBatchAuthorize"
:disabled=
"!selectedCount"
<el-button
type=
"primary"
:loading=
"submitting"
@
click=
"handleBatchAuthorize"
:disabled=
"!selectedCount"
...
...
src/modules/admin/lab/case/index.ts
浏览文件 @
ac045689
...
@@ -2,10 +2,6 @@ import type { RouteRecordRaw } from 'vue-router'
...
@@ -2,10 +2,6 @@ import type { RouteRecordRaw } from 'vue-router'
import
AppLayout
from
'@/components/layout/Index.vue'
import
AppLayout
from
'@/components/layout/Index.vue'
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
{
path
:
'/admin/lab'
,
redirect
:
'/admin/lab/case'
},
{
{
path
:
'/admin/lab/case'
,
path
:
'/admin/lab/case'
,
component
:
AppLayout
,
component
:
AppLayout
,
...
...
src/modules/admin/lab/case/views/Index.vue
浏览文件 @
ac045689
...
@@ -85,4 +85,6 @@ function onUpdateSuccess() {
...
@@ -85,4 +85,6 @@ function onUpdateSuccess() {
grid-template-columns
:
repeat
(
4
,
1fr
);
grid-template-columns
:
repeat
(
4
,
1fr
);
gap
:
20px
;
gap
:
20px
;
}
}
@media
(
max-width
:
1024px
)
{
.list-card
{
grid-template-columns
:
repeat
(
2
,
1fr
);
gap
:
16px
;
}
}
@media
(
max-width
:
767px
)
{
.list-card
{
grid-template-columns
:
1fr
;
gap
:
12px
;
}
}
</
style
>
</
style
>
src/modules/admin/lab/dashboard/components/History.vue
浏览文件 @
ac045689
...
@@ -104,11 +104,10 @@ const listOptions = computed(() => {
...
@@ -104,11 +104,10 @@ const listOptions = computed(() => {
align-items
:
center
;
align-items
:
center
;
justify-content
:
space-evenly
;
justify-content
:
space-evenly
;
margin
:
90px
0
;
margin
:
90px
0
;
&
:empty
{
flex-wrap
:
wrap
;
row-gap
:
20px
;
display
:
none
;
&
:empty
{
display
:
none
;
}
}
li
{
li
{
width
:
212px
;
flex
:
0
0
212px
;
height
:
212px
;
height
:
212px
;
background-color
:
rgba
(
247
,
247
,
247
,
1
);
background-color
:
rgba
(
247
,
247
,
247
,
1
);
border-radius
:
50%
;
border-radius
:
50%
;
...
@@ -147,4 +146,5 @@ const listOptions = computed(() => {
...
@@ -147,4 +146,5 @@ const listOptions = computed(() => {
margin
:
20px
0
;
margin
:
20px
0
;
border-left
:
3px
solid
#aa1941
;
border-left
:
3px
solid
#aa1941
;
}
}
@media
(
max-width
:
767px
)
{
.statistics
{
margin
:
40px
0
;
}
.statistics
li
{
flex
:
0
0
140px
;
height
:
140px
;
}
}
</
style
>
</
style
>
src/modules/admin/lab/dashboard/components/Live.vue
浏览文件 @
ac045689
...
@@ -107,11 +107,10 @@ const listOptions = computed(() => {
...
@@ -107,11 +107,10 @@ const listOptions = computed(() => {
align-items
:
center
;
align-items
:
center
;
justify-content
:
space-evenly
;
justify-content
:
space-evenly
;
margin
:
90px
0
;
margin
:
90px
0
;
&
:empty
{
flex-wrap
:
wrap
;
row-gap
:
20px
;
display
:
none
;
&
:empty
{
display
:
none
;
}
}
li
{
li
{
width
:
212px
;
flex
:
0
0
212px
;
height
:
212px
;
height
:
212px
;
background-color
:
rgba
(
247
,
247
,
247
,
1
);
background-color
:
rgba
(
247
,
247
,
247
,
1
);
border-radius
:
50%
;
border-radius
:
50%
;
...
@@ -150,4 +149,5 @@ const listOptions = computed(() => {
...
@@ -150,4 +149,5 @@ const listOptions = computed(() => {
margin
:
20px
0
;
margin
:
20px
0
;
border-left
:
3px
solid
#aa1941
;
border-left
:
3px
solid
#aa1941
;
}
}
@media
(
max-width
:
767px
)
{
.statistics
{
margin
:
40px
0
;
}
.statistics
li
{
flex
:
0
0
140px
;
height
:
140px
;
}
}
</
style
>
</
style
>
src/modules/admin/lab/discuss/components/DiscussItem.vue
浏览文件 @
ac045689
...
@@ -53,6 +53,8 @@ defineEmits<{
...
@@ -53,6 +53,8 @@ defineEmits<{
.discuss-box-user
{
.discuss-box-user
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
flex-wrap
:
wrap
;
min-width
:
0
;
.button-comment
{
.button-comment
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
...
@@ -112,6 +114,7 @@ defineEmits<{
...
@@ -112,6 +114,7 @@ defineEmits<{
font-weight
:
400
;
font-weight
:
400
;
line-height
:
24px
;
line-height
:
24px
;
color
:
#333333
;
color
:
#333333
;
word-break
:
break-word
;
}
}
.discuss-comment
{
.discuss-comment
{
...
@@ -134,12 +137,16 @@ defineEmits<{
...
@@ -134,12 +137,16 @@ defineEmits<{
margin-left
:
10px
;
margin-left
:
10px
;
color
:
#333
;
color
:
#333
;
overflow
:
hidden
;
overflow
:
hidden
;
word-break
:
break-word
;
}
}
.discuss-comment__username
{
.discuss-comment__username
{
font-size
:
16px
;
font-size
:
16px
;
line-height
:
20px
;
line-height
:
20px
;
color
:
var
(
--
main-color
);
color
:
var
(
--
main-color
);
}
}
@media
(
max-width
:
767px
)
{
.discuss-item
{
padding
:
12px
8px
;
}
}
.discuss-comment-time
{
.discuss-comment-time
{
margin-top
:
10px
;
margin-top
:
10px
;
font-size
:
14px
;
font-size
:
14px
;
...
...
src/modules/admin/lab/example/index.ts
浏览文件 @
ac045689
...
@@ -2,10 +2,6 @@ import type { RouteRecordRaw } from 'vue-router'
...
@@ -2,10 +2,6 @@ import type { RouteRecordRaw } from 'vue-router'
import
AppLayout
from
'@/components/layout/Index.vue'
import
AppLayout
from
'@/components/layout/Index.vue'
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
export
const
routes
:
Array
<
RouteRecordRaw
>
=
[
{
path
:
'/admin/lab'
,
redirect
:
'/admin/lab/example'
,
},
{
{
path
:
'/admin/lab/example'
,
path
:
'/admin/lab/example'
,
component
:
AppLayout
,
component
:
AppLayout
,
...
...
src/modules/admin/lab/experiment/components/CompetitionRuleDialog.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ElMessage
}
from
'element-plus'
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
{
getCompetitionRule
,
saveCompetitionRule
}
from
'../api'
import
{
getCompetitionRule
,
saveCompetitionRule
}
from
'../api'
interface
Props
{
interface
Props
{
id
:
string
id
:
string
}
}
const
props
=
defineProps
<
Props
>
()
const
props
=
defineProps
<
Props
>
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
dialogVisible
=
ref
(
false
)
const
dialogVisible
=
ref
(
false
)
...
@@ -226,7 +228,42 @@ function disabledMinSubmitDate(time: Date) {
...
@@ -226,7 +228,42 @@ function disabledMinSubmitDate(time: Date) {
<p>
成绩规则:
</p>
<p>
成绩规则:
</p>
<el-button
type=
"primary"
:icon=
"Plus"
@
click=
"handleAdd"
></el-button>
<el-button
type=
"primary"
:icon=
"Plus"
@
click=
"handleAdd"
></el-button>
</el-row>
</el-row>
<el-table
:data=
"form.config.rules"
>
<div
v-if=
"isMobile"
class=
"rule-card-list"
>
<div
class=
"rule-card"
v-for=
"(row, $index) in form.config.rules"
:key=
"`$
{row.type}-${$index}`">
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
评分项
</span>
<el-select
v-model=
"row.type"
style=
"width: 100%"
@
change=
"handleTypeChange(row)"
>
<el-option
v-for=
"item in currentRuleNames(row.type)"
:key=
"item.value"
v-bind=
"item"
></el-option>
</el-select>
</div>
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
分数
</span>
<div
class=
"rule-card__inline"
>
<el-input-number
v-model=
"row.percent"
:min=
"0"
:max=
"100"
@
change=
"handlePercentChange(row, $index)"
/>
分
</div>
</div>
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
评分方式
</span>
<el-radio-group
v-model=
"row.rule_mode"
size=
"small"
>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
<el-radio
:label=
"2"
:disabled=
"[4, 5, 6].includes(row.type)"
>
自动评分
</el-radio>
</el-radio-group>
</div>
<div
class=
"rule-card__actions"
>
<el-button
style=
"padding: 0"
text
type=
"primary"
@
click=
"handleEdit(row)"
:disabled=
"[4, 5, 6].includes(row.type) || row.rule_mode === 1"
>
编辑
</el-button
>
<el-button
style=
"padding: 0"
text
type=
"primary"
@
click=
"handleRemove($index)"
>
删除
</el-button>
</div>
</div>
</div>
<el-table
v-else
:data=
"form.config.rules"
>
<el-table-column
prop=
"name"
width=
"170"
>
<el-table-column
prop=
"name"
width=
"170"
>
<template
#
default=
"
{ row }">
<template
#
default=
"
{ row }">
<el-select
v-model=
"row.type"
style=
"width: 100%"
@
change=
"handleTypeChange(row)"
>
<el-select
v-model=
"row.type"
style=
"width: 100%"
@
change=
"handleTypeChange(row)"
>
...
@@ -305,4 +342,48 @@ function disabledMinSubmitDate(time: Date) {
...
@@ -305,4 +342,48 @@ function disabledMinSubmitDate(time: Date) {
padding
:
5px
10px
;
padding
:
5px
10px
;
}
}
}
}
.rule-card-list
{
width
:
100%
;
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.rule-card
{
width
:
100%
;
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
box-sizing
:
border-box
;
}
.rule-card__field
+
.rule-card__field
{
margin-top
:
12px
;
}
.rule-card__label
{
display
:
block
;
margin-bottom
:
8px
;
color
:
#909399
;
font-size
:
13px
;
}
.rule-card__inline
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
}
.rule-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
gap
:
12px
;
flex-wrap
:
wrap
;
padding-top
:
12px
;
}
@media
(
max-width
:
767px
)
{
.total
{
text-align
:
left
;
p
{
min-width
:
0
;
width
:
100%
;
}
}
}
</
style
>
</
style
>
src/modules/admin/lab/experiment/components/GradeRulesDialog.vue
浏览文件 @
ac045689
...
@@ -3,10 +3,12 @@ import type { FormInstance } from 'element-plus'
...
@@ -3,10 +3,12 @@ import type { FormInstance } from 'element-plus'
import
type
{
ExperimentItem
}
from
'../types'
import
type
{
ExperimentItem
}
from
'../types'
import
{
Plus
,
Minus
}
from
'@element-plus/icons-vue'
import
{
Plus
,
Minus
}
from
'@element-plus/icons-vue'
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
{
useMediaQuery
}
from
'@vueuse/core'
import
{
gradeRule
,
gradeRuleList
}
from
'@/utils/dictionary'
import
{
gradeRule
,
gradeRuleList
}
from
'@/utils/dictionary'
import
{
getExperimentGradeRule
,
updateExperimentGradeRule
,
getScoreExamList
}
from
'../api'
import
{
getExperimentGradeRule
,
updateExperimentGradeRule
,
getScoreExamList
}
from
'../api'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
const
appConfig
=
useAppConfig
()
const
appConfig
=
useAppConfig
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
interface
Props
{
interface
Props
{
data
:
ExperimentItem
data
:
ExperimentItem
...
@@ -269,7 +271,7 @@ onMounted(() => {
...
@@ -269,7 +271,7 @@ onMounted(() => {
<el-form
ref=
"formRef"
:model=
"form"
label-suffix=
":"
>
<el-form
ref=
"formRef"
:model=
"form"
label-suffix=
":"
>
<el-form-item
label=
"实验名称"
>
{{
data
?.
name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
data
?.
name
}}
</el-form-item>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"是否允许查看成绩明细"
prop=
"is_show"
>
<el-form-item
label=
"是否允许查看成绩明细"
prop=
"is_show"
>
<el-radio-group
v-model=
"form.is_show"
>
<el-radio-group
v-model=
"form.is_show"
>
<el-radio
label=
"1"
>
是
</el-radio>
<el-radio
label=
"1"
>
是
</el-radio>
...
@@ -277,7 +279,7 @@ onMounted(() => {
...
@@ -277,7 +279,7 @@ onMounted(() => {
</el-radio-group>
</el-radio-group>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验总成绩"
>
{{
data
?.
score
}}
</el-form-item>
<el-form-item
label=
"实验总成绩"
>
{{
data
?.
score
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
@@ -289,7 +291,36 @@ onMounted(() => {
...
@@ -289,7 +291,36 @@ onMounted(() => {
<el-button
type=
"primary"
:icon=
"Plus"
@
click=
"handleAddExamRule"
:disabled=
"form.exam_rules.length >= 1"
>
<el-button
type=
"primary"
:icon=
"Plus"
@
click=
"handleAddExamRule"
:disabled=
"form.exam_rules.length >= 1"
>
</el-button>
</el-button>
</el-row>
</el-row>
<el-table
:data=
"form.exam_rules"
row-key=
"id"
>
<div
v-if=
"isMobile"
class=
"rule-card-list"
>
<div
class=
"rule-card"
v-for=
"(row, $index) in form.exam_rules"
:key=
"row.id || $index"
>
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
理论考试
</span>
<el-select
v-model=
"row.exam_id"
style=
"width: 100%"
>
<el-option
v-for=
"item in examList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.exam_id"
></el-option>
</el-select>
</div>
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
权重
</span>
<div
class=
"rule-card__inline"
>
<el-input-number
v-model=
"row.percent"
:min=
"0"
@
change=
"handlePercentChange(row, $index, 2)"
/>
%
</div>
</div>
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
评分方式
</span>
<el-radio-group
v-model=
"row.is_auto_scoring"
size=
"small"
>
<el-radio
label=
"1"
>
自动评分
</el-radio>
</el-radio-group>
</div>
<div
class=
"rule-card__row"
>
<span>
满分
</span>
<strong>
{{
rowScore
(
row
.
percent
)
}}
</strong>
</div>
<div
class=
"rule-card__actions"
>
<el-button
style=
"padding: 0"
text
type=
"primary"
@
click=
"handleRemoveExamRule($index)"
v-if=
"row.type !== 1"
>
删除
</el-button>
</div>
</div>
</div>
<el-table
v-else
:data=
"form.exam_rules"
row-key=
"id"
>
<el-table-column
prop=
"name"
width=
"170"
>
<el-table-column
prop=
"name"
width=
"170"
>
<template
#
default=
"
{ row }">
<template
#
default=
"
{ row }">
<el-select
v-model=
"row.exam_id"
style=
"width: 100%"
>
<el-select
v-model=
"row.exam_id"
style=
"width: 100%"
>
...
@@ -332,7 +363,47 @@ onMounted(() => {
...
@@ -332,7 +363,47 @@ onMounted(() => {
<p>
实操成绩规则:
</p>
<p>
实操成绩规则:
</p>
<el-button
type=
"primary"
:icon=
"Plus"
@
click=
"handleAdd"
></el-button>
<el-button
type=
"primary"
:icon=
"Plus"
@
click=
"handleAdd"
></el-button>
</el-row>
</el-row>
<el-table
:data=
"form.rule_list"
row-key=
"id"
>
<div
v-if=
"isMobile"
class=
"rule-card-list"
>
<div
class=
"rule-card"
v-for=
"(row, $index) in form.rule_list"
:key=
"row.id || `${row.type}-${$index}`"
>
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
规则名称
</span>
<el-input
v-model=
"row.name"
:maxlength=
"20"
style=
"width: 100%"
v-if=
"row.type === 5"
/>
<el-select
v-model=
"row.type"
style=
"width: 100%"
@
change=
"handleTypeChange(row)"
v-else
>
<el-option
v-for=
"item in currentRuleNames(row.type)"
:key=
"item.value"
v-bind=
"item"
></el-option>
</el-select>
</div>
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
权重
</span>
<div
class=
"rule-card__inline"
>
<el-input-number
v-model=
"row.percent"
:min=
"0"
@
change=
"handlePercentChange(row, $index, 1)"
/>
%
</div>
</div>
<div
class=
"rule-card__field"
>
<span
class=
"rule-card__label"
>
评分方式
</span>
<el-radio-group
v-model=
"row.rule_mode"
size=
"small"
>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
<el-radio
:label=
"2"
:disabled=
"row.type === 1 || row.type === 5 || row.type === 8"
>
自动评分
</el-radio>
</el-radio-group>
</div>
<div
class=
"rule-card__row"
>
<span>
满分
</span>
<strong>
{{ rowScore(row.percent) }}
</strong>
</div>
<div
class=
"rule-card__actions"
>
<el-button
:disabled=
"row.type === 1"
style=
"padding: 0"
text
type=
"primary"
@
click=
"handleEdit(row)"
v-if=
"row.type !== 1 && row.type !== 5"
>
编辑
</el-button
>
<el-button
style=
"padding: 0"
text
type=
"primary"
@
click=
"handleRemove($index)"
>
删除
</el-button>
</div>
</div>
</div>
<el-table
v-else
:data=
"form.rule_list"
row-key=
"id"
>
<el-table-column
prop=
"name"
width=
"170"
>
<el-table-column
prop=
"name"
width=
"170"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-input
v-model=
"row.name"
:maxlength=
"20"
style=
"width: 100%"
v-if=
"row.type === 5"
/>
<el-input
v-model=
"row.name"
:maxlength=
"20"
style=
"width: 100%"
v-if=
"row.type === 5"
/>
...
@@ -400,6 +471,7 @@ onMounted(() => {
...
@@ -400,6 +471,7 @@ onMounted(() => {
<
template
v-if=
"marketingShow"
>
<
template
v-if=
"marketingShow"
>
<el-form-item
<el-form-item
style=
"margin-bottom: 10px"
style=
"margin-bottom: 10px"
class=
"marketing-item"
label-width=
"150px"
label-width=
"150px"
:label=
"marketingType[item.type as '1']"
:label=
"marketingType[item.type as '1']"
v-for=
"(item, index) in marketingForm.details"
v-for=
"(item, index) in marketingForm.details"
...
@@ -452,4 +524,64 @@ onMounted(() => {
...
@@ -452,4 +524,64 @@ onMounted(() => {
float
:
right
;
float
:
right
;
}
}
}
}
.rule-card-list
{
width
:
100%
;
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.rule-card
{
width
:
100%
;
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
box-sizing
:
border-box
;
}
.rule-card__field
+
.rule-card__field
{
margin-top
:
12px
;
}
.rule-card__label
{
display
:
block
;
margin-bottom
:
8px
;
color
:
#909399
;
font-size
:
13px
;
}
.rule-card__inline
{
display
:
flex
;
align-items
:
center
;
gap
:
8px
;
}
.rule-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding-top
:
12px
;
margin-top
:
12px
;
border-top
:
1px
solid
#f3f4f6
;
}
.rule-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
gap
:
12px
;
flex-wrap
:
wrap
;
padding-top
:
12px
;
}
@media
(
max-width
:
767px
)
{
.total
,
.total-c
{
padding
:
10px
0
;
p
{
margin-left
:
0
;
min-width
:
0
;
width
:
100%
;
float
:
none
;
}
}
.marketing-item
{
:deep
(
.el-form-item__content
)
{
width
:
100%
;
}
}
}
</
style
>
</
style
>
src/modules/admin/lab/experiment/components/Questions/GroupQuestion.vue
浏览文件 @
ac045689
...
@@ -94,7 +94,8 @@ defineExpose({ formRef })
...
@@ -94,7 +94,8 @@ defineExpose({ formRef })
.upload-box
{
.upload-box
{
display
:
flex
;
display
:
flex
;
.upload-loading
{
.upload-loading
{
width
:
300px
;
max-width
:
300px
;
width
:
100%
;
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
&
:hover
{
&
:hover
{
...
...
src/modules/admin/lab/experiment/components/Questions/JourneyQuestion.vue
浏览文件 @
ac045689
...
@@ -61,7 +61,8 @@ defineExpose({ formRef })
...
@@ -61,7 +61,8 @@ defineExpose({ formRef })
.upload-box
{
.upload-box
{
display
:
flex
;
display
:
flex
;
.upload-loading
{
.upload-loading
{
width
:
300px
;
max-width
:
300px
;
width
:
100%
;
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
&
:hover
{
&
:hover
{
...
...
src/modules/admin/lab/experiment/components/Questions/MaterialQuestion.vue
浏览文件 @
ac045689
...
@@ -119,7 +119,8 @@ defineExpose({ formRef })
...
@@ -119,7 +119,8 @@ defineExpose({ formRef })
.upload-box
{
.upload-box
{
display
:
flex
;
display
:
flex
;
.upload-loading
{
.upload-loading
{
width
:
300px
;
max-width
:
300px
;
width
:
100%
;
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
&
:hover
{
&
:hover
{
...
...
src/modules/admin/lab/experiment/components/Questions/TagQuestion.vue
浏览文件 @
ac045689
...
@@ -93,7 +93,8 @@ defineExpose({ formRef })
...
@@ -93,7 +93,8 @@ defineExpose({ formRef })
.upload-box
{
.upload-box
{
display
:
flex
;
display
:
flex
;
.upload-loading
{
.upload-loading
{
width
:
300px
;
max-width
:
300px
;
width
:
100%
;
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
&
:hover
{
&
:hover
{
...
...
src/modules/admin/lab/experiment/components/ReportDesignAttachment.vue
浏览文件 @
ac045689
...
@@ -43,7 +43,7 @@ function handleHasScoreChange(value?: number) {
...
@@ -43,7 +43,7 @@ function handleHasScoreChange(value?: number) {
<
template
>
<
template
>
<div
class=
"report-design-item"
>
<div
class=
"report-design-item"
>
<el-row
:gutter=
"40"
>
<el-row
:gutter=
"40"
>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
<el-form-item
label=
"附件组件名称"
label=
"附件组件名称"
label-width=
"130px"
label-width=
"130px"
...
@@ -52,12 +52,12 @@ function handleHasScoreChange(value?: number) {
...
@@ -52,12 +52,12 @@ function handleHasScoreChange(value?: number) {
<el-input
v-model=
"form.name"
placeholder=
"例:实验源代码程序包"
maxlength=
"20"
/>
<el-input
v-model=
"form.name"
placeholder=
"例:实验源代码程序包"
maxlength=
"20"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"分值"
prop=
"score"
>
<el-form-item
label=
"分值"
prop=
"score"
>
<el-input-number
:min=
"0"
v-model=
"form.score"
@
change=
"handleScoreChange"
/>
<el-input-number
:min=
"0"
v-model=
"form.score"
@
change=
"handleScoreChange"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"评分规则"
prop=
"rule_mode"
>
<el-form-item
label=
"评分规则"
prop=
"rule_mode"
>
<el-radio-group
v-model=
"form.rule_mode"
>
<el-radio-group
v-model=
"form.rule_mode"
>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
...
@@ -65,7 +65,7 @@ function handleHasScoreChange(value?: number) {
...
@@ -65,7 +65,7 @@ function handleHasScoreChange(value?: number) {
</el-radio-group>
</el-radio-group>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"最低分"
prop=
"min_score"
>
<el-form-item
label=
"最低分"
prop=
"min_score"
>
<el-input-number
:min=
"0"
:max=
"form.score"
v-model=
"form.min_score"
v-if=
"form.rule_mode === 1"
/>
<el-input-number
:min=
"0"
:max=
"form.score"
v-model=
"form.min_score"
v-if=
"form.rule_mode === 1"
/>
<template
v-else
>
<template
v-else
>
...
...
src/modules/admin/lab/experiment/components/ReportDesignContent.vue
浏览文件 @
ac045689
...
@@ -27,7 +27,7 @@ function handleScoreChange(value?: number) {
...
@@ -27,7 +27,7 @@ function handleScoreChange(value?: number) {
<
template
>
<
template
>
<div
class=
"report-design-item"
>
<div
class=
"report-design-item"
>
<el-row
:gutter=
"40"
>
<el-row
:gutter=
"40"
>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
<el-form-item
label=
"内容组件名称"
label=
"内容组件名称"
label-width=
"130px"
label-width=
"130px"
...
@@ -36,12 +36,12 @@ function handleScoreChange(value?: number) {
...
@@ -36,12 +36,12 @@ function handleScoreChange(value?: number) {
<el-input
v-model=
"form.name"
placeholder=
"例:实验目的"
maxlength=
"20"
/>
<el-input
v-model=
"form.name"
placeholder=
"例:实验目的"
maxlength=
"20"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"分值"
prop=
"score"
>
<el-form-item
label=
"分值"
prop=
"score"
>
<el-input-number
:min=
"0"
v-model=
"form.score"
@
change=
"handleScoreChange"
/>
<el-input-number
:min=
"0"
v-model=
"form.score"
@
change=
"handleScoreChange"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"评分规则"
prop=
"rule_mode"
>
<el-form-item
label=
"评分规则"
prop=
"rule_mode"
>
<el-radio-group
v-model=
"form.rule_mode"
>
<el-radio-group
v-model=
"form.rule_mode"
>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
...
@@ -49,7 +49,7 @@ function handleScoreChange(value?: number) {
...
@@ -49,7 +49,7 @@ function handleScoreChange(value?: number) {
</el-radio-group>
</el-radio-group>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"最低分"
prop=
"min_score"
>
<el-form-item
label=
"最低分"
prop=
"min_score"
>
<el-input-number
:min=
"0"
:max=
"form.score"
v-model=
"form.min_score"
/>
<el-input-number
:min=
"0"
:max=
"form.score"
v-model=
"form.min_score"
/>
</el-form-item>
</el-form-item>
...
...
src/modules/admin/lab/experiment/components/ReportDesignPaper.vue
浏览文件 @
ac045689
...
@@ -17,17 +17,17 @@ watchEffect(() => {
...
@@ -17,17 +17,17 @@ watchEffect(() => {
<div
class=
"report-design-item"
>
<div
class=
"report-design-item"
>
<el-form
:model=
"form"
label-suffix=
":"
>
<el-form
:model=
"form"
label-suffix=
":"
>
<el-row
:gutter=
"40"
>
<el-row
:gutter=
"40"
>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"试卷组件名称"
prop=
"name"
label-width=
"130px"
>
<el-form-item
label=
"试卷组件名称"
prop=
"name"
label-width=
"130px"
>
<el-input
v-model=
"form.name"
placeholder=
"例:商业数据分析基础理论"
maxlength=
"20"
/>
<el-input
v-model=
"form.name"
placeholder=
"例:商业数据分析基础理论"
maxlength=
"20"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"分值"
prop=
"score"
>
<el-form-item
label=
"分值"
prop=
"score"
>
<el-input-number
:min=
"0"
v-model=
"form.score"
/>
<el-input-number
:min=
"0"
v-model=
"form.score"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"评分规则"
prop=
"rule_mode"
>
<el-form-item
label=
"评分规则"
prop=
"rule_mode"
>
<el-radio-group
v-model=
"form.rule_mode"
>
<el-radio-group
v-model=
"form.rule_mode"
>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
...
@@ -35,7 +35,7 @@ watchEffect(() => {
...
@@ -35,7 +35,7 @@ watchEffect(() => {
</el-radio-group>
</el-radio-group>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"最低分"
prop=
"min_score"
>
<el-form-item
label=
"最低分"
prop=
"min_score"
>
<el-input-number
:min=
"0"
v-model=
"form.min_score"
/>
<el-input-number
:min=
"0"
v-model=
"form.min_score"
/>
</el-form-item>
</el-form-item>
...
...
src/modules/admin/lab/experiment/components/ReportDesignQuestion.vue
浏览文件 @
ac045689
...
@@ -27,7 +27,7 @@ function handleScoreChange(value?: number) {
...
@@ -27,7 +27,7 @@ function handleScoreChange(value?: number) {
<
template
>
<
template
>
<div
class=
"report-design-item"
>
<div
class=
"report-design-item"
>
<el-row
:gutter=
"40"
>
<el-row
:gutter=
"40"
>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
<el-form-item
label=
"思考题组件名称"
label=
"思考题组件名称"
label-width=
"130px"
label-width=
"130px"
...
@@ -36,12 +36,12 @@ function handleScoreChange(value?: number) {
...
@@ -36,12 +36,12 @@ function handleScoreChange(value?: number) {
<el-input
v-model=
"form.name"
placeholder=
"例:实验扩展思考"
maxlength=
"20"
/>
<el-input
v-model=
"form.name"
placeholder=
"例:实验扩展思考"
maxlength=
"20"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"分值"
prop=
"score"
>
<el-form-item
label=
"分值"
prop=
"score"
>
<el-input-number
:min=
"0"
v-model=
"form.score"
@
change=
"handleScoreChange"
/>
<el-input-number
:min=
"0"
v-model=
"form.score"
@
change=
"handleScoreChange"
/>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"评分规则"
prop=
"rule_mode"
>
<el-form-item
label=
"评分规则"
prop=
"rule_mode"
>
<el-radio-group
v-model=
"form.rule_mode"
>
<el-radio-group
v-model=
"form.rule_mode"
>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
<el-radio
:label=
"1"
>
人工评分
</el-radio>
...
@@ -49,7 +49,7 @@ function handleScoreChange(value?: number) {
...
@@ -49,7 +49,7 @@ function handleScoreChange(value?: number) {
</el-radio-group>
</el-radio-group>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"6"
>
<el-col
:
xs=
"12"
:sm=
"12"
:md
=
"6"
>
<el-form-item
label=
"最低分"
prop=
"min_score"
>
<el-form-item
label=
"最低分"
prop=
"min_score"
>
<el-input-number
:min=
"0"
:max=
"form.score"
v-model=
"form.min_score"
/>
<el-input-number
:min=
"0"
:max=
"form.score"
v-model=
"form.min_score"
/>
</el-form-item>
</el-form-item>
...
...
src/modules/admin/lab/experiment/components/ReportPreview.vue
浏览文件 @
ac045689
...
@@ -16,42 +16,42 @@ const teacherText = $computed(() => {
...
@@ -16,42 +16,42 @@ const teacherText = $computed(() => {
<h1>
实验报告
</h1>
<h1>
实验报告
</h1>
<el-form
label-suffix=
":"
>
<el-form
label-suffix=
":"
>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"课程名称"
>
{{
data
.
course_name
}}
</el-form-item>
<el-form-item
label=
"课程名称"
>
{{
data
.
course_name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验名称"
>
{{
data
.
name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
data
.
name
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验地点"
></el-form-item>
<el-form-item
label=
"实验地点"
></el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验日期"
></el-form-item>
<el-form-item
label=
"实验日期"
></el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验类型"
>
{{
data
.
type_name
}}
</el-form-item>
<el-form-item
label=
"实验类型"
>
{{
data
.
type_name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
<el-form-item
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"专业"
></el-form-item>
<el-form-item
label=
"专业"
></el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"班级"
></el-form-item>
<el-form-item
label=
"班级"
></el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"姓名"
></el-form-item>
<el-form-item
label=
"姓名"
></el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学号"
></el-form-item>
<el-form-item
label=
"学号"
></el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
...
src/modules/admin/lab/experiment/views/Questions.vue
浏览文件 @
ac045689
...
@@ -143,6 +143,7 @@ const handleSubmit = async () => {
...
@@ -143,6 +143,7 @@ const handleSubmit = async () => {
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
.btn-box
{
.btn-box
{
display
:
flex
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
8px
;
margin-bottom
:
20px
;
margin-bottom
:
20px
;
.btn-r
{
.btn-r
{
margin-left
:
auto
;
margin-left
:
auto
;
...
...
src/modules/admin/lab/experiment/views/Report.vue
浏览文件 @
ac045689
...
@@ -107,21 +107,21 @@ function handlePreview() {
...
@@ -107,21 +107,21 @@ function handlePreview() {
<AppCard
title=
"实验报告规则设置"
>
<AppCard
title=
"实验报告规则设置"
>
<el-form
ref=
"formRef"
:model=
"form"
label-suffix=
":"
hide-required-asterisk
v-if=
"detail"
>
<el-form
ref=
"formRef"
:model=
"form"
label-suffix=
":"
hide-required-asterisk
v-if=
"detail"
>
<el-row>
<el-row>
<el-col
:
span
=
"8"
>
<el-col
:
xs=
"24"
:sm=
"12"
:md
=
"8"
>
<el-form-item
label=
"实验名称"
>
{{
detail
.
name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
detail
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"8"
>
<el-col
:
xs=
"24"
:sm=
"12"
:md
=
"8"
>
<el-form-item
label=
"实验课程名称"
>
{{
detail
.
course_name
}}
</el-form-item>
<el-form-item
label=
"实验课程名称"
>
{{
detail
.
course_name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"8"
>
<el-col
:
xs=
"24"
:sm=
"12"
:md
=
"8"
>
<el-form-item
label=
"所属机构/学校"
>
{{
detail
.
organ_id_name
}}
</el-form-item>
<el-form-item
label=
"所属机构/学校"
>
{{
detail
.
organ_id_name
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"8"
>
<el-col
:
xs=
"24"
:sm=
"12"
:md
=
"8"
>
<el-form-item
label=
"实验类型"
>
{{
detail
.
type_name
}}
</el-form-item>
<el-form-item
label=
"实验类型"
>
{{
detail
.
type_name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"8"
>
<el-col
:
xs=
"24"
:sm=
"12"
:md
=
"8"
>
<el-form-item
:span=
"3"
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
<el-form-item
:span=
"3"
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
...
src/modules/admin/lab/experiment/views/View.vue
浏览文件 @
ac045689
...
@@ -231,3 +231,16 @@ function handleUpdateGradeRules() {
...
@@ -231,3 +231,16 @@ function handleUpdateGradeRules() {
:data=
"detail"
:data=
"detail"
v-if=
"gradeRulesDialogVisible && detail"
></GradeRulesDialog>
v-if=
"gradeRulesDialogVisible && detail"
></GradeRulesDialog>
</template>
</template>
<
style
lang=
"scss"
scoped
>
.btn-all
{
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
8px
;
}
@media
(
max-width
:
767px
)
{
.btn-all
.el-button
{
width
:
100%
;
}
}
</
style
>
src/modules/admin/lab/score/components/ImportDialog.vue
浏览文件 @
ac045689
...
@@ -50,7 +50,7 @@ watchEffect(() => {
...
@@ -50,7 +50,7 @@ watchEffect(() => {
align-items
:
center
;
align-items
:
center
;
justify-content
:
center
;
justify-content
:
center
;
.el-button
{
.el-button
{
width
:
220px
;
max-width
:
220px
;
width
:
100%
;
}
}
p
{
p
{
color
:
#999
;
color
:
#999
;
...
...
src/modules/admin/lab/score/components/Question.vue
浏览文件 @
ac045689
...
@@ -148,7 +148,7 @@ const handleSubmit = function () {
...
@@ -148,7 +148,7 @@ const handleSubmit = function () {
<el-button
type=
"primary"
@
click=
"updateScore(questionDetail)"
>
保存
</el-button>
<el-button
type=
"primary"
@
click=
"updateScore(questionDetail)"
>
保存
</el-button>
</el-row>
</el-row>
</el-card>
</el-card>
<el-row
justify=
"center"
>
<el-row
justify=
"center"
class=
"question-actions"
>
<el-button
:disabled=
"!hasPrev"
type=
"primary"
@
click=
"handlePrev"
>
上一题
</el-button>
<el-button
:disabled=
"!hasPrev"
type=
"primary"
@
click=
"handlePrev"
>
上一题
</el-button>
<el-button
:disabled=
"!hasNext"
type=
"primary"
@
click=
"handleNext"
>
下一题
</el-button>
<el-button
:disabled=
"!hasNext"
type=
"primary"
@
click=
"handleNext"
>
下一题
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit()"
>
提交
</el-button>
<el-button
type=
"primary"
@
click=
"handleSubmit()"
>
提交
</el-button>
...
@@ -237,4 +237,51 @@ const handleSubmit = function () {
...
@@ -237,4 +237,51 @@ const handleSubmit = function () {
font-size
:
14px
;
font-size
:
14px
;
}
}
}
}
.question-actions
{
gap
:
8px
;
}
@media
(
max-width
:
767px
)
{
.question-number
{
dd
{
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
8px
;
span
{
margin-right
:
0
;
margin-bottom
:
0
;
}
}
}
.question-item__stem
,
.question-item__content
,
.question-item__tip
{
line-height
:
1
.6
;
word-break
:
break-word
;
}
.question-item__files-item
{
align-items
:
flex-start
;
}
.question-item__files-item__title
{
min-width
:
0
;
p
{
word-break
:
break-word
;
}
}
.question-item-score
{
flex-direction
:
column
;
gap
:
10px
;
span
{
margin-right
:
0
;
}
}
.question-actions
{
:deep
(
.el-button
)
{
margin-left
:
0
;
width
:
calc
(
50%
-
4px
);
}
:deep
(
.el-button
:last-child
)
{
width
:
100%
;
}
}
}
</
style
>
</
style
>
src/modules/admin/lab/score/components/ScoreDialog.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
type
{
RecordItem
,
FileItem
}
from
'../types'
import
type
{
RecordItem
,
FileItem
}
from
'../types'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
useMediaQuery
}
from
'@vueuse/core'
import
{
getExperimentScore
,
getExperimentScoreTemplate
,
updateExperimentScore
,
getExperimentReport
}
from
'../api'
import
{
getExperimentScore
,
getExperimentScoreTemplate
,
updateExperimentScore
,
getExperimentReport
}
from
'../api'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
const
appConfig
=
useAppConfig
()
const
appConfig
=
useAppConfig
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
ScoreViewPicturesDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewPicturesDialog.vue'
))
const
ScoreViewPicturesDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewPicturesDialog.vue'
))
const
ScoreViewPrepareDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewPrepareDialog.vue'
))
const
ScoreViewPrepareDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewPrepareDialog.vue'
))
...
@@ -171,33 +173,33 @@ function handleViewAuto(row: any) {
...
@@ -171,33 +173,33 @@ function handleViewAuto(row: any) {
@
update:modelValue=
"(value) => $emit('update:modelValue', value)"
>
@
update:modelValue=
"(value) => $emit('update:modelValue', value)"
>
<el-form
label-width=
"120px"
label-suffix=
":"
v-if=
"detail"
>
<el-form
label-width=
"120px"
label-suffix=
":"
v-if=
"detail"
>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验名称"
>
{{
data
.
experiment_name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
data
.
experiment_name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
<el-form-item
label=
"实验课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学生姓名"
>
{{
data
.
student_name
}}
</el-form-item>
<el-form-item
label=
"学生姓名"
>
{{
data
.
student_name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学生学号"
>
{{
data
.
sno_number
}}
</el-form-item>
<el-form-item
label=
"学生学号"
>
{{
data
.
sno_number
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"所属专业"
>
{{
data
.
specialty_name
}}
</el-form-item>
<el-form-item
label=
"所属专业"
>
{{
data
.
specialty_name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"所属班级"
>
{{
data
.
class_name
}}
</el-form-item>
<el-form-item
label=
"所属班级"
>
{{
data
.
class_name
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-divider
/>
<el-divider
/>
<el-form-item
label=
"理论成绩"
>
{{
data
.
theory_score
}}
</el-form-item>
<el-form-item
label=
"理论成绩"
>
{{
data
.
theory_score
}}
</el-form-item>
<el-form-item
label=
"实验成绩"
>
<el-form-item
label=
"实验成绩"
>
<el-row
justify=
"end"
style=
"width: 100%"
>
<el-row
justify=
"end"
style=
"width: 100%"
class=
"score-action-row"
>
<el-button
type=
"primary"
@
click=
"prepareVisible = true"
>
查看实验准备
</el-button>
<el-button
type=
"primary"
@
click=
"prepareVisible = true"
>
查看实验准备
</el-button>
<el-button
type=
"primary"
@
click=
"resultVisible = true"
>
查看实验结果
</el-button>
<el-button
type=
"primary"
@
click=
"resultVisible = true"
>
查看实验结果
</el-button>
<el-button
type=
"primary"
@
click=
"pictureVisible = true"
>
查看截图
</el-button>
<el-button
type=
"primary"
@
click=
"pictureVisible = true"
>
查看截图
</el-button>
...
@@ -208,11 +210,60 @@ function handleViewAuto(row: any) {
...
@@ -208,11 +210,60 @@ function handleViewAuto(row: any) {
<p
class=
"t1"
>
{{
scoreValue
(
score
)
}}
</p>
<p
class=
"t1"
>
{{
scoreValue
(
score
)
}}
</p>
<p
class=
"t2"
>
满分:
{{
experiment
.
score
}}
</p>
<p
class=
"t2"
>
满分:
{{
experiment
.
score
}}
</p>
</div>
</div>
<div
v-if=
"isMobile"
class=
"score-detail-card-list"
>
<div
class=
"score-detail-card"
v-for=
"row in form.score_details"
:key=
"`$
{row.type}-${row.name}`">
<div
class=
"score-detail-card__row"
><span>
实验成绩组成项
</span><strong>
{{
row
.
name
||
'-'
}}
</strong></div>
<div
class=
"score-detail-card__row"
><span>
权重
</span><strong>
{{
row
.
percent
}}
%
</strong></div>
<div
class=
"score-detail-card__row"
><span>
满分
</span><strong>
{{
row
.
score
||
'-'
}}
</strong></div>
<div
class=
"score-detail-card__row score-detail-card__row--field"
>
<span>
得分
</span>
<div
class=
"score-detail-card__field"
>
<el-input-number
v-model=
"row.commit_score"
:min=
"0"
:max=
"100"
:controls=
"false"
:step=
"0.01"
step-strictly
placeholder=
"请输入成绩"
style=
"width: 100%"
v-if=
"!(row.type === 1 && experiment.report_upload_way === 2)"
></el-input-number>
<strong
v-else
>
{{
row
.
commit_score
}}
</strong>
</div>
</div>
<div
class=
"score-detail-card__actions"
>
<template
v-if=
"row.type === 1"
>
<el-button
link
type=
"primary"
v-if=
"experiment.report_upload_way === 2"
>
<a
:href=
"getOperationUrl(row.type)"
target=
"_blank"
>
批改
</a>
</el-button>
<template
v-if=
"experiment.report_upload_way === 1"
>
<el-button
link
type=
"primary"
v-if=
"file?.url"
>
<a
:href=
"file.url"
target=
"_blank"
>
查阅报告
</a>
</el-button>
<p
class=
"score-detail-card__warning"
v-else
>
未上传
</p>
</
template
>
</template>
<
template
v-if=
"[6, 7, 9, 11, 12].includes(row.type)"
>
<el-button
link
type=
"primary"
@
click=
"handleViewAuto(row)"
>
查看自动评分结果
</el-button>
</
template
>
<
template
v-if=
"[6, 7, 8, 9, 10, 11, 12].includes(row.type)"
>
<el-button
link
type=
"primary"
>
<a
:href=
"`/admin/lab/score/score?id=$
{props.data.experiment_id}
&
sid=${props.data.student_id}
&
type=${row.type}`"
target="_blank"
>查看原始结果
</a
>
</el-button>
</
template
>
</div>
</div>
</div>
<el-table
<el-table
:data=
"form.score_details"
:data=
"form.score_details"
stripe
stripe
:header-cell-style=
"{ background: '#ededed' }"
:header-cell-style=
"{ background: '#ededed' }"
style="margin-top: 20px">
style=
"margin-top: 20px"
v-else
>
<el-table-column
label=
"实验成绩组成项"
prop=
"name"
align=
"left"
></el-table-column>
<el-table-column
label=
"实验成绩组成项"
prop=
"name"
align=
"left"
></el-table-column>
<el-table-column
label=
"权重"
prop=
"percent"
align=
"center"
width=
"80"
>
<el-table-column
label=
"权重"
prop=
"percent"
align=
"center"
width=
"80"
>
<
template
#
default=
"{ row }"
>
{{
row
.
percent
}}
%
</
template
>
<
template
#
default=
"{ row }"
>
{{
row
.
percent
}}
%
</
template
>
...
@@ -301,6 +352,7 @@ function handleViewAuto(row: any) {
...
@@ -301,6 +352,7 @@ function handleViewAuto(row: any) {
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
justify-content
:
center
;
justify-content
:
center
;
gap
:
24px
;
}
}
.score-result__total
{
.score-result__total
{
min-width
:
120px
;
min-width
:
120px
;
...
@@ -311,4 +363,63 @@ function handleViewAuto(row: any) {
...
@@ -311,4 +363,63 @@ function handleViewAuto(row: any) {
color
:
var
(
--
main-color
);
color
:
var
(
--
main-color
);
}
}
}
}
.score-detail-card-list
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
margin-top
:
20px
;
}
.score-detail-card
{
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
}
.score-detail-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
}
.score-detail-card__row
:last-of-type
{
border-bottom
:
none
;
}
.score-detail-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.score-detail-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
word-break
:
break-word
;
}
.score-detail-card__row--field
{
align-items
:
center
;
}
.score-detail-card__field
{
width
:
140px
;
max-width
:
100%
;
}
.score-detail-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
flex-wrap
:
wrap
;
gap
:
8px
;
padding-top
:
8px
;
}
.score-detail-card__warning
{
color
:
red
;
}
@media
(
max-width
:
767px
)
{
.score-action-row
{
gap
:
8px
;
justify-content
:
flex-start
!
important
;
}
.score-result
{
flex-direction
:
column
;
align-items
:
stretch
;
}
}
</
style
>
</
style
>
src/modules/admin/lab/score/components/ScoreViewPicturesDialog.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
type
{
RecordItem
,
FileItem
}
from
'../types'
import
type
{
RecordItem
,
FileItem
}
from
'../types'
import
{
useMediaQuery
}
from
'@vueuse/core'
interface
Props
{
interface
Props
{
data
:
RecordItem
data
:
RecordItem
}
}
const
props
=
defineProps
<
Props
>
()
const
props
=
defineProps
<
Props
>
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
// 实验过程截图
// 实验过程截图
const
pictures
=
$computed
<
FileItem
[]
>
(()
=>
{
const
pictures
=
$computed
<
FileItem
[]
>
(()
=>
{
...
@@ -19,7 +21,7 @@ const pictures = $computed<FileItem[]>(() => {
...
@@ -19,7 +21,7 @@ const pictures = $computed<FileItem[]>(() => {
<
template
>
<
template
>
<el-dialog
title=
"查看实验截图"
width=
"800px"
>
<el-dialog
title=
"查看实验截图"
width=
"800px"
>
<ul
class=
"picture-list"
>
<ul
class=
"picture-list"
:class=
"
{ 'picture-list--mobile': isMobile }"
>
<li
v-for=
"item in pictures"
:key=
"item.url"
>
<li
v-for=
"item in pictures"
:key=
"item.url"
>
<p
class=
"t1"
>
<p
class=
"t1"
>
<a
:href=
"item.url"
target=
"_blank"
>
{{
item
.
name
}}
</a>
<a
:href=
"item.url"
target=
"_blank"
>
{{
item
.
name
}}
</a>
...
@@ -42,6 +44,7 @@ const pictures = $computed<FileItem[]>(() => {
...
@@ -42,6 +44,7 @@ const pictures = $computed<FileItem[]>(() => {
display
:
flex
;
display
:
flex
;
justify-content
:
space-between
;
justify-content
:
space-between
;
line-height
:
30px
;
line-height
:
30px
;
gap
:
12px
;
}
}
a
{
a
{
color
:
var
(
--
main-color
);
color
:
var
(
--
main-color
);
...
@@ -53,4 +56,21 @@ const pictures = $computed<FileItem[]>(() => {
...
@@ -53,4 +56,21 @@ const pictures = $computed<FileItem[]>(() => {
overflow
:
hidden
;
overflow
:
hidden
;
}
}
}
}
.picture-list--mobile
{
li
{
display
:
block
;
padding
:
12px
14px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
margin-bottom
:
12px
;
line-height
:
1
.7
;
}
.t1
{
white-space
:
normal
;
word-break
:
break-word
;
}
.t2
{
color
:
#909399
;
}
}
</
style
>
</
style
>
src/modules/admin/lab/score/views/Report.vue
浏览文件 @
ac045689
<
script
setup
>
<
script
setup
>
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
{
useMediaQuery
}
from
'@vueuse/core'
import
{
getExperimentScore
,
getExperimentReport
,
updateExperimentReport
,
getExperimentScoreTemplate
}
from
'../api'
import
{
getExperimentScore
,
getExperimentReport
,
updateExperimentReport
,
getExperimentScoreTemplate
}
from
'../api'
import
{
reportScoreRule
}
from
'@/utils/dictionary'
import
{
reportScoreRule
}
from
'@/utils/dictionary'
const
route
=
useRoute
()
const
route
=
useRoute
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
let
experiment
=
$ref
()
let
experiment
=
$ref
()
let
report
=
$ref
()
let
report
=
$ref
()
...
@@ -122,42 +124,42 @@ function scoreValue(value) {
...
@@ -122,42 +124,42 @@ function scoreValue(value) {
scroll-to-error
scroll-to-error
v-if=
"experiment && report"
>
v-if=
"experiment && report"
>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
<el-form-item
label=
"课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验名称"
>
{{
experiment
.
name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
experiment
.
name
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验地点"
>
{{
report
.
experiment_address
}}
</el-form-item>
<el-form-item
label=
"实验地点"
>
{{
report
.
experiment_address
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验日期"
>
{{
report
.
experiment_date
}}
</el-form-item>
<el-form-item
label=
"实验日期"
>
{{
report
.
experiment_date
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验类型"
>
{{
experiment
.
type_level
}}
</el-form-item>
<el-form-item
label=
"实验类型"
>
{{
experiment
.
type_level
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
<el-form-item
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"专业"
>
{{
experiment
.
student
.
specialty
.
name
}}
</el-form-item>
<el-form-item
label=
"专业"
>
{{
experiment
.
student
.
specialty
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"班级"
>
{{
classText
}}
</el-form-item>
<el-form-item
label=
"班级"
>
{{
classText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"姓名"
>
{{
experiment
.
student
.
name
}}
</el-form-item>
<el-form-item
label=
"姓名"
>
{{
experiment
.
student
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学号"
>
{{
experiment
.
student
.
sno_number
}}
</el-form-item>
<el-form-item
label=
"学号"
>
{{
experiment
.
student
.
sno_number
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
@@ -195,7 +197,22 @@ function scoreValue(value) {
...
@@ -195,7 +197,22 @@ function scoreValue(value) {
</
template
>
</
template
>
<!-- 附件 -->
<!-- 附件 -->
<
template
v-if=
"item.type === 2"
>
<
template
v-if=
"item.type === 2"
>
<el-table
:data=
"item.files"
stripe
:header-cell-style=
"
{ background: '#ededed' }" style="margin-top: 20px">
<div
v-if=
"isMobile"
class=
"report-file-card-list"
>
<div
class=
"report-file-card"
v-for=
"(file, fileIndex) in item.files || []"
:key=
"file.id || file.url || fileIndex"
>
<div
class=
"report-file-card__row"
><span>
序号
</span><strong>
{{
fileIndex
+
1
}}
</strong></div>
<div
class=
"report-file-card__row"
>
<span>
附件类型
</span>
<strong>
{{
file
.
type
===
'1'
?
'本地上传'
:
'实验截图'
}}
</strong>
</div>
<div
class=
"report-file-card__row"
><span>
附件名称
</span><strong>
{{
file
.
name
||
'-'
}}
</strong></div>
<div
class=
"report-file-card__row"
><span>
更新时间
</span><strong>
{{
file
.
updated_time
||
'-'
}}
</strong></div>
<div
class=
"report-file-card__actions"
>
<el-button
text
type=
"primary"
><a
:href=
"file.url"
target=
"_blank"
>
查看
</a></el-button>
</div>
</div>
<el-empty
v-if=
"!item.files?.length"
description=
"暂无附件"
/>
</div>
<el-table
v-else
:data=
"item.files"
stripe
:header-cell-style=
"
{ background: '#ededed' }" style="margin-top: 20px">
<el-table-column
label=
"序号"
type=
"index"
width=
"80"
align=
"center"
></el-table-column>
<el-table-column
label=
"序号"
type=
"index"
width=
"80"
align=
"center"
></el-table-column>
<el-table-column
label=
"附件类型"
prop=
"type"
align=
"center"
>
<el-table-column
label=
"附件类型"
prop=
"type"
align=
"center"
>
<template
#
default=
"
{ row }">
<template
#
default=
"
{ row }">
...
@@ -314,6 +331,42 @@ function scoreValue(value) {
...
@@ -314,6 +331,42 @@ function scoreValue(value) {
justify-content
:
space-between
;
justify-content
:
space-between
;
line-height
:
32px
;
line-height
:
32px
;
}
}
.report-file-card-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
margin-top
:
20px
;
}
.report-file-card
{
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
}
.report-file-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
}
.report-file-card__row
:last-of-type
{
border-bottom
:
none
;
}
.report-file-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.report-file-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
word-break
:
break-word
;
}
.report-file-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
8px
;
}
.t2
{
.t2
{
margin
:
40px
0
20px
;
margin
:
40px
0
20px
;
...
@@ -323,4 +376,34 @@ function scoreValue(value) {
...
@@ -323,4 +376,34 @@ function scoreValue(value) {
text-align
:
center
;
text-align
:
center
;
line-height
:
40px
;
line-height
:
40px
;
}
}
@media
(
max-width
:
767px
)
{
.report-title
{
padding
:
12px
0
20px
;
}
.report-score
{
margin
:
24px
0
;
text-align
:
center
;
font-size
:
20px
;
}
.report-form-item
{
margin-bottom
:
24px
;
.form-hd
{
flex-direction
:
column
;
gap
:
8px
;
align-items
:
flex-start
;
span
{
padding
:
0
;
}
}
}
.report-form-item-comment_hd
{
flex-direction
:
column
;
align-items
:
flex-start
;
gap
:
8px
;
}
.t2
{
margin
:
24px
0
16px
;
line-height
:
36px
;
}
}
</
style
>
</
style
>
src/modules/admin/lab/video/views/Index.vue
浏览文件 @
ac045689
...
@@ -85,4 +85,7 @@ function onUpdateSuccess() {
...
@@ -85,4 +85,7 @@ function onUpdateSuccess() {
grid-template-columns
:
repeat
(
5
,
1fr
);
grid-template-columns
:
repeat
(
5
,
1fr
);
gap
:
20px
;
gap
:
20px
;
}
}
@media
(
max-width
:
1400px
)
{
.list-card
{
grid-template-columns
:
repeat
(
3
,
1fr
);
}
}
@media
(
max-width
:
1024px
)
{
.list-card
{
grid-template-columns
:
repeat
(
2
,
1fr
);
gap
:
16px
;
}
}
@media
(
max-width
:
767px
)
{
.list-card
{
grid-template-columns
:
1fr
;
gap
:
12px
;
}
}
</
style
>
</
style
>
src/modules/ai/views/Index.vue
浏览文件 @
ac045689
...
@@ -50,8 +50,8 @@ watch(messages.value, () => nextTick(() => scrollToBottom()))
...
@@ -50,8 +50,8 @@ watch(messages.value, () => nextTick(() => scrollToBottom()))
:srcdoc=
"item.content"
:srcdoc=
"item.content"
frameborder=
"0"
frameborder=
"0"
v-if=
"item.type === 'html'"
v-if=
"item.type === 'html'"
width=
"
900
"
width=
"
100%
"
height=
"
5
00"
></iframe>
height=
"
4
00"
></iframe>
<div
v-html=
"item.content"
v-else
></div>
<div
v-html=
"item.content"
v-else
></div>
</div>
</div>
</div>
</div>
...
@@ -94,7 +94,8 @@ watch(messages.value, () => nextTick(() => scrollToBottom()))
...
@@ -94,7 +94,8 @@ watch(messages.value, () => nextTick(() => scrollToBottom()))
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
flex
:
1
;
flex
:
1
;
width
:
1000px
;
max-width
:
1000px
;
width
:
100%
;
overflow
:
hidden
;
overflow
:
hidden
;
.ai-upload
{
.ai-upload
{
margin
:
40px
0
;
margin
:
40px
0
;
...
@@ -106,6 +107,7 @@ watch(messages.value, () => nextTick(() => scrollToBottom()))
...
@@ -106,6 +107,7 @@ watch(messages.value, () => nextTick(() => scrollToBottom()))
}
}
.ai-header-inner
{
.ai-header-inner
{
max-width
:
1000px
;
max-width
:
1000px
;
width
:
100%
;
padding
:
18px
0
;
padding
:
18px
0
;
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
...
@@ -235,4 +237,8 @@ watch(messages.value, () => nextTick(() => scrollToBottom()))
...
@@ -235,4 +237,8 @@ watch(messages.value, () => nextTick(() => scrollToBottom()))
background-color
:
#000
;
background-color
:
#000
;
}
}
}
}
@media
(
max-width
:
767px
)
{
.ai-header-inner
{
flex-direction
:
column
;
gap
:
8px
;
}
.ai-main
{
padding
:
12px
;
}
}
</
style
>
</
style
>
src/modules/drawLots/views/Index.vue
浏览文件 @
ac045689
...
@@ -106,6 +106,8 @@ function handlePrint() {
...
@@ -106,6 +106,8 @@ function handlePrint() {
background
:
url(@/assets/images/drawLots/bg.png)
no-repeat
center
top
;
background
:
url(@/assets/images/drawLots/bg.png)
no-repeat
center
top
;
.inner
{
.inner
{
max-width
:
1100px
;
max-width
:
1100px
;
width
:
100%
;
padding
:
0
16px
;
margin
:
0
auto
;
margin
:
0
auto
;
}
}
h1
{
h1
{
...
@@ -137,7 +139,8 @@ function handlePrint() {
...
@@ -137,7 +139,8 @@ function handlePrint() {
.box
{
.box
{
position
:
relative
;
position
:
relative
;
z-index
:
100
;
z-index
:
100
;
width
:
800px
;
max-width
:
800px
;
width
:
100%
;
height
:
260px
;
height
:
260px
;
background
:
#ab0a3d
;
background
:
#ab0a3d
;
border-radius
:
8px
;
border-radius
:
8px
;
...
@@ -152,7 +155,8 @@ function handlePrint() {
...
@@ -152,7 +155,8 @@ function handlePrint() {
text-align
:
center
;
text-align
:
center
;
}
}
.box-main
{
.box-main
{
width
:
760px
;
max-width
:
760px
;
width
:
100%
;
height
:
260px
;
height
:
260px
;
background
:
#fff
url(@/assets/images/drawLots/bg3.png)
no-repeat
right
10px
center
;
background
:
#fff
url(@/assets/images/drawLots/bg3.png)
no-repeat
right
10px
center
;
border-radius
:
8px
;
border-radius
:
8px
;
...
@@ -175,7 +179,7 @@ function handlePrint() {
...
@@ -175,7 +179,7 @@ function handlePrint() {
}
}
.box-info
{
.box-info
{
position
:
relative
;
position
:
relative
;
width
:
491px
;
max-width
:
491px
;
width
:
100%
;
height
:
167px
;
height
:
167px
;
background
:
url(@/assets/images/drawLots/bg2.png)
no-repeat
;
background
:
url(@/assets/images/drawLots/bg2.png)
no-repeat
;
display
:
flex
;
display
:
flex
;
...
@@ -240,7 +244,8 @@ function handlePrint() {
...
@@ -240,7 +244,8 @@ function handlePrint() {
position
:
absolute
;
position
:
absolute
;
top
:
0
;
top
:
0
;
left
:
-20px
;
left
:
-20px
;
width
:
840px
;
max-width
:
840px
;
width
:
100%
;
height
:
30px
;
height
:
30px
;
background
:
#ab0a3d
;
background
:
#ab0a3d
;
border-radius
:
8px
;
border-radius
:
8px
;
...
@@ -272,4 +277,124 @@ function handlePrint() {
...
@@ -272,4 +277,124 @@ function handlePrint() {
margin
:
40px
0
20px
;
margin
:
40px
0
20px
;
}
}
}
}
@media
(
max-width
:
767px
)
{
.drawLots
{
background-size
:
cover
;
.inner
{
padding
:
0
12px
24px
;
}
h1
{
padding
:
40px
0
24px
;
font-size
:
28px
;
line-height
:
1
.4
;
}
.search
{
margin
:
0
0
24px
;
flex-wrap
:
wrap
;
gap
:
12px
;
.el-input
{
width
:
100%
;
height
:
48px
;
font-size
:
16px
;
}
.el-button
{
margin-left
:
0
;
width
:
100%
;
height
:
48px
;
font-size
:
16px
;
}
}
.box
{
height
:
auto
;
.box-title
{
padding
:
0
12px
;
font-size
:
18px
;
}
.box-main
{
flex-direction
:
column
;
height
:
auto
;
padding
:
20px
12px
;
gap
:
16px
;
background-position
:
right
bottom
;
background-size
:
120px
auto
;
}
.box-info
{
width
:
100%
;
max-width
:
100%
;
height
:
auto
;
background-size
:
cover
;
background-position
:
center
;
flex-direction
:
column
;
padding
:
16px
12px
;
box-sizing
:
border-box
;
.name
{
position
:
static
;
max-width
:
100%
;
margin-bottom
:
10px
;
white-space
:
normal
;
word-break
:
break-word
;
}
.col
{
width
:
100%
;
margin-top
:
0
;
margin-right
:
0
;
}
dl
{
font-size
:
14px
;
line-height
:
1
.5
;
dt
{
width
:
72px
;
}
dd
{
flex
:
1
;
min-width
:
0
;
word-break
:
break-word
;
}
&
+
dl
{
margin-top
:
12px
;
}
}
}
}
.footer
{
height
:
auto
;
margin-top
:
16px
;
background-size
:
cover
;
background-position
:
center
;
padding
:
28px
0
18px
;
.button
{
max-width
:
100%
;
width
:
100%
;
margin
:
0
auto
;
}
}
}
::v-deep
(
.drawLots-dialog
)
{
.bar
{
left
:
0
;
width
:
100%
;
height
:
20px
;
}
h2
{
margin
:
24px
0
;
font-size
:
22px
;
}
.el-form
{
margin-left
:
0
;
.el-form-item
{
margin-bottom
:
12px
;
}
p
{
font-size
:
18px
;
}
}
.el-button
{
width
:
100%
;
max-width
:
180px
;
height
:
48px
;
font-size
:
16px
;
margin
:
24px
0
12px
;
}
}
}
</
style
>
</
style
>
src/modules/home/components/AdminHome.vue
浏览文件 @
ac045689
...
@@ -51,33 +51,38 @@ function handleChange(id: string, type: number) {
...
@@ -51,33 +51,38 @@ function handleChange(id: string, type: number) {
margin
:
20px
auto
;
margin
:
20px
auto
;
background
:
url(@/assets/images/home_expert_bg.png)
no-repeat
center
center
;
background
:
url(@/assets/images/home_expert_bg.png)
no-repeat
center
center
;
background-size
:
contain
;
background-size
:
contain
;
width
:
1308px
;
width
:
100%
;
max-width
:
1308px
;
height
:
642px
;
height
:
642px
;
.link1
{
.link1
{
position
:
absolute
;
position
:
absolute
;
bottom
:
100px
;
bottom
:
100px
;
width
:
400px
;
width
:
100%
;
max-width
:
400px
;
height
:
300px
;
height
:
300px
;
}
}
.link2
{
.link2
{
position
:
absolute
;
position
:
absolute
;
left
:
450px
;
left
:
450px
;
bottom
:
50px
;
bottom
:
50px
;
width
:
310px
;
width
:
100%
;
max-width
:
310px
;
height
:
250px
;
height
:
250px
;
}
}
.link3
{
.link3
{
position
:
absolute
;
position
:
absolute
;
top
:
0
;
top
:
0
;
right
:
80px
;
right
:
80px
;
width
:
400px
;
width
:
100%
;
max-width
:
400px
;
height
:
300px
;
height
:
300px
;
}
}
.link4
{
.link4
{
position
:
absolute
;
position
:
absolute
;
bottom
:
0
;
bottom
:
0
;
right
:
0
;
right
:
0
;
width
:
400px
;
width
:
100%
;
max-width
:
400px
;
height
:
340px
;
height
:
340px
;
}
}
}
}
...
@@ -94,4 +99,18 @@ function handleChange(id: string, type: number) {
...
@@ -94,4 +99,18 @@ function handleChange(id: string, type: number) {
margin-left
:
20px
;
margin-left
:
20px
;
}
}
}
}
@media
(
max-width
:
1024px
)
{
.bg
{
padding
:
30px
16px
;
}
}
@media
(
max-width
:
767px
)
{
.bg
{
padding
:
20px
12px
;
}
.link1
,
.link2
,
.link3
,
.link4
{
max-width
:
100%
;
margin-bottom
:
16px
;
}
}
</
style
>
</
style
>
src/modules/home/components/StudentHome.vue
浏览文件 @
ac045689
...
@@ -109,7 +109,8 @@ const learnURL = import.meta.env.VITE_SAAS_LEARN_URL
...
@@ -109,7 +109,8 @@ const learnURL = import.meta.env.VITE_SAAS_LEARN_URL
position
:
absolute
;
position
:
absolute
;
top
:
200px
;
top
:
200px
;
right
:
80px
;
right
:
80px
;
width
:
300px
;
width
:
100%
;
max-width
:
300px
;
height
:
300px
;
height
:
300px
;
}
}
}
}
...
@@ -122,26 +123,30 @@ const learnURL = import.meta.env.VITE_SAAS_LEARN_URL
...
@@ -122,26 +123,30 @@ const learnURL = import.meta.env.VITE_SAAS_LEARN_URL
margin
:
20px
auto
;
margin
:
20px
auto
;
background
:
url(@/assets/images/home_student_bg.png)
no-repeat
center
center
;
background
:
url(@/assets/images/home_student_bg.png)
no-repeat
center
center
;
background-size
:
contain
;
background-size
:
contain
;
width
:
1215px
;
width
:
100%
;
max-width
:
1215px
;
height
:
577px
;
height
:
577px
;
.link1
{
.link1
{
position
:
absolute
;
position
:
absolute
;
top
:
160px
;
top
:
160px
;
width
:
250px
;
width
:
100%
;
max-width
:
250px
;
height
:
250px
;
height
:
250px
;
}
}
.link2
{
.link2
{
position
:
absolute
;
position
:
absolute
;
left
:
400px
;
left
:
400px
;
bottom
:
0
;
bottom
:
0
;
width
:
300px
;
width
:
100%
;
max-width
:
300px
;
height
:
250px
;
height
:
250px
;
}
}
.link3
{
.link3
{
position
:
absolute
;
position
:
absolute
;
top
:
200px
;
top
:
200px
;
right
:
0
;
right
:
0
;
width
:
300px
;
width
:
100%
;
max-width
:
300px
;
height
:
300px
;
height
:
300px
;
}
}
}
}
...
@@ -158,4 +163,13 @@ const learnURL = import.meta.env.VITE_SAAS_LEARN_URL
...
@@ -158,4 +163,13 @@ const learnURL = import.meta.env.VITE_SAAS_LEARN_URL
margin-left
:
20px
;
margin-left
:
20px
;
}
}
}
}
@media
(
max-width
:
767px
)
{
.bg
{
padding
:
20px
12px
;
}
.link1
,
.link2
,
.link3
,
.link4
{
max-width
:
100%
;
margin-bottom
:
16px
;
}
}
</
style
>
</
style
>
src/modules/home/components/TeacherHome.vue
浏览文件 @
ac045689
...
@@ -72,33 +72,38 @@ function handleChange(id: string, type: number) {
...
@@ -72,33 +72,38 @@ function handleChange(id: string, type: number) {
margin
:
20px
auto
;
margin
:
20px
auto
;
background
:
url(@/assets/images/home_teacher_bg.png)
no-repeat
center
center
;
background
:
url(@/assets/images/home_teacher_bg.png)
no-repeat
center
center
;
background-size
:
contain
;
background-size
:
contain
;
width
:
1308px
;
width
:
100%
;
max-width
:
1308px
;
height
:
642px
;
height
:
642px
;
.link1
{
.link1
{
position
:
absolute
;
position
:
absolute
;
bottom
:
100px
;
bottom
:
100px
;
width
:
400px
;
width
:
100%
;
max-width
:
400px
;
height
:
300px
;
height
:
300px
;
}
}
.link2
{
.link2
{
position
:
absolute
;
position
:
absolute
;
left
:
450px
;
left
:
450px
;
bottom
:
50px
;
bottom
:
50px
;
width
:
310px
;
width
:
100%
;
max-width
:
310px
;
height
:
250px
;
height
:
250px
;
}
}
.link3
{
.link3
{
position
:
absolute
;
position
:
absolute
;
top
:
0
;
top
:
0
;
right
:
80px
;
right
:
80px
;
width
:
400px
;
width
:
100%
;
max-width
:
400px
;
height
:
300px
;
height
:
300px
;
}
}
.link4
{
.link4
{
position
:
absolute
;
position
:
absolute
;
bottom
:
0
;
bottom
:
0
;
right
:
0
;
right
:
0
;
width
:
400px
;
width
:
100%
;
max-width
:
400px
;
height
:
340px
;
height
:
340px
;
}
}
}
}
...
@@ -115,4 +120,18 @@ function handleChange(id: string, type: number) {
...
@@ -115,4 +120,18 @@ function handleChange(id: string, type: number) {
margin-left
:
20px
;
margin-left
:
20px
;
}
}
}
}
@media
(
max-width
:
1024px
)
{
.bg
{
padding
:
30px
16px
;
}
}
@media
(
max-width
:
767px
)
{
.bg
{
padding
:
20px
12px
;
}
.link1
,
.link2
,
.link3
,
.link4
{
max-width
:
100%
;
margin-bottom
:
16px
;
}
}
</
style
>
</
style
>
src/modules/home/components/Total.vue
浏览文件 @
ac045689
...
@@ -63,6 +63,8 @@ onMounted(() => {
...
@@ -63,6 +63,8 @@ onMounted(() => {
.total
{
.total
{
display
:
flex
;
display
:
flex
;
justify-content
:
space-between
;
justify-content
:
space-between
;
flex-wrap
:
wrap
;
row-gap
:
16px
;
dl
{
dl
{
text-align
:
left
;
text-align
:
left
;
}
}
...
@@ -92,4 +94,24 @@ onMounted(() => {
...
@@ -92,4 +94,24 @@ onMounted(() => {
color
:
#999
;
color
:
#999
;
}
}
}
}
@media
(
max-width
:
767px
)
{
.total
{
justify-content
:
flex-start
;
gap
:
8px
;
padding
:
0
8px
;
}
.total
.line
{
display
:
none
;
}
.total
dl
{
flex
:
0
0
calc
(
50%
-
4px
);
box-sizing
:
border-box
;
padding
:
12px
8px
;
background
:
#fff
;
border-radius
:
8px
;
text-align
:
center
;
}
.total
dt
span
{
font-size
:
22px
;
}
.total
dd
{
font-size
:
13px
;
}
}
</
style
>
</
style
>
src/modules/home/views/Game.vue
浏览文件 @
ac045689
...
@@ -66,12 +66,14 @@ const menus = computed(() => {
...
@@ -66,12 +66,14 @@ const menus = computed(() => {
.card-list
{
.card-list
{
height
:
100%
;
height
:
100%
;
display
:
flex
;
display
:
flex
;
flex-wrap
:
wrap
;
align-items
:
center
;
align-items
:
center
;
justify-content
:
center
;
justify-content
:
center
;
gap
:
30px
;
gap
:
30px
;
}
}
.card
{
.card
{
width
:
310px
;
width
:
100%
;
max-width
:
310px
;
height
:
520px
;
height
:
520px
;
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
...
@@ -79,7 +81,8 @@ const menus = computed(() => {
...
@@ -79,7 +81,8 @@ const menus = computed(() => {
justify-content
:
center
;
justify-content
:
center
;
background-color
:
#fff
;
background-color
:
#fff
;
.icon
{
.icon
{
width
:
246px
;
max-width
:
246px
;
width
:
100%
;
height
:
238px
;
height
:
238px
;
img
{
img
{
width
:
100%
;
width
:
100%
;
...
@@ -93,7 +96,8 @@ const menus = computed(() => {
...
@@ -93,7 +96,8 @@ const menus = computed(() => {
color
:
#578ef9
;
color
:
#578ef9
;
}
}
.button
{
.button
{
width
:
130px
;
max-width
:
130px
;
width
:
100%
;
height
:
40px
;
height
:
40px
;
font-size
:
16px
;
font-size
:
16px
;
line-height
:
40px
;
line-height
:
40px
;
...
@@ -106,4 +110,13 @@ const menus = computed(() => {
...
@@ -106,4 +110,13 @@ const menus = computed(() => {
}
}
}
}
}
}
@media
(
max-width
:
767px
)
{
.card-list
{
flex-direction
:
column
;
gap
:
16px
;
}
.card
{
max-width
:
100%
;
}
}
</
style
>
</
style
>
src/modules/register/views/Index.vue
浏览文件 @
ac045689
...
@@ -114,7 +114,7 @@ const goPage = function () {
...
@@ -114,7 +114,7 @@ const goPage = function () {
<AppCard>
<AppCard>
<div
style=
"position: relative; z-index: 9"
>
<div
style=
"position: relative; z-index: 9"
>
<h1>
2023年全国大学生商业数据分析与应用大赛
</h1>
<h1>
2023年全国大学生商业数据分析与应用大赛
</h1>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
label-width=
"124px"
style=
"
width: 600px; margin: 0 auto
"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
label-width=
"124px"
style=
"
max-width: 600px; width: 100%; margin: 0 auto; padding: 0 16px;
"
>
<!--
<el-form-item
label=
"报名赛项"
>
<!--
<el-form-item
label=
"报名赛项"
>
<el-input
v-model=
"form.name"
disabled
/>
<el-input
v-model=
"form.name"
disabled
/>
</el-form-item>
-->
</el-form-item>
-->
...
@@ -209,14 +209,16 @@ const goPage = function () {
...
@@ -209,14 +209,16 @@ const goPage = function () {
top
:
10%
;
top
:
10%
;
left
:
50%
;
left
:
50%
;
transform
:
translateX
(
-50%
);
transform
:
translateX
(
-50%
);
width
:
202px
;
max-width
:
202px
;
width
:
100%
;
}
}
.pop
{
.pop
{
position
:
absolute
;
position
:
absolute
;
top
:
25%
;
top
:
25%
;
left
:
50%
;
left
:
50%
;
transform
:
translateX
(
-50%
);
transform
:
translateX
(
-50%
);
width
:
366px
;
max-width
:
366px
;
width
:
100%
;
img
{
img
{
width
:
100%
;
width
:
100%
;
}
}
...
@@ -226,7 +228,8 @@ const goPage = function () {
...
@@ -226,7 +228,8 @@ const goPage = function () {
left
:
50%
;
left
:
50%
;
transform
:
translateX
(
-50%
);
transform
:
translateX
(
-50%
);
.btn1
{
.btn1
{
width
:
170px
;
max-width
:
170px
;
width
:
100%
;
line-height
:
50px
;
line-height
:
50px
;
background
:
#e92d55
;
background
:
#e92d55
;
border-radius
:
40px
;
border-radius
:
40px
;
...
@@ -236,7 +239,8 @@ const goPage = function () {
...
@@ -236,7 +239,8 @@ const goPage = function () {
cursor
:
pointer
;
cursor
:
pointer
;
}
}
.btn2
{
.btn2
{
width
:
170px
;
max-width
:
170px
;
width
:
100%
;
line-height
:
50px
;
line-height
:
50px
;
border
:
1px
solid
#e92d55
;
border
:
1px
solid
#e92d55
;
border-radius
:
40px
;
border-radius
:
40px
;
...
@@ -281,7 +285,8 @@ const goPage = function () {
...
@@ -281,7 +285,8 @@ const goPage = function () {
top
:
50%
;
top
:
50%
;
left
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
transform
:
translate
(
-50%
,
-50%
);
width
:
400px
;
width
:
100%
;
max-width
:
400px
;
height
:
450px
;
height
:
450px
;
background
:
#fff
;
background
:
#fff
;
border-radius
:
40px
;
border-radius
:
40px
;
...
@@ -290,10 +295,12 @@ const goPage = function () {
...
@@ -290,10 +295,12 @@ const goPage = function () {
top
:
-25px
;
top
:
-25px
;
left
:
50%
;
left
:
50%
;
transform
:
translateX
(
-50%
);
transform
:
translateX
(
-50%
);
width
:
276px
;
max-width
:
276px
;
width
:
100%
;
}
}
.text-box
{
.text-box
{
width
:
300px
;
max-width
:
300px
;
width
:
100%
;
padding-top
:
187px
;
padding-top
:
187px
;
margin
:
0
auto
;
margin
:
0
auto
;
text-align
:
center
;
text-align
:
center
;
...
@@ -312,7 +319,8 @@ const goPage = function () {
...
@@ -312,7 +319,8 @@ const goPage = function () {
.btn
{
.btn
{
text-align
:
center
;
text-align
:
center
;
margin
:
0
auto
;
margin
:
0
auto
;
width
:
240px
;
max-width
:
240px
;
width
:
100%
;
line-height
:
88px
;
line-height
:
88px
;
background
:
#e92d55
;
background
:
#e92d55
;
box-shadow
:
0px
20px
30px
#ffd3dc
;
box-shadow
:
0px
20px
30px
#ffd3dc
;
...
@@ -325,4 +333,9 @@ const goPage = function () {
...
@@ -325,4 +333,9 @@ const goPage = function () {
}
}
}
}
}
}
@media
(
max-width
:
767px
)
{
.content
{
padding
:
20px
12px
;
}
}
</
style
>
</
style
>
src/modules/student/contest/components/DiscussItem.vue
浏览文件 @
ac045689
...
@@ -68,6 +68,8 @@ const commentVisible = $ref(false)
...
@@ -68,6 +68,8 @@ const commentVisible = $ref(false)
.discuss-box-user
{
.discuss-box-user
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
flex-wrap
:
wrap
;
min-width
:
0
;
}
}
.discuss-box-user__avatar
{
.discuss-box-user__avatar
{
width
:
40px
;
width
:
40px
;
...
@@ -112,6 +114,7 @@ const commentVisible = $ref(false)
...
@@ -112,6 +114,7 @@ const commentVisible = $ref(false)
font-weight
:
400
;
font-weight
:
400
;
line-height
:
24px
;
line-height
:
24px
;
color
:
#333333
;
color
:
#333333
;
word-break
:
break-word
;
}
}
.discuss-box-footer
{
.discuss-box-footer
{
display
:
flex
;
display
:
flex
;
...
@@ -154,6 +157,7 @@ const commentVisible = $ref(false)
...
@@ -154,6 +157,7 @@ const commentVisible = $ref(false)
margin-left
:
10px
;
margin-left
:
10px
;
color
:
#333
;
color
:
#333
;
overflow
:
hidden
;
overflow
:
hidden
;
word-break
:
break-word
;
}
}
.discuss-comment__username
{
.discuss-comment__username
{
font-size
:
16px
;
font-size
:
16px
;
...
@@ -167,4 +171,7 @@ const commentVisible = $ref(false)
...
@@ -167,4 +171,7 @@ const commentVisible = $ref(false)
color
:
#999999
;
color
:
#999999
;
text-align
:
right
;
text-align
:
right
;
}
}
@media
(
max-width
:
767px
)
{
.discuss-item
{
padding
:
12px
8px
;
}
}
</
style
>
</
style
>
src/modules/student/contest/views/Index.vue
浏览文件 @
ac045689
...
@@ -44,4 +44,6 @@ onMounted(() => {
...
@@ -44,4 +44,6 @@ onMounted(() => {
grid-template-columns
:
repeat
(
4
,
1fr
);
grid-template-columns
:
repeat
(
4
,
1fr
);
gap
:
20px
;
gap
:
20px
;
}
}
@media
(
max-width
:
1024px
)
{
.contest-list
{
grid-template-columns
:
repeat
(
2
,
1fr
);
gap
:
16px
;
}
}
@media
(
max-width
:
767px
)
{
.contest-list
{
grid-template-columns
:
1fr
;
gap
:
12px
;
}
}
</
style
>
</
style
>
src/modules/student/contest/views/Join.vue
浏览文件 @
ac045689
...
@@ -113,7 +113,7 @@ function handleCancel() {
...
@@ -113,7 +113,7 @@ function handleCancel() {
<
template
>
<
template
>
<AppCard
title=
"大赛报名"
>
<AppCard
title=
"大赛报名"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
label-width=
"124px"
style=
"
width: 600px; margin: 0 auto
"
>
<el-form
ref=
"formRef"
:model=
"form"
:rules=
"rules"
label-width=
"124px"
style=
"
max-width: 600px; width: 100%; margin: 0 auto; padding: 0 12px;
"
>
<el-form-item
label=
"报名赛项"
>
<el-form-item
label=
"报名赛项"
>
<el-input
v-model=
"form.name"
disabled
/>
<el-input
v-model=
"form.name"
disabled
/>
</el-form-item>
</el-form-item>
...
...
src/modules/student/contest/views/Score.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
getScoreReport
,
getMyContestList
}
from
'../api'
import
{
getScoreReport
,
getMyContestList
}
from
'../api'
import
{
useMediaQuery
}
from
'@vueuse/core'
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
let
eventValue
=
$ref
(
''
)
let
eventValue
=
$ref
(
''
)
let
eventOption
:
any
=
$ref
([])
let
eventOption
:
any
=
$ref
([])
...
@@ -28,15 +31,23 @@ const selectChange = function () {
...
@@ -28,15 +31,23 @@ const selectChange = function () {
<
template
>
<
template
>
<AppCard>
<AppCard>
<h1>
2024 年湖北工匠杯成绩查询
</h1>
<h1>
2024 年湖北工匠杯成绩查询
</h1>
<div
style=
"display: flex; align-items: center; padding-top: 30px"
>
<div
style=
"display: flex; align-items: center; padding-top: 30px
; flex-wrap: wrap
"
>
<span
style=
"margin-right: 10px"
>
赛项
</span>
<span
style=
"margin-right: 10px"
>
赛项
</span>
<el-select
style=
"width: 320px"
v-model=
"eventValue"
placeholder=
"请选择"
@
change=
"selectChange"
>
<el-select
style=
"width:
100%; max-width:
320px"
v-model=
"eventValue"
placeholder=
"请选择"
@
change=
"selectChange"
>
<el-option
v-for=
"item in eventOption"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
<el-option
v-for=
"item in eventOption"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-select>
</div>
</div>
<h3>
考生基础信息
</h3>
<h3>
考生基础信息
</h3>
<!--
{{
scoreInfo
?.
id
?
[
scoreInfo
]
:
[]
}}
-->
<div
v-if=
"isMobile && scoreInfo?.id"
class=
"mobile-score-card"
>
<el-table
:data=
"scoreInfo?.id ? [scoreInfo] : []"
stripe
:header-cell-style=
"
{ background: '#ededed' }">
<div
class=
"mobile-score-card__row"
><span>
选手姓名
</span><strong>
{{
scoreInfo
.
student
?.
name
||
'-'
}}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
参赛ID
</span><strong>
{{
scoreInfo
.
id
||
'-'
}}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
性别
</span><strong>
{{
scoreInfo
.
student
?.
gender
===
1
?
'男'
:
'女'
}}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
学校
</span><strong>
{{
scoreInfo
.
org
?.
name
||
'-'
}}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
所在专业
</span><strong>
{{
scoreInfo
.
specialty
?.
name
||
'-'
}}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
所在年级
</span><strong>
{{
scoreInfo
.
grade
||
'-'
}}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
联系电话
</span><strong>
{{
scoreInfo
.
student
?.
mobile
||
'-'
}}
</strong></div>
</div>
<el-table
v-else
:data=
"scoreInfo?.id ? [scoreInfo] : []"
stripe
:header-cell-style=
"
{ background: '#ededed' }">
<el-table-column
prop=
"student.name"
label=
"选手姓名"
/>
<el-table-column
prop=
"student.name"
label=
"选手姓名"
/>
<el-table-column
prop=
"id"
label=
"参赛ID"
/>
<el-table-column
prop=
"id"
label=
"参赛ID"
/>
<el-table-column
label=
"性别"
>
<el-table-column
label=
"性别"
>
...
@@ -57,7 +68,21 @@ const selectChange = function () {
...
@@ -57,7 +68,21 @@ const selectChange = function () {
{ label: '占比(%)', prop: 'ratio' },
{ label: '占比(%)', prop: 'ratio' },
{ label: '实际得分', prop: 'score' }
{ label: '实际得分', prop: 'score' }
] -->
] -->
<el-table
:data=
"scoreInfo?.score_detail"
stripe
:header-cell-style=
"{ background: '#ededed' }"
>
<div
v-if=
"isMobile"
class=
"mobile-score-list"
>
<div
class=
"mobile-score-card"
v-for=
"(item, index) in scoreInfo?.score_detail || []"
:key=
"index"
>
<div
class=
"mobile-score-card__row"
><span>
桌号
</span><strong>
{{ item.extension?.table_number || '-' }}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
考试账号
</span><strong>
{{ item.extension?.account || '-' }}
</strong></div>
<div
class=
"mobile-score-card__row"
>
<span>
考试类型
</span>
<strong>
{{ item.extension?.type === '2' ? '商业数据分析师实操考试' : '理论考试' }}
</strong>
</div>
<div
class=
"mobile-score-card__row"
><span>
分值
</span><strong>
{{ item.old_score || '-' }}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
占比(%)
</span><strong>
{{ item.ratio || '-' }}
</strong></div>
<div
class=
"mobile-score-card__row"
><span>
实际得分
</span><strong>
{{ item.score || '-' }}
</strong></div>
</div>
<el-empty
v-if=
"!scoreInfo?.score_detail?.length"
description=
"暂无成绩数据"
/>
</div>
<el-table
v-else
:data=
"scoreInfo?.score_detail"
stripe
:header-cell-style=
"{ background: '#ededed' }"
>
<el-table-column
prop=
"extension.table_number"
label=
"桌号"
/>
<el-table-column
prop=
"extension.table_number"
label=
"桌号"
/>
<el-table-column
prop=
"extension.account"
label=
"考试账号"
/>
<el-table-column
prop=
"extension.account"
label=
"考试账号"
/>
<el-table-column
prop=
"extension.type"
label=
"考试类型"
>
<el-table-column
prop=
"extension.type"
label=
"考试类型"
>
...
@@ -90,4 +115,37 @@ h3 {
...
@@ -90,4 +115,37 @@ h3 {
padding-top
:
40px
;
padding-top
:
40px
;
line-height
:
30px
;
line-height
:
30px
;
}
}
.mobile-score-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.mobile-score-card
{
margin-top
:
12px
;
padding
:
14px
16px
;
background
:
#fff
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
}
.mobile-score-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
font-size
:
14px
;
}
.mobile-score-card__row
:last-child
{
border-bottom
:
none
;
}
.mobile-score-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.mobile-score-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
color
:
#303133
;
word-break
:
break-word
;
}
</
style
>
</
style
>
src/modules/student/lab/components/BindCaptureDialog.vue
浏览文件 @
ac045689
<
script
setup
>
<
script
setup
>
import
{
getExperimentRecord
}
from
'../api'
import
{
getExperimentRecord
}
from
'../api'
import
{
useNow
,
useDateFormat
}
from
'@vueuse/core'
import
{
useNow
,
useDateFormat
}
from
'@vueuse/core'
import
{
useMediaQuery
}
from
'@vueuse/core'
const
props
=
defineProps
({
experiment
:
Object
,
data
:
Object
})
const
props
=
defineProps
({
experiment
:
Object
,
data
:
Object
})
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
emit
=
defineEmits
([
'update'
,
'update:modelValue'
])
const
emit
=
defineEmits
([
'update'
,
'update:modelValue'
])
...
@@ -50,7 +52,24 @@ function handleRemove(row) {
...
@@ -50,7 +52,24 @@ function handleRemove(row) {
<
template
>
<
template
>
<el-dialog
append-to-body
title=
"关联截图"
width=
"800px"
@
update:modelValue=
"value => $emit('update:modelValue', value)"
>
<el-dialog
append-to-body
title=
"关联截图"
width=
"800px"
@
update:modelValue=
"value => $emit('update:modelValue', value)"
>
<el-table
:data=
"currentPictures"
stripe
>
<div
v-if=
"isMobile"
class=
"capture-card-list"
>
<div
class=
"capture-card"
v-for=
"row in currentPictures"
:key=
"row.url"
>
<div
class=
"capture-card__row"
>
<span>
截图名称
</span>
<el-link
type=
"primary"
:href=
"row.url"
target=
"_blank"
>
{{
row
.
name
}}
</el-link>
</div>
<div
class=
"capture-card__row"
>
<span>
上传时间
</span>
<strong>
{{
row
.
upload_time
||
'-'
}}
</strong>
</div>
<div
class=
"capture-card__actions"
>
<el-button
text
type=
"danger"
@
click=
"handleRemove(row)"
v-if=
"row.is_bind"
>
取消关联
</el-button>
<el-button
text
type=
"primary"
@
click=
"handleBind(row)"
v-else
>
关联截图
</el-button>
</div>
</div>
<el-empty
v-if=
"!currentPictures.length"
description=
"暂无截图"
/>
</div>
<el-table
v-else
:data=
"currentPictures"
stripe
>
<el-table-column
prop=
"name"
>
<el-table-column
prop=
"name"
>
<template
#
default=
"
{ row }">
<template
#
default=
"
{ row }">
<el-link
type=
"primary"
:href=
"row.url"
target=
"_blank"
>
{{
row
.
name
}}
</el-link>
<el-link
type=
"primary"
:href=
"row.url"
target=
"_blank"
>
{{
row
.
name
}}
</el-link>
...
@@ -71,3 +90,41 @@ function handleRemove(row) {
...
@@ -71,3 +90,41 @@ function handleRemove(row) {
</
template
>
</
template
>
</el-dialog>
</el-dialog>
</template>
</template>
<
style
scoped
>
.capture-card-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.capture-card
{
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
}
.capture-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
}
.capture-card__row
:last-of-type
{
border-bottom
:
none
;
}
.capture-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.capture-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
word-break
:
break-word
;
}
.capture-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
8px
;
}
</
style
>
src/modules/student/lab/components/DiscussItem.vue
浏览文件 @
ac045689
...
@@ -68,6 +68,8 @@ const commentVisible = $ref(false)
...
@@ -68,6 +68,8 @@ const commentVisible = $ref(false)
.discuss-box-user
{
.discuss-box-user
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
flex-wrap
:
wrap
;
min-width
:
0
;
}
}
.discuss-box-user__avatar
{
.discuss-box-user__avatar
{
width
:
40px
;
width
:
40px
;
...
@@ -112,6 +114,7 @@ const commentVisible = $ref(false)
...
@@ -112,6 +114,7 @@ const commentVisible = $ref(false)
font-weight
:
400
;
font-weight
:
400
;
line-height
:
24px
;
line-height
:
24px
;
color
:
#333333
;
color
:
#333333
;
word-break
:
break-word
;
}
}
.discuss-box-footer
{
.discuss-box-footer
{
display
:
flex
;
display
:
flex
;
...
@@ -154,6 +157,7 @@ const commentVisible = $ref(false)
...
@@ -154,6 +157,7 @@ const commentVisible = $ref(false)
margin-left
:
10px
;
margin-left
:
10px
;
color
:
#333
;
color
:
#333
;
overflow
:
hidden
;
overflow
:
hidden
;
word-break
:
break-word
;
}
}
.discuss-comment__username
{
.discuss-comment__username
{
font-size
:
16px
;
font-size
:
16px
;
...
@@ -167,4 +171,7 @@ const commentVisible = $ref(false)
...
@@ -167,4 +171,7 @@ const commentVisible = $ref(false)
color
:
#999999
;
color
:
#999999
;
text-align
:
right
;
text-align
:
right
;
}
}
@media
(
max-width
:
767px
)
{
.discuss-item
{
padding
:
12px
8px
;
}
}
</
style
>
</
style
>
src/modules/student/lab/components/Info.vue
浏览文件 @
ac045689
...
@@ -3,7 +3,7 @@ const props = defineProps({ data: Object })
...
@@ -3,7 +3,7 @@ const props = defineProps({ data: Object })
const
teacherText
=
$computed
(()
=>
{
const
teacherText
=
$computed
(()
=>
{
if
(
!
props
.
data
)
return
''
if
(
!
props
.
data
)
return
''
return
props
.
data
.
teachers
.
map
(
item
=>
item
.
name
).
join
(
'、'
)
return
props
.
data
.
teachers
.
map
(
(
item
)
=>
item
.
name
).
join
(
'、'
)
})
})
</
script
>
</
script
>
...
@@ -20,10 +20,10 @@ const teacherText = $computed(() => {
...
@@ -20,10 +20,10 @@ const teacherText = $computed(() => {
</el-form>
</el-form>
<el-divider
/>
<el-divider
/>
<el-form
label-suffix=
":"
label-position=
"top"
>
<el-form
label-suffix=
":"
label-position=
"top"
>
<el-form-item
label=
"实验目的"
>
{{
data
.
purpose
}}
</el-form-item>
<el-form-item
label=
"实验目的"
v-if=
"data.purpose"
>
{{
data
.
purpose
}}
</el-form-item>
<el-form-item
label=
"实验要求"
>
{{
data
.
requirements
}}
</el-form-item>
<el-form-item
label=
"实验要求"
v-if=
"data.requirements"
>
{{
data
.
requirements
}}
</el-form-item>
<el-form-item
label=
"实验内容及原理"
>
{{
data
.
content
}}
</el-form-item>
<el-form-item
label=
"实验内容及原理"
v-if=
"data.content"
>
{{
data
.
content
}}
</el-form-item>
<el-form-item
label=
"实验步骤及过程"
>
{{
data
.
procedure
}}
</el-form-item>
<el-form-item
label=
"实验步骤及过程"
v-if=
"data.procedure"
>
{{
data
.
procedure
}}
</el-form-item>
</el-form>
</el-form>
</
template
>
</
template
>
<el-empty
description=
"暂无数据"
v-else
/>
<el-empty
description=
"暂无数据"
v-else
/>
...
...
src/modules/student/lab/components/ReportFilePreview.vue
浏览文件 @
ac045689
...
@@ -18,26 +18,26 @@ const detail = $ref(inject<ExperimentRecord>('detail'))
...
@@ -18,26 +18,26 @@ const detail = $ref(inject<ExperimentRecord>('detail'))
<el-dialog
title=
"查看实验报告"
:close-on-click-modal=
"false"
width=
"600px"
>
<el-dialog
title=
"查看实验报告"
:close-on-click-modal=
"false"
width=
"600px"
>
<el-form
label-suffix=
":"
label-width=
"110px"
label-position=
"right"
>
<el-form
label-suffix=
":"
label-width=
"110px"
label-position=
"right"
>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验名称"
>
{{
data
.
name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
data
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验课程名称"
>
{{
data
.
course
.
name
}}
</el-form-item>
<el-form-item
label=
"实验课程名称"
>
{{
data
.
course
.
name
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学生姓名"
>
{{
data
.
student
.
name
}}
</el-form-item>
<el-form-item
label=
"学生姓名"
>
{{
data
.
student
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学生学号"
>
{{
data
.
student
.
sno_number
}}
</el-form-item>
<el-form-item
label=
"学生学号"
>
{{
data
.
student
.
sno_number
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"所属专业"
>
{{
data
.
student
.
specialty
.
name
}}
</el-form-item>
<el-form-item
label=
"所属专业"
>
{{
data
.
student
.
specialty
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"所属班级"
>
{{
classText
}}
</el-form-item>
<el-form-item
label=
"所属班级"
>
{{
classText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
...
src/modules/student/lab/components/ReportPreview.vue
浏览文件 @
ac045689
<
script
setup
>
<
script
setup
>
import
{
getExperimentReport
}
from
'../api'
import
{
getExperimentReport
}
from
'../api'
import
{
useMediaQuery
}
from
'@vueuse/core'
const
props
=
defineProps
({
id
:
String
,
makePdf
:
Boolean
})
const
props
=
defineProps
({
id
:
String
,
makePdf
:
Boolean
})
const
emit
=
defineEmits
([
'ready'
])
const
emit
=
defineEmits
([
'ready'
])
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
let
experiment
=
$ref
()
let
experiment
=
$ref
()
let
report
=
$ref
()
let
report
=
$ref
()
...
@@ -62,42 +64,42 @@ function handleClose() {
...
@@ -62,42 +64,42 @@ function handleClose() {
<h1
class=
"report-title"
>
实验报告
</h1>
<h1
class=
"report-title"
>
实验报告
</h1>
<el-form
label-suffix=
":"
hide-required-asterisk
v-if=
"experiment"
>
<el-form
label-suffix=
":"
hide-required-asterisk
v-if=
"experiment"
>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
<el-form-item
label=
"课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验名称"
>
{{
experiment
.
name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
experiment
.
name
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验地点"
>
{{
report
.
experiment_address
}}
</el-form-item>
<el-form-item
label=
"实验地点"
>
{{
report
.
experiment_address
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验日期"
>
{{
report
.
experiment_date
}}
</el-form-item>
<el-form-item
label=
"实验日期"
>
{{
report
.
experiment_date
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验类型"
>
{{
experiment
.
type_level
}}
</el-form-item>
<el-form-item
label=
"实验类型"
>
{{
experiment
.
type_level
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
<el-form-item
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"专业"
>
{{
experiment
.
student
.
specialty
.
name
}}
</el-form-item>
<el-form-item
label=
"专业"
>
{{
experiment
.
student
.
specialty
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"班级"
>
{{
classText
}}
</el-form-item>
<el-form-item
label=
"班级"
>
{{
classText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"姓名"
>
{{
experiment
.
student
.
name
}}
</el-form-item>
<el-form-item
label=
"姓名"
>
{{
experiment
.
student
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学号"
>
{{
experiment
.
student
.
sno_number
}}
</el-form-item>
<el-form-item
label=
"学号"
>
{{
experiment
.
student
.
sno_number
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
@@ -121,7 +123,23 @@ function handleClose() {
...
@@ -121,7 +123,23 @@ function handleClose() {
</
template
>
</
template
>
<!-- 附件 -->
<!-- 附件 -->
<
template
v-if=
"item.type === 2"
>
<
template
v-if=
"item.type === 2"
>
<div
v-if=
"isMobile && !makePdf"
class=
"report-file-card-list"
>
<div
class=
"report-file-card"
v-for=
"(file, fileIndex) in item.files"
:key=
"file.id || file.url || fileIndex"
>
<div
class=
"report-file-card__row"
><span>
序号
</span><strong>
{{
fileIndex
+
1
}}
</strong></div>
<div
class=
"report-file-card__row"
>
<span>
附件类型
</span>
<strong>
{{
file
.
type
===
'1'
?
'本地上传'
:
'实验截图'
}}
</strong>
</div>
<div
class=
"report-file-card__row"
><span>
附件名称
</span><strong>
{{
file
.
name
||
'-'
}}
</strong></div>
<div
class=
"report-file-card__row"
><span>
更新时间
</span><strong>
{{
file
.
updated_time
||
'-'
}}
</strong></div>
<div
class=
"report-file-card__actions"
>
<el-button
text
type=
"primary"
><a
:href=
"file.url"
target=
"_blank"
>
查看
</a></el-button>
</div>
</div>
<el-empty
v-if=
"!item.files?.length"
description=
"暂无附件"
/>
</div>
<el-table
<el-table
v-else
:data=
"item.files"
:data=
"item.files"
stripe
stripe
:header-cell-style=
"
{ background: '#ededed' }"
:header-cell-style=
"
{ background: '#ededed' }"
...
@@ -221,4 +239,60 @@ function handleClose() {
...
@@ -221,4 +239,60 @@ function handleClose() {
border
:
1px
solid
var
(
--
main-color
);
border
:
1px
solid
var
(
--
main-color
);
border-radius
:
6px
;
border-radius
:
6px
;
}
}
.report-file-card-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
margin-top
:
20px
;
}
.report-file-card
{
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
}
.report-file-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
}
.report-file-card__row
:last-of-type
{
border-bottom
:
none
;
}
.report-file-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.report-file-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
word-break
:
break-word
;
}
.report-file-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
padding-top
:
8px
;
}
@media
(
max-width
:
767px
)
{
.report-preview__inner
{
padding
:
20px
12px
;
}
.report-title
{
padding
:
12px
0
20px
;
}
.report-form-item
{
margin-bottom
:
24px
;
.form-hd
{
flex-direction
:
column
;
gap
:
6px
;
align-items
:
flex-start
;
}
}
.report-score
{
margin
:
24px
0
;
font-size
:
20px
;
}
}
</
style
>
</
style
>
src/modules/student/lab/components/Result.vue
浏览文件 @
ac045689
...
@@ -203,4 +203,38 @@ h3 {
...
@@ -203,4 +203,38 @@ h3 {
}
}
}
}
}
}
@media
(
max-width
:
767px
)
{
.picture-list
{
li
{
height
:
auto
;
margin
:
16px
0
;
img
{
display
:
block
;
aspect-ratio
:
16
/
9
;
}
p
{
position
:
static
;
padding
:
8px
10px
0
;
color
:
#666
;
text-align
:
left
;
background
:
none
;
}
}
.cover
{
display
:
block
;
position
:
static
;
background
:
none
;
}
.cover-inner
{
flex-direction
:
row
;
justify-content
:
flex-start
;
gap
:
10px
;
padding
:
10px
;
.el-button
{
width
:
auto
;
margin
:
0
;
}
}
}
}
</
style
>
</
style
>
src/modules/student/lab/components/ResultScoreDialog.vue
浏览文件 @
ac045689
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
getExperimentScore
}
from
'../api'
import
{
getExperimentScore
}
from
'../api'
import
{
useMediaQuery
}
from
'@vueuse/core'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
const
appConfig
=
useAppConfig
()
const
appConfig
=
useAppConfig
()
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
ResultScoreViewAutoDialog
=
defineAsyncComponent
(()
=>
import
(
'./ResultScoreViewAutoDialog.vue'
))
const
ResultScoreViewAutoDialog
=
defineAsyncComponent
(()
=>
import
(
'./ResultScoreViewAutoDialog.vue'
))
...
@@ -95,30 +97,30 @@ function handleViewAuto(row: any) {
...
@@ -95,30 +97,30 @@ function handleViewAuto(row: any) {
<el-form-item
label=
"实验名称"
>
{{
experiment
.
name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
experiment
.
name
}}
</el-form-item>
<el-form-item
label=
"实验课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
<el-form-item
label=
"实验课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学生姓名"
>
{{
experiment
.
student
.
name
}}
</el-form-item>
<el-form-item
label=
"学生姓名"
>
{{
experiment
.
student
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学生学号"
>
{{
experiment
.
student
.
sno_number
}}
</el-form-item>
<el-form-item
label=
"学生学号"
>
{{
experiment
.
student
.
sno_number
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"所属专业"
>
{{
experiment
.
student
.
specialty
.
name
}}
</el-form-item>
<el-form-item
label=
"所属专业"
>
{{
experiment
.
student
.
specialty
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"所属班级"
>
{{
classText
}}
</el-form-item>
<el-form-item
label=
"所属班级"
>
{{
classText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"评分教师"
>
<el-form-item
label=
"评分教师"
>
{{
{{
detail
.
checker_sso_user
.
real_name
||
detail
.
checker_sso_user
.
nickname
||
detail
.
checker_sso_user
.
username
detail
.
checker_sso_user
.
real_name
||
detail
.
checker_sso_user
.
nickname
||
detail
.
checker_sso_user
.
username
}}
}}
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"评分时间"
>
{{
detail
.
check_time
}}
</el-form-item>
<el-form-item
label=
"评分时间"
>
{{
detail
.
check_time
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
@@ -127,11 +129,34 @@ function handleViewAuto(row: any) {
...
@@ -127,11 +129,34 @@ function handleViewAuto(row: any) {
<p>
实验得分
</p>
<p>
实验得分
</p>
<p
class=
"t1"
>
{{
detail
.
score
}}
</p>
<p
class=
"t1"
>
{{
detail
.
score
}}
</p>
</div>
</div>
<div
v-if=
"detail.is_show === '1' && isMobile"
class=
"score-detail-card-list"
>
<div
class=
"score-detail-card"
v-for=
"row in detail.score_details"
:key=
"`$
{row.type}-${row.name}`">
<div
class=
"score-detail-card__row"
><span>
实验成绩组成项
</span><strong>
{{
row
.
name
||
'-'
}}
</strong></div>
<div
class=
"score-detail-card__row"
><span>
权重
</span><strong>
{{
row
.
percent
}}
%
</strong></div>
<div
class=
"score-detail-card__row"
>
<span>
得分
</span>
<strong>
{{
row
.
commit_score
}}
<template
v-if=
"(row.type === 1 && experiment.report_upload_way === 2) || row.type === 8"
>
<el-button
text
type=
"primary"
>
<a
:href=
"getOperationUrl(row.type)"
target=
"_blank"
>
查看明细
</a>
</el-button>
</
template
>
</strong>
</div>
<div
class=
"score-detail-card__actions"
>
<el-button
type=
"primary"
link
@
click=
"handleViewAuto(row)"
v-if=
"[6, 7, 9, 11, 12].includes(row.type)"
>
查看标准答案
</el-button>
<el-button
link
type=
"primary"
>
<a
:href=
"getOperationUrl(row.type)"
target=
"_blank"
>
查看我的答案
</a>
</el-button>
</div>
</div>
</div>
<el-table
<el-table
:data=
"detail.score_details"
:data=
"detail.score_details"
stripe
stripe
:header-cell-style=
"{ background: '#ededed' }"
:header-cell-style=
"{ background: '#ededed' }"
v-if="detail.is_show === '1'">
v-
else-
if=
"detail.is_show === '1'"
>
<el-table-column
label=
"实验成绩组成项"
prop=
"name"
align=
"center"
></el-table-column>
<el-table-column
label=
"实验成绩组成项"
prop=
"name"
align=
"center"
></el-table-column>
<el-table-column
label=
"权重"
prop=
"percent"
align=
"center"
>
<el-table-column
label=
"权重"
prop=
"percent"
align=
"center"
>
<
template
#
default=
"{ row }"
>
{{
row
.
percent
}}
%
</
template
>
<
template
#
default=
"{ row }"
>
{{
row
.
percent
}}
%
</
template
>
...
@@ -188,6 +213,7 @@ function handleViewAuto(row: any) {
...
@@ -188,6 +213,7 @@ function handleViewAuto(row: any) {
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
justify-content
:
center
;
justify-content
:
center
;
gap
:
24px
;
}
}
.form-result__score
{
.form-result__score
{
padding
:
40px
;
padding
:
40px
;
...
@@ -198,4 +224,51 @@ function handleViewAuto(row: any) {
...
@@ -198,4 +224,51 @@ function handleViewAuto(row: any) {
color
:
var
(
--
main-color
);
color
:
var
(
--
main-color
);
}
}
}
}
.score-detail-card-list
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.score-detail-card
{
padding
:
14px
16px
;
background
:
#fff
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
}
.score-detail-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
}
.score-detail-card__row
:last-of-type
{
border-bottom
:
none
;
}
.score-detail-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.score-detail-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
word-break
:
break-word
;
}
.score-detail-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
flex-wrap
:
wrap
;
gap
:
8px
;
padding-top
:
8px
;
}
@media
(
max-width
:
767px
)
{
.form-result
{
flex-direction
:
column
;
align-items
:
stretch
;
}
.form-result__score
{
padding
:
20px
;
}
}
</
style
>
</
style
>
src/modules/student/lab/views/Competition.vue
浏览文件 @
ac045689
...
@@ -185,11 +185,16 @@ useEventListener(window, 'message', async (event) => {
...
@@ -185,11 +185,16 @@ useEventListener(window, 'message', async (event) => {
width
:
100%
;
width
:
100%
;
margin-top
:
20px
;
margin-top
:
20px
;
display
:
flex
;
display
:
flex
;
align-items
:
stretch
;
min-height
:
0
;
}
}
.iframe
{
.iframe
{
display
:
block
;
flex
:
1
;
width
:
100%
;
width
:
100%
;
height
:
100%
;
height
:
100%
;
min-height
:
100%
;
}
}
.welcome-box
{
.welcome-box
{
...
@@ -198,7 +203,8 @@ useEventListener(window, 'message', async (event) => {
...
@@ -198,7 +203,8 @@ useEventListener(window, 'message', async (event) => {
.entry-btn
{
.entry-btn
{
display
:
block
;
display
:
block
;
width
:
300px
;
max-width
:
300px
;
width
:
100%
;
margin
:
100px
auto
;
margin
:
100px
auto
;
}
}
}
}
...
@@ -214,6 +220,7 @@ useEventListener(window, 'message', async (event) => {
...
@@ -214,6 +220,7 @@ useEventListener(window, 'message', async (event) => {
.welcome-box-header-content
{
.welcome-box-header-content
{
width
:
100%
;
width
:
100%
;
max-width
:
1000px
;
max-width
:
1000px
;
padding
:
0
16px
;
margin
:
0
auto
;
margin
:
0
auto
;
color
:
#fff
;
color
:
#fff
;
padding
:
40px
0
;
padding
:
40px
0
;
...
@@ -253,4 +260,22 @@ useEventListener(window, 'message', async (event) => {
...
@@ -253,4 +260,22 @@ useEventListener(window, 'message', async (event) => {
text-shadow
:
0px
2px
4px
rgba
(
0
,
0
,
0
,
0
.5
);
text-shadow
:
0px
2px
4px
rgba
(
0
,
0
,
0
,
0
.5
);
}
}
}
}
@media
(
max-width
:
767px
)
{
.iframe-box
{
margin-top
:
12px
;
display
:
block
;
height
:
74vh
;
min-height
:
74vh
;
overflow
:
hidden
;
}
.iframe
{
height
:
74vh
;
min-height
:
74vh
;
}
.welcome-box-header
{
padding
:
40px
16px
;
}
}
</
style
>
</
style
>
src/modules/student/lab/views/Index.vue
浏览文件 @
ac045689
差异被折叠。
点击展开。
src/modules/student/lab/views/Report.vue
浏览文件 @
ac045689
...
@@ -3,6 +3,7 @@ import AppEditor from '@/components/base/AppEditor.vue'
...
@@ -3,6 +3,7 @@ import AppEditor from '@/components/base/AppEditor.vue'
import
{
useMapStore
}
from
'@/stores/map'
import
{
useMapStore
}
from
'@/stores/map'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
import
{
useFileDialog
}
from
'@vueuse/core'
import
{
useFileDialog
}
from
'@vueuse/core'
import
{
useMediaQuery
}
from
'@vueuse/core'
import
{
upload
}
from
'@/utils/upload'
import
{
upload
}
from
'@/utils/upload'
import
{
useNow
,
useDateFormat
}
from
'@vueuse/core'
import
{
useNow
,
useDateFormat
}
from
'@vueuse/core'
import
{
import
{
...
@@ -15,6 +16,7 @@ import {
...
@@ -15,6 +16,7 @@ import {
import
BindCaptureDialog
from
'../components/BindCaptureDialog.vue'
import
BindCaptureDialog
from
'../components/BindCaptureDialog.vue'
const
props
=
defineProps
({
id
:
String
})
const
props
=
defineProps
({
id
:
String
})
const
isMobile
=
useMediaQuery
(
'(max-width: 767px)'
)
const
experimentAddress
=
useMapStore
().
getMapValuesByKey
(
'experiment_address'
)
const
experimentAddress
=
useMapStore
().
getMapValuesByKey
(
'experiment_address'
)
...
@@ -163,48 +165,48 @@ function handleUpdateBindCapture(files) {
...
@@ -163,48 +165,48 @@ function handleUpdateBindCapture(files) {
hide-required-asterisk
hide-required-asterisk
v-if=
"experiment"
>
v-if=
"experiment"
>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
<el-form-item
label=
"课程名称"
>
{{
experiment
.
course
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验名称"
>
{{
experiment
.
name
}}
</el-form-item>
<el-form-item
label=
"实验名称"
>
{{
experiment
.
name
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验地点"
>
<el-form-item
label=
"实验地点"
>
<el-select
v-model=
"form.experiment_address"
>
<el-select
v-model=
"form.experiment_address"
>
<el-option
v-for=
"item in experimentAddress"
v-bind=
"item"
:key=
"item.id"
></el-option>
<el-option
v-for=
"item in experimentAddress"
v-bind=
"item"
:key=
"item.id"
></el-option>
</el-select>
</el-select>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验日期"
>
<el-form-item
label=
"实验日期"
>
<el-date-picker
v-model=
"form.experiment_date"
value-format=
"YYYY-MM-DD"
></el-date-picker>
<el-date-picker
v-model=
"form.experiment_date"
value-format=
"YYYY-MM-DD"
></el-date-picker>
</el-form-item>
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"实验类型"
>
{{
experiment
.
type_level
}}
</el-form-item>
<el-form-item
label=
"实验类型"
>
{{
experiment
.
type_level
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
<el-form-item
label=
"指导教师"
>
{{
teacherText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"专业"
>
{{
experiment
.
student
.
specialty
.
name
}}
</el-form-item>
<el-form-item
label=
"专业"
>
{{
experiment
.
student
.
specialty
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"班级"
>
{{
classText
}}
</el-form-item>
<el-form-item
label=
"班级"
>
{{
classText
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
<el-row>
<el-row>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"姓名"
>
{{
experiment
.
student
.
name
}}
</el-form-item>
<el-form-item
label=
"姓名"
>
{{
experiment
.
student
.
name
}}
</el-form-item>
</el-col>
</el-col>
<el-col
:
span
=
"12"
>
<el-col
:
xs=
"24"
:sm=
"24"
:md
=
"12"
>
<el-form-item
label=
"学号"
>
{{
experiment
.
student
.
sno_number
}}
</el-form-item>
<el-form-item
label=
"学号"
>
{{
experiment
.
student
.
sno_number
}}
</el-form-item>
</el-col>
</el-col>
</el-row>
</el-row>
...
@@ -221,7 +223,23 @@ function handleUpdateBindCapture(files) {
...
@@ -221,7 +223,23 @@ function handleUpdateBindCapture(files) {
<el-button
type=
"primary"
@
click=
"handleBindCapture(item)"
v-if=
"item.categories.includes(1)"
<el-button
type=
"primary"
@
click=
"handleBindCapture(item)"
v-if=
"item.categories.includes(1)"
>
关联截图
</el-button
>
关联截图
</el-button
>
>
<el-table
:data=
"item.files"
stripe
:header-cell-style=
"
{ background: '#ededed' }" style="margin-top: 20px">
<div
v-if=
"isMobile"
class=
"report-file-card-list"
>
<div
class=
"report-file-card"
v-for=
"(file, fileIndex) in item.files || []"
:key=
"file.id || file.url || fileIndex"
>
<div
class=
"report-file-card__row"
><span>
序号
</span><strong>
{{
fileIndex
+
1
}}
</strong></div>
<div
class=
"report-file-card__row"
>
<span>
附件类型
</span>
<strong>
{{
file
.
type
===
'1'
?
'本地上传'
:
'实验截图'
}}
</strong>
</div>
<div
class=
"report-file-card__row"
><span>
附件名称
</span><strong>
{{
file
.
name
||
'-'
}}
</strong></div>
<div
class=
"report-file-card__row"
><span>
更新时间
</span><strong>
{{
file
.
updated_time
||
'-'
}}
</strong></div>
<div
class=
"report-file-card__actions"
>
<el-button
text
type=
"primary"
><a
:href=
"file.url"
target=
"_blank"
>
查看
</a></el-button>
<el-button
text
type=
"danger"
@
click=
"handleRemoveFile(item, fileIndex)"
>
删除
</el-button>
</div>
</div>
<el-empty
v-if=
"!item.files?.length"
description=
"暂无附件"
/>
</div>
<el-table
v-else
:data=
"item.files"
stripe
:header-cell-style=
"
{ background: '#ededed' }" style="margin-top: 20px">
<el-table-column
label=
"序号"
type=
"index"
width=
"80"
align=
"center"
></el-table-column>
<el-table-column
label=
"序号"
type=
"index"
width=
"80"
align=
"center"
></el-table-column>
<el-table-column
label=
"附件类型"
prop=
"type"
align=
"center"
>
<el-table-column
label=
"附件类型"
prop=
"type"
align=
"center"
>
<template
#
default=
"
{ row }">
<template
#
default=
"
{ row }">
...
@@ -274,4 +292,47 @@ function handleUpdateBindCapture(files) {
...
@@ -274,4 +292,47 @@ function handleUpdateBindCapture(files) {
justify-content
:
flex-start
;
justify-content
:
flex-start
;
}
}
}
}
.report-file-card-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
margin-top
:
20px
;
}
.report-file-card
{
padding
:
14px
16px
;
border
:
1px
solid
#ebeef5
;
border-radius
:
10px
;
background
:
#fff
;
}
.report-file-card__row
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
padding
:
6px
0
;
border-bottom
:
1px
solid
#f3f4f6
;
}
.report-file-card__row
:last-of-type
{
border-bottom
:
none
;
}
.report-file-card__row
span
{
flex-shrink
:
0
;
color
:
#909399
;
}
.report-file-card__row
strong
{
min-width
:
0
;
text-align
:
right
;
word-break
:
break-word
;
}
.report-file-card__actions
{
display
:
flex
;
justify-content
:
flex-end
;
flex-wrap
:
wrap
;
gap
:
8px
;
padding-top
:
8px
;
}
@media
(
max-width
:
767px
)
{
.report-title
{
padding
:
12px
0
20px
;
}
}
</
style
>
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论