oa-frontend-pretrial-cleanup 收敛PC试运行前页面风格

这个提交包含在:
2026-05-26 17:02:21 +08:00
父节点 91304bb40b
当前提交 66b3ceb08f
共修改 19 个文件,包含 193 行新增和 95 行删除
+28 -7
查看文件
@@ -14,7 +14,7 @@ import { useAuth } from "../auth/AuthContext";
import { hasAnyPermission } from "../auth/permissions";
import { DateTextInput } from "../components/common/DateTextInput";
import { StatusBadge } from "../components/common/StatusBadge";
import { FilterBar, ListWorkspace, StatStrip, WorkspaceHeader } from "../components/patterns/ListWorkspace";
import { FilterBar, ListWorkspace, StatStrip, WorkspaceHeader, WorkspaceNotice } from "../components/patterns/ListWorkspace";
import { MetricCard } from "../components/patterns/MetricCard";
import { SectionPanel } from "../components/patterns/SectionPanel";
import { Button } from "../components/ui/button";
@@ -22,6 +22,7 @@ import { Input } from "../components/ui/input";
import { Label } from "../components/ui/label";
import { Textarea } from "../components/ui/textarea";
import { formatDisplayDate } from "../lib/displayFormat";
import { hasTrialNoise } from "../lib/trialNoise";
import { toast } from "sonner";
const STATUS_OPTIONS: Array<{ value: "all" | ProjectStatus; label: string }> = [
@@ -76,6 +77,7 @@ export function ProjectsPage() {
const [startsAt, setStartsAt] = useState("");
const [targetEndAt, setTargetEndAt] = useState("");
const [isConfidential, setIsConfidential] = useState(false);
const [showTrialData, setShowTrialData] = useState(false);
const listQuery = useQuery({
queryKey: ["projects", "list", status, mine, q],
@@ -99,8 +101,18 @@ export function ProjectsPage() {
);
const projectItems = listQuery.data?.items ?? [];
const visibleProjectItems = useMemo(
() =>
showTrialData
? projectItems
: projectItems.filter(
(item) => !hasTrialNoise(item.projectNo, item.name, item.clientName, item.clientAlias, item.summary),
),
[projectItems, showTrialData],
);
const hiddenTrialProjectCount = projectItems.length - visibleProjectItems.length;
const projectStats = useMemo(() => {
return projectItems.reduce(
return visibleProjectItems.reduce(
(acc, item) => {
acc.total += 1;
if (item.status === "active") {
@@ -112,7 +124,7 @@ export function ProjectsPage() {
},
{ total: 0, active: 0, overdueMilestones: 0, openRisks: 0 },
);
}, [projectItems]);
}, [visibleProjectItems]);
const createMutation = useMutation({
mutationFn: () =>
@@ -183,7 +195,7 @@ export function ProjectsPage() {
<div className="page-shell-grid">
<div className="space-y-6">
<FilterBar className="grid gap-3 md:grid-cols-[minmax(0,1fr),180px,160px]">
<FilterBar className="grid gap-3 md:grid-cols-[minmax(0,1fr),180px,160px,160px]">
<Input placeholder="搜索项目编号、项目名、客户名" value={q} onChange={(event) => updateSearch({ q: event.target.value })} />
<select className="select-std" value={status} onChange={(event) => updateSearch({ status: event.target.value })}>
{STATUS_OPTIONS.map((item) => (
@@ -195,18 +207,27 @@ export function ProjectsPage() {
<Button type="button" variant={mine ? "default" : "secondary"} onClick={() => updateSearch({ mine: !mine })}>
{mine ? "只看我的" : "切换到我的"}
</Button>
<Button type="button" variant={showTrialData ? "default" : "secondary"} onClick={() => setShowTrialData((value) => !value)}>
{showTrialData ? "隐藏测试数据" : "显示测试数据"}
</Button>
</FilterBar>
{!showTrialData && hiddenTrialProjectCount > 0 ? (
<WorkspaceNotice title={`已隐藏 ${hiddenTrialProjectCount} 条 TEST/SMOKE 项目`} tone="neutral">
试运行默认只展示正式项目;需要排障时可临时显示测试数据。
</WorkspaceNotice>
) : null}
<SectionPanel
title="项目列表"
description={projectItems.length ? `当前筛出 ${projectItems.length} 个项目` : "按项目名、客户或状态快速缩小范围"}
description={visibleProjectItems.length ? `当前显示 ${visibleProjectItems.length} 个项目` : "按项目名、客户或状态快速缩小范围"}
>
<div className="space-y-4">
{listQuery.isLoading ? <div className="text-sm text-zinc-500">项目加载中...</div> : null}
{listQuery.isError ? <div className="text-sm text-red-600">{resolveError(listQuery.error, "加载项目失败")}</div> : null}
<div className="grid gap-4">
{projectItems.map((item) => (
{visibleProjectItems.map((item) => (
<Link key={item.id} to={`/projects/${item.id}`} className="card-std block space-y-3 p-5 hover:border-primary/40">
<div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
<div>
@@ -228,7 +249,7 @@ export function ProjectsPage() {
<div className="text-sm text-zinc-500">{summaryLine(item)}</div>
</Link>
))}
{!listQuery.isLoading && !projectItems.length ? (
{!listQuery.isLoading && !visibleProjectItems.length ? (
<div className="rounded-xl border border-dashed border-zinc-200 bg-zinc-50 px-4 py-8 text-sm text-zinc-500">
当前没有符合筛选条件的项目。
</div>