From 5b2cc33038f234b2cd47f4946b2aff47eb545488 Mon Sep 17 00:00:00 2001 From: yelan Date: Tue, 1 Sep 2026 14:50:07 +0800 Subject: [PATCH] fix(signing): align workbench with MEDISIGN contract --- clinical-web/src/api/workbench/artifacts.ts | 12 ++-- clinical-web/src/api/workbench/deliveries.ts | 14 +++-- clinical-web/src/api/workbench/signing.ts | 26 ++++++-- clinical-web/src/api/workbench/types.ts | 27 ++++---- .../src/views/management/reports/index.vue | 2 +- .../components/SigningArtifactList.vue | 2 +- .../signing/components/SigningTaskDetail.vue | 4 +- .../signing/components/SigningTaskList.vue | 62 ++++++++++++++++++- .../src/views/workbench/signing/index.vue | 51 +++++++++++---- patient-h5/src/api/index.ts | 6 +- 10 files changed, 155 insertions(+), 51 deletions(-) diff --git a/clinical-web/src/api/workbench/artifacts.ts b/clinical-web/src/api/workbench/artifacts.ts index 4ae822a..8028ca3 100644 --- a/clinical-web/src/api/workbench/artifacts.ts +++ b/clinical-web/src/api/workbench/artifacts.ts @@ -46,21 +46,23 @@ function getCollectionRecords(collection: ArtifactCollection) { } function normalizeArtifact(dto: SignArtifactResponseDto): SigningArtifact { - const artifactType: SignArtifactType = dto.artifactType ?? dto.type ?? 'UNKNOWN' + const artifactType: SignArtifactType = dto.artifactType const label = artifactLabels[artifactType] ?? '签署文件' - const mimeType = dto.mimeType ?? dto.contentType ?? 'application/octet-stream' + const mimeType = dto.mimeType || 'application/octet-stream' const extension = mimeType === 'application/pdf' ? 'pdf' : mimeType === 'image/png' ? 'png' : 'bin' return { id: dto.id, taskId: dto.taskId, + pipelineId: dto.pipelineId, artifactType, label, - fileName: dto.fileName || `${label}.${extension}`, + fileName: `${label}.${extension}`, mimeType, - size: dto.size ?? dto.byteSize ?? dto.fileSize ?? 0, - sha256: dto.sha256 ?? dto.contentSha256 ?? '', + sizeBytes: dto.sizeBytes, + sha256: dto.sha256, + metadata: dto.metadata ?? {}, createdAt: formatDateTime(dto.createdAt), } } diff --git a/clinical-web/src/api/workbench/deliveries.ts b/clinical-web/src/api/workbench/deliveries.ts index 780fb11..56fdfdc 100644 --- a/clinical-web/src/api/workbench/deliveries.ts +++ b/clinical-web/src/api/workbench/deliveries.ts @@ -41,15 +41,12 @@ export function sendSigningSms( export function resendSigningSms( taskId: string, - expectedRowVersion?: number, idempotencyKey?: string, ): Promise { - const data = expectedRowVersion === undefined ? undefined : { expectedRowVersion } - return request .post>( `/v1/sign-deliveries/${encodeURIComponent(taskId)}/sms/resend`, - data, + undefined, { headers: idempotencyHeaders(idempotencyKey) }, ) .then(unwrapNullableApiResponse) @@ -69,9 +66,14 @@ export function createPadSigningSession( .then(unwrapApiResponse) } -export function consumeSigningToken(payload: TokenConsumeRequest): Promise { +export function consumeSigningToken( + payload: TokenConsumeRequest, + idempotencyKey?: string, +): Promise { return request - .post>('/v1/sign-deliveries/token/consume', payload) + .post>('/v1/sign-deliveries/token/consume', payload, { + headers: idempotencyHeaders(idempotencyKey), + }) .then(unwrapApiResponse) } diff --git a/clinical-web/src/api/workbench/signing.ts b/clinical-web/src/api/workbench/signing.ts index 4d2cc7f..63c09b2 100644 --- a/clinical-web/src/api/workbench/signing.ts +++ b/clinical-web/src/api/workbench/signing.ts @@ -10,6 +10,7 @@ import type { AvailableTemplateVersionResponseDto, BackendSigningMethod, BackendSigningTaskStatus, + BackendVisitType, CreateSigningTaskInput, CreateSigningTaskRequest, PatientProfile, @@ -563,7 +564,6 @@ function toBackendTaskQuery(query: SigningTaskQuery, options: SigningApiOptions pending: 'WAITING_SIGN', signing: 'GENERATING', signed: 'SIGNED', - rejected: 'FAILED', expired: 'EXPIRED', void: 'VOIDED', failed: 'FAILED', @@ -579,6 +579,19 @@ function toBackendTaskQuery(query: SigningTaskQuery, options: SigningApiOptions params.signMethod = query.method === 'sms' ? 'SMS' : 'PAD' } + if (query.visitType && query.visitType !== 'all') { + const visitTypeMap: Partial> = { + 门诊: 'OUTPATIENT', + 住院: 'INPATIENT', + 体检: 'CHECKUP', + } + const visitType = visitTypeMap[query.visitType] + + if (visitType) { + params.visitType = visitType + } + } + if (query.documentId) { params.templateVersionId = findTemplate(options.templates, query.documentId)?.versionId ?? query.documentId @@ -604,8 +617,12 @@ function toBackendTaskQuery(query: SigningTaskQuery, options: SigningApiOptions params.createdTo = end.toISOString() } - if (query.campus && query.campus !== 'all' && options.campusId) { - params.campusId = options.campusId + if (query.campus && query.campus !== 'all') { + const campusId = options.campusIds?.[query.campus] ?? options.campusId + + if (campusId) { + params.campusId = campusId + } } if (query.department && options.departmentIds?.[query.department]) { @@ -1031,7 +1048,7 @@ export async function resendSigningSms( options: SigningTaskActionOptions = {}, ): Promise { if (!useMockData) { - await resendSigningSmsDelivery(id, options.expectedRowVersion) + await resendSigningSmsDelivery(id) return getSigningTaskDetail(id, options) } @@ -1107,7 +1124,6 @@ export function getSigningStatusLabel(status: SigningTaskStatus) { pending: '待签署', signing: '签署中', signed: '已签署', - rejected: '已拒签', expired: '已超时', void: '已作废', failed: '处理失败', diff --git a/clinical-web/src/api/workbench/types.ts b/clinical-web/src/api/workbench/types.ts index 6d004c3..a43b3eb 100644 --- a/clinical-web/src/api/workbench/types.ts +++ b/clinical-web/src/api/workbench/types.ts @@ -9,8 +9,7 @@ export interface WorkbenchOverviewQuery { rankingPeriod: HomeRankingPeriod } -export type SigningTaskStatus = - 'pending' | 'signing' | 'signed' | 'rejected' | 'expired' | 'void' | 'failed' +export type SigningTaskStatus = 'pending' | 'signing' | 'signed' | 'expired' | 'void' | 'failed' export type PatientSex = '男' | '女' | '未知' @@ -171,6 +170,7 @@ export interface SigningApiOptions { templates?: SigningTemplate[] campus?: WorkbenchCampus campusId?: string + campusIds?: Record campusNames?: Record departmentIds?: Record } @@ -438,32 +438,29 @@ export interface SignTaskEventResponseDto { export type SignArtifactType = 'ORIGINAL_PDF' | 'SIGNATURE_IMAGE' | 'SIGNED_PDF' | string -/** MEDISIGN 签署产物 DTO。部分文件元数据由不同版本的服务端返回,字段保持可选并在 API 边界归一化。 */ export interface SignArtifactResponseDto { id: string taskId: string - artifactType?: SignArtifactType - type?: SignArtifactType - fileName?: string | null - mimeType?: string | null - contentType?: string | null - size?: number | null - byteSize?: number | null - fileSize?: number | null - sha256?: string | null - contentSha256?: string | null - createdAt?: string | null + pipelineId: string + artifactType: SignArtifactType + sizeBytes: number + mimeType: string + sha256: string + metadata: Record + createdAt: string } export interface SigningArtifact { id: string taskId: string + pipelineId: string artifactType: SignArtifactType label: string fileName: string mimeType: string - size: number + sizeBytes: number sha256: string + metadata: Record createdAt: string } diff --git a/clinical-web/src/views/management/reports/index.vue b/clinical-web/src/views/management/reports/index.vue index fbc854a..21ba40a 100644 --- a/clinical-web/src/views/management/reports/index.vue +++ b/clinical-web/src/views/management/reports/index.vue @@ -226,7 +226,7 @@ function mapReportTask(task: SigningTaskRecord, templates: SigningTemplate[]): R ? 'signed' : task.status === 'expired' ? 'expired' - : task.status === 'void' || task.status === 'failed' || task.status === 'rejected' + : task.status === 'void' || task.status === 'failed' ? 'void' : 'pending' diff --git a/clinical-web/src/views/workbench/signing/components/SigningArtifactList.vue b/clinical-web/src/views/workbench/signing/components/SigningArtifactList.vue index 2b7db98..9e05b97 100644 --- a/clinical-web/src/views/workbench/signing/components/SigningArtifactList.vue +++ b/clinical-web/src/views/workbench/signing/components/SigningArtifactList.vue @@ -48,7 +48,7 @@ function formatFileSize(size: number) {
{{ artifact.label }} - {{ artifact.fileName }} · {{ formatFileSize(artifact.size) }} + {{ artifact.fileName }} · {{ formatFileSize(artifact.sizeBytes) }} 生成于 {{ artifact.createdAt }}
-