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 = {