Browse Source

update

master
CANCERYS\kw093 1 day ago
parent
commit
317f46ba29
9 changed files with 163 additions and 77 deletions
  1. +4
    -2
      src/app/api/jo/actions.ts
  2. +53
    -2
      src/components/ProductionProcess/FinishedQcJobOrderList.tsx
  3. +14
    -16
      src/components/ProductionProcess/ProductionProcessDetail.tsx
  4. +45
    -17
      src/components/ProductionProcess/ProductionProcessJobOrderDetail.tsx
  5. +2
    -2
      src/components/ProductionProcess/ProductionProcessList.tsx
  6. +22
    -22
      src/components/ProductionProcess/ProductionProcessStepExecution.tsx
  7. +2
    -2
      src/components/Qc/QcStockInModal.tsx
  8. +13
    -4
      src/i18n/zh/common.json
  9. +8
    -10
      src/i18n/zh/jo.json

+ 4
- 2
src/app/api/jo/actions.ts View File

@@ -324,9 +324,11 @@ export interface AllJoborderProductProcessInfoResponse {
assignedTo: number; assignedTo: number;
pickOrderId: number; pickOrderId: number;
pickOrderStatus: string; pickOrderStatus: string;
itemCode: string;
itemName: string; itemName: string;
requiredQty: number; requiredQty: number;
jobOrderId: number; jobOrderId: number;
uom: string;
stockInLineId: number; stockInLineId: number;
jobOrderCode: string; jobOrderCode: string;
productProcessLineCount: number; productProcessLineCount: number;
@@ -908,9 +910,9 @@ export const fetchCompletedJobOrderPickOrdersrecords = cache(async () => {
}, },
); );
}); });
export const fetchJoForPrintQrCode = cache(async () => {
export const fetchJoForPrintQrCode = cache(async (date: string) => {
return serverFetchJson<JobOrderListForPrintQrCodeResponse[]>( return serverFetchJson<JobOrderListForPrintQrCodeResponse[]>(
`${BASE_API_URL}/jo/joForPrintQrCode`,
`${BASE_API_URL}/jo/joForPrintQrCode/${date}`,
{ {
method: "GET", method: "GET",
next: { tags: ["jo-print-qr-code"] }, next: { tags: ["jo-print-qr-code"] },


+ 53
- 2
src/components/ProductionProcess/FinishedQcJobOrderList.tsx View File

@@ -17,6 +17,10 @@ import {
Paper, Paper,
IconButton, IconButton,
Tooltip, Tooltip,
FormControl,
InputLabel,
Select,
MenuItem,
} from "@mui/material"; } from "@mui/material";
import QrCodeIcon from '@mui/icons-material/QrCode'; import QrCodeIcon from '@mui/icons-material/QrCode';
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -50,11 +54,28 @@ const FinishedQcJobOrderList: React.FC<FinishedQcJobOrderListProps> = ({
const [page, setPage] = useState(0); const [page, setPage] = useState(0);
const [isPrinting, setIsPrinting] = useState(false); const [isPrinting, setIsPrinting] = useState(false);
const [printingId, setPrintingId] = useState<number | null>(null); const [printingId, setPrintingId] = useState<number | null>(null);
const [selectedDate, setSelectedDate] = useState<string>("today");
const getDateLabel = (offset: number) => {
return dayjs().subtract(offset, 'day').format('YYYY-MM-DD');
};

// 根据选择的日期获取实际日期字符串
const getDateParam = (dateOption: string): string => {
if (dateOption === "today") {
return dayjs().format('YYYY-MM-DD');
} else if (dateOption === "yesterday") {
return dayjs().subtract(1, 'day').format('YYYY-MM-DD');
} else if (dateOption === "dayBeforeYesterday") {
return dayjs().subtract(2, 'day').format('YYYY-MM-DD');
}
return dayjs().format('YYYY-MM-DD');
};


const fetchJobOrders = useCallback(async () => { const fetchJobOrders = useCallback(async () => {
setLoading(true); setLoading(true);
try { try {
const data = await fetchJoForPrintQrCode();
const dateParam = getDateParam(selectedDate);
const data = await fetchJoForPrintQrCode(dateParam);
setJobOrders(data || []); setJobOrders(data || []);
setPage(0); setPage(0);
} catch (e) { } catch (e) {
@@ -63,7 +84,9 @@ const FinishedQcJobOrderList: React.FC<FinishedQcJobOrderListProps> = ({
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, []);
}, [selectedDate]);




useEffect(() => { useEffect(() => {
fetchJobOrders(); fetchJobOrders();
@@ -114,6 +137,34 @@ const FinishedQcJobOrderList: React.FC<FinishedQcJobOrderListProps> = ({


return ( return (
<Box> <Box>
{/* Date Selector */}
<Stack direction="row" spacing={2} sx={{ mb: 2, alignItems: 'flex-start' }}>
<Box sx={{ maxWidth: 300 }}>
<FormControl fullWidth size="small">
<InputLabel id="date-select-label">{t("Select Date")}</InputLabel>
<Select
labelId="date-select-label"
id="date-select"
value={selectedDate}
// label={t("Select Date")}
onChange={(e) => {
setSelectedDate(e.target.value);
}}
>
<MenuItem value="today">
{t("Today")} ({getDateLabel(0)})
</MenuItem>
<MenuItem value="yesterday">
{t("Yesterday")} ({getDateLabel(1)})
</MenuItem>
<MenuItem value="dayBeforeYesterday">
{t("Day Before Yesterday")} ({getDateLabel(2)})
</MenuItem>
</Select>
</FormControl>
</Box>
</Stack>

{loading ? ( {loading ? (
<Box sx={{ display: "flex", justifyContent: "center", p: 3 }}> <Box sx={{ display: "flex", justifyContent: "center", p: 3 }}>
<CircularProgress /> <CircularProgress />


+ 14
- 16
src/components/ProductionProcess/ProductionProcessDetail.tsx View File

@@ -56,7 +56,7 @@ const ProductionProcessDetail: React.FC<ProductProcessDetailProps> = ({
onBack, onBack,
fromJosave, fromJosave,
}) => { }) => {
const { t } = useTranslation();
const { t } = useTranslation("common");
const { data: session } = useSession() as { data: SessionWithTokens | null }; const { data: session } = useSession() as { data: SessionWithTokens | null };
const currentUserId = session?.id ? parseInt(session.id) : undefined; const currentUserId = session?.id ? parseInt(session.id) : undefined;
const { values: qrValues, startScan, stopScan, resetScan } = useQrCodeScannerContext(); const { values: qrValues, startScan, stopScan, resetScan } = useQrCodeScannerContext();
@@ -334,16 +334,6 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
const effectiveEquipmentCode = const effectiveEquipmentCode =
scannedEquipmentCode ?? null; scannedEquipmentCode ?? null;
if (!effectiveEquipmentCode) {
console.error("No equipment code available");
alert(t("Please scan equipment code or equipment detail ID"));
setIsAutoSubmitting(false);
if (autoSubmitTimerRef.current) {
clearTimeout(autoSubmitTimerRef.current);
autoSubmitTimerRef.current = null;
}
return false;
}
console.log("Submitting scan data with equipmentCode:", { console.log("Submitting scan data with equipmentCode:", {
productProcessLineId: lineId, productProcessLineId: lineId,
@@ -353,7 +343,7 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
const response = await newUpdateProductProcessLineQrscan({ const response = await newUpdateProductProcessLineQrscan({
productProcessLineId: lineId, productProcessLineId: lineId,
equipmentCode: effectiveEquipmentCode,
equipmentCode: effectiveEquipmentCode ?? "",
staffNo: scannedStaffNo, staffNo: scannedStaffNo,
}); });
@@ -423,6 +413,8 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
setProcessedQrCodes(new Set()); setProcessedQrCodes(new Set());
setScannedOperatorId(null); setScannedOperatorId(null);
setScannedEquipmentId(null); setScannedEquipmentId(null);
setScannedStaffNo(null); // ✅ Add this
setScannedEquipmentCode(null);
setIsAutoSubmitting(false); // 添加:重置自动提交状态 setIsAutoSubmitting(false); // 添加:重置自动提交状态
setLineDetailForScan(null); setLineDetailForScan(null);
// 获取 line detail 以获取 bomProcessEquipmentId // 获取 line detail 以获取 bomProcessEquipmentId
@@ -446,7 +438,9 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
} }
setIsManualScanning(false); setIsManualScanning(false);
setIsAutoSubmitting(false); // 添加:重置自动提交状态
setIsAutoSubmitting(false);
setScannedStaffNo(null); // ✅ Add this
setScannedEquipmentCode(null);
stopScan(); stopScan();
resetScan(); resetScan();
}, [stopScan, resetScan]); }, [stopScan, resetScan]);
@@ -461,7 +455,7 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
} }
}; };
// 提交扫描结果并验证 // 提交扫描结果并验证
/*
useEffect(() => { useEffect(() => {
console.log("Auto-submit check:", { console.log("Auto-submit check:", {
scanningLineId, scanningLineId,
@@ -501,6 +495,7 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
// 只在组件卸载时清除 // 只在组件卸载时清除
}; };
}, [scanningLineId, scannedStaffNo, scannedEquipmentCode, isAutoSubmitting, isManualScanning, submitScanAndStart]); }, [scanningLineId, scannedStaffNo, scannedEquipmentCode, isAutoSubmitting, isManualScanning, submitScanAndStart]);
*/
useEffect(() => { useEffect(() => {
return () => { return () => {
if (autoSubmitTimerRef.current) { if (autoSubmitTimerRef.current) {
@@ -518,6 +513,9 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
setScannedEquipmentId(null); setScannedEquipmentId(null);
setProcessedQrCodes(new Set()); setProcessedQrCodes(new Set());
setScannedStaffNo(null);
setScannedEquipmentCode(null);
setProcessedQrCodes(new Set());
// 清除之前的定时器 // 清除之前的定时器
if (autoSubmitTimerRef.current) { if (autoSubmitTimerRef.current) {
clearTimeout(autoSubmitTimerRef.current); clearTimeout(autoSubmitTimerRef.current);
@@ -783,7 +781,7 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
{/* ✅ Show both options */} {/* ✅ Show both options */}
{scannedEquipmentCode {scannedEquipmentCode
? `${t("Equipment Code")}: ${scannedEquipmentCode}` ? `${t("Equipment Code")}: ${scannedEquipmentCode}`
: t("Please scan equipment code or equipment detail id")
: t("Please scan equipment code")
} }
</Typography> </Typography>
</Box> </Box>
@@ -809,7 +807,7 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
<Button <Button
variant="contained" variant="contained"
onClick={() => scanningLineId && handleSubmitScanAndStart(scanningLineId)} onClick={() => scanningLineId && handleSubmitScanAndStart(scanningLineId)}
disabled={!scannedStaffNo || (!scannedEquipmentCode)}
disabled={!scannedStaffNo }
> >
{t("Submit & Start")} {t("Submit & Start")}
</Button> </Button>


+ 45
- 17
src/components/ProductionProcess/ProductionProcessJobOrderDetail.tsx View File

@@ -316,7 +316,7 @@ const handleRelease = useCallback(async ( jobOrderId: number) => {
headerAlign: "left", headerAlign: "left",
type: "number", type: "number",
renderCell: (params) => { renderCell: (params) => {
return <Typography sx={{ fontSize: "18px" }}>{params.value}</Typography>;
return <Typography sx={{ fontWeight: 500 }}>{params.value}</Typography>;
}, },
}, },
{ {
@@ -326,16 +326,28 @@ const handleRelease = useCallback(async ( jobOrderId: number) => {
align: "left", align: "left",
headerAlign: "left", headerAlign: "left",
renderCell: (params) => { renderCell: (params) => {
return <Typography sx={{ fontSize: "18px" }}>{params.value || ""}</Typography>;
return(
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
<Typography sx={{ fontWeight: 500 }}>&nbsp;</Typography>
<Typography sx={{ fontWeight: 500 }}>{params.value || ""}</Typography>
<Typography sx={{ fontWeight: 500 }}>&nbsp;</Typography>
</Box>
)
}, },
}, },

]; ];
const productionProcessesLineRemarkTableRows = const productionProcessesLineRemarkTableRows =
processData?.productProcessLines?.map((line: any) => ({ processData?.productProcessLines?.map((line: any) => ({
id: line.seqNo, id: line.seqNo,
seqNo: line.seqNo, seqNo: line.seqNo,

description: line.description ?? "", description: line.description ?? "",




})) ?? []; })) ?? [];




@@ -487,21 +499,37 @@ const handleRelease = useCallback(async ( jobOrderId: number) => {
/> />
</Box> </Box>
); );
const ProductionProcessesLineRemarkTableContent = () => (
<Box sx={{ mt: 2 }}>
<ProcessSummaryHeader processData={processData} />
<StyledDataGrid
sx={{
"--DataGrid-overlayHeight": "100px",
}}
disableColumnMenu
rows={productionProcessesLineRemarkTableRows ?? []}
columns={productionProcessesLineRemarkTableColumns}
getRowHeight={() => 'auto'}
/>
</Box>
);
const ProductionProcessesLineRemarkTableContent = () => (
<Box sx={{ mt: 2 }}>
<ProcessSummaryHeader processData={processData} />
<StyledDataGrid
sx={{
"--DataGrid-overlayHeight": "100px",
// ✅ Match ProductionProcessDetail font size (default body2 = 0.875rem)
"& .MuiDataGrid-cell": {
fontSize: "0.875rem", // ✅ Match default body2 size
fontWeight: 500,
},
"& .MuiDataGrid-columnHeader": {
fontSize: "0.875rem", // ✅ Match header size
fontWeight: 600,
},
// ✅ Ensure empty columns are visible
"& .MuiDataGrid-columnHeaders": {
display: "flex",
},
"& .MuiDataGrid-row": {
display: "flex",
},
}}
disableColumnMenu
rows={productionProcessesLineRemarkTableRows ?? []}
columns={productionProcessesLineRemarkTableColumns}
getRowHeight={() => 'auto'}
hideFooter={false} // ✅ Ensure footer is visible
/>
</Box>
);


return ( return (


+ 2
- 2
src/components/ProductionProcess/ProductionProcessList.tsx View File

@@ -235,10 +235,10 @@ const ProductProcessList: React.FC<ProductProcessListProps> = ({ onSelectProcess
</Stack> </Stack>


<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
{t("Item Name")}: {process.itemName}
{t("Item Name")}: {process.itemCode} {process.itemName}
</Typography> </Typography>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
{t("Required Qty")}: {process.requiredQty}
{t("Required Qty")}: {process.requiredQty} {process.uom}
</Typography> </Typography>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
{t("Production date")}: {process.date ? dayjs(process.date as any).format(OUTPUT_DATE_FORMAT) : "-"} {t("Production date")}: {process.date ? dayjs(process.date as any).format(OUTPUT_DATE_FORMAT) : "-"}


+ 22
- 22
src/components/ProductionProcess/ProductionProcessStepExecution.tsx View File

@@ -410,7 +410,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro
<Card sx={{ bgcolor: 'success.50', border: '2px solid', borderColor: 'success.main', mb: 3 }}> <Card sx={{ bgcolor: 'success.50', border: '2px solid', borderColor: 'success.main', mb: 3 }}>
<CardContent> <CardContent>
<Typography variant="h5" color="success.main" gutterBottom fontWeight="bold"> <Typography variant="h5" color="success.main" gutterBottom fontWeight="bold">
{t("Completed Step")}: {lineDetail?.name} (Seq: {lineDetail?.seqNo})
{t("Completed Step")}: {lineDetail?.name} ({t("Seq")}: {lineDetail?.seqNo})
</Typography> </Typography>
{/*<Divider sx={{ my: 2 }} />*/} {/*<Divider sx={{ my: 2 }} />*/}
@@ -420,27 +420,27 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro
{t("Step Information")} {t("Step Information")}
</Typography> </Typography>
<Grid container spacing={2} sx={{ mb: 3 }}> <Grid container spacing={2} sx={{ mb: 3 }}>
<Grid item xs={12} md={6}>
<Typography variant="body2" color="text.secondary">
<strong>{t("Description")}:</strong> {lineDetail?.description || "-"}
</Typography>
</Grid>
<Grid item xs={12} md={6}>
<Typography variant="body2" color="text.secondary">
<strong>{t("Operator")}:</strong> {lineDetail?.operatorName || "-"}
</Typography>
</Grid>
<Grid item xs={12} md={6}>
<Typography variant="body2" color="text.secondary">
<strong>{t("Equipment")}:</strong> {equipmentName}
</Typography>
</Grid>
<Grid item xs={12} md={6}>
<Typography variant="body2" color="text.secondary">
<strong>{t("Status")}:</strong> {lineDetail?.status || "-"}
</Typography>
</Grid>
<Grid item xs={12} md={6}>
<Typography variant="body2" color="text.secondary" sx={{ fontSize: '1.25rem' }}>
<strong>{t("Description")}:</strong> {lineDetail?.description || "-"}
</Typography>
</Grid> </Grid>
<Grid item xs={12} md={6}>
<Typography variant="body2" color="text.secondary" sx={{ fontSize: '1.25rem' }}>
<strong>{t("Operator")}:</strong> {lineDetail?.operatorName || "-"}
</Typography>
</Grid>
<Grid item xs={12} md={6}>
<Typography variant="body2" color="text.secondary" sx={{ fontSize: '1.25rem' }}>
<strong>{t("Equipment")}:</strong> {equipmentName}
</Typography>
</Grid>
<Grid item xs={12} md={6}>
<Typography variant="body2" color="text.secondary" sx={{ fontSize: '1.25rem' }}>
<strong>{t("Status")}:</strong> {t(lineDetail?.status || "-")}
</Typography>
</Grid>
</Grid>


{/*<Divider sx={{ my: 2 }} />*/} {/*<Divider sx={{ my: 2 }} />*/}


@@ -563,7 +563,7 @@ const ProductionProcessStepExecution: React.FC<ProductionProcessStepExecutionPro
<Card sx={{ bgcolor: 'primary.50', border: '2px solid', borderColor: 'primary.main', height: '100%' }}> <Card sx={{ bgcolor: 'primary.50', border: '2px solid', borderColor: 'primary.main', height: '100%' }}>
<CardContent> <CardContent>
<Typography variant="h6" color="primary.main" gutterBottom> <Typography variant="h6" color="primary.main" gutterBottom>
{t("Executing")}: {lineDetail?.name} (Seq: {lineDetail?.seqNo})
{t("Executing")}: {lineDetail?.name} ({t("Seq")}:{lineDetail?.seqNo})
</Typography> </Typography>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
{lineDetail?.description} {lineDetail?.description}


+ 2
- 2
src/components/Qc/QcStockInModal.tsx View File

@@ -397,7 +397,7 @@ const QcStockInModal: React.FC<Props> = ({
// confirmButtonText: t("confirm putaway"), html: ""}); // confirmButtonText: t("confirm putaway"), html: ""});
// onOpenPutaway(); // onOpenPutaway();
const isJobOrderBom = (stockInLineInfo?.jobOrderId != null || printSource === "productionProcess") const isJobOrderBom = (stockInLineInfo?.jobOrderId != null || printSource === "productionProcess")
&& stockInLineInfo?.bomDescription === "半成品";
&& stockInLineInfo?.bomDescription === "WIP";
if (isJobOrderBom) { if (isJobOrderBom) {
// Auto putaway to default warehouse // Auto putaway to default warehouse
const defaultWarehouseId = stockInLineInfo?.defaultWarehouseId ?? 1; const defaultWarehouseId = stockInLineInfo?.defaultWarehouseId ?? 1;
@@ -417,7 +417,7 @@ const QcStockInModal: React.FC<Props> = ({
itemId: stockInLineInfo?.itemId, // Include Item ID itemId: stockInLineInfo?.itemId, // Include Item ID
purchaseOrderId: stockInLineInfo?.purchaseOrderId, // Include PO ID if exists purchaseOrderId: stockInLineInfo?.purchaseOrderId, // Include PO ID if exists
purchaseOrderLineId: stockInLineInfo?.purchaseOrderLineId, // Include POL ID if exists purchaseOrderLineId: stockInLineInfo?.purchaseOrderLineId, // Include POL ID if exists
acceptedQty: stockInLineInfo?.acceptedQty, // Include acceptedQty
acceptedQty:acceptQty, // Include acceptedQty
acceptQty: stockInLineInfo?.acceptedQty, // Putaway quantity acceptQty: stockInLineInfo?.acceptedQty, // Putaway quantity
warehouseId: defaultWarehouseId, warehouseId: defaultWarehouseId,
status: "received", // Use string like PutAwayModal status: "received", // Use string like PutAwayModal


+ 13
- 4
src/i18n/zh/common.json View File

@@ -84,7 +84,14 @@
"Detail Scheduling": "詳細排程", "Detail Scheduling": "詳細排程",
"Customer": "客戶", "Customer": "客戶",
"qcItem": "品檢項目", "qcItem": "品檢項目",
"Item": "物料",
"Item": "成品/半成品",
"Today": "今天",
"Yesterday": "昨天",
"Input Equipment is not match with process": "輸入的設備與流程不匹配",
"Staff No is required": "員工編號必填",
"Day Before Yesterday": "前天",
"Select Date": "選擇日期",
"Production Date": "生產日期", "Production Date": "生產日期",
"QC Check Item": "QC品檢項目", "QC Check Item": "QC品檢項目",
"QC Category": "QC品檢模板", "QC Category": "QC品檢模板",
@@ -179,7 +186,6 @@
"Production Process Information": "生產流程信息", "Production Process Information": "生產流程信息",
"Production Process Steps": "生產流程步驟", "Production Process Steps": "生產流程步驟",
"Scan Operator & Equipment": "掃描操作員和設備", "Scan Operator & Equipment": "掃描操作員和設備",
"Seq": "序號",
"Setup Time (mins)": "生產前預備時間(分鐘)", "Setup Time (mins)": "生產前預備時間(分鐘)",
"Start": "開始", "Start": "開始",
"Start QR Scan": "開始掃碼", "Start QR Scan": "開始掃碼",
@@ -195,10 +201,13 @@
"Validation failed. Please check operator and equipment.": "驗證失敗. 請檢查操作員和設備.", "Validation failed. Please check operator and equipment.": "驗證失敗. 請檢查操作員和設備.",
"View": "查看", "View": "查看",
"Back": "返回", "Back": "返回",
"BoM Material": "物料清單",
"BoM Material": "成品/半成品清單",
"N/A": "不適用", "N/A": "不適用",
"Is Dark | Dense | Float| Scrap Rate| Allergic Substance | Time Sequence | Complexity": "顔色深淺度 | 濃淡 | 浮沉 | 損耗率 | 過敏原 | 時間次序 | 複雜度", "Is Dark | Dense | Float| Scrap Rate| Allergic Substance | Time Sequence | Complexity": "顔色深淺度 | 濃淡 | 浮沉 | 損耗率 | 過敏原 | 時間次序 | 複雜度",
"Item Code": "物料編號",
"Item Code": "成品/半成品名稱",
"Please scan equipment code": "請掃描設備編號",
"Equipment Code": "設備編號",
"Seq": "步驟",
"Item Name": "物料名稱", "Item Name": "物料名稱",
"Job Order Info": "工單信息", "Job Order Info": "工單信息",
"Matching Stock": "工單對料", "Matching Stock": "工單對料",


+ 8
- 10
src/i18n/zh/jo.json View File

@@ -8,7 +8,7 @@
"Code": "工單編號", "Code": "工單編號",
"Name": "成品/半成品名稱", "Name": "成品/半成品名稱",
"Picked Qty": "已提料數量", "Picked Qty": "已提料數量",
"Confirm All": "確認所有",
"Confirm All": "確認所有提料",
"UoM": "銷售單位", "UoM": "銷售單位",
"No": "沒有", "No": "沒有",
"User not found with staffNo:": "用戶不存在", "User not found with staffNo:": "用戶不存在",
@@ -156,7 +156,9 @@
"Reject": "拒絕", "Reject": "拒絕",
"Stock Unit": "庫存單位", "Stock Unit": "庫存單位",
"Group": "組", "Group": "組",
"Item": "物料",
"Input Equipment is not match with process": "輸入的設備與流程不匹配",
"Item": "成品/半成品",
"Select Date": "選擇日期",
"No Group": "沒有組", "No Group": "沒有組",
"No created items": "沒有創建物料", "No created items": "沒有創建物料",
"Order Quantity": "需求數量", "Order Quantity": "需求數量",
@@ -284,7 +286,6 @@
"acceptQty must not greater than": "接受數量不能大於", "acceptQty must not greater than": "接受數量不能大於",
"escalation": "升級", "escalation": "升級",
"failedQty": "失敗數量", "failedQty": "失敗數量",
"qcItem": "QC物料",
"qcResult": "QC結果", "qcResult": "QC結果",
"remarks": "備註", "remarks": "備註",
"supervisor": "主管", "supervisor": "主管",
@@ -334,13 +335,15 @@
"pending": "待處理", "pending": "待處理",


"Please scan equipment code (optional if not required)": "請掃描設備編號(可選)", "Please scan equipment code (optional if not required)": "請掃描設備編號(可選)",
"Please scan equipment code": "請掃描設備編號",
"Equipment Code": "設備編號",
"Please scan operator code": "請掃描操作員編號", "Please scan operator code": "請掃描操作員編號",
"Please scan operator code first": "請先掃描操作員編號", "Please scan operator code first": "請先掃描操作員編號",
"Processing Time (mins)": "步驟時間(分鐘)", "Processing Time (mins)": "步驟時間(分鐘)",
"Production Process Information": "生產流程信息", "Production Process Information": "生產流程信息",
"Production Process Steps": "生產流程步驟", "Production Process Steps": "生產流程步驟",
"Scan Operator & Equipment": "掃描操作員和設備", "Scan Operator & Equipment": "掃描操作員和設備",
"Seq": "序號",
"Seq:": "步驟",
"Setup Time (mins)": "生產前預備時間(分鐘)", "Setup Time (mins)": "生產前預備時間(分鐘)",
"Start": "開始", "Start": "開始",
"Start QR Scan": "開始掃碼", "Start QR Scan": "開始掃碼",
@@ -366,18 +369,13 @@
"View": "查看", "View": "查看",
"Back": "返回", "Back": "返回",
"N/A": "不適用", "N/A": "不適用",
"BoM Material": "物料清單",
"BoM Material": "成品/半成品清單",
"Is Dark | Dense | Float| Scrap Rate| Allergic Substance | Time Sequence | Complexity": "顔色深淺度 | 濃淡 | 浮沉 | 損耗率 | 過敏原 | 時間順序 | 複雜度", "Is Dark | Dense | Float| Scrap Rate| Allergic Substance | Time Sequence | Complexity": "顔色深淺度 | 濃淡 | 浮沉 | 損耗率 | 過敏原 | 時間順序 | 複雜度",
"Item Code": "物料編號",
"Item Name": "物料名稱",
"Enter the number of cartons: ": "請輸入箱數:", "Enter the number of cartons: ": "請輸入箱數:",
"Number of cartons": "箱數", "Number of cartons": "箱數",
"You need to enter a number": "您需要輸入一個數字", "You need to enter a number": "您需要輸入一個數字",
"Number must be at least 1": "數字必須至少為1", "Number must be at least 1": "數字必須至少為1",


"Cancel": "取消",
"Print Pick Record": "打印板頭紙",
"Printed Successfully.": "成功列印",
"Job Order Info": "工單信息", "Job Order Info": "工單信息",
"Matching Stock": "工單對料", "Matching Stock": "工單對料",
"No data found": "沒有找到資料", "No data found": "沒有找到資料",


Loading…
Cancel
Save