import { useState, useCallback, useMemo, useEffect, memo } from "react"; import { Search, Loader2, AlertCircle, GitBranch, RefreshCw, X, Plus, Warehouse, UserPlus, } from "lucide-react"; import TaskFlowView from "./TaskFlowView"; import { getTaskTree, receiveTask, rejectTask, transferTask, } from "../../services/taskApi"; import { useToast } from "../ui/Toast"; import type { ProductScanResponse, TaskResponse } from "../../types/api"; import { getStatusConfig } from "../../constants/task"; import ImageUploader from "../ui/ImageUploader"; import { extractErrorMessage } from "../../utils/errorMessage"; // ============================================================ // 通用 Modal 容器 // ============================================================ export const Modal = memo(function Modal({ open, onClose, title, children, widthClass = "max-w-md", bodyClassName = "", }: { open: boolean; onClose: () => void; title: string; children: React.ReactNode; widthClass?: string; bodyClassName?: string; }) { // 🚀 弹窗打开时锁定背景滚动(防止滚动穿透),关闭时恢复 useEffect(() => { if (!open) return; const prev = document.body.style.overflow; document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = prev; }; }, [open]); if (!open) return null; return (
{/* 遮罩 */}
{/* 弹窗 */}

{title}

{children}
); }); // ============================================================ // 确认接收弹窗 // ============================================================ export const ReceiveConfirmModal = memo(function ReceiveConfirmModal({ open, task, submitting, onClose, onConfirm, }: { open: boolean; task: TaskResponse | null; submitting: boolean; onClose: () => void; onConfirm: () => void; }) { if (!task) return null; return (

{task.task_name}

当前状态: {getStatusConfig(task.status).label} {" → "} 进行中 (WIP)

确认接收后,该任务将标记为"进行中",系统将记录接收时间。

); }); // ============================================================ // 品质驳回弹窗 // ============================================================ export const RejectModal = memo(function RejectModal({ open, task, submitting, onClose, onSubmit, }: { open: boolean; task: TaskResponse | null; submitting: boolean; onClose: () => void; onSubmit: (reason: string, images: string[]) => void; }) { const [reason, setReason] = useState(""); const [images, setImages] = useState([]); if (!task) return null; function handleSubmit(e: React.FormEvent) { e.preventDefault(); const trimmed = reason.trim(); if (!trimmed) return; // 异常图片为选填:编号错误、选错工序等场景无需拍照举证,不再拦截无图提交 onSubmit(trimmed, images); setReason(""); setImages([]); } function handleClose() { setReason(""); setImages([]); onClose(); } return (

{task.task_name}

⚠ 驳回后将自动生成返工任务,分配给上一道工序负责人