优化财务与管理页视觉 Wave4(05-27-pc-finance-admin-visual-wave4)
这个提交包含在:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { isApiError } from "../api/types";
|
||||
import { mapApiErrorMessage } from "../api/errorMessages";
|
||||
@@ -436,6 +436,16 @@ export function InvoicePoolPage() {
|
||||
|
||||
const totalPages = Math.max(1, Math.ceil((listQuery.data?.total ?? 0) / PAGE_SIZE));
|
||||
const detail = detailQuery.data;
|
||||
const invoiceStats = useMemo(() => {
|
||||
const items = listQuery.data?.items ?? [];
|
||||
return {
|
||||
total: listQuery.data?.total ?? 0,
|
||||
pending: items.filter((item) => item.status === "pending_ocr").length,
|
||||
failed: items.filter((item) => item.status === "ocr_failed").length,
|
||||
available: items.filter((item) => item.status === "available").length,
|
||||
bound: items.filter((item) => item.status === "bound").length,
|
||||
};
|
||||
}, [listQuery.data?.items, listQuery.data?.total]);
|
||||
const canEditDetail = Boolean(
|
||||
detail &&
|
||||
(canManageInvoice ||
|
||||
@@ -449,7 +459,7 @@ export function InvoicePoolPage() {
|
||||
<ListWorkspace>
|
||||
<WorkspaceHeader
|
||||
title="票据中心"
|
||||
subtitle="上传、识别、绑定。"
|
||||
subtitle="上传、识别、绑定和异常复核集中处理。"
|
||||
actions={
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -480,6 +490,29 @@ export function InvoicePoolPage() {
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
<div className="finance-status-strip" data-testid="invoice-pool-summary">
|
||||
<div className="finance-metric-card">
|
||||
<div className="finance-metric-card__label">票据总数</div>
|
||||
<div className="finance-metric-card__value">{invoiceStats.total}</div>
|
||||
</div>
|
||||
<div className="finance-metric-card">
|
||||
<div className="finance-metric-card__label">识别中</div>
|
||||
<div className="finance-metric-card__value">{invoiceStats.pending}</div>
|
||||
</div>
|
||||
<div className="finance-metric-card">
|
||||
<div className="finance-metric-card__label">识别失败</div>
|
||||
<div className="finance-metric-card__value">{invoiceStats.failed}</div>
|
||||
</div>
|
||||
<div className="finance-metric-card">
|
||||
<div className="finance-metric-card__label">可绑定</div>
|
||||
<div className="finance-metric-card__value">{invoiceStats.available}</div>
|
||||
</div>
|
||||
<div className="finance-metric-card">
|
||||
<div className="finance-metric-card__label">已绑定</div>
|
||||
<div className="finance-metric-card__value">{invoiceStats.bound}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<InvoiceUploadCard
|
||||
selectedFiles={selectedFiles}
|
||||
setSelectedFiles={setSelectedFiles}
|
||||
|
||||
在新工单中引用
屏蔽一个用户