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

chore: update

上级 a4686548
......@@ -21,6 +21,7 @@
"dayjs": "^1.11.6",
"element-plus": "^2.2.21",
"file-saver": "^2.0.5",
"html-to-image": "^1.10.8",
"lodash-es": "^4.17.21",
"pinia": "^2.0.24",
"qs": "^6.11.0",
......@@ -2798,6 +2799,11 @@
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.4.2.tgz",
"integrity": "sha512-6rOvaUiNKy9lET1X0ECnyZ5O5kSV0PJbtA5yZUgdEF7fGJEVwSLSislltyt7nFwVVALYHQJtfGeAR2Y0A0uJkg=="
},
"node_modules/html-to-image": {
"version": "1.10.8",
"resolved": "https://registry.npmmirror.com/html-to-image/-/html-to-image-1.10.8.tgz",
"integrity": "sha512-t+JyFJwKDCp4ZwBp4iC/wqw0meQDDc77Qs8OFl5P7RGlIP3LQMvwpD7VXxqQfC7/TfC+GKYlFP6WDYfXTmXHfw=="
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz",
......@@ -7060,6 +7066,11 @@
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.4.2.tgz",
"integrity": "sha512-6rOvaUiNKy9lET1X0ECnyZ5O5kSV0PJbtA5yZUgdEF7fGJEVwSLSislltyt7nFwVVALYHQJtfGeAR2Y0A0uJkg=="
},
"html-to-image": {
"version": "1.10.8",
"resolved": "https://registry.npmmirror.com/html-to-image/-/html-to-image-1.10.8.tgz",
"integrity": "sha512-t+JyFJwKDCp4ZwBp4iC/wqw0meQDDc77Qs8OFl5P7RGlIP3LQMvwpD7VXxqQfC7/TfC+GKYlFP6WDYfXTmXHfw=="
},
"http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz",
......
......@@ -27,6 +27,7 @@
"dayjs": "^1.11.6",
"element-plus": "^2.2.21",
"file-saver": "^2.0.5",
"html-to-image": "^1.10.8",
"lodash-es": "^4.17.21",
"pinia": "^2.0.24",
"qs": "^6.11.0",
......
......@@ -2,6 +2,7 @@
import { getExperimentReport } from '../api'
const props = defineProps({ id: String })
const emit = defineEmits(['ready'])
let experiment = $ref()
let report = $ref()
......@@ -24,7 +25,7 @@ function fetchInfo() {
report = res.data.report
let detail = []
// 已批改
if (report.status === '3') {
if (report.is_comment === '1') {
try {
detail = JSON.parse(report.score_detail).map(item => {
return { ...item, commit_score: parseFloat(item.commit_score) }
......@@ -40,9 +41,12 @@ function fetchInfo() {
}
}
report = Object.assign(report, { detail, score: parseFloat(report.score) })
nextTick(() => {
emit('ready')
})
})
}
onMounted(() => {
watchEffect(() => {
fetchInfo()
})
......@@ -54,6 +58,7 @@ function handleClose() {
<template>
<div class="report-preview">
<div class="report-preview__inner">
<h1 class="report-title">实验报告</h1>
<el-form label-suffix=":" hide-required-asterisk v-if="experiment">
<el-row>
......@@ -107,7 +112,7 @@ function handleClose() {
<el-form-item v-for="(item, index) in report.detail" :key="item.id" class="report-form-item">
<div class="form-hd">
<h3>{{ index + 1 }}、{{ item.name }}</h3>
<p>得分:{{ item.commit_score }}分</p>
<p v-if="isCommit">得分:{{ item.commit_score }}分</p>
</div>
<!-- 内容 -->
<template v-if="item.type === 1">
......@@ -143,6 +148,7 @@ function handleClose() {
</div>
</el-form-item>
</el-form>
</div>
<el-row justify="center">
<el-button type="primary" plain auto-insert-space @click="handleClose">关闭</el-button>
</el-row>
......@@ -150,6 +156,10 @@ function handleClose() {
</template>
<style lang="scss" scoped>
.report-preview__inner {
padding: 40px;
background-color: #fff;
}
.report-title {
padding: 20px;
font-size: 20px;
......
<script setup lang="ts">
import type { ExperimentRecord } from '../types'
import { ElMessageBox } from 'element-plus'
import type { ExperimentRecord, ExperimentRecordFile } from '../types'
import { ElMessage, ElMessageBox } from 'element-plus'
import ImageViewer from '@/components/ImageViewer.vue'
import { uploadExperimentPicture } from '../api'
import { uploadExperimentPicture, getExperimentReport, getExperimentReportCache } from '../api'
const ResultScoreDialog = defineAsyncComponent(() => import('./ResultScoreDialog.vue'))
interface Props {
......@@ -29,7 +29,40 @@ function handlePreview(index: number) {
imageViewerIndex = index
}
// 删除
function handleRemove(index: number) {
async function handleRemove(index: number, file: ExperimentRecordFile) {
if (!props.experiment_id) return
let reportDetail: any = []
await getExperimentReportCache({ experiment_id: props.experiment_id }).then(res => {
const report = res.data.report
if (report.detail) {
try {
reportDetail = JSON.parse(report.detail)
} catch (error) {
console.log(error)
}
}
})
await getExperimentReport({ experiment_id: props.experiment_id }).then(res => {
const report = res.data.report
if (report.detail) {
try {
reportDetail = JSON.parse(report.detail)
} catch (error) {
console.log(error)
}
}
})
const reportFiles: any[] = reportDetail.reduce((result: any[], item: any) => {
if (item.type === 2) {
result = result.concat(item.files)
}
return result
}, [])
const found = reportFiles.find(item => item.url === file.url)
if (found) {
ElMessage.error('不能删除实验报告中的截图,请先删除实验报告关联的截图!')
return
}
ElMessageBox.confirm('删除之后无法恢复,确认删除该截图吗?', '提示').then(() => {
if (!props.experiment_id) return
const pictures = detail?.pictures.filter((item, i) => i !== index)
......@@ -60,7 +93,7 @@ function handleRemove(index: number) {
<div class="cover">
<div class="cover-inner">
<el-button type="primary" plain round @click="handlePreview(index)">查看</el-button>
<el-button type="primary" plain round @click="handleRemove(index)" v-if="canRemove">删除</el-button>
<el-button type="primary" plain round @click="handleRemove(index, item)" v-if="canRemove">删除</el-button>
</div>
</div>
</li>
......
......@@ -8,6 +8,7 @@ import { upload } from '@/utils/upload'
import { getExperiment, getExperimentRecord, uploadExperimentPicture, submitExperimentRecord } from '../api'
import dayjs from 'dayjs'
import { saveAs } from 'file-saver'
import { toBlob } from 'html-to-image'
const Info = defineAsyncComponent(() => import('../components/Info.vue'))
const Book = defineAsyncComponent(() => import('../components/Book.vue'))
......@@ -18,7 +19,7 @@ const ReportDialog = defineAsyncComponent(() => import('../components/ReportDial
const ReportFilePreview = defineAsyncComponent(() => import('../components/ReportFilePreview.vue'))
const PrepareDialog = defineAsyncComponent(() => import('../components/PrepareDialog.vue'))
const ResultDialog = defineAsyncComponent(() => import('../components/ResultDialog.vue'))
// const ReportPreview = defineAsyncComponent(() => import('../components/ReportPreview.vue'))
const ReportPreview = defineAsyncComponent(() => import('../components/ReportPreview.vue'))
const route = useRoute()
......@@ -179,16 +180,30 @@ function handleReportView() {
}
// 导出实验报告
let isExport = $ref(false)
function handleReportExport() {
if (!detail) return
const fileName = `${detail.student.sno_number}_${detail.student.name}_${detail.experiment.name}_实验报告`
// 在线报告
if (experimentInfo?.report_upload_way === 2) {
console.log('在线报告导出')
isExport = true
} else {
saveAs(detail.file.url, fileName)
}
}
function handleReportPreviewReady() {
if (!detail) return
const fileName = `${detail.student.sno_number}_${detail.student.name}_${detail.experiment.name}_实验报告`
const el: HTMLElement | null = document.querySelector('.report-preview__inner')
if (!el) return
setTimeout(() => {
toBlob(el).then(res => {
res && saveAs(res, fileName)
isExport = false
})
}, 100)
}
</script>
<template>
......@@ -296,9 +311,9 @@ function handleReportExport() {
v-if="resultDialogVisible && experimentInfo"></ResultDialog>
<!-- 导出在线报告 -->
<!-- <template v-if="experimentInfo?.id">
<ReportPreview :id="experimentInfo?.id"></ReportPreview>
</template> -->
<template v-if="experimentInfo?.id && isExport">
<ReportPreview :id="experimentInfo?.id" @ready="handleReportPreviewReady"></ReportPreview>
</template>
</template>
<style lang="scss" scoped>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论