import { type LoaderFunctionArgs, type MetaFunction } from '@remix-run/node'; import { Link, useLoaderData } from '@remix-run/react'; import { Card } from '~/components/ui/Card'; import { Table } from '~/components/ui/Table'; import { Tag, type TagColor } from '~/components/ui/Tag'; import { loadRuleYamlPacks, type RuleSummary, type RuleYamlPack } from '~/utils/rules-yaml-mock.server'; import styles from '~/styles/pages/rules_test.css?url'; export const links = () => [ { rel: 'stylesheet', href: styles } ]; export const meta: MetaFunction = () => [ { title: '规则 YAML 列表 - 智慧法务' } ]; type RuleRow = RuleSummary & { rowId: string; packId: string; documentType: string; moduleType: string; mainType: string; subtype: string; yamlName: string; yamlStatus: RuleYamlPack['sourceStatus']; }; type LoaderData = { rows: RuleRow[]; packs: RuleYamlPack[]; filters: { documentType: string; mainType: string; subtype: string; ruleGroup: string; keyword: string; }; options: { documentTypes: string[]; mainTypes: string[]; subtypes: string[]; ruleGroups: string[]; }; }; function unique(values: string[]): string[] { return Array.from(new Set(values.filter(Boolean))); } function riskColor(risk: string): TagColor { if (risk === 'high') return 'red'; if (risk === 'medium') return 'orange'; if (risk === 'low') return 'green'; return 'gray'; } export async function loader({ request }: LoaderFunctionArgs) { const url = new URL(request.url); const requestedMainType = url.searchParams.get('mainType') || url.searchParams.get('ruleTypeName') || ''; const requestedSubtype = url.searchParams.get('subtype') || url.searchParams.get('documentAttributeType') || ''; const requestedRuleGroup = url.searchParams.get('ruleGroup') || url.searchParams.getAll('ruleGroups')[0] || ''; const requestedFilters = { documentType: url.searchParams.get('documentType') || '', mainType: requestedMainType, subtype: requestedSubtype, ruleGroup: requestedRuleGroup, keyword: url.searchParams.get('keyword') || '' }; const packs = await loadRuleYamlPacks(); const documentTypes = unique(packs.map(pack => pack.documentType)); const inferredDocumentType = packs.find(pack => pack.mainType === requestedFilters.mainType)?.documentType || ''; const currentDocumentType = documentTypes.includes(requestedFilters.documentType) ? requestedFilters.documentType : inferredDocumentType || documentTypes[0] || ''; const scopedFilters = { ...requestedFilters, documentType: currentDocumentType, mainType: packs.some(pack => pack.documentType === currentDocumentType && pack.mainType === requestedFilters.mainType) ? requestedFilters.mainType : '', subtype: packs.some(pack => pack.documentType === currentDocumentType && (!requestedFilters.mainType || pack.mainType === requestedFilters.mainType) && pack.subtype === requestedFilters.subtype ) ? requestedFilters.subtype : '' }; const scopedPacks = packs.filter(pack => pack.documentType === scopedFilters.documentType && (!scopedFilters.mainType || pack.mainType === scopedFilters.mainType) && (!scopedFilters.subtype || pack.subtype === scopedFilters.subtype) ); const ruleGroupOptions = unique(scopedPacks.flatMap(pack => pack.rules.map(rule => rule.group))).sort((a, b) => a.localeCompare(b, 'zh-CN')); const filters = { ...scopedFilters, ruleGroup: ruleGroupOptions.includes(requestedFilters.ruleGroup) ? requestedFilters.ruleGroup : '' }; const visiblePacks = packs.filter(pack => pack.documentType === filters.documentType && (!filters.mainType || pack.mainType === filters.mainType) && (!filters.subtype || pack.subtype === filters.subtype) ); const rows: RuleRow[] = visiblePacks.flatMap((pack): RuleRow[] => { if (pack.rules.length === 0) { return [{ rowId: `${pack.id}-empty`, packId: pack.id, documentType: pack.documentType, moduleType: pack.moduleType, mainType: pack.mainType, subtype: pack.subtype, yamlName: pack.metadata.name || '待配置 YAML', yamlStatus: pack.sourceStatus, id: `${pack.id}-empty`, ruleId: '-', name: '暂无规则配置', group: '待配置', risk: '-', score: '-', type: '-', checkTypes: [], logic: '', subRules: [], subRuleIds: [], scope: [], dependencies: [], stageCount: 0, appliesIn: [], prompt: '', description: '当前文档类型已保留规则列表与 YAML 配置页流程,等待后续接入规则文件。' }]; } return pack.rules.map(rule => ({ ...rule, rowId: `${pack.id}-${rule.ruleId || rule.id}`, packId: pack.id, documentType: pack.documentType, moduleType: pack.moduleType, mainType: pack.mainType, subtype: pack.subtype, yamlName: pack.metadata.name, yamlStatus: pack.sourceStatus })); }).filter(row => { if (filters.ruleGroup && row.group !== filters.ruleGroup) { return false; } if (!filters.keyword) return true; return [row.ruleId, row.name, row.group, row.yamlName, row.subtype] .some(value => value.toLowerCase().includes(filters.keyword.toLowerCase())); }); return Response.json({ rows, packs, filters, options: { documentTypes, mainTypes: unique(packs.filter(pack => pack.documentType === filters.documentType).map(pack => pack.mainType)), subtypes: unique(packs.filter(pack => pack.documentType === filters.documentType && (!filters.mainType || pack.mainType === filters.mainType) ).map(pack => pack.subtype)), ruleGroups: ruleGroupOptions } } satisfies LoaderData); } export default function RulesTestList() { const { rows } = useLoaderData() as LoaderData; const columns = [ { title: '规则', key: 'rule', width: '24%', render: (_: unknown, record: RuleRow) => (
{record.name} {record.ruleId}
) }, { title: '子分类', key: 'subtype', width: '12%', align: 'center' as const, render: (_: unknown, record: RuleRow) => (
{record.subtype}
) }, { title: '规则组', dataIndex: 'group' as keyof RuleRow, key: 'group', width: '14%', align: 'center' as const }, { title: '风险', key: 'risk', width: '8%', align: 'center' as const, render: (_: unknown, record: RuleRow) => ( {record.risk} ) }, { title: '分值', key: 'score', width: '8%', align: 'center' as const, render: (_: unknown, record: RuleRow) => ( {record.score} ) }, { title: '依赖字段', key: 'dependencies', width: '20%', render: (_: unknown, record: RuleRow) => ( {record.dependencies.length > 0 ? record.dependencies.slice(0, 3).join('、') : '-'} ) }, { title: '操作', key: 'operation', width: '14%', align: 'center' as const, render: (_: unknown, record: RuleRow) => ( 配置 ) } ]; return (
暂无规则。当前类型的规则列表流程已保留,可进入配置页查看空 YAML 模板。} /> ); }