import type { AnnotationCatalog, FormField, WorkflowStep } from '../domain/annotation';
|
import type { WritableQianpiyePluginContext } from '../domain/context';
|
|
const STEPS_PATH = '/api/dms/biz/wenjian/qianpiye/steps';
|
|
interface ActionResult<T> {
|
code: number;
|
data?: T;
|
msg?: string;
|
}
|
|
export class WorkflowStepsApiError extends Error {
|
readonly status: number;
|
|
constructor(status: number, message: string) {
|
super(message);
|
this.name = 'WorkflowStepsApiError';
|
this.status = status;
|
}
|
}
|
|
function isWorkflowStep(value: unknown): value is WorkflowStep {
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;
|
const step = value as Record<string, unknown>;
|
return typeof step.key === 'string'
|
&& typeof step.label === 'string'
|
&& (step.role === 'START' || step.role === 'APPROVE');
|
}
|
|
function isFormField(value: unknown): value is FormField {
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;
|
const field = value as Record<string, unknown>;
|
return typeof field.key === 'string' && typeof field.label === 'string'
|
&& ['tag', 'formId', 'table', 'column'].every((key) => field[key] === undefined || typeof field[key] === 'string');
|
}
|
|
function isAnnotationCatalog(value: unknown): value is AnnotationCatalog {
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;
|
const catalog = value as Record<string, unknown>;
|
return typeof catalog.newFlowVersionId === 'string' && catalog.newFlowVersionId.length > 0
|
&& typeof catalog.revisionFlowVersionId === 'string' && catalog.revisionFlowVersionId.length > 0
|
&& Array.isArray(catalog.workflowSteps) && catalog.workflowSteps.every(isWorkflowStep)
|
&& Array.isArray(catalog.formFields) && catalog.formFields.every(isFormField);
|
}
|
|
async function readPayload(response: Response): Promise<ActionResult<unknown> | null> {
|
try {
|
const value: unknown = await response.json();
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) return null;
|
return value as ActionResult<unknown>;
|
} catch {
|
return null;
|
}
|
}
|
|
export async function fetchAnnotationCatalog(context: WritableQianpiyePluginContext, refresh = false,
|
signal?: AbortSignal): Promise<AnnotationCatalog> {
|
const query = refresh ? '?refresh=true' : '';
|
const response = await fetch(`${context.apiBaseUrl}${STEPS_PATH}${query}`, {
|
headers: { Authorization: `Ticket ${context.ticket}` },
|
signal,
|
});
|
const payload = await readPayload(response);
|
if (!response.ok) {
|
throw new WorkflowStepsApiError(response.status, payload?.msg || response.statusText || '加载流程步骤失败');
|
}
|
if (!payload || payload.code !== 200 || !isAnnotationCatalog(payload.data)) {
|
throw new WorkflowStepsApiError(response.status, payload?.msg || '流程步骤接口响应无效');
|
}
|
return payload.data;
|
}
|