feat(签署): 支持文书填写项与签名回显

This commit is contained in:
yelan
2026-09-16 15:54:40 +08:00
parent b15df82be2
commit 5361839cf2
10 changed files with 1178 additions and 164 deletions
@@ -19,6 +19,7 @@ import {
voidSigningTask,
} from '@/api/workbench/signing'
import type {
SigningAnswers,
SigningDateRange,
SigningMethod,
SigningArtifact,
@@ -32,6 +33,7 @@ import type {
} from '@/api/workbench/types'
import NewSigningTaskDialog from '@/components/signing/NewSigningTaskDialog.vue'
import { useAppStore } from '@/stores/app'
import type { SigningFieldProgress } from '@/utils/signing-document'
import OnlineSigningDialog from './components/OnlineSigningDialog.vue'
import SignaturePadDialog from './components/SignaturePadDialog.vue'
@@ -82,6 +84,10 @@ const selectedTaskId = ref<string | null>(null)
const selectedTask = ref<SigningTaskRecord | null>(null)
/** 当前任务里患者已勾选的条目,签署完成时随签名一起固化到任务上 */
const signingSelection = ref<string[]>([])
/** 当前任务文书的填写项取值(含签名图),签署完成时随签名一起固化 */
const signingAnswers = ref<SigningAnswers>({})
/** 文书填写项完成情况:签署前用它做必填校验、提示异常项 */
const signingProgress = ref<SigningFieldProgress | null>(null)
const taskEvents = ref<SigningTaskEvent[]>([])
const artifacts = ref<SigningArtifact[]>([])
const templates = ref<SigningTemplate[]>([])
@@ -215,9 +221,11 @@ async function loadOrganizationOptions() {
async function loadTaskDetail(id: string | null) {
const requestId = ++detailRequestId
// 换任务时先清空勾选,避免把上一个任务的勾选带到新任务上;
// 文书组件挂载后会用任务自身的勾选重新上报
// 换任务时先清空勾选与填写项,避免把上一个任务的取值带到新任务上;
// 文书组件挂载后会用任务自身固化的取值重新上报
signingSelection.value = []
signingAnswers.value = {}
signingProgress.value = null
if (!id) {
selectedTask.value = null
@@ -254,6 +262,7 @@ async function loadTaskDetail(id: string | null) {
}
selectedTask.value = detailResult.value
signingAnswers.value = { ...(detailResult.value.fieldAnswers ?? {}) }
if (eventsResult.status === 'fulfilled') {
taskEvents.value = eventsResult.value
@@ -348,6 +357,26 @@ function handleSelectionChange(items: string[]) {
signingSelection.value = items
}
function handleFieldChange(answers: SigningAnswers, progress: SigningFieldProgress) {
signingAnswers.value = answers
signingProgress.value = progress
}
/**
* 采集签名前的填写项校验。
* 必填项没填完就采集签名,等于签了一份内容不完整的文书,因此在入口处挡住。
*/
function assertFieldsReady() {
const missing = signingProgress.value?.missingRequired ?? []
if (missing.length) {
ElMessage.warning(`请先完成必填项:${missing.join('、')}`)
return false
}
return true
}
function handlePageChange(nextPage: number) {
const pageCount = Math.max(Math.ceil(total.value / pageSize.value), 1)
@@ -383,6 +412,10 @@ async function handleTaskAction(action: SigningTaskAction) {
return
}
if (!assertFieldsReady()) {
return
}
signatureDialogVisible.value = true
return
}
@@ -409,6 +442,10 @@ async function handleTaskAction(action: SigningTaskAction) {
return
}
if (!assertFieldsReady()) {
return
}
onlineDialogVisible.value = true
return
}
@@ -514,7 +551,12 @@ async function confirmPadSignature(signatureDataUrl: string) {
try {
await refreshTask(
await completeSigningTask(task.id, signatureDataUrl, signingSelection.value),
await completeSigningTask(
task.id,
signatureDataUrl,
signingSelection.value,
signingAnswers.value,
),
'手写签署已完成',
)
signatureDialogVisible.value = false
@@ -532,7 +574,12 @@ async function completeOnlineSignature(signatureDataUrl: string) {
try {
await refreshTask(
await completeSigningTask(task.id, signatureDataUrl, signingSelection.value),
await completeSigningTask(
task.id,
signatureDataUrl,
signingSelection.value,
signingAnswers.value,
),
'线上签署已完成',
)
onlineDialogVisible.value = false
@@ -655,6 +702,7 @@ onMounted(() => {
@action="handleTaskAction"
@download-artifact="downloadArtifact"
@selection-change="handleSelectionChange"
@field-change="handleFieldChange"
/>
</div>