feat(ui): add serial number columns to cleaner operation history

- Add order-level serial number column in order table
- Add material-level serial number column in material details table
- Update colSpan from 10 to 11 to accommodate new column
This commit is contained in:
Misaka_Company
2026-04-14 14:01:21 +08:00
parent 1f033eb315
commit 4ce5b91340

View File

@@ -270,9 +270,7 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
} }
const filteredOrders = const filteredOrders =
currentAttempt !== undefined currentAttempt !== undefined ? orders.filter((o) => o.attemptNumber === currentAttempt) : orders
? orders.filter((o) => o.attemptNumber === currentAttempt)
: orders
return ( return (
<div className="border border-gray-200 rounded-lg overflow-hidden"> <div className="border border-gray-200 rounded-lg overflow-hidden">
@@ -291,9 +289,7 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
<div className="flex-1 grid grid-cols-7 gap-3 text-sm"> <div className="flex-1 grid grid-cols-7 gap-3 text-sm">
<div> <div>
<div className="text-gray-500 text-xs"></div> <div className="text-gray-500 text-xs"></div>
<div className="font-medium text-gray-900"> <div className="font-medium text-gray-900">{formatDateTime(batch.operationTime)}</div>
{formatDateTime(batch.operationTime)}
</div>
</div> </div>
<div> <div>
<div className="text-gray-500 text-xs"></div> <div className="text-gray-500 text-xs"></div>
@@ -318,9 +314,7 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
</div> </div>
<div> <div>
<div className="text-gray-500 text-xs"></div> <div className="text-gray-500 text-xs"></div>
<div className="font-medium text-green-600"> <div className="font-medium text-green-600">{batch.totalMaterialsDeleted}</div>
{batch.totalMaterialsDeleted}
</div>
</div> </div>
<div> <div>
<div className="text-gray-500 text-xs"></div> <div className="text-gray-500 text-xs"></div>
@@ -389,24 +383,16 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
)} )}
<div className="flex flex-wrap gap-4 text-xs text-gray-600"> <div className="flex flex-wrap gap-4 text-xs text-gray-600">
{executions {executions
.filter( .filter((e) => currentAttempt === undefined || e.attemptNumber === currentAttempt)
(e) =>
currentAttempt === undefined ||
e.attemptNumber === currentAttempt
)
.map((exec) => ( .map((exec) => (
<React.Fragment key={exec.attemptNumber}> <React.Fragment key={exec.attemptNumber}>
<span> <span>{formatDuration(exec.operationTime, exec.endTime)}</span>
{formatDuration(exec.operationTime, exec.endTime)}
</span>
<span> <span>
{exec.ordersProcessed}/{exec.totalOrders} {exec.ordersProcessed}/{exec.totalOrders}
</span> </span>
<span>{exec.totalMaterialsDeleted}</span> <span>{exec.totalMaterialsDeleted}</span>
{exec.totalMaterialsFailed > 0 && ( {exec.totalMaterialsFailed > 0 && (
<span className="text-red-600"> <span className="text-red-600">{exec.totalMaterialsFailed}</span>
{exec.totalMaterialsFailed}
</span>
)} )}
{exec.totalUncertainDeletions > 0 && ( {exec.totalUncertainDeletions > 0 && (
<span className="text-amber-600"> <span className="text-amber-600">
@@ -419,9 +405,7 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
{exec.errorMessage.length > 80 ? '...' : ''} {exec.errorMessage.length > 80 ? '...' : ''}
</span> </span>
)} )}
{exec.appVersion && ( {exec.appVersion && <span className="text-gray-400">v{exec.appVersion}</span>}
<span className="text-gray-400">v{exec.appVersion}</span>
)}
</React.Fragment> </React.Fragment>
))} ))}
</div> </div>
@@ -435,9 +419,10 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
<thead className="bg-gray-50"> <thead className="bg-gray-50">
<tr> <tr>
<th className="px-4 py-2 text-left font-medium text-gray-600 w-8" /> <th className="px-4 py-2 text-left font-medium text-gray-600 w-8" />
<th className="px-4 py-2 text-left font-medium text-gray-600"> <th className="px-4 py-2 text-left font-medium text-gray-600 w-12 text-center">
</th> </th>
<th className="px-4 py-2 text-left font-medium text-gray-600"></th>
<th className="px-4 py-2 text-left font-medium text-gray-600"> <th className="px-4 py-2 text-left font-medium text-gray-600">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -446,38 +431,21 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
onClick={() => handleCopyColumn('orderNumber')} onClick={() => handleCopyColumn('orderNumber')}
title="复制所有订单号" title="复制所有订单号"
> >
<Copy <Copy size={14} className="text-gray-500 hover:text-gray-700" />
size={14}
className="text-gray-500 hover:text-gray-700"
/>
</button> </button>
</div> </div>
</th> </th>
<th className="px-4 py-2 text-left font-medium text-gray-600"> <th className="px-4 py-2 text-left font-medium text-gray-600"></th>
<th className="px-4 py-2 text-left font-medium text-gray-600"></th>
</th> <th className="px-4 py-2 text-left font-medium text-gray-600"></th>
<th className="px-4 py-2 text-left font-medium text-gray-600"> <th className="px-4 py-2 text-left font-medium text-gray-600"></th>
<th className="px-4 py-2 text-left font-medium text-gray-600"></th>
</th> <th className="px-4 py-2 text-left font-medium text-gray-600"></th>
<th className="px-4 py-2 text-left font-medium text-gray-600"> <th className="px-4 py-2 text-left font-medium text-gray-600"></th>
</th>
<th className="px-4 py-2 text-left font-medium text-gray-600">
</th>
<th className="px-4 py-2 text-left font-medium text-gray-600">
</th>
<th className="px-4 py-2 text-left font-medium text-gray-600">
</th>
<th className="px-4 py-2 text-left font-medium text-gray-600">
</th>
</tr> </tr>
</thead> </thead>
<tbody className="divide-y divide-gray-100"> <tbody className="divide-y divide-gray-100">
{filteredOrders.map((order) => { {filteredOrders.map((order, index) => {
const orderKey = `${currentAttempt ?? order.attemptNumber}:${order.orderNumber}` const orderKey = `${currentAttempt ?? order.attemptNumber}:${order.orderNumber}`
const isOrderExpanded = expandedOrders.has(orderKey) const isOrderExpanded = expandedOrders.has(orderKey)
const materials = orderMaterials.get(orderKey) || [] const materials = orderMaterials.get(orderKey) || []
@@ -501,6 +469,9 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
<ChevronRight size={14} className="text-gray-400" /> <ChevronRight size={14} className="text-gray-400" />
)} )}
</td> </td>
<td className="px-4 py-2 text-gray-500 font-medium text-xs text-center">
{index + 1}
</td>
<td className="px-4 py-2 text-gray-900 font-mono text-xs"> <td className="px-4 py-2 text-gray-900 font-mono text-xs">
{order.productionId || '-'} {order.productionId || '-'}
</td> </td>
@@ -541,15 +512,9 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
<span className="text-gray-400 text-xs">-</span> <span className="text-gray-400 text-xs">-</span>
)} )}
</td> </td>
<td className="px-4 py-2 text-green-600"> <td className="px-4 py-2 text-green-600">{order.materialsDeleted}</td>
{order.materialsDeleted} <td className="px-4 py-2 text-gray-500">{order.materialsSkipped}</td>
</td> <td className="px-4 py-2 text-red-600">{order.materialsFailed || '-'}</td>
<td className="px-4 py-2 text-gray-500">
{order.materialsSkipped}
</td>
<td className="px-4 py-2 text-red-600">
{order.materialsFailed || '-'}
</td>
<td className="px-4 py-2 text-amber-600"> <td className="px-4 py-2 text-amber-600">
{order.uncertainDeletions || '-'} {order.uncertainDeletions || '-'}
</td> </td>
@@ -561,30 +526,25 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
{/* Material details */} {/* Material details */}
{isOrderExpanded && ( {isOrderExpanded && (
<tr> <tr>
<td colSpan={10} className="bg-gray-50/50 px-8 py-3"> <td colSpan={11} className="bg-gray-50/50 px-8 py-3">
{isLoadingMaterials ? ( {isLoadingMaterials ? (
<div className="text-xs text-gray-500"> <div className="text-xs text-gray-500">...</div>
...
</div>
) : materials.length > 0 ? ( ) : materials.length > 0 ? (
<table className="w-full text-xs"> <table className="w-full text-xs">
<thead> <thead>
<tr className="text-gray-500"> <tr className="text-gray-500">
<th className="px-3 py-1.5 text-left font-medium w-12 text-center">
</th>
<th className="px-3 py-1.5 text-left font-medium"> <th className="px-3 py-1.5 text-left font-medium">
</th> </th>
<th className="px-3 py-1.5 text-left font-medium"> <th className="px-3 py-1.5 text-left font-medium">
</th> </th>
<th className="px-3 py-1.5 text-left font-medium"> <th className="px-3 py-1.5 text-left font-medium"></th>
<th className="px-3 py-1.5 text-left font-medium"></th>
</th> <th className="px-3 py-1.5 text-left font-medium"></th>
<th className="px-3 py-1.5 text-left font-medium">
</th>
<th className="px-3 py-1.5 text-left font-medium">
</th>
<th className="px-3 py-1.5 text-left font-medium"> <th className="px-3 py-1.5 text-left font-medium">
</th> </th>
@@ -593,6 +553,9 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
<tbody className="divide-y divide-gray-100"> <tbody className="divide-y divide-gray-100">
{materials.map((mat, idx) => ( {materials.map((mat, idx) => (
<tr key={idx} className="hover:bg-gray-50"> <tr key={idx} className="hover:bg-gray-50">
<td className="px-3 py-1.5 text-gray-500 font-medium text-xs text-center">
{idx + 1}
</td>
<td className="px-3 py-1.5 font-mono text-gray-700"> <td className="px-3 py-1.5 font-mono text-gray-700">
{mat.materialCode} {mat.materialCode}
</td> </td>
@@ -644,9 +607,7 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
</tbody> </tbody>
</table> </table>
) : ( ) : (
<div className="text-xs text-gray-500"> <div className="text-xs text-gray-500"></div>
</div>
)} )}
</td> </td>
</tr> </tr>
@@ -658,9 +619,7 @@ const BatchItem = React.memo(({ batch, isAdmin, onDelete }: BatchItemProps) => {
</table> </table>
</div> </div>
) : ( ) : (
<div className="px-4 py-6 text-center text-sm text-gray-500"> <div className="px-4 py-6 text-center text-sm text-gray-500"></div>
</div>
)} )}
</div> </div>
)} )}
@@ -721,8 +680,6 @@ export const CleanerOperationHistoryModal: React.FC<CleanerOperationHistoryModal
} }
}, [logger]) }, [logger])
useEffect(() => { useEffect(() => {
if (isOpen) { if (isOpen) {
void fetchBatches() void fetchBatches()
@@ -749,7 +706,13 @@ export const CleanerOperationHistoryModal: React.FC<CleanerOperationHistoryModal
if (!isOpen) return null if (!isOpen) return null
return ( return (
<Modal isOpen={isOpen} onClose={onClose} title="清理操作历史" size="3xl" className="!max-w-[68rem]"> <Modal
isOpen={isOpen}
onClose={onClose}
title="清理操作历史"
size="3xl"
className="!max-w-[68rem]"
>
<div className="flex flex-col h-[70vh]"> <div className="flex flex-col h-[70vh]">
{/* Toolbar */} {/* Toolbar */}
<div className="flex items-start justify-between mb-4 pb-4 border-b border-gray-200"> <div className="flex items-start justify-between mb-4 pb-4 border-b border-gray-200">