"use client"; import { createPickOrder, SavePickOrderRequest, SavePickOrderLineRequest } from "@/app/api/pickOrder/actions"; import { Autocomplete, Box, Button, FormControl, Grid, Stack, TextField, Typography, Checkbox, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, } from "@mui/material"; import { Controller, FormProvider, SubmitHandler, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useCallback, useEffect, useMemo, useState } from "react"; import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import dayjs from "dayjs"; import { Check, Search } from "@mui/icons-material"; import { ItemCombo, fetchAllItemsInClient } from "@/app/api/settings/item/actions"; import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; import SearchResults, { Column } from "../SearchResults/SearchResults"; import { fetchJobOrderDetailByCode } from "@/app/api/jo/actions"; import SearchBox, { Criterion } from "../SearchBox"; type Props = { filterArgs?: Record; searchQuery?: Record; }; // 扩展表单类型以包含搜索字段 interface SearchFormData extends SavePickOrderRequest { searchCode?: string; searchName?: string; } interface CreatedItem { itemId: number; itemName: string; itemCode: string; qty: number; uom: string; uomId: number; isSelected: boolean; currentStockBalance?: number; targetDate?: string; // Make it optional to match the source } // Add interface for search items with quantity interface SearchItemWithQty extends ItemCombo { qty: number | null; // Changed from number to number | null jobOrderCode?: string; jobOrderId?: number; currentStockBalance?: number; targetDate?: string; } interface JobOrderDetailPickLine { id: number; code: string; name: string; lotNo: string | null; reqQty: number; uom: string; status: string; } const NewCreateItem: React.FC = ({ filterArgs, searchQuery }) => { const { t } = useTranslation("pickOrder"); const [items, setItems] = useState([]); const [filteredItems, setFilteredItems] = useState([]); const [createdItems, setCreatedItems] = useState([]); const [isLoading, setIsLoading] = useState(false); const [hasSearched, setHasSearched] = useState(false); // Add state for selected item IDs in search results const [selectedSearchItemIds, setSelectedSearchItemIds] = useState<(string | number)[]>([]); // Add state for second search const [secondSearchQuery, setSecondSearchQuery] = useState>({}); const [secondSearchResults, setSecondSearchResults] = useState([]); const [isLoadingSecondSearch, setIsLoadingSecondSearch] = useState(false); const [hasSearchedSecond, setHasSearchedSecond] = useState(false); // Add selection state for second search const [selectedSecondSearchItemIds, setSelectedSecondSearchItemIds] = useState<(string | number)[]>([]); const formProps = useForm(); const errors = formProps.formState.errors; const targetDate = formProps.watch("targetDate"); const type = formProps.watch("type"); const searchCode = formProps.watch("searchCode"); const searchName = formProps.watch("searchName"); const [jobOrderItems, setJobOrderItems] = useState([]); const [isLoadingJobOrder, setIsLoadingJobOrder] = useState(false); useEffect(() => { const loadItems = async () => { try { const itemsData = await fetchAllItemsInClient(); console.log("Loaded items:", itemsData); setItems(itemsData); setFilteredItems([]); } catch (error) { console.error("Error loading items:", error); } }; loadItems(); }, []); const searchJobOrderItems = useCallback(async (jobOrderCode: string) => { if (!jobOrderCode.trim()) return; setIsLoadingJobOrder(true); try { const jobOrderDetail = await fetchJobOrderDetailByCode(jobOrderCode); setJobOrderItems(jobOrderDetail.pickLines || []); // Convert Job Order items to SearchItemWithQty format const convertedItems = (jobOrderDetail.pickLines || []).map(item => ({ id: item.id, label: item.name, qty: item.reqQty, // Pre-fill with required quantity uom: item.uom, uomId: 0, // We'll need to get this from the item lookup jobOrderCode: jobOrderDetail.code, jobOrderId: jobOrderDetail.id, })); setFilteredItems(convertedItems); setHasSearched(true); } catch (error) { console.error("Error fetching Job Order items:", error); alert(t("Job Order not found or has no items")); } finally { setIsLoadingJobOrder(false); } }, [t]); // Update useEffect to handle Job Order search useEffect(() => { if (searchQuery && searchQuery.jobOrderCode) { searchJobOrderItems(searchQuery.jobOrderCode); } else if (searchQuery && items.length > 0) { // Existing item search logic // ... your existing search logic } }, [searchQuery, items, searchJobOrderItems]); useEffect(() => { if (searchQuery && items.length > 0) { const hasValidSearch = ( (searchQuery.items && searchQuery.items.trim && searchQuery.items.trim() !== "") || (searchQuery.code && searchQuery.code.trim && searchQuery.code.trim() !== "") || (searchQuery.type && searchQuery.type !== "All") ); if (hasValidSearch) { let filtered = items; if (searchQuery.items) { const itemsToSearch = Array.isArray(searchQuery.items) ? searchQuery.items : [searchQuery.items]; if (itemsToSearch.length > 0 && !itemsToSearch.includes("All")) { filtered = filtered.filter(item => itemsToSearch.some((searchItem: string) => item.label.toLowerCase().includes(searchItem.toLowerCase()) ) ); } } if (searchQuery.code) { filtered = filtered.filter(item => item.label.toLowerCase().includes(searchQuery.code.toLowerCase()) ); } if (searchQuery.type && searchQuery.type !== "All") { // filtered = filtered.filter(item => item.type === searchQuery.type); } // Convert to SearchItemWithQty with default qty = null const filteredWithQty = filtered.slice(0, 10).map(item => ({ ...item, qty: null // Changed from 1 to null })); setFilteredItems(filteredWithQty); setHasSearched(true); } else { setFilteredItems([]); setHasSearched(false); } } else { setFilteredItems([]); setHasSearched(false); } }, [searchQuery, items]); useEffect(() => { if (searchQuery) { if (searchQuery.type) { formProps.setValue("type", searchQuery.type); } if (searchQuery.targetDate) { formProps.setValue("targetDate", searchQuery.targetDate); } if (searchQuery.code) { formProps.setValue("searchCode", searchQuery.code); } if (searchQuery.items) { formProps.setValue("searchName", searchQuery.items); } } }, [searchQuery, formProps]); useEffect(() => { setFilteredItems([]); setHasSearched(false); }, []); const typeList = [ { type: "Consumable" }, { type: "Material" }, { type: "Product" } ]; const handleTypeChange = useCallback( (event: React.SyntheticEvent, newValue: {type: string} | null) => { formProps.setValue("type", newValue?.type || ""); }, [formProps], ); const handleSearch = useCallback(() => { if (!type) { alert(t("Please select type")); return; } if (!searchCode && !searchName) { alert(t("Please enter at least code or name")); return; } setIsLoading(true); setHasSearched(true); console.log("Searching with:", { type, searchCode, searchName, targetDate, itemsCount: items.length }); setTimeout(() => { let filtered = items; if (searchCode && searchCode.trim()) { filtered = filtered.filter(item => item.label.toLowerCase().includes(searchCode.toLowerCase()) ); console.log("After code filter:", filtered.length); } if (searchName && searchName.trim()) { filtered = filtered.filter(item => item.label.toLowerCase().includes(searchName.toLowerCase()) ); console.log("After name filter:", filtered.length); } // Convert to SearchItemWithQty with default qty = null and include targetDate const filteredWithQty = filtered.slice(0, 100).map(item => ({ ...item, qty: null, targetDate: targetDate, // Add target date to each item })); console.log("Final filtered results:", filteredWithQty.length); setFilteredItems(filteredWithQty); setIsLoading(false); }, 500); }, [type, searchCode, searchName, targetDate, items, t]); // Add targetDate back to dependencies // Handle quantity change in search results const handleSearchQtyChange = useCallback((itemId: number, newQty: number | null) => { setFilteredItems(prev => prev.map(item => item.id === itemId ? { ...item, qty: newQty } : item ) ); // Auto-update created items if this item exists there setCreatedItems(prev => prev.map(item => item.itemId === itemId ? { ...item, qty: newQty || 1 } : item ) ); }, []); // Modified handler for search item selection const handleSearchItemSelect = useCallback((itemId: number, isSelected: boolean) => { if (isSelected) { const item = filteredItems.find(i => i.id === itemId); if (!item) return; const existingItem = createdItems.find(created => created.itemId === item.id); if (existingItem) { alert(t("Item already exists in created items")); return; } const newCreatedItem: CreatedItem = { itemId: item.id, itemName: item.label, itemCode: item.label, qty: item.qty || 1, uom: item.uom || "", uomId: item.uomId || 0, isSelected: true, currentStockBalance: item.currentStockBalance, targetDate: item.targetDate || targetDate, // Use item's targetDate or fallback to form's targetDate }; setCreatedItems(prev => [...prev, newCreatedItem]); } }, [filteredItems, createdItems, t, targetDate]); // Handler for created item selection const handleCreatedItemSelect = useCallback((itemId: number, isSelected: boolean) => { setCreatedItems(prev => prev.map(item => item.itemId === itemId ? { ...item, isSelected } : item ) ); }, []); const handleQtyChange = useCallback((itemId: number, newQty: number) => { setCreatedItems(prev => prev.map(item => item.itemId === itemId ? { ...item, qty: newQty } : item ) ); }, []); // Check if item is already in created items const isItemInCreated = useCallback((itemId: number) => { return createdItems.some(item => item.itemId === itemId); }, [createdItems]); const onSubmit = useCallback>( async (data, event) => { const selectedCreatedItems = createdItems.filter(item => item.isSelected); if (selectedCreatedItems.length === 0) { alert(t("Please select at least one item to submit")); return; } if (!data.type) { alert(t("Please select product type")); return; } if (!data.targetDate) { alert(t("Please select target date")); return; } let formattedTargetDate = data.targetDate; if (data.targetDate && typeof data.targetDate === 'string') { try { const date = dayjs(data.targetDate); formattedTargetDate = date.format('YYYY-MM-DD'); } catch (error) { console.error("Invalid date format:", data.targetDate); alert(t("Invalid date format")); return; } } const pickOrderData: SavePickOrderRequest = { type: data.type || "Consumable", targetDate: formattedTargetDate, pickOrderLine: selectedCreatedItems.map(item => ({ itemId: item.itemId, qty: item.qty, uomId: item.uomId } as SavePickOrderLineRequest)) }; console.log("Submitting pick order:", pickOrderData); try { const res = await createPickOrder(pickOrderData); if (res.id) { console.log("Pick order created successfully:", res); setCreatedItems(prev => prev.filter(item => !item.isSelected)); formProps.reset(); setHasSearched(false); setFilteredItems([]); alert(t("Pick order created successfully")); } } catch (error) { console.error("Error creating pick order:", error); alert(t("Failed to create pick order")); } }, [createdItems, t, formProps] ); const handleReset = useCallback(() => { formProps.reset(); setCreatedItems([]); setHasSearched(false); setFilteredItems([]); }, [formProps]); // Pagination state const [page, setPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(10); // Handle page change const handleChangePage = ( _event: React.MouseEvent | React.KeyboardEvent, newPage: number, ) => { console.log(_event); setPage(newPage); // The original code had setPagingController and defaultPagingController, // but these are not defined in the provided context. // Assuming they are meant to be part of a larger context or will be added. // For now, commenting out the setPagingController part as it's not defined. // if (setPagingController) { // setPagingController({ // ...(pagingController ?? defaultPagingController), // pageNum: newPage + 1, // }); // } }; // Handle rows per page change const handleChangeRowsPerPage = ( event: React.ChangeEvent, ) => { console.log(event); setRowsPerPage(+event.target.value); setPage(0); // The original code had setPagingController and defaultPagingController, // but these are not defined in the provided context. // Assuming they are meant to be part of a larger context or will be added. // For now, commenting out the setPagingController part as it's not defined. // if (setPagingController) { // setPagingController({ // ...(pagingController ?? defaultPagingController), // pageNum: 1, // }); // } }; // Add checkbox change handler for first search const handleSearchCheckboxChange = useCallback((ids: (string | number)[] | ((prev: (string | number)[]) => (string | number)[])) => { if (typeof ids === 'function') { const newIds = ids(selectedSearchItemIds); setSelectedSearchItemIds(newIds); if (newIds.length === filteredItems.length) { filteredItems.forEach(item => { if (!isItemInCreated(item.id)) { handleSearchItemSelect(item.id, true); } }); } else { filteredItems.forEach(item => { const isSelected = newIds.includes(item.id); const isCurrentlyInCreated = isItemInCreated(item.id); if (isSelected && !isCurrentlyInCreated) { handleSearchItemSelect(item.id, true); } else if (!isSelected && isCurrentlyInCreated) { setCreatedItems(prev => prev.filter(createdItem => createdItem.itemId !== item.id)); } }); } } else { const previousIds = selectedSearchItemIds; setSelectedSearchItemIds(ids); const newlySelected = ids.filter(id => !previousIds.includes(id)); const newlyDeselected = previousIds.filter(id => !ids.includes(id)); newlySelected.forEach(id => { if (!isItemInCreated(id as number)) { handleSearchItemSelect(id as number, true); } }); newlyDeselected.forEach(id => { setCreatedItems(prev => prev.filter(createdItem => createdItem.itemId !== id)); }); } }, [selectedSearchItemIds, filteredItems, isItemInCreated, handleSearchItemSelect]); // Define columns for SearchResults const searchItemColumns: Column[] = useMemo(() => [ { name: "id", label: "", type: "checkbox", disabled: (item) => isItemInCreated(item.id), // Disable if already in created items }, { name: "label", label: t("Item"), renderCell: (item) => { const parts = item.label.split(' - '); const code = parts[0] || ''; const name = parts[1] || ''; return ( {name} {/* 显示项目名称 */} {code} {/* 显示项目代码 */} ); }, }, { name: "qty", label: t("Order Quantity"), renderCell: (item) => ( { const value = e.target.value; const numValue = value === "" ? null : Number(value); handleSearchQtyChange(item.id, numValue); }} onKeyDown={(e) => { // Allow typing numbers, backspace, delete, arrow keys if (!/[0-9]/.test(e.key) && !['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Enter'].includes(e.key)) { e.preventDefault(); } }} inputProps={{ min: 1, step: 1, style: { textAlign: 'center' } // Center the text }} sx={{ width: '80px', '& .MuiInputBase-input': { textAlign: 'center', cursor: 'text' } }} /> ), }, { name: "currentStockBalance", label: t("Current Stock"), renderCell: (item) => { const stockBalance = item.currentStockBalance || 0; return ( 0 ? "success.main" : "error.main"} sx={{ fontWeight: stockBalance > 0 ? 'bold' : 'normal' }} > {stockBalance} ); }, }, { name: "targetDate", label: t("Target Date"), renderCell: (item) => ( {item.targetDate ? new Date(item.targetDate).toLocaleDateString() : "-"} ), }, { name: "uom", label: t("Unit"), renderCell: (item) => item.uom || "-", }, ], [t, isItemInCreated, handleSearchQtyChange]); const pickOrderSearchCriteria: Criterion[] = useMemo( () => [ { label: t("Product Type"), paramName: "type", type: "autocomplete", options: [ { value: "Consumable", label: t("Consumable") }, { value: "MATERIAL", label: t("Material") }, { value: "JOB_ORDER", label: t("Job Order") } ], }, { label: t("Item Code"), paramName: "code", type: "text" }, { label: t("Item Name"), paramName: "name", type: "text" }, ], [t], ); // Add search handler for second search (same as first search) const handleSecondSearch = useCallback((query: Record) => { console.log("Second search triggered with query:", query); setSecondSearchQuery({ ...query }); setIsLoadingSecondSearch(true); // 同步第二个搜索框的信息到表单 - 确保类型值正确 if (query.type) { // 确保类型值符合后端枚举格式 let correctType = query.type; if (query.type === "consumable") { correctType = "Consumable"; } else if (query.type === "material") { correctType = "MATERIAL"; } else if (query.type === "jo") { correctType = "JOB_ORDER"; } formProps.setValue("type", correctType); } // 设置默认目标日期为今天 const today = dayjs().format(INPUT_DATE_FORMAT); formProps.setValue("targetDate", today); setTimeout(() => { let filtered = items; // Same filtering logic as first search if (query.code && query.code.trim()) { filtered = filtered.filter(item => item.label.toLowerCase().includes(query.code.toLowerCase()) ); } if (query.name && query.name.trim()) { filtered = filtered.filter(item => item.label.toLowerCase().includes(query.name.toLowerCase()) ); } if (query.type && query.type !== "All") { // Filter by type if needed } // Convert to SearchItemWithQty with default qty = null and today's date const filteredWithQty = filtered.slice(0, 100).map(item => ({ ...item, qty: null, targetDate: today, // 使用今天的日期作为默认值 })); setSecondSearchResults(filteredWithQty); setHasSearchedSecond(true); setIsLoadingSecondSearch(false); }, 500); }, [items, formProps]); // Add reset handler for second search const handleSecondReset = useCallback(() => { console.log("Second search reset"); setSecondSearchQuery({}); setSecondSearchResults([]); setHasSearchedSecond(false); // 清空表单中的类型,但保留今天的日期 formProps.setValue("type", ""); const today = dayjs().format(INPUT_DATE_FORMAT); formProps.setValue("targetDate", today); }, [formProps]); // Add quantity change handler for second search const handleSecondSearchQtyChange = useCallback((itemId: number, newQty: number | null) => { setSecondSearchResults(prev => prev.map(item => item.id === itemId ? { ...item, qty: newQty } : item ) ); // Auto-update created items if this item exists there setCreatedItems(prev => prev.map(item => item.itemId === itemId ? { ...item, qty: newQty || 1 } : item ) ); }, []); // Add item selection handler for second search const handleSecondSearchItemSelect = useCallback((itemId: number, isSelected: boolean) => { if (isSelected) { const item = secondSearchResults.find(i => i.id === itemId); if (!item) return; const existingItem = createdItems.find(created => created.itemId === item.id); if (existingItem) { alert(t("Item already exists in created items")); return; } const newCreatedItem: CreatedItem = { itemId: item.id, itemName: item.label, itemCode: item.label, qty: item.qty || 1, uom: item.uom || "", uomId: item.uomId || 0, isSelected: true, currentStockBalance: item.currentStockBalance, targetDate: item.targetDate || targetDate, }; setCreatedItems(prev => [...prev, newCreatedItem]); } }, [secondSearchResults, createdItems, t, targetDate]); // Add checkbox change handler for second search const handleSecondSearchCheckboxChange = useCallback((ids: (string | number)[] | ((prev: (string | number)[]) => (string | number)[])) => { if (typeof ids === 'function') { const newIds = ids(selectedSecondSearchItemIds); setSelectedSecondSearchItemIds(newIds); // 处理全选逻辑 - 选择所有搜索结果,不仅仅是当前页面 if (newIds.length === secondSearchResults.length) { // 全选:将所有搜索结果添加到创建项目 secondSearchResults.forEach(item => { if (!isItemInCreated(item.id)) { handleSecondSearchItemSelect(item.id, true); } }); } else { // 部分选择:只处理当前页面的选择 secondSearchResults.forEach(item => { const isSelected = newIds.includes(item.id); const isCurrentlyInCreated = isItemInCreated(item.id); if (isSelected && !isCurrentlyInCreated) { handleSecondSearchItemSelect(item.id, true); } else if (!isSelected && isCurrentlyInCreated) { setCreatedItems(prev => prev.filter(createdItem => createdItem.itemId !== item.id)); } }); } } else { const previousIds = selectedSecondSearchItemIds; setSelectedSecondSearchItemIds(ids); const newlySelected = ids.filter(id => !previousIds.includes(id)); const newlyDeselected = previousIds.filter(id => !ids.includes(id)); newlySelected.forEach(id => { if (!isItemInCreated(id as number)) { handleSecondSearchItemSelect(id as number, true); } }); newlyDeselected.forEach(id => { setCreatedItems(prev => prev.filter(createdItem => createdItem.itemId !== id)); }); } }, [selectedSecondSearchItemIds, secondSearchResults, isItemInCreated, handleSecondSearchItemSelect]); // Define columns for second search (same as first search but with different handlers) const secondSearchItemColumns: Column[] = useMemo(() => [ { name: "id", label: "", type: "checkbox", disabled: (item) => isItemInCreated(item.id), }, { name: "label", label: t("Item"), renderCell: (item) => { // 格式化标签显示:将 "CODE - NAME" 格式化为更友好的显示 const parts = item.label.split(' - '); const code = parts[0] || ''; const name = parts[1] || ''; return ( {name} {/* 显示项目名称 */} {code} {/* 显示项目代码 */} ); }, }, { name: "currentStockBalance", label: t("Current Stock"), renderCell: (item) => { const stockBalance = item.currentStockBalance || 0; return ( 0 ? "success.main" : "error.main"} sx={{ fontWeight: stockBalance > 0 ? 'bold' : 'normal' }} > {stockBalance} ); }, }, { name: "uom", label: t("Unit"), renderCell: (item) => item.uom || "-", }, { name: "qty", label: t("Order Quantity"), renderCell: (item) => ( { const value = e.target.value; const numValue = value === "" ? null : Number(value); handleSecondSearchQtyChange(item.id, numValue); }} onKeyDown={(e) => { if (!/[0-9]/.test(e.key) && !['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Enter'].includes(e.key)) { e.preventDefault(); } }} inputProps={{ min: 1, step: 1, style: { textAlign: 'center' } }} sx={{ width: '80px', '& .MuiInputBase-input': { textAlign: 'center', cursor: 'text' } }} /> ), }, { name: "targetDate", label: t("Target Date"), renderCell: (item) => ( { if (date) { const formattedDate = date.format(INPUT_DATE_FORMAT); // 更新搜索结果中的目标日期 setSecondSearchResults(prev => prev.map(searchItem => searchItem.id === item.id ? { ...searchItem, targetDate: formattedDate } : searchItem ) ); // 更新创建项目中的目标日期 setCreatedItems(prev => prev.map(createdItem => createdItem.itemId === item.id ? { ...createdItem, targetDate: formattedDate } : createdItem ) ); // 更新表单中的目标日期 formProps.setValue("targetDate", formattedDate); } }} slotProps={{ textField: { size: "small", sx: { width: '160px', // 增加宽度以显示完整日期 '& .MuiInputBase-input': { fontSize: '0.875rem' // 稍微减小字体以适应更多内容 } } }, }} /> ), }, ], [t, isItemInCreated, handleSecondSearchQtyChange, formProps]); return ( {/* {t("Pick Order Detail")} {/* option.type} options={typeList} onChange={handleTypeChange} renderInput={(params) => } /> ( )} /> ( )} /> ( { if (!date) return; formProps.setValue("targetDate", date.format(INPUT_DATE_FORMAT)); }} inputRef={field.ref} slotProps={{ textField: { error: Boolean(errors.targetDate?.message), helperText: errors.targetDate?.message, }, }} /> )} /> */} {/* First Search Box - Item Search */} {t("Search Items")} {/* Second Search Results */} {hasSearchedSecond && ( {t("Search Results")} ({secondSearchResults.length}) {isLoadingSecondSearch ? ( {t("Loading...")} ) : secondSearchResults.length === 0 ? ( {t("No results found")} ) : ( items={secondSearchResults} columns={secondSearchItemColumns} totalCount={secondSearchResults.length} checkboxIds={selectedSecondSearchItemIds} setCheckboxIds={handleSecondSearchCheckboxChange} /> )} )} {/* Search Results with SearchResults component */} {hasSearched && filteredItems.length > 0 && ( {t("Search Results")} ({filteredItems.length}) {filteredItems.length >= 100 && ( {t("Showing first 100 results")} )} items={filteredItems} columns={searchItemColumns} totalCount={filteredItems.length} checkboxIds={selectedSearchItemIds} setCheckboxIds={handleSearchCheckboxChange} /> )} {/* 创建项目区域 */} {createdItems.length > 0 && ( {t("Created Items")} ({createdItems.length}) {t("Selected")} {t("Item")} {t("Current Stock")} {t("Unit")} {t("Order Quantity")} {t("Target Date")} {createdItems.map((item) => ( handleCreatedItemSelect(item.itemId, e.target.checked)} /> {item.itemName} {item.itemCode} 0 ? "success.main" : "error.main"} > {item.currentStockBalance || 0} {item.uom} { const newQty = Number(e.target.value); handleQtyChange(item.itemId, newQty); setFilteredItems(prev => prev.map(searchItem => searchItem.id === item.itemId ? { ...searchItem, qty: newQty } : searchItem ) ); }} onKeyDown={(e) => { if (!/[0-9]/.test(e.key) && !['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', 'Enter'].includes(e.key)) { e.preventDefault(); } }} inputProps={{ min: 1, step: 1, style: { textAlign: 'center' } }} sx={{ width: '80px', '& .MuiInputBase-input': { textAlign: 'center', cursor: 'text' } }} /> { if (date) { const formattedDate = date.format(INPUT_DATE_FORMAT); handleQtyChange(item.itemId, item.qty); // 触发重新渲染 setCreatedItems(prev => prev.map(createdItem => createdItem.itemId === item.itemId ? { ...createdItem, targetDate: formattedDate } : createdItem ) ); formProps.setValue("targetDate", formattedDate); } }} slotProps={{ textField: { size: "small", sx: { width: '180px', // 增加宽度以显示完整日期 '& .MuiInputBase-input': { fontSize: '0.875rem' // 稍微减小字体以适应更多内容 } } }, }} /> ))}
)} {/* 操作按钮 */}
); }; export default NewCreateItem;