From 39e9fc4fe3d348d9b5d5e5f775d78560140da122 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Sun, 23 Nov 2025 01:28:34 +0800 Subject: [PATCH] update --- src/app/(main)/jo/page.tsx | 2 +- src/app/(main)/po/page.tsx | 2 +- src/components/JoSave/JoSave.tsx | 9 +- src/components/Jodetail/JodetailSearch.tsx | 18 +- .../Jodetail/completeJobOrderRecord.tsx | 178 ++++++++++++---- src/components/PoDetail/PoDetail.tsx | 2 +- src/components/PoDetail/PoInputGrid.tsx | 2 +- src/components/PoDetail/QCDatagrid.tsx | 4 +- src/components/PoSearch/PoSearch.tsx | 2 +- .../ProductionProcessDetail.tsx | 21 +- .../ProductionProcessJobOrderDetail.tsx | 19 +- .../ProductionProcessStepExecution.tsx | 2 + src/i18n/zh/common.json | 21 +- src/i18n/zh/dashboard.json | 1 + src/i18n/zh/home.json | 3 +- src/i18n/zh/jo.json | 201 +++++++++++++++++- src/i18n/zh/purchaseOrder.json | 4 +- 17 files changed, 425 insertions(+), 66 deletions(-) diff --git a/src/app/(main)/jo/page.tsx b/src/app/(main)/jo/page.tsx index 6a4349e..9027ebf 100644 --- a/src/app/(main)/jo/page.tsx +++ b/src/app/(main)/jo/page.tsx @@ -26,7 +26,7 @@ const jo: React.FC = async () => { {t("Job Order")} - {/* TODO: Improve */} + {/* TODO: Improve */} }> diff --git a/src/app/(main)/po/page.tsx b/src/app/(main)/po/page.tsx index 61b5dfe..96263ab 100644 --- a/src/app/(main)/po/page.tsx +++ b/src/app/(main)/po/page.tsx @@ -17,7 +17,7 @@ const PurchaseOrder: React.FC = async () => { // preloadClaims(); return ( <> - + | undefined; @@ -192,10 +192,16 @@ const JoSave: React.FC = ({ {serverError} )} + {/* + */} + {id ? ( + + ) : null} + {/* + */} diff --git a/src/components/Jodetail/JodetailSearch.tsx b/src/components/Jodetail/JodetailSearch.tsx index 530c94f..0fd11d4 100644 --- a/src/components/Jodetail/JodetailSearch.tsx +++ b/src/components/Jodetail/JodetailSearch.tsx @@ -33,6 +33,8 @@ import { fetchCompletedJobOrderPickOrders, fetchCompletedJobOrderPickOrderRecords } from "@/app/api/jo/actions"; +import { fetchPrinterCombo } from "@/app/api/settings/printer"; +import { PrinterCombo } from "@/app/api/settings/printer"; interface Props { pickOrders: PickOrderResult[]; } @@ -63,6 +65,7 @@ const [hasAssignedJobOrders, setHasAssignedJobOrders] = useState(false); const [hasDataTab0, setHasDataTab0] = useState(false); const [hasDataTab1, setHasDataTab1] = useState(false); const hasAnyAssignedData = hasDataTab0 || hasDataTab1; +const [printers, setPrinters] = useState([]); const [hideCompletedUntilNext, setHideCompletedUntilNext] = useState( typeof window !== 'undefined' && localStorage.getItem('hideCompletedUntilNext') === 'true' ); @@ -92,6 +95,19 @@ const hasAnyAssignedData = hasDataTab0 || hasDataTab1; window.removeEventListener('jobOrderDataStatus', handleJobOrderDataChange as EventListener); }; }, []); + useEffect(() => { + const fetchPrinters = async () => { + try { + // 需要创建一个客户端版本的 fetchPrinterCombo + // 或者使用 API 路由 + // const printersData = await fetch('/api/printers/combo').then(r => r.json()); + // setPrinters(printersData); + } catch (error) { + console.error("Error fetching printers:", error); + } + }; + fetchPrinters(); + }, []); useEffect(() => { const onAssigned = () => { localStorage.removeItem('hideCompletedUntilNext'); @@ -466,7 +482,7 @@ const hasAnyAssignedData = hasDataTab0 || hasDataTab1; p: 2 }}> {tabIndex === 0 && } - {tabIndex === 1 && } + {tabIndex === 1 && } {tabIndex === 2 && } {/* {tabIndex === 3 && } */} diff --git a/src/components/Jodetail/completeJobOrderRecord.tsx b/src/components/Jodetail/completeJobOrderRecord.tsx index 4838d13..31213f3 100644 --- a/src/components/Jodetail/completeJobOrderRecord.tsx +++ b/src/components/Jodetail/completeJobOrderRecord.tsx @@ -25,6 +25,7 @@ import { AccordionSummary, AccordionDetails, Checkbox, + Autocomplete, } from "@mui/material"; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import { useCallback, useEffect, useState, useRef, useMemo } from "react"; @@ -44,9 +45,10 @@ import SearchBox, { Criterion } from "../SearchBox"; import { useSession } from "next-auth/react"; import { SessionWithTokens } from "@/config/authConfig"; import Swal from "sweetalert2"; - +import { PrinterCombo } from "@/app/api/settings/printer"; interface Props { filterArgs: Record; + printerCombo: PrinterCombo[]; } // 修改:已完成的 Job Order Pick Order 接口 @@ -99,7 +101,7 @@ interface LotDetail { uomDesc: string; } -const CompleteJobOrderRecord: React.FC = ({ filterArgs }) => { +const CompleteJobOrderRecord: React.FC = ({ filterArgs ,printerCombo=[]}) => { const { t } = useTranslation("jo"); const router = useRouter(); const { data: session } = useSession() as { data: SessionWithTokens | null }; @@ -119,7 +121,24 @@ const CompleteJobOrderRecord: React.FC = ({ filterArgs }) => { // 修改:搜索状态 const [searchQuery, setSearchQuery] = useState>({}); const [filteredJobOrderPickOrders, setFilteredJobOrderPickOrders] = useState([]); - + //const [selectedPrinter, setSelectedPrinter] = useState(printerCombo[0]); + const defaultDemoPrinter: PrinterCombo = { + id: 2, + value: 2, + name: "2fi", + label: "2fi", + code: "2fi" + }; + const availablePrinters = useMemo(() => { + if (printerCombo.length === 0) { + return [defaultDemoPrinter]; + } + return printerCombo; + }, [printerCombo]); + const [selectedPrinter, setSelectedPrinter] = useState( + printerCombo && printerCombo.length > 0 ? printerCombo[0] : null + ); + const [printQty, setPrintQty] = useState(1); // 修改:分页状态 const [paginationController, setPaginationController] = useState({ pageNum: 0, @@ -297,44 +316,84 @@ const CompleteJobOrderRecord: React.FC = ({ filterArgs }) => { })); }, []); - const handlePickRecord = useCallback(async () =>{ - try{ - if (!selectedJobOrderPickOrder) { + const handlePickRecord = useCallback(async (jobOrderPickOrder: CompletedJobOrderPickOrder) => { + try { + if (!jobOrderPickOrder) { console.error("No selected job order pick order available"); return; } - const pickOrderId = selectedJobOrderPickOrder.pickOrderId; - console.log("Pick Order ID:", pickOrderId); - const printRequest = { - pickOrderId: pickOrderId, - printerId: 2, - printQty: 1 - }; + // 检查是否已选择打印机 + if (!selectedPrinter) { + Swal.fire({ + position: "bottom-end", + icon: "warning", + text: t("Please select a printer first"), + showConfirmButton: false, + timer: 1500 + }); + return; + } + + // 检查打印数量是否有效 + if (!printQty || printQty < 1) { + Swal.fire({ + position: "bottom-end", + icon: "warning", + text: t("Please enter a valid print quantity (at least 1)"), + showConfirmButton: false, + timer: 1500 + }); + return; + } + + const pickOrderId = jobOrderPickOrder.pickOrderId; + console.log("Pick Order ID:", pickOrderId); - console.log("Printing Pick Record with request: ", printRequest); + // 使用已选择的打印机和数量 + const printerId = selectedPrinter.id; - const response = await PrintPickRecord(printRequest) + const printRequest = { + pickOrderId: pickOrderId, + printerId: printerId, + printQty: printQty + }; - console.log("Print Pick Record response: ", response); + console.log("Printing Pick Record with request: ", printRequest); - if(response.success){ - Swal.fire({ + const response = await PrintPickRecord(printRequest); + + console.log("Print Pick Record response: ", response); + + if (response.success) { + Swal.fire({ position: "bottom-end", icon: "success", text: t("Printed Successfully."), showConfirmButton: false, timer: 1500 + }); + } else { + console.error("Print failed: ", response.message); + Swal.fire({ + position: "bottom-end", + icon: "error", + text: response.message || t("Print failed"), + showConfirmButton: false, + timer: 1500 + }); + } + } catch (error) { + console.error("error: ", error); + Swal.fire({ + position: "bottom-end", + icon: "error", + text: t("An error occurred while printing"), + showConfirmButton: false, + timer: 1500 }); - } else { - console.error("Print failed: ", response.message); - } - }catch(error){ - console.error("error: ", error) } - -},[t, selectedJobOrderPickOrder]); - + }, [t, selectedPrinter, printQty]); // 修改:如果显示详情视图,渲染 Job Order 详情和 Lot 信息 if (showDetailView && selectedJobOrderPickOrder) { return ( @@ -373,16 +432,18 @@ const CompleteJobOrderRecord: React.FC = ({ filterArgs }) => { {t("Required Qty")}: {selectedJobOrderPickOrder.reqQty} {selectedJobOrderPickOrder.uom} + {/* + */} @@ -538,26 +599,56 @@ const CompleteJobOrderRecord: React.FC = ({ filterArgs }) => { {t("Total")}: {filteredJobOrderPickOrders.length} {t("completed Job Order pick orders with matching")} - + + + + {t("Select Printer")}: + + option.name || option.label || option.code || `Printer ${option.id}`} + value={selectedPrinter} + onChange={(_, newValue) => setSelectedPrinter(newValue)} + sx={{ minWidth: 250 }} + size="small" + renderInput={(params) => } + /> + + {t("Print Quantity")}: + + { + const value = parseInt(e.target.value) || 1; + setPrintQty(Math.max(1, value)); + }} + inputProps={{ min: 1, step: 1 }} + sx={{ width: 120 }} + size="small" + /> + + {/* 列表 */} {filteredJobOrderPickOrders.length === 0 ? ( - - - {t("No completed Job Order pick orders with matching found")} - - -) : ( - - {paginatedData.map((jobOrderPickOrder) => ( + + + {t("No completed Job Order pick orders with matching found")} + + + ) : ( + + {paginatedData.map((jobOrderPickOrder) => ( - {jobOrderPickOrder.pickOrderCode} + {jobOrderPickOrder.jobOrderCode} - {jobOrderPickOrder.jobOrderName} - {jobOrderPickOrder.jobOrderCode} + {jobOrderPickOrder.jobOrderName} - {jobOrderPickOrder.pickOrderCode} {t("Completed")}: {new Date(jobOrderPickOrder.completedDate).toLocaleString()} @@ -566,6 +657,7 @@ const CompleteJobOrderRecord: React.FC = ({ filterArgs }) => { {t("Target Date")}: {jobOrderPickOrder.pickOrderTargetDate} + = ({ filterArgs }) => { > {t("View Details")} + + + ))} diff --git a/src/components/PoDetail/PoDetail.tsx b/src/components/PoDetail/PoDetail.tsx index c06ff86..0cdff76 100644 --- a/src/components/PoDetail/PoDetail.tsx +++ b/src/components/PoDetail/PoDetail.tsx @@ -101,7 +101,7 @@ const PoSearchList: React.FC<{ selectedPoId: number; onSelect: (po: PoResult) => void; }> = ({ poList, selectedPoId, onSelect }) => { - const { t } = useTranslation("purchaseOrder"); + const { t } = useTranslation(["purchaseOrder", "dashboard"]); const [searchTerm, setSearchTerm] = useState(''); const filteredPoList = useMemo(() => { diff --git a/src/components/PoDetail/PoInputGrid.tsx b/src/components/PoDetail/PoInputGrid.tsx index 96c0274..e40595d 100644 --- a/src/components/PoDetail/PoInputGrid.tsx +++ b/src/components/PoDetail/PoInputGrid.tsx @@ -963,7 +963,7 @@ const closeNewModal = useCallback(() => { ); } const NoRowsOverlay: React.FC = () => { - const { t } = useTranslation("home"); + const { t } = useTranslation("purchaseOrder"); return ( ({ const { t, // i18n: { language }, - } = useTranslation("purchaseOrder"); + } = useTranslation(["purchaseOrder","dashboard"]); const formKey = _formKey.toString(); const { setValue, getValues } = useFormContext(); const [rowModesModel, setRowModesModel] = useState({}); @@ -380,7 +380,7 @@ const FooterToolbar: React.FC = ({ child }) => { return {child}; }; const NoRowsOverlay: React.FC = () => { - const { t } = useTranslation("home"); + const { t } = useTranslation("purchaseOrder"); return ( = ({ const [selectAll, setSelectAll] = useState(false); const [filteredPo, setFilteredPo] = useState(po); const [filterArgs, setFilterArgs] = useState>({estimatedArrivalDate : dayjsToDateString(dayjs(), "input")}); - const { t } = useTranslation("purchaseOrder"); + const { t } = useTranslation(["purchaseOrder", "dashboard"]); const router = useRouter(); const [pagingController, setPagingController] = useState( defaultPagingController, diff --git a/src/components/ProductionProcess/ProductionProcessDetail.tsx b/src/components/ProductionProcess/ProductionProcessDetail.tsx index 1cc4138..65f64db 100644 --- a/src/components/ProductionProcess/ProductionProcessDetail.tsx +++ b/src/components/ProductionProcess/ProductionProcessDetail.tsx @@ -489,10 +489,25 @@ const ProductionProcessDetail: React.FC = ({ {t("Description")} {t("Equipment Type/Code")} {t("Operator")} - + {/*} {t("Processing Time (mins)")} {t("Setup Time (mins)")} {t("Changeover Time (mins)")} +*/} + + + + + {t("Time Information(mins)")} + + + {t("Processing Time")}- + + + {t("Setup Time")} - {t("Changeover Time")} + + + {t("Status")} {t("Action")} @@ -516,10 +531,12 @@ const ProductionProcessDetail: React.FC = ({ {line.description || "-"} {equipmentName} {line.operatorName} - + {/* {line.durationInMinutes} {line.prepTimeInMinutes} {line.postProdTimeInMinutes} + */} + {line.durationInMinutes} - {line.prepTimeInMinutes} - {line.postProdTimeInMinutes} {isCompleted ? ( void; + fromJosave?: boolean; } const ProductionProcessJobOrderDetail: React.FC = ({ jobOrderId, onBack, + fromJosave, }) => { const { t } = useTranslation(); const [loading, setLoading] = useState(false); @@ -363,7 +365,7 @@ const handleRelease = useCallback(() => { {t("Lines with insufficient stock: ")}{stockCounts.insufficient} - + {!fromJosave && ( + )} @@ -414,9 +417,15 @@ const handleRelease = useCallback(() => { - - - + {!fromJosave && ( + + )} + {!fromJosave && ( + + )} + {!fromJosave && ( + + )} @@ -424,6 +433,7 @@ const handleRelease = useCallback(() => { {tabIndex === 0 && } {tabIndex === 1 && } + {tabIndex === 2 && ( { )} {tabIndex === 3 && } {tabIndex === 4 && } + ); diff --git a/src/components/ProductionProcess/ProductionProcessStepExecution.tsx b/src/components/ProductionProcess/ProductionProcessStepExecution.tsx index a20958e..086651d 100644 --- a/src/components/ProductionProcess/ProductionProcessStepExecution.tsx +++ b/src/components/ProductionProcess/ProductionProcessStepExecution.tsx @@ -347,6 +347,7 @@ const ProductionProcessStepExecution: React.FC + {/*