fix: align case-file rule filters with business types
This commit is contained in:
@@ -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 (
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
Reference in New Issue
Block a user