|
|
|
<template>
|
|
|
|
<div class="flex justify-between items-center h-[64px] px-5 bg-white">
|
|
|
|
<h1>金融产品设计及数字化营销沙盘系统</h1>
|
|
|
|
<div class="inline-flex items-center">
|
|
|
|
<el-tooltip effect="light"
|
|
|
|
content="退出实训"
|
|
|
|
placement="bottom">
|
|
|
|
<img class="mr-3 cursor-pointer"
|
|
|
|
src="@/assets/images/level/1.png"
|
|
|
|
alt=""
|
|
|
|
@click="logout" />
|
|
|
|
</el-tooltip>
|
|
|
|
<el-tooltip effect="light"
|
|
|
|
content="返回关卡"
|
|
|
|
placement="bottom">
|
|
|
|
<img class="mr-3 cursor-pointer"
|
|
|
|
src="@/assets/images/level/2.png"
|
|
|
|
alt=""
|
|
|
|
@click="toLevel" />
|
|
|
|
</el-tooltip>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="py-5 px-[300px]">
|
|
|
|
<div class="content"
|
|
|
|
:class="{loading}"
|
|
|
|
id="pdfDom">
|
|
|
|
<div class="text-right"
|
|
|
|
v-if="!loading">
|
|
|
|
<el-button @click="editReport">
|
|
|
|
{{ editing ? "保存" : "编辑" }}
|
|
|
|
</el-button>
|
|
|
|
<el-button type="primary"
|
|
|
|
@click="exportPage">导出报告</el-button>
|
|
|
|
</div>
|
|
|
|
<h6 class="mb-8 text-[24px] text-center text-[#333]">标准实验报告</h6>
|
|
|
|
<div class="max-h-[calc(100vh-204px)] overflow-auto p-4 border border-solid border-[#e1e6f2]">
|
|
|
|
<h6 class="l-title">
|
|
|
|
<img src="@/assets/images/report/report1.png"
|
|
|
|
alt="">
|
|
|
|
基本信息
|
|
|
|
</h6>
|
|
|
|
<ul class="info-list flex flex-wrap py-2 px-4"
|
|
|
|
:class="[{edit: editing}]">
|
|
|
|
<li>
|
|
|
|
<label>学生姓名:</label>
|
|
|
|
<el-input v-if="editing"
|
|
|
|
v-model="form.userName"
|
|
|
|
disabled></el-input>
|
|
|
|
<span v-else>{{ form.userName }}</span>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>学生学号:</label>
|
|
|
|
<el-input v-if="editing"
|
|
|
|
v-model="form.workNumber"
|
|
|
|
disabled></el-input>
|
|
|
|
<span v-else>{{ form.workNumber }}</span>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>实验时间:</label>
|
|
|
|
<el-input v-if="editing"
|
|
|
|
v-model="form.submitTime"
|
|
|
|
disabled></el-input>
|
|
|
|
<span v-else>{{ form.submitTime }}</span>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>实验成绩:</label>
|
|
|
|
<el-input v-if="editing"
|
|
|
|
v-model="form.score"
|
|
|
|
disabled></el-input>
|
|
|
|
<div v-else
|
|
|
|
class="relative min-w-[150px] border-b border-solid border-[#e1e6f2]">
|
|
|
|
<em class="absolute top-[-12px] left-[30px] font-semibold font-['din'] text-[30px] text-[#0b1d30]">{{ form.score }}</em>
|
|
|
|
<img class="absolute bottom-[-15px] left-0"
|
|
|
|
src="@/assets/images/report/point.png"
|
|
|
|
alt="">
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>学生班级:</label>
|
|
|
|
<el-input v-if="editing"
|
|
|
|
v-model="form.className"></el-input>
|
|
|
|
<span v-else>{{ form.className }}</span>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>指导老师:</label>
|
|
|
|
<el-input v-if="editing"
|
|
|
|
v-model="form.instructor"></el-input>
|
|
|
|
<span v-else>{{ form.instructor }}</span>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<label>实验学时:</label>
|
|
|
|
<el-input v-if="editing"
|
|
|
|
v-model="form.period"></el-input>
|
|
|
|
<span v-else>{{ form.period }}</span>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
<div class="m-b-20">
|
|
|
|
<h6 class="l-title">
|
|
|
|
<img src="@/assets/images/report/report2.png"
|
|
|
|
alt="">
|
|
|
|
实验项目名称
|
|
|
|
</h6>
|
|
|
|
<el-input v-if="editing"
|
|
|
|
v-model="form.projectName"
|
|
|
|
type="textarea"></el-input>
|
|
|
|
<div v-else
|
|
|
|
class="pre-wrap"
|
|
|
|
v-html="form.projectName"></div>
|
|
|
|
</div>
|
|
|
|
<div class="m-b-20">
|
|
|
|
<h6 class="l-title">
|
|
|
|
<img src="@/assets/images/report/report3.png"
|
|
|
|
alt="">
|
|
|
|
实验目的
|
|
|
|
</h6>
|
|
|
|
<tinymce v-if="editing"
|
|
|
|
v-model="form.purpose" />
|
|
|
|
<div v-else
|
|
|
|
class="pre-wrap"
|
|
|
|
v-html="form.purpose"></div>
|
|
|
|
</div>
|
|
|
|
<div class="m-b-20">
|
|
|
|
<h6 class="l-title">
|
|
|
|
<img src="@/assets/images/report/report4.png"
|
|
|
|
alt="">
|
|
|
|
实验数据
|
|
|
|
</h6>
|
|
|
|
<el-table class="mb-4"
|
|
|
|
:data="expData"
|
|
|
|
border
|
|
|
|
header-align="center">
|
|
|
|
<el-table-column type="index"
|
|
|
|
label="序号"
|
|
|
|
align="center"
|
|
|
|
width="60">
|
|
|
|
<template #default="{ row, $index }">
|
|
|
|
{{ $index + 1 }}
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column prop="judgmentName"
|
|
|
|
label="判分点"
|
|
|
|
width="200"
|
|
|
|
align="center"></el-table-column>
|
|
|
|
<el-table-column prop="judgmentName"
|
|
|
|
label="考核点"
|
|
|
|
align="center"
|
|
|
|
width="150">
|
|
|
|
<template #default="{ row }">
|
|
|
|
<div v-for="(item, i) in row.lcRuleRecords"
|
|
|
|
:key="i">
|
|
|
|
<span>
|
|
|
|
<span>{{i+1}}. </span>{{item.name}}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column prop="ruleAnswer"
|
|
|
|
label="参考答案"
|
|
|
|
style='word-wrap: break-word'>
|
|
|
|
<template #default="{ row }">
|
|
|
|
<div v-for="(item, i) in row?.lcRuleRecords"
|
|
|
|
:key="i">
|
|
|
|
<span>
|
|
|
|
<span>{{i+1}}. </span>{{item.ruleAnswer}}
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column prop="userAnswer"
|
|
|
|
label="学生答案">
|
|
|
|
<template #default="{ row }">
|
|
|
|
<div v-for="(item, i) in row?.lcRuleRecords"
|
|
|
|
:key="i">
|
|
|
|
<span v-if='item.userAnswer'>
|
|
|
|
<span>{{i+1}}. </span>{{item.userAnswer}}
|
|
|
|
</span>
|
|
|
|
<span v-else>
|
|
|
|
<span>{{i+1}}. </span>未填写
|
|
|
|
</span>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</el-table-column>
|
|
|
|
<el-table-column prop="quesScore"
|
|
|
|
label="分值"
|
|
|
|
width="80"
|
|
|
|
align="center"></el-table-column>
|
|
|
|
<el-table-column prop="score"
|
|
|
|
label="得分"
|
|
|
|
width="80"
|
|
|
|
align="center"></el-table-column>
|
|
|
|
</el-table>
|
|
|
|
</div>
|
|
|
|
<div class="m-b-20">
|
|
|
|
<h6 class="l-title">
|
|
|
|
<img src="@/assets/images/report/report5.png"
|
|
|
|
alt="">
|
|
|
|
实验总结与体会
|
|
|
|
</h6>
|
|
|
|
<tinymce v-if="editing"
|
|
|
|
v-model="form.summarize" />
|
|
|
|
<div v-else
|
|
|
|
class="pre-wrap"
|
|
|
|
v-html="form.summarize"></div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<Panel />
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
import { ref, onMounted } from 'vue';
|
|
|
|
import Panel from '@/components/Panel/index.vue';
|
|
|
|
import { logout } from '@/store/useCurrentUser';
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
import Cookies from 'js-cookie';
|
|
|
|
import { useRouter, useRoute } from 'vue-router';
|
|
|
|
import { reportDetail, exportBankExperimentReport, updateReport, editExperimentalData } from '@/api/system';
|
|
|
|
import Tinymce from '@/components/Tinymce/index.vue';
|
|
|
|
import { downloadFileDirect } from '@/utils/common';
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
const reportId = ref<string | number>(Cookies.get('sand-reportId'));
|
|
|
|
const form = ref<Record<string, any>>({});
|
|
|
|
const expData = ref<Record<string, any>[]>([]);
|
|
|
|
const editing = ref<boolean>(false);
|
|
|
|
const userScores = ref<Record<string, any>[]>([]);
|
|
|
|
|
|
|
|
// 处理实验数据
|
|
|
|
const handleList = (list: Record<string, any>[]) => {
|
|
|
|
list.map((e) => {
|
|
|
|
e.assessmentPoint = '';
|
|
|
|
e.referenceAnswer = '';
|
|
|
|
e.answer = '';
|
|
|
|
e?.lcRuleRecords?.map((n, i) => {
|
|
|
|
e.assessmentPoint += `${i + 1}.${n.name}`;
|
|
|
|
// e.referenceAnswer += `${i + 1}.${n.ruleAnswer}`;
|
|
|
|
e.referenceAnswer += `${i + 1}.${n.ruleAnswer}`;
|
|
|
|
e.answer += `${i + 1}.${n.userAnswer || '未填写'}`;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
console.log('🚀 ~ file: Index.vue:235 ~ handleList ~ list:', list);
|
|
|
|
expData.value = list;
|
|
|
|
};
|
|
|
|
// 查询详情
|
|
|
|
const getData = async () => {
|
|
|
|
const res = await reportDetail(reportId.value);
|
|
|
|
form.value = res.report;
|
|
|
|
userScores.value = res.userScores;
|
|
|
|
const { data } = res.report;
|
|
|
|
// 如果没有data,则添加,否则,直接使用
|
|
|
|
if (!data) {
|
|
|
|
handleList(res.userScores);
|
|
|
|
await editExperimentalData({
|
|
|
|
reportId: reportId.value,
|
|
|
|
data: JSON.stringify(res.userScores),
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
handleList(res.userScores);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// 导出
|
|
|
|
const exportPage = async () => {
|
|
|
|
const param = JSON.parse(JSON.stringify(form.value));
|
|
|
|
const list = JSON.parse(JSON.stringify(expData.value));
|
|
|
|
list.forEach((e, i) => {
|
|
|
|
e.id = i + 1;
|
|
|
|
if (e.referenceAnswer && typeof e.referenceAnswer === 'string')
|
|
|
|
e.referenceAnswer = e.referenceAnswer
|
|
|
|
.replace(/<[^>]+>/g, '')
|
|
|
|
.replace(/( |&|%s)/g, '')
|
|
|
|
.replace(/>/g, '>')
|
|
|
|
.replace(/</g, '<');
|
|
|
|
if (e.answer && typeof e.answer === 'string') {
|
|
|
|
e.answer = e.answer.replace(/<[^>]+>/g, '');
|
|
|
|
e.answer = e.answer.replace(/( |&|%s)/g, '');
|
|
|
|
e.answer = e.answer.replace(/>/g, '>');
|
|
|
|
e.answer = e.answer.replace(/</g, '<');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
for (const i in param) {
|
|
|
|
if (param[i] && typeof param[i] === 'string') param[i] = param[i].replace(/<[^>]+>/g, '');
|
|
|
|
}
|
|
|
|
param.purpose = param.purpose.replace(/<[^>]+>/g, '');
|
|
|
|
const res = await exportBankExperimentReport({
|
|
|
|
...param,
|
|
|
|
experimentalData: list,
|
|
|
|
});
|
|
|
|
downloadFileDirect(`实验报告.docx`, new Blob([res]));
|
|
|
|
};
|
|
|
|
// 编辑实验报告
|
|
|
|
const editReport = async () => {
|
|
|
|
if (editing.value) {
|
|
|
|
await updateReport(form.value);
|
|
|
|
editing.value = false;
|
|
|
|
ElMessage.success('修改成功');
|
|
|
|
} else {
|
|
|
|
editing.value = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
// 返回关卡
|
|
|
|
const toLevel = () => {
|
|
|
|
router.push('/');
|
|
|
|
};
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
getData();
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
code,
|
|
|
|
kbd,
|
|
|
|
samp {
|
|
|
|
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
|
|
|
|
word-wrap: break-word;
|
|
|
|
white-space: pre-wrap;
|
|
|
|
}
|
|
|
|
:deep(pre) {
|
|
|
|
white-space: pre-wrap; /* css-3 */
|
|
|
|
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
|
|
|
white-space: pre-wrap; /* Opera 4-6 */
|
|
|
|
white-space: -o-pre-wrap; /* Opera 7 */
|
|
|
|
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
|
|
|
word-break: break-all;
|
|
|
|
overflow: hidden;
|
|
|
|
font-size: 12px;
|
|
|
|
font-weight: 400;
|
|
|
|
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
|
|
|
|
}
|
|
|
|
.content {
|
|
|
|
&.loading {
|
|
|
|
padding-top: 30px;
|
|
|
|
}
|
|
|
|
.l-title {
|
|
|
|
@apply flex items-center px-2 py-1 mb-3 bg-[#f7f9fc];
|
|
|
|
img {
|
|
|
|
@apply mr-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.info-list {
|
|
|
|
li {
|
|
|
|
@apply inline-flex w-[25%] px-2 mb-[34px];
|
|
|
|
}
|
|
|
|
&.edit {
|
|
|
|
li {
|
|
|
|
@apply items-center;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
label {
|
|
|
|
@apply text-sm text-[#333] whitespace-nowrap;
|
|
|
|
}
|
|
|
|
span {
|
|
|
|
@apply min-w-[150px] px-2 pb-[3px] text-sm;
|
|
|
|
border-bottom: 1px solid #e1e6f2;
|
|
|
|
}
|
|
|
|
:deep(.el-input) {
|
|
|
|
@apply w-[174px];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
:deep(.el-textarea .el-textarea__inner),
|
|
|
|
.pre-wrap {
|
|
|
|
min-height: 72px;
|
|
|
|
padding: 10px 16px;
|
|
|
|
font-size: 14px;
|
|
|
|
color: #333;
|
|
|
|
&.edit {
|
|
|
|
color: #abb3c6;
|
|
|
|
border: 1px solid #cacfdb;
|
|
|
|
border-radius: 4px;
|
|
|
|
background-color: #f6f7f9;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
:deep(.table th) {
|
|
|
|
background-color: #e1eaff !important;
|
|
|
|
.cell {
|
|
|
|
line-height: 35px;
|
|
|
|
color: #555555;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.result-pic {
|
|
|
|
margin: 10px 0;
|
|
|
|
}
|
|
|
|
@media (max-width: 1650px) {
|
|
|
|
.wrap {
|
|
|
|
padding: 12px 200px 20px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@media (max-width: 1430px) {
|
|
|
|
.wrap {
|
|
|
|
padding: 12px 100px 20px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|