Files
leaudit-platform-frontend/app/utils/rules-config-packs.server.ts
T
2026-05-07 09:59:01 +08:00

125 lines
4.0 KiB
TypeScript

import { API_BASE_URL } from '~/config/api-config';
import { getUserSession } from '~/api/login/auth.server';
import {
buildRuleYamlPack,
EMPTY_RULE_YAML,
type RuleYamlPack,
} from './rules-yaml-mock.server';
type RuleConfigPackApi = {
packId: number;
groupId: number;
rootGroupId?: number | null;
bindingId?: number | null;
ruleSetId?: number | null;
ruleType?: string | null;
ruleName?: string | null;
currentVersionId?: number | null;
fallbackVersionId?: number | null;
resolvedVersionId?: number | null;
hasUsableVersion?: boolean;
usableRuleCount?: number;
documentTypeId?: number | null;
documentType?: string;
moduleType?: string;
mainType?: string;
subtype?: string;
yamlText?: string;
sourceStatus?: 'ready' | 'empty' | 'missing';
};
type ApiEnvelope<T> = {
code?: number;
message?: string;
msg?: string;
data?: T;
};
export type RuleVersionItem = {
id: number;
ruleSetId: number;
versionNo: string;
status: string;
ossUrl: string;
changeNote?: string | null;
publishedAt?: string | null;
};
function getMessage(payload: unknown, fallback: string): string {
if (!payload || typeof payload !== 'object') {
return fallback;
}
return String((payload as ApiEnvelope<unknown>).message || (payload as ApiEnvelope<unknown>).msg || fallback);
}
function mapApiPackToRuleYamlPack(item: RuleConfigPackApi): RuleYamlPack {
const ruleTypeCode = String(item.ruleType || '').trim();
// 业务类型必须以后端 pack 聚合返回的 mainType 为准。
// 不能再从 ruleType 第二段硬拆;例如 contract.entrust 会被错误显示成 entrust。
const businessType = item.mainType || item.documentType || '';
const yamlSource = (item.yamlText || '').trim() ? String(item.yamlText) : EMPTY_RULE_YAML;
const sourceStatus = item.sourceStatus || ((item.yamlText || '').trim() ? 'ready' : 'empty');
return buildRuleYamlPack(
{
id: String(item.packId),
yamlPath: null,
documentType: item.documentType || '',
moduleType: item.moduleType || (item.documentType ? `${item.documentType}评查` : '规则配置'),
mainType: item.mainType || item.documentType || '',
subtype: item.subtype || '通用',
businessType,
ruleTypeCode,
currentVersionId: item.currentVersionId ?? null,
fallbackVersionId: item.fallbackVersionId ?? null,
resolvedVersionId: item.resolvedVersionId ?? null,
},
yamlSource,
sourceStatus,
);
}
async function fetchRuleConfigPayload<T>(request: Request, path: string): Promise<T> {
const { frontendJWT } = await getUserSession(request);
if (!frontendJWT) {
throw new Response('未登录或会话已失效', { status: 401 });
}
const response = await fetch(`${API_BASE_URL}${path}`, {
method: 'GET',
headers: {
Authorization: `Bearer ${frontendJWT}`,
Accept: 'application/json',
},
});
const payload = (await response.json()) as ApiEnvelope<T>;
if (!response.ok || typeof payload.data === 'undefined' || payload.data === null) {
throw new Response(getMessage(payload, '规则配置加载失败'), { status: response.status || 500 });
}
return payload.data;
}
export async function loadRuleConfigPacks(request: Request): Promise<RuleYamlPack[]> {
const items = await fetchRuleConfigPayload<RuleConfigPackApi[]>(request, '/api/v3/rule-config-packs');
return items.map(mapApiPackToRuleYamlPack);
}
export async function loadRuleConfigPack(request: Request, packId: string): Promise<RuleYamlPack | undefined> {
if (!packId) {
const packs = await loadRuleConfigPacks(request);
return packs[0];
}
const item = await fetchRuleConfigPayload<RuleConfigPackApi>(request, `/api/v3/rule-config-packs/${encodeURIComponent(packId)}`);
return mapApiPackToRuleYamlPack(item);
}
export async function loadRuleConfigVersions(request: Request, ruleType: string): Promise<RuleVersionItem[]> {
if (!ruleType) {
return [];
}
return fetchRuleConfigPayload<RuleVersionItem[]>(request, `/api/rule-sets/${encodeURIComponent(ruleType)}/versions`);
}