style: format changed files with prettier
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -64,7 +64,12 @@ export function registerCleanerHistoryHandlers(): void {
|
|||||||
*/
|
*/
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
IPC_CHANNELS.CLEANER_HISTORY_GET_BATCH_DETAILS,
|
IPC_CHANNELS.CLEANER_HISTORY_GET_BATCH_DETAILS,
|
||||||
async (_event, batchId: string): Promise<IpcResult<{ executions: CleanerExecutionRecord[]; orders: CleanerOrderRecord[] }>> => {
|
async (
|
||||||
|
_event,
|
||||||
|
batchId: string
|
||||||
|
): Promise<
|
||||||
|
IpcResult<{ executions: CleanerExecutionRecord[]; orders: CleanerOrderRecord[] }>
|
||||||
|
> => {
|
||||||
return withErrorHandling(async () => {
|
return withErrorHandling(async () => {
|
||||||
const currentUser = SessionManager.getInstance().getUserInfo()
|
const currentUser = SessionManager.getInstance().getUserInfo()
|
||||||
|
|
||||||
@@ -94,7 +99,12 @@ export function registerCleanerHistoryHandlers(): void {
|
|||||||
*/
|
*/
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
IPC_CHANNELS.CLEANER_HISTORY_GET_MATERIAL_DETAILS,
|
IPC_CHANNELS.CLEANER_HISTORY_GET_MATERIAL_DETAILS,
|
||||||
async (_event, batchId: string, attemptNumber: number, orderNumber: string): Promise<IpcResult<CleanerMaterialRecord[]>> => {
|
async (
|
||||||
|
_event,
|
||||||
|
batchId: string,
|
||||||
|
attemptNumber: number,
|
||||||
|
orderNumber: string
|
||||||
|
): Promise<IpcResult<CleanerMaterialRecord[]>> => {
|
||||||
return withErrorHandling(async () => {
|
return withErrorHandling(async () => {
|
||||||
const currentUser = SessionManager.getInstance().getUserInfo()
|
const currentUser = SessionManager.getInstance().getUserInfo()
|
||||||
|
|
||||||
|
|||||||
@@ -481,8 +481,7 @@ export class CleanerApplicationService {
|
|||||||
: 'success'
|
: 'success'
|
||||||
|
|
||||||
// Build error message from execution-level errors (excluding per-order errors)
|
// Build error message from execution-level errors (excluding per-order errors)
|
||||||
const execErrorMessage =
|
const execErrorMessage = result.errors.length > 0 ? result.errors.join('\n') : undefined
|
||||||
result.errors.length > 0 ? result.errors.join('\n') : undefined
|
|
||||||
|
|
||||||
// Update execution status
|
// Update execution status
|
||||||
await historyDao.updateExecutionStatus(
|
await historyDao.updateExecutionStatus(
|
||||||
|
|||||||
@@ -752,8 +752,15 @@ export class CleanerOperationHistoryDAO {
|
|||||||
attemptNumber: row.AttemptNumber as number,
|
attemptNumber: row.AttemptNumber as number,
|
||||||
userId: row.UserId as number,
|
userId: row.UserId as number,
|
||||||
username: row.Username as string,
|
username: row.Username as string,
|
||||||
operationTime: row.OperationTime instanceof Date ? row.OperationTime : new Date(row.OperationTime as string),
|
operationTime:
|
||||||
endTime: row.EndTime ? (row.EndTime instanceof Date ? row.EndTime : new Date(row.EndTime as string)) : null,
|
row.OperationTime instanceof Date
|
||||||
|
? row.OperationTime
|
||||||
|
: new Date(row.OperationTime as string),
|
||||||
|
endTime: row.EndTime
|
||||||
|
? row.EndTime instanceof Date
|
||||||
|
? row.EndTime
|
||||||
|
: new Date(row.EndTime as string)
|
||||||
|
: null,
|
||||||
status: row.Status as string,
|
status: row.Status as string,
|
||||||
isDryRun: !!(row.IsDryRun as number),
|
isDryRun: !!(row.IsDryRun as number),
|
||||||
totalOrders: row.TotalOrders as number,
|
totalOrders: row.TotalOrders as number,
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ export const cleanerApi = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Cleaner operation history
|
// Cleaner operation history
|
||||||
getHistoryBatches: (options?: GetCleanerBatchesOptions): Promise<IpcResult<CleanerBatchStats[]>> =>
|
getHistoryBatches: (
|
||||||
|
options?: GetCleanerBatchesOptions
|
||||||
|
): Promise<IpcResult<CleanerBatchStats[]>> =>
|
||||||
invokeIpc(IPC_CHANNELS.CLEANER_HISTORY_GET_BATCHES, options),
|
invokeIpc(IPC_CHANNELS.CLEANER_HISTORY_GET_BATCHES, options),
|
||||||
|
|
||||||
getHistoryBatchDetails: (
|
getHistoryBatchDetails: (
|
||||||
@@ -43,7 +45,12 @@ export const cleanerApi = {
|
|||||||
attemptNumber: number,
|
attemptNumber: number,
|
||||||
orderNumber: string
|
orderNumber: string
|
||||||
): Promise<IpcResult<CleanerMaterialRecord[]>> =>
|
): Promise<IpcResult<CleanerMaterialRecord[]>> =>
|
||||||
invokeIpc(IPC_CHANNELS.CLEANER_HISTORY_GET_MATERIAL_DETAILS, batchId, attemptNumber, orderNumber),
|
invokeIpc(
|
||||||
|
IPC_CHANNELS.CLEANER_HISTORY_GET_MATERIAL_DETAILS,
|
||||||
|
batchId,
|
||||||
|
attemptNumber,
|
||||||
|
orderNumber
|
||||||
|
),
|
||||||
|
|
||||||
deleteHistoryBatch: (batchId: string): Promise<IpcResult<{ deleted: boolean }>> =>
|
deleteHistoryBatch: (batchId: string): Promise<IpcResult<{ deleted: boolean }>> =>
|
||||||
invokeIpc(IPC_CHANNELS.CLEANER_HISTORY_DELETE_BATCH, batchId)
|
invokeIpc(IPC_CHANNELS.CLEANER_HISTORY_DELETE_BATCH, batchId)
|
||||||
|
|||||||
@@ -98,10 +98,7 @@ const formatDateTime = (dateStr: string | Date | null | undefined): string => {
|
|||||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||||
}
|
}
|
||||||
|
|
||||||
const formatDuration = (
|
const formatDuration = (startTime: string | Date | null, endTime: string | Date | null) => {
|
||||||
startTime: string | Date | null,
|
|
||||||
endTime: string | Date | null
|
|
||||||
) => {
|
|
||||||
if (!startTime || !endTime) return '-'
|
if (!startTime || !endTime) return '-'
|
||||||
const start = typeof startTime === 'string' ? new Date(startTime) : startTime
|
const start = typeof startTime === 'string' ? new Date(startTime) : startTime
|
||||||
const end = typeof endTime === 'string' ? new Date(endTime) : endTime
|
const end = typeof endTime === 'string' ? new Date(endTime) : endTime
|
||||||
@@ -130,15 +127,13 @@ export const CleanerOperationHistoryModal: React.FC<CleanerOperationHistoryModal
|
|||||||
const [error, setError] = useState<string | null>(null)
|
const [error, setError] = useState<string | null>(null)
|
||||||
const [expandedBatches, setExpandedBatches] = useState<Set<string>>(new Set())
|
const [expandedBatches, setExpandedBatches] = useState<Set<string>>(new Set())
|
||||||
const [expandedOrders, setExpandedOrders] = useState<Set<string>>(new Set())
|
const [expandedOrders, setExpandedOrders] = useState<Set<string>>(new Set())
|
||||||
const [batchExecutions, setBatchExecutions] = useState<Map<string, ExecutionRecord[]>>(
|
const [batchExecutions, setBatchExecutions] = useState<Map<string, ExecutionRecord[]>>(new Map())
|
||||||
new Map()
|
|
||||||
)
|
|
||||||
const [batchOrders, setBatchOrders] = useState<Map<string, CleanerHistoryOrderRecord[]>>(
|
const [batchOrders, setBatchOrders] = useState<Map<string, CleanerHistoryOrderRecord[]>>(
|
||||||
new Map()
|
new Map()
|
||||||
)
|
)
|
||||||
const [orderMaterials, setOrderMaterials] = useState<
|
const [orderMaterials, setOrderMaterials] = useState<Map<string, CleanerHistoryMaterialRecord[]>>(
|
||||||
Map<string, CleanerHistoryMaterialRecord[]>
|
new Map()
|
||||||
>(new Map())
|
)
|
||||||
const [selectedAttempt, setSelectedAttempt] = useState<Map<string, number>>(new Map())
|
const [selectedAttempt, setSelectedAttempt] = useState<Map<string, number>>(new Map())
|
||||||
const [deleting, setDeleting] = useState<Set<string>>(new Set())
|
const [deleting, setDeleting] = useState<Set<string>>(new Set())
|
||||||
const [allUsers, setAllUsers] = useState<string[]>([])
|
const [allUsers, setAllUsers] = useState<string[]>([])
|
||||||
@@ -545,9 +540,7 @@ export const CleanerOperationHistoryModal: React.FC<CleanerOperationHistoryModal
|
|||||||
{/* Execution records */}
|
{/* Execution records */}
|
||||||
{executions.length > 0 && (
|
{executions.length > 0 && (
|
||||||
<div className="px-4 py-3 bg-gray-50/50 border-b border-gray-100">
|
<div className="px-4 py-3 bg-gray-50/50 border-b border-gray-100">
|
||||||
<div className="text-xs font-medium text-gray-500 mb-2">
|
<div className="text-xs font-medium text-gray-500 mb-2">执行记录</div>
|
||||||
执行记录
|
|
||||||
</div>
|
|
||||||
{executions.length > 1 && (
|
{executions.length > 1 && (
|
||||||
<div className="flex gap-1 mb-2">
|
<div className="flex gap-1 mb-2">
|
||||||
{executions.map((exec) => (
|
{executions.map((exec) => (
|
||||||
@@ -659,153 +652,153 @@ export const CleanerOperationHistoryModal: React.FC<CleanerOperationHistoryModal
|
|||||||
const orderKey = `${batch.batchId}:${currentAttempt ?? order.attemptNumber}:${order.orderNumber}`
|
const orderKey = `${batch.batchId}:${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) || []
|
||||||
const isLoadingMaterials =
|
const isLoadingMaterials = loadingMaterials.has(orderKey)
|
||||||
loadingMaterials.has(orderKey)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={orderKey}>
|
<React.Fragment key={orderKey}>
|
||||||
<tr
|
<tr
|
||||||
className="hover:bg-gray-50 cursor-pointer"
|
className="hover:bg-gray-50 cursor-pointer"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
toggleOrderExpansion(
|
toggleOrderExpansion(
|
||||||
batch.batchId,
|
batch.batchId,
|
||||||
currentAttempt ?? order.attemptNumber,
|
currentAttempt ?? order.attemptNumber,
|
||||||
order.orderNumber
|
order.orderNumber
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
|
||||||
<td className="px-4 py-2">
|
|
||||||
{isOrderExpanded ? (
|
|
||||||
<ChevronDown size={14} className="text-gray-400" />
|
|
||||||
) : (
|
|
||||||
<ChevronRight size={14} className="text-gray-400" />
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
<td className="px-4 py-2 text-gray-900 font-mono text-xs">
|
|
||||||
{order.orderNumber}
|
|
||||||
</td>
|
|
||||||
<td className="px-4 py-2">
|
|
||||||
<span
|
|
||||||
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium ${
|
|
||||||
statusStyles[order.status] || statusStyles.pending
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
{statusIcons[order.status]}
|
<td className="px-4 py-2">
|
||||||
{statusLabels[order.status] || order.status}
|
{isOrderExpanded ? (
|
||||||
</span>
|
<ChevronDown size={14} className="text-gray-400" />
|
||||||
</td>
|
) : (
|
||||||
<td className="px-4 py-2 text-green-600">
|
<ChevronRight size={14} className="text-gray-400" />
|
||||||
{order.materialsDeleted}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-2 text-gray-500">
|
<td className="px-4 py-2 text-gray-900 font-mono text-xs">
|
||||||
{order.materialsSkipped}
|
{order.orderNumber}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-4 py-2 text-red-600">
|
<td className="px-4 py-2">
|
||||||
{order.materialsFailed || '-'}
|
<span
|
||||||
</td>
|
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium ${
|
||||||
<td className="px-4 py-2 text-amber-600">
|
statusStyles[order.status] || statusStyles.pending
|
||||||
{order.uncertainDeletions || '-'}
|
}`}
|
||||||
</td>
|
>
|
||||||
<td className="px-4 py-2 text-red-600 text-xs max-w-xs truncate">
|
{statusIcons[order.status]}
|
||||||
{order.errorMessage || '-'}
|
{statusLabels[order.status] || order.status}
|
||||||
</td>
|
</span>
|
||||||
</tr>
|
</td>
|
||||||
|
<td className="px-4 py-2 text-green-600">
|
||||||
|
{order.materialsDeleted}
|
||||||
|
</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">
|
||||||
|
{order.uncertainDeletions || '-'}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 text-red-600 text-xs max-w-xs truncate">
|
||||||
|
{order.errorMessage || '-'}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
{/* Material details */}
|
{/* Material details */}
|
||||||
{isOrderExpanded && (
|
{isOrderExpanded && (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={8} className="bg-gray-50/50 px-8 py-3">
|
<td colSpan={8} 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">
|
<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>
|
||||||
<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>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<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 font-mono text-gray-700">
|
<td className="px-3 py-1.5 font-mono text-gray-700">
|
||||||
{mat.materialCode}
|
{mat.materialCode}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-1.5 text-gray-700">
|
<td className="px-3 py-1.5 text-gray-700">
|
||||||
{mat.materialName}
|
{mat.materialName}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-1.5 text-gray-600">
|
<td className="px-3 py-1.5 text-gray-600">
|
||||||
{mat.rowNumber}
|
{mat.rowNumber}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-1.5">
|
<td className="px-3 py-1.5">
|
||||||
<span
|
<span
|
||||||
className={`px-1.5 py-0.5 rounded text-xs font-medium ${
|
className={`px-1.5 py-0.5 rounded text-xs font-medium ${
|
||||||
mat.result === 'deleted'
|
mat.result === 'deleted'
|
||||||
? 'bg-green-100 text-green-700'
|
? 'bg-green-100 text-green-700'
|
||||||
: mat.result === 'skipped'
|
: mat.result === 'skipped'
|
||||||
? 'bg-gray-100 text-gray-700'
|
? 'bg-gray-100 text-gray-700'
|
||||||
: mat.result === 'failed'
|
: mat.result === 'failed'
|
||||||
? 'bg-red-100 text-red-700'
|
? 'bg-red-100 text-red-700'
|
||||||
: mat.result === 'uncertain'
|
: mat.result === 'uncertain'
|
||||||
? 'bg-amber-100 text-amber-700'
|
? 'bg-amber-100 text-amber-700'
|
||||||
: 'bg-gray-100 text-gray-700'
|
: 'bg-gray-100 text-gray-700'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{mat.result === 'deleted'
|
{mat.result === 'deleted'
|
||||||
? '已删除'
|
? '已删除'
|
||||||
: mat.result === 'skipped'
|
: mat.result === 'skipped'
|
||||||
? '已跳过'
|
? '已跳过'
|
||||||
: mat.result === 'failed'
|
: mat.result === 'failed'
|
||||||
? '失败'
|
? '失败'
|
||||||
: mat.result === 'uncertain'
|
: mat.result === 'uncertain'
|
||||||
? '不确定'
|
? '不确定'
|
||||||
: mat.result}
|
: mat.result}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-1.5 text-gray-600 max-w-xs truncate">
|
<td className="px-3 py-1.5 text-gray-600 max-w-xs truncate">
|
||||||
{mat.reason || '-'}
|
{mat.reason || '-'}
|
||||||
</td>
|
</td>
|
||||||
<td className="px-3 py-1.5 text-gray-600">
|
<td className="px-3 py-1.5 text-gray-600">
|
||||||
{mat.attemptCount > 1 ? (
|
{mat.attemptCount > 1 ? (
|
||||||
<span className="text-amber-600">
|
<span className="text-amber-600">
|
||||||
{mat.attemptCount}
|
{mat.attemptCount}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
'1'
|
'1'
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-xs text-gray-500">
|
<div className="text-xs text-gray-500">
|
||||||
暂无物料详情
|
暂无物料详情
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)})}
|
)
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user