"use client"; import { useState, useCallback } from "react"; import { useRouter } from "next/navigation"; import { ArrowLeft, Trash2, ToggleLeft, ToggleRight, Search } from "lucide-react"; import { api } from "@/lib/api/client"; import { ENDPOINTS } from "@/lib/api/endpoints"; import { useToast } from "@/lib/hooks/useToast"; import type { CompanyRuleResponse } from "@/lib/api/types"; // 模拟数据 const mockRules: CompanyRuleResponse[] = [ { id: 1, company_id: 1, rule_type: "FIELD_MAPPING", match_condition: { source_field: "员工姓名" }, target_value: "员工姓名", priority: 0, status: "ACTIVE", description: "工资表员工姓名字段映射", match_count: 15, last_used_at: "2024-01-15T10:30:00Z", created_at: "2024-01-01T00:00:00Z", updated_at: "2024-01-15T10:30:00Z", }, { id: 2, company_id: 1, rule_type: "FIELD_MAPPING", match_condition: { source_field: "基本薪资" }, target_value: "基本工资", priority: 0, status: "ACTIVE", description: "工资表基本薪资字段映射", match_count: 12, last_used_at: "2024-01-15T10:30:00Z", created_at: "2024-01-05T00:00:00Z", updated_at: "2024-01-15T10:30:00Z", }, { id: 3, company_id: 1, rule_type: "FIELD_MAPPING", match_condition: { source_field: "实发合计" }, target_value: "实发工资", priority: 1, status: "INACTIVE", description: "工资表实发合计字段映射(已停用)", match_count: 8, last_used_at: "2024-01-10T00:00:00Z", created_at: "2024-01-08T00:00:00Z", updated_at: "2024-01-12T00:00:00Z", }, ]; const RULE_TYPE_LABELS: Record = { FIELD_MAPPING: "字段映射", ACCOUNT_MAPPING: "科目映射", DEPARTMENT_MAPPING: "部门映射", }; export default function RulesPage() { const router = useRouter(); const toast = useToast(); const [rules, setRules] = useState(mockRules); const [searchQuery, setSearchQuery] = useState(""); const [typeFilter, setTypeFilter] = useState(""); const [statusFilter, setStatusFilter] = useState(""); // 过滤规则 const filteredRules = rules.filter((rule) => { const matchesSearch = !searchQuery || rule.match_condition.source_field?.toLowerCase().includes(searchQuery.toLowerCase()) || rule.target_value.toLowerCase().includes(searchQuery.toLowerCase()) || rule.description?.toLowerCase().includes(searchQuery.toLowerCase()); const matchesType = !typeFilter || rule.rule_type === typeFilter; const matchesStatus = !statusFilter || rule.status === statusFilter; return matchesSearch && matchesType && matchesStatus; }); // 切换规则状态 const handleToggleStatus = useCallback( async (ruleId: number, currentStatus: string) => { const newStatus = currentStatus === "ACTIVE" ? "INACTIVE" : "ACTIVE"; try { await api.patch(ENDPOINTS.MAPPING.RULE_STATUS(ruleId), { status: newStatus, }); setRules((prev) => prev.map((rule) => rule.id === ruleId ? { ...rule, status: newStatus } : rule ) ); toast.success(`规则已${newStatus === "ACTIVE" ? "启用" : "停用"}`); } catch { toast.error("状态更新失败"); } }, [toast] ); // 删除规则 const handleDeleteRule = useCallback( async (ruleId: number) => { if (!confirm("确定要删除这条规则吗?")) return; try { await api.delete(ENDPOINTS.MAPPING.RULE_DELETE(ruleId)); setRules((prev) => prev.filter((rule) => rule.id !== ruleId)); toast.success("规则已删除"); } catch { toast.error("删除失败"); } }, [toast] ); const activeCount = rules.filter((r) => r.status === "ACTIVE").length; const inactiveCount = rules.filter((r) => r.status === "INACTIVE").length; return (
{/* 页面头部 */}

规则管理

管理企业字段映射规则,实现自动识别

{/* 统计卡片 */}
{rules.length}
总规则数
{activeCount}
启用中
{inactiveCount}
已停用
{/* 筛选栏 */}
setSearchQuery(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" />
{/* 规则列表 */}
{filteredRules.map((rule) => ( ))}
规则类型 匹配条件 目标字段 匹配次数 状态 最近使用 操作
{RULE_TYPE_LABELS[rule.rule_type] || rule.rule_type} {rule.match_condition.source_field || JSON.stringify(rule.match_condition)} {rule.target_value} {rule.match_count} {rule.status === "ACTIVE" ? "启用" : "停用"} {rule.last_used_at ? new Date(rule.last_used_at).toLocaleDateString("zh-CN") : "-"}
{filteredRules.length === 0 && (
暂无规则数据
)}
{/* 说明 */}

规则说明

  • • 字段映射规则会在上传同类文件时自动应用
  • • 精确匹配的规则(完全相同的字段名)会优先于模糊匹配
  • • 停用规则不会在自动识别中应用,但不会删除
  • • 删除规则后,下次上传相同格式文件需要重新确认映射
); }