刘光辉
6 小时以前 cf11e63b659afcc9792ab3e395f1b45d844431a8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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;
}