feat: UI优化和功能完善

- 添加公共分页组件,支持上边显示、分页大小10
- 侧边栏/Header按Liner风格优化,添加动画效果
- 异常处理列表支持分页和明细弹窗
- 任务结果页面支持已匹配列表分页
- 修复Dialog弹窗背景透明问题
- 新增dropdown-menu组件
- 添加parsed_file_record模型和回填脚本
- 前端枚举中文化
This commit is contained in:
freedakgmail
2026-07-07 12:57:15 +08:00
parent 78bd27a59a
commit b93929eb1a
24 changed files with 3155 additions and 608 deletions
+57 -36
View File
@@ -33,8 +33,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
AlertTriangle,
import { AlertTriangle,
CheckCircle,
Clock,
Eye,
@@ -42,6 +41,7 @@ import {
XCircle,
} from "lucide-react";
import { api } from "@/lib/api/client";
import { Pagination } from "@/components/ui/pagination";
interface ExceptionItem {
id: number;
@@ -93,6 +93,35 @@ const typeLabels: Record<string, string> = {
duplicate_record: "重复记录",
format_error: "格式错误",
logic_error: "逻辑错误",
rule_violation: "规则违规",
threshold_exceeded: "阈值超限",
missing_employee: "员工缺失",
extra_employee: "多余员工",
amount_difference: "金额差异",
zero_amount: "金额为零",
negative_amount: "负数金额",
unusual_amount: "金额异常",
duplicate_employee: "重复员工",
bank_mismatch: "银行不匹配",
bank_missing: "银行记录缺失",
bank_extra: "银行多余记录",
AMOUNT_MISMATCH: "金额不一致",
MISSING_RECORD: "记录缺失",
DUPLICATE_RECORD: "重复记录",
FORMAT_ERROR: "格式错误",
LOGIC_ERROR: "逻辑错误",
RULE_VIOLATION: "规则违规",
THRESHOLD_EXCEEDED: "阈值超限",
MISSING_EMPLOYEE: "员工缺失",
EXTRA_EMPLOYEE: "多余员工",
AMOUNT_DIFFERENCE: "金额差异",
ZERO_AMOUNT: "金额为零",
NEGATIVE_AMOUNT: "负数金额",
UNUSUAL_AMOUNT: "金额异常",
DUPLICATE_EMPLOYEE: "重复员工",
BANK_MISMATCH: "银行不匹配",
BANK_MISSING: "银行记录缺失",
BANK_EXTRA: "银行多余记录",
};
const container = {
@@ -121,8 +150,8 @@ function ExceptionsContent() {
const [severity, setSeverity] = useState(searchParams.get("severity") || "");
const [exceptionType, setExceptionType] = useState(searchParams.get("type") || "");
const [page, setPage] = useState(Number(searchParams.get("page")) || 1);
const [pageSize] = useState(20);
const [pageSize, setPageSize] = useState(10);
const [selectedException, setSelectedException] = useState<ExceptionItem | null>(null);
const [detailOpen, setDetailOpen] = useState(false);
@@ -130,7 +159,16 @@ function ExceptionsContent() {
fetchExceptions();
fetchSummary();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [taskId, status, severity, exceptionType, page]);
}, [taskId, status, severity, exceptionType]);
function onPageChange(newPage: number, newPageSize: number) {
setPage(newPage);
if (newPageSize !== pageSize) {
setPageSize(newPageSize);
}
fetchExceptions();
fetchSummary();
}
async function fetchExceptions() {
setLoading(true);
@@ -344,6 +382,10 @@ function ExceptionsContent() {
<SelectItem value="duplicate_record"></SelectItem>
<SelectItem value="format_error"></SelectItem>
<SelectItem value="logic_error"></SelectItem>
<SelectItem value="missing_employee"></SelectItem>
<SelectItem value="duplicate_employee"></SelectItem>
<SelectItem value="zero_amount"></SelectItem>
<SelectItem value="unusual_amount"></SelectItem>
</SelectContent>
</Select>
</div>
@@ -371,6 +413,14 @@ function ExceptionsContent() {
</div>
</CardHeader>
<CardContent className="p-0">
{total > 0 && (
<Pagination
page={page}
pageSize={pageSize}
total={total}
onChange={onPageChange}
/>
)}
<Table>
<TableHeader>
<TableRow className="hover:bg-transparent">
@@ -428,7 +478,7 @@ function ExceptionsContent() {
</TableCell>
<TableCell>
<Badge variant="outline" className="font-normal">
{typeLabels[exception.exception_type] || exception.exception_type}
{typeLabels[exception.exception_type] || typeLabels[exception.exception_type.toLowerCase()] || typeLabels[exception.exception_type.toUpperCase()] || exception.exception_type}
</Badge>
</TableCell>
<TableCell>
@@ -473,35 +523,6 @@ function ExceptionsContent() {
)}
</TableBody>
</Table>
{/* Pagination */}
{totalPages > 1 && (
<div className="flex items-center justify-between px-6 py-4 border-t">
<p className="text-caption text-muted-foreground">
{page} {totalPages}
</p>
<div className="flex items-center gap-2">
<Button
variant="outline"
size="sm"
disabled={page <= 1}
onClick={() => setPage(page - 1)}
className="btn-press"
>
</Button>
<Button
variant="outline"
size="sm"
disabled={page >= totalPages}
onClick={() => setPage(page + 1)}
className="btn-press"
>
</Button>
</div>
</div>
)}
</CardContent>
</Card>
</motion.div>
@@ -525,7 +546,7 @@ function ExceptionsContent() {
</div>
<div>
<p className="text-caption text-muted-foreground"></p>
<Badge variant="outline">{typeLabels[selectedException.exception_type] || selectedException.exception_type}</Badge>
<Badge variant="outline">{typeLabels[selectedException.exception_type] || typeLabels[selectedException.exception_type.toLowerCase()] || typeLabels[selectedException.exception_type.toUpperCase()] || selectedException.exception_type}</Badge>
</div>
<div>
<p className="text-caption text-muted-foreground"></p>