|
- "use client";
- import React, { useState, useRef } from "react";
- import { MachineQrCode } from "./types";
- import {
- Button,
- TextField,
- Typography,
- Paper,
- Box,
- IconButton,
- Stack,
- } from "@mui/material";
- import CloseIcon from "@mui/icons-material/Close";
- import { isCorrectMachineUsed } from "@/app/api/jo/actions";
- import { Machine } from "@/app/api/jo";
- import { useTranslation } from "react-i18next";
-
- interface MachineScannerProps {
- machines: Machine[];
- onMachinesChange: (machines: Machine[]) => void;
- error?: string;
- isActive?: boolean;
- onActivate?: () => void;
- onDeactivate?: () => void;
- }
-
- const machineDatabase: Machine[] = [
- { id: 1, name: "CNC Mill #1", code: "CNC001", qrCode: "QR-CNC001" },
- { id: 2, name: "Lathe #2", code: "LAT002", qrCode: "QR-LAT002" },
- { id: 3, name: "Press #3", code: "PRS003", qrCode: "QR-PRS003" },
- { id: 4, name: "Welder #4", code: "WLD004", qrCode: "QR-WLD004" },
- { id: 5, name: "Drill Press #5", code: "DRL005", qrCode: "QR-DRL005" },
- ];
-
- const MachineScanner: React.FC<MachineScannerProps> = ({
- machines,
- onMachinesChange,
- error,
- isActive=false,
- onActivate,
- onDeactivate,
- }) => {
- const [scanningMode, setScanningMode] = useState<boolean>(false);
- const [scanError, setScanError] = useState<string | null>(null);
- const machineScanRef = useRef<HTMLInputElement>(null);
- const { t } = useTranslation();
-
- const startScanning = (): void => {
- setScanningMode(true);
- onActivate?.();
- setTimeout(() => {
- if (machineScanRef.current) {
- machineScanRef.current.focus();
- }
- }, 100);
- };
-
- const stopScanning = (): void => {
- setScanningMode(false);
- onDeactivate?.();
- };
-
- const handleMachineScan = async (
- e: React.KeyboardEvent<HTMLInputElement>,
- ): Promise<void> => {
- const target = e.target as HTMLInputElement;
- let scannedInput = target.value.trim();
-
- if (e.key === "Enter" || scannedInput.endsWith("}")) {
- console.log("Raw machine input:", scannedInput);
-
- try {
- let machineCode: string;
-
- // 尝试解析 JSON
- try {
- const scannedObj: MachineQrCode = JSON.parse(scannedInput);
- machineCode = scannedObj.code;
- } catch (jsonError) {
- // 如果不是 JSON,尝试从花括号中提取
- const match = scannedInput.match(/\{([^}?]+)\??}?/);
- if (match && match[1]) {
- machineCode = match[1].trim();
- console.log("Extracted machine code from braces:", machineCode);
- } else {
- // 如果没有花括号,直接使用输入值
- machineCode = scannedInput.replace(/[{}?]/g, '').trim();
- console.log("Using plain machine code:", machineCode);
- }
- }
-
- if (!machineCode) {
- setScanError("Invalid input format");
- return;
- }
-
- // 首先尝试从 API 获取
- const response = await isCorrectMachineUsed(machineCode);
-
- if (response.message === "Success") {
- const isAlreadyAdded = machines.some(
- (m) => m.code === response.entity.code,
- );
-
- if (!isAlreadyAdded) {
- onMachinesChange([...machines, response.entity]);
- }
-
- target.value = "";
- setScanError(null);
- } else {
- // 如果 API 失败,尝试从本地默认数据查找
- const localMachine = machineDatabase.find(
- (m) => m.code.toLowerCase() === machineCode.toLowerCase()
- );
-
- if (localMachine) {
- const isAlreadyAdded = machines.some(
- (m) => m.code === localMachine.code
- );
-
- if (!isAlreadyAdded) {
- onMachinesChange([...machines, localMachine]);
- }
-
- target.value = "";
- setScanError(null);
- console.log(" Used local machine data:", localMachine);
- } else {
- setScanError(
- "Machine not found. Please check the code and try again."
- );
- target.value = "";
- }
- }
- } catch (error) {
- console.error("Error processing machine scan:", error);
- setScanError(
- "An error occurred while checking the machine. Please try again."
- );
- target.value = "";
- }
- }
- };
-
- const removeMachine = (machineId: number): void => {
- onMachinesChange(machines.filter((m) => m.id !== machineId));
- };
-
- return (
- <Box>
- <Stack
- direction="row"
- alignItems="center"
- justifyContent="space-between"
- mb={2}
- >
- <Typography variant="h6" fontWeight={600}>
- Machines *
- </Typography>
- <Button
- variant={scanningMode ? "contained" : "outlined"}
- color={scanningMode ? "success" : "primary"}
- onClick={startScanning}
- >
- {scanningMode ? "Scanning..." : "Scan QR Code"}
- </Button>
- </Stack>
-
- {scanningMode && (
- <Paper
- elevation={2}
- sx={{
- mb: 2,
- p: 2,
- bgcolor: "green.50",
- border: "1px solid",
- borderColor: "green.200",
- }}
- >
- <Stack direction="row" alignItems="center" spacing={2}>
- <TextField
- inputRef={machineScanRef}
- type="text"
- onKeyDown={handleMachineScan}
- fullWidth
- label="Scan machine QR code or enter manually..."
- variant="outlined"
- size="small"
- sx={{ bgcolor: "white" }}
- />
- <Button variant="contained" color="inherit" onClick={stopScanning}>
- Cancel
- </Button>
- </Stack>
- {scanError ? (
- <Typography variant="body2" color="error" mt={1}>
- {scanError}
- </Typography>
- ) : (
- <Typography variant="body2" color="success.main" mt={1}>
- {t(
- "Position the QR code scanner and scan, or type the machine code manually",
- )}
- </Typography>
- )}
- </Paper>
- )}
-
- {error && (
- <Typography color="error" variant="body2" mb={1}>
- {error}
- </Typography>
- )}
-
- <Stack spacing={1}>
- {machines.map((machine) => (
- <Paper
- key={machine.id}
- sx={{
- p: 2,
- display: "flex",
- alignItems: "center",
- justifyContent: "space-between",
- bgcolor: "green.50",
- border: "1px solid",
- borderColor: "green.200",
- }}
- >
- <Box>
- <Typography fontWeight={500} color="success.dark">
- {machine.name}
- </Typography>
- <Typography variant="body2" color="success.main">
- {machine.code}
- </Typography>
- </Box>
- <IconButton onClick={() => removeMachine(machine.id)} color="error">
- <CloseIcon />
- </IconButton>
- </Paper>
- ))}
- {machines.length === 0 && (
- <Paper
- sx={{
- p: 2,
- bgcolor: "grey.100",
- border: "1px solid",
- borderColor: "grey.200",
- }}
- >
- <Typography
- color="text.secondary"
- fontStyle="italic"
- variant="body2"
- >
- No machines added yet. Use the scan button to add machines.
- </Typography>
- </Paper>
- )}
- </Stack>
- </Box>
- );
- };
-
- export default MachineScanner;
|