|
|
|
@@ -21,10 +21,8 @@ import ChevronRight from "@mui/icons-material/ChevronRight"; |
|
|
|
import Settings from "@mui/icons-material/Settings"; |
|
|
|
import { |
|
|
|
checkPrinterStatus, |
|
|
|
fetchLaserBag2MarkInfo, |
|
|
|
fetchLaserJobOrders, |
|
|
|
fetchLaserBag2Settings, |
|
|
|
type LaserBag2MarkInfo, |
|
|
|
type LaserLastReceiveSuccess, |
|
|
|
JobOrderListItem, |
|
|
|
patchSetting, |
|
|
|
@@ -48,8 +46,6 @@ const PRINTER_RETRY_MS = 30 * 1000; |
|
|
|
const LASER_SEND_COUNT = 3; |
|
|
|
const BETWEEN_SEND_MS = 3000; |
|
|
|
const SUCCESS_SIGNAL_MS = 3500; |
|
|
|
/** Poll laser TCP GetMarkData / GetMarkStatus / GetMarkedCount */ |
|
|
|
const MARK_INFO_MS = 5000; |
|
|
|
|
|
|
|
function formatQty(val: number | null | undefined): string { |
|
|
|
if (val == null) return "—"; |
|
|
|
@@ -68,11 +64,6 @@ function getBatch(jo: JobOrderListItem): string { |
|
|
|
return (jo.lotNo || "—").trim() || "—"; |
|
|
|
} |
|
|
|
|
|
|
|
function fmtMarkText(s: string | null | undefined): string { |
|
|
|
if (s == null || s === "") return "—"; |
|
|
|
return s; |
|
|
|
} |
|
|
|
|
|
|
|
function delay(ms: number): Promise<void> { |
|
|
|
return new Promise((resolve) => setTimeout(resolve, ms)); |
|
|
|
} |
|
|
|
@@ -98,8 +89,6 @@ const LaserPrintSearch: React.FC = () => { |
|
|
|
const [settingsLoaded, setSettingsLoaded] = useState(false); |
|
|
|
const [printerConnected, setPrinterConnected] = useState(false); |
|
|
|
const [printerMessage, setPrinterMessage] = useState("檸檬機(激光機)未連接"); |
|
|
|
const [markInfo, setMarkInfo] = useState<LaserBag2MarkInfo | null>(null); |
|
|
|
const [markInfoError, setMarkInfoError] = useState<string | null>(null); |
|
|
|
|
|
|
|
const loadSystemSettings = useCallback(async () => { |
|
|
|
try { |
|
|
|
@@ -185,23 +174,6 @@ const LaserPrintSearch: React.FC = () => { |
|
|
|
return () => clearInterval(id); |
|
|
|
}, [printerConnected, checkLaser, settingsLoaded]); |
|
|
|
|
|
|
|
const loadMarkInfo = useCallback(async () => { |
|
|
|
try { |
|
|
|
const m = await fetchLaserBag2MarkInfo(); |
|
|
|
setMarkInfo(m); |
|
|
|
setMarkInfoError(null); |
|
|
|
} catch (e) { |
|
|
|
setMarkInfoError(e instanceof Error ? e.message : "無法讀取打標狀態"); |
|
|
|
} |
|
|
|
}, []); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
if (!settingsLoaded) return; |
|
|
|
void loadMarkInfo(); |
|
|
|
const id = setInterval(() => void loadMarkInfo(), MARK_INFO_MS); |
|
|
|
return () => clearInterval(id); |
|
|
|
}, [settingsLoaded, loadMarkInfo]); |
|
|
|
|
|
|
|
const goPrevDay = () => { |
|
|
|
setPlanDate((d) => dayjs(d).subtract(1, "day").format("YYYY-MM-DD")); |
|
|
|
}; |
|
|
|
@@ -258,7 +230,6 @@ const LaserPrintSearch: React.FC = () => { |
|
|
|
: ""; |
|
|
|
setSuccessSignal(`已送出 ${LASER_SEND_COUNT} 次至檸檬機(激光機)${ackHint}`); |
|
|
|
await loadSystemSettings(); |
|
|
|
void loadMarkInfo(); |
|
|
|
} catch (e) { |
|
|
|
setErrorSnackbar({ |
|
|
|
open: true, |
|
|
|
@@ -279,7 +250,6 @@ const LaserPrintSearch: React.FC = () => { |
|
|
|
void checkLaser(); |
|
|
|
await loadSystemSettings(); |
|
|
|
void loadJobOrders(false); |
|
|
|
void loadMarkInfo(); |
|
|
|
} catch (e) { |
|
|
|
setErrorSnackbar({ |
|
|
|
open: true, |
|
|
|
@@ -288,14 +258,6 @@ const LaserPrintSearch: React.FC = () => { |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
const lastReceiveJson = |
|
|
|
lastLaserReceive?.itemId != null && lastLaserReceive?.stockInLineId != null |
|
|
|
? JSON.stringify({ |
|
|
|
itemId: lastLaserReceive.itemId, |
|
|
|
stockInLineId: lastLaserReceive.stockInLineId, |
|
|
|
}) |
|
|
|
: null; |
|
|
|
|
|
|
|
return ( |
|
|
|
<Box sx={{ minHeight: "70vh", display: "flex", flexDirection: "column" }}> |
|
|
|
{successSignal && ( |
|
|
|
@@ -306,74 +268,11 @@ const LaserPrintSearch: React.FC = () => { |
|
|
|
{settingsLoaded && lastLaserReceive && ( |
|
|
|
<Alert severity="info" sx={{ mb: 2 }}> |
|
|
|
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}> |
|
|
|
上次印表機已確認(receive)的工單 |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2" component="div" sx={{ mt: 0.5 }}> |
|
|
|
工單號:{lastLaserReceive.jobOrderNo ?? "—"} 批號/Lot:{lastLaserReceive.lotNo ?? "—"} |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2" component="div" sx={{ mt: 0.5, fontFamily: "monospace" }}> |
|
|
|
JSON:{lastReceiveJson ?? "—"} |
|
|
|
</Typography> |
|
|
|
<Typography variant="caption" color="text.secondary" display="block" sx={{ mt: 0.5 }}> |
|
|
|
時間:{formatHongKongDateTime(lastLaserReceive.sentAt)} 來源:{lastLaserReceive.source ?? "—"} |
|
|
|
{lastLaserReceive.printerAck ? ` 回覆:${lastLaserReceive.printerAck}` : ""} |
|
|
|
上次印表機已確認工單:{lastLaserReceive.jobOrderNo ?? "—"} {formatHongKongDateTime(lastLaserReceive.sentAt)} |
|
|
|
</Typography> |
|
|
|
</Alert> |
|
|
|
)} |
|
|
|
|
|
|
|
{settingsLoaded && ( |
|
|
|
<Paper sx={{ p: 2, mb: 2, backgroundColor: BG_TOP }}> |
|
|
|
<Typography variant="subtitle2" sx={{ fontWeight: 600, mb: 1 }}> |
|
|
|
目前激光機打標(TCP:GetMarkData/GetMarkStatus/GetMarkedCount) |
|
|
|
{markInfo ? ` ${markInfo.host}:${markInfo.port}` : ""} |
|
|
|
</Typography> |
|
|
|
{markInfoError && ( |
|
|
|
<Typography variant="body2" color="error" sx={{ mb: 1 }}> |
|
|
|
{markInfoError} |
|
|
|
</Typography> |
|
|
|
)} |
|
|
|
{!markInfo && !markInfoError && ( |
|
|
|
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}> |
|
|
|
<CircularProgress size={22} /> |
|
|
|
<Typography variant="body2" color="text.secondary"> |
|
|
|
讀取中… |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
)} |
|
|
|
{markInfo && ( |
|
|
|
<Stack spacing={0.75}> |
|
|
|
<Typography variant="body2"> |
|
|
|
<strong>GetMarkStatus</strong>(0 待機/1 打標中/2 其他): |
|
|
|
{markInfo.markStatusLabel ?? "—"} |
|
|
|
{markInfo.markStatus != null ? `(${markInfo.markStatus})` : ""} |
|
|
|
{markInfo.rawMarkStatus ? ` 原始:${markInfo.rawMarkStatus}` : ""} |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2" sx={{ wordBreak: "break-word" }}> |
|
|
|
<strong>GetMarkData</strong>(目前標記字串): |
|
|
|
{fmtMarkText(markInfo.markData)} |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2"> |
|
|
|
<strong>GetMarkedCount</strong>: |
|
|
|
{markInfo.markedCount != null |
|
|
|
? markInfo.markedCount.toLocaleString() |
|
|
|
: fmtMarkText(markInfo.rawMarkedCount)} |
|
|
|
{markInfo.markedCount != null && |
|
|
|
markInfo.rawMarkedCount != null && |
|
|
|
markInfo.rawMarkedCount !== "" && |
|
|
|
String(markInfo.markedCount) !== markInfo.rawMarkedCount.trim() |
|
|
|
? ` 原始:${markInfo.rawMarkedCount}` |
|
|
|
: ""} |
|
|
|
</Typography> |
|
|
|
{markInfo.error ? ( |
|
|
|
<Typography variant="caption" color="warning.main" display="block"> |
|
|
|
部分查詢:{markInfo.error} |
|
|
|
</Typography> |
|
|
|
) : null} |
|
|
|
</Stack> |
|
|
|
)} |
|
|
|
</Paper> |
|
|
|
)} |
|
|
|
|
|
|
|
<Paper sx={{ p: 2, mb: 2, backgroundColor: BG_TOP }}> |
|
|
|
<Stack direction="row" alignItems="center" justifyContent="space-between" flexWrap="wrap" gap={2}> |
|
|
|
<Stack direction="row" alignItems="center" spacing={2}> |
|
|
|
|