瀏覽代碼

update workbenchprintlabel to show QRcode

MergeProblem1
CANCERYS\kw093 1 周之前
父節點
當前提交
169584e2c9
共有 5 個文件被更改,包括 70 次插入50 次删除
  1. +8
    -0
      src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx
  2. +48
    -48
      src/components/DoWorkbench/WorkbenchLotLabelPrintModal.tsx
  3. +8
    -0
      src/components/JoWorkbench/newJobPickExecution.tsx
  4. +2
    -1
      src/components/PickOrderSearch/PickOrderSearch.tsx
  5. +4
    -1
      src/components/PickOrderSearch/WorkbenchPickExecution.tsx

+ 8
- 0
src/components/DoWorkbench/WorkbenchGoodPickExecutionDetail.tsx 查看文件

@@ -561,6 +561,14 @@ const [pickOrderSwitching, setPickOrderSwitching] = useState(false);
const [workbenchLotLabelContextLot, setWorkbenchLotLabelContextLot] = const [workbenchLotLabelContextLot, setWorkbenchLotLabelContextLot] =
useState<any | null>(null); useState<any | null>(null);


useEffect(() => {
if (!qrScanSuccess || !workbenchLotLabelModalOpen) return;
setWorkbenchLotLabelModalOpen(false);
setWorkbenchLotLabelInitialPayload(null);
setWorkbenchLotLabelReminderText(null);
setWorkbenchLotLabelContextLot(null);
}, [qrScanSuccess, workbenchLotLabelModalOpen]);

// Add these missing state variables after line 352 // Add these missing state variables after line 352
const [isManualScanning, setIsManualScanning] = useState<boolean>(false); const [isManualScanning, setIsManualScanning] = useState<boolean>(false);
// Track processed QR codes by itemId+stockInLineId combination for better lot confirmation handling // Track processed QR codes by itemId+stockInLineId combination for better lot confirmation handling


+ 48
- 48
src/components/DoWorkbench/WorkbenchLotLabelPrintModal.tsx 查看文件

@@ -36,6 +36,7 @@ import {
fetchWorkbenchPrinters, fetchWorkbenchPrinters,
printWorkbenchLotLabel, printWorkbenchLotLabel,
} from "@/app/api/doworkbench/actions"; } from "@/app/api/doworkbench/actions";
import { QRCodeSVG } from "qrcode.react";


type ScanPayload = { type ScanPayload = {
itemId: number; itemId: number;
@@ -66,6 +67,7 @@ type QrCodeAnalysisResponse = {
sameItemLots: Array<{ sameItemLots: Array<{
lotNo: string; lotNo: string;
inventoryLotLineId: number; inventoryLotLineId: number;
stockInLineId?: number | null;
availableQty: number; availableQty: number;
uom: string; uom: string;
warehouseCode?: string | null; warehouseCode?: string | null;
@@ -175,9 +177,9 @@ const WorkbenchLotLabelPrintModal: React.FC<WorkbenchLotLabelPrintModalProps> =
const [printingLotLineId, setPrintingLotLineId] = useState<number | null>( const [printingLotLineId, setPrintingLotLineId] = useState<number | null>(
null, null,
); );
const [workbenchScanPickLotLineId, setWorkbenchScanPickLotLineId] = useState<
number | null
>(null);
const [qrVisibleLotLineId, setQrVisibleLotLineId] = useState<number | null>(
null,
);


const [snackbar, setSnackbar] = useState<{ const [snackbar, setSnackbar] = useState<{
open: boolean; open: boolean;
@@ -195,7 +197,7 @@ const WorkbenchLotLabelPrintModal: React.FC<WorkbenchLotLabelPrintModalProps> =
setAnalysis(null); setAnalysis(null);
setPrintQty(1); setPrintQty(1);
setPrintingLotLineId(null); setPrintingLotLineId(null);
setWorkbenchScanPickLotLineId(null);
setQrVisibleLotLineId(null);
}, []); }, []);


useEffect(() => { useEffect(() => {
@@ -383,6 +385,7 @@ const WorkbenchLotLabelPrintModal: React.FC<WorkbenchLotLabelPrintModalProps> =
? { ? {
lotNo: scanned?.lotNo ?? "", lotNo: scanned?.lotNo ?? "",
inventoryLotLineId: scannedLotLineId, inventoryLotLineId: scannedLotLineId,
stockInLineId: Number(scanned?.stockInLineId ?? 0) || null,
availableQty: Math.max(fromApi, fromTable) as number, availableQty: Math.max(fromApi, fromTable) as number,
uom: (scannedRow?.uom ?? triggerLotUom ?? "") as string, uom: (scannedRow?.uom ?? triggerLotUom ?? "") as string,
warehouseCode: warehouseCode:
@@ -465,33 +468,6 @@ const WorkbenchLotLabelPrintModal: React.FC<WorkbenchLotLabelPrintModalProps> =
[selectedPrinterId, printQty], [selectedPrinterId, printQty],
); );


const handleWorkbenchScanPickOne = useCallback(
async (inventoryLotLineId: number, lotNo: string) => {
if (!onWorkbenchScanPick) return;
setWorkbenchScanPickLotLineId(inventoryLotLineId);
try {
const n = Number(submitQty);
const qtyPayload =
Number.isFinite(n) && n >= 0 ? { qty: n } : {};
await onWorkbenchScanPick({ inventoryLotLineId, lotNo, ...qtyPayload });
setSnackbar({
open: true,
message: `掃碼提貨成功:Lot ${lotNo}`,
severity: "success",
});
} catch (e) {
setSnackbar({
open: true,
message: e instanceof Error ? e.message : "掃碼提貨失敗",
severity: "error",
});
} finally {
setWorkbenchScanPickLotLineId(null);
}
},
[onWorkbenchScanPick, submitQty],
);

return ( return (
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth> <Dialog open={open} onClose={onClose} maxWidth="md" fullWidth>
<DialogTitle>批號標籤列印(提貨台)</DialogTitle> <DialogTitle>批號標籤列印(提貨台)</DialogTitle>
@@ -664,14 +640,20 @@ const WorkbenchLotLabelPrintModal: React.FC<WorkbenchLotLabelPrintModalProps> =
{filteredLots.map((lot) => { {filteredLots.map((lot) => {
const isPrinting = const isPrinting =
printingLotLineId === lot.inventoryLotLineId; printingLotLineId === lot.inventoryLotLineId;
const isScanPicking =
workbenchScanPickLotLineId === lot.inventoryLotLineId;
const loc = String(lot.warehouseCode ?? "").trim(); const loc = String(lot.warehouseCode ?? "").trim();
const canWorkbenchPick =
const canShowLotQr =
!!onWorkbenchScanPick && !!onWorkbenchScanPick &&
!!analysis && !!analysis &&
!analysisLoading && !analysisLoading &&
!disableScanPick; !disableScanPick;
const lotQrPayload =
Number.isFinite(Number(analysis?.itemId)) &&
Number.isFinite(Number(lot.stockInLineId))
? {
itemId: Number(analysis?.itemId),
stockInLineId: Number(lot.stockInLineId),
}
: null;
return ( return (
<Box <Box
key={lot.inventoryLotLineId} key={lot.inventoryLotLineId}
@@ -713,7 +695,7 @@ const WorkbenchLotLabelPrintModal: React.FC<WorkbenchLotLabelPrintModalProps> =
> >
<Button <Button
variant="contained" variant="contained"
disabled={!canPrint || isPrinting || isScanPicking}
disabled={!canPrint || isPrinting}
onClick={() => onClick={() =>
void handlePrintOne( void handlePrintOne(
lot.inventoryLotLineId, lot.inventoryLotLineId,
@@ -732,30 +714,48 @@ const WorkbenchLotLabelPrintModal: React.FC<WorkbenchLotLabelPrintModalProps> =
variant="outlined" variant="outlined"
color="secondary" color="secondary"
title={ title={
disableScanPick
? "此出庫行已掃碼或已完成,無法再掃碼提貨"
!lotQrPayload
? "此列無法取得 QR payload(需 stockInLineId)"
: disableScanPick
? "此出庫行已掃碼或已完成,無法顯示 QR"
: undefined : undefined
} }
disabled={ disabled={
!canWorkbenchPick ||
isPrinting ||
isScanPicking
!canShowLotQr || !lotQrPayload || isPrinting
} }
onClick={() => onClick={() =>
void handleWorkbenchScanPickOne(
lot.inventoryLotLineId,
lot.lotNo,
setQrVisibleLotLineId((prev) =>
prev === lot.inventoryLotLineId
? null
: lot.inventoryLotLineId,
) )
} }
> >
{isScanPicking ? (
<CircularProgress size={18} />
) : (
"掃碼提貨"
)}
顯示 QR
</Button> </Button>
) : null} ) : null}
</Stack> </Stack>
{qrVisibleLotLineId === lot.inventoryLotLineId &&
lotQrPayload ? (
<Box
sx={{
mt: 1.5,
ml: "auto",
p: 1.5,
borderRadius: 1,
border: "1px dashed",
borderColor: "divider",
textAlign: "center",
minWidth: 220,
}}
>
<QRCodeSVG
value={JSON.stringify(lotQrPayload)}
size={160}
includeMargin
/>
</Box>
) : null}
</Box> </Box>
); );
})} })}


+ 8
- 0
src/components/JoWorkbench/newJobPickExecution.tsx 查看文件

@@ -739,6 +739,14 @@ const JobPickExecution: React.FC<Props> = ({ filterArgs, onBackToList }) => {
const [workbenchLotLabelReminderText, setWorkbenchLotLabelReminderText] = const [workbenchLotLabelReminderText, setWorkbenchLotLabelReminderText] =
useState<string | null>(null); useState<string | null>(null);


useEffect(() => {
if (!qrScanSuccess || !workbenchLotLabelModalOpen) return;
setWorkbenchLotLabelModalOpen(false);
setWorkbenchLotLabelInitialPayload(null);
setWorkbenchLotLabelContextLot(null);
setWorkbenchLotLabelReminderText(null);
}, [qrScanSuccess, workbenchLotLabelModalOpen]);

// Add these missing state variables // Add these missing state variables
const [isManualScanning, setIsManualScanning] = useState<boolean>(false); const [isManualScanning, setIsManualScanning] = useState<boolean>(false);
const [processedQrCodes, setProcessedQrCodes] = useState<Set<string>>( const [processedQrCodes, setProcessedQrCodes] = useState<Set<string>>(


+ 2
- 1
src/components/PickOrderSearch/PickOrderSearch.tsx 查看文件

@@ -123,6 +123,7 @@ const PickOrderSearch: React.FC<Props> = () => {
{/* <Tab label={t("Release")} iconPosition="end" /> */} {/* <Tab label={t("Release")} iconPosition="end" /> */}
{/* <Tab label={t("Pick Execution")} iconPosition="end" /> */} {/* <Tab label={t("Pick Execution")} iconPosition="end" /> */}
<Tab label={t("Pick Execution")} iconPosition="end" /> <Tab label={t("Pick Execution")} iconPosition="end" />
{/* <Tab label={t("old Pick Execution")} iconPosition="end" /> */}
</Tabs> </Tabs>
</Box> </Box>


@@ -131,7 +132,7 @@ const PickOrderSearch: React.FC<Props> = () => {
p: 2 p: 2
}}> }}>
{tabIndex === 2 && <WorkbenchPickExecution filterArgs={filterArgs} />} {tabIndex === 2 && <WorkbenchPickExecution filterArgs={filterArgs} />}
{/* {tabIndex === 3 && <PickExecution filterArgs={filterArgs} />} */}
{/* {tabIndex === 3 && <PickExecution filterArgs={filterArgs} />} */}
{tabIndex === 0 && ( {tabIndex === 0 && (
<NewCreateItem <NewCreateItem
filterArgs={filterArgs} filterArgs={filterArgs}


+ 4
- 1
src/components/PickOrderSearch/WorkbenchPickExecution.tsx 查看文件

@@ -605,6 +605,9 @@ const WorkbenchPickExecution: React.FC<Props> = ({ filterArgs }) => {
), ),
); );
} }
setWorkbenchLotLabelModalOpen(false);
setWorkbenchLotLabelContextLot(null);
setWorkbenchLotLabelInitialPayload(null);
await refreshReleasedTopRowsAfterMutation(); await refreshReleasedTopRowsAfterMutation();
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@@ -1627,7 +1630,6 @@ const WorkbenchPickExecution: React.FC<Props> = ({ filterArgs }) => {
hideScanSection={workbenchLotLabelInitialPayload != null || workbenchLotLabelContextLot != null} hideScanSection={workbenchLotLabelInitialPayload != null || workbenchLotLabelContextLot != null}
triggerLotAvailableQty={workbenchLotLabelContextLot?.availableQty ?? null} triggerLotAvailableQty={workbenchLotLabelContextLot?.availableQty ?? null}
triggerLotUom={workbenchLotLabelContextLot?.uomDesc ?? null} triggerLotUom={workbenchLotLabelContextLot?.uomDesc ?? null}
onWorkbenchScanPick={handleWorkbenchLotLabelScanPick}
submitQty={ submitQty={
workbenchLotLabelContextLot?.stockOutLineId workbenchLotLabelContextLot?.stockOutLineId
? Number(resolveSingleSubmitQty(workbenchLotLabelContextLot)) ? Number(resolveSingleSubmitQty(workbenchLotLabelContextLot))
@@ -1647,6 +1649,7 @@ const WorkbenchPickExecution: React.FC<Props> = ({ filterArgs }) => {
} }
setQtyBySolId((prev) => ({ ...prev, [solId]: qty })); setQtyBySolId((prev) => ({ ...prev, [solId]: qty }));
}} }}
onWorkbenchScanPick={handleWorkbenchLotLabelScanPick}
/> />
<ManualLotConfirmationModal <ManualLotConfirmationModal
open={manualLotConfirmationOpen} open={manualLotConfirmationOpen}


Loading…
取消
儲存