fix(signing): align workbench with MEDISIGN contract

This commit is contained in:
yelan
2026-09-01 14:50:07 +08:00
parent 8b4b9d031d
commit 5b2cc33038
10 changed files with 155 additions and 51 deletions
+7 -5
View File
@@ -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),
}
}
+8 -6
View File
@@ -41,15 +41,12 @@ export function sendSigningSms(
export function resendSigningSms(
taskId: string,
expectedRowVersion?: number,
idempotencyKey?: string,
): Promise<SignDeliveryResponseDto | null> {
const data = expectedRowVersion === undefined ? undefined : { expectedRowVersion }
return request
.post<ApiResponseOf<SignDeliveryResponseDto | null>>(
`/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<TokenConsumeResponse> {
export function consumeSigningToken(
payload: TokenConsumeRequest,
idempotencyKey?: string,
): Promise<TokenConsumeResponse> {
return request
.post<ApiResponseOf<TokenConsumeResponse>>('/v1/sign-deliveries/token/consume', payload)
.post<ApiResponseOf<TokenConsumeResponse>>('/v1/sign-deliveries/token/consume', payload, {
headers: idempotencyHeaders(idempotencyKey),
})
.then(unwrapApiResponse)
}
+21 -5
View File
@@ -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<Record<VisitType, BackendVisitType>> = {
门诊: '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<SigningTaskRecord | null> {
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: '处理失败',
+12 -15
View File
@@ -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<string, string>
campusNames?: Record<string, WorkbenchCampus>
departmentIds?: Record<string, string>
}
@@ -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<string, unknown>
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<string, unknown>
createdAt: string
}