feat(signing): 支持点击文中签名位就地采集签名
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
import { getCampuses, getDepartments } from '@/api/management/organization'
|
||||
@@ -38,7 +38,7 @@ import type {
|
||||
import NewSigningTaskDialog from '@/components/signing/NewSigningTaskDialog.vue'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import { useLoginStore } from '@/stores/login'
|
||||
import type { SigningFieldProgress } from '@/utils/signing-document'
|
||||
import type { SigningFieldProgress, SigningSignatureRequest } from '@/utils/signing-document'
|
||||
import { downloadSigningPdf } from '@/utils/signing-pdf'
|
||||
|
||||
import OnlineSigningDialog from './components/OnlineSigningDialog.vue'
|
||||
@@ -95,6 +95,15 @@ const signingSelection = ref<string[]>([])
|
||||
const signingAnswers = ref<SigningAnswers>({})
|
||||
/** 文书填写项完成情况:签署前用它做必填校验、提示异常项 */
|
||||
const signingProgress = ref<SigningFieldProgress | null>(null)
|
||||
/**
|
||||
* 在文书里点击签名位采集到的签名图(key 是字段键,如 doctor)。
|
||||
* 与 signingAnswers 分开:signingAnswers 每次输入都会变,把它当渲染输入会让
|
||||
* 整篇文书重渲染、光标丢失;这份只在真的采到签名时变化。
|
||||
*/
|
||||
const fieldSignatureInjections = ref<SigningAnswers>({})
|
||||
/** 当前正在采集的签名位,null 表示弹窗不是由「点击文中签名位」打开的 */
|
||||
const pendingSignatureField = ref<SigningSignatureRequest | null>(null)
|
||||
const fieldSignatureDialogVisible = ref(false)
|
||||
const taskEvents = ref<SigningTaskEvent[]>([])
|
||||
const artifacts = ref<SigningArtifact[]>([])
|
||||
const templates = ref<SigningTemplate[]>([])
|
||||
@@ -253,6 +262,9 @@ async function loadTaskDetail(id: string | null) {
|
||||
signingSelection.value = []
|
||||
signingAnswers.value = {}
|
||||
signingProgress.value = null
|
||||
fieldSignatureInjections.value = {}
|
||||
pendingSignatureField.value = null
|
||||
fieldSignatureDialogVisible.value = false
|
||||
|
||||
if (!id) {
|
||||
selectedTask.value = null
|
||||
@@ -408,10 +420,14 @@ function handleFieldChange(answers: SigningAnswers, progress: SigningFieldProgre
|
||||
}
|
||||
|
||||
/**
|
||||
* 采集签名前的填写项校验。
|
||||
* 必填项没填完就采集签名,等于签了一份内容不完整的文书,因此在入口处挡住。
|
||||
* 采集主签名前的检查。
|
||||
*
|
||||
* ① 必填项没填完 → 直接挡住:签一份内容不完整的文书没有意义;
|
||||
* ② 文书里还有没采集的签名位 → 让操作人员确认后再继续。
|
||||
* 这一条不能硬挡:医师确实可能签在纸质件上,替业务做决定是越界;
|
||||
* 但也不能不提醒,否则文书会带着空签名位被固化。
|
||||
*/
|
||||
function assertFieldsReady() {
|
||||
async function assertSigningReady() {
|
||||
const missing = signingProgress.value?.missingRequired ?? []
|
||||
|
||||
if (missing.length) {
|
||||
@@ -419,7 +435,59 @@ function assertFieldsReady() {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
const pending = signingProgress.value?.pendingSignatures ?? []
|
||||
|
||||
if (!pending.length) {
|
||||
return true
|
||||
}
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`文书中还有签名位未采集:${pending.join('、')}。可直接点击文中签名位完成,也可以继续采集主签名。`,
|
||||
'还有签名位待采集',
|
||||
{ confirmButtonText: '继续签署', cancelButtonText: '返回采集', type: 'warning' },
|
||||
)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/** 点击文中签名位:先记下采的是哪一个,再由弹窗把签名图回灌到该位置 */
|
||||
function handleSignatureRequest(request: SigningSignatureRequest) {
|
||||
if (!selectedTask.value) {
|
||||
return
|
||||
}
|
||||
|
||||
pendingSignatureField.value = request
|
||||
fieldSignatureDialogVisible.value = true
|
||||
}
|
||||
|
||||
function closeFieldSignatureDialog() {
|
||||
fieldSignatureDialogVisible.value = false
|
||||
pendingSignatureField.value = null
|
||||
}
|
||||
|
||||
/**
|
||||
* 单个签名位采集完成。
|
||||
*
|
||||
* 这里不调 completeSigningTask:医师签名只是文书上的一个填写项,
|
||||
* 任务级的「签署完成」仍要由主签名位(患者签名)触发,
|
||||
* 否则点一下医师签名就把整个任务标记成已签署了。
|
||||
*/
|
||||
function confirmFieldSignature(signatureDataUrl: string) {
|
||||
const request = pendingSignatureField.value
|
||||
|
||||
if (!request) {
|
||||
return
|
||||
}
|
||||
|
||||
fieldSignatureInjections.value = {
|
||||
...fieldSignatureInjections.value,
|
||||
[request.fieldId]: signatureDataUrl,
|
||||
}
|
||||
closeFieldSignatureDialog()
|
||||
ElMessage.success(`「${request.label}」签名已采集,将随本次签署一并固化`)
|
||||
}
|
||||
|
||||
function handlePageChange(nextPage: number) {
|
||||
@@ -471,7 +539,7 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!assertFieldsReady()) {
|
||||
if (!(await assertSigningReady())) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -501,7 +569,7 @@ async function handleTaskAction(action: SigningTaskAction) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!assertFieldsReady()) {
|
||||
if (!(await assertSigningReady())) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -803,10 +871,12 @@ onMounted(() => {
|
||||
:can-view-audit="canViewEvents"
|
||||
:can-view-artifacts="canViewArtifacts"
|
||||
:can-download-artifact="canDownloadArtifacts"
|
||||
:signature-injections="fieldSignatureInjections"
|
||||
@action="handleTaskAction"
|
||||
@download-artifact="downloadArtifact"
|
||||
@selection-change="handleSelectionChange"
|
||||
@field-change="handleFieldChange"
|
||||
@signature-request="handleSignatureRequest"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -821,6 +891,16 @@ onMounted(() => {
|
||||
@close="signatureDialogVisible = false"
|
||||
@confirm="confirmPadSignature"
|
||||
/>
|
||||
<!-- 文书里单个签名位(医师签名等)的采集入口:签完只回填该位置,不结束任务 -->
|
||||
<SignaturePadDialog
|
||||
:visible="fieldSignatureDialogVisible"
|
||||
:task="selectedTask"
|
||||
:title="`采集「${pendingSignatureField?.label ?? '签名'}」`"
|
||||
:hint="`请让签署人在下框内签名,签名图将回显到文书中的「${pendingSignatureField?.label ?? '签名'}」位置;本次采集不会结束签署任务:`"
|
||||
confirm-label="确认采集"
|
||||
@close="closeFieldSignatureDialog"
|
||||
@confirm="confirmFieldSignature"
|
||||
/>
|
||||
<OnlineSigningDialog
|
||||
:visible="onlineDialogVisible"
|
||||
:task="selectedTask"
|
||||
|
||||
Reference in New Issue
Block a user