136 lines
3.8 KiB
TypeScript
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
|
|
}
|
|
}
|