|
|
|
@@ -13,6 +13,9 @@ import { |
|
|
|
import CloseIcon from "@mui/icons-material/Close"; |
|
|
|
import { isOperatorExist } from "@/app/api/jo/actions"; |
|
|
|
import { OperatorQrCode } from "./types"; |
|
|
|
// ✅ 新增:导入 user API |
|
|
|
import { fetchUserDetails } from "@/app/api/user/actions"; |
|
|
|
import { fetchNameList } from "@/app/api/user/actions"; |
|
|
|
|
|
|
|
interface OperatorScannerProps { |
|
|
|
operators: Operator[]; |
|
|
|
@@ -27,19 +30,20 @@ const OperatorScanner: React.FC<OperatorScannerProps> = ({ |
|
|
|
operators, |
|
|
|
onOperatorsChange, |
|
|
|
error, |
|
|
|
isActive=false, |
|
|
|
isActive = false, |
|
|
|
onActivate, |
|
|
|
onDeactivate, |
|
|
|
}) => { |
|
|
|
const [scanningMode, setScanningMode] = useState<boolean>(false); |
|
|
|
const [scanError, setScanError] = useState<string | null>(null); |
|
|
|
const operatorScanRef = useRef<HTMLInputElement>(null); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
if (!isActive && scanningMode) { |
|
|
|
|
|
|
|
stopScanning(); |
|
|
|
} |
|
|
|
}, [isActive]); |
|
|
|
|
|
|
|
const startScanning = (): void => { |
|
|
|
setScanningMode(true); |
|
|
|
setScanError(null); |
|
|
|
@@ -67,6 +71,54 @@ const OperatorScanner: React.FC<OperatorScannerProps> = ({ |
|
|
|
console.log("Raw input:", usernameInput); |
|
|
|
|
|
|
|
try { |
|
|
|
// ✅ 检查是否是测试快捷格式 {2fitest<id>} |
|
|
|
const testMatch = usernameInput.match(/\{2fitest(\d+)\??}?/i); |
|
|
|
if (testMatch && testMatch[1]) { |
|
|
|
const userId = parseInt(testMatch[1]); |
|
|
|
console.log(`🧪 Test mode: Fetching user with ID ${userId} from API`); |
|
|
|
|
|
|
|
try { |
|
|
|
// ✅ 方案 1:使用 fetchNameList 获取所有用户,然后找到对应 ID |
|
|
|
const nameList = await fetchNameList(); |
|
|
|
const matchedUser = nameList.find(user => user.id === userId); |
|
|
|
|
|
|
|
if (matchedUser) { |
|
|
|
// ✅ 将 NameList 转换为 Operator 格式 |
|
|
|
const operator: Operator = { |
|
|
|
id: matchedUser.id, |
|
|
|
name: matchedUser.name, |
|
|
|
username: `user${matchedUser.id}`, // 生成一个 username |
|
|
|
}; |
|
|
|
|
|
|
|
const isAlreadyAdded = operators.some( |
|
|
|
(op) => op.id === operator.id, |
|
|
|
); |
|
|
|
|
|
|
|
if (!isAlreadyAdded) { |
|
|
|
onOperatorsChange([...operators, operator]); |
|
|
|
} |
|
|
|
|
|
|
|
target.value = ""; |
|
|
|
setScanError(null); |
|
|
|
console.log(`✅ Added operator from API:`, operator); |
|
|
|
return; |
|
|
|
} else { |
|
|
|
setScanError( |
|
|
|
`User with ID ${userId} not found. Please check the ID and try again.` |
|
|
|
); |
|
|
|
target.value = ""; |
|
|
|
return; |
|
|
|
} |
|
|
|
} catch (apiError) { |
|
|
|
console.error("Error fetching user by ID:", apiError); |
|
|
|
setScanError( |
|
|
|
"Failed to fetch user data. Please try again." |
|
|
|
); |
|
|
|
target.value = ""; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
let username: string; |
|
|
|
|
|
|
|
// ✅ 尝试解析 JSON |
|
|
|
@@ -163,7 +215,6 @@ const OperatorScanner: React.FC<OperatorScannerProps> = ({ |
|
|
|
variant="outlined" |
|
|
|
size="small" |
|
|
|
sx={{ bgcolor: "white" }} |
|
|
|
onInput={handleOperatorScan} |
|
|
|
/> |
|
|
|
<Button variant="contained" color="inherit" onClick={stopScanning}> |
|
|
|
Cancel |
|
|
|
@@ -176,7 +227,7 @@ const OperatorScanner: React.FC<OperatorScannerProps> = ({ |
|
|
|
) : ( |
|
|
|
<Typography variant="body2" color="success.main" mt={1}> |
|
|
|
Position the ID card scanner and scan, or type the employee ID |
|
|
|
manually |
|
|
|
manually. Test format: {"{2fitest<id>"} (e.g., {"{2fitest1}"}) |
|
|
|
</Typography> |
|
|
|
)} |
|
|
|
</Paper> |
|
|
|
@@ -207,7 +258,7 @@ const OperatorScanner: React.FC<OperatorScannerProps> = ({ |
|
|
|
{operator.name} |
|
|
|
</Typography> |
|
|
|
<Typography variant="body2" color="primary.main"> |
|
|
|
{operator.username} |
|
|
|
ID: {operator.id} | Username: {operator.username} |
|
|
|
</Typography> |
|
|
|
</Box> |
|
|
|
<IconButton |
|
|
|
@@ -241,4 +292,4 @@ const OperatorScanner: React.FC<OperatorScannerProps> = ({ |
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
export default OperatorScanner; |
|
|
|
export default OperatorScanner; |