feat(文档库): 打通模板正文真实模式并新增渲染验证
模板列表接口不返回正文,展示、编辑与发起签署前需再取版本详情获取 contentHtml, 为此新增 getTemplateContent、createTemplateWithContent、updateTemplateContent 与 deleteTemplate(归档),并在签署端按 contentSha256 缓存正文快照。 同时新增 scripts/login.cjs 与 scripts/verify-pages.cjs,通过真实登录与 CDP 渲染截图、断言关键内容并收集运行时错误,并补充 .gitignore、eslint 忽略与文档说明。
This commit is contained in:
@@ -1,46 +1,113 @@
|
||||
/**
|
||||
* 文档库的演示数据与展示文案。
|
||||
*
|
||||
* 状态标签放在这里而不是随演示数据一起删掉:标签是纯展示映射,
|
||||
* 接真实接口后照样要用,不能和"演示数据"捆在一起。
|
||||
*
|
||||
* 演示文书库的种子与读写逻辑在 utils/mock-document-library:
|
||||
* 文档库页面和签署工作台必须读同一份数据,否则会出现「文档库里维护的模板,签署端选不到」,
|
||||
* 或者签署端混着一批文档库里看不到、也无法维护的模板。
|
||||
*/
|
||||
import type { DocumentRecord } from '@/api/management/types'
|
||||
import type { LocalDocument, LocalDepartment } from '@/utils/mock-document-library'
|
||||
import { readDocumentLibrary, writeDocumentLibrary } from '@/utils/mock-document-library'
|
||||
import type { SigningDocumentData } from '@/utils/signing-document'
|
||||
|
||||
import type { DocumentDepartment, DocumentStatus } from './types'
|
||||
|
||||
const documentStatusLabels: Record<DocumentStatus, string> = {
|
||||
enabled: '启用中',
|
||||
draft: '草稿',
|
||||
archived: '归档',
|
||||
review: '需复审',
|
||||
/**
|
||||
* 演示文库与页面模型之间的归一。
|
||||
*
|
||||
* utils/mock-document-library 刻意只声明自己用到的字段(不反向依赖 views 的类型),
|
||||
* 它返回的文书缺了页面模型要求的 category / updatedBy / updatedAt,code 也可能为空。
|
||||
* 两种口径不一致会在 loadLibrary / saveDocumentLibrary 处直接报类型错误,
|
||||
* 因此在这一层做一次显式补齐——而不是让 utils 反过来依赖 views,
|
||||
* 也不是把页面的必填字段放宽成可选(放宽会掩盖真实接口返回缺字段的问题)。
|
||||
*
|
||||
* 补齐用的值都标注了是演示数据的缺省值,不冒充真实字段:
|
||||
* updatedAt 留空串,页面会显示成"—",不会假装有一份真实的更新时间。
|
||||
*/
|
||||
function toDocumentRecord(document: LocalDocument, categoryName: string): DocumentRecord {
|
||||
return {
|
||||
...document,
|
||||
code: document.code ?? '',
|
||||
category: categoryName,
|
||||
updatedBy: '演示数据',
|
||||
updatedAt: document.updatedAt ?? '',
|
||||
}
|
||||
}
|
||||
|
||||
export const documentStatusOptions = Object.entries(documentStatusLabels).map(([key, label]) => ({
|
||||
key: key as DocumentStatus,
|
||||
label,
|
||||
}))
|
||||
export function toDocumentDepartment(department: LocalDepartment): DocumentDepartment {
|
||||
return {
|
||||
...department,
|
||||
categories: department.categories.map((category) => ({
|
||||
...category,
|
||||
documents: category.documents.map((document) => toDocumentRecord(document, category.name)),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
export { documentStatusLabels }
|
||||
|
||||
// 演示文书库的种子与读取逻辑都在 utils/mock-document-library:
|
||||
// 文档库页面和签署工作台必须读同一份数据,否则会出现「文档库里维护的模板,签署端选不到」,
|
||||
// 或者签署端混着一批文档库里看不到、也无法维护的模板。
|
||||
/** 读取演示文书库:优先用本地保存的,没有则用种子(调用方负责再克隆一份使用) */
|
||||
export function loadDocumentLibrary(): DocumentDepartment[] {
|
||||
return readDocumentLibrary()
|
||||
}
|
||||
|
||||
/** 保存演示文书库,刷新后仍可继续编辑、预览与发起签署 */
|
||||
export function saveDocumentLibrary(library: DocumentDepartment[]): void {
|
||||
writeDocumentLibrary(library)
|
||||
return readDocumentLibrary().map(toDocumentDepartment)
|
||||
}
|
||||
|
||||
/**
|
||||
* 签署预览使用的示例患者快照(脱敏演示数据)。
|
||||
* 创建文书时还没有真实签署任务,用固定示例值让科室看到占位符被填充后的版式;
|
||||
* 真实签署仍以任务创建时的患者/就诊快照为准。
|
||||
* 保存演示文书库。
|
||||
* 落本地时要把 category 摘掉(LocalDocument 没有 category 字段,
|
||||
* 分类信息在 categories 这一层的 name 上),否则多存一个字段会在下次读取时对不上。
|
||||
* updatedBy 同理:它是页面模型为「必须有人维护」补的展示字段,不是演示文库的数据。
|
||||
*/
|
||||
export const signingPreviewPatient: SigningDocumentData = {
|
||||
patientName: '李某某',
|
||||
sex: '男',
|
||||
age: 46,
|
||||
visitNo: 'V20260914001',
|
||||
visitDate: '2026-09-14',
|
||||
phone: '138****5678',
|
||||
signedAt: '',
|
||||
export function saveDocumentLibrary(library: DocumentDepartment[]): void {
|
||||
writeDocumentLibrary(
|
||||
library.map((department) => ({
|
||||
...department,
|
||||
categories: department.categories.map((category) => ({
|
||||
name: category.name,
|
||||
documents: category.documents.map(toLocalDocument),
|
||||
})),
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面模型的文书 → 演示文库存储结构。
|
||||
*
|
||||
* 逐字段列出而不是解构剔除:解构剔除(`const { category, ...rest }`)会因为
|
||||
* 被剔除的变量未使用而触发 lint,且多加一个页面专用字段时容易忘掉同步。
|
||||
* 这里明确列出演示文库认识哪些字段,多出来的页面字段(category / updatedBy)自然被丢掉。
|
||||
*/
|
||||
function toLocalDocument(document: DocumentRecord): LocalDocument {
|
||||
return {
|
||||
id: document.id,
|
||||
name: document.name,
|
||||
code: document.code,
|
||||
version: document.version,
|
||||
status: document.status,
|
||||
backendStatus: document.backendStatus,
|
||||
description: document.description ?? '',
|
||||
versionId: document.versionId,
|
||||
departmentId: document.departmentId,
|
||||
departmentName: document.departmentName,
|
||||
campusId: document.campusId,
|
||||
campusName: document.campusName,
|
||||
updatedAt: document.updatedAt,
|
||||
contentHtml: document.contentHtml,
|
||||
contentSha256: document.contentSha256,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态标签。键集合与后端模板状态枚举一一对应
|
||||
* (见 api/management/types.ts 的 BackendTemplateStatus 与 documents.ts 的 normalizeDocumentStatus),
|
||||
* 不再有后端枚举里不存在的 enabled。
|
||||
*/
|
||||
export const documentStatusLabels: Record<DocumentStatus, string> = {
|
||||
draft: '草稿',
|
||||
review: '需复审',
|
||||
published: '已发布',
|
||||
archived: '已归档',
|
||||
}
|
||||
|
||||
export const documentStatusOptions = (
|
||||
Object.entries(documentStatusLabels) as [DocumentStatus, string][]
|
||||
).map(([key, label]) => ({ key, label }))
|
||||
|
||||
Reference in New Issue
Block a user