feat(sign): 补齐医护端与患者端签署流程
This commit is contained in:
@@ -48,6 +48,12 @@ export const FIELD_REQUIRED_ATTR = 'data-required'
|
||||
export const FIELD_OPTIONS_ATTR = 'data-options'
|
||||
export const FIELD_MULTI_ATTR = 'data-multi'
|
||||
export const FIELD_RISK_ATTR = 'data-risk'
|
||||
export const FIELD_PDF_PAGE_ATTR = 'data-pdf-page'
|
||||
export const FIELD_PDF_X_ATTR = 'data-pdf-x'
|
||||
export const FIELD_PDF_Y_ATTR = 'data-pdf-y'
|
||||
export const FIELD_PDF_WIDTH_ATTR = 'data-pdf-width'
|
||||
export const FIELD_PDF_HEIGHT_ATTR = 'data-pdf-height'
|
||||
export const FIELD_PDF_COORDINATE_SYSTEM_ATTR = 'data-pdf-coordinate-system'
|
||||
|
||||
/** 结构化占位符的选择器:渲染端与解析端必须用同一个。 */
|
||||
export const FIELD_ELEMENT_SELECTOR = `${FIELD_ELEMENT_TAG}[${FIELD_ID_ATTR}]`
|
||||
@@ -81,6 +87,15 @@ export function createFieldElement(doc: Document, field: SigningFieldDef): HTMLE
|
||||
element.setAttribute(FIELD_RISK_ATTR, field.risk)
|
||||
}
|
||||
|
||||
if (field.pdfPosition) {
|
||||
element.setAttribute(FIELD_PDF_PAGE_ATTR, String(field.pdfPosition.page))
|
||||
element.setAttribute(FIELD_PDF_X_ATTR, String(field.pdfPosition.x))
|
||||
element.setAttribute(FIELD_PDF_Y_ATTR, String(field.pdfPosition.y))
|
||||
element.setAttribute(FIELD_PDF_WIDTH_ATTR, String(field.pdfPosition.width))
|
||||
element.setAttribute(FIELD_PDF_HEIGHT_ATTR, String(field.pdfPosition.height))
|
||||
element.setAttribute(FIELD_PDF_COORDINATE_SYSTEM_ATTR, field.pdfPosition.coordinateSystem)
|
||||
}
|
||||
|
||||
element.textContent = field.label
|
||||
|
||||
return element
|
||||
@@ -109,10 +124,35 @@ export function readFieldFromElement(element: Element): SigningFieldDef | null {
|
||||
// 没有 data-field 时用标签反查目录,签名位这类字段至少还能还原成正确的控件
|
||||
const resolved = id ? null : resolveFieldByLabel(label)
|
||||
|
||||
const pdfPositionValues = [
|
||||
element.getAttribute(FIELD_PDF_PAGE_ATTR),
|
||||
element.getAttribute(FIELD_PDF_X_ATTR),
|
||||
element.getAttribute(FIELD_PDF_Y_ATTR),
|
||||
element.getAttribute(FIELD_PDF_WIDTH_ATTR),
|
||||
element.getAttribute(FIELD_PDF_HEIGHT_ATTR),
|
||||
]
|
||||
const pdfNumbers = pdfPositionValues.map((value) => Number(value))
|
||||
const hasPdfPosition = pdfPositionValues.every((value) => value !== null && value.trim() !== '')
|
||||
const pdfCoordinateSystem = element.getAttribute(FIELD_PDF_COORDINATE_SYSTEM_ATTR)
|
||||
const pdfPosition =
|
||||
hasPdfPosition && pdfNumbers.every(Number.isFinite)
|
||||
? {
|
||||
page: pdfNumbers[0],
|
||||
x: pdfNumbers[1],
|
||||
y: pdfNumbers[2],
|
||||
width: pdfNumbers[3],
|
||||
height: pdfNumbers[4],
|
||||
coordinateSystem:
|
||||
pdfCoordinateSystem === 'PDF_BOTTOM_LEFT'
|
||||
? ('PDF_BOTTOM_LEFT' as const)
|
||||
: ('TOP_LEFT' as const),
|
||||
}
|
||||
: undefined
|
||||
|
||||
return {
|
||||
id: id || (resolved as SigningFieldDef).id,
|
||||
label: label || id,
|
||||
kind: ((element.getAttribute(FIELD_KIND_ATTR) ?? resolved?.kind ?? 'text') as SigningFieldKind),
|
||||
kind: (element.getAttribute(FIELD_KIND_ATTR) ?? resolved?.kind ?? 'text') as SigningFieldKind,
|
||||
required:
|
||||
element.getAttribute(FIELD_REQUIRED_ATTR) === 'true' ||
|
||||
(!element.hasAttribute(FIELD_REQUIRED_ATTR) && resolved?.required === true),
|
||||
@@ -122,6 +162,7 @@ export function readFieldFromElement(element: Element): SigningFieldDef | null {
|
||||
.filter(Boolean),
|
||||
multi: readMultiAttribute(element, resolved),
|
||||
risk: element.getAttribute(FIELD_RISK_ATTR)?.trim() || resolved?.risk || undefined,
|
||||
pdfPosition,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,11 +416,7 @@ export interface ScannedFieldToken {
|
||||
* 只对自定义文本项有意义(调用方保证),目录里的字段同名共用一份取值是刻意的。
|
||||
* claimed 是有限集合、next 严格递增,所以循环一定收敛。
|
||||
*/
|
||||
function nextFreeCustomSequence(
|
||||
label: string,
|
||||
sequence: number,
|
||||
claimed: Set<string>,
|
||||
): number {
|
||||
function nextFreeCustomSequence(label: string, sequence: number, claimed: Set<string>): number {
|
||||
let next = sequence
|
||||
|
||||
while (claimed.has(createCustomField(label, 'text', [], next).id)) {
|
||||
|
||||
Reference in New Issue
Block a user