oa-frontend-pretrial-cleanup 收敛PC试运行前页面风格
这个提交包含在:
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Link, useSearchParams } from "react-router-dom";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import {
|
||||
@@ -24,12 +24,14 @@ import { hasAnyPermission } from "../auth/permissions";
|
||||
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 { Button } from "../components/ui/button";
|
||||
import { Input } from "../components/ui/input";
|
||||
import { Label } from "../components/ui/label";
|
||||
import { Textarea } from "../components/ui/textarea";
|
||||
import { downloadBlob } from "../lib/download";
|
||||
import { formatDisplayDate } from "../lib/displayFormat";
|
||||
import { hasTrialNoise } from "../lib/trialNoise";
|
||||
import { toast } from "sonner";
|
||||
|
||||
const CONFIDENTIALITY_OPTIONS: ConfidentialityLevel[] = ["public", "internal", "confidential", "restricted"];
|
||||
@@ -200,6 +202,7 @@ export function ContractsRegistryPage() {
|
||||
const [editorId, setEditorId] = useState<string | null>(null);
|
||||
const [editor, setEditor] = useState<EditorState>(() => buildEmptyEditor(initialProjectId));
|
||||
const [showExpiring, setShowExpiring] = useState(false);
|
||||
const [showTrialData, setShowTrialData] = useState(false);
|
||||
|
||||
const filterPayload = buildFiltersPayload(filters);
|
||||
const contractsQuery = useQuery({
|
||||
@@ -223,6 +226,16 @@ export function ContractsRegistryPage() {
|
||||
const projectOptions = projectsQuery.data?.items ?? [];
|
||||
const employeeOptions = canBrowseEmployees ? employeesQuery.data?.items ?? [] : [];
|
||||
const contracts = contractsQuery.data?.items ?? [];
|
||||
const visibleContracts = useMemo(
|
||||
() =>
|
||||
showTrialData
|
||||
? contracts
|
||||
: contracts.filter(
|
||||
(item) => !hasTrialNoise(item.contractNo, item.counterpartyName, item.summary, item.project?.name),
|
||||
),
|
||||
[contracts, showTrialData],
|
||||
);
|
||||
const hiddenTrialContractCount = contracts.length - visibleContracts.length;
|
||||
const expiringItems = expiringQuery.data?.items ?? [];
|
||||
const editingItem = editorId ? contracts.find((item) => item.id === editorId) ?? null : null;
|
||||
const readonlyOwnerLabel = editingItem?.owner
|
||||
@@ -633,24 +646,29 @@ export function ContractsRegistryPage() {
|
||||
<h3 className="text-base font-semibold text-zinc-900">台账列表</h3>
|
||||
<div className="mt-1 text-sm text-zinc-500">{filters.projectId ? "已按项目过滤" : "显示全部可见合同"}</div>
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
setFilters({
|
||||
projectId: initialProjectId,
|
||||
status: "",
|
||||
contractType: "",
|
||||
counterpartyName: "",
|
||||
expiryDateFrom: "",
|
||||
expiryDateTo: "",
|
||||
});
|
||||
setEditorId(null);
|
||||
setEditor(buildEmptyEditor(initialProjectId));
|
||||
}}
|
||||
>
|
||||
重置筛选
|
||||
</Button>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
setFilters({
|
||||
projectId: initialProjectId,
|
||||
status: "",
|
||||
contractType: "",
|
||||
counterpartyName: "",
|
||||
expiryDateFrom: "",
|
||||
expiryDateTo: "",
|
||||
});
|
||||
setEditorId(null);
|
||||
setEditor(buildEmptyEditor(initialProjectId));
|
||||
}}
|
||||
>
|
||||
重置筛选
|
||||
</Button>
|
||||
<Button type="button" variant={showTrialData ? "default" : "secondary"} onClick={() => setShowTrialData((value) => !value)}>
|
||||
{showTrialData ? "隐藏测试数据" : "显示测试数据"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
|
||||
@@ -733,8 +751,14 @@ export function ContractsRegistryPage() {
|
||||
<div className="text-sm text-red-600">{resolveError(contractsQuery.error, "加载合同台账失败")}</div>
|
||||
) : null}
|
||||
|
||||
{!showTrialData && hiddenTrialContractCount > 0 ? (
|
||||
<WorkspaceNotice title={`已隐藏 ${hiddenTrialContractCount} 条 TEST/SMOKE 合同`} tone="neutral">
|
||||
试运行默认只展示正式合同;需要核对测试样本时可临时显示。
|
||||
</WorkspaceNotice>
|
||||
) : null}
|
||||
|
||||
<div className="space-y-3">
|
||||
{contracts.map((item) => (
|
||||
{visibleContracts.map((item) => (
|
||||
<div key={item.id} className="rounded-lg border border-zinc-200 p-4">
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-start md:justify-between">
|
||||
<div className="space-y-2">
|
||||
@@ -802,7 +826,7 @@ export function ContractsRegistryPage() {
|
||||
</div>
|
||||
))}
|
||||
|
||||
{!contractsQuery.isLoading && !contracts.length ? (
|
||||
{!contractsQuery.isLoading && !visibleContracts.length ? (
|
||||
<div className="text-sm text-zinc-500">暂无符合筛选条件的合同台账。</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
在新工单中引用
屏蔽一个用户