import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/Components/ui/table"; import { Badge } from "@/Components/ui/badge"; import { Eye, ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react'; import { Button } from '@/Components/ui/button'; export interface Activity { id: number; description: string; subject_type: string; event: string; causer: string; created_at: string; properties: any; } interface LogTableProps { activities: Activity[]; sortField?: string; sortOrder?: 'asc' | 'desc'; onSort?: (field: string) => void; onViewDetail: (activity: Activity) => void; from?: number; // 起始索引編號 (paginator.from) } // 主體類型解析 (Model 類名轉中文) const subjectTypeMap: Record = { // 完整路徑映射 'App\\Modules\\Inventory\\Models\\Product': '商品資料', 'App\\Modules\\Inventory\\Models\\Warehouse': '倉庫資料', 'App\\Modules\\Inventory\\Models\\Inventory': '庫存異動', 'App\\Modules\\Inventory\\Models\\Category': '商品分類', 'App\\Modules\\Inventory\\Models\\Unit': '單位', 'App\\Modules\\Inventory\\Models\\InventoryTransaction': '庫存異動紀錄', 'App\\Modules\\Inventory\\Models\\GoodsReceipt': '進貨單', 'App\\Modules\\Inventory\\Models\\InventoryCountDoc': '庫存盤點單', 'App\\Modules\\Inventory\\Models\\InventoryAdjustDoc': '庫存盤調單', 'App\\Modules\\Inventory\\Models\\InventoryTransferOrder': '庫存調撥單', 'App\\Modules\\Inventory\\Models\\StockMovementDoc': '庫存單據', 'App\\Modules\\Procurement\\Models\\Vendor': '廠商資料', 'App\\Modules\\Procurement\\Models\\PurchaseOrder': '採購單', 'App\\Modules\\Production\\Models\\ProductionOrder': '生產工單', 'App\\Modules\\Production\\Models\\Recipe': '生產配方', 'App\\Modules\\Production\\Models\\RecipeItem': '配方品項', 'App\\Modules\\Production\\Models\\ProductionOrderItem': '工單品項', 'App\\Modules\\Finance\\Models\\UtilityFee': '公共事業費', 'App\\Modules\\Core\\Models\\User': '使用者帳號', 'App\\Modules\\Core\\Models\\Role': '角色權限', // 簡寫映射 'Product': '商品資料', 'Warehouse': '倉庫資料', 'Inventory': '庫存異動', 'InventoryTransaction': '庫存異動紀錄', 'Category': '商品分類', 'Unit': '單位', 'Vendor': '廠商資料', 'PurchaseOrder': '採購單', 'GoodsReceipt': '進貨單', 'ProductionOrder': '生產工單', 'Recipe': '生產配方', 'InventoryCountDoc': '庫存盤點單', 'InventoryAdjustDoc': '庫存盤調單', 'InventoryTransferOrder': '庫存調撥單', 'StockMovementDoc': '庫存單據', 'User': '使用者帳號', 'Role': '角色權限', 'UtilityFee': '公共事業費', }; export default function LogTable({ activities, sortField, sortOrder, onSort, onViewDetail, from = 1 }: LogTableProps) { const getSubjectTypeLabel = (type: string) => subjectTypeMap[type] || type; const getEventBadgeClass = (event: string) => { switch (event) { case 'created': return 'bg-green-50 text-green-700 border-green-200 hover:bg-green-100'; case 'updated': return 'bg-blue-50 text-blue-700 border-blue-200 hover:bg-blue-100'; case 'deleted': return 'bg-red-50 text-red-700 border-red-200 hover:bg-red-100'; default: return 'bg-gray-50 text-gray-700 border-gray-200 hover:bg-gray-100'; } }; const getEventLabel = (event: string) => { switch (event) { case 'created': return '新增'; case 'updated': return '更新'; case 'deleted': return '刪除'; default: return event; } }; const getDescription = (activity: Activity) => { const props = activity.properties || {}; const attrs = props.attributes || {}; const old = props.old || {}; const snapshot = props.snapshot || {}; // 嘗試在快照、屬性或舊值中尋找名稱 // 優先順序:快照 > 特定名稱欄位 > 通用名稱 > 代碼 > ID const nameParams = ['doc_no', 'po_number', 'name', 'code', 'product_name', 'warehouse_name', 'category_name', 'base_unit_name', 'title', 'category']; let subjectName = ''; // 庫存的特殊處理:顯示 "倉庫 - 商品" if ((snapshot.warehouse_name || attrs.warehouse_name) && (snapshot.product_name || attrs.product_name)) { const wName = snapshot.warehouse_name || attrs.warehouse_name; const pName = snapshot.product_name || attrs.product_name; subjectName = `${wName} - ${pName}`; } else if (old.warehouse_name && old.product_name) { subjectName = `${old.warehouse_name} - ${old.product_name}`; } else { // 預設備案 for (const param of nameParams) { if (snapshot[param]) { subjectName = snapshot[param]; break; } if (attrs[param]) { subjectName = attrs[param]; break; } if (old[param]) { subjectName = old[param]; break; } } } // 如果找不到名稱,嘗試使用 ID,如果可能則格式化顯示,或者如果與主題類型重複則不顯示 if (!subjectName && (attrs.id || old.id)) { subjectName = `#${attrs.id || old.id}`; } // 組合部分:[操作者] [動作] [名稱] [主題] // Example: Admin 新增 可樂 商品 // Example: Admin 更新 台北倉 - 可樂 庫存 return ( {activity.causer} {getEventLabel(activity.event)} {subjectName && ( {subjectName} )} {props.sub_subject ? ( {props.sub_subject} ) : ( {getSubjectTypeLabel(activity.subject_type)} )} {/* 如果有原因/來源則顯示(例如:來自補貨) */} {(attrs._reason || old._reason) && ( (來自 {attrs._reason || old._reason}) )} ); }; const SortIcon = ({ field }: { field: string }) => { if (!onSort) return null; if (sortField !== field) { return ; } if (sortOrder === "asc") { return ; } return ; }; return (
# {onSort ? ( ) : ( "時間" )} 操作人員 描述 動作 操作對象 操作 {activities.length > 0 ? ( activities.map((activity, index) => ( {from + index} {activity.created_at} {activity.causer}
{getDescription(activity)}
{getEventLabel(activity.event)} {getSubjectTypeLabel(activity.subject_type)}
)) ) : ( 尚無操作紀錄 )}
); }