浏览代码

update

master
CANCERYS\kw093 1 个月前
父节点
当前提交
71ac0ce1a9
共有 6 个文件被更改,包括 782 次插入487 次删除
  1. +89
    -1
      src/app/api/pickOrder/actions.ts
  2. +19
    -7
      src/components/FinishedGoodSearch/FGPickOrderInfoCard.tsx
  3. +4
    -1
      src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx
  4. +57
    -26
      src/components/FinishedGoodSearch/GoodPickExecution.tsx
  5. +609
    -451
      src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx
  6. +4
    -1
      src/i18n/zh/pickOrder.json

+ 89
- 1
src/app/api/pickOrder/actions.ts 查看文件

@@ -111,7 +111,7 @@ export interface GetPickOrderLineInfo {
itemName: string;
availableQty: number| null;
requiredQty: number;
uomCode: string;
uomShortDesc: string;
uomDesc: string;
suggestedList: any[];
pickedQty: number;
@@ -245,6 +245,15 @@ export interface UpdateSuggestedLotLineIdRequest {
newLotLineId: number;
}
export interface FGPickOrderResponse {
// ✅ 新增:支持多个 pick orders
doPickOrderId: number; // ✅ 新增:do_pick_order 的 ID
pickOrderIds?: number[]; // ✅ 新增:所有 pick order IDs
pickOrderCodes?: string; // ✅ 新增:所有 pick order codes(逗号分隔)
deliveryOrderIds?: number[]; // ✅ 新增:所有 delivery order IDs
deliveryNos?: string; // ✅ 新增:所有 delivery order codes(逗号分隔)
numberOfPickOrders?: number; // ✅ 新增:pick order 数量
// ✅ 保留原有字段用于向后兼容(显示第一个 pick order)
pickOrderId: number;
pickOrderCode: string;
pickOrderConsoCode: string;
@@ -265,6 +274,37 @@ export interface FGPickOrderResponse {
storeId: string;
qrCodeData: number;
}
export interface DoPickOrderDetail {
doPickOrder: {
id: number;
store_id: string;
ticket_no: string;
ticket_status: string;
truck_id: number;
truck_departure_time: string;
shop_id: number;
handled_by: number | null;
loading_sequence: number;
ticket_release_time: string | null;
TruckLanceCode: string;
ShopCode: string;
ShopName: string;
RequiredDeliveryDate: string;
};
pickOrders: Array<{
pick_order_id: number;
pick_order_code: string;
do_order_id: number;
delivery_order_code: string;
consoCode: string;
status: string;
targetDate: string;
}>;
selectedPickOrderId: number;
lotDetails: any[]; // 使用现有的 lot detail 结构
pickOrderCodes?: string;
deliveryNos?: string;
}
export interface AutoAssignReleaseByStoreRequest {
userId: number;
storeId: string; // "2/F" | "4/F"
@@ -385,6 +425,20 @@ export interface LaneBtn {
unassigned: number;
total: number;
}
export const fetchDoPickOrderDetail = async (
doPickOrderId: number,
selectedPickOrderId?: number
): Promise<DoPickOrderDetail> => {
const url = selectedPickOrderId
? `${BASE_API_URL}/pickOrder/do-pick-order-detail/${doPickOrderId}?selectedPickOrderId=${selectedPickOrderId}`
: `${BASE_API_URL}/pickOrder/do-pick-order-detail/${doPickOrderId}`;
const response = await serverFetchJson<DoPickOrderDetail>(url, {
method: "GET",
});
return response;
};
export const updatePickExecutionIssueStatus = async (
data: UpdatePickExecutionIssueRequest
): Promise<PostPickOrderResponse> => {
@@ -738,6 +792,40 @@ interface SuggestionWithStatus {
stockOutLineQty?: number;
suggestionStatus: 'active' | 'completed' | 'rejected' | 'in_progress' | 'unknown';
}
// 在 actions.ts 中修改接口定义
export interface FGPickOrderHierarchicalResponse {
fgInfo: {
doPickOrderId: number;
ticketNo: string;
storeId: string;
shopCode: string;
shopName: string;
truckLanceCode: string;
departureTime: string;
};
pickOrders: Array<{
pickOrderId: number;
pickOrderCode: string;
doOrderId: number;
deliveryOrderCode: string;
consoCode: string;
status: string;
targetDate: string;
pickOrderLines: Array<{
id: number;
requiredQty: number;
status: string;
item: {
id: number;
code: string;
name: string;
uomCode: string;
uomDesc: string;
};
lots: Array<any>; // 可以是空数组
}>;
}>;
}
export interface CheckCompleteResponse {
id: number | null;
name: string;


+ 19
- 7
src/components/FinishedGoodSearch/FGPickOrderInfoCard.tsx 查看文件

@@ -2,14 +2,22 @@

import { Box, Card, CardContent, Grid, TextField, Stack } from "@mui/material";
import { useTranslation } from "react-i18next";
import { FGPickOrderResponse } from "@/app/api/pickOrder/actions";
import { FGPickOrderResponse, DoPickOrderDetail } from "@/app/api/pickOrder/actions";

interface Props {
fgOrder: FGPickOrderResponse;
doPickOrderDetail?: DoPickOrderDetail | null;
}

const FGPickOrderInfoCard: React.FC<Props> = ({ fgOrder }) => {
const FGPickOrderInfoCard: React.FC<Props> = ({ fgOrder, doPickOrderDetail }) => {
const { t } = useTranslation("pickOrder");
if (!fgOrder) {
return null;
}
const pickOrderCodes = fgOrder.pickOrderCodes || "";
const deliveryOrderCodes = fgOrder.deliveryNos || "";

return (
<Card sx={{ display: "block", mb: 2 }}>
@@ -17,21 +25,25 @@ const FGPickOrderInfoCard: React.FC<Props> = ({ fgOrder }) => {
<Box>
<Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
<Grid item xs={6}>
<Grid item xs={6}>
<TextField
value={fgOrder.pickOrderCode || ""}
label={t("Pick Order Code")}
value={pickOrderCodes || ""} // ✅ 显示所有 pick order codes
label={t("Pick Order Code(s)")} // ✅ 修改标签
fullWidth
disabled={true}
multiline={pickOrderCodes.includes(',')} // ✅ 如果有多个代码,使用多行
rows={pickOrderCodes.includes(',') ? 2 : 1}
/>
</Grid>
<Grid item xs={6}>
<TextField
value={fgOrder.deliveryNo || ""}
label={t("Delivery No")}
value={deliveryOrderCodes || ""} // ✅ 显示所有 delivery order codes
label={t("Delivery Order Code(s)")} // ✅ 修改标签
fullWidth
disabled={true}
multiline={deliveryOrderCodes.includes(',')} // ✅ 如果有多个代码,使用多行
rows={deliveryOrderCodes.includes(',') ? 2 : 1}
/>
</Grid>


+ 4
- 1
src/components/FinishedGoodSearch/FinishedGoodFloorLanePanel.tsx 查看文件

@@ -22,7 +22,8 @@ const FinishedGoodFloorLanePanel: React.FC<Props> = ({ onPickOrderAssigned }) =>
const [summary4F, setSummary4F] = useState<StoreLaneSummary | null>(null);
const [isLoadingSummary, setIsLoadingSummary] = useState(false);
const [isAssigning, setIsAssigning] = useState(false);
const [selectedDate, setSelectedDate] = useState<string>("today");
//const [selectedDate, setSelectedDate] = useState<string>("today");
const [selectedDate, setSelectedDate] = useState<string>("2025-09-27");

const loadData = async (dateValue: string) => {
setIsLoadingSummary(true);
@@ -131,6 +132,7 @@ const FinishedGoodFloorLanePanel: React.FC<Props> = ({ onPickOrderAssigned }) =>
<Box sx={{ maxWidth: 300, mb: 2 }}>
<FormControl fullWidth size="small">
<InputLabel id="date-select-label">{t("Select Date")}</InputLabel>
<Select
labelId="date-select-label"
id="date-select"
@@ -152,6 +154,7 @@ const FinishedGoodFloorLanePanel: React.FC<Props> = ({ onPickOrderAssigned }) =>
{t("Day After Tomorrow")} ({getDateLabel(2)})
</MenuItem>
</Select>
</FormControl>
</Box>



+ 57
- 26
src/components/FinishedGoodSearch/GoodPickExecution.tsx 查看文件

@@ -32,7 +32,9 @@ import {
AutoAssignReleaseResponse,
checkPickOrderCompletion,
PickOrderCompletionResponse,
checkAndCompletePickOrderByConsoCode
checkAndCompletePickOrderByConsoCode,
fetchDoPickOrderDetail,
DoPickOrderDetail,
} from "@/app/api/pickOrder/actions";
import { fetchNameList, NameList } from "@/app/api/user/actions";
import {
@@ -50,7 +52,8 @@ import { fetchStockInLineInfo } from "@/app/api/po/actions";
import GoodPickExecutionForm from "./GoodPickExecutionForm";
import FGPickOrderCard from "./FGPickOrderCard";
import FinishedGoodFloorLanePanel from "./FinishedGoodFloorLanePanel";
import FGPickOrderInfoCard from "./FGPickOrderInfoCard";
import FGPickOrderInfoCard from "./FGPickOrderInfoCard";
import GoodPickExecutiondetail from "./GoodPickExecutiondetail";
interface Props {
filterArgs: Record<string, any>;
onFgPickOrdersChange?: (fgPickOrders: FGPickOrderResponse[]) => void;
@@ -322,7 +325,9 @@ const PickExecution: React.FC<Props> = ({ filterArgs, onFgPickOrdersChange }) =>
const [originalCombinedData, setOriginalCombinedData] = useState<any[]>([]);
const { values: qrValues, isScanning, startScan, stopScan, resetScan } = useQrCodeScannerContext();
const [doPickOrderDetail, setDoPickOrderDetail] = useState<DoPickOrderDetail | null>(null);
const [selectedPickOrderId, setSelectedPickOrderId] = useState<number | null>(null);
const [pickOrderSwitching, setPickOrderSwitching] = useState(false);
const [qrScanInput, setQrScanInput] = useState<string>('');
const [qrScanError, setQrScanError] = useState<boolean>(false);
const [qrScanSuccess, setQrScanSuccess] = useState<boolean>(false);
@@ -352,25 +357,48 @@ const PickExecution: React.FC<Props> = ({ filterArgs, onFgPickOrdersChange }) =>
const [selectedLotForExecutionForm, setSelectedLotForExecutionForm] = useState<any | null>(null);
const [fgPickOrders, setFgPickOrders] = useState<FGPickOrderResponse[]>([]);
const [fgPickOrdersLoading, setFgPickOrdersLoading] = useState(false);
const fetchFgPickOrdersData = useCallback(async () => {
if (!currentUserId) return;
// 在 GoodPickExecutiondetail.tsx 中修改 fetchFgPickOrdersData
// 修改 fetchFgPickOrdersData 函数:
const fetchFgPickOrdersData = useCallback(async () => {
if (!currentUserId) return;
setFgPickOrdersLoading(true);
try {
const fgPickOrders = await fetchFGPickOrdersByUserId(currentUserId);
setFgPickOrdersLoading(true);
try {
// ✅ 简化:直接使用 userId 调用 API,不需要循环
const fgPickOrders = await fetchFGPickOrdersByUserId(currentUserId);
console.log("🔍 DEBUG: Fetched FG pick orders:", fgPickOrders);
console.log("🔍 DEBUG: First order numberOfPickOrders:", fgPickOrders[0]?.numberOfPickOrders);
setFgPickOrders(fgPickOrders);
// ✅ 如果有多个 pick orders,获取 do_pick_order 详细信息
if (fgPickOrders.length > 0 && fgPickOrders[0].numberOfPickOrders && fgPickOrders[0].numberOfPickOrders > 1) {
console.log("🔍 This ticket has multiple pick orders, fetching detail...");
setFgPickOrders(fgPickOrders);
onFgPickOrdersChange?.(fgPickOrders);
console.log("✅ Fetched FG pick orders for user:", fgPickOrders);
} catch (error) {
console.error("❌ Error fetching FG pick orders:", error);
setFgPickOrders([]);
onFgPickOrdersChange?.([]);
} finally {
setFgPickOrdersLoading(false);
try {
const detail = await fetchDoPickOrderDetail(fgPickOrders[0].doPickOrderId);
console.log("🔍 DEBUG: Fetched do_pick_order detail:", detail);
setDoPickOrderDetail(detail);
// ✅ 设置默认选中第一个 pick order
if (!selectedPickOrderId && detail.pickOrders.length > 0) {
setSelectedPickOrderId(detail.pickOrders[0].pick_order_id);
}
} catch (error) {
console.error("Error fetching do_pick_order detail:", error);
}
} else {
console.log("🔍 DEBUG: Single pick order or numberOfPickOrders not > 1");
console.log("🔍 DEBUG: numberOfPickOrders value:", fgPickOrders[0]?.numberOfPickOrders);
}
}, [currentUserId, onFgPickOrdersChange]);
} catch (error) {
console.error("❌ Error fetching FG pick orders:", error);
setFgPickOrders([]);
} finally {
setFgPickOrdersLoading(false);
}
}, [currentUserId, selectedPickOrderId]);
// ✅ 简化:移除复杂的 useEffect 依赖
useEffect(() => {
@@ -972,13 +1000,16 @@ return (
) : (
// ✅ 有活动订单,显示 FG 订单信息
<Box>
{fgPickOrders.map((fgOrder) => (
<FGPickOrderInfoCard
key={fgOrder.pickOrderId}
fgOrder={fgOrder}
/>
))}
</Box>
{fgPickOrders.map((fgOrder) => (
<Box key={fgOrder.pickOrderId} sx={{ mb: 2 }}>
<FGPickOrderInfoCard
fgOrder={fgOrder}
/>

</Box>
))}
</Box>
)}
{/* Modals */}


+ 609
- 451
src/components/FinishedGoodSearch/GoodPickExecutiondetail.tsx
文件差异内容过多而无法显示
查看文件


+ 4
- 1
src/i18n/zh/pickOrder.json 查看文件

@@ -13,11 +13,14 @@
"Assigned To": "已分配",
"Do you want to start?": "確定開始嗎?",
"Start": "開始",
"Pick Order Code(s)": "提料單編號",
"Delivery Order Code(s)": "送貨單編號",
"Start Success": "開始成功",
"Truck Lance Code": "車牌號碼",
"Completed Date": "完成日期",
"Completed Time": "完成時間",

"Select Pick Order:": "選擇提料單:",
"⚠️ No Stock Available": "⚠️ 沒有庫存",
"Start Fail": "開始失敗",
"Start PO": "開始採購訂單",
"Do you want to complete?": "確定完成嗎?",


正在加载...
取消
保存