"use client"; import { Autocomplete, Box, Button, CircularProgress, FormControl, Grid, Modal, TextField, Typography, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, Checkbox, TablePagination, } from "@mui/material"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { newassignPickOrder, AssignPickOrderInputs, releaseAssignedPickOrders, // Add this import } from "@/app/api/pickOrder/actions"; import { fetchNameList, NameList ,fetchNewNameList, NewNameList} from "@/app/api/user/actions"; import { FormProvider, useForm } from "react-hook-form"; import { isEmpty, sortBy, uniqBy, upperFirst, groupBy } from "lodash"; import { OUTPUT_DATE_FORMAT, arrayToDayjs } from "@/app/utils/formatUtil"; import useUploadContext from "../UploadProvider/useUploadContext"; import dayjs from "dayjs"; import arraySupport from "dayjs/plugin/arraySupport"; import SearchBox, { Criterion } from "../SearchBox"; import { fetchPickOrderItemsByPageClient } from "@/app/api/settings/item/actions"; dayjs.extend(arraySupport); interface Props { filterArgs: Record; } // 使用 fetchPickOrderItemsByPageClient 返回的数据结构 interface ItemRow { id: string; pickOrderId: number; pickOrderCode: string; itemId: number; itemCode: string; itemName: string; requiredQty: number; currentStock: number; unit: string; targetDate: any; status: string; consoCode?: string; assignTo?: number; groupName?: string; } // 分组后的数据结构 interface GroupedItemRow { pickOrderId: number; pickOrderCode: string; targetDate: any; status: string; consoCode?: string; items: ItemRow[]; } const style = { position: "absolute", top: "50%", left: "50%", transform: "translate(-50%, -50%)", bgcolor: "background.paper", pt: 5, px: 5, pb: 10, width: { xs: "100%", sm: "100%", md: "100%" }, }; const AssignAndRelease: React.FC = ({ filterArgs }) => { const { t } = useTranslation("pickOrder"); const { setIsUploading } = useUploadContext(); // 修复:选择状态改为按 pick order ID 存储 const [selectedPickOrderIds, setSelectedPickOrderIds] = useState([]); const [filteredItems, setFilteredItems] = useState([]); const [isLoadingItems, setIsLoadingItems] = useState(false); const [pagingController, setPagingController] = useState({ pageNum: 1, pageSize: 10, }); const [totalCountItems, setTotalCountItems] = useState(); const [modalOpen, setModalOpen] = useState(false); const [usernameList, setUsernameList] = useState([]); const [searchQuery, setSearchQuery] = useState>({}); const [originalItemData, setOriginalItemData] = useState([]); const formProps = useForm(); const errors = formProps.formState.errors; // 将项目按 pick order 分组 const groupedItems = useMemo(() => { const grouped = groupBy(filteredItems, 'pickOrderId'); return Object.entries(grouped).map(([pickOrderId, items]) => { const firstItem = items[0]; return { pickOrderId: parseInt(pickOrderId), pickOrderCode: firstItem.pickOrderCode, targetDate: firstItem.targetDate, status: firstItem.status, consoCode: firstItem.consoCode, items: items } as GroupedItemRow; }); }, [filteredItems]); // 修复:处理 pick order 选择 const handlePickOrderSelect = useCallback((pickOrderId: number, checked: boolean) => { if (checked) { setSelectedPickOrderIds(prev => [...prev, pickOrderId]); } else { setSelectedPickOrderIds(prev => prev.filter(id => id !== pickOrderId)); } }, []); // 修复:检查 pick order 是否被选中 const isPickOrderSelected = useCallback((pickOrderId: number) => { return selectedPickOrderIds.includes(pickOrderId); }, [selectedPickOrderIds]); // 使用 fetchPickOrderItemsByPageClient 获取数据 const fetchNewPageItems = useCallback( async (pagingController: Record, filterArgs: Record) => { console.log("=== fetchNewPageItems called ==="); console.log("pagingController:", pagingController); console.log("filterArgs:", filterArgs); setIsLoadingItems(true); try { const params = { ...pagingController, ...filterArgs, // 新增:排除状态为 "assigned" 的提料单 //status: "pending,released,completed,cancelled" // 或者使用其他方式过滤 }; console.log("Final params:", params); const res = await fetchPickOrderItemsByPageClient(params); console.log("API Response:", res); if (res && res.records) { console.log("Records received:", res.records.length); console.log("First record:", res.records[0]); // 新增:在前端也过滤掉 "assigned" 状态的项目 const filteredRecords = res.records.filter((item: any) => item.status !== "assigned"); const itemRows: ItemRow[] = filteredRecords.map((item: any) => ({ id: item.id, pickOrderId: item.pickOrderId, pickOrderCode: item.pickOrderCode, itemId: item.itemId, itemCode: item.itemCode, itemName: item.itemName, requiredQty: item.requiredQty, currentStock: item.currentStock ?? 0, unit: item.unit, targetDate: item.targetDate, status: item.status, consoCode: item.consoCode, assignTo: item.assignTo, groupName: item.groupName, })); setOriginalItemData(itemRows); setFilteredItems(itemRows); setTotalCountItems(filteredRecords.length); // 使用过滤后的数量 } else { console.log("No records in response"); setFilteredItems([]); setTotalCountItems(0); } } catch (error) { console.error("Error fetching items:", error); setFilteredItems([]); setTotalCountItems(0); } finally { setIsLoadingItems(false); } }, [], ); const searchCriteria: Criterion[] = useMemo( () => [ { label: t("Pick Order Code"), paramName: "pickOrderCode", type: "text", }, { label: t("Item Code"), paramName: "itemCode", type: "text" }, { label: t("Group Code"), paramName: "groupName", type: "text", }, { label: t("Item Name"), paramName: "itemName", type: "text", }, { label: t("Target Date From"), label2: t("Target Date To"), paramName: "targetDate", type: "dateRange", }, { label: t("Pick Order Status"), paramName: "status", type: "autocomplete", options: sortBy( uniqBy( originalItemData.map((item) => ({ value: item.status, label: t(upperFirst(item.status)), })), "value", ), "label", ), }, ], [originalItemData, t], ); const handleSearch = useCallback((query: Record) => { setSearchQuery({ ...query }); console.log("Search query:", query); const filtered = originalItemData.filter((item) => { const itemTargetDateStr = arrayToDayjs(item.targetDate); const itemCodeMatch = !query.itemCode || item.itemCode?.toLowerCase().includes((query.itemCode || "").toLowerCase()); const itemNameMatch = !query.itemName || item.itemName?.toLowerCase().includes((query.itemName || "").toLowerCase()); const pickOrderCodeMatch = !query.pickOrderCode || item.pickOrderCode?.toLowerCase().includes((query.pickOrderCode || "").toLowerCase()); const groupNameMatch = !query.groupName || item.groupName?.toLowerCase().includes((query.groupName || "").toLowerCase()); // 日期范围搜索 let dateMatch = true; if (query.targetDate || query.targetDateTo) { try { if (query.targetDate && !query.targetDateTo) { const fromDate = dayjs(query.targetDate); dateMatch = itemTargetDateStr.isSame(fromDate, 'day') || itemTargetDateStr.isAfter(fromDate, 'day'); } else if (!query.targetDate && query.targetDateTo) { const toDate = dayjs(query.targetDateTo); dateMatch = itemTargetDateStr.isSame(toDate, 'day') || itemTargetDateStr.isBefore(toDate, 'day'); } else if (query.targetDate && query.targetDateTo) { const fromDate = dayjs(query.targetDate); const toDate = dayjs(query.targetDateTo); dateMatch = (itemTargetDateStr.isSame(fromDate, 'day') || itemTargetDateStr.isAfter(fromDate, 'day')) && (itemTargetDateStr.isSame(toDate, 'day') || itemTargetDateStr.isBefore(toDate, 'day')); } } catch (error) { console.error("Date parsing error:", error); dateMatch = true; } } const statusMatch = !query.status || query.status.toLowerCase() === "all" || item.status?.toLowerCase().includes((query.status || "").toLowerCase()); return itemCodeMatch && itemNameMatch && groupNameMatch && pickOrderCodeMatch && dateMatch && statusMatch; }); console.log("Filtered items count:", filtered.length); setFilteredItems(filtered); }, [originalItemData]); const handleReset = useCallback(() => { setSearchQuery({}); setFilteredItems(originalItemData); setTimeout(() => { setSearchQuery({}); }, 0); }, [originalItemData]); // 修复:处理分页变化 const handlePageChange = useCallback((event: unknown, newPage: number) => { const newPagingController = { ...pagingController, pageNum: newPage + 1, // API 使用 1-based 分页 }; setPagingController(newPagingController); }, [pagingController]); const handlePageSizeChange = useCallback((event: React.ChangeEvent) => { const newPageSize = parseInt(event.target.value, 10); const newPagingController = { pageNum: 1, // 重置到第一页 pageSize: newPageSize, }; setPagingController(newPagingController); }, []); const handleAssignOnly = useCallback(async (data: AssignPickOrderInputs) => { if (selectedPickOrderIds.length === 0) return; setIsUploading(true); try { // 修复:直接使用选中的 pick order IDs const assignRes = await newassignPickOrder({ pickOrderIds: selectedPickOrderIds, assignTo: data.assignTo, }); if (assignRes && assignRes.code === "SUCCESS") { console.log("Assign successful:", assignRes); setModalOpen(false); setSelectedPickOrderIds([]); // 清空选择 fetchNewPageItems(pagingController, filterArgs); } else { console.error("Assign failed:", assignRes); } } catch (error) { console.error("Error in assign:", error); } finally { setIsUploading(false); } }, [selectedPickOrderIds, setIsUploading, fetchNewPageItems, pagingController, filterArgs]); const handleAssignAndReleaseCombined = useCallback(async (data: AssignPickOrderInputs) => { if (selectedPickOrderIds.length === 0) return; setIsUploading(true); try { // Step 1: Assign the pick orders const assignRes = await newassignPickOrder({ pickOrderIds: selectedPickOrderIds, assignTo: data.assignTo, }); if (assignRes && assignRes.code === "SUCCESS") { console.log("Assign successful:", assignRes); // Step 2: Release the assigned pick orders const releaseRes = await releaseAssignedPickOrders({ pickOrderIds: selectedPickOrderIds, assignTo: data.assignTo, }); if (releaseRes && releaseRes.code === "SUCCESS") { console.log("Assign and Release successful:", releaseRes); setModalOpen(false); setSelectedPickOrderIds([]); // 清空选择 fetchNewPageItems(pagingController, filterArgs); } else { console.error("Release failed:", releaseRes); } } else { console.error("Assign failed:", assignRes); } } catch (error) { console.error("Error in assign and release:", error); } finally { setIsUploading(false); } }, [selectedPickOrderIds, setIsUploading, fetchNewPageItems, pagingController, filterArgs]); const openAssignModal = useCallback(() => { setModalOpen(true); formProps.reset(); }, [formProps]); // 组件挂载时加载数据 useEffect(() => { console.log("=== Component mounted ==="); fetchNewPageItems(pagingController, filterArgs || {}); }, []); // 只在组件挂载时执行一次 // 当 pagingController 或 filterArgs 变化时重新调用 API useEffect(() => { console.log("=== Dependencies changed ==="); if (pagingController && (filterArgs || {})) { fetchNewPageItems(pagingController, filterArgs || {}); } }, [pagingController, filterArgs, fetchNewPageItems]); useEffect(() => { const loadUsernameList = async () => { try { const res = await fetchNewNameList(); if (res) { setUsernameList(res); } } catch (error) { console.error("Error loading username list:", error); } }; loadUsernameList(); }, []); // 自定义分组表格组件 const CustomGroupedTable = () => { return ( <> {t("Selected")} {t("Pick Order Code")} {t("Group Code")} {t("Item Code")} {t("Item Name")} {t("Order Quantity")} {t("Current Stock")} {t("Stock Unit")} {t("Target Date")} {t("Pick Order Status")} {groupedItems.length === 0 ? ( {t("No data available")} ) : ( groupedItems.map((group) => ( group.items.map((item, index) => ( {/* Checkbox - 只在第一个项目显示,按 pick order 选择 */} {index === 0 ? ( handlePickOrderSelect(group.pickOrderId, e.target.checked)} disabled={!isEmpty(item.consoCode)} /> ) : null} {/* Pick Order Code - 只在第一个项目显示 */} {index === 0 ? item.pickOrderCode : null} {/* Group Name */} {index === 0 ? (item.groupName || "No Group") : null} {/* Item Code */} {item.itemCode} {/* Item Name */} {item.itemName} {/* Order Quantity */} {item.requiredQty} {/* Current Stock */} 0 ? "success.main" : "error.main"} sx={{ fontWeight: item.currentStock > 0 ? 'bold' : 'normal' }} > {item.currentStock.toLocaleString()} {/* Unit */} {item.unit} {/* Target Date - 只在第一个项目显示 */} {index === 0 ? ( arrayToDayjs(item.targetDate) .add(-1, "month") .format(OUTPUT_DATE_FORMAT) ) : null} {/* Pick Order Status - 只在第一个项目显示 */} {index === 0 ? upperFirst(item.status) : null} )) )) )}
{/* 修复:添加分页组件 */} `${from}-${to} of ${count !== -1 ? count : `more than ${to}`}` } /> ); }; return ( <> {isLoadingItems ? ( ) : ( )} {modalOpen ? ( setModalOpen(false)} aria-labelledby="modal-modal-title" aria-describedby="modal-modal-description" > {t("Assign Pick Orders")} {t("Selected Pick Orders")}: {selectedPickOrderIds.length}
{ // 修改:显示更详细的用户信息 const title = option.title ? ` (${option.title})` : ''; const department = option.department ? ` - ${option.department}` : ''; return `${option.name}${title}${department}`; }} renderOption={(props, option) => ( {option.name} {option.title && ` (${option.title})`} {option.department && ` - ${option.department}`} )} onChange={(_, value) => { formProps.setValue("assignTo", value?.id || 0); }} renderInput={(params) => ( )} /> {t("Select an action for the assigned pick orders.")}
) : undefined} ); }; export default AssignAndRelease;