Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-lab
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-lab
Commits
b368622d
提交
b368622d
authored
6月 16, 2023
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: 新增实验试题
上级
622542ff
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
201 行增加
和
10 行删除
+201
-10
api.ts
src/modules/student/lab/api.ts
+10
-0
Question.vue
src/modules/student/lab/components/Question.vue
+182
-0
Index.vue
src/modules/student/lab/views/Index.vue
+9
-10
没有找到文件。
src/modules/student/lab/api.ts
浏览文件 @
b368622d
...
...
@@ -120,3 +120,13 @@ export function getExperimentReport(params: { experiment_id: string }) {
export
function
getExperimentScore
(
params
:
{
experiment_id
:
string
})
{
return
httpRequest
.
get
(
'/api/lab/v1/student/experiment/achievement'
,
{
params
})
}
// 获取实验试题列表
export
function
getExperimentQuestionList
(
params
:
{
experiment_id
:
string
})
{
return
httpRequest
.
get
(
'/api/lab/v1/student/experiment-question/list'
,
{
params
})
}
// 获取实验试题详情
export
function
getExperimentQuestion
(
params
:
{
experiment_id
:
string
;
id
:
string
})
{
return
httpRequest
.
get
(
'/api/lab/v1/student/experiment-question/detail'
,
{
params
})
}
src/modules/student/lab/components/Question.vue
0 → 100644
浏览文件 @
b368622d
<
script
setup
lang=
"ts"
>
import
{
getExperimentQuestionList
,
getExperimentQuestion
}
from
'../api'
interface
Props
{
experiment_id
:
string
}
interface
QuestionListItem
{
experiment_id
:
string
id
:
string
type
:
string
}
type
QuestionGroupListItem
=
QuestionListItem
&
{
index
:
number
}
interface
QuestionGroupList
{
type
:
string
list
:
Array
<
QuestionGroupListItem
>
}
const
props
=
defineProps
<
Props
>
()
const
questionIndex
=
ref
<
number
>
(
1
)
const
questionId
=
computed
(()
=>
{
return
questionList
.
value
[
questionIndex
.
value
-
1
]?.
id
})
const
questionList
=
ref
<
QuestionListItem
[]
>
([])
const
questionGroupList
=
computed
<
QuestionGroupList
[]
>
(()
=>
{
return
questionList
.
value
.
reduce
((
result
,
item
,
index
)
=>
{
let
currentGroup
=
result
.
find
(({
type
})
=>
type
===
item
.
type
)
if
(
!
currentGroup
)
{
result
.
push
({
type
:
item
.
type
,
list
:
[]
})
currentGroup
=
result
[
result
.
length
-
1
]
}
currentGroup
.
list
.
push
({
...
item
,
index
:
index
+
1
})
return
result
},
[]
as
QuestionGroupList
[])
})
const
hasPrev
=
computed
(()
=>
questionIndex
.
value
>
1
)
const
hasNext
=
computed
(()
=>
questionIndex
.
value
<
questionList
.
value
.
length
)
// 试题列表
async
function
fetchList
()
{
if
(
!
props
.
experiment_id
)
return
const
res
=
await
getExperimentQuestionList
({
experiment_id
:
props
.
experiment_id
})
questionList
.
value
=
res
.
data
.
items
}
watchEffect
(()
=>
{
if
(
props
.
experiment_id
)
fetchList
()
})
// 试题详情
const
questionDetail
=
ref
()
async
function
fetchDetail
()
{
if
(
!
questionId
.
value
)
return
const
res
=
await
getExperimentQuestion
({
experiment_id
:
props
.
experiment_id
,
id
:
questionId
.
value
})
const
detail
=
res
.
data
.
detail
let
files
=
[]
try
{
files
=
JSON
.
parse
(
detail
.
files
)
}
catch
(
error
)
{
console
.
log
(
error
)
}
questionDetail
.
value
=
{
...
detail
,
files
,
score
:
parseFloat
(
detail
.
score
)
}
}
watch
(
questionId
,
id
=>
{
if
(
id
)
fetchDetail
()
})
function
handleClick
(
question
:
QuestionGroupListItem
)
{
questionIndex
.
value
=
question
.
index
}
function
handlePrev
()
{
questionIndex
.
value
--
}
function
handleNext
()
{
questionIndex
.
value
++
}
</
script
>
<
template
>
<div
v-if=
"questionList.length"
>
<el-card
shadow=
"never"
class=
"question-number"
>
<dl
v-for=
"group in questionGroupList"
:key=
"group.type"
>
<dt>
{{
group
.
type
}}
</dt>
<dd>
<span
:class=
"
{ 'is-active': question.id === questionId }"
v-for="question in group.list"
:key="question.index"
@click="handleClick(question)"
>
{{
question
.
index
}}
</span
>
</dd>
</dl>
</el-card>
<el-card
shadow=
"never"
class=
"question-item"
v-if=
"questionDetail"
>
<h3
class=
"question-item__title"
>
标签管理
</h3>
<p
class=
"question-item__stem"
>
{{
questionIndex
}}
、
{{
questionDetail
.
title
}}
<span>
(
{{
questionDetail
.
score
}}
分)
</span>
</p>
<p
class=
"question-item__content"
>
{{
questionDetail
.
content
}}
</p>
<ul
class=
"question-item__files"
>
<li
class=
"question-item__files-item"
v-for=
"(file, index) in questionDetail.files"
:key=
"index"
>
<div
class=
"question-item__files-item__title"
>
<p>
{{
file
.
name
}}
</p>
<p>
{{
file
.
size
}}
</p>
</div>
<a
:href=
"file.url"
target=
"_blank"
v-if=
"file.is_download"
>
下载
</a>
<a
:href=
"file.url"
target=
"_blank"
>
查看
</a>
</li>
</ul>
</el-card>
<el-row
justify=
"center"
>
<el-button
type=
"primary"
:disabled=
"!hasPrev"
@
click=
"handlePrev"
>
上一题
</el-button>
<el-button
type=
"primary"
:disabled=
"!hasNext"
@
click=
"handleNext"
>
下一题
</el-button>
</el-row>
</div>
<el-empty
description=
"暂无数据"
v-else
/>
</
template
>
<
style
lang=
"scss"
scoped
>
.question-number
{
dt
{
font-size
:
14px
;
margin-bottom
:
10px
;
}
dd
{
span
{
margin-right
:
10px
;
margin-bottom
:
10px
;
display
:
inline-block
;
width
:
28px
;
height
:
28px
;
text-align
:
center
;
font-size
:
14px
;
line-height
:
28px
;
border
:
1px
solid
#bbb
;
border-radius
:
50%
;
cursor
:
pointer
;
&
.is-active
{
color
:
#fff
;
background-color
:
var
(
--
main-color
);
border-color
:
var
(
--
main-color
);
}
}
}
}
.question-item
{
margin-top
:
10px
;
margin-bottom
:
20px
;
}
.question-item__title
{
margin-bottom
:
10px
;
font-size
:
16px
;
font-weight
:
500
;
}
.question-item__stem
{
font-size
:
14px
;
color
:
#101010
;
}
.question-item__content
{
margin-top
:
10px
;
font-size
:
13px
;
color
:
#75797b
;
}
.question-item__files-item
{
margin-top
:
10px
;
display
:
flex
;
align-items
:
center
;
padding
:
10px
;
background-color
:
#f2f2f2
;
border-radius
:
6px
;
a
{
margin-left
:
10px
;
font-size
:
14px
;
color
:
var
(
--
main-color
);
}
}
.question-item__files-item__title
{
flex
:
1
;
font-size
:
12px
;
color
:
#75797b
;
}
</
style
>
src/modules/student/lab/views/Index.vue
浏览文件 @
b368622d
...
...
@@ -11,6 +11,7 @@ import { saveAs } from 'file-saver'
import
html2pdf
from
'html2pdf.js'
import
{
useCookies
}
from
'@vueuse/integrations/useCookies'
const
Question
=
defineAsyncComponent
(()
=>
import
(
'../components/Question.vue'
))
const
Info
=
defineAsyncComponent
(()
=>
import
(
'../components/Info.vue'
))
const
Case
=
defineAsyncComponent
(()
=>
import
(
'../components/Case.vue'
))
const
Book
=
defineAsyncComponent
(()
=>
import
(
'../components/Book.vue'
))
...
...
@@ -235,6 +236,9 @@ function handleReportPreviewReady() {
</el-form-item>
</el-form>
<el-tabs
type=
"border-card"
>
<el-tab-pane
label=
"实验试题"
lazy
>
<Question
:experiment_id=
"form.experiment_id"
></Question>
</el-tab-pane>
<el-tab-pane
label=
"实验信息"
lazy
>
<Info
:data=
"experimentInfo"
></Info>
</el-tab-pane>
...
...
@@ -274,8 +278,7 @@ function handleReportPreviewReady() {
<el-button
type=
"primary"
:disabled=
"disabled"
v-if=
"experimentInfo?.report_upload_way === 2 && !experimentInfo?.is_commit_report"
>
v-if=
"experimentInfo?.report_upload_way === 2 && !experimentInfo?.is_commit_report"
>
<router-link
:to=
"`/student/lab/report/$
{form.experiment_id}`" target="_blank">在线实验报告
</router-link>
</el-button>
<el-button
...
...
@@ -309,26 +312,22 @@ function handleReportPreviewReady() {
v-model=
"reportDialogVisible"
:data=
"experimentInfo"
@
update=
"fetchExperimentRecord"
v-if=
"reportDialogVisible && experimentInfo"
></ReportDialog>
v-if=
"reportDialogVisible && experimentInfo"
></ReportDialog>
<ReportFilePreview
v-model=
"reportFilePreviewVisible"
:data=
"experimentInfo"
v-if=
"reportFilePreviewVisible && experimentInfo"
></ReportFilePreview>
v-if=
"reportFilePreviewVisible && experimentInfo"
></ReportFilePreview>
<!-- 实验准备 -->
<PrepareDialog
v-model=
"prepareDialogVisible"
:data=
"experimentInfo"
v-if=
"prepareDialogVisible && experimentInfo"
></PrepareDialog>
v-if=
"prepareDialogVisible && experimentInfo"
></PrepareDialog>
<!-- 实验结果 -->
<ResultDialog
v-model=
"resultDialogVisible"
:data=
"experimentInfo"
v-if=
"resultDialogVisible && experimentInfo"
></ResultDialog>
v-if=
"resultDialogVisible && experimentInfo"
></ResultDialog>
<!-- 导出在线报告 -->
<
template
v-if=
"experimentInfo?.id && isExport"
>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论