"use client"; import { Box, Button, Paper, Stack, Typography, TextField, Table, TableBody, TableCell, TableHead, TableRow, Card, CardContent, Grid, } from "@mui/material"; import QrCodeIcon from '@mui/icons-material/QrCode'; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import StopIcon from "@mui/icons-material/Stop"; import PauseIcon from "@mui/icons-material/Pause"; import PlayArrowIcon from "@mui/icons-material/PlayArrow"; import { useTranslation } from "react-i18next"; import { JobOrderProcessLineDetailResponse, updateProductProcessLineQty,updateProductProcessLineQrscan,fetchProductProcessLineDetail ,UpdateProductProcessLineQtyRequest} from "@/app/api/jo/actions"; import { Operator, Machine } from "@/app/api/jo"; import React, { useCallback, useEffect, useState } from "react"; import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider"; import { fetchNameList, NameList } from "@/app/api/user/actions"; interface ProductionProcessStepExecutionProps { lineId: number | null onBack: () => void //onClose: () => void // onOutputSubmitted: () => Promise } const ProductionProcessStepExecution: React.FC = ({ lineId, onBack, }) => { const { t } = useTranslation(); const [lineDetail, setLineDetail] = useState(null); const isCompleted = lineDetail?.status === "Completed"; const [outputData, setOutputData] = useState({ productProcessLineId: lineId ?? 0, outputFromProcessQty: 0, outputFromProcessUom: "", defectQty: 0, defectUom: "", scrapQty: 0, scrapUom: "", byproductName: "", byproductQty: 0, byproductUom: "" }); const [isManualScanning, setIsManualScanning] = useState(false); const [processedQrCodes, setProcessedQrCodes] = useState>(new Set()); const [scannedOperators, setScannedOperators] = useState([]); const [scannedMachines, setScannedMachines] = useState([]); const [isPaused, setIsPaused] = useState(false); const [showOutputTable, setShowOutputTable] = useState(false); const { values: qrValues, startScan, stopScan, resetScan } = useQrCodeScannerContext(); const equipmentName = (lineDetail as any)?.equipment || lineDetail?.equipmentType || "-"; // 检查是否两个都已扫描 //const bothScanned = lineDetail?.operatorId && lineDetail?.equipmentId; useEffect(() => { if (!lineId) { setLineDetail(null); return; } fetchProductProcessLineDetail(lineId) .then((detail) => { setLineDetail(detail as any); // 初始化 outputData 从 lineDetail setOutputData(prev => ({ ...prev, productProcessLineId: detail.id, outputFromProcessQty: (detail as any).outputFromProcessQty || 0, // 取消注释,使用类型断言 outputFromProcessUom: (detail as any).outputFromProcessUom || "", // 取消注释,使用类型断言 defectQty: detail.defectQty || 0, defectUom: detail.defectUom || "", scrapQty: detail.scrapQty || 0, scrapUom: detail.scrapUom || "", byproductName: detail.byproductName || "", byproductQty: detail.byproductQty || 0, byproductUom: detail.byproductUom || "" })); }) .catch(err => { console.error("Failed to load line detail", err); setLineDetail(null); }); }, [lineId]); const handleSubmitOutput = async () => { if (!lineDetail?.id) return; try { // 直接使用 actions.ts 中定义的函数 await updateProductProcessLineQty({ productProcessLineId: lineDetail?.id || 0 as number, byproductName: outputData.byproductName, byproductQty: outputData.byproductQty, byproductUom: outputData.byproductUom, outputFromProcessQty: outputData.outputFromProcessQty, outputFromProcessUom: outputData.outputFromProcessUom, // outputFromProcessUom: outputData.outputFromProcessUom, defectQty: outputData.defectQty, defectUom: outputData.defectUom, scrapQty: outputData.scrapQty, scrapUom: outputData.scrapUom, }); console.log(" Output data submitted successfully"); fetchProductProcessLineDetail(lineDetail.id) .then((detail) => { setLineDetail(detail as any); // 初始化 outputData 从 lineDetail setOutputData(prev => ({ ...prev, productProcessLineId: detail.id, outputFromProcessQty: (detail as any).outputFromProcessQty || 0, // 取消注释,使用类型断言 outputFromProcessUom: (detail as any).outputFromProcessUom || "", // 取消注释,使用类型断言 defectQty: detail.defectQty || 0, defectUom: detail.defectUom || "", scrapQty: detail.scrapQty || 0, scrapUom: detail.scrapUom || "", byproductName: detail.byproductName || "", byproductQty: detail.byproductQty || 0, byproductUom: detail.byproductUom || "" })); }) .catch(err => { console.error("Failed to load line detail", err); setLineDetail(null); }); } catch (error) { console.error("Error submitting output:", error); alert("Failed to submit output data. Please try again."); } }; // 处理 QR 码扫描效果 useEffect(() => { if (isManualScanning && qrValues.length > 0 && lineDetail?.id) { const latestQr = qrValues[qrValues.length - 1]; if (processedQrCodes.has(latestQr)) { return; } setProcessedQrCodes(prev => new Set(prev).add(latestQr)); //processQrCode(latestQr); } }, [qrValues, isManualScanning, lineDetail?.id, processedQrCodes]); // 开始扫描 const handlePause = () => { setIsPaused(true); }; const handleContinue = () => { setIsPaused(false); }; const handleStop = () => { setIsPaused(false); // TODO: 调用停止流程的 API }; return ( {/* 如果已完成,显示合并的视图 */} {isCompleted ? ( {t("Completed Step")}: {lineDetail?.name} (Seq: {lineDetail?.seqNo}) {/**/} {/* 步骤信息部分 */} {t("Step Information")} {t("Description")}: {lineDetail?.description || "-"} {t("Operator")}: {lineDetail?.operatorName || "-"} {t("Equipment")}: {equipmentName} {t("Status")}: {lineDetail?.status || "-"} {/**/} {/* 产出数据部分 */} {t("Production Output Data")} {t("Type")} {t("Quantity")} {t("Unit")} {/* Output from Process */} {t("Output from Process")} {lineDetail?.outputFromProcessQty || 0} {lineDetail?.outputFromProcessUom || "-"} {/* By-product */} {lineDetail?.byproductQty && lineDetail.byproductQty > 0 && ( {t("By-product")} {lineDetail.byproductName && ( ({lineDetail.byproductName}) )} {lineDetail.byproductQty} {lineDetail.byproductUom || "-"} )} {/* Defect */} {lineDetail?.defectQty && lineDetail.defectQty > 0 && ( {t("Defect")} {lineDetail.defectQty} {lineDetail.defectUom || "-"} )} {/* Scrap */} {lineDetail?.scrapQty && lineDetail.scrapQty > 0 && ( {t("Scrap")} {lineDetail.scrapQty} {lineDetail.scrapUom || "-"} )}
) : ( <> {/* 如果未完成,显示原来的两个部分 */} {/* 当前步骤信息 */} {t("Executing")}: {lineDetail?.name} (Seq: {lineDetail?.seqNo}) {lineDetail?.description} {t("Operator")}: {lineDetail?.operatorName || "-"} {t("Equipment")}: {equipmentName} {!isPaused ? ( ) : ( )} {/* ========== 产出输入表单 ========== */} {t("Production Output Data Entry")} {showOutputTable && ( {t("Type")} {t("Quantity")} {t("Unit")} {/* start line output */} {t("Output from Process")} setOutputData({ ...outputData, outputFromProcessQty: parseInt(e.target.value) || 0 })} /> setOutputData({ ...outputData, outputFromProcessUom: e.target.value })} /> {/* byproduct */} {t("By-product")} setOutputData({ ...outputData, byproductQty: parseInt(e.target.value) || 0 })} /> setOutputData({ ...outputData, byproductUom: e.target.value })} /> {/* defect */} {t("Defect")} setOutputData({ ...outputData, defectQty: parseInt(e.target.value) || 0 })} /> setOutputData({ ...outputData, defectUom: e.target.value })} /> {/* scrap */} {t("Scrap")} setOutputData({ ...outputData, scrapQty: parseInt(e.target.value) || 0 })} /> setOutputData({ ...outputData, scrapUom: e.target.value })} />
{/* submit button */}
)}
)}
); }; export default ProductionProcessStepExecution;