预览原先在 5 个地方各写一遍(文书库预览、编辑器签署预览、发起签署弹窗预览、 工作台在线预览、工作台文书区),基础排版已经分叉:表格边框 #52646e 与 #c8d7dd 两套色、单元格内边距 5px 7px 与 5px 9px 两个值、只有两处带宋体。 原型本身是「一处渲染(.paper + fillDocHtml)、两种外框」,这次按那个形状收口。 新增 - utils/document-paper.ts:基础排版的**唯一一份** CSS(p / h1-h4 / 表格 / 宋体)。 运行期幂等注入 head —— 因为同一份纸有两条渲染通道:v-html(吃全局样式)与 iframe srcdoc(隔离模板自带 style,只能吃字符串),各写一份必然漂移。 - components/document/DocumentPaper.vue:唯一的纸渲染器。 signing / raw 两模式、interactive、取值还原、☑☐ 就地切换、签名位请求采集、 填写项与勾选上报、getDocumentElement()(供导出 PDF)。 - components/document/DocumentPreviewDialog.vue:唯一的预览外框。 标题/副标题/徽标、可选页签、加载与错误态、纸舞台(浅色卡片 / 深灰 A4)、 #footer 与 #empty 插槽。 - styles/document-preview.css:页脚按钮等**插槽内容**要用的类。 插槽节点带的是父组件 scope id,弹窗的 scoped 样式命中不了 —— 与 signing-document.css 同一类问题,同一套解法。 迁移 - 文书库预览、编辑器签署预览、发起签署弹窗预览、工作台在线预览全部改走统一组件; SigningDocumentInteractive 的纸换成 DocumentPaper,只留任务外壳 (横幅 / 作废章 / 填写项进度)。 - 删除四处基础排版副本;SimSun 与 :deep(table) 现在各只剩一处。 行为保持 - 文书库预览仍是两个页签(文书内容走 iframe 隔离、签署预览走 v-html), 没有正文时仍给占位版式(占位符写成 {患者姓名} 原始形态,不预填示例值)。 - 工作台预览的深灰 A4 舞台、页脚说明与两个出口按钮不变。 - 作废章原先是纸的兄弟节点、DOM 顺序在前,纸改成自带白底后会被盖住 —— 给章补 z-index,并在探针里加命中测试锁死。 验证 - 新增 probe-doc-paper.cjs:31/31 PASS。核心是**计算样式**断言 (边框色 / 内边距 / 宋体 / border-collapse),并断言文书库预览与编辑器预览 两份纸的样式**逐项一致** —— 只看 DOM 存在证明不了"只有一份排版"。 - 回归:probe-new-task 104/104、probe-workbench-lib 46/46(新增作废章命中测试)、 probe-dept-confirm 36/36、probe-method-domain 14/14、probe-report-analytics 92/92。 - vue-tsc 与 eslint 0 错。 净减 888 行(309 增 / 1197 删)。
85 lines
3.0 KiB
Vue
85 lines
3.0 KiB
Vue
<script setup lang="ts">
|
||
/**
|
||
* 已签署 / 待科室确认文书的在线预览(原型 openPdfView 的 mdPdfView)。
|
||
*
|
||
* 它只是**统一预览弹窗**在签署工作台这一处的配置:
|
||
* 深灰 A4 舞台 + 「只读副本 / 下载 PDF 原件」两个出口。
|
||
* 纸的渲染在 components/document/DocumentPaper.vue、弹窗外壳在 DocumentPreviewDialog.vue,
|
||
* 这里不重复实现任何渲染逻辑 —— 预览看到的版式必须与工作台里、与导出的 PDF 完全一致。
|
||
*/
|
||
import { computed } from 'vue'
|
||
|
||
import type { SigningTaskRecord } from '@/api/workbench/types'
|
||
import DocumentPreviewDialog from '@/components/document/DocumentPreviewDialog.vue'
|
||
import SigningDocumentPreview from '@/components/signing/SigningDocumentPreview.vue'
|
||
import type { SigningDocumentData } from '@/utils/signing-document'
|
||
|
||
const props = defineProps<{
|
||
visible: boolean
|
||
task: SigningTaskRecord | null
|
||
/** 导出中:两个下载按钮一起禁用,避免重复点出多份 PDF */
|
||
exporting: boolean
|
||
}>()
|
||
|
||
const emit = defineEmits<{
|
||
close: []
|
||
download: []
|
||
'download-readonly-copy': []
|
||
}>()
|
||
|
||
const subtitle = computed(() =>
|
||
props.task ? `${props.task.documentName} · ${props.task.id} · ${props.task.patientName}` : '',
|
||
)
|
||
|
||
/** 只挑渲染真正需要的字段显式映射,不直接透传整个任务对象 */
|
||
const documentData = computed<SigningDocumentData>(() => ({
|
||
patientName: props.task?.patientName ?? '',
|
||
sex: props.task?.sex ?? '',
|
||
age: props.task?.age ?? '',
|
||
visitNo: props.task?.visitNo ?? '',
|
||
visitDate: props.task?.visitDate ?? '',
|
||
signedAt: props.task?.signedAt ?? '',
|
||
signatureDataUrl: props.task?.signatureDataUrl,
|
||
selectedItems: props.task?.selectedItems,
|
||
fieldAnswers: props.task?.fieldAnswers,
|
||
}))
|
||
</script>
|
||
|
||
<template>
|
||
<DocumentPreviewDialog
|
||
:visible="visible && Boolean(task)"
|
||
title="在线预览(PDF)"
|
||
:subtitle="subtitle"
|
||
:content-html="task?.documentContentHtml ?? ''"
|
||
:data="documentData"
|
||
stage="stage"
|
||
:width="900"
|
||
@close="emit('close')"
|
||
>
|
||
<!-- 正文取不到时用带任务信息的回退纸样,而不是一句「暂无正文」:
|
||
那会把「后端没给正文」和「这份文书本来就是空的」混为一谈 -->
|
||
<template #empty>
|
||
<SigningDocumentPreview v-if="task" :task="task" />
|
||
</template>
|
||
|
||
<template #footer>
|
||
<span class="preview-note-footer">
|
||
正式文书以服务端生成的 PDF 原件为准;此处预览按任务固化的文书版本渲染。
|
||
</span>
|
||
<span class="preview-spacer" />
|
||
<button
|
||
type="button"
|
||
class="preview-button preview-button--ghost"
|
||
:disabled="exporting"
|
||
title="生成带水印与审计编号的副本,对外提供时使用"
|
||
@click="emit('download-readonly-copy')"
|
||
>
|
||
只读副本
|
||
</button>
|
||
<button type="button" class="preview-button" :disabled="exporting" @click="emit('download')">
|
||
{{ exporting ? '生成中…' : '下载 PDF 原件' }}
|
||
</button>
|
||
</template>
|
||
</DocumentPreviewDialog>
|
||
</template>
|