统一页面右上角操作区(05-31-unified-page-header-actions)

这个提交包含在:
2026-05-31 16:41:44 +08:00
父节点 b71d23e661
当前提交 dcf34d7ac6
共修改 18 个文件,包含 480 行新增和 183 行删除
+61 -54
查看文件
@@ -25,7 +25,7 @@ import { ActionConfirmDialog } from "../components/common/ActionConfirmDialog";
import { PageHeader } from "../components/common/PageHeader";
import { StatusBadge } from "../components/common/StatusBadge";
import { DateTextInput } from "../components/common/DateTextInput";
import { WorkspaceNotice } from "../components/patterns/ListWorkspace";
import { HeaderActionGroup, WorkspaceNotice } from "../components/patterns/ListWorkspace";
import {
BusinessListToolbar,
BusinessMobileList,
@@ -334,12 +334,7 @@ export function ContractsRegistryPage() {
<PageHeader
title="合同"
actions={
<div className="flex flex-wrap gap-2">
{initialProjectId ? (
<Button asChild variant="secondary" type="button">
<Link to="/projects">返回项目</Link>
</Button>
) : null}
<HeaderActionGroup>
<Button
type="button"
onClick={() => {
@@ -349,37 +344,7 @@ export function ContractsRegistryPage() {
>
新增合同
</Button>
<Button
type="button"
variant={showExpiring ? "default" : "secondary"}
disabled={expiringQuery.isLoading}
onClick={() => setShowExpiring((value) => !value)}
>
到期列表 {expiringContractCount}
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button type="button" variant="secondary" disabled={exportMutation.isPending}>
{exportMutation.isPending ? "导出中..." : "导出"}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onSelect={() => setConfirmExportFormat("csv")}>
导出 CSV
</DropdownMenuItem>
<DropdownMenuItem onSelect={() => setConfirmExportFormat("xlsx")}>
导出 Excel
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<Button
type="button"
variant={showAdvancedFilters || filters.expiryDateFrom || filters.expiryDateTo || showTrialData ? "default" : "secondary"}
onClick={() => setShowAdvancedFilters((value) => !value)}
>
筛选
</Button>
</div>
</HeaderActionGroup>
}
/>
@@ -672,27 +637,48 @@ export function ContractsRegistryPage() {
<>
<Button
type="button"
variant="secondary"
onClick={() => {
setFilters({
projectId: initialProjectId,
status: "",
contractType: "",
counterpartyName: "",
expiryDateFrom: "",
expiryDateTo: "",
});
setShowEditor(false);
setEditorId(null);
setEditor(buildEmptyEditor(initialProjectId));
}}
size="sm"
variant={showAdvancedFilters || filters.expiryDateFrom || filters.expiryDateTo || showTrialData ? "default" : "secondary"}
onClick={() => setShowAdvancedFilters((value) => !value)}
>
重置筛选
筛选
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button type="button" size="sm" variant={showExpiring ? "default" : "secondary"}>
更多
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{initialProjectId ? (
<DropdownMenuItem asChild>
<Link to="/projects">返回项目</Link>
</DropdownMenuItem>
) : null}
<DropdownMenuItem
disabled={expiringQuery.isLoading}
onSelect={() => setShowExpiring((value) => !value)}
>
{showExpiring ? "退出到期列表" : `到期列表 ${expiringContractCount}`}
</DropdownMenuItem>
<DropdownMenuItem
disabled={exportMutation.isPending}
onSelect={() => setConfirmExportFormat("csv")}
>
导出 CSV
</DropdownMenuItem>
<DropdownMenuItem
disabled={exportMutation.isPending}
onSelect={() => setConfirmExportFormat("xlsx")}
>
导出 Excel
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
}
advanced={showAdvancedFilters || filters.expiryDateFrom || filters.expiryDateTo || showTrialData ? (
<div className="grid gap-3 md:grid-cols-[160px_160px_auto] xl:grid-cols-[180px_180px_auto]" data-testid="contracts-advanced-filters">
<div className="grid gap-3 md:grid-cols-[160px_160px_auto_auto] xl:grid-cols-[180px_180px_auto_auto]" data-testid="contracts-advanced-filters">
<div className="space-y-2">
<Label>到期日开始</Label>
<DateTextInput
@@ -714,6 +700,27 @@ export function ContractsRegistryPage() {
{showTrialData ? "隐藏测试数据" : "显示测试数据"}
</Button>
</div>
<div className="flex items-end">
<Button
type="button"
variant="secondary"
onClick={() => {
setFilters({
projectId: initialProjectId,
status: "",
contractType: "",
counterpartyName: "",
expiryDateFrom: "",
expiryDateTo: "",
});
setShowEditor(false);
setEditorId(null);
setEditor(buildEmptyEditor(initialProjectId));
}}
>
重置筛选
</Button>
</div>
</div>
) : null}
>