Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-lab
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-lab
Commits
5532ea51
提交
5532ea51
authored
2月 24, 2025
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: 修改教师端自动评分
上级
325b2cc5
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
205 行增加
和
22 行删除
+205
-22
api.ts
src/modules/admin/lab/score/api.ts
+19
-3
ScoreDialog.vue
src/modules/admin/lab/score/components/ScoreDialog.vue
+58
-19
ScoreViewAutoDialog.vue
...odules/admin/lab/score/components/ScoreViewAutoDialog.vue
+128
-0
没有找到文件。
src/modules/admin/lab/score/api.ts
浏览文件 @
5532ea51
...
@@ -24,14 +24,20 @@ export function getExperimentRecord(params: { experiment_id: string; student_id:
...
@@ -24,14 +24,20 @@ export function getExperimentRecord(params: { experiment_id: string; student_id:
}
}
// 实验记录评分
// 实验记录评分
export
function
checkExperimentRecord
(
data
:
{
experiment_id
:
string
;
student_id
:
string
;
operate
:
number
;
result
:
number
;
file
:
number
})
{
export
function
checkExperimentRecord
(
data
:
{
experiment_id
:
string
student_id
:
string
operate
:
number
result
:
number
file
:
number
})
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/record/check'
,
data
)
return
httpRequest
.
post
(
'/api/lab/v1/teacher/record/check'
,
data
)
}
}
// 批量导入实验记录评分
// 批量导入实验记录评分
export
function
uploadCheckExperimentRecord
(
data
:
{
file
:
File
})
{
export
function
uploadCheckExperimentRecord
(
data
:
{
file
:
File
})
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/record/upload'
,
data
,
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/record/upload'
,
data
,
{
headers
:
{
'Content-Type'
:
'multipart/form-data'
}
headers
:
{
'Content-Type'
:
'multipart/form-data'
}
,
})
})
}
}
...
@@ -50,7 +56,12 @@ export function getExperimentReport(params: { experiment_id: string; student_id:
...
@@ -50,7 +56,12 @@ export function getExperimentReport(params: { experiment_id: string; student_id:
return
httpRequest
.
get
(
'/api/lab/v1/teacher/experiment/report-achievement'
,
{
params
})
return
httpRequest
.
get
(
'/api/lab/v1/teacher/experiment/report-achievement'
,
{
params
})
}
}
// 批改学员实验报告成绩
// 批改学员实验报告成绩
export
function
updateExperimentReport
(
data
:
{
experiment_id
:
string
;
student_id
:
string
;
score_detail
:
string
;
comment
:
string
})
{
export
function
updateExperimentReport
(
data
:
{
experiment_id
:
string
student_id
:
string
score_detail
:
string
comment
:
string
})
{
return
httpRequest
.
post
(
'/api/lab/v1/teacher/experiment/report-check'
,
data
)
return
httpRequest
.
post
(
'/api/lab/v1/teacher/experiment/report-check'
,
data
)
}
}
...
@@ -106,3 +117,8 @@ export function syncExperimentExam(params: { experiment_id: string }) {
...
@@ -106,3 +117,8 @@ export function syncExperimentExam(params: { experiment_id: string }) {
export
function
recordReject
(
params
:
{
experiment_id
:
string
;
student_id
:
string
})
{
export
function
recordReject
(
params
:
{
experiment_id
:
string
;
student_id
:
string
})
{
return
httpRequest
.
get
(
'/api/lab/v1/teacher/record/reject'
,
{
params
})
return
httpRequest
.
get
(
'/api/lab/v1/teacher/record/reject'
,
{
params
})
}
}
// 教师查看分数详情页面
export
function
getExperimentScoreDetail
(
params
:
{
experiment_id
:
string
;
student_id
:
string
;
type
:
string
})
{
return
httpRequest
.
get
(
'/api/lab/v1/teacher/experiment/score-detail'
,
{
params
})
}
src/modules/admin/lab/score/components/ScoreDialog.vue
浏览文件 @
5532ea51
...
@@ -9,6 +9,7 @@ const appConfig = useAppConfig()
...
@@ -9,6 +9,7 @@ const appConfig = useAppConfig()
const
ScoreViewPicturesDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewPicturesDialog.vue'
))
const
ScoreViewPicturesDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewPicturesDialog.vue'
))
const
ScoreViewPrepareDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewPrepareDialog.vue'
))
const
ScoreViewPrepareDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewPrepareDialog.vue'
))
const
ScoreViewResultDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewResultDialog.vue'
))
const
ScoreViewResultDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewResultDialog.vue'
))
const
ScoreViewAutoDialog
=
defineAsyncComponent
(()
=>
import
(
'./ScoreViewAutoDialog.vue'
))
interface
Props
{
interface
Props
{
data
:
RecordItem
data
:
RecordItem
...
@@ -23,7 +24,8 @@ const emit = defineEmits<{
...
@@ -23,7 +24,8 @@ const emit = defineEmits<{
let
experiment
=
$ref
<
any
>
()
let
experiment
=
$ref
<
any
>
()
let
detail
=
$ref
<
any
>
()
let
detail
=
$ref
<
any
>
()
async
function
fetchInfo
()
{
async
function
fetchInfo
()
{
await
getExperimentScore
({
experiment_id
:
props
.
data
.
experiment_id
,
student_id
:
props
.
data
.
student_id
}).
then
(
async
res
=>
{
await
getExperimentScore
({
experiment_id
:
props
.
data
.
experiment_id
,
student_id
:
props
.
data
.
student_id
}).
then
(
async
(
res
)
=>
{
experiment
=
res
.
data
.
experiment
experiment
=
res
.
data
.
experiment
detail
=
res
.
data
.
achievement
detail
=
res
.
data
.
achievement
if
(
detail
.
score_details
)
{
if
(
detail
.
score_details
)
{
...
@@ -33,7 +35,7 @@ async function fetchInfo() {
...
@@ -33,7 +35,7 @@ async function fetchInfo() {
...
item
,
...
item
,
percent
:
parseFloat
(
item
.
percent
),
percent
:
parseFloat
(
item
.
percent
),
score
:
parseFloat
(
item
.
score
),
score
:
parseFloat
(
item
.
score
),
commit_score
:
parseFloat
(
item
.
commit_score
)
commit_score
:
parseFloat
(
item
.
commit_score
),
}
}
})
})
}
catch
(
error
)
{
}
catch
(
error
)
{
...
@@ -46,20 +48,21 @@ async function fetchInfo() {
...
@@ -46,20 +48,21 @@ async function fetchInfo() {
if
(
experiment
.
report_upload_way
===
2
)
{
if
(
experiment
.
report_upload_way
===
2
)
{
await
fetchReport
()
await
fetchReport
()
}
}
})
}
)
}
}
watchEffect
(()
=>
{
watchEffect
(()
=>
{
fetchInfo
()
fetchInfo
()
})
})
async
function
fetchTemplate
()
{
async
function
fetchTemplate
()
{
await
getExperimentScoreTemplate
({
experiment_id
:
props
.
data
.
experiment_id
}).
then
(
res
=>
{
await
getExperimentScoreTemplate
({
experiment_id
:
props
.
data
.
experiment_id
}).
then
(
(
res
)
=>
{
form
.
score_details
=
res
.
data
.
detail
.
rule_list
.
map
((
item
:
any
)
=>
{
form
.
score_details
=
res
.
data
.
detail
.
rule_list
.
map
((
item
:
any
)
=>
{
return
{
return
{
...
item
,
...
item
,
percent
:
parseFloat
(
item
.
percent
),
percent
:
parseFloat
(
item
.
percent
),
score
:
parseFloat
(
item
.
score
),
score
:
parseFloat
(
item
.
score
),
commit_score
:
parseFloat
(
item
.
commit_score
)
commit_score
:
parseFloat
(
item
.
commit_score
)
,
}
}
})
})
})
})
...
@@ -68,7 +71,8 @@ async function fetchTemplate() {
...
@@ -68,7 +71,8 @@ async function fetchTemplate() {
// 获取实验报告分数
// 获取实验报告分数
let
report
=
$ref
<
any
>
()
let
report
=
$ref
<
any
>
()
async
function
fetchReport
()
{
async
function
fetchReport
()
{
await
getExperimentReport
({
experiment_id
:
props
.
data
.
experiment_id
,
student_id
:
props
.
data
.
student_id
}).
then
(
res
=>
{
await
getExperimentReport
({
experiment_id
:
props
.
data
.
experiment_id
,
student_id
:
props
.
data
.
student_id
}).
then
(
(
res
)
=>
{
report
=
res
.
data
.
detail
report
=
res
.
data
.
detail
const
reportScore
=
parseFloat
(
report
.
score
||
0
)
const
reportScore
=
parseFloat
(
report
.
score
||
0
)
form
.
score_details
=
form
.
score_details
.
map
((
item
:
any
)
=>
{
form
.
score_details
=
form
.
score_details
.
map
((
item
:
any
)
=>
{
...
@@ -77,7 +81,8 @@ async function fetchReport() {
...
@@ -77,7 +81,8 @@ async function fetchReport() {
}
}
return
item
return
item
})
})
})
}
)
}
}
// 实验报告文件
// 实验报告文件
...
@@ -93,7 +98,7 @@ const file = $computed<FileItem>(() => {
...
@@ -93,7 +98,7 @@ const file = $computed<FileItem>(() => {
const
form
=
reactive
<
any
>
({
const
form
=
reactive
<
any
>
({
experiment_id
:
props
.
data
.
experiment_id
,
experiment_id
:
props
.
data
.
experiment_id
,
student_id
:
props
.
data
.
student_id
,
student_id
:
props
.
data
.
student_id
,
score_details
:
[]
score_details
:
[]
,
})
})
const
score
=
$computed
<
number
>
(()
=>
{
const
score
=
$computed
<
number
>
(()
=>
{
...
@@ -105,14 +110,16 @@ const score = $computed<number>(() => {
...
@@ -105,14 +110,16 @@ const score = $computed<number>(() => {
// 提交
// 提交
function
handleSubmit
()
{
function
handleSubmit
()
{
ElMessageBox
.
confirm
(
'更改成绩之后将以最新成绩为准,您可以查看批改成绩历史数据,确定需要修改成绩吗?'
,
'提示'
).
then
(()
=>
{
ElMessageBox
.
confirm
(
'更改成绩之后将以最新成绩为准,您可以查看批改成绩历史数据,确定需要修改成绩吗?'
,
'提示'
).
then
(
()
=>
{
const
params
=
{
...
form
,
score_details
:
JSON
.
stringify
(
form
.
score_details
)
}
const
params
=
{
...
form
,
score_details
:
JSON
.
stringify
(
form
.
score_details
)
}
updateExperimentScore
(
params
).
then
(()
=>
{
updateExperimentScore
(
params
).
then
(()
=>
{
ElMessage
({
message
:
'保存成功'
,
type
:
'success'
})
ElMessage
({
message
:
'保存成功'
,
type
:
'success'
})
emit
(
'update'
)
emit
(
'update'
)
emit
(
'update:modelValue'
,
false
)
emit
(
'update:modelValue'
,
false
)
})
})
})
}
)
}
}
function
scoreValue
(
value
:
any
)
{
function
scoreValue
(
value
:
any
)
{
...
@@ -146,10 +153,22 @@ function getOperationUrl(type: number) {
...
@@ -146,10 +153,22 @@ function getOperationUrl(type: number) {
return
`
${
dmlURL
}
/material?experiment_id=
${
props
.
data
.
experiment_id
}
&student_id=
${
props
.
data
.
student_id
}
`
return
`
${
dmlURL
}
/material?experiment_id=
${
props
.
data
.
experiment_id
}
&student_id=
${
props
.
data
.
student_id
}
`
}
}
}
}
const
autoVisible
=
ref
(
false
)
const
currentRow
=
ref
(
null
)
function
handleViewAuto
(
row
:
any
)
{
autoVisible
.
value
=
true
currentRow
.
value
=
row
}
</
script
>
</
script
>
<
template
>
<
template
>
<el-dialog
title=
"学生实验评分"
:close-on-click-modal=
"false"
width=
"800px"
@
update:modelValue=
"value => $emit('update:modelValue', value)"
>
<el-dialog
title=
"学生实验评分"
:close-on-click-modal=
"false"
width=
"800px"
@
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
:span=
"12"
>
...
@@ -189,12 +208,16 @@ function getOperationUrl(type: number) {
...
@@ -189,12 +208,16 @@ function getOperationUrl(type: number) {
<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>
<el-table
:data=
"form.score_details"
stripe
:header-cell-style=
"
{ background: '#ededed' }" style="margin-top: 20px">
<el-table
<el-table-column
label=
"实验成绩组成项"
prop=
"name"
align=
"center"
></el-table-column>
:data=
"form.score_details"
<el-table-column
label=
"权重"
prop=
"percent"
align=
"center"
>
stripe
:header-cell-style=
"
{ background: '#ededed' }"
style="margin-top: 20px">
<el-table-column
label=
"实验成绩组成项"
prop=
"name"
align=
"left"
></el-table-column>
<el-table-column
label=
"权重"
prop=
"percent"
align=
"center"
width=
"80"
>
<template
#
default=
"
{ row }">
{{
row
.
percent
}}
%
</
template
>
<template
#
default=
"
{ row }">
{{
row
.
percent
}}
%
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"满分"
prop=
"score"
align=
"center"
>
100
</el-table-column>
<el-table-column
label=
"满分"
prop=
"score"
align=
"center"
width=
"100"
>
100
</el-table-column>
<el-table-column
label=
"得分"
prop=
"commit_score"
align=
"center"
>
<el-table-column
label=
"得分"
prop=
"commit_score"
align=
"center"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<el-input-number
<el-input-number
...
@@ -210,7 +233,7 @@ function getOperationUrl(type: number) {
...
@@ -210,7 +233,7 @@ function getOperationUrl(type: number) {
<span
v-else
>
{{
row
.
commit_score
}}
</span>
<span
v-else
>
{{
row
.
commit_score
}}
</span>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"操作"
prop=
"commit_score"
align=
"center
"
>
<el-table-column
label=
"操作"
align=
"center"
width=
"180
"
>
<
template
#
default=
"{ row }"
>
<
template
#
default=
"{ row }"
>
<template
v-if=
"row.type === 1"
>
<template
v-if=
"row.type === 1"
>
<el-button
text
type=
"primary"
v-if=
"experiment.report_upload_way === 2"
>
<el-button
text
type=
"primary"
v-if=
"experiment.report_upload_way === 2"
>
...
@@ -223,9 +246,16 @@ function getOperationUrl(type: number) {
...
@@ -223,9 +246,16 @@ function getOperationUrl(type: number) {
<p
style=
"color: red"
v-else
>
未上传
</p>
<p
style=
"color: red"
v-else
>
未上传
</p>
</
template
>
</
template
>
</template>
</template>
<
template
v-else-if=
"[6, 7, 8, 9, 10].includes(row.type)"
>
<
template
v-if=
"[6, 7, 9, 11, 12].includes(row.type)"
>
<el-button
text
type=
"primary"
@
click=
"handleViewAuto(row)"
>
查看自动评分结果
</el-button>
</
template
>
<
template
v-if=
"[6, 7, 8, 9, 10, 11, 12].includes(row.type)"
>
<el-button
text
type=
"primary"
>
<el-button
text
type=
"primary"
>
<a
:href=
"`/admin/lab/score/score?id=$
{props.data.experiment_id}
&
sid=${props.data.student_id}
&
type=${row.type}`" target="_blank">查看结果
</a>
<a
:href=
"`/admin/lab/score/score?id=$
{props.data.experiment_id}
&
sid=${props.data.student_id}
&
type=${row.type}`"
target="_blank"
>查看原始结果
</a
>
</el-button>
</el-button>
</
template
>
</
template
>
</template>
</template>
...
@@ -253,7 +283,16 @@ function getOperationUrl(type: number) {
...
@@ -253,7 +283,16 @@ function getOperationUrl(type: number) {
:student_id=
"data.student_id"
:student_id=
"data.student_id"
v-if=
"resultVisible"
></ScoreViewResultDialog>
v-if=
"resultVisible"
></ScoreViewResultDialog>
<!-- 实验截图 -->
<!-- 实验截图 -->
<ScoreViewPicturesDialog
v-model=
"pictureVisible"
:data=
"detail"
v-if=
"pictureVisible && detail"
></ScoreViewPicturesDialog>
<ScoreViewPicturesDialog
v-model=
"pictureVisible"
:data=
"detail"
v-if=
"pictureVisible && detail"
></ScoreViewPicturesDialog>
<!-- 实验截图 -->
<ScoreViewAutoDialog
v-model=
"autoVisible"
:data=
"detail"
:row=
"currentRow"
v-if=
"autoVisible"
></ScoreViewAutoDialog>
</el-dialog>
</el-dialog>
</template>
</template>
...
...
src/modules/admin/lab/score/components/ScoreViewAutoDialog.vue
0 → 100644
浏览文件 @
5532ea51
<
script
setup
lang=
"ts"
>
import
type
{
RecordItem
}
from
'../types'
import
AppList
from
'@/components/base/AppList.vue'
import
{
getExperimentScoreDetail
}
from
'../api'
import
{
gradeRule
}
from
'@/utils/dictionary'
import
{
useAppConfig
}
from
'@/composables/useAppConfig'
const
appConfig
=
useAppConfig
()
interface
Props
{
data
:
RecordItem
row
:
any
}
const
props
=
defineProps
<
Props
>
()
let
datalist
=
$ref
<
any
>
([])
function
fetchInfo
()
{
getExperimentScoreDetail
({
experiment_id
:
props
.
data
.
experiment_id
,
student_id
:
props
.
data
.
student_id
,
type
:
props
.
row
.
type
,
}).
then
((
res
)
=>
{
datalist
=
res
.
data
})
}
watchEffect
(()
=>
{
fetchInfo
()
})
const
appList
=
$ref
<
InstanceType
<
typeof
AppList
>
|
null
>
(
null
)
const
title
=
computed
(()
=>
{
return
'查看'
+
gradeRule
[
props
.
row
.
type
]
})
// 列表配置
const
listOptions
=
computed
(()
=>
{
let
columns
=
[]
switch
(
props
.
row
.
type
)
{
case
6
:
// 用户标签
columns
=
[
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'标签名称'
,
prop
:
'student_name'
},
{
label
:
'正确标签名称'
,
prop
:
'teacher_name'
},
{
label
:
'标签数据量'
,
prop
:
'student_total'
},
{
label
:
'正确标签数据量'
,
prop
:
'teacher_total'
},
{
label
:
'操作'
,
prop
:
'status'
,
slots
:
'table-x'
},
]
break
case
7
:
// 用户群组
columns
=
[
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'群组名称'
,
prop
:
'student_name'
},
{
label
:
'正确群组名称'
,
prop
:
'teacher_name'
},
{
label
:
'群组数据量'
,
prop
:
'student_total'
},
{
label
:
'正确群组数据量'
,
prop
:
'teacher_total'
},
{
label
:
'操作'
,
prop
:
'status'
,
slots
:
'table-x'
},
]
break
case
9
:
// 营销资料
columns
=
[
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'营销资料名称'
,
prop
:
'student_name'
},
{
label
:
'营销资料类型'
,
prop
:
'type_name'
},
{
label
:
'正确营销资料名称'
,
prop
:
'teacher_name'
},
{
label
:
'AI综合评分'
,
prop
:
'score'
},
{
label
:
'AI评价'
,
prop
:
'comment'
},
]
break
case
11
:
// 用户数据
columns
=
[
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'文件名称'
,
prop
:
'file_name'
},
{
label
:
'用户数据量'
,
prop
:
'student_total'
},
{
label
:
'正确答案'
,
prop
:
'teacher_total'
},
{
label
:
'导入时间'
,
prop
:
'created_time'
},
{
label
:
'状态'
,
prop
:
'status'
},
]
break
case
12
:
// 事件数据
columns
=
[
{
label
:
'序号'
,
type
:
'index'
,
width
:
60
},
{
label
:
'文件名称'
,
prop
:
'file_name'
},
{
label
:
'事件名称'
,
prop
:
'event_name'
},
{
label
:
'事件数据量'
,
prop
:
'student_total'
},
{
label
:
'正确答案'
,
prop
:
'teacher_total'
},
{
label
:
'导入时间'
,
prop
:
'created_time'
},
{
label
:
'状态'
,
prop
:
'status'
},
]
break
default
:
break
}
return
{
columns
,
data
:
datalist
,
}
})
function
getOperationUrl
(
row
:
any
)
{
const
type
=
props
.
row
.
type
const
dmlURL
=
appConfig
.
dmlURL
||
import
.
meta
.
env
.
VITE_DML_URL
if
(
type
===
6
)
{
// 用户标签
return
`
${
dmlURL
}
/label?experiment_id=
${
props
.
data
.
experiment_id
}
&student_id=
${
props
.
data
.
student_id
}
&id=
${
row
.
id
}
&name=
${
row
.
student_name
}
`
}
else
if
(
type
===
7
)
{
// 用户群组
return
`
${
dmlURL
}
/group?experiment_id=
${
props
.
data
.
experiment_id
}
&student_id=
${
props
.
data
.
student_id
}
&id=
${
row
.
id
}
&name=
${
row
.
student_name
}
`
}
}
</
script
>
<
template
>
<el-dialog
:title=
"title"
>
<AppList
v-bind=
"listOptions"
ref=
"appList"
>
<template
#
table-x=
"
{ row }">
<el-button
type=
"primary"
text
>
<a
:href=
"getOperationUrl(row)"
target=
"_blank"
>
查看
</a>
</el-button>
</
template
>
</AppList>
</el-dialog>
</template>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论