Ver a proveniência

simplifiy the view in laser printer (lemon)

stable1
[email protected] há 2 semanas
ascendente
cometimento
20ce8ffddf
2 ficheiros alterados com 1 adições e 130 eliminações
  1. +0
    -28
      src/app/api/laserPrint/actions.ts
  2. +1
    -102
      src/components/LaserPrint/LaserPrintSearch.tsx

+ 0
- 28
src/app/api/laserPrint/actions.ts Ver ficheiro

@@ -38,20 +38,6 @@ export interface LaserBag2Settings {
lastReceiveSuccess?: LaserLastReceiveSuccess | null;
}

/** Live TCP queries GetMarkData / GetMarkStatus / GetMarkedCount (same host/port as laser send). */
export interface LaserBag2MarkInfo {
host: string;
port: number;
markData?: string | null;
/** 0 idle, 1 marking, 2 other — when the device returns a parseable digit */
markStatus?: number | null;
markStatusLabel?: string | null;
markedCount?: number | null;
rawMarkStatus?: string | null;
rawMarkedCount?: string | null;
error?: string | null;
}

export interface LaserBag2SendRequest {
itemId: number | null;
stockInLineId: number | null;
@@ -123,20 +109,6 @@ export async function fetchLaserBag2Settings(): Promise<LaserBag2Settings> {
return res.json() as Promise<LaserBag2Settings>;
}

export async function fetchLaserBag2MarkInfo(): Promise<LaserBag2MarkInfo> {
const base = (NEXT_PUBLIC_API_URL ?? "").replace(/\/$/, "");
if (!base) {
throw new Error("NEXT_PUBLIC_API_URL is not set.");
}
const url = `${base}/plastic/laser-bag2-mark-info`;
const res = await clientAuthFetch(url, { method: "GET" });
if (!res.ok) {
const body = await res.text().catch(() => "");
throw new Error(`讀取打標狀態失敗(${res.status})${body ? `:${body.slice(0, 200)}` : ""}`);
}
return res.json() as Promise<LaserBag2MarkInfo>;
}

export async function sendLaserBag2Job(body: LaserBag2SendRequest): Promise<LaserBag2SendResponse> {
const url = `${NEXT_PUBLIC_API_URL}/plastic/print-laser-bag2`;
const res = await clientAuthFetch(url, {


+ 1
- 102
src/components/LaserPrint/LaserPrintSearch.tsx Ver ficheiro

@@ -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}>


Carregando…
Cancelar
Guardar