Files
xh-medical-sign-web/patient-h5/src/composables/useSignFlow.ts
T

136 lines
3.8 KiB
TypeScript

import { reactive } from 'vue'
import { consumeSigningToken, uploadSigningSignature } from '@/api'
import type { SignatureUploadResponse } from '@/api/types'
import type { SignFlowState } from '@/types/signing'
const initialState: SignFlowState = {
mode: 'mock',
status: 'idle',
patientName: '张*',
visitNo: 'MZ20260827018',
documentTitle: '儿科急诊特殊检查知情同意书',
taskNo: 'CT-20260827-001',
taskId: '',
deliveryId: '',
uploadToken: '',
channel: '',
consentAccepted: false,
signerName: '',
relation: '',
signatureCaptured: false,
submittedAt: '',
backendStatus: '',
pipelineId: '',
uploadResult: null,
errorMessage: '',
}
export const signingState = reactive<SignFlowState>({ ...initialState })
export function resetSignFlow() {
Object.assign(signingState, {
...initialState,
uploadResult: null,
})
}
function getErrorMessage(error: unknown) {
return error instanceof Error ? error.message : '签署链接验证失败,请联系现场医务人员。'
}
export async function initializeSignFlow(token?: string) {
resetSignFlow()
const candidate = token?.trim()
const shouldUseRealFlow = Boolean(candidate) || import.meta.env.VITE_USE_MOCK === 'false'
signingState.mode = shouldUseRealFlow ? 'real' : 'mock'
if (!shouldUseRealFlow) {
signingState.status = 'ready'
return true
}
if (!candidate) {
signingState.status = 'blocked'
signingState.errorMessage = '请使用短信或二维码中的有效签署链接进入。'
return false
}
signingState.status = 'loading'
try {
const session = await consumeSigningToken({ token: candidate, channel: 'SMS' })
signingState.taskId = session.taskId
signingState.taskNo = session.taskId
signingState.deliveryId = session.deliveryId
signingState.uploadToken = session.uploadToken
signingState.channel = session.channel
signingState.documentTitle = '待签署知情同意文书'
signingState.patientName = '患者信息待确认'
signingState.visitNo = ''
signingState.status = 'ready'
return true
} catch (error) {
signingState.status = 'error'
signingState.errorMessage = getErrorMessage(error)
return false
}
}
export async function submitRealSignature(input: {
file: Blob
signerName: string
relation: NonNullable<SignFlowState['relation']>
consentAccepted: boolean
}): Promise<SignatureUploadResponse> {
if (signingState.mode !== 'real') {
throw new Error('当前是演示签署流程')
}
if (
!signingState.taskId ||
!signingState.deliveryId ||
!signingState.uploadToken ||
!input.consentAccepted
) {
throw new Error('签署凭证或知情确认状态无效,请重新打开签署链接。')
}
signingState.status = 'submitting'
signingState.errorMessage = ''
try {
const result = await uploadSigningSignature({
taskId: signingState.taskId,
deliveryId: signingState.deliveryId,
uploadToken: signingState.uploadToken,
file: input.file,
metadata: JSON.stringify({
signerName: input.signerName,
relation: input.relation,
consentAccepted: input.consentAccepted,
signedAt: new Date().toISOString(),
}),
})
signingState.signerName = input.signerName
signingState.relation = input.relation
signingState.consentAccepted = input.consentAccepted
signingState.signatureCaptured = true
signingState.submittedAt = new Date().toLocaleString('zh-CN')
signingState.backendStatus = result.status
signingState.pipelineId = result.pipelineId
signingState.uploadResult = result
signingState.uploadToken = ''
signingState.status = 'submitted'
return result
} catch (error) {
signingState.status = 'ready'
signingState.errorMessage = getErrorMessage(error)
throw error
}
}