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

chore: update

上级 52fd3661
...@@ -19,6 +19,7 @@ const emit = defineEmits<{ ...@@ -19,6 +19,7 @@ const emit = defineEmits<{
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive<any>({ const form = reactive<any>({
experiment_id: props.data.id,
is_show: '1', is_show: '1',
rule_list: [{ name: '实验报告', type: 1, percent: 100, rule_mode: 1 }] rule_list: [{ name: '实验报告', type: 1, percent: 100, rule_mode: 1 }]
}) })
...@@ -76,7 +77,7 @@ function handleSubmit() { ...@@ -76,7 +77,7 @@ function handleSubmit() {
} }
formRef?.validate().then(() => { formRef?.validate().then(() => {
const params = { experiment_id: props.data.id, ...form, rule_list: JSON.stringify(form.rule_list) } const params = { ...form, rule_list: JSON.stringify(form.rule_list) }
updateExperimentGradeRule(params).then(() => { updateExperimentGradeRule(params).then(() => {
ElMessage({ message: '保存成功', type: 'success' }) ElMessage({ message: '保存成功', type: 'success' })
emit('update') emit('update')
......
...@@ -3,11 +3,10 @@ import type { Component } from 'vue' ...@@ -3,11 +3,10 @@ import type { Component } from 'vue'
import { Delete } from '@element-plus/icons-vue' import { Delete } from '@element-plus/icons-vue'
import { ElMessageBox } from 'element-plus' import { ElMessageBox } from 'element-plus'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import ReportDesignContent from './ReportDesignContent.vue'
const ReportDesignContent = defineAsyncComponent(() => import('./ReportDesignContent.vue')) import ReportDesignAttachment from './ReportDesignAttachment.vue'
const ReportDesignAttachment = defineAsyncComponent(() => import('./ReportDesignAttachment.vue')) import ReportDesignQuestion from './ReportDesignQuestion.vue'
const ReportDesignQuestion = defineAsyncComponent(() => import('./ReportDesignQuestion.vue')) import ReportDesignPaper from './ReportDesignPaper.vue'
const ReportDesignPaper = defineAsyncComponent(() => import('./ReportDesignPaper.vue'))
interface Props { interface Props {
modelValue: any[] modelValue: any[]
...@@ -36,12 +35,14 @@ function getComponent(type: number) { ...@@ -36,12 +35,14 @@ function getComponent(type: number) {
// 添加 // 添加
function handleAdd(type: number) { function handleAdd(type: number) {
datalist.unshift({ type }) datalist.unshift({ type, id: Date.now(), name: '', score: 10 })
emit('update:modelValue', datalist)
} }
// 删除 // 删除
function handleRemove(index: number) { function handleRemove(index: number) {
ElMessageBox.confirm('删除组件将导致报告分值的变化,请确认是否删除组件?', '提示').then(() => { ElMessageBox.confirm('删除组件将导致报告分值的变化,请确认是否删除组件?', '提示').then(() => {
datalist.splice(index, 1) datalist.splice(index, 1)
emit('update:modelValue', datalist)
}) })
} }
function handleChange(data: any, index: number) { function handleChange(data: any, index: number) {
...@@ -57,8 +58,9 @@ function handleChange(data: any, index: number) { ...@@ -57,8 +58,9 @@ function handleChange(data: any, index: number) {
<el-button type="primary" @click="handleAdd(1)">添加内容组件</el-button> <el-button type="primary" @click="handleAdd(1)">添加内容组件</el-button>
<el-button type="primary" @click="handleAdd(2)">添加附件组件</el-button> <el-button type="primary" @click="handleAdd(2)">添加附件组件</el-button>
<el-button type="primary" @click="handleAdd(3)">添加思考题组件</el-button> <el-button type="primary" @click="handleAdd(3)">添加思考题组件</el-button>
<el-button type="primary" @click="handleAdd(4)">添加试卷组件</el-button> <el-button type="primary" disabled @click="handleAdd(4)">添加试卷组件</el-button>
</el-button-group> </el-button-group>
<slot name="header"></slot>
</div> </div>
<div class="report-design-bd"> <div class="report-design-bd">
<draggable v-model="datalist" item-key="id"> <draggable v-model="datalist" item-key="id">
...@@ -66,6 +68,7 @@ function handleChange(data: any, index: number) { ...@@ -66,6 +68,7 @@ function handleChange(data: any, index: number) {
<div class="report-design-item-card"> <div class="report-design-item-card">
<component <component
:is="getComponent(element.type)" :is="getComponent(element.type)"
:index="index"
:data="element" :data="element"
@change="(data:any) => handleChange(data, index)" /> @change="(data:any) => handleChange(data, index)" />
<el-button type="danger" :icon="Delete" circle @click="handleRemove(index)" /> <el-button type="danger" :icon="Delete" circle @click="handleRemove(index)" />
...@@ -77,6 +80,10 @@ function handleChange(data: any, index: number) { ...@@ -77,6 +80,10 @@ function handleChange(data: any, index: number) {
</template> </template>
<style lang="scss"> <style lang="scss">
.report-design-hd {
display: flex;
align-items: center;
}
.report-design-item-card { .report-design-item-card {
display: flex; display: flex;
align-items: center; align-items: center;
......
<script setup lang="ts"> <script setup lang="ts">
interface Props { interface Props {
index: number
data: any data: any
} }
const props = defineProps<Props>() const props = defineProps<Props>()
...@@ -28,50 +29,62 @@ watchEffect(() => { ...@@ -28,50 +29,62 @@ watchEffect(() => {
}) })
watch(form, value => emit('change', value), { deep: true }) watch(form, value => emit('change', value), { deep: true })
function handleScoreChange(value: number) {
form.min_score = Math.min(value, form.min_score)
form.has_score = Math.min(value, form.has_score)
form.no_score = Math.min(value, form.no_score)
}
</script> </script>
<template> <template>
<div class="report-design-item"> <div class="report-design-item">
<el-form :model="form" label-suffix=":"> <el-row :gutter="40">
<el-row :gutter="40"> <el-col :span="6">
<el-col :span="6"> <el-form-item
<el-form-item label="附件组件名称" prop="name" label-width="130px"> label="附件组件名称"
<el-input v-model="form.name" placeholder="例:实验源代码程序包" maxlength="20" /> label-width="130px"
</el-form-item> :prop="'detail_list.' + index + '.name'"
</el-col> :rules="[{ required: true, message: '请输入' }]">
<el-col :span="6"> <el-input v-model="form.name" placeholder="例:实验源代码程序包" maxlength="20" />
<el-form-item label="分值" prop="score"> </el-form-item>
<el-input-number :min="0" v-model="form.score" /> </el-col>
</el-form-item> <el-col :span="6">
</el-col> <el-form-item label="分值" prop="score">
<el-col :span="6"> <el-input-number :min="0" v-model="form.score" @change="handleScoreChange" />
<el-form-item label="评分规则" prop="rule_mode"> </el-form-item>
<el-radio-group v-model="form.rule_mode"> </el-col>
<el-radio :label="1">人工评分</el-radio> <el-col :span="6">
<el-radio :label="2">自动评分</el-radio> <el-form-item label="评分规则" prop="rule_mode">
</el-radio-group> <el-radio-group v-model="form.rule_mode">
</el-form-item> <el-radio :label="1">人工评分</el-radio>
</el-col> <el-radio :label="2">自动评分</el-radio>
<el-col :span="6"> </el-radio-group>
<el-form-item label="最低分" prop="min_score"> </el-form-item>
<el-input-number :min="0" v-model="form.min_score" v-if="form.rule_mode === 1" /> </el-col>
<template v-else> <el-col :span="6">
<el-form-item label="有附件" label-width="auto" style="margin-right: 10px; margin-bottom: 10px"> <el-form-item label="最低分" prop="min_score">
<el-input-number :min="0" v-model="form.has_score" /> <el-input-number :min="0" :max="form.score" v-model="form.min_score" v-if="form.rule_mode === 1" />
</el-form-item> <template v-else>
<el-form-item label="无附件" label-width="auto" style="margin-bottom: 10px"> <el-form-item label="有附件" label-width="auto" style="margin-right: 10px; margin-bottom: 10px">
<el-input-number :min="0" v-model="form.no_score" /> <el-input-number :min="0" :max="form.score" v-model="form.has_score" />
</el-form-item> </el-form-item>
</template> <el-form-item label="无附件" label-width="auto" style="margin-bottom: 10px">
</el-form-item> <el-input-number :min="0" :max="form.score" v-model="form.no_score" />
</el-col> </el-form-item>
</el-row> </template>
<el-form-item label="附件类型" prop="categories" label-width="130px"> </el-form-item>
<el-checkbox-group v-model="form.categories"> </el-col>
<el-checkbox :label="1">实验截图</el-checkbox> </el-row>
<el-checkbox :label="2">本地文件</el-checkbox> <el-form-item
</el-checkbox-group> label="附件类型"
</el-form-item> label-width="130px"
</el-form> :prop="'detail_list.' + index + '.categories'"
:rules="[{ required: true, message: '请选择' }]">
<el-checkbox-group v-model="form.categories">
<el-checkbox :label="1">实验截图</el-checkbox>
<el-checkbox :label="2">本地文件</el-checkbox>
</el-checkbox-group>
</el-form-item>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
interface Props { interface Props {
index: number
data: any data: any
} }
const props = defineProps<Props>() const props = defineProps<Props>()
...@@ -17,44 +18,54 @@ watchEffect(() => { ...@@ -17,44 +18,54 @@ watchEffect(() => {
}) })
watch(form, value => emit('change', value), { deep: true }) watch(form, value => emit('change', value), { deep: true })
function handleScoreChange(value: number) {
form.min_score = Math.min(value, form.min_score)
}
</script> </script>
<template> <template>
<div class="report-design-item"> <div class="report-design-item">
<el-form :model="form" label-suffix=":"> <el-row :gutter="40">
<el-row :gutter="40"> <el-col :span="6">
<el-col :span="6"> <el-form-item
<el-form-item label="内容组件名称" prop="name" label-width="130px"> label="内容组件名称"
<el-input v-model="form.name" placeholder="例:实验目的" maxlength="20" /> label-width="130px"
</el-form-item> :prop="'detail_list.' + index + '.name'"
</el-col> :rules="[{ required: true, message: '请输入' }]">
<el-col :span="6"> <el-input v-model="form.name" placeholder="例:实验目的" maxlength="20" />
<el-form-item label="分值" prop="score"> </el-form-item>
<el-input-number :min="0" v-model="form.score" /> </el-col>
</el-form-item> <el-col :span="6">
</el-col> <el-form-item label="分值" prop="score">
<el-col :span="6"> <el-input-number :min="0" v-model="form.score" @change="handleScoreChange" />
<el-form-item label="评分规则" prop="rule_mode"> </el-form-item>
<el-radio-group v-model="form.rule_mode"> </el-col>
<el-radio :label="1">人工评分</el-radio> <el-col :span="6">
<!-- <el-radio :label="2">自动评分</el-radio> --> <el-form-item label="评分规则" prop="rule_mode">
</el-radio-group> <el-radio-group v-model="form.rule_mode">
</el-form-item> <el-radio :label="1">人工评分</el-radio>
</el-col> <!-- <el-radio :label="2">自动评分</el-radio> -->
<el-col :span="6"> </el-radio-group>
<el-form-item label="最低分" prop="min_score"> </el-form-item>
<el-input-number :min="0" v-model="form.min_score" /> </el-col>
</el-form-item> <el-col :span="6">
</el-col> <el-form-item label="最低分" prop="min_score">
</el-row> <el-input-number :min="0" :max="form.score" v-model="form.min_score" />
<el-form-item label="组件提示信息" prop="notice_message" label-width="130px"> </el-form-item>
<el-input </el-col>
type="textarea" </el-row>
v-model="form.notice_message" <el-form-item
:autosize="{ minRows: 4 }" label="组件提示信息"
show-word-limit label-width="130px"
maxlength="200" /> :prop="'detail_list.' + index + '.notice_message'"
</el-form-item> :rules="[{ required: true, message: '请输入' }]">
</el-form> <el-input
type="textarea"
v-model="form.notice_message"
:autosize="{ minRows: 4 }"
show-word-limit
maxlength="200" />
</el-form-item>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
interface Props { interface Props {
index: number
data: any data: any
} }
const props = defineProps<Props>() const props = defineProps<Props>()
...@@ -17,44 +18,54 @@ watchEffect(() => { ...@@ -17,44 +18,54 @@ watchEffect(() => {
}) })
watch(form, value => emit('change', value), { deep: true }) watch(form, value => emit('change', value), { deep: true })
function handleScoreChange(value: number) {
form.min_score = Math.min(value, form.min_score)
}
</script> </script>
<template> <template>
<div class="report-design-item"> <div class="report-design-item">
<el-form :model="form" label-suffix=":"> <el-row :gutter="40">
<el-row :gutter="40"> <el-col :span="6">
<el-col :span="6"> <el-form-item
<el-form-item label="思考题组件名称" prop="name" label-width="130px"> label="思考题组件名称"
<el-input v-model="form.name" placeholder="例:实验扩展思考" maxlength="20" /> label-width="130px"
</el-form-item> :prop="'detail_list.' + index + '.name'"
</el-col> :rules="[{ required: true, message: '请输入' }]">
<el-col :span="6"> <el-input v-model="form.name" placeholder="例:实验扩展思考" maxlength="20" />
<el-form-item label="分值" prop="score"> </el-form-item>
<el-input-number :min="0" v-model="form.score" /> </el-col>
</el-form-item> <el-col :span="6">
</el-col> <el-form-item label="分值" prop="score">
<el-col :span="6"> <el-input-number :min="0" v-model="form.score" @change="handleScoreChange" />
<el-form-item label="评分规则" prop="rule_mode"> </el-form-item>
<el-radio-group v-model="form.rule_mode"> </el-col>
<el-radio :label="1">人工评分</el-radio> <el-col :span="6">
<!-- <el-radio :label="2">自动评分</el-radio> --> <el-form-item label="评分规则" prop="rule_mode">
</el-radio-group> <el-radio-group v-model="form.rule_mode">
</el-form-item> <el-radio :label="1">人工评分</el-radio>
</el-col> <!-- <el-radio :label="2">自动评分</el-radio> -->
<el-col :span="6"> </el-radio-group>
<el-form-item label="最低分" prop="min_score"> </el-form-item>
<el-input-number :min="0" v-model="form.min_score" /> </el-col>
</el-form-item> <el-col :span="6">
</el-col> <el-form-item label="最低分" prop="min_score">
</el-row> <el-input-number :min="0" :max="form.score" v-model="form.min_score" />
<el-form-item label="思考题题干内容" prop="question_stem" label-width="130px"> </el-form-item>
<el-input </el-col>
type="textarea" </el-row>
v-model="form.question_stem" <el-form-item
:autosize="{ minRows: 4 }" label="思考题题干内容"
show-word-limit label-width="130px"
maxlength="200" /> :prop="'detail_list.' + index + '.question_stem'"
</el-form-item> :rules="[{ required: true, message: '请输入' }]">
</el-form> <el-input
type="textarea"
v-model="form.question_stem"
:autosize="{ minRows: 4 }"
show-word-limit
maxlength="200" />
</el-form-item>
</div> </div>
</template> </template>
...@@ -63,11 +63,38 @@ const teacherText = $computed(() => { ...@@ -63,11 +63,38 @@ const teacherText = $computed(() => {
<p class="score">{{ item.score }}</p> <p class="score">{{ item.score }}</p>
<p class="rule-mode">{{ reportScoreRule[item.rule_mode] }}</p> <p class="rule-mode">{{ reportScoreRule[item.rule_mode] }}</p>
</div> </div>
<el-input <!-- 内容组件 -->
type="textarea" <template v-if="item.type === 1">
readonly <p>{{ item.notice_message || item.question_stem }}</p>
:autosize="{ minRows: 6 }" <el-input
:value="item.notice_message || item.question_stem" /> type="textarea"
readonly
:autosize="{ minRows: 6 }"
:placeholder="`这里是学生填写的${item.name}回答内容,支持富文本。`" />
</template>
<!-- 附件组件 -->
<template v-else-if="item.type === 2">
<el-table :data="[{}, {}]" stripe :header-cell-style="{ background: '#ededed' }">
<el-table-column label="序号" type="index" width="80px" align="center"></el-table-column>
<el-table-column label="附件类型" align="center"></el-table-column>
<el-table-column label="附件名称" align="center"></el-table-column>
<el-table-column label="更新时间" align="center"></el-table-column>
<el-table-column label="操作" align="right">
<el-link>查看</el-link>
</el-table-column>
</el-table>
</template>
<!-- 思考题 -->
<template v-else-if="item.type === 3">
<p>{{ item.question_stem }}</p>
<el-input
type="textarea"
readonly
:autosize="{ minRows: 6 }"
:placeholder="`这里是学生填写的${item.name}回答内容,支持富文本。`" />
</template>
<!-- 试卷 -->
<template v-else-if="item.type === 4"> </template>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row justify="center"> <el-row justify="center">
...@@ -85,6 +112,9 @@ const teacherText = $computed(() => { ...@@ -85,6 +112,9 @@ const teacherText = $computed(() => {
} }
.total-score { .total-score {
text-align: right; text-align: right;
font-size: 16px;
font-weight: bold;
color: var(--main-color);
padding-right: 100px; padding-right: 100px;
} }
.form-hd { .form-hd {
......
<script setup lang="ts"> <script setup lang="ts">
import type { ExperimentItem } from '../types' import type { ExperimentItem } from '../types'
import { ElMessageBox } from 'element-plus' import type { FormInstance } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import ReportDesign from '../components/ReportDesign.vue' import ReportDesign from '../components/ReportDesign.vue'
import { getExperiment } from '../api' import { getExperiment, getExperimentReportRule, updateExperimentReportRule } from '../api'
const ReportPreview = defineAsyncComponent(() => import('../components/ReportPreview.vue')) const ReportPreview = defineAsyncComponent(() => import('../components/ReportPreview.vue'))
...@@ -16,49 +17,76 @@ const teacherText = $computed(() => { ...@@ -16,49 +17,76 @@ const teacherText = $computed(() => {
if (!detail) return '' if (!detail) return ''
return detail.teacher.map(item => item.name).join('、') return detail.teacher.map(item => item.name).join('、')
}) })
function fetchInfo() { // 获取实验信息
function fetchExperimentInfo() {
getExperiment({ experiment_id: props.id }).then(res => { getExperiment({ experiment_id: props.id }).then(res => {
detail = res.data.info detail = res.data.info
}) })
} }
const formRef = $ref<FormInstance>()
const form = reactive({ const form = reactive({
switch: true, experiment_id: props.id,
detail_list: [ report_upload_way: 1,
{ detail_list: []
id: '233434343', })
name: '实验目的',
type: 1, // 获取报告信息
notice_message: '好好学习天线向上', function fetchInfo() {
rule_mode: 1, getExperimentReportRule({ experiment_id: props.id }).then(res => {
score: '10.00', const { data } = res
min_score: '5.00' let detailList = []
}, try {
{ detailList = JSON.parse(data.info.detail_list).map((item: any) => {
id: '233434344', return { ...item, percent: parseFloat(item.percent) }
name: '实验附件', })
type: 2, } catch (error) {
rule_mode: 2, console.log(error)
score: '10.00',
min_score: '5.00',
categories: [1, 2],
has_score: '8.00',
no_score: '5.00'
},
{
id: '233434344',
name: '思考题',
type: 3,
rule_mode: 1,
score: '10.00',
min_score: '5.00',
question_stem: '这是思考题的题干'
} }
] Object.assign(form, { report_upload_way: data.way, detail_list: detailList })
})
}
onMounted(() => {
fetchExperimentInfo()
fetchInfo()
})
const score = $computed(() => {
return detail?.score ? parseFloat(detail.score) : 0
})
// 合计
const total = $computed(() => {
return form.detail_list.reduce((result: number, item: any) => {
return result + (item.score || 0)
}, 0)
}) })
onMounted(() => fetchInfo())
// 保存 // 保存
function handleSubmit() {} function handleSubmit() {
if (total !== score) {
ElMessage.error('请确保组件总分等于实验总分!')
return
}
formRef?.validate().then(() => {
const params = { ...form, detail_list: JSON.stringify(form.detail_list) }
if (form.report_upload_way === 1) {
ElMessageBox.confirm('确定将当前实验的实验报告提交方式保存为学生手工上传文件吗?', '提示', {
type: 'warning'
}).then(() => {
updateExperimentReportRule(params).then(() => {
ElMessage({ message: '保存成功', type: 'success' })
window.close()
})
})
} else {
updateExperimentReportRule(params).then(() => {
ElMessage({ message: '保存成功', type: 'success' })
})
}
})
}
// 关闭 // 关闭
function handleClose() { function handleClose() {
...@@ -76,7 +104,7 @@ function handlePreview() { ...@@ -76,7 +104,7 @@ function handlePreview() {
<template> <template>
<AppCard title="实验报告规则设置"> <AppCard title="实验报告规则设置">
<el-form :model="form" label-suffix=":" v-if="detail"> <el-form ref="formRef" :model="form" label-suffix=":" hide-required-asterisk v-if="detail">
<el-row> <el-row>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="实验名称">{{ detail.name }}</el-form-item> <el-form-item label="实验名称">{{ detail.name }}</el-form-item>
...@@ -96,22 +124,38 @@ function handlePreview() { ...@@ -96,22 +124,38 @@ function handlePreview() {
<el-form-item :span="3" label="指导教师">{{ teacherText }}</el-form-item> <el-form-item :span="3" label="指导教师">{{ teacherText }}</el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item label="实验报告提交方式" prop="switch"> <el-form-item label="实验报告提交方式" prop="report_upload_way">
<el-switch <el-switch
v-model="form.switch" v-model="form.report_upload_way"
active-text="上传文件" active-text="上传文件"
:active-value="1"
inactive-text="在线填写" inactive-text="在线填写"
:inactive-value="2"
style="--el-switch-on-color: #ba143e; --el-switch-off-color: #ba143e" /> style="--el-switch-on-color: #ba143e; --el-switch-off-color: #ba143e" />
</el-form-item> </el-form-item>
<ReportDesign v-model="form.detail_list"></ReportDesign> <ReportDesign v-model="form.detail_list" v-if="form.report_upload_way === 2">
<template #header>
<p class="report-header-item">实验总分:{{ detail.score }}</p>
<p class="report-header-item">组件总分:{{ total }}</p>
</template>
</ReportDesign>
</el-form> </el-form>
<el-row justify="center"> <el-row justify="center">
<el-space :size="40"> <el-space :size="40">
<el-button auto-insert-space @click="handleClose">关闭</el-button> <el-button auto-insert-space @click="handleClose">关闭</el-button>
<el-button type="primary" auto-insert-space @click="handleSubmit">保存</el-button> <el-button type="primary" auto-insert-space @click="handleSubmit">保存</el-button>
<el-button type="primary" auto-insert-space @click="handlePreview">预览</el-button> <el-button type="primary" auto-insert-space @click="handlePreview" v-if="form.report_upload_way === 2"
>预览</el-button
>
</el-space> </el-space>
</el-row> </el-row>
<ReportPreview v-model="previewVisible" :data="{ ...detail, ...form }"></ReportPreview> <ReportPreview v-model="previewVisible" :data="{ ...detail, ...form }"></ReportPreview>
</AppCard> </AppCard>
</template> </template>
<style lang="scss">
.report-header-item {
flex: 1;
text-align: center;
}
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论