diff --git a/app/components/layout/Layout.tsx b/app/components/layout/Layout.tsx
index d5c097e..9d8c362 100644
--- a/app/components/layout/Layout.tsx
+++ b/app/components/layout/Layout.tsx
@@ -136,13 +136,14 @@ export function Layout({ children, userRole = 'developer' as UserRole, frontendJ
const isRulesTestTopbarPage = isRulesTestDetail;
const rulesTestDetailData = matches.find(match => match.pathname.startsWith('/rulesTest/detail'))?.data as RulesTestDetailData | undefined;
const detailPack = rulesTestDetailData?.pack;
+ const detailPackFilterMainType = detailPack?.businessType || detailPack?.mainType || '';
const isContractDetail = !!detailPack?.documentType?.includes('合同');
const isCaseFileDetail = !!detailPack?.documentType?.includes('案卷');
const showFieldNav = isContractDetail && (detailPack?.fields?.length || 0) > 0;
const showSubDocumentNav = isCaseFileDetail && (detailPack?.subDocuments?.length || 0) > 0;
const showVisualNav = (detailPack?.visualElements?.length || 0) > 0;
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';
return (
diff --git a/app/components/layout/Sidebar.tsx b/app/components/layout/Sidebar.tsx
index 8576c87..0e09f82 100644
--- a/app/components/layout/Sidebar.tsx
+++ b/app/components/layout/Sidebar.tsx
@@ -344,22 +344,8 @@ export function Sidebar({ onToggle, collapsed, userRole, frontendJWT = '' }: Sid
if (isCaseFileModule) {
return {
...item,
- children: [
- {
- 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
- }
- ]
+ path: buildRulesTestListPath(),
+ children: undefined
};
}
diff --git a/app/routes/rulesTest.detail.tsx b/app/routes/rulesTest.detail.tsx
index 4c484ac..1abf117 100644
--- a/app/routes/rulesTest.detail.tsx
+++ b/app/routes/rulesTest.detail.tsx
@@ -518,6 +518,7 @@ export default function RulesTestDetail() {
() => versions.find((item) => ['published', 'rollback'].includes(item.status) && item.id !== pack.currentVersionId),
[versions, pack.currentVersionId],
);
+ const packFilterMainType = pack.businessType || pack.mainType;
const currentResolvedVersion = useMemo(
() => versions.find((item) => item.id === pack.currentVersionId || item.id === pack.fallbackVersionId) || null,
[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 (
diff --git a/app/routes/rulesTest.list.tsx b/app/routes/rulesTest.list.tsx
index bfa7f24..4c00a74 100644
--- a/app/routes/rulesTest.list.tsx
+++ b/app/routes/rulesTest.list.tsx
@@ -71,6 +71,10 @@ function resolveDocumentScope(pack: Pick): string {
+ return pack.businessType || pack.mainType || '';
+}
+
function riskColor(risk: string): TagColor {
if (risk === 'high') return 'red';
if (risk === 'medium') return 'orange';
@@ -103,7 +107,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
const documentTypes = unique(packScopes.map(item => item.scope));
const requestedDocumentType = requestedFilters.documentType;
const inferredDocumentType = requestedMainType
- ? packScopes.find(item => item.pack.mainType === requestedMainType)?.scope || ''
+ ? packScopes.find(item => resolveBusinessType(item.pack) === requestedMainType)?.scope || ''
: '';
const currentDocumentType = documentTypes.includes(requestedDocumentType)
? requestedDocumentType
@@ -114,18 +118,18 @@ export async function loader({ request }: LoaderFunctionArgs) {
const scopedFilters = {
...requestedFilters,
documentType: currentDocumentType,
- mainType: scopedDocumentPacks.some(pack => pack.mainType === requestedFilters.mainType)
+ mainType: scopedDocumentPacks.some(pack => resolveBusinessType(pack) === requestedFilters.mainType)
? requestedFilters.mainType
: '',
subtype: scopedDocumentPacks.some(pack =>
- (!requestedFilters.mainType || pack.mainType === requestedFilters.mainType) &&
+ (!requestedFilters.mainType || resolveBusinessType(pack) === requestedFilters.mainType) &&
pack.subtype === requestedFilters.subtype
)
? requestedFilters.subtype
: ''
};
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 ruleGroupSourcePacks = scopedFilters.subtype
@@ -141,7 +145,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
ruleGroup: ruleGroupOptions.includes(requestedFilters.ruleGroup) ? requestedFilters.ruleGroup : ''
};
const visiblePacks = scopedDocumentPacks.filter(pack =>
- (!filters.mainType || pack.mainType === filters.mainType) &&
+ (!filters.mainType || resolveBusinessType(pack) === filters.mainType) &&
(!filters.subtype || pack.subtype === filters.subtype)
);
@@ -152,7 +156,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
packId: pack.id,
documentType: pack.documentType,
moduleType: pack.moduleType,
- mainType: pack.mainType,
+ mainType: resolveBusinessType(pack),
subtype: pack.subtype,
yamlName: pack.metadata.name || '待配置 YAML',
yamlStatus: pack.sourceStatus,
@@ -182,7 +186,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
packId: pack.id,
documentType: pack.documentType,
moduleType: pack.moduleType,
- mainType: pack.mainType,
+ mainType: resolveBusinessType(pack),
subtype: pack.subtype,
yamlName: pack.metadata.name,
yamlStatus: pack.sourceStatus
@@ -213,7 +217,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
pageSize: filters.pageSize,
options: {
documentTypes,
- mainTypes: unique(scopedDocumentPacks.map(pack => pack.mainType)),
+ mainTypes: unique(scopedDocumentPacks.map(pack => resolveBusinessType(pack))),
subtypes: subtypeOptions,
ruleGroups: ruleGroupOptions
}
@@ -244,6 +248,16 @@ export default function RulesTestList() {
const handleFilterChange = (event: React.ChangeEvent) => {
const { name, value } = event.target;
+ if (name === 'mainType') {
+ updateParams({
+ mainType: value,
+ ruleTypeName: undefined,
+ subtype: undefined,
+ documentAttributeType: undefined,
+ ruleGroup: undefined,
+ });
+ return;
+ }
if (name === 'subtype') {
updateParams({ subtype: value, documentAttributeType: undefined, ruleGroup: undefined });
return;
@@ -257,7 +271,7 @@ export default function RulesTestList() {
const handleReset = () => {
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');
setSearchParams(nextParams);
};
@@ -362,6 +376,16 @@ export default function RulesTestList() {
}
>
+ ({ value: mainType, label: mainType }))}
+ onChange={handleFilterChange}
+ className="mr-3 w-[18%]"
+ placeholder="全部"
+ />
+
({ value: subtype, label: subtype }))}
onChange={handleFilterChange}
className="mr-3 w-[18%]"
+ placeholder={filters.mainType || options.mainTypes.length <= 1 ? '全部' : '请先选择业务类型'}
/>
{
+ 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 sourceStatus = item.sourceStatus || ((item.yamlText || '').trim() ? 'ready' : 'empty');
@@ -64,6 +72,8 @@ function mapApiPackToRuleYamlPack(item: RuleConfigPackApi): RuleYamlPack {
moduleType: item.moduleType || (item.documentType ? `${item.documentType}评查` : '规则配置'),
mainType: item.mainType || item.documentType || '',
subtype: item.subtype || '通用',
+ businessType,
+ ruleTypeCode,
},
yamlSource,
sourceStatus,
diff --git a/app/utils/rules-yaml-mock.server.ts b/app/utils/rules-yaml-mock.server.ts
index f26dd93..d9ad59a 100644
--- a/app/utils/rules-yaml-mock.server.ts
+++ b/app/utils/rules-yaml-mock.server.ts
@@ -7,6 +7,8 @@ export type RulePackScope = {
moduleType: string;
mainType: string;
subtype: string;
+ businessType?: string;
+ ruleTypeCode?: string;
};
export type RuleSummary = {