feat(签署文书): 统一签署态文书样式并精简演示种子为单份麻精同意书

This commit is contained in:
yelan
2026-09-24 17:08:12 +08:00
parent 9a6ac93e21
commit 5ea79178cb
30 changed files with 3787 additions and 2878 deletions
+81
View File
@@ -765,6 +765,87 @@ export function upgradeFieldTokensToStructured(contentHtml: string): string {
)
}
/**
* 把导入的 Word 表格里的「勾选」列转成结构化勾选占位符(原型 docCheckboxize 的口径)。
*
* 为什么在**导入时**转,而不是留到签署渲染再转:
* ① 转完它就是一个正常的填写项,科室可以点开改名称、类型、选项,
* 与手工插入的占位符没有任何区别;
* ② 留在渲染期转的话,这份文书在编辑器里始终是一张"看不出哪里要勾"的空表格,
* 科室没法在保存前核对。
*
* 取值列的选择顺序照原型:勾选列右边第二列 → 左边第一列 → 右边第一列 → 「选择项目」。
* 原型会给转出来的勾选项写 data-risk="是",但那个值在渲染侧从未被读取
* (勾选的取值是布尔,命中判据比不出来),属于原型里没落地的残留,这里不抄。
*
* 字段键必须逐格现取:同一张表里两行都叫「已阅读」时,共用 `custom:已阅读`
* 会让两处勾选互相覆盖,所以用 allocateCustomFieldId 的同款规则按占用情况往后编号。
*/
export function convertCheckboxColumnsToFields(contentHtml: string): string {
if (!contentHtml || !contentHtml.includes('<table')) {
return contentHtml
}
const parsed = new DOMParser().parseFromString(
`<div id="${SCAN_ROOT_ID}">${contentHtml}</div>`,
'text/html',
)
const root = parsed.getElementById(SCAN_ROOT_ID)
if (!root) {
return contentHtml
}
const claimed = collectStructuredIdsFrom(root)
let changed = false
root.querySelectorAll('table').forEach((table) => {
const rows = Array.from(table.querySelectorAll('tr'))
if (rows.length < 2) {
return
}
const headerRow = rows[0] as HTMLTableRowElement
const headerCells = Array.from(headerRow.cells)
const checkIndex = headerCells.findIndex((cell) => cell.textContent?.trim() === '勾选')
if (checkIndex === -1) {
return
}
rows.slice(1).forEach((row) => {
const cells = Array.from((row as HTMLTableRowElement).cells)
const target = cells[checkIndex]
// 只转空单元格:已经有内容的说明科室自己填过,别覆盖
if (!target || (target.textContent ?? '').trim()) {
return
}
const label =
(cells[checkIndex + 2]?.textContent ?? '').trim() ||
(cells[checkIndex - 1]?.textContent ?? '').trim() ||
(cells[checkIndex + 1]?.textContent ?? '').trim() ||
'选择项目'
let sequence = 1
while (claimed.has(createCustomField(label, 'checkbox', [], sequence).id)) {
sequence += 1
}
const field = createCustomField(label, 'checkbox', [], sequence)
claimed.add(field.id)
target.replaceChildren(createFieldElement(parsed, { ...field, required: true }))
changed = true
})
})
return changed ? root.innerHTML : contentHtml
}
/**
* 给新插入的自定义文本项分配一个在本文书里唯一的字段键。
*