diff --git a/client/src/lib/testIds.ts b/client/src/lib/testIds.ts new file mode 100644 index 00000000..23a1e91e --- /dev/null +++ b/client/src/lib/testIds.ts @@ -0,0 +1,51 @@ +export const TEST_IDS = { + login: { + identifier: "login-identifier", + password: "login-password", + submit: "login-submit", + }, + topbar: { + profileTrigger: "topbar-profile-trigger", + }, + workflow: { + tasksTable: "workflow-tasks-table", + taskRow: "workflow-task-row", + detailLink: "workflow-task-detail-link", + summary: "workflow-task-summary", + approve: "workflow-task-approve", + reject: "workflow-task-reject", + rejectComment: "workflow-task-reject-comment", + returnBtn: "workflow-task-return", + returnComment: "workflow-task-return-comment", + transferApprover: "workflow-task-transfer-approver", + transferReason: "workflow-task-transfer-reason", + transferBtn: "workflow-task-transfer", + actionError: "workflow-task-action-error", + overview: "workflow-task-overview", + }, + reimbursement: { + summary: "reimbursement-summary", + items: "reimbursement-items", + itemAdd: "reimbursement-item-add", + submit: "reimbursement-submit", + withdraw: "reimbursement-withdraw", + pay: "reimbursement-pay", + budgetHint: "reimbursement-budget-hint", + erpExport: "reimbursement-erp-export", + overview: "reimbursement-overview", + }, + weeklyReport: { + save: "weekly-report-save", + submit: "weekly-report-submit", + createTodo: "weekly-report-create-todo", + }, + todo: { + createTitle: "todo-create-title", + createSubmit: "todo-create-submit", + row: "todo-row", + complete: "todo-complete", + }, + audit: { + export: "audit-export", + }, +} as const; diff --git a/client/src/pages/ReimbursementDetailPage.tsx b/client/src/pages/ReimbursementDetailPage.tsx index df721875..63848e52 100644 --- a/client/src/pages/ReimbursementDetailPage.tsx +++ b/client/src/pages/ReimbursementDetailPage.tsx @@ -23,11 +23,15 @@ import { useAuth } from "../auth/AuthContext"; import { hasPermission } from "../auth/permissions"; import { CardSkeleton } from "../components/common/CardSkeleton"; import { ConfirmDialog } from "../components/common/ConfirmDialog"; -import { PageHeader } from "../components/common/PageHeader"; import { RiskFlagsCard } from "../components/common/RiskFlagsCard"; +import { StatusBadge } from "../components/common/StatusBadge"; import { AiSuggestionCard } from "../components/ai/AiSuggestionCard"; import { Button } from "../components/ui/button"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../components/ui/table"; +import { DetailSideMeta } from "../components/patterns/DetailSideMeta"; +import { EntityOverviewHero } from "../components/patterns/EntityOverviewHero"; +import { PageScaffold } from "../components/patterns/PageScaffold"; +import { SectionPanel } from "../components/patterns/SectionPanel"; import { ReimbursementActions, type PayPayload } from "./reimbursement-detail/ReimbursementActions"; import { ReimbursementItemEditor, @@ -80,7 +84,7 @@ export function ReimbursementDetailPage() { const erpPreviewQuery = useQuery({ enabled: Boolean(reimbursementId) && canManageIntegration && detailQuery.data?.status === "paid", - queryKey: ["reimbursements", reimbursementId, "erp-journal-preview"], + queryKey: ["reimbursements", reimbursementId, "integration-journal-preview"], queryFn: () => previewReimbursementJournal(reimbursementId), }); @@ -247,7 +251,7 @@ export function ReimbursementDetailPage() { }, onSuccess: async (result) => { await Promise.all([ - queryClient.invalidateQueries({ queryKey: ["reimbursements", reimbursementId, "erp-journal-preview"] }), + queryClient.invalidateQueries({ queryKey: ["reimbursements", reimbursementId, "integration-journal-preview"] }), queryClient.invalidateQueries({ queryKey: ["reimbursements", reimbursementId] }), ]); setActionError(""); @@ -390,128 +394,91 @@ export function ReimbursementDetailPage() { }; return ( -
报销可选挂到项目,用于项目执行面板汇总。
-- 当前金额将超出预算上限,提交时会被阻断(block 模式)。 -
- ) : budgetHint.exceedsThreshold ? ( -- 当前金额已达到预算预警阈值,提交后会记录预算预警审计。 -
- ) : ( -当前预算充足,可继续提交。
- )} -已付款报销单会按标准凭证切片通过 Outbox 异步发送到财务桥接出口。
-正在加载凭证切片预览...
: null} - {erpPreviewQuery.isError ? ( -- {isApiError(erpPreviewQuery.error) - ? `${erpPreviewQuery.error.code}: ${mapApiErrorMessage( - erpPreviewQuery.error.code, - erpPreviewQuery.error.details, - erpPreviewQuery.error.message, - )}` - : "加载财务桥接预览失败"} -
- ) : null} - - {erpPreviewQuery.data ? ( -报销可选挂到项目,用于项目执行面板汇总。
+暂无关联票据
- )} + +暂无关联票据
+ )} ++ 当前金额将超出预算上限,提交时会被阻断(block 模式)。 +
+ ) : budgetHint.exceedsThreshold ? ( ++ 当前金额已达到预算预警阈值,提交后会记录预算预警审计。 +
+ ) : ( +当前预算充足,可继续提交。
+ )} +已付款报销单会按标准凭证切片通过 Outbox 异步发送到财务桥接出口。
+正在加载凭证切片预览...
: null} + {erpPreviewQuery.isError ? ( ++ {isApiError(erpPreviewQuery.error) + ? `${erpPreviewQuery.error.code}: ${mapApiErrorMessage( + erpPreviewQuery.error.code, + erpPreviewQuery.error.details, + erpPreviewQuery.error.message, + )}` + : "加载财务桥接预览失败"} +
+ ) : null} + + {erpPreviewQuery.data ? ( +- {actionError} -
- ) : null} - -驳回
-退回
-转审
- -暂无历史记录
- )} + ++ {actionError} +
+ ) : null} + +驳回
+退回
+转审
+ +暂无历史记录
+ )} +