diff --git a/src/app/api/pickOrder/actions.ts b/src/app/api/pickOrder/actions.ts index 548f2c1..6b3044a 100644 --- a/src/app/api/pickOrder/actions.ts +++ b/src/app/api/pickOrder/actions.ts @@ -443,6 +443,7 @@ export interface UpdatePickExecutionIssueRequest { export interface StoreLaneSummary { storeId: string; rows: LaneRow[]; + defaultTruckCount: number | null; } export interface LaneRow { @@ -606,16 +607,22 @@ export const updatePickExecutionIssueStatus = async ( }; export async function fetchStoreLaneSummary(storeId: string, requiredDate?: string, releaseType?: string): Promise { const dateToUse = requiredDate || dayjs().format('YYYY-MM-DD'); + const url = `${BASE_API_URL}/doPickOrder/summary-by-store?storeId=${encodeURIComponent(storeId)}&requiredDate=${encodeURIComponent(dateToUse)}&releaseType=${encodeURIComponent(releaseType || 'all')}`; - const response = await serverFetchJson( - url, - { + const label = `[API] fetchStoreLaneSummary ${storeId}`; + console.time(label); + try { + const response = await serverFetchJson(url, { method: "GET", cache: "no-store", - next: { revalidate: 0 } - } - ); - return response; + next: { revalidate: 0 }, + }); + console.timeEnd(label); + return response; + } catch (error) { + console.error(`[API] Error in fetchStoreLaneSummary ${storeId}:`, error); + throw error; + } } // 按车道分配订单 @@ -1414,6 +1421,22 @@ export const fetchReleasedDoPickOrdersForSelection = async ( }); return response ?? []; }; +export const fetchReleasedDoPickOrdersForSelectionToday = async ( + shopName?: string, + storeId?: string, + truck?: string +): Promise => { + const params = new URLSearchParams(); + if (shopName?.trim()) params.append("shopName", shopName.trim()); + if (storeId?.trim()) params.append("storeId", storeId.trim()); + if (truck?.trim()) params.append("truck", truck.trim()); + const query = params.toString(); + const url = `${BASE_API_URL}/doPickOrder/released-today${query ? `?${query}` : ""}`; + const response = await serverFetchJson(url, { + method: "GET", + }); + return response ?? []; +}; export const fetchReleasedDoPickOrderCountByStore = async ( storeId: string ): Promise => { diff --git a/src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx b/src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx index b396b42..336f270 100644 --- a/src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx +++ b/src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx @@ -1,7 +1,7 @@ "use client"; import { Box, Button, Grid, Stack, Typography, Select, MenuItem, FormControl, InputLabel ,Tooltip} from "@mui/material"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useState, useRef } from "react"; import { useTranslation } from "react-i18next"; import { useSession } from "next-auth/react"; import { SessionWithTokens } from "@/config/authConfig"; @@ -21,18 +21,48 @@ const FinishedGoodFloorLanePanel: React.FC = ({ onPickOrderAssigned, onSw const currentUserId = session?.id ? parseInt(session.id) : undefined; const [selectedStore, setSelectedStore] = useState("2/F"); const [selectedTruck, setSelectedTruck] = useState(""); + const [selectedDefaultTruck, setSelectedDefaultTruck] = useState(""); const [modalOpen, setModalOpen] = useState(false); const [truckCounts2F, setTruckCounts2F] = useState<{ truck: string; count: number }[]>([]); const [truckCounts4F, setTruckCounts4F] = useState<{ truck: string; count: number }[]>([]); const [summary2F, setSummary2F] = useState(null); const [summary4F, setSummary4F] = useState(null); +// 其他 state 旁邊加一組: +const hasLoggedRef = useRef(false); +const fullReadyLoggedRef = useRef(false); +const pendingRef = useRef(0); +const [defaultDateScope, setDefaultDateScope] = useState<"today" | "before">("today"); const [isLoadingSummary, setIsLoadingSummary] = useState(false); const [isAssigning, setIsAssigning] = useState(false); + const [isDefaultTruck, setIsDefaultTruck] = useState(false); //const [selectedDate, setSelectedDate] = useState("today"); + const defaultTruckCount = summary4F?.defaultTruckCount ?? 0; + const [beforeTodayTruckXCount, setBeforeTodayTruckXCount] = useState(0); + const [selectedDate, setSelectedDate] = useState("today"); const [releaseType, setReleaseType] = useState("batch"); + const startFullTimer = () => { + if (typeof window === "undefined") return; + const key = "__FG_FLOOR_FULL_TIMER_STARTED__" as const; + if (!(window as any)[key]) { + (window as any)[key] = true; + console.time("[FG] FloorLanePanel full ready"); + } + }; + + const tryEndFullTimer = () => { + if (typeof window === "undefined") return; + const key = "__FG_FLOOR_FULL_TIMER_STARTED__" as const; + if ((window as any)[key] && !fullReadyLoggedRef.current && pendingRef.current === 0) { + fullReadyLoggedRef.current = true; + console.timeEnd("[FG] FloorLanePanel full ready"); + delete (window as any)[key]; + } + }; const loadSummaries = useCallback(async () => { setIsLoadingSummary(true); + pendingRef.current += 1; + startFullTimer(); try { // Convert selectedDate to the format needed let dateParam: string | undefined; @@ -54,15 +84,33 @@ const FinishedGoodFloorLanePanel: React.FC = ({ onPickOrderAssigned, onSw console.error("Error loading summaries:", error); } finally { setIsLoadingSummary(false); + // ⭐ 新增:this async 结束,pending--,尝试结束 full ready 计时 + pendingRef.current -= 1; + tryEndFullTimer(); + if (!hasLoggedRef.current) { + hasLoggedRef.current = true; + + if (typeof window !== "undefined") { + const key = "__FG_FLOOR_PANEL_TIMER_STARTED__" as const; + + if ((window as any)[key]) { + console.timeEnd("[FG] FloorLanePanel initial load"); + delete (window as any)[key]; + } else { + console.log("Timer '[FG] FloorLanePanel initial load' already ended or never started, skip."); + } + } + } } }, [selectedDate, releaseType]); - // 初始化 useEffect(() => { loadSummaries(); }, [loadSummaries]); useEffect(() => { const loadCounts = async () => { + pendingRef.current += 1; + startFullTimer(); try { const [list2F, list4F] = await Promise.all([ fetchReleasedDoPickOrdersForSelection(undefined, "2/F"), @@ -84,10 +132,36 @@ const FinishedGoodFloorLanePanel: React.FC = ({ onPickOrderAssigned, onSw console.error("Error loading counts:", e); setTruckCounts2F([]); setTruckCounts4F([]); + }finally { + // ⭐ 新增:结束时 pending--,尝试结束 full ready 计时 + pendingRef.current -= 1; + tryEndFullTimer(); } }; loadCounts(); }, [loadSummaries]); + useEffect(() => { + const loadBeforeTodayTruckX = async () => { + pendingRef.current += 1; + startFullTimer(); + try { + const list = await fetchReleasedDoPickOrdersForSelection( + undefined, // shopName + undefined, // storeId: Truck X 的 store_id 是 null + "車線-X" // 只看 Truck X + ); + setBeforeTodayTruckXCount(list.length); + } catch (e) { + console.error("Error loading beforeTodayTruckX:", e); + setBeforeTodayTruckXCount(0); + }finally { + // ⭐ 新增:结束时 pending--,尝试结束 full ready 计时 + pendingRef.current -= 1; + tryEndFullTimer(); + } + }; + loadBeforeTodayTruckX(); + }, []); const handleAssignByLane = useCallback(async ( storeId: string, truckDepartureTime: string, @@ -299,7 +373,7 @@ const getDateLabel = (offset: number) => { {/* Grid containing both floors */} - + {/* 2/F 楼层面板 */} @@ -499,6 +573,45 @@ const getDateLabel = (offset: number) => { + + {/* 4/F Today default lane*/} + + + + {t("Truck X")} + + {defaultTruckCount === 0 ? ( + {t("No entries available")} + ) : ( + + )} + + + {/* 2/F 未完成已放單 - 與上方相同 UI */} { + + + {t("Truck X")} + + {beforeTodayTruckXCount === 0 ? ( + {t("No entries available")} + ) : ( + + )} + + + setModalOpen(false)} onAssigned={() => { loadSummaries(); diff --git a/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx b/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx index ef47f79..2465887 100644 --- a/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx +++ b/src/components/FinishedGoodSearch/FinishedGoodSearch.tsx @@ -82,8 +82,27 @@ const [selectedPrinterForDraft, setSelectedPrinterForDraft] = useState([]); + useEffect(() => { + if (typeof window === "undefined") return; + + const key = "__FG_PAGE_READY_TIMER_STARTED__" as const; + + if ((window as any)[key]) { + console.log("Timer '[FinishedGoodSearch] page ready' already started, skip."); + return; + } + + (window as any)[key] = true; + console.time("[FinishedGoodSearch] page ready"); + }, []); + const [releasedOrderCount, setReleasedOrderCount] = useState(0); - + useEffect(() => { + console.time("[FinishedGoodSearch] initial render"); + return () => { + console.timeEnd("[FinishedGoodSearch] initial render"); + }; + }, []); const fetchReleasedOrderCount = useCallback(async () => { try { const releasedOrders = await fetchReleasedDoPickOrders(); @@ -702,6 +721,18 @@ const handleAssignByLane = useCallback(async ( filterArgs={filterArgs} onFgPickOrdersChange={setFgPickOrdersData} onSwitchToDetailTab={handleSwitchToDetailTab} + onFirstLoadDone={() => { + if (typeof window === "undefined") return; + const key = "__FG_PAGE_READY_TIMER_STARTED__" as const; + + // 只在计时器真的存在时才调用 timeEnd,避免 "does not exist" + if ((window as any)[key]) { + console.timeEnd("[FinishedGoodSearch] page ready"); + delete (window as any)[key]; + } else { + console.log("Timer '[FinishedGoodSearch] page ready' was already ended, skip."); + } + }} /> )} {tabIndex === 1 && ( diff --git a/src/components/FinishedGoodSearch/GoodPickExecution.tsx b/src/components/FinishedGoodSearch/GoodPickExecution.tsx index 5a4d61a..7ba541c 100644 --- a/src/components/FinishedGoodSearch/GoodPickExecution.tsx +++ b/src/components/FinishedGoodSearch/GoodPickExecution.tsx @@ -59,6 +59,7 @@ interface Props { filterArgs: Record; onFgPickOrdersChange?: (fgPickOrders: FGPickOrderResponse[]) => void; onSwitchToDetailTab?: () => void; + onFirstLoadDone?: () => void; } // QR Code Modal Component (from LotTable) @@ -72,7 +73,7 @@ const QrCodeModal: React.FC<{ const { t } = useTranslation("pickOrder"); const { values: qrValues, isScanning, startScan, stopScan, resetScan } = useQrCodeScannerContext(); const [manualInput, setManualInput] = useState(''); - + const floorPanelTimerStartedRef = useRef(false); const [manualInputSubmitted, setManualInputSubmitted] = useState(false); const [manualInputError, setManualInputError] = useState(false); const [isProcessingQr, setIsProcessingQr] = useState(false); @@ -315,7 +316,7 @@ const QrCodeModal: React.FC<{ ); }; -const PickExecution: React.FC = ({ filterArgs, onFgPickOrdersChange, onSwitchToDetailTab }) => { +const PickExecution: React.FC = ({ filterArgs, onFgPickOrdersChange, onSwitchToDetailTab, onFirstLoadDone }) => { const { t } = useTranslation("pickOrder"); const router = useRouter(); const { data: session } = useSession() as { data: SessionWithTokens | null }; @@ -353,7 +354,7 @@ const [pickOrderSwitching, setPickOrderSwitching] = useState(false); // Add QR modal states const [qrModalOpen, setQrModalOpen] = useState(false); const [selectedLotForQr, setSelectedLotForQr] = useState(null); - + const floorPanelTimerStartedRef = useRef(false); // Add GoodPickExecutionForm states const [pickExecutionFormOpen, setPickExecutionFormOpen] = useState(false); const [selectedLotForExecutionForm, setSelectedLotForExecutionForm] = useState(null); @@ -523,12 +524,18 @@ const fetchFgPickOrdersData = useCallback(async () => { if (session && currentUserId && !initializationRef.current) { console.log(" Session loaded, initializing pick order..."); initializationRef.current = true; - - // Only fetch existing data, no auto-assignment - fetchAllCombinedLotData(); + + (async () => { + try { + await fetchAllCombinedLotData(); // ✅ 等待数据加载完成 + } finally { + if (onFirstLoadDone) { + onFirstLoadDone(); // ✅ 这时候再结束 [FinishedGoodSearch] page ready + } + } + })(); } - }, [session, currentUserId, fetchAllCombinedLotData]); - + }, [session, currentUserId, fetchAllCombinedLotData, onFirstLoadDone]); // Add event listener for manual assignment useEffect(() => { const handlePickOrderAssigned = () => { @@ -823,7 +830,24 @@ const fetchFgPickOrdersData = useCallback(async () => { } }, [qrValues, combinedLotData, handleQrCodeSubmit]); - + useEffect(() => { + if (typeof window === "undefined") return; + + const key = "__FG_FLOOR_PANEL_TIMER_STARTED__" as const; + + // 只有当「没有 FG 订单」时才会显示 FinishedGoodFloorLanePanel + if (fgPickOrders.length === 0 && !fgPickOrdersLoading) { + if (!(window as any)[key]) { + (window as any)[key] = true; + console.time("[FG] FloorLanePanel initial load"); + } + } + + // 如果之后拿到 FG 订单,你可以选择在这里清掉标记(可选) + if (fgPickOrders.length > 0 && (window as any)[key]) { + // delete (window as any)[key]; + } + }, [fgPickOrders.length, fgPickOrdersLoading]); const handlePickQtyChange = useCallback((lotKey: string, value: number | string) => { if (value === '' || value === null || value === undefined) { setPickQtyData(prev => ({ diff --git a/src/components/FinishedGoodSearch/ReleasedDoPickOrderSelectModal.tsx b/src/components/FinishedGoodSearch/ReleasedDoPickOrderSelectModal.tsx index beefe38..01abc52 100644 --- a/src/components/FinishedGoodSearch/ReleasedDoPickOrderSelectModal.tsx +++ b/src/components/FinishedGoodSearch/ReleasedDoPickOrderSelectModal.tsx @@ -22,18 +22,21 @@ import { fetchReleasedDoPickOrdersForSelection, assignByDoPickOrderId, type ReleasedDoPickOrderListItem, + fetchReleasedDoPickOrdersForSelectionToday, } from "@/app/api/pickOrder/actions"; import { useSession } from "next-auth/react"; import { SessionWithTokens } from "@/config/authConfig"; import Swal from "sweetalert2"; import dayjs from "dayjs"; - +type DateScope = "today" | "before"; interface Props { open: boolean; onClose: () => void; onAssigned: () => void; storeId: string; truck: string; + isDefaultTruck: boolean; + defaultDateScope?: "today" | "before"; } const ReleasedDoPickOrderSelectModal: React.FC = ({ @@ -42,11 +45,12 @@ const ReleasedDoPickOrderSelectModal: React.FC = ({ onAssigned, storeId, truck, + isDefaultTruck, }) => { const { t } = useTranslation("pickOrder"); const { data: session } = useSession() as { data: SessionWithTokens | null }; const currentUserId = session?.id ? parseInt(session.id) : undefined; - + const [defaultDateScope, setDefaultDateScope] = useState<"today" | "before">("today"); const [list, setList] = useState([]); const [loading, setLoading] = useState(false); const [shopSearch, setShopSearch] = useState(""); @@ -56,11 +60,33 @@ const ReleasedDoPickOrderSelectModal: React.FC = ({ if (!open) return; setLoading(true); try { - const data = await fetchReleasedDoPickOrdersForSelection( - shopSearch.trim() || undefined, - storeId, - truck?.trim() || undefined // 傳入 truck - ); + let data: ReleasedDoPickOrderListItem[]; // ⭐ 先宣告 + + if (isDefaultTruck) { + if (defaultDateScope === "today") { + // Truck X 今天 + data = await fetchReleasedDoPickOrdersForSelectionToday( + undefined, // shopName + undefined, // storeId + "車線-X" // truck + ); + } else { + // Truck X 以前(/released,server 內是 < today) + data = await fetchReleasedDoPickOrdersForSelection( + undefined, + undefined, + "車線-X" + ); + } + } else { + // 一般車道 + data = await fetchReleasedDoPickOrdersForSelection( + shopSearch.trim() || undefined, + storeId, + truck?.trim() || undefined + ); + } + setList(data); } catch (e) { console.error(e); @@ -68,7 +94,7 @@ const ReleasedDoPickOrderSelectModal: React.FC = ({ } finally { setLoading(false); } - }, [open, shopSearch, storeId, truck]); + }, [open, shopSearch, storeId, truck, isDefaultTruck, defaultDateScope]); useEffect(() => { loadList(); diff --git a/src/components/ProductionProcess/JobProcessStatus.tsx b/src/components/ProductionProcess/JobProcessStatus.tsx index d009f02..cd74669 100644 --- a/src/components/ProductionProcess/JobProcessStatus.tsx +++ b/src/components/ProductionProcess/JobProcessStatus.tsx @@ -213,7 +213,7 @@ const [lastDataRefreshTime, setLastDataRefreshTime] = useState diff --git a/src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx b/src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx index eaa6a36..9db2e11 100644 --- a/src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx +++ b/src/components/QrCodeScannerProvider/QrCodeScannerProvider.tsx @@ -57,7 +57,7 @@ const QrCodeScannerProvider: React.FC = ({ setScanResult(undefined); resetScannerInput(); - console.log("%c Scanner Reset", "color:cyan"); + //console.log("%c Scanner Reset", "color:cyan"); if (error.length > 0) { console.log("%c Error:", "color:red", error); @@ -68,25 +68,25 @@ const QrCodeScannerProvider: React.FC = ({ const startQrCodeScanner = useCallback(() => { const startTime = performance.now(); - console.log(`⏱️ [SCANNER START] Called at: ${new Date().toISOString()}`); + //console.log(`⏱️ [SCANNER START] Called at: ${new Date().toISOString()}`); resetQrCodeScanner(); const resetTime = performance.now() - startTime; - console.log(`⏱️ [SCANNER START] Reset time: ${resetTime.toFixed(2)}ms`); + //console.log(`⏱️ [SCANNER START] Reset time: ${resetTime.toFixed(2)}ms`); setIsScanning(() => true); const setScanningTime = performance.now() - startTime; - console.log(`⏱️ [SCANNER START] setScanning time: ${setScanningTime.toFixed(2)}ms`); + //console.log(`⏱️ [SCANNER START] setScanning time: ${setScanningTime.toFixed(2)}ms`); const totalTime = performance.now() - startTime; - console.log(`%c Scanning started `, "color:cyan"); - console.log(`⏱️ [SCANNER START] Total start time: ${totalTime.toFixed(2)}ms`); - console.log(`⏰ [SCANNER START] Scanner started at: ${new Date().toISOString()}`); + //console.log(`%c Scanning started `, "color:cyan"); + //console.log(`⏱️ [SCANNER START] Total start time: ${totalTime.toFixed(2)}ms`); + //console.log(`⏰ [SCANNER START] Scanner started at: ${new Date().toISOString()}`); }, [resetQrCodeScanner]); const endQrCodeScanner = useCallback(() => { setIsScanning(() => false); - console.log("%c Scanning stopped ", "color:cyan"); + //console.log("%c Scanning stopped ", "color:cyan"); }, []); // Find by rough match, return 0 if not found @@ -127,12 +127,12 @@ const QrCodeScannerProvider: React.FC = ({ useEffect(() => { const effectStartTime = performance.now(); - console.log(`⏱️ [KEYBOARD LISTENER EFFECT] Triggered at: ${new Date().toISOString()}`); - console.log(`⏱️ [KEYBOARD LISTENER EFFECT] isScanning: ${isScanning}`); + //console.log(`⏱️ [KEYBOARD LISTENER EFFECT] Triggered at: ${new Date().toISOString()}`); + //console.log(`⏱️ [KEYBOARD LISTENER EFFECT] isScanning: ${isScanning}`); if (isScanning) { const listenerRegisterStartTime = performance.now(); - console.log(`⏱️ [KEYBOARD LISTENER] Registering keyboard listener at: ${new Date().toISOString()}`); + //console.log(`⏱️ [KEYBOARD LISTENER] Registering keyboard listener at: ${new Date().toISOString()}`); // Reset refs when starting scan keysRef.current = []; @@ -147,9 +147,9 @@ const QrCodeScannerProvider: React.FC = ({ // ✅ OPTIMIZED: Use refs to accumulate keys immediately (no state update delay) if (event.key.length === 1) { if (isFirstKeyRef.current) { - console.log(`⏱️ [KEYBOARD] First key press detected: "${event.key}"`); - console.log(`⏰ [KEYBOARD] First key press at: ${keyPressTimestamp}`); - console.log(`⏱️ [KEYBOARD] Time since listener registered: ${(keyPressTime - listenerRegisterStartTime).toFixed(2)}ms`); + //console.log(`⏱️ [KEYBOARD] First key press detected: "${event.key}"`); + //console.log(`⏰ [KEYBOARD] First key press at: ${keyPressTimestamp}`); + //console.log(`⏱️ [KEYBOARD] Time since listener registered: ${(keyPressTime - listenerRegisterStartTime).toFixed(2)}ms`); isFirstKeyRef.current = false; } keysRef.current.push(event.key); @@ -157,20 +157,20 @@ const QrCodeScannerProvider: React.FC = ({ if (event.key === "{") { const braceTime = performance.now(); - console.log(`⏱️ [KEYBOARD] Left brace "{" detected at: ${new Date().toISOString()}`); - console.log(`⏱️ [KEYBOARD] Time since listener registered: ${(braceTime - listenerRegisterStartTime).toFixed(2)}ms`); + //console.log(`⏱️ [KEYBOARD] Left brace "{" detected at: ${new Date().toISOString()}`); + //console.log(`⏱️ [KEYBOARD] Time since listener registered: ${(braceTime - listenerRegisterStartTime).toFixed(2)}ms`); leftBraceCountRef.current += 1; } else if (event.key === "}") { const braceTime = performance.now(); - console.log(`⏱️ [KEYBOARD] Right brace "}" detected at: ${new Date().toISOString()}`); - console.log(`⏱️ [KEYBOARD] Time since listener registered: ${(braceTime - listenerRegisterStartTime).toFixed(2)}ms`); + //console.log(`⏱️ [KEYBOARD] Right brace "}" detected at: ${new Date().toISOString()}`); + //console.log(`⏱️ [KEYBOARD] Time since listener registered: ${(braceTime - listenerRegisterStartTime).toFixed(2)}ms`); rightBraceCountRef.current += 1; // ✅ OPTIMIZED: Check for complete QR immediately and update state only once if (leftBraceCountRef.current === rightBraceCountRef.current && leftBraceCountRef.current > 0) { const completeTime = performance.now(); - console.log(`⏱️ [KEYBOARD] Complete QR detected immediately! Time: ${completeTime.toFixed(2)}ms`); - console.log(`⏰ [KEYBOARD] Complete QR at: ${new Date().toISOString()}`); + //console.log(`⏱️ [KEYBOARD] Complete QR detected immediately! Time: ${completeTime.toFixed(2)}ms`); + //console.log(`⏰ [KEYBOARD] Complete QR at: ${new Date().toISOString()}`); const qrValue = keysRef.current.join("").substring( keysRef.current.indexOf("{"), @@ -223,26 +223,26 @@ const QrCodeScannerProvider: React.FC = ({ document.addEventListener("keydown", handleKeyDown); const listenerRegisterTime = performance.now() - listenerRegisterStartTime; - console.log(`⏱️ [KEYBOARD LISTENER] Listener registered in: ${listenerRegisterTime.toFixed(2)}ms`); - console.log(`⏰ [KEYBOARD LISTENER] Listener ready at: ${new Date().toISOString()}`); + //console.log(`⏱️ [KEYBOARD LISTENER] Listener registered in: ${listenerRegisterTime.toFixed(2)}ms`); + //console.log(`⏰ [KEYBOARD LISTENER] Listener ready at: ${new Date().toISOString()}`); return () => { - console.log(`⏱️ [KEYBOARD LISTENER] Removing keyboard listener at: ${new Date().toISOString()}`); + // console.log(`⏱️ [KEYBOARD LISTENER] Removing keyboard listener at: ${new Date().toISOString()}`); document.removeEventListener("keydown", handleKeyDown); }; } else { - console.log(`⏱️ [KEYBOARD LISTENER EFFECT] Scanner not active, skipping listener registration`); + //console.log(`⏱️ [KEYBOARD LISTENER EFFECT] Scanner not active, skipping listener registration`); } const effectTime = performance.now() - effectStartTime; - console.log(`⏱️ [KEYBOARD LISTENER EFFECT] Total effect time: ${effectTime.toFixed(2)}ms`); + //console.log(`⏱️ [KEYBOARD LISTENER EFFECT] Total effect time: ${effectTime.toFixed(2)}ms`); }, [isScanning]); // ✅ OPTIMIZED: Simplify the QR scanner effect - it's now mainly for initial detection useEffect(() => { const effectStartTime = performance.now(); - console.log(`⏱️ [QR SCANNER EFFECT] Triggered at: ${new Date().toISOString()}`); - console.log(`⏱️ [QR SCANNER EFFECT] Keys count: ${keys.length}, leftBrace: ${leftCurlyBraceCount}, rightBrace: ${rightCurlyBraceCount}`); + //console.log(`⏱️ [QR SCANNER EFFECT] Triggered at: ${new Date().toISOString()}`); + //console.log(`⏱️ [QR SCANNER EFFECT] Keys count: ${keys.length}, leftBrace: ${leftCurlyBraceCount}, rightBrace: ${rightCurlyBraceCount}`); if (rightCurlyBraceCount > leftCurlyBraceCount || leftCurlyBraceCount > 1) { // Prevent multiple scan setScanState("retry"); @@ -254,9 +254,9 @@ useEffect(() => { { const scanDetectedTime = performance.now(); setScanState("scanning"); - console.log(`%c Scan detected, waiting for inputs...`, "color:cyan"); - console.log(`⏱️ [QR SCANNER] Scan detected time: ${scanDetectedTime.toFixed(2)}ms`); - console.log(`⏰ [QR SCANNER] Scan detected at: ${new Date().toISOString()}`); + // console.log(`%c Scan detected, waiting for inputs...`, "color:cyan"); + //console.log(`⏱️ [QR SCANNER] Scan detected time: ${scanDetectedTime.toFixed(2)}ms`); + //console.log(`⏰ [QR SCANNER] Scan detected at: ${new Date().toISOString()}`); } // Note: Complete QR detection is now handled directly in handleKeyDown // This effect is mainly for UI feedback and error handling @@ -266,13 +266,13 @@ useEffect(() => { useEffect(() => { if (qrCodeScannerValues.length > 0) { const processStartTime = performance.now(); - console.log(`⏱️ [QR SCANNER PROCESS] Processing qrCodeScannerValues at: ${new Date().toISOString()}`); - console.log(`⏱️ [QR SCANNER PROCESS] Values count: ${qrCodeScannerValues.length}`); + // console.log(`⏱️ [QR SCANNER PROCESS] Processing qrCodeScannerValues at: ${new Date().toISOString()}`); + //console.log(`⏱️ [QR SCANNER PROCESS] Values count: ${qrCodeScannerValues.length}`); const scannedValues = qrCodeScannerValues[0]; - console.log(`%c Scanned Result: `, "color:cyan", scannedValues); - console.log(`⏱️ [QR SCANNER PROCESS] Scanned value: ${scannedValues}`); - console.log(`⏰ [QR SCANNER PROCESS] Processing at: ${new Date().toISOString()}`); + //console.log(`%c Scanned Result: `, "color:cyan", scannedValues); + //console.log(`⏱️ [QR SCANNER PROCESS] Scanned value: ${scannedValues}`); + //console.log(`⏰ [QR SCANNER PROCESS] Processing at: ${new Date().toISOString()}`); if (scannedValues.substring(0, 8) == "{2fitest") { // DEBUGGING // 先检查是否是 {2fiteste...} 或 {2fitestu...} 格式 @@ -310,7 +310,7 @@ useEffect(() => { } setScanResult(debugValue); const processTime = performance.now() - processStartTime; - console.log(`⏱️ [QR SCANNER PROCESS] Non-numeric processing time: ${processTime.toFixed(2)}ms`); + // console.log(`⏱️ [QR SCANNER PROCESS] Non-numeric processing time: ${processTime.toFixed(2)}ms`); return; } } @@ -319,8 +319,8 @@ useEffect(() => { const parseStartTime = performance.now(); const data: QrCodeInfo = JSON.parse(scannedValues); const parseTime = performance.now() - parseStartTime; - console.log(`%c Parsed scan data`, "color:green", data); - console.log(`⏱️ [QR SCANNER PROCESS] JSON parse time: ${parseTime.toFixed(2)}ms`); + // console.log(`%c Parsed scan data`, "color:green", data); + //console.log(`⏱️ [QR SCANNER PROCESS] JSON parse time: ${parseTime.toFixed(2)}ms`); const content = scannedValues.substring(1, scannedValues.length - 1); data.value = content; @@ -328,14 +328,14 @@ useEffect(() => { const setResultStartTime = performance.now(); setScanResult(data); const setResultTime = performance.now() - setResultStartTime; - console.log(`⏱️ [QR SCANNER PROCESS] setScanResult time: ${setResultTime.toFixed(2)}ms`); - console.log(`⏰ [QR SCANNER PROCESS] setScanResult at: ${new Date().toISOString()}`); + // console.log(`⏱️ [QR SCANNER PROCESS] setScanResult time: ${setResultTime.toFixed(2)}ms`); + //console.log(`⏰ [QR SCANNER PROCESS] setScanResult at: ${new Date().toISOString()}`); const processTime = performance.now() - processStartTime; - console.log(`⏱️ [QR SCANNER PROCESS] Total processing time: ${processTime.toFixed(2)}ms`); + // console.log(`⏱️ [QR SCANNER PROCESS] Total processing time: ${processTime.toFixed(2)}ms`); } catch (error) { // Rough match for other scanner input -- Pending Review - console.log(`⏱️ [QR SCANNER PROCESS] JSON parse failed, trying rough match`); + //console.log(`⏱️ [QR SCANNER PROCESS] JSON parse failed, trying rough match`); const silId = findIdByRoughMatch(scannedValues, "StockInLine").number ?? 0; if (silId == 0) { diff --git a/src/i18n/zh/pickOrder.json b/src/i18n/zh/pickOrder.json index 0a9d55f..6d9d881 100644 --- a/src/i18n/zh/pickOrder.json +++ b/src/i18n/zh/pickOrder.json @@ -39,6 +39,8 @@ "Lines Per Pick Order": "每提料單行數", "Pick Orders Details": "提料單詳情", "Lines": "行數", + "Before Today": "以前", + "Truck X": "車線-X", "Finsihed good items": "成品項目", "kinds": "款", "Completed Date": "完成日期",