对齐规则列表页交互样式

This commit is contained in:
2026-04-29 11:22:20 +08:00
parent dce5ac0c9a
commit 84d2e0a1a5
4 changed files with 209 additions and 102 deletions
+3 -3
View File
@@ -84,7 +84,7 @@ export function Breadcrumb({ items = [], className = '' }: BreadcrumbProps) {
<nav className={finalClassName} aria-label="面包屑导航">
<ol className="flex items-center space-x-2 text-sm text-gray-500 mb-0">
<li>
<Link to="/" className="hover:text-primary-600 flex items-center">
<Link to="/" className="hover:text-[--color-primary-hover] flex items-center">
<i className="ri-home-line mr-1" />
</Link>
@@ -98,7 +98,7 @@ export function Breadcrumb({ items = [], className = '' }: BreadcrumbProps) {
) : (
<Link
to={item.to || '#'}
className="hover:text-primary-600"
className="hover:text-[--color-primary-hover]"
prefetch="intent"
preventScrollReset={false}
>
@@ -110,4 +110,4 @@ export function Breadcrumb({ items = [], className = '' }: BreadcrumbProps) {
</ol>
</nav>
);
}
}
+2 -93
View File
@@ -36,20 +36,6 @@ type RulesTestDetailData = {
};
};
type RulesTestListData = {
filters?: {
documentType?: string;
mainType?: string;
subtype?: string;
ruleGroup?: string;
keyword?: string;
};
options?: {
subtypes?: string[];
ruleGroups?: string[];
};
};
export function Layout({ children, userRole = 'developer' as UserRole, frontendJWT = '', isMobile = false }: LayoutProps) {
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [effectiveUserRole, setEffectiveUserRole] = useState<UserRole>(userRole);
@@ -146,13 +132,9 @@ export function Layout({ children, userRole = 'developer' as UserRole, frontendJ
return <>{children}</>;
}
const isRulesTestList = location.pathname.startsWith('/rulesTest/list');
const isRulesTestDetail = location.pathname.startsWith('/rulesTest/detail');
const isRulesTestTopbarPage = isRulesTestList || isRulesTestDetail;
const rulesTestListData = matches.find(match => match.pathname.startsWith('/rulesTest/list'))?.data as RulesTestListData | undefined;
const isRulesTestTopbarPage = isRulesTestDetail;
const rulesTestDetailData = matches.find(match => match.pathname.startsWith('/rulesTest/detail'))?.data as RulesTestDetailData | undefined;
const listFilters = rulesTestListData?.filters || {};
const listOptions = rulesTestListData?.options || {};
const detailPack = rulesTestDetailData?.pack;
const isContractDetail = !!detailPack?.documentType?.includes('合同');
const isCaseFileDetail = !!detailPack?.documentType?.includes('案卷');
@@ -162,13 +144,6 @@ export function Layout({ children, userRole = 'developer' as UserRole, frontendJ
const rulesListHref = detailPack?.documentType
? `/rulesTest/list?documentType=${encodeURIComponent(detailPack.documentType)}${detailPack.mainType ? `&mainType=${encodeURIComponent(detailPack.mainType)}` : ''}`
: '/rulesTest/list';
const listScopeText = [
listFilters.documentType,
listFilters.mainType && listFilters.mainType !== listFilters.documentType ? listFilters.mainType : ''
].filter(Boolean).join(' / ');
const submitTopbarFilter = (event: React.ChangeEvent<HTMLSelectElement>) => {
event.currentTarget.form?.requestSubmit();
};
return (
<div className="layout-container">
@@ -180,72 +155,6 @@ export function Layout({ children, userRole = 'developer' as UserRole, frontendJ
frontendJWT={effectiveFrontendJWT}
/>
{/* 规则列表页顶部栏 */}
{isRulesTestList && (
<div className={`page-topbar rules-list-topbar ${sidebarCollapsed ? 'sidebar-collapsed' : ''}`}>
<div className="topbar-content">
<div className="topbar-left">
<span className="topbar-icon" aria-hidden="true">
<i className="ri-list-settings-line"></i>
</span>
<div className="topbar-heading">
<h2 className="topbar-title"></h2>
<span className="topbar-breadcrumb">
<span></span>
{listScopeText && (
<>
<span className="separator">/</span>
<span>{listScopeText}</span>
</>
)}
</span>
</div>
</div>
<div className="topbar-right">
<a className="topbar-action secondary" href="/rules/list">
<i className="ri-history-line"></i>
<span></span>
</a>
</div>
</div>
<form method="get" action="/rulesTest/list" className="topbar-filter-strip">
<input type="hidden" name="documentType" defaultValue={listFilters.documentType || ''} />
{listFilters.mainType && <input type="hidden" name="mainType" defaultValue={listFilters.mainType} />}
<label className="topbar-filter-field">
<span></span>
<select name="subtype" value={listFilters.subtype || ''} onChange={submitTopbarFilter}>
<option value=""></option>
{(listOptions.subtypes || []).map(option => (
<option key={option} value={option}>{option}</option>
))}
</select>
</label>
<label className="topbar-filter-field">
<span></span>
<select name="ruleGroup" value={listFilters.ruleGroup || ''} onChange={submitTopbarFilter}>
<option value=""></option>
{(listOptions.ruleGroups || []).map(group => (
<option key={group} value={group}>{group}</option>
))}
</select>
</label>
<label className="topbar-filter-field topbar-filter-field-search">
<span></span>
<input
key={listFilters.keyword || 'empty-keyword'}
name="keyword"
defaultValue={listFilters.keyword || ''}
placeholder="规则名称 / 编码 / 规则组"
/>
</label>
<button className="topbar-action" type="submit">
<i className="ri-search-line"></i>
<span></span>
</button>
</form>
</div>
)}
{/* 规则详情页顶部栏 */}
{isRulesTestDetail && (
<div className={`page-topbar ${sidebarCollapsed ? 'sidebar-collapsed' : ''}`}>
@@ -283,7 +192,7 @@ export function Layout({ children, userRole = 'developer' as UserRole, frontendJ
</div>
)}
<div className={`main-content ${sidebarCollapsed ? 'sidebar-collapsed' : ''} ${isRulesTestDetail ? 'rules-detail-main' : ''} ${isRulesTestList ? 'rules-list-main' : ''}`}>
<div className={`main-content ${sidebarCollapsed ? 'sidebar-collapsed' : ''} ${isRulesTestDetail ? 'rules-detail-main' : ''}`}>
{/* 应用模块选择器 */}
{/* <div className="app-module-selector py-2 px-4 border-b border-gray-100 flex items-center">
{APP_MODULES.map(app => (