提交 5532ea51 authored 作者: 王鹏飞's avatar 王鹏飞

chore: 修改教师端自动评分

上级 325b2cc5
...@@ -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 })
}
...@@ -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,43 +24,45 @@ const emit = defineEmits<{ ...@@ -23,43 +24,45 @@ 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(
experiment = res.data.experiment async (res) => {
detail = res.data.achievement experiment = res.data.experiment
if (detail.score_details) { detail = res.data.achievement
try { if (detail.score_details) {
form.score_details = JSON.parse(detail.score_details).map((item: any) => { try {
return { form.score_details = JSON.parse(detail.score_details).map((item: any) => {
...item, return {
percent: parseFloat(item.percent), ...item,
score: parseFloat(item.score), percent: parseFloat(item.percent),
commit_score: parseFloat(item.commit_score) score: parseFloat(item.score),
} commit_score: parseFloat(item.commit_score),
}) }
} catch (error) { })
} catch (error) {
await fetchTemplate()
console.log(error)
}
} else {
await fetchTemplate() await fetchTemplate()
console.log(error)
} }
} else { if (experiment.report_upload_way === 2) {
await fetchTemplate() await fetchReport()
} }
if (experiment.report_upload_way === 2) {
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,16 +71,18 @@ async function fetchTemplate() { ...@@ -68,16 +71,18 @@ 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(
report = res.data.detail (res) => {
const reportScore = parseFloat(report.score || 0) report = res.data.detail
form.score_details = form.score_details.map((item: any) => { const reportScore = parseFloat(report.score || 0)
if (item.type === 1) { form.score_details = form.score_details.map((item: any) => {
item.commit_score = reportScore if (item.type === 1) {
} item.commit_score = reportScore
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) } () => {
updateExperimentScore(params).then(() => { const params = { ...form, score_details: JSON.stringify(form.score_details) }
ElMessage({ message: '保存成功', type: 'success' }) updateExperimentScore(params).then(() => {
emit('update') ElMessage({ message: '保存成功', type: 'success' })
emit('update:modelValue', false) emit('update')
}) 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>
......
<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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论