提交 ef8d6fc5 authored 作者: lhh's avatar lhh

update

上级 be13cd6d
......@@ -78,3 +78,23 @@ export function getExperimentScore(params: { experiment_id: string; student_id:
export function updateExperimentScore(data: { experiment_id: string; student_id: string; score_details: string }) {
return httpRequest.post('/api/lab/v1/teacher/experiment/achievement-check', data)
}
// 获取学员信息
export function getStudentInfo(params: { experiment_id: string; student_id: string }) {
return httpRequest.get('/api/lab/v1/teacher/student/detail', { params })
}
// 获取学员信息
export function getQuestionList(params: { experiment_id: string; student_id: string }) {
return httpRequest.get('/api/lab/v1/teacher/experiment-question/list', { params })
}
// 打分
export function updateQuestionScore(data: { question_id: string; student_id: string; commit_score: string }) {
return httpRequest.post('/api/lab/v1/teacher/experiment-question/check', data)
}
// 同步学生分数
export function asyncStudentResult(data: { experiment_id: string; student_id: string; }) {
return httpRequest.post('/api/lab/v1/teacher/experiment-question/async-student-result', data)
}
<script setup lang="ts">
import { getQuestionList, updateQuestionScore, asyncStudentResult } from '../api'
import { ElMessage } from 'element-plus'
const route = useRoute()
onMounted(() => {
fetchList()
})
// 序号
let orderList = $ref<any[]>([])
// 所有题
let questionList = $ref([])
// 当前题序
let currentIndex = $ref(1)
// 获取当前题
const questionDetail: any = computed(() => {
return questionList.find((item: any) => item.order === currentIndex)
})
const fetchList = function () {
getQuestionList({ experiment_id: route.query.id as string, student_id: route.query.sid as string }).then(res => {
if (res.data?.items) {
questionList = res.data.items.map((item: any, index: number) => {
item.order = index
return item
})
}
orderList = res.data.items.reduce((a: any, b: any, i: number) => {
if (b.type === '101' || b.type === '102') {
setData('1', '用户/事件管理')
}
if (b.type === '201' || b.type === '202') {
setData('2', '标签管理')
}
if (b.type === '301' || b.type === '302') {
setData('3', '群组管理')
}
if (
b.type === '401' ||
b.type === '402' ||
b.type === '403' ||
b.type === '404' ||
b.type === '405' ||
b.type === '406' ||
b.type === '407' ||
b.type === '408'
) {
setData('4', '资料管理')
}
function setData(type: string, name: string) {
const index = a.findIndex((item: { type: string }) => item.type === type)
b.order = i + 1
index === -1 ? a.push({ type: type, name: name, q: [b] }) : a[index].q.push(b)
}
return a
}, [])
})
}
const hasPrev = computed(() => currentIndex > 1)
const hasNext = computed(() => currentIndex < questionList.length)
function handlePrev() {
currentIndex--
}
function handleNext() {
currentIndex++
}
const handleOrder = function (order: number) {
currentIndex = order
}
// 打分
const updateScore = function (item: any) {
updateQuestionScore({
question_id: item.id,
student_id: route.query.sid as string,
commit_score: item.commit_score
}).then(res => {
if (res.data.status) {
item.is_complete_check = true
ElMessage({ message: '保存成功', type: 'success' })
}
})
}
// 同步分数
const handleSubmit = function () {
asyncStudentResult({ experiment_id: route.query.id as string, student_id: route.query.sid as string }).then(res => {
if (res.data.status) {
ElMessage({ message: '提交成功', type: 'success' })
}
})
}
</script>
<template>
<div v-if="orderList.length">
<el-card shadow="never" class="question-number">
<dl v-for="group in orderList" :key="group.type">
<dt>{{ group.name }}</dt>
<dd>
<span
@click="handleOrder(question.order)"
:class="{ 'is-active': question.is_complete_check }"
v-for="question in group.q"
:key="question.id"
>{{ question.order }}</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">
{{ questionDetail?.order }}{{ questionDetail.title }} <span>{{ questionDetail.score }}分)</span>
</p>
<ul class="question-item__files" v-if="questionDetail.files">
<li class="question-item__files-item" v-for="file in questionDetail.files" :key="file.url">
<div class="question-item__files-item__title">
<p>{{ file.name }}</p>
<p>{{ file.size }}</p>
</div>
</li>
</ul>
<p class="question-item__tip">作答详情:详见系统</p>
<p class="question-item__content">解析:{{ questionDetail.answer_analysis }}</p>
<div class="question-item-score">
<span>本题得分</span>
<el-input-number
style="width: 100px"
v-model="questionDetail.commit_score"
:min="0"
:max="questionDetail.score"
size="small"
controls-position="right"
/>
</div>
<el-row justify="center">
<!-- <el-button>取消</el-button> -->
<el-button type="primary" @click="updateScore(questionDetail)">保存</el-button>
</el-row>
</el-card>
<el-row justify="center">
<el-button :disabled="!hasPrev" type="primary" @click="handlePrev">上一题</el-button>
<el-button :disabled="!hasNext" type="primary" @click="handleNext">下一题</el-button>
<el-button type="primary" @click="handleSubmit()">提交</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;
}
.question-item__tip {
margin: 15px 0;
font-size: 14px;
color: #101010;
}
.question-item-score {
display: flex;
justify-content: center;
align-items: center;
padding: 20px 0;
span {
margin-right: 10px;
font-size: 14px;
}
}
</style>
......@@ -164,7 +164,8 @@ function getOperationUrl(type: number) {
title="学生实验评分"
:close-on-click-modal="false"
width="800px"
@update:modelValue="$emit('update:modelValue')">
@update:modelValue="$emit('update:modelValue')"
>
<el-form label-width="120px" label-suffix=":" v-if="detail">
<el-row>
<el-col :span="12">
......@@ -207,7 +208,8 @@ function getOperationUrl(type: number) {
:data="form.score_details"
stripe
:header-cell-style="{ background: '#ededed' }"
style="margin-top: 20px">
style="margin-top: 20px"
>
<el-table-column label="实验成绩组成项" prop="name" align="center"></el-table-column>
<el-table-column label="权重" prop="percent" align="center">
<template #default="{ row }"> {{ row.percent }}% </template>
......@@ -224,7 +226,8 @@ function getOperationUrl(type: number) {
step-strictly
placeholder="请输入成绩"
style="width: 100px"
v-if="!(row.type === 1 && experiment.report_upload_way === 2)"></el-input-number>
v-if="!(row.type === 1 && experiment.report_upload_way === 2)"
></el-input-number>
<span v-else>{{ row.commit_score }}</span>
</template>
</el-table-column>
......@@ -235,7 +238,8 @@ function getOperationUrl(type: number) {
text
type="primary"
@click="$emit('update:modelValue')"
v-if="experiment.report_upload_way === 2">
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">
......@@ -245,9 +249,13 @@ function getOperationUrl(type: number) {
<p style="color: red" v-else>未上传</p>
</template>
</template>
<template v-else-if="[6, 7, 8, 9].includes(row.type)">
<template v-else-if="[6, 7, 8, 9, 10].includes(row.type)">
<el-button text type="primary">
<a :href="getOperationUrl(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>
......@@ -267,18 +275,21 @@ function getOperationUrl(type: number) {
v-model="prepareVisible"
:experiment_id="data.experiment_id"
:student_id="data.student_id"
v-if="prepareVisible"></ScoreViewPrepareDialog>
v-if="prepareVisible"
></ScoreViewPrepareDialog>
<!-- 实验结果 -->
<ScoreViewResultDialog
v-model="resultVisible"
:experiment_id="data.experiment_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>
v-if="pictureVisible && detail"
></ScoreViewPicturesDialog>
</el-dialog>
</template>
......
<script setup lang="ts">
import { getStudentInfo } from '../api'
import type { StudentInfo } from '../types'
const route = useRoute()
let info = $ref<StudentInfo>()
onMounted(() => {
getStudentInfo({ experiment_id: route.query.id as string, student_id: route.query.sid as string }).then(
(res: { data: { detail: StudentInfo } }) => {
info = res.data?.detail
}
)
})
</script>
<template>
<el-form label-width="100px">
<el-form-item label="姓名:">{{ info?.name }}</el-form-item>
<el-form-item label="学号:">{{ info?.sno_number }}</el-form-item>
<el-form-item label="所属班级:">{{ info?.class.name }}</el-form-item>
<el-form-item label="所属专业:">{{ info?.specialty.name }}</el-form-item>
<el-form-item label="实验名称:">{{ info?.experiment.name }}</el-form-item>
</el-form>
</template>
<style lang="scss" scoped></style>
......@@ -7,7 +7,8 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout,
children: [
{ path: '', component: () => import('./views/Index.vue') },
{ path: 'report', component: () => import('./views/Report.vue') }
{ path: 'report', component: () => import('./views/Report.vue') },
{ path: 'score', component: () => import('./views/Score.vue') }
]
}
]
......@@ -36,3 +36,17 @@ export interface ScoreLog {
check_time: string
checker_id_name: string
}
export interface StudentInfo {
name: string
sno_number: string
class: {
name: string
}
specialty: {
name: string
}
experiment: {
name: string
}
}
<script setup lang="ts">
import DragPanel from '@/components/DragPanel.vue'
const StudentInfo = defineAsyncComponent(() => import('../components/StudentInfo.vue'))
const Question = defineAsyncComponent(() => import('../components/Question.vue'))
const route = useRoute()
let resizeKey = $ref(0)
function handleResize() {
resizeKey = Date.now()
}
const getIframeUrl = function () {
const type = route.query.type
if (type === '6') {
// 用户标签
return `${import.meta.env.VITE_DML_URL}/label?experiment_id=${route.query.id}&student_id=${route.query.sid}`
} else if (type === '7') {
// 用户群组
return `${import.meta.env.VITE_DML_URL}/group?experiment_id=${route.query.id}&student_id=${route.query.sid}`
} else if (type === '8') {
// 用户旅程
return `${import.meta.env.VITE_DML_URL}/trip/review?experiment_id=${route.query.id}&student_id=${route.query.sid}`
} else if (type === '9') {
// 营销资料
return `${import.meta.env.VITE_DML_URL}/material?experiment_id=${route.query.id}&student_id=${route.query.sid}`
} else if (type === '10') {
// 用户事件
return `${import.meta.env.VITE_DML_URL}/user?experiment_id=${route.query.id}&student_id=${route.query.sid}`
}
}
</script>
<template>
<DragPanel @resize="handleResize">
<template #left>
<div class="lab-left">
<el-tabs type="border-card">
<el-tab-pane label="打分详情" lazy>
<Question></Question>
</el-tab-pane>
<el-tab-pane label="基本信息" lazy>
<StudentInfo></StudentInfo>
</el-tab-pane>
</el-tabs>
</div>
</template>
<template #right>
<div class="lab-box">
<iframe :src="getIframeUrl()" frameborder="0" class="iframe" ref="iframeRef"></iframe>
</div>
</template>
</DragPanel>
</template>
<!-- 上传报告 -->
<style lang="scss" scoped>
.close-btn {
cursor: pointer;
position: absolute;
top: -40px;
right: 45px;
transform: rotate(270deg);
transform-origin: center;
}
.lab-left {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
overflow: hidden;
h1 {
margin-bottom: 20px;
}
.el-tabs {
flex: 1;
border: 0;
overflow: hidden;
}
:deep(.el-tabs__header) {
background-color: #e1e4eb;
}
:deep(.el-tabs__item) {
padding: 0 14px !important;
border: 0;
border-radius: 6px 6px 0px 0px;
}
:deep(.el-tabs__content) {
height: calc(100% - 40px);
box-sizing: border-box;
}
:deep(.el-tab-pane) {
height: 100%;
overflow-y: auto;
}
}
.lab-box {
position: relative;
flex: 1;
width: 100%;
margin-top: 20px;
background: #f8f9fa;
}
.iframe {
width: 100%;
height: 100%;
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论