金融产品设计及数字化营销沙盘
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

<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(/(&nbsp;|&amp;|%s)/g, '')
.replace(/>/g, '&gt;')
.replace(/</g, '&lt;');
if (e.answer && typeof e.answer === 'string') {
e.answer = e.answer.replace(/<[^>]+>/g, '');
e.answer = e.answer.replace(/(&nbsp;|&amp;|%s)/g, '');
e.answer = e.answer.replace(/>/g, '&gt;');
e.answer = e.answer.replace(/</g, '&lt;');
}
});
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>