feat(signing): 统一演示文书库并支持下载签名原图
This commit is contained in:
@@ -4,6 +4,7 @@ import { unwrapApiResponse } from '@/utils/api-response'
|
||||
import { mockFlags } from '@/utils/mock-flags'
|
||||
import { request } from '@/utils/request'
|
||||
|
||||
import { getMockSigningTask } from './signing'
|
||||
import type {
|
||||
ApiPageResponse,
|
||||
ApiResponseOf,
|
||||
@@ -70,9 +71,71 @@ function normalizeArtifact(dto: SignArtifactResponseDto): SigningArtifact {
|
||||
|
||||
export const isArtifactMockEnabled = useMockData
|
||||
|
||||
/**
|
||||
* 演示签名原图产物的 id 前缀。
|
||||
* 演示环境没有文件服务,下载时靠 id 反查任务里的签名图,
|
||||
* 保证「签名原图」在演示里也是真能下载到的文件,而不是占位提示。
|
||||
*/
|
||||
const MOCK_SIGNATURE_PREFIX = 'mock-signature-'
|
||||
|
||||
function estimateDataUrlBytes(dataUrl: string) {
|
||||
const payload = dataUrl.split(',')[1]
|
||||
|
||||
if (!payload) {
|
||||
return 0
|
||||
}
|
||||
|
||||
// base64 每 4 个字符还原 3 字节,末尾可能有填充,这里取近似值用于展示
|
||||
return Math.floor((payload.replace(/=+$/, '').length * 3) / 4)
|
||||
}
|
||||
|
||||
/** 演示产物:已签署且有签名图时,给出可下载的签名原图 */
|
||||
function buildMockArtifacts(taskId: string): SigningArtifact[] {
|
||||
const task = getMockSigningTask(taskId)
|
||||
|
||||
if (!task || task.status !== 'signed' || !task.signatureDataUrl) {
|
||||
return []
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
id: `${MOCK_SIGNATURE_PREFIX}${task.id}`,
|
||||
taskId: task.id,
|
||||
pipelineId: `mock-pipeline-${task.id}`,
|
||||
artifactType: 'SIGNATURE_IMAGE',
|
||||
label: artifactLabels.SIGNATURE_IMAGE ?? '签名原图',
|
||||
fileName: '签名原图.png',
|
||||
mimeType: 'image/png',
|
||||
sizeBytes: estimateDataUrlBytes(task.signatureDataUrl),
|
||||
sha256: '',
|
||||
metadata: {},
|
||||
createdAt: formatDateTime(task.signedAt ?? task.updatedAt),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
/** 把签名图 dataURL 还原成可下载的二进制 Blob */
|
||||
function dataUrlToBlob(dataUrl: string): Blob {
|
||||
const [meta, payload] = dataUrl.split(',')
|
||||
const mimeType = /data:([^;]+)/.exec(meta ?? '')?.[1] ?? 'application/octet-stream'
|
||||
|
||||
if (!payload) {
|
||||
return new Blob([], { type: mimeType })
|
||||
}
|
||||
|
||||
const binary = window.atob(payload)
|
||||
const bytes = new Uint8Array(binary.length)
|
||||
|
||||
for (let index = 0; index < binary.length; index += 1) {
|
||||
bytes[index] = binary.charCodeAt(index)
|
||||
}
|
||||
|
||||
return new Blob([bytes], { type: mimeType })
|
||||
}
|
||||
|
||||
export async function getSigningArtifacts(taskId: string): Promise<SigningArtifact[]> {
|
||||
if (useMockData) {
|
||||
return []
|
||||
return buildMockArtifacts(taskId)
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -115,6 +178,16 @@ export async function getSigningArtifact(
|
||||
|
||||
export function downloadSigningArtifact(artifactId: string): Promise<Blob> {
|
||||
if (useMockData) {
|
||||
// 演示环境没有文件服务,按 id 反查任务里的签名图,返回真实的 PNG
|
||||
if (artifactId.startsWith(MOCK_SIGNATURE_PREFIX)) {
|
||||
const taskId = artifactId.slice(MOCK_SIGNATURE_PREFIX.length)
|
||||
const signatureDataUrl = getMockSigningTask(taskId)?.signatureDataUrl
|
||||
|
||||
if (signatureDataUrl) {
|
||||
return Promise.resolve(dataUrlToBlob(signatureDataUrl))
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(new Blob(['Mock 签署文件,仅用于界面演示。'], { type: 'text/plain' }))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user