feat(签署): 保存并还原患者勾选结果
签署完成时将患者勾选的条目固化到任务记录,重新打开已签署文书时还原勾选状态,重新发起签署则清空历史勾选。
This commit is contained in:
@@ -21,6 +21,8 @@ export interface SigningDocumentData {
|
||||
visitDate: string
|
||||
signedAt?: string
|
||||
signatureDataUrl?: string
|
||||
/** 已勾选的条目名:签署完成后重新打开文书时用来还原勾选状态 */
|
||||
selectedItems?: string[]
|
||||
}
|
||||
|
||||
const SIGNATURE_PLACEHOLDER = '{患者签名}'
|
||||
@@ -105,7 +107,7 @@ function fillPatientPlaceholders(root: Element, data: SigningDocumentData) {
|
||||
})
|
||||
}
|
||||
|
||||
function convertCheckboxes(root: Element, interactive: boolean) {
|
||||
function convertCheckboxes(root: Element, interactive: boolean, selected: Set<string>) {
|
||||
root.querySelectorAll('table').forEach((table) => {
|
||||
// 不能只认 <thead>:WangEditor 的表格节点是 <table><tbody><tr>,它导出时不会生成
|
||||
// thead,粘贴带 thead 的表格时其 preParseHtml 也把 thead 拆掉;.docx 经 mammoth
|
||||
@@ -148,6 +150,13 @@ function convertCheckboxes(root: Element, interactive: boolean) {
|
||||
checkbox.setAttribute('data-sign-item', itemName)
|
||||
checkbox.disabled = !interactive
|
||||
|
||||
// 必须写成 attribute:innerHTML 只序列化 HTML 属性,只设 .checked 这个
|
||||
// property 会在生成 HTML 时被丢掉,渲染回来就成了未勾选
|
||||
if (selected.has(itemName)) {
|
||||
checkbox.checked = true
|
||||
checkbox.setAttribute('checked', '')
|
||||
}
|
||||
|
||||
checkCell.textContent = ''
|
||||
checkCell.appendChild(checkbox)
|
||||
})
|
||||
@@ -180,6 +189,7 @@ function replaceOptionMarkers(
|
||||
type: 'radio' | 'checkbox',
|
||||
groupName: string,
|
||||
interactive: boolean,
|
||||
selected: Set<string>,
|
||||
) {
|
||||
const parts = (textNode.textContent ?? '').split(OPTION_SPLIT_PATTERN)
|
||||
const fragment = document.createDocumentFragment()
|
||||
@@ -206,6 +216,12 @@ function replaceOptionMarkers(
|
||||
input.disabled = !interactive
|
||||
input.setAttribute('data-sign-item', label)
|
||||
|
||||
// 同表格勾选:只设 property 不会出现在生成的 HTML 里,必须落成属性
|
||||
if (label !== '' && selected.has(label)) {
|
||||
input.checked = true
|
||||
input.setAttribute('checked', '')
|
||||
}
|
||||
|
||||
if (type === 'radio') {
|
||||
input.name = groupName
|
||||
input.value = label
|
||||
@@ -234,7 +250,7 @@ function replaceOptionMarkers(
|
||||
* 同一段/同一单元格里出现两个及以上方框时按「二选一」处理成互斥单选;
|
||||
* 只有一个方框则保持多选语义,避免把「□高血压」这类单项确认误判成互斥组。
|
||||
*/
|
||||
function convertInlineOptions(root: Element, interactive: boolean) {
|
||||
function convertInlineOptions(root: Element, interactive: boolean, selected: Set<string>) {
|
||||
const groups = new Map<Element, Text[]>()
|
||||
|
||||
collectOptionTextNodes(root).forEach((textNode) => {
|
||||
@@ -261,7 +277,9 @@ function convertInlineOptions(root: Element, interactive: boolean) {
|
||||
const type = markerCount > 1 ? 'radio' : 'checkbox'
|
||||
const groupName = `sign-option-${groupSeq}`
|
||||
|
||||
textNodes.forEach((textNode) => replaceOptionMarkers(textNode, type, groupName, interactive))
|
||||
textNodes.forEach((textNode) =>
|
||||
replaceOptionMarkers(textNode, type, groupName, interactive, selected),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -297,8 +315,11 @@ export function buildSigningDocumentHtml(
|
||||
replaceTextPlaceholder(root, SIGNATURE_PLACEHOLDER, '(待患者签署)')
|
||||
}
|
||||
|
||||
convertCheckboxes(root, interactive)
|
||||
convertInlineOptions(root, interactive)
|
||||
// 已签署的文书再次打开时,把上次记录的勾选状态还原出来
|
||||
const selected = new Set(data.selectedItems ?? [])
|
||||
|
||||
convertCheckboxes(root, interactive, selected)
|
||||
convertInlineOptions(root, interactive, selected)
|
||||
|
||||
return root.innerHTML
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user