You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
395 lines
12 KiB
395 lines
12 KiB
<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>
|
|
|