Просмотр исходного кода

Remove hardcoded placeholders and codes

debrand
Harry Groves 1 месяц назад
Родитель
Сommit
2f7419207b
27 измененных файлов: 255 добавлений и 6875 удалений
  1. +2
    -2
      src/app/(main)/laserPrint/page.tsx
  2. +2
    -2
      src/app/(main)/m18Syn/page.tsx
  3. +3
    -3
      src/app/(main)/ps/page.tsx
  4. +1
    -1
      src/app/(main)/report/AsyncItemCodeAutocomplete.tsx
  5. +1
    -1
      src/app/(main)/report/ItemQcReportFilters.tsx
  6. +2
    -2
      src/app/(main)/report/page.tsx
  7. +1
    -1
      src/app/(main)/report/reportCategories.ts
  8. +4
    -7
      src/app/(main)/testing/page.tsx
  9. +3
    -3
      src/app/api/bagPrint/actions.ts
  10. +28
    -20
      src/components/BagPrint/BagPrintSearch.tsx
  11. +2
    -2
      src/components/DeliveryOrderFloorSettings/DeliveryOrderFloorSettings.tsx
  12. +23
    -1871
      src/components/DetailScheduleDetail/ViewByFGDetails.tsx
  13. +18
    -1872
      src/components/DetailedScheduleDetail/TempRecords.tsx
  14. +21
    -15
      src/components/LaserPrint/LaserPrintSearch.tsx
  15. +2
    -2
      src/components/PoDetail/PutAwayForm.tsx
  16. +29
    -34
      src/components/PoWorkbench/detailsGrid/poWorkbenchDetailsGridMock.ts
  17. +2
    -2
      src/components/ProductionProcess/ProductionProcessDetail.tsx
  18. +11
    -2911
      src/components/RoughScheduleDetail/TempRecords.tsx
  19. +35
    -71
      src/config/reportConfig.ts
  20. +6
    -6
      src/i18n/en/deliveryOrderFloor.json
  21. +2
    -2
      src/i18n/en/m18Sync.json
  22. +23
    -17
      src/i18n/en/report.json
  23. +6
    -6
      src/i18n/zh/deliveryOrderFloor.json
  24. +1
    -1
      src/i18n/zh/laserPrint.json
  25. +2
    -2
      src/i18n/zh/m18Sync.json
  26. +2
    -2
      src/i18n/zh/navigation.json
  27. +23
    -17
      src/i18n/zh/report.json

+ 2
- 2
src/app/(main)/laserPrint/page.tsx Просмотреть файл

@@ -4,7 +4,7 @@ import LaserPrintSearch from "@/components/LaserPrint/LaserPrintSearch";
import { Stack, Typography } from "@mui/material"; import { Stack, Typography } from "@mui/material";


export const metadata: Metadata = { export const metadata: Metadata = {
title: "檸檬機(激光機)",
title: "激光機",
}; };


export default async function LaserPrintPage() { export default async function LaserPrintPage() {
@@ -12,7 +12,7 @@ export default async function LaserPrintPage() {
<I18nProvider namespaces={["laserPrint", "navigation", "common"]}> <I18nProvider namespaces={["laserPrint", "navigation", "common"]}>
<Stack direction="row" justifyContent="space-between" flexWrap="wrap" rowGap={2}> <Stack direction="row" justifyContent="space-between" flexWrap="wrap" rowGap={2}>
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
檸檬機(激光機)
激光機
</Typography> </Typography>
</Stack> </Stack>
<LaserPrintSearch /> <LaserPrintSearch />


+ 2
- 2
src/app/(main)/m18Syn/page.tsx Просмотреть файл

@@ -318,7 +318,7 @@ export default function M18SynPage() {
label="PO Code" label="PO Code"
value={m18PoCode} value={m18PoCode}
onChange={(e) => setM18PoCode(e.target.value)} onChange={(e) => setM18PoCode(e.target.value)}
placeholder="e.g. PFP002PO26030341"
placeholder="e.g. DEMO-PO-001"
sx={{ minWidth: 320 }} sx={{ minWidth: 320 }}
/> />
<Button variant="contained" color="primary" onClick={handleSyncM18PoByCode} disabled={isSyncingM18Po}> <Button variant="contained" color="primary" onClick={handleSyncM18PoByCode} disabled={isSyncingM18Po}>
@@ -418,7 +418,7 @@ export default function M18SynPage() {
label="Item / product code" label="Item / product code"
value={m18ProductCode} value={m18ProductCode}
onChange={(e) => setM18ProductCode(e.target.value)} onChange={(e) => setM18ProductCode(e.target.value)}
placeholder="e.g. PP1175 (M18 item code)"
placeholder="e.g. DEMO-FG-01"
sx={{ minWidth: 320 }} sx={{ minWidth: 320 }}
/> />
<Button <Button


+ 3
- 3
src/app/(main)/ps/page.tsx Просмотреть файл

@@ -1179,9 +1179,9 @@ export default function ProductionSchedulePage() {
<th className="px-4 py-2 text-left font-bold text-slate-700 dark:text-slate-200">設定排期庫存</th> <th className="px-4 py-2 text-left font-bold text-slate-700 dark:text-slate-200">設定排期庫存</th>
<th className="px-4 py-2 text-right font-bold text-slate-700 dark:text-slate-200">過去平均出貨量</th> <th className="px-4 py-2 text-right font-bold text-slate-700 dark:text-slate-200">過去平均出貨量</th>
<th className="px-4 py-2 text-left font-bold text-slate-700 dark:text-slate-200">設定排期每天出貨量</th> <th className="px-4 py-2 text-left font-bold text-slate-700 dark:text-slate-200">設定排期每天出貨量</th>
<th className="px-4 py-2 text-center font-bold text-slate-700 dark:text-slate-200">咖啡</th>
<th className="px-4 py-2 text-center font-bold text-slate-700 dark:text-slate-200">茶</th>
<th className="px-4 py-2 text-center font-bold text-slate-700 dark:text-slate-200">檸檬</th>
<th className="px-4 py-2 text-center font-bold text-slate-700 dark:text-slate-200">類別 A</th>
<th className="px-4 py-2 text-center font-bold text-slate-700 dark:text-slate-200">類別 B</th>
<th className="px-4 py-2 text-center font-bold text-slate-700 dark:text-slate-200">類別 C</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>


+ 1
- 1
src/app/(main)/report/AsyncItemCodeAutocomplete.tsx Просмотреть файл

@@ -239,7 +239,7 @@ const AsyncItemCodeAutocomplete: React.FC<Props> = ({
{...params} {...params}
fullWidth fullWidth
label={label} label={label}
placeholder={hasSelection ? "" : (placeholder || "e.g. FA0591")}
placeholder={hasSelection ? "" : (placeholder || "e.g. DEMO-FG-01")}
helperText={t("typeToSearchItemCode", { min: minChars })} helperText={t("typeToSearchItemCode", { min: minChars })}
InputLabelProps={params.InputLabelProps} InputLabelProps={params.InputLabelProps}
InputProps={{ InputProps={{


+ 1
- 1
src/app/(main)/report/ItemQcReportFilters.tsx Просмотреть файл

@@ -75,7 +75,7 @@ export default function ItemQcReportFilters({
label={field("itemCode", "貨品編號 Item Code")} label={field("itemCode", "貨品編號 Item Code")}
value={criteria.itemCode || ""} value={criteria.itemCode || ""}
onChange={(e) => onFieldChange("itemCode", e.target.value)} onChange={(e) => onFieldChange("itemCode", e.target.value)}
placeholder="e.g. MJ0364"
placeholder="e.g. DEMO-FG-01"
/> />
</Grid> </Grid>
<Grid item {...gridSize}> <Grid item {...gridSize}>


+ 2
- 2
src/app/(main)/report/page.tsx Просмотреть файл

@@ -159,7 +159,7 @@ export default function ReportPage() {
if (reportId === 'rep-010') { if (reportId === 'rep-010') {
updateCriteria({ qcType: 'all', qcItemScope: 'all' }); updateCriteria({ qcType: 'all', qcItemScope: 'all' });
} else if (reportId === 'rep-004') { } else if (reportId === 'rep-004') {
updateCriteria({ storeId: 'All', poPrefix: 'All' });
updateCriteria({ storeId: 'All' });
} else if (reportId === 'rep-021') { } else if (reportId === 'rep-021') {
updateCriteria({ storeId: 'All', stockTakeSectionDescription: 'All', lotOrigin: 'All' }); updateCriteria({ storeId: 'All', stockTakeSectionDescription: 'All', lotOrigin: 'All' });
} else { } else {
@@ -727,7 +727,7 @@ export default function ReportPage() {
<Grid item {...gridSize} key={fieldKey}> <Grid item {...gridSize} key={fieldKey}>
<AsyncItemCodeAutocomplete <AsyncItemCodeAutocomplete
label={translatedLabel} label={translatedLabel}
placeholder={field.placeholder || "e.g. FA0591"}
placeholder={field.placeholder || "e.g. DEMO-FG-01"}
value={selectedCodes} value={selectedCodes}
onInputValueChange={(text) => { onInputValueChange={(text) => {
pendingItemCodeInputRef.current[field.name] = text; pendingItemCodeInputRef.current[field.name] = text;


+ 1
- 1
src/app/(main)/report/reportCategories.ts Просмотреть файл

@@ -33,6 +33,6 @@ export const REPORT_CATEGORIES: ReportCategoryConfig[] = [
headerBg: "#f5d4a8", headerBg: "#f5d4a8",
bodyBg: "#fdf6ec", bodyBg: "#fdf6ec",
accent: "#e65100", accent: "#e65100",
reportIds: ["rep-006", "rep-005", "rep-015"],
reportIds: ["rep-006", "rep-005"],
}, },
]; ];

+ 4
- 7
src/app/(main)/testing/page.tsx Просмотреть файл

@@ -560,7 +560,7 @@ export default function TestingPage() {
<Alert severity="info" sx={{ mb: 2 }}> <Alert severity="info" sx={{ mb: 2 }}>
Uses <strong>GET /py/job-orders?planStart=</strong> for the day, Uses <strong>GET /py/job-orders?planStart=</strong> for the day,
then the same <code>jobOrders</code> payload as{" "} then the same <code>jobOrders</code> payload as{" "}
<strong>Bag Print → 下載 OnPack2023檸檬機</strong>. The ZIP contains
<strong>Bag Print → 下載 OnPack 文字</strong>. The ZIP contains
loose <code>.job</code> / <code>.image</code> / BMPs — extract loose <code>.job</code> / <code>.image</code> / BMPs — extract
before sending to NGE; the ZIP itself is only a transport bundle. before sending to NGE; the ZIP itself is only a transport bundle.
</Alert> </Alert>
@@ -973,12 +973,9 @@ export default function TestingPage() {
<TabPanel value={tabValue} index={5}> <TabPanel value={tabValue} index={5}>
<Section title="6. M18 sync alert email"> <Section title="6. M18 sync alert email">
<Alert severity="info" sx={{ mb: 2 }}> <Alert severity="info" sx={{ mb: 2 }}>
Production sync errors email{" "}
<strong>[email protected]</strong> and{" "}
<strong>[email protected]</strong> (see{" "}
<code>scheduler.sync-alert.email.to-addresses</code>). WhatsApp/Twilio
is disabled. SMTP from DB <code>MAIL.smtp.*</code> (e.g. Gmail{" "}
<code>[email protected]</code> + app password).
Production sync errors email the addresses in{" "}
<code>scheduler.sync-alert.email.to-addresses</code>. WhatsApp/Twilio
is disabled. SMTP comes from DB <code>MAIL.smtp.*</code>.
</Alert> </Alert>
<Stack spacing={2} sx={{ mb: 2, maxWidth: 720 }}> <Stack spacing={2} sx={{ mb: 2, maxWidth: 720 }}>
<TextField <TextField


+ 3
- 3
src/app/api/bagPrint/actions.ts Просмотреть файл

@@ -180,7 +180,7 @@ function skippedWithoutExpiryFromResponse(res: Response): string[] {
.filter(Boolean); .filter(Boolean);
} }


/** 汁水機 OnPack — same as QR ZIP, plus LOGO_EXP BMP from item_default_shelf_life. */
/** OnPack QR — same as QR ZIP, plus LOGO_EXP BMP from item_default_shelf_life. */
export async function downloadOnPackQrZipWithExpiry( export async function downloadOnPackQrZipWithExpiry(
request: OnPackQrDownloadRequest, request: OnPackQrDownloadRequest,
): Promise<OnPackZipDownload> { ): Promise<OnPackZipDownload> {
@@ -201,7 +201,7 @@ export async function downloadOnPackQrZipWithExpiry(
}; };
} }


/** OnPack2023 檸檬機 — text QR template (`onpack2030_2`), no separate .bmp */
/** OnPack text QR template (`onpack2030_2`), no separate .bmp */
export async function downloadOnPackTextQrZip( export async function downloadOnPackTextQrZip(
request: OnPackQrDownloadRequest, request: OnPackQrDownloadRequest,
): Promise<Blob> { ): Promise<Blob> {
@@ -219,7 +219,7 @@ export async function downloadOnPackTextQrZip(
return res.blob(); return res.blob();
} }


/** OnPack2023 檸檬機 — same as text ZIP, plus TEXT_EXP from item_default_shelf_life. */
/** OnPack text QR — same as text ZIP, plus TEXT_EXP from item_default_shelf_life. */
export async function downloadOnPackTextQrZipWithExpiry( export async function downloadOnPackTextQrZipWithExpiry(
request: OnPackQrDownloadRequest, request: OnPackQrDownloadRequest,
): Promise<OnPackZipDownload> { ): Promise<OnPackZipDownload> {


+ 28
- 20
src/components/BagPrint/BagPrintSearch.tsx Просмотреть файл

@@ -82,15 +82,23 @@ const SETTINGS_KEY = "bagPrint_settings";
const DEFAULT_SETTINGS = { const DEFAULT_SETTINGS = {
dabag_ip: "", dabag_ip: "",
dabag_port: "3008", dabag_port: "3008",
laser_ip: "192.168.17.10",
laser_ip: "",
laser_port: "45678", laser_port: "45678",
}; };


const LIVE_PRINTER_HOSTS = new Set(["192.168.17.10", "192.168.18.77"]);

function loadSettings(): typeof DEFAULT_SETTINGS { function loadSettings(): typeof DEFAULT_SETTINGS {
if (typeof window === "undefined") return DEFAULT_SETTINGS; if (typeof window === "undefined") return DEFAULT_SETTINGS;
try { try {
const s = localStorage.getItem(SETTINGS_KEY); const s = localStorage.getItem(SETTINGS_KEY);
if (s) return { ...DEFAULT_SETTINGS, ...JSON.parse(s) };
if (s) {
const merged = { ...DEFAULT_SETTINGS, ...JSON.parse(s) };
if (LIVE_PRINTER_HOSTS.has(String(merged.laser_ip ?? "").trim())) {
merged.laser_ip = "";
}
return merged;
}
} catch {} } catch {}
return DEFAULT_SETTINGS; return DEFAULT_SETTINGS;
} }
@@ -467,11 +475,11 @@ const BagPrintSearch: React.FC = () => {
link.remove(); link.remove();
window.URL.revokeObjectURL(url); window.URL.revokeObjectURL(url);


setSnackbar(skippedExpirySnackbar("OnPack 汁水機(含到期日)ZIP 已下載", skippedWithoutExpiry));
setSnackbar(skippedExpirySnackbar("OnPack QR(含到期日)ZIP 已下載", skippedWithoutExpiry));
} catch (e) { } catch (e) {
setSnackbar({ setSnackbar({
open: true, open: true,
message: e instanceof Error ? e.message : "下載 OnPack 汁水機(含到期日)失敗",
message: e instanceof Error ? e.message : "下載 OnPack QR(含到期日)失敗",
severity: "error", severity: "error",
}); });
} finally { } finally {
@@ -505,11 +513,11 @@ const BagPrintSearch: React.FC = () => {
link.remove(); link.remove();
window.URL.revokeObjectURL(url); window.URL.revokeObjectURL(url);


setSnackbar({ open: true, message: "OnPack2023檸檬機 ZIP 已下載", severity: "success" });
setSnackbar({ open: true, message: "OnPack 文字 ZIP 已下載", severity: "success" });
} catch (e) { } catch (e) {
setSnackbar({ setSnackbar({
open: true, open: true,
message: e instanceof Error ? e.message : "下載 OnPack2023檸檬機 失敗",
message: e instanceof Error ? e.message : "下載 OnPack 文字 失敗",
severity: "error", severity: "error",
}); });
} finally { } finally {
@@ -544,11 +552,11 @@ const BagPrintSearch: React.FC = () => {
link.remove(); link.remove();
window.URL.revokeObjectURL(url); window.URL.revokeObjectURL(url);


setSnackbar(skippedExpirySnackbar("OnPack2023檸檬機(含到期日)ZIP 已下載", skippedWithoutExpiry));
setSnackbar(skippedExpirySnackbar("OnPack 文字(含到期日)ZIP 已下載", skippedWithoutExpiry));
} catch (e) { } catch (e) {
setSnackbar({ setSnackbar({
open: true, open: true,
message: e instanceof Error ? e.message : "下載 OnPack2023檸檬機(含到期日)失敗",
message: e instanceof Error ? e.message : "下載 OnPack 文字(含到期日)失敗",
severity: "error", severity: "error",
}); });
} finally { } finally {
@@ -597,7 +605,7 @@ const BagPrintSearch: React.FC = () => {
), ),
); );
} catch { } catch {
/* 檸檬機標籤可沒有;不擋畫面 */
/* 激光機標籤可沒有;不擋畫面 */
} }
})(); })();
}, []); }, []);
@@ -793,7 +801,7 @@ const BagPrintSearch: React.FC = () => {
jobOrders.length === 0 jobOrders.length === 0
} }
> >
{downloadingOnPack ? "下載中..." : "下載 OnPack 汁水機 QR code"}
{downloadingOnPack ? "下載中..." : "下載 OnPack QR code"}
</Button> </Button>
<Button <Button
variant="contained" variant="contained"
@@ -808,7 +816,7 @@ const BagPrintSearch: React.FC = () => {
jobOrders.length === 0 jobOrders.length === 0
} }
> >
{downloadingOnPackExp ? "下載中..." : "下載 OnPack 汁水機(含到期日)"}
{downloadingOnPackExp ? "下載中..." : "下載 OnPack QR(含到期日)"}
</Button> </Button>
<Button <Button
variant="contained" variant="contained"
@@ -824,7 +832,7 @@ const BagPrintSearch: React.FC = () => {
jobOrders.length === 0 jobOrders.length === 0
} }
> >
{downloadingOnPackText ? "下載中..." : "下載 OnPack2023檸檬機"}
{downloadingOnPackText ? "下載中..." : "下載 OnPack 文字"}
</Button> </Button>
{canSeeOnPackAdmin && ( {canSeeOnPackAdmin && (
<Button <Button
@@ -841,7 +849,7 @@ const BagPrintSearch: React.FC = () => {
jobOrders.length === 0 jobOrders.length === 0
} }
> >
{downloadingOnPackTextExp ? "下載中..." : "下載 OnPack2023檸檬機(含到期日)"}
{downloadingOnPackTextExp ? "下載中..." : "下載 OnPack 文字(含到期日)"}
</Button> </Button>
)} )}
</Stack> </Stack>
@@ -903,8 +911,8 @@ const BagPrintSearch: React.FC = () => {
{jo.itemCode || "—"} {jo.itemCode || "—"}
</Typography> </Typography>
<Stack direction="row" spacing={0.5} flexWrap="wrap" useFlexGap sx={{ mt: 0.5 }}> <Stack direction="row" spacing={0.5} flexWrap="wrap" useFlexGap sx={{ mt: 0.5 }}>
{juiceExpiryOk ? <Chip size="small" label="汁水機" color="primary" /> : null}
{lemonOk ? <Chip size="small" label="檸檬機" color="secondary" /> : null}
{juiceExpiryOk ? <Chip size="small" label="OnPack QR" color="primary" /> : null}
{lemonOk ? <Chip size="small" label="激光機" color="secondary" /> : null}
</Stack> </Stack>
</Box> </Box>
<Box sx={{ flex: 1, minWidth: 0 }}> <Box sx={{ flex: 1, minWidth: 0 }}>
@@ -1086,17 +1094,17 @@ const BagPrintSearch: React.FC = () => {
> >
<Stack spacing={1.5} sx={{ flexShrink: 0, mb: 1 }}> <Stack spacing={1.5} sx={{ flexShrink: 0, mb: 1 }}>
<Typography variant="subtitle2" color="primary"> <Typography variant="subtitle2" color="primary">
汁水機({expiryCodes.length})
OnPack QR({expiryCodes.length})
</Typography> </Typography>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
「下載 OnPack 汁水機(含到期日)」只用此清單。名稱印在 Product 行,過長可改短後按儲存。
「下載 OnPack QR(含到期日)」只用此清單。名稱印在 Product 行,過長可改短後按儲存。
點欄位標題可排序;冷藏/-18/列印第一次點擊會把「未設」排到最前。 點欄位標題可排序;冷藏/-18/列印第一次點擊會把「未設」排到最前。
</Typography> </Typography>
<Stack direction="row" spacing={1} alignItems="center"> <Stack direction="row" spacing={1} alignItems="center">
<TextField <TextField
label="新增品號" label="新增品號"
size="small" size="small"
placeholder="例如 PP2211"
placeholder="例如 DEMO-FG-01"
value={expiryCodeInput} value={expiryCodeInput}
onChange={(e) => setExpiryCodeInput(e.target.value)} onChange={(e) => setExpiryCodeInput(e.target.value)}
onKeyDown={(e) => { onKeyDown={(e) => {
@@ -1216,7 +1224,7 @@ const BagPrintSearch: React.FC = () => {
onChange={(e) => onChange={(e) =>
setNameDrafts((prev) => ({ ...prev, [row.itemCode]: e.target.value })) setNameDrafts((prev) => ({ ...prev, [row.itemCode]: e.target.value }))
} }
placeholder={row.defaultPrintName || "例如 豬肉水(1包X2千克)"}
placeholder={row.defaultPrintName || "例如 鄉村麵包"}
inputProps={{ maxLength: 255 }} inputProps={{ maxLength: 255 }}
fullWidth fullWidth
/> />
@@ -1292,7 +1300,7 @@ const BagPrintSearch: React.FC = () => {
</TableContainer> </TableContainer>
)} )}
<Typography variant="body2" color="text.secondary" sx={{ flexShrink: 0, mt: 1 }}> <Typography variant="body2" color="text.secondary" sx={{ flexShrink: 0, mt: 1 }}>
檸檬機到期日 ZIP 品號稍後加入。
激光機到期日 ZIP 品號稍後加入。
</Typography> </Typography>
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>


+ 2
- 2
src/components/DeliveryOrderFloorSettings/DeliveryOrderFloorSettings.tsx Просмотреть файл

@@ -358,8 +358,8 @@ const DeliveryOrderFloorSettings: React.FC = () => {
onChange={onFloorSelectChange} onChange={onFloorSelectChange}
disabled={dialogSaving || comboLoading} disabled={dialogSaving || comboLoading}
> >
<MenuItem value="2F">2F</MenuItem>
<MenuItem value="4F">4F</MenuItem>
<MenuItem value="2F">2/F</MenuItem>
<MenuItem value="4F">4/F</MenuItem>
</Select> </Select>
</FormControl> </FormControl>
<Button <Button


+ 23
- 1871
src/components/DetailScheduleDetail/ViewByFGDetails.tsx
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 18
- 1872
src/components/DetailedScheduleDetail/TempRecords.tsx
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 21
- 15
src/components/LaserPrint/LaserPrintSearch.tsx Просмотреть файл

@@ -83,21 +83,27 @@ const LaserPrintSearch: React.FC = () => {
message: "", message: "",
}); });
const [successSignal, setSuccessSignal] = useState<string | null>(null); const [successSignal, setSuccessSignal] = useState<string | null>(null);
const [laserHost, setLaserHost] = useState("192.168.18.77");
const [laserHost, setLaserHost] = useState("");
const [laserPort, setLaserPort] = useState("45678"); const [laserPort, setLaserPort] = useState("45678");
const [laserItemCodes, setLaserItemCodes] = useState("PP1175");
const [laserItemCodes, setLaserItemCodes] = useState("");
const [lastLaserReceive, setLastLaserReceive] = useState<LaserLastReceiveSuccess | null>(null); const [lastLaserReceive, setLastLaserReceive] = useState<LaserLastReceiveSuccess | null>(null);
const [settingsLoaded, setSettingsLoaded] = useState(false); const [settingsLoaded, setSettingsLoaded] = useState(false);
const [printerConnected, setPrinterConnected] = useState(false); const [printerConnected, setPrinterConnected] = useState(false);
const [printerMessage, setPrinterMessage] = useState("檸檬機(激光機)未連接");
const [printerMessage, setPrinterMessage] = useState("激光機未連接");
const sendInFlightRef = useRef(false); const sendInFlightRef = useRef(false);


const loadSystemSettings = useCallback(async () => { const loadSystemSettings = useCallback(async () => {
try { try {
const s = await fetchLaserBag2Settings(); const s = await fetchLaserBag2Settings();
setLaserHost(s.host);
const host = (s.host ?? "").trim();
setLaserHost(host === "192.168.18.77" || host === "192.168.17.10" ? "" : host);
setLaserPort(String(s.port)); setLaserPort(String(s.port));
setLaserItemCodes(s.itemCodes ?? "PP1175");
const itemCodes = (s.itemCodes ?? "")
.split(",")
.map((code) => code.trim())
.filter((code) => code && code !== "PP1175" && code !== "PP2211")
.join(",");
setLaserItemCodes(itemCodes);
setLastLaserReceive(s.lastReceiveSuccess ?? null); setLastLaserReceive(s.lastReceiveSuccess ?? null);
setSettingsLoaded(true); setSettingsLoaded(true);
} catch (e) { } catch (e) {
@@ -158,7 +164,7 @@ const LaserPrintSearch: React.FC = () => {
setPrinterMessage(result.message); setPrinterMessage(result.message);
} catch (e) { } catch (e) {
setPrinterConnected(false); setPrinterConnected(false);
setPrinterMessage(e instanceof Error ? e.message : "檸檬機(激光機)狀態檢查失敗");
setPrinterMessage(e instanceof Error ? e.message : "激光機狀態檢查失敗");
} }
}, []); }, []);


@@ -201,7 +207,7 @@ const LaserPrintSearch: React.FC = () => {
if (sendInFlightRef.current || sendingJobId !== null) return; if (sendInFlightRef.current || sendingJobId !== null) return;


if (!laserHost.trim()) { if (!laserHost.trim()) {
setErrorSnackbar({ open: true, message: "請在系統設定中填寫檸檬機(激光機) IP。" });
setErrorSnackbar({ open: true, message: "請在系統設定中填寫激光機 IP。" });
return; return;
} }


@@ -239,8 +245,8 @@ const LaserPrintSearch: React.FC = () => {
: ""; : "";
setSuccessSignal( setSuccessSignal(
laterFail laterFail
? `已送出 ${sentOk} 次至檸檬機(激光機)${ackHint}(後續重送失敗:${laterFail})`
: `已送出 ${sentOk} 次至檸檬機(激光機)${ackHint}`,
? `已送出 ${sentOk} 次至激光機${ackHint}(後續重送失敗:${laterFail})`
: `已送出 ${sentOk} 次至激光機${ackHint}`,
); );
await loadSystemSettings(); await loadSystemSettings();
} catch (e) { } catch (e) {
@@ -287,7 +293,7 @@ const LaserPrintSearch: React.FC = () => {
{lastLaserReceive.source ? ` (${lastLaserReceive.source === "AUTO" ? "自動送出" : "手動點選"})` : ""} {lastLaserReceive.source ? ` (${lastLaserReceive.source === "AUTO" ? "自動送出" : "手動點選"})` : ""}
</Typography> </Typography>
<Typography variant="body2" sx={{ mt: 0.5 }}> <Typography variant="body2" sx={{ mt: 0.5 }}>
此時間只會在檸檬機回覆 receive 時更新。之後送出失敗不會改這裡。
此時間只會在激光機回覆 receive 時更新。之後送出失敗不會改這裡。
</Typography> </Typography>
</Alert> </Alert>
)} )}
@@ -332,7 +338,7 @@ const LaserPrintSearch: React.FC = () => {
}} }}
title={printerMessage} title={printerMessage}
> >
檸檬機(激光機):
激光機:
</Box> </Box>
</Stack> </Stack>
</Stack> </Stack>
@@ -420,11 +426,11 @@ const LaserPrintSearch: React.FC = () => {
</Paper> </Paper>


<Dialog open={settingsOpen} onClose={() => setSettingsOpen(false)} maxWidth="sm" fullWidth> <Dialog open={settingsOpen} onClose={() => setSettingsOpen(false)} maxWidth="sm" fullWidth>
<DialogTitle>檸檬機(激光機)(系統設定)</DialogTitle>
<DialogTitle>激光機(系統設定)</DialogTitle>
<DialogContent> <DialogContent>
<Stack spacing={2} sx={{ mt: 1 }}> <Stack spacing={2} sx={{ mt: 1 }}>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
儲存後寫入資料庫,後端送出走此 IP/埠(預設 192.168.18.77:45678)。
儲存後寫入資料庫,後端送出走此 IP/埠。未填 IP 則不會送出。
</Typography> </Typography>
<TextField <TextField
label="IP" label="IP"
@@ -446,8 +452,8 @@ const LaserPrintSearch: React.FC = () => {
value={laserItemCodes} value={laserItemCodes}
onChange={(e) => setLaserItemCodes(e.target.value)} onChange={(e) => setLaserItemCodes(e.target.value)}
fullWidth fullWidth
placeholder="PP1175"
helperText="預設 PP1175;可輸入多個品號,例如 PP1175,AB999。留空則列表顯示當日全部包裝工單。"
placeholder="例如 DEMO-FG-01"
helperText="可輸入多個品號,例如 DEMO-FG-01,DEMO-FG-02。留空則列表顯示當日全部包裝工單。"
/> />
</Stack> </Stack>
</DialogContent> </DialogContent>


+ 2
- 2
src/components/PoDetail/PutAwayForm.tsx Просмотреть файл

@@ -116,7 +116,7 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse=[], disabled, sugg
group: "default", group: "default",
}; };
const options = useMemo(() => { const options = useMemo(() => {
const defaultLabel = suggestedLocationCode || t("W201 - 2F-A,B室");
const defaultLabel = suggestedLocationCode || t("Select warehouse");
return [ return [
{ value: 1, label: defaultLabel, group: "default" }, { value: 1, label: defaultLabel, group: "default" },
...filteredWarehouse.map((w) => ({ ...filteredWarehouse.map((w) => ({
@@ -260,7 +260,7 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse=[], disabled, sugg
editable: false, editable: false,
renderCell(params) { renderCell(params) {
const value = (params.value as string) ?? ""; const value = (params.value as string) ?? "";
// 目前格式像 "2F-W201-#L-08 - 2F-W201",只要左邊 LocationCode
// Location label is "code - description"; keep the code on the left.
const locationCode = value.split(" - ")[0] || value; const locationCode = value.split(" - ")[0] || value;
return ( return (


+ 29
- 34
src/components/PoWorkbench/detailsGrid/poWorkbenchDetailsGridMock.ts Просмотреть файл

@@ -5,72 +5,67 @@ export const PO_WORKBENCH_DETAILS_GRID_MOCK_ROWS: readonly PoWorkbenchDetailsGri
[ [
{ {
id: "mock-line-1", id: "mock-line-1",
itemName:
"澳洲和牛腱(冷凍)· A5級去筋切片裝 2.5kg×4包/箱(供應商批次:AU-WG-2026-Q1)",
itemCode: "AB1234",
itemName: "普通麵粉",
itemCode: "DEMO-RM-01",
category: "material", category: "material",
storageLocation: "YF-W201-#A-12",
storageLocation: "DEMO-A-#A-01",
receiveStatus: "pending", receiveStatus: "pending",
expectedQty: 100, expectedQty: 100,
purchaseUnitLabel: "1箱X100包X150克",
purchaseUnitLabel: "1袋X25公斤",
receivedQtyPurchase: 0, receivedQtyPurchase: 0,
receivedQtyInventory: 0, receivedQtyInventory: 0,
inventoryUnitLabel: "克",
inventoryUnitLabel: "公斤",
}, },
{ {
id: "mock-line-2", id: "mock-line-2",
itemName:
"耐高温真空膠袋(食品級)· 300×450mm 厚度80μm 每卷500個(雙層密封條)",
itemCode: "BC5678",
itemName: "鮮奶",
itemCode: "DEMO-RM-02",
category: "consumable", category: "consumable",
storageLocation: "YF-C305-#B-04",
storageLocation: "DEMO-B-#B-02",
receiveStatus: "receiving", receiveStatus: "receiving",
expectedQty: 24, expectedQty: 24,
purchaseUnitLabel: "1箱X24卷X500個",
receivedQtyPurchase: 26,
receivedQtyInventory: 312000,
inventoryUnitLabel: "個",
purchaseUnitLabel: "1箱X12瓶X1升",
receivedQtyPurchase: 12,
receivedQtyInventory: 12,
inventoryUnitLabel: "升",
}, },
{ {
id: "mock-line-3", id: "mock-line-3",
itemName:
"照燒汁(商用濃縮裝)· 日式醬油基底 5L/桶(開封後需冷藏,效期見標籤)",
itemCode: "FG9012",
itemName: "鄉村麵包",
itemCode: "DEMO-FG-01",
category: "finishedGoods", category: "finishedGoods",
storageLocation: "YF-D102-#C-08",
storageLocation: "DEMO-A-#C-03",
receiveStatus: "completed", receiveStatus: "completed",
expectedQty: 48, expectedQty: 48,
purchaseUnitLabel: "1板X4桶X5升",
purchaseUnitLabel: "1箱X8個",
receivedQtyPurchase: 48, receivedQtyPurchase: 48,
receivedQtyInventory: 960,
inventoryUnitLabel: "升",
receivedQtyInventory: 48,
inventoryUnitLabel: "個",
}, },
{ {
id: "mock-line-4", id: "mock-line-4",
itemName:
"高筋麵粉預拌漿(半成品)· 中央廚房標準配方 20kg/袋(含酵母改良劑)",
itemCode: "DE3456",
itemName: "麵團",
itemCode: "DEMO-SF-01",
category: "semiFinished", category: "semiFinished",
storageLocation: "YF-W118-#D-22",
storageLocation: "DEMO-A-#D-04",
receiveStatus: "receiving", receiveStatus: "receiving",
expectedQty: 60, expectedQty: 60,
purchaseUnitLabel: "1板X3袋X20公斤",
receivedQtyPurchase: 55,
receivedQtyInventory: 3300,
purchaseUnitLabel: "1袋X10公斤",
receivedQtyPurchase: 40,
receivedQtyInventory: 40,
inventoryUnitLabel: "公斤", inventoryUnitLabel: "公斤",
}, },
{ {
id: "mock-line-5", id: "mock-line-5",
itemName:
"廚房多功能清潔劑(濃縮原液)· 無磷配方 1L×12瓶/箱(勿與漂白水混用)",
itemCode: "EF7890",
itemName: "奶包",
itemCode: "DEMO-FG-02",
category: "miscNonConsumable", category: "miscNonConsumable",
storageLocation: "YF-M402-#E-01",
storageLocation: "DEMO-B-#E-05",
receiveStatus: "pending", receiveStatus: "pending",
expectedQty: 120, expectedQty: 120,
purchaseUnitLabel: "1扎X3箱X12包X350克",
purchaseUnitLabel: "1箱X20個",
receivedQtyPurchase: 0, receivedQtyPurchase: 0,
receivedQtyInventory: 0, receivedQtyInventory: 0,
inventoryUnitLabel: "瓶",
inventoryUnitLabel: "個",
}, },
] as const; ] as const;

+ 2
- 2
src/components/ProductionProcess/ProductionProcessDetail.tsx Просмотреть файл

@@ -315,7 +315,7 @@ const fetchProcessDetailRef = useRef<() => Promise<void>>();
const processQrCode = useCallback((qrValue: string, lineId: number) => { const processQrCode = useCallback((qrValue: string, lineId: number) => {
// 设备快捷格式:{2fitesteXXX} - XXX 直接作为设备代码 // 设备快捷格式:{2fitesteXXX} - XXX 直接作为设备代码
// 格式:{2fitesteXXX} = equipmentCode: "XXX" // 格式:{2fitesteXXX} = equipmentCode: "XXX"
// 例如:{2fiteste包裝機類-真空八爪魚機-1號} = equipmentCode: "包裝機類-真空八爪魚機-1號"
// 例如:{2fitesteDEMO-EQ-01} = equipmentCode: "DEMO-EQ-01"
if (qrValue.match(/\{2fiteste(.+)\}/)) { if (qrValue.match(/\{2fiteste(.+)\}/)) {
const match = qrValue.match(/\{2fiteste(.+)\}/); const match = qrValue.match(/\{2fiteste(.+)\}/);
const equipmentCode = match![1]; const equipmentCode = match![1];
@@ -371,7 +371,7 @@ const processQrCode = useCallback((qrValue: string, lineId: number) => {
// 可能是员工编号 // 可能是员工编号
setScannedStaffNo(trimmedValue); setScannedStaffNo(trimmedValue);
} else if (trimmedValue.includes("-")) { } else if (trimmedValue.includes("-")) {
// 可能包含 "-" 的是设备代码(如 "包裝機類-真空八爪魚機-1號")
// 可能包含 "-" 的是设备代码(如 "DEMO-EQ-01")
setScannedEquipmentCode(trimmedValue); setScannedEquipmentCode(trimmedValue);
} }
} }


+ 11
- 2911
src/components/RoughScheduleDetail/TempRecords.tsx
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 35
- 71
src/config/reportConfig.ts Просмотреть файл

@@ -54,9 +54,20 @@ const asyncItemCodeField = (
multiple: true, multiple: true,
allowInput: true, allowInput: true,
asyncSearch: true, asyncSearch: true,
placeholder: "e.g. FA0591",
placeholder: "e.g. DEMO-FG-01",
}); });


const floorOptionsAll: ReportField["options"] = [
{ label: "全部", value: "All" },
{ label: "2/F", value: "2/F" },
{ label: "4/F", value: "4/F" },
];

const floorOptions: ReportField["options"] = [
{ label: "2/F", value: "2/F" },
{ label: "4/F", value: "4/F" },
];

const pasteItemCodeField = (): ReportField => ({ const pasteItemCodeField = (): ReportField => ({
label: "貼上貨品編號 Paste Item Codes", label: "貼上貨品編號 Paste Item Codes",
name: "itemCodePaste", name: "itemCodePaste",
@@ -124,29 +135,12 @@ export const REPORTS: ReportDefinition[] = [
name: "storeId", name: "storeId",
type: "select", type: "select",
required: false, required: false,
options: [
{ label: "全部", value: "All" },
{ label: "1F", value: "1F" },
{ label: "2F", value: "2F" },
{ label: "3F", value: "3F" },
{ label: "4F", value: "4F" },
],
options: floorOptionsAll,
}, },
{ label: "倉庫 Warehouse", name: "warehouse", type: "text", required: false, placeholder: "e.g. W201" },
{ label: "倉庫 Warehouse", name: "warehouse", type: "text", required: false, placeholder: "e.g. DEMO-A" },
{ label: "區域 Area", name: "area", type: "text", required: false, placeholder: "e.g. #A" }, { label: "區域 Area", name: "area", type: "text", required: false, placeholder: "e.g. #A" },
{ label: "儲位 Slot", name: "slot", type: "text", required: false, placeholder: "e.g. 01" }, { label: "儲位 Slot", name: "slot", type: "text", required: false, placeholder: "e.g. 01" },
{ label: "批號 Lot No", name: "lotNo", type: "text", required: false, placeholder: "e.g. LT-202608" }, { label: "批號 Lot No", name: "lotNo", type: "text", required: false, placeholder: "e.g. LT-202608" },
{
label: "PP/PF 分類",
name: "poPrefix",
type: "select",
required: false,
options: [
{ label: "全部", value: "All" },
{ label: "PP", value: "PP" },
{ label: "PF", value: "PF" },
],
},
] ]
}, },
{ {
@@ -193,13 +187,7 @@ export const REPORTS: ReportDefinition[] = [
name: "store_id", name: "store_id",
type: "select", type: "select",
required: false, required: false,
options: [
{ label: "全部", value: "All" },
{ label: "1F", value: "1F" },
{ label: "2F", value: "2F" },
{ label: "3F", value: "3F" },
{ label: "4F", value: "4F" }
],
options: floorOptionsAll,
}, },
{ {
label: "狀態", label: "狀態",
@@ -220,14 +208,11 @@ export const REPORTS: ReportDefinition[] = [
multiple: true, multiple: true,
options: [ options: [
{ label: "全部", value: "All" }, { label: "全部", value: "All" },
{ label: "PP", value: "PP" },
{ label: "PF", value: "PF" },
{ label: "TOA", value: "TOA" },
{ label: "工廠生產", value: "工廠生產" },
{ label: "倉存調整", value: "倉存調整" },
{ label: "期初存貨", value: "期初存貨" },
{ label: "採購入倉", value: "採購入倉" },
{ label: "其他入倉", value: "其他入倉" },
{ label: "採購", value: "purchase" },
{ label: "生產", value: "production" },
{ label: "倉存調整", value: "adjustment" },
{ label: "期初存貨", value: "opening" },
{ label: "其他", value: "other" },
], ],
}, },
] ]
@@ -241,19 +226,13 @@ export const REPORTS: ReportDefinition[] = [
fields: [ fields: [
{ label: "庫存日期 Stock Date(僅今天)", name: "stockDate", type: "date", required: true, disabled: true }, { label: "庫存日期 Stock Date(僅今天)", name: "stockDate", type: "date", required: true, disabled: true },
{ label: "貨品編號 Item Code", name: "itemCode", type: "text", required: false }, { label: "貨品編號 Item Code", name: "itemCode", type: "text", required: false },
{ label: "倉位 Warehouse Code", name: "warehouseCode", type: "text", required: false, placeholder: "e.g. W200 or 2F-W200-#A-00" },
{ label: "倉位 Warehouse Code", name: "warehouseCode", type: "text", required: false, placeholder: "e.g. DEMO-A" },
{ {
label: "樓層 Store ID", label: "樓層 Store ID",
name: "storeId", name: "storeId",
type: "select", type: "select",
required: false, required: false,
options: [
{ label: "全部", value: "All" },
{ label: "1F", value: "1F" },
{ label: "2F", value: "2F" },
{ label: "3F", value: "3F" },
{ label: "4F", value: "4F" },
],
options: floorOptionsAll,
}, },
{ label: "批號 Lot No", name: "lotNo", type: "text", required: false, placeholder: "e.g. LT-202608" }, { label: "批號 Lot No", name: "lotNo", type: "text", required: false, placeholder: "e.g. LT-202608" },
], ],
@@ -271,15 +250,9 @@ export const REPORTS: ReportDefinition[] = [
name: "storeId", name: "storeId",
type: "select", type: "select",
required: false, required: false,
options: [
{ label: "全部", value: "All" },
{ label: "1F", value: "1F" },
{ label: "2F", value: "2F" },
{ label: "3F", value: "3F" },
{ label: "4F", value: "4F" },
],
options: floorOptionsAll,
}, },
{ label: "倉庫 Warehouse", name: "warehouse", type: "text", required: false, placeholder: "e.g. W201" },
{ label: "倉庫 Warehouse", name: "warehouse", type: "text", required: false, placeholder: "e.g. DEMO-A" },
{ label: "區域 Area", name: "area", type: "text", required: false, placeholder: "e.g. #A" }, { label: "區域 Area", name: "area", type: "text", required: false, placeholder: "e.g. #A" },
{ label: "儲位 Slot", name: "slot", type: "text", required: false, placeholder: "e.g. 02" }, { label: "儲位 Slot", name: "slot", type: "text", required: false, placeholder: "e.g. 02" },
{ {
@@ -299,8 +272,8 @@ export const REPORTS: ReportDefinition[] = [
required: false, required: false,
options: [ options: [
{ label: "全部", value: "All" }, { label: "全部", value: "All" },
{ label: "PP", value: "PP" },
{ label: "PF", value: "PF" },
{ label: "採購", value: "purchase" },
{ label: "生產", value: "production" },
{ label: "其他", value: "other" }, { label: "其他", value: "other" },
], ],
}, },
@@ -442,12 +415,10 @@ export const REPORTS: ReportDefinition[] = [
{ label: "類別 Category", name: "stockCategory", type: "select", required: false, { label: "類別 Category", name: "stockCategory", type: "select", required: false,
multiple: true, multiple: true,
options: [ options: [
{ label: "All", value: "All" },
{ label: "MAT", value: "MAT" },
{ label: "WIP", value: "WIP" },
{ label: "NM", value: "NM" },
{ label: "FG", value: "FG" },
{ label: "CMB", value: "CMB" }
{ label: "全部", value: "All" },
{ label: "原料", value: "mat" },
{ label: "半成品", value: "sfg" },
{ label: "成品", value: "fg" },
] }, ] },
{ label: "貨品編號 Item Code", name: "itemCode", type: "select", required: false, { label: "貨品編號 Item Code", name: "itemCode", type: "select", required: false,
multiple: true, multiple: true,
@@ -472,9 +443,9 @@ export const REPORTS: ReportDefinition[] = [
{ label: "類別 Category", name: "stockCategory", type: "select", required: false, { label: "類別 Category", name: "stockCategory", type: "select", required: false,
multiple: true, multiple: true,
options: [ options: [
{ label: "All", value: "All" },
{ label: "WIP", value: "WIP" },
{ label: "FG", value: "FG" },
{ label: "全部", value: "All" },
{ label: "半成品", value: "sfg" },
{ label: "成品", value: "fg" },
] }, ] },
{ label: "貨品編號 Item Code", name: "itemCode", type: "select", required: false, { label: "貨品編號 Item Code", name: "itemCode", type: "select", required: false,
multiple: true, multiple: true,
@@ -533,10 +504,7 @@ export const REPORTS: ReportDefinition[] = [
name: "storeId", name: "storeId",
type: "select", type: "select",
required: false, required: false,
options: [
{ label: "2F", value: "2F" },
{ label: "4F", value: "4F" },
],
options: floorOptions,
}, },
], ],
}, },
@@ -574,11 +542,7 @@ export const REPORTS: ReportDefinition[] = [
name: "storeId", name: "storeId",
type: "select", type: "select",
required: false, required: false,
options: [
{ label: "全部", value: "All" },
{ label: "2F", value: "2F" },
{ label: "4F", value: "4F" },
],
options: floorOptionsAll,
}, },
], ],
}, },

+ 6
- 6
src/i18n/en/deliveryOrderFloor.json Просмотреть файл

@@ -1,12 +1,12 @@
{ {
"title": "Delivery order / workbench floor (supplier codes)", "title": "Delivery order / workbench floor (supplier codes)",
"Intro": "Manage supplier codes assigned to each floor. Use the edit button to add or remove suppliers from a floor.", "Intro": "Manage supplier codes assigned to each floor. Use the edit button to add or remove suppliers from a floor.",
"2F supplier": "2F supplier",
"4F supplier": "4F supplier",
"Edit 2F": "Edit 2F",
"Edit 4F": "Edit 4F",
"Edit 2F title": "Edit 2F supplier codes",
"Edit 4F title": "Edit 4F supplier codes",
"2F supplier": "2/F supplier",
"4F supplier": "4/F supplier",
"Edit 2F": "Edit 2/F",
"Edit 4F": "Edit 4/F",
"Edit 2F title": "Edit 2/F supplier codes",
"Edit 4F title": "Edit 4/F supplier codes",
"Edit dialog title": "Edit floor–supplier mapping", "Edit dialog title": "Edit floor–supplier mapping",
"Floor label": "Floor", "Floor label": "Floor",
"Add mapping": "Add mapping", "Add mapping": "Add mapping",


+ 2
- 2
src/i18n/en/m18Sync.json Просмотреть файл

@@ -20,10 +20,10 @@
"btnSyncDoExtra": "Sync DO (Extra) from M18", "btnSyncDoExtra": "Sync DO (Extra) from M18",
"btnSyncProduct": "Sync product from M18", "btnSyncProduct": "Sync product from M18",
"syncing": "Syncing...", "syncing": "Syncing...",
"placeholderPoCode": "e.g. PFP002PO26030341",
"placeholderPoCode": "e.g. DEMO-PO-001",
"placeholderDoCode": "e.g. same document code as M18 shop PO", "placeholderDoCode": "e.g. same document code as M18 shop PO",
"placeholderDoExtraCode": "Enter multiple codes separated by comma or newline", "placeholderDoExtraCode": "Enter multiple codes separated by comma or newline",
"placeholderProductCode": "e.g. PP1175 (M18 item code)",
"placeholderProductCode": "e.g. DEMO-FG-01",
"waiting": "Waiting for implementation...", "waiting": "Waiting for implementation...",
"noResponse": "No response received", "noResponse": "No response received",
"alreadyExists": "{{docName}} already exists in system", "alreadyExists": "{{docName}} already exists in system",


+ 23
- 17
src/i18n/en/report.json Просмотреть файл

@@ -57,17 +57,11 @@
"warehouse": "Warehouse", "warehouse": "Warehouse",
"area": "Area", "area": "Area",
"slot": "Slot", "slot": "Slot",
"lotNo": "Lot No",
"poPrefix": "PP/PF"
"lotNo": "Lot No"
}, },
"options": { "options": {
"storeId": { "storeId": {
"All": "All" "All": "All"
},
"poPrefix": {
"All": "All",
"PP": "PP",
"PF": "PF"
} }
}, },
"fieldHints": { "fieldHints": {
@@ -107,14 +101,11 @@
}, },
"type": { "type": {
"All": "All", "All": "All",
"PP": "PP",
"PF": "PF",
"TOA": "TOA",
"工廠生產": "Factory production",
"倉存調整": "Inventory adjustment",
"期初存貨": "Opening inventory",
"採購入倉": "Purchase inbound",
"其他入倉": "Other inbound"
"purchase": "Purchase",
"production": "Production",
"adjustment": "Inventory adjustment",
"opening": "Opening inventory",
"other": "Other"
} }
} }
}, },
@@ -208,6 +199,14 @@
}, },
"fieldHints": { "fieldHints": {
"itemCodePaste": "Paste item codes from Excel. Separate with spaces, commas, or new lines" "itemCodePaste": "Paste item codes from Excel. Separate with spaces, commas, or new lines"
},
"options": {
"stockCategory": {
"All": "All",
"mat": "Material",
"sfg": "Semi-finished",
"fg": "Finished goods"
}
} }
}, },
"rep-005": { "rep-005": {
@@ -222,6 +221,13 @@
}, },
"fieldHints": { "fieldHints": {
"itemCodePaste": "Paste item codes from Excel. Separate with spaces, commas, or new lines" "itemCodePaste": "Paste item codes from Excel. Separate with spaces, commas, or new lines"
},
"options": {
"stockCategory": {
"All": "All",
"sfg": "Semi-finished",
"fg": "Finished goods"
}
} }
}, },
"rep-015": { "rep-015": {
@@ -295,8 +301,8 @@
}, },
"lotOrigin": { "lotOrigin": {
"All": "All", "All": "All",
"PP": "PP",
"PF": "PF",
"purchase": "Purchase",
"production": "Production",
"other": "Other" "other": "Other"
} }
} }


+ 6
- 6
src/i18n/zh/deliveryOrderFloor.json Просмотреть файл

@@ -1,12 +1,12 @@
{ {
"title": "送貨單樓層設定(供應商代碼)", "title": "送貨單樓層設定(供應商代碼)",
"Intro": "管理各樓層的供應商代碼。點擊編輯按鈕可新增或移除供應商。", "Intro": "管理各樓層的供應商代碼。點擊編輯按鈕可新增或移除供應商。",
"2F supplier": "2F 供應商",
"4F supplier": "4F 供應商",
"Edit 2F": "編輯 2F",
"Edit 4F": "編輯 4F",
"Edit 2F title": "編輯 2F 供應商代碼",
"Edit 4F title": "編輯 4F 供應商代碼",
"2F supplier": "2/F 供應商",
"4F supplier": "4/F 供應商",
"Edit 2F": "編輯 2/F",
"Edit 4F": "編輯 4/F",
"Edit 2F title": "編輯 2/F 供應商代碼",
"Edit 4F title": "編輯 4/F 供應商代碼",
"Edit dialog title": "編輯樓層供應商映射", "Edit dialog title": "編輯樓層供應商映射",
"Floor label": "樓層", "Floor label": "樓層",
"Add mapping": "新增映射", "Add mapping": "新增映射",


+ 1
- 1
src/i18n/zh/laserPrint.json Просмотреть файл

@@ -1,3 +1,3 @@
{ {
"title": "檸檬機(激光機)"
"title": "激光機"
} }

+ 2
- 2
src/i18n/zh/m18Sync.json Просмотреть файл

@@ -20,10 +20,10 @@
"btnSyncDoExtra": "從 M18 同步送貨訂單(加單)", "btnSyncDoExtra": "從 M18 同步送貨訂單(加單)",
"btnSyncProduct": "從 M18 同步貨品", "btnSyncProduct": "從 M18 同步貨品",
"syncing": "同步中…", "syncing": "同步中…",
"placeholderPoCode": "例:PFP002PO26030341",
"placeholderPoCode": "例:DEMO-PO-001",
"placeholderDoCode": "例:與 M18 店鋪訂單相同的文件編號", "placeholderDoCode": "例:與 M18 店鋪訂單相同的文件編號",
"placeholderDoExtraCode": "可輸入多個 code,用逗號或換行分隔", "placeholderDoExtraCode": "可輸入多個 code,用逗號或換行分隔",
"placeholderProductCode": "例:PP1175(M18 貨品編號)",
"placeholderProductCode": "例:DEMO-FG-01",
"waiting": "等待實作…", "waiting": "等待實作…",
"noResponse": "未收到回應", "noResponse": "未收到回應",
"alreadyExists": "{{docName}}已存在系統", "alreadyExists": "{{docName}}已存在系統",


+ 2
- 2
src/i18n/zh/navigation.json Просмотреть файл

@@ -25,7 +25,7 @@
"nav.breadcrumb.joEdit": "工單詳情", "nav.breadcrumb.joEdit": "工單詳情",
"nav.breadcrumb.joTesting": "工單測試", "nav.breadcrumb.joTesting": "工單測試",
"nav.breadcrumb.joWorkbench": "工單工作台", "nav.breadcrumb.joWorkbench": "工單工作台",
"nav.breadcrumb.laserPrint": "檸檬機(激光機)",
"nav.breadcrumb.laserPrint": "激光機",
"nav.breadcrumb.m18Sync": "M18 同步", "nav.breadcrumb.m18Sync": "M18 同步",
"nav.breadcrumb.poEdit": "編輯", "nav.breadcrumb.poEdit": "編輯",
"nav.breadcrumb.poWorkbench": "採購單工作台", "nav.breadcrumb.poWorkbench": "採購單工作台",
@@ -64,7 +64,7 @@
"nav.jobOrder.productionProcess": "工單生產流程", "nav.jobOrder.productionProcess": "工單生產流程",
"nav.jobOrder.searchCreate": "搜索工單/ 建立工單", "nav.jobOrder.searchCreate": "搜索工單/ 建立工單",
"nav.jobOrderManagement": "管理工單", "nav.jobOrderManagement": "管理工單",
"nav.laserPrint": "檸檬機(激光機)",
"nav.laserPrint": "激光機",
"nav.m18Sync": "M18 同步", "nav.m18Sync": "M18 同步",
"nav.productionServer": "正式伺服器", "nav.productionServer": "正式伺服器",
"nav.report": "報告管理", "nav.report": "報告管理",


+ 23
- 17
src/i18n/zh/report.json Просмотреть файл

@@ -57,17 +57,11 @@
"warehouse": "倉庫", "warehouse": "倉庫",
"area": "區域", "area": "區域",
"slot": "儲位", "slot": "儲位",
"lotNo": "批號",
"poPrefix": "PP/PF 分類"
"lotNo": "批號"
}, },
"options": { "options": {
"storeId": { "storeId": {
"All": "全部" "All": "全部"
},
"poPrefix": {
"All": "全部",
"PP": "PP",
"PF": "PF"
} }
}, },
"fieldHints": { "fieldHints": {
@@ -107,14 +101,11 @@
}, },
"type": { "type": {
"All": "全部", "All": "全部",
"PP": "PP",
"PF": "PF",
"TOA": "TOA",
"工廠生產": "工廠生產",
"倉存調整": "倉存調整",
"期初存貨": "期初存貨",
"採購入倉": "採購入倉",
"其他入倉": "其他入倉"
"purchase": "採購",
"production": "生產",
"adjustment": "倉存調整",
"opening": "期初存貨",
"other": "其他"
} }
} }
}, },
@@ -208,6 +199,14 @@
}, },
"fieldHints": { "fieldHints": {
"itemCodePaste": "可從 Excel 貼上多個貨品編號,以空格、逗號或換行分隔" "itemCodePaste": "可從 Excel 貼上多個貨品編號,以空格、逗號或換行分隔"
},
"options": {
"stockCategory": {
"All": "全部",
"mat": "原料",
"sfg": "半成品",
"fg": "成品"
}
} }
}, },
"rep-005": { "rep-005": {
@@ -222,6 +221,13 @@
}, },
"fieldHints": { "fieldHints": {
"itemCodePaste": "可從 Excel 貼上多個貨品編號,以空格、逗號或換行分隔" "itemCodePaste": "可從 Excel 貼上多個貨品編號,以空格、逗號或換行分隔"
},
"options": {
"stockCategory": {
"All": "全部",
"sfg": "半成品",
"fg": "成品"
}
} }
}, },
"rep-015": { "rep-015": {
@@ -295,8 +301,8 @@
}, },
"lotOrigin": { "lotOrigin": {
"All": "全部", "All": "全部",
"PP": "PP",
"PF": "PF",
"purchase": "採購",
"production": "生產",
"other": "其他" "other": "其他"
} }
} }


Загрузка…
Отмена
Сохранить