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

chore: 修改教师端自动评分

上级 325b2cc5
......@@ -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)
}
// 批量导入实验记录评分
export function uploadCheckExperimentRecord(data: { file: File }) {
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:
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)
}
......@@ -106,3 +117,8 @@ export function syncExperimentExam(params: { experiment_id: string }) {
export function recordReject(params: { experiment_id: string; student_id: string }) {
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()
const ScoreViewPicturesDialog = defineAsyncComponent(() => import('./ScoreViewPicturesDialog.vue'))
const ScoreViewPrepareDialog = defineAsyncComponent(() => import('./ScoreViewPrepareDialog.vue'))
const ScoreViewResultDialog = defineAsyncComponent(() => import('./ScoreViewResultDialog.vue'))
const ScoreViewAutoDialog = defineAsyncComponent(() => import('./ScoreViewAutoDialog.vue'))
interface Props {
data: RecordItem
......@@ -23,43 +24,45 @@ const emit = defineEmits<{
let experiment = $ref<any>()
let detail = $ref<any>()
async function fetchInfo() {
await getExperimentScore({ experiment_id: props.data.experiment_id, student_id: props.data.student_id }).then(async res => {
experiment = res.data.experiment
detail = res.data.achievement
if (detail.score_details) {
try {
form.score_details = JSON.parse(detail.score_details).map((item: any) => {
return {
...item,
percent: parseFloat(item.percent),
score: parseFloat(item.score),
commit_score: parseFloat(item.commit_score)
}
})
} catch (error) {
await getExperimentScore({ experiment_id: props.data.experiment_id, student_id: props.data.student_id }).then(
async (res) => {
experiment = res.data.experiment
detail = res.data.achievement
if (detail.score_details) {
try {
form.score_details = JSON.parse(detail.score_details).map((item: any) => {
return {
...item,
percent: parseFloat(item.percent),
score: parseFloat(item.score),
commit_score: parseFloat(item.commit_score),
}
})
} catch (error) {
await fetchTemplate()
console.log(error)
}
} else {
await fetchTemplate()
console.log(error)
}
} else {
await fetchTemplate()
}
if (experiment.report_upload_way === 2) {
await fetchReport()
if (experiment.report_upload_way === 2) {
await fetchReport()
}
}
})
)
}
watchEffect(() => {
fetchInfo()
})
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) => {
return {
...item,
percent: parseFloat(item.percent),
score: parseFloat(item.score),
commit_score: parseFloat(item.commit_score)
commit_score: parseFloat(item.commit_score),
}
})
})
......@@ -68,16 +71,18 @@ async function fetchTemplate() {
// 获取实验报告分数
let report = $ref<any>()
async function fetchReport() {
await getExperimentReport({ experiment_id: props.data.experiment_id, student_id: props.data.student_id }).then(res => {
report = res.data.detail
const reportScore = parseFloat(report.score || 0)
form.score_details = form.score_details.map((item: any) => {
if (item.type === 1) {
item.commit_score = reportScore
}
return item
})
})
await getExperimentReport({ experiment_id: props.data.experiment_id, student_id: props.data.student_id }).then(
(res) => {
report = res.data.detail
const reportScore = parseFloat(report.score || 0)
form.score_details = form.score_details.map((item: any) => {
if (item.type === 1) {
item.commit_score = reportScore
}
return item
})
}
)
}
// 实验报告文件
......@@ -93,7 +98,7 @@ const file = $computed<FileItem>(() => {
const form = reactive<any>({
experiment_id: props.data.experiment_id,
student_id: props.data.student_id,
score_details: []
score_details: [],
})
const score = $computed<number>(() => {
......@@ -105,14 +110,16 @@ const score = $computed<number>(() => {
// 提交
function handleSubmit() {
ElMessageBox.confirm('更改成绩之后将以最新成绩为准,您可以查看批改成绩历史数据,确定需要修改成绩吗?', '提示').then(() => {
const params = { ...form, score_details: JSON.stringify(form.score_details) }
updateExperimentScore(params).then(() => {
ElMessage({ message: '保存成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
})
ElMessageBox.confirm('更改成绩之后将以最新成绩为准,您可以查看批改成绩历史数据,确定需要修改成绩吗?', '提示').then(
() => {
const params = { ...form, score_details: JSON.stringify(form.score_details) }
updateExperimentScore(params).then(() => {
ElMessage({ message: '保存成功', type: 'success' })
emit('update')
emit('update:modelValue', false)
})
}
)
}
function scoreValue(value: any) {
......@@ -146,10 +153,22 @@ function getOperationUrl(type: number) {
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>
<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-row>
<el-col :span="12">
......@@ -189,12 +208,16 @@ function getOperationUrl(type: number) {
<p class="t1">{{ scoreValue(score) }}</p>
<p class="t2">满分:{{ experiment.score }}</p>
</div>
<el-table :data="form.score_details" stripe :header-cell-style="{ background: '#ededed' }" style="margin-top: 20px">
<el-table-column label="实验成绩组成项" prop="name" align="center"></el-table-column>
<el-table-column label="权重" prop="percent" align="center">
<el-table
:data="form.score_details"
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>
</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">
<template #default="{ row }">
<el-input-number
......@@ -210,7 +233,7 @@ function getOperationUrl(type: number) {
<span v-else>{{ row.commit_score }}</span>
</template>
</el-table-column>
<el-table-column label="操作" prop="commit_score" align="center">
<el-table-column label="操作" align="center" width="180">
<template #default="{ row }">
<template v-if="row.type === 1">
<el-button text type="primary" v-if="experiment.report_upload_way === 2">
......@@ -223,9 +246,16 @@ function getOperationUrl(type: number) {
<p style="color: red" v-else>未上传</p>
</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">
<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>
</template>
</template>
......@@ -253,7 +283,16 @@ function getOperationUrl(type: number) {
:student_id="data.student_id"
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>
</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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论