fix: align case-file rule filters with business types

This commit is contained in:
wren
2026-05-06 18:18:49 +08:00
parent c7bbe59882
commit 2d8bab2c91
6 changed files with 52 additions and 27 deletions
+2 -1
View File
@@ -136,13 +136,14 @@ export function Layout({ children, userRole = 'developer' as UserRole, frontendJ
const isRulesTestTopbarPage = isRulesTestDetail; const isRulesTestTopbarPage = isRulesTestDetail;
const rulesTestDetailData = matches.find(match => match.pathname.startsWith('/rulesTest/detail'))?.data as RulesTestDetailData | undefined; const rulesTestDetailData = matches.find(match => match.pathname.startsWith('/rulesTest/detail'))?.data as RulesTestDetailData | undefined;
const detailPack = rulesTestDetailData?.pack; const detailPack = rulesTestDetailData?.pack;
const detailPackFilterMainType = detailPack?.businessType || detailPack?.mainType || '';
const isContractDetail = !!detailPack?.documentType?.includes('合同'); const isContractDetail = !!detailPack?.documentType?.includes('合同');
const isCaseFileDetail = !!detailPack?.documentType?.includes('案卷'); const isCaseFileDetail = !!detailPack?.documentType?.includes('案卷');
const showFieldNav = isContractDetail && (detailPack?.fields?.length || 0) > 0; const showFieldNav = isContractDetail && (detailPack?.fields?.length || 0) > 0;
const showSubDocumentNav = isCaseFileDetail && (detailPack?.subDocuments?.length || 0) > 0; const showSubDocumentNav = isCaseFileDetail && (detailPack?.subDocuments?.length || 0) > 0;
const showVisualNav = (detailPack?.visualElements?.length || 0) > 0; const showVisualNav = (detailPack?.visualElements?.length || 0) > 0;
const rulesListHref = detailPack?.documentType const rulesListHref = detailPack?.documentType
? `/rulesTest/list?documentType=${encodeURIComponent(detailPack.documentType)}${detailPack.mainType ? `&mainType=${encodeURIComponent(detailPack.mainType)}` : ''}` ? `/rulesTest/list?documentType=${encodeURIComponent(detailPack.documentType)}${detailPackFilterMainType ? `&mainType=${encodeURIComponent(detailPackFilterMainType)}` : ''}`
: '/rulesTest/list'; : '/rulesTest/list';
return ( return (
+2 -16
View File
@@ -344,22 +344,8 @@ export function Sidebar({ onToggle, collapsed, userRole, frontendJWT = '' }: Sid
if (isCaseFileModule) { if (isCaseFileModule) {
return { return {
...item, ...item,
children: [ path: buildRulesTestListPath(),
{ children: undefined
id: 'rules-admin-penalty',
title: '行政处罚',
path: buildRulesTestListPath('行政处罚'),
icon: 'ri-list-check-3',
order: 1
},
{
id: 'rules-admin-license',
title: '行政许可',
path: buildRulesTestListPath('行政许可'),
icon: 'ri-list-check-3',
order: 2
}
]
}; };
} }
+2 -1
View File
@@ -518,6 +518,7 @@ export default function RulesTestDetail() {
() => versions.find((item) => ['published', 'rollback'].includes(item.status) && item.id !== pack.currentVersionId), () => versions.find((item) => ['published', 'rollback'].includes(item.status) && item.id !== pack.currentVersionId),
[versions, pack.currentVersionId], [versions, pack.currentVersionId],
); );
const packFilterMainType = pack.businessType || pack.mainType;
const currentResolvedVersion = useMemo( const currentResolvedVersion = useMemo(
() => versions.find((item) => item.id === pack.currentVersionId || item.id === pack.fallbackVersionId) || null, () => versions.find((item) => item.id === pack.currentVersionId || item.id === pack.fallbackVersionId) || null,
[pack.currentVersionId, pack.fallbackVersionId, versions], [pack.currentVersionId, pack.fallbackVersionId, versions],
@@ -719,7 +720,7 @@ export default function RulesTestDetail() {
} }
]; ];
const backLink = `/rulesTest/list?documentType=${encodeURIComponent(pack.documentType)}&mainType=${encodeURIComponent(pack.mainType)}&subtype=${encodeURIComponent(pack.subtype)}`; const backLink = `/rulesTest/list?documentType=${encodeURIComponent(pack.documentType)}&mainType=${encodeURIComponent(packFilterMainType)}&subtype=${encodeURIComponent(pack.subtype)}`;
return ( return (
<div className="rules-test-page rules-page"> <div className="rules-test-page rules-page">
+34 -9
View File
@@ -71,6 +71,10 @@ function resolveDocumentScope(pack: Pick<RuleYamlPack, 'documentType' | 'mainTyp
return pack.documentType || pack.mainType || pack.moduleType || '未分类'; return pack.documentType || pack.mainType || pack.moduleType || '未分类';
} }
function resolveBusinessType(pack: Pick<RuleYamlPack, 'businessType' | 'mainType'>): string {
return pack.businessType || pack.mainType || '';
}
function riskColor(risk: string): TagColor { function riskColor(risk: string): TagColor {
if (risk === 'high') return 'red'; if (risk === 'high') return 'red';
if (risk === 'medium') return 'orange'; if (risk === 'medium') return 'orange';
@@ -103,7 +107,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
const documentTypes = unique(packScopes.map(item => item.scope)); const documentTypes = unique(packScopes.map(item => item.scope));
const requestedDocumentType = requestedFilters.documentType; const requestedDocumentType = requestedFilters.documentType;
const inferredDocumentType = requestedMainType const inferredDocumentType = requestedMainType
? packScopes.find(item => item.pack.mainType === requestedMainType)?.scope || '' ? packScopes.find(item => resolveBusinessType(item.pack) === requestedMainType)?.scope || ''
: ''; : '';
const currentDocumentType = documentTypes.includes(requestedDocumentType) const currentDocumentType = documentTypes.includes(requestedDocumentType)
? requestedDocumentType ? requestedDocumentType
@@ -114,18 +118,18 @@ export async function loader({ request }: LoaderFunctionArgs) {
const scopedFilters = { const scopedFilters = {
...requestedFilters, ...requestedFilters,
documentType: currentDocumentType, documentType: currentDocumentType,
mainType: scopedDocumentPacks.some(pack => pack.mainType === requestedFilters.mainType) mainType: scopedDocumentPacks.some(pack => resolveBusinessType(pack) === requestedFilters.mainType)
? requestedFilters.mainType ? requestedFilters.mainType
: '', : '',
subtype: scopedDocumentPacks.some(pack => subtype: scopedDocumentPacks.some(pack =>
(!requestedFilters.mainType || pack.mainType === requestedFilters.mainType) && (!requestedFilters.mainType || resolveBusinessType(pack) === requestedFilters.mainType) &&
pack.subtype === requestedFilters.subtype pack.subtype === requestedFilters.subtype
) )
? requestedFilters.subtype ? requestedFilters.subtype
: '' : ''
}; };
const scopedByMainTypePacks = scopedDocumentPacks.filter(pack => const scopedByMainTypePacks = scopedDocumentPacks.filter(pack =>
!scopedFilters.mainType || pack.mainType === scopedFilters.mainType !scopedFilters.mainType || resolveBusinessType(pack) === scopedFilters.mainType
); );
const subtypeOptions = unique(scopedByMainTypePacks.map(pack => pack.subtype)); const subtypeOptions = unique(scopedByMainTypePacks.map(pack => pack.subtype));
const ruleGroupSourcePacks = scopedFilters.subtype const ruleGroupSourcePacks = scopedFilters.subtype
@@ -141,7 +145,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
ruleGroup: ruleGroupOptions.includes(requestedFilters.ruleGroup) ? requestedFilters.ruleGroup : '' ruleGroup: ruleGroupOptions.includes(requestedFilters.ruleGroup) ? requestedFilters.ruleGroup : ''
}; };
const visiblePacks = scopedDocumentPacks.filter(pack => const visiblePacks = scopedDocumentPacks.filter(pack =>
(!filters.mainType || pack.mainType === filters.mainType) && (!filters.mainType || resolveBusinessType(pack) === filters.mainType) &&
(!filters.subtype || pack.subtype === filters.subtype) (!filters.subtype || pack.subtype === filters.subtype)
); );
@@ -152,7 +156,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
packId: pack.id, packId: pack.id,
documentType: pack.documentType, documentType: pack.documentType,
moduleType: pack.moduleType, moduleType: pack.moduleType,
mainType: pack.mainType, mainType: resolveBusinessType(pack),
subtype: pack.subtype, subtype: pack.subtype,
yamlName: pack.metadata.name || '待配置 YAML', yamlName: pack.metadata.name || '待配置 YAML',
yamlStatus: pack.sourceStatus, yamlStatus: pack.sourceStatus,
@@ -182,7 +186,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
packId: pack.id, packId: pack.id,
documentType: pack.documentType, documentType: pack.documentType,
moduleType: pack.moduleType, moduleType: pack.moduleType,
mainType: pack.mainType, mainType: resolveBusinessType(pack),
subtype: pack.subtype, subtype: pack.subtype,
yamlName: pack.metadata.name, yamlName: pack.metadata.name,
yamlStatus: pack.sourceStatus yamlStatus: pack.sourceStatus
@@ -213,7 +217,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
pageSize: filters.pageSize, pageSize: filters.pageSize,
options: { options: {
documentTypes, documentTypes,
mainTypes: unique(scopedDocumentPacks.map(pack => pack.mainType)), mainTypes: unique(scopedDocumentPacks.map(pack => resolveBusinessType(pack))),
subtypes: subtypeOptions, subtypes: subtypeOptions,
ruleGroups: ruleGroupOptions ruleGroups: ruleGroupOptions
} }
@@ -244,6 +248,16 @@ export default function RulesTestList() {
const handleFilterChange = (event: React.ChangeEvent<HTMLSelectElement>) => { const handleFilterChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const { name, value } = event.target; const { name, value } = event.target;
if (name === 'mainType') {
updateParams({
mainType: value,
ruleTypeName: undefined,
subtype: undefined,
documentAttributeType: undefined,
ruleGroup: undefined,
});
return;
}
if (name === 'subtype') { if (name === 'subtype') {
updateParams({ subtype: value, documentAttributeType: undefined, ruleGroup: undefined }); updateParams({ subtype: value, documentAttributeType: undefined, ruleGroup: undefined });
return; return;
@@ -257,7 +271,7 @@ export default function RulesTestList() {
const handleReset = () => { const handleReset = () => {
const nextParams = new URLSearchParams(searchParams); const nextParams = new URLSearchParams(searchParams);
['ruleGroup', 'subtype', 'documentAttributeType', 'keyword', 'page'].forEach(key => nextParams.delete(key)); ['mainType', 'ruleTypeName', 'ruleGroup', 'subtype', 'documentAttributeType', 'keyword', 'page'].forEach(key => nextParams.delete(key));
nextParams.set('page', '1'); nextParams.set('page', '1');
setSearchParams(nextParams); setSearchParams(nextParams);
}; };
@@ -362,6 +376,16 @@ export default function RulesTestList() {
</Button> </Button>
} }
> >
<FilterSelect
label="业务类型"
name="mainType"
value={filters.mainType}
options={options.mainTypes.map(mainType => ({ value: mainType, label: mainType }))}
onChange={handleFilterChange}
className="mr-3 w-[18%]"
placeholder="全部"
/>
<FilterSelect <FilterSelect
label="子类型" label="子类型"
name="subtype" name="subtype"
@@ -369,6 +393,7 @@ export default function RulesTestList() {
options={options.subtypes.map(subtype => ({ value: subtype, label: subtype }))} options={options.subtypes.map(subtype => ({ value: subtype, label: subtype }))}
onChange={handleFilterChange} onChange={handleFilterChange}
className="mr-3 w-[18%]" className="mr-3 w-[18%]"
placeholder={filters.mainType || options.mainTypes.length <= 1 ? '全部' : '请先选择业务类型'}
/> />
<FilterSelect <FilterSelect
+10
View File
@@ -53,6 +53,14 @@ function getMessage(payload: unknown, fallback: string): string {
} }
function mapApiPackToRuleYamlPack(item: RuleConfigPackApi): RuleYamlPack { function mapApiPackToRuleYamlPack(item: RuleConfigPackApi): RuleYamlPack {
const ruleTypeCode = String(item.ruleType || '').trim();
const businessType = (() => {
const segments = ruleTypeCode.split('.').map(segment => segment.trim()).filter(Boolean);
if (segments.length >= 2) {
return segments[1];
}
return item.mainType || item.documentType || '';
})();
const yamlSource = (item.yamlText || '').trim() ? String(item.yamlText) : EMPTY_RULE_YAML; const yamlSource = (item.yamlText || '').trim() ? String(item.yamlText) : EMPTY_RULE_YAML;
const sourceStatus = item.sourceStatus || ((item.yamlText || '').trim() ? 'ready' : 'empty'); const sourceStatus = item.sourceStatus || ((item.yamlText || '').trim() ? 'ready' : 'empty');
@@ -64,6 +72,8 @@ function mapApiPackToRuleYamlPack(item: RuleConfigPackApi): RuleYamlPack {
moduleType: item.moduleType || (item.documentType ? `${item.documentType}评查` : '规则配置'), moduleType: item.moduleType || (item.documentType ? `${item.documentType}评查` : '规则配置'),
mainType: item.mainType || item.documentType || '', mainType: item.mainType || item.documentType || '',
subtype: item.subtype || '通用', subtype: item.subtype || '通用',
businessType,
ruleTypeCode,
}, },
yamlSource, yamlSource,
sourceStatus, sourceStatus,
+2
View File
@@ -7,6 +7,8 @@ export type RulePackScope = {
moduleType: string; moduleType: string;
mainType: string; mainType: string;
subtype: string; subtype: string;
businessType?: string;
ruleTypeCode?: string;
}; };
export type RuleSummary = { export type RuleSummary = {