5
5
This commit is contained in:
750
src/App.tsx
750
src/App.tsx
@ -3,6 +3,7 @@ import { Button, Typography, List, Card, Space, Divider, Spin, Table, Select, Mo
|
|||||||
import { useState, useEffect, useRef } from 'react';
|
import { useState, useEffect, useRef } from 'react';
|
||||||
import { addDays, format } from 'date-fns';
|
import { addDays, format } from 'date-fns';
|
||||||
import { zhCN } from 'date-fns/locale';
|
import { zhCN } from 'date-fns/locale';
|
||||||
|
import { executePricingQuery, executeSecondaryProcessQuery, executePricingDetailsQuery } from './services/apiService';
|
||||||
|
|
||||||
const { Title, Text } = Typography;
|
const { Title, Text } = Typography;
|
||||||
|
|
||||||
@ -36,7 +37,12 @@ export default function App() {
|
|||||||
const [selectedRecords, setSelectedRecords] = useState<string[]>([]);
|
const [selectedRecords, setSelectedRecords] = useState<string[]>([]);
|
||||||
const [recordDetails, setRecordDetails] = useState<any[]>([]);
|
const [recordDetails, setRecordDetails] = useState<any[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [queryResults, setQueryResults] = useState<any[]>([]);
|
||||||
|
const [queryLoading, setQueryLoading] = useState(false);
|
||||||
|
const [secondaryProcessResults, setSecondaryProcessResults] = useState<any[]>([]);
|
||||||
|
const [secondaryProcessLoading, setSecondaryProcessLoading] = useState(false);
|
||||||
|
const [pricingDetailsResults, setPricingDetailsResults] = useState<any[]>([]);
|
||||||
|
const [pricingDetailsLoading, setPricingDetailsLoading] = useState(false);
|
||||||
|
|
||||||
// 标签相关状态
|
// 标签相关状态
|
||||||
const [labelOptions, setLabelOptions] = useState<{[key: string]: any[]}>({});
|
const [labelOptions, setLabelOptions] = useState<{[key: string]: any[]}>({});
|
||||||
@ -88,8 +94,6 @@ export default function App() {
|
|||||||
const [batchProgressList, setBatchProgressList] = useState<{ index: number; foreignId: string; status: 'success' | 'failed'; message?: string }[]>([]);
|
const [batchProgressList, setBatchProgressList] = useState<{ index: number; foreignId: string; status: 'success' | 'failed'; message?: string }[]>([]);
|
||||||
const [batchCurrentRowInfo, setBatchCurrentRowInfo] = useState<{ index: number; foreignId: string; style: string; color: string } | null>(null);
|
const [batchCurrentRowInfo, setBatchCurrentRowInfo] = useState<{ index: number; foreignId: string; style: string; color: string } | null>(null);
|
||||||
const batchAbortRef = useRef<boolean>(false);
|
const batchAbortRef = useRef<boolean>(false);
|
||||||
const [lastSavedDeliveryRecordId, setLastSavedDeliveryRecordId] = useState<string | null>(null);
|
|
||||||
const [lastSavedDeliveryVersion, setLastSavedDeliveryVersion] = useState<number | null>(null);
|
|
||||||
// 删除未使用的 deliveryRecords 状态
|
// 删除未使用的 deliveryRecords 状态
|
||||||
const [selectedDeliveryRecordId, setSelectedDeliveryRecordId] = useState<string>('');
|
const [selectedDeliveryRecordId, setSelectedDeliveryRecordId] = useState<string>('');
|
||||||
// 从货期记录读取到的record_ids(用于保存回写)
|
// 从货期记录读取到的record_ids(用于保存回写)
|
||||||
@ -103,6 +107,9 @@ export default function App() {
|
|||||||
const resetGlobalState = (opts?: { resetMode?: boolean }) => {
|
const resetGlobalState = (opts?: { resetMode?: boolean }) => {
|
||||||
// 运行时加载状态
|
// 运行时加载状态
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
setQueryLoading(false);
|
||||||
|
setSecondaryProcessLoading(false);
|
||||||
|
setPricingDetailsLoading(false);
|
||||||
setLabelLoading(false);
|
setLabelLoading(false);
|
||||||
setAdjustLoading(false);
|
setAdjustLoading(false);
|
||||||
setTimelineLoading(false);
|
setTimelineLoading(false);
|
||||||
@ -216,6 +223,26 @@ export default function App() {
|
|||||||
// 新表ID(批量生成表)
|
// 新表ID(批量生成表)
|
||||||
const BATCH_TABLE_ID = 'tblXO7iSxBYxrqtY';
|
const BATCH_TABLE_ID = 'tblXO7iSxBYxrqtY';
|
||||||
|
|
||||||
|
const fetchAllRecordsByPage = async (table: any, params?: any) => {
|
||||||
|
let token: any = undefined;
|
||||||
|
let all: any[] = [];
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
const res: any = await table.getRecordsByPage({ pageSize: Math.min(200, (params && params.pageSize) ? params.pageSize : 200), pageToken: token, ...(params || {}) });
|
||||||
|
const recs: any[] = Array.isArray(res?.records) ? res.records : [];
|
||||||
|
all = all.concat(recs);
|
||||||
|
const nextToken = res?.pageToken;
|
||||||
|
const hm = !!res?.hasMore;
|
||||||
|
token = nextToken;
|
||||||
|
if (!hm && !nextToken) break;
|
||||||
|
}
|
||||||
|
return all;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRecordTotalByPage = async (table: any, params?: any) => {
|
||||||
|
const res: any = await table.getRecordIdListByPage({ pageSize: 1, ...(params || {}) });
|
||||||
|
return res?.total || 0;
|
||||||
|
};
|
||||||
|
|
||||||
// 已移除:调整模式不再加载货期记录列表
|
// 已移除:调整模式不再加载货期记录列表
|
||||||
|
|
||||||
// 入口选择处理
|
// 入口选择处理
|
||||||
@ -229,8 +256,7 @@ export default function App() {
|
|||||||
const openBatchModal = async () => {
|
const openBatchModal = async () => {
|
||||||
try {
|
try {
|
||||||
const batchTable = await bitable.base.getTable(BATCH_TABLE_ID);
|
const batchTable = await bitable.base.getTable(BATCH_TABLE_ID);
|
||||||
const res = await batchTable.getRecords({ pageSize: 5000 });
|
const total = await getRecordTotalByPage(batchTable);
|
||||||
const total = res.records?.length || 0;
|
|
||||||
setBatchTotalRows(total);
|
setBatchTotalRows(total);
|
||||||
setBatchStartRow(1);
|
setBatchStartRow(1);
|
||||||
setBatchEndRow(total > 0 ? total : 1);
|
setBatchEndRow(total > 0 ? total : 1);
|
||||||
@ -258,11 +284,15 @@ export default function App() {
|
|||||||
setTimelineLoading(true);
|
setTimelineLoading(true);
|
||||||
try {
|
try {
|
||||||
const deliveryTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
const deliveryTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
||||||
const deliveryRecord = await deliveryTable.getRecordById(deliveryRecordId);
|
const nodeDetailsField: any = await deliveryTable.getField(DELIVERY_NODE_DETAILS_FIELD_ID);
|
||||||
const nodeDetailsVal = deliveryRecord?.fields?.[DELIVERY_NODE_DETAILS_FIELD_ID];
|
const recordIdsField: any = await deliveryTable.getField(DELIVERY_RECORD_IDS_FIELD_ID);
|
||||||
|
const snapshotField: any = await deliveryTable.getField(DELIVERY_SNAPSHOT_JSON_FIELD_ID);
|
||||||
|
const startTimeField: any = await deliveryTable.getField(DELIVERY_START_TIME_FIELD_ID);
|
||||||
|
|
||||||
|
const nodeDetailsVal = await nodeDetailsField.getValue(deliveryRecordId);
|
||||||
// 读取record_ids文本字段并保留原始文本(用于原样写回)
|
// 读取record_ids文本字段并保留原始文本(用于原样写回)
|
||||||
try {
|
try {
|
||||||
const recordIdsTextVal = deliveryRecord?.fields?.[DELIVERY_RECORD_IDS_FIELD_ID];
|
const recordIdsTextVal = await recordIdsField.getValue(deliveryRecordId);
|
||||||
const raw = extractText(recordIdsTextVal);
|
const raw = extractText(recordIdsTextVal);
|
||||||
if (raw && raw.trim() !== '') {
|
if (raw && raw.trim() !== '') {
|
||||||
setRestoredRecordIdsText(raw.trim());
|
setRestoredRecordIdsText(raw.trim());
|
||||||
@ -284,7 +314,7 @@ export default function App() {
|
|||||||
|
|
||||||
// 优先使用货期记录表中的快照字段进行一键还原(新方案)
|
// 优先使用货期记录表中的快照字段进行一键还原(新方案)
|
||||||
try {
|
try {
|
||||||
const deliverySnapVal = deliveryRecord?.fields?.[DELIVERY_SNAPSHOT_JSON_FIELD_ID];
|
const deliverySnapVal = await snapshotField.getValue(deliveryRecordId);
|
||||||
let deliverySnapStr: string | null = null;
|
let deliverySnapStr: string | null = null;
|
||||||
if (typeof deliverySnapVal === 'string') {
|
if (typeof deliverySnapVal === 'string') {
|
||||||
deliverySnapStr = deliverySnapVal;
|
deliverySnapStr = deliverySnapVal;
|
||||||
@ -357,7 +387,7 @@ export default function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!startTimeRestored) {
|
if (!startTimeRestored) {
|
||||||
const startTimeValue = deliveryRecord?.fields?.[DELIVERY_START_TIME_FIELD_ID];
|
const startTimeValue = await startTimeField.getValue(deliveryRecordId);
|
||||||
if (startTimeValue) {
|
if (startTimeValue) {
|
||||||
let extractedStartTime: Date | null = null;
|
let extractedStartTime: Date | null = null;
|
||||||
if (typeof startTimeValue === 'number') {
|
if (typeof startTimeValue === 'number') {
|
||||||
@ -427,6 +457,120 @@ export default function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const processTable = await bitable.base.getTable(PROCESS_DATA_TABLE_ID);
|
const processTable = await bitable.base.getTable(PROCESS_DATA_TABLE_ID);
|
||||||
|
try {
|
||||||
|
const processSnapshotField: any = await processTable.getField(PROCESS_SNAPSHOT_JSON_FIELD_ID);
|
||||||
|
let snapStr: string | null = null;
|
||||||
|
for (const id of recordIds) {
|
||||||
|
const snapVal = await processSnapshotField.getValue(id);
|
||||||
|
const candidate = extractText(snapVal);
|
||||||
|
if (candidate && candidate.trim() !== '') {
|
||||||
|
snapStr = candidate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (snapStr && snapStr.trim() !== '') {
|
||||||
|
const snapshot = JSON.parse(snapStr);
|
||||||
|
if (Array.isArray(snapshot.timelineResults)) {
|
||||||
|
setIsRestoringSnapshot(true);
|
||||||
|
|
||||||
|
if (snapshot.selectedLabels) setSelectedLabels(snapshot.selectedLabels);
|
||||||
|
if (!mode && snapshot.mode) setMode(snapshot.mode);
|
||||||
|
if (snapshot.foreignId) setCurrentForeignId(snapshot.foreignId);
|
||||||
|
if (snapshot.styleText) setCurrentStyleText(snapshot.styleText);
|
||||||
|
if (snapshot.colorText) setCurrentColorText(snapshot.colorText);
|
||||||
|
if (snapshot.text2) setCurrentText2(snapshot.text2);
|
||||||
|
|
||||||
|
if (snapshot.generationModeState) {
|
||||||
|
const genState = snapshot.generationModeState;
|
||||||
|
if (genState.currentForeignId) setCurrentForeignId(genState.currentForeignId);
|
||||||
|
if (genState.currentStyleText) setCurrentStyleText(genState.currentStyleText);
|
||||||
|
if (genState.currentColorText) setCurrentColorText(genState.currentColorText);
|
||||||
|
if (genState.currentText2) setCurrentText2(genState.currentText2);
|
||||||
|
if (genState.currentVersionNumber !== undefined) setCurrentVersionNumber(genState.currentVersionNumber);
|
||||||
|
if (genState.recordDetails && Array.isArray(genState.recordDetails)) {
|
||||||
|
setRecordDetails(genState.recordDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot.version !== undefined) {
|
||||||
|
let vNum: number | null = null;
|
||||||
|
if (typeof snapshot.version === 'number') {
|
||||||
|
vNum = snapshot.version;
|
||||||
|
} else if (typeof snapshot.version === 'string') {
|
||||||
|
const match = snapshot.version.match(/\d+/);
|
||||||
|
if (match) {
|
||||||
|
vNum = parseInt(match[0], 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vNum !== null && !isNaN(vNum)) setCurrentVersionNumber(vNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapshot.timelineAdjustments) setTimelineAdjustments(snapshot.timelineAdjustments);
|
||||||
|
if (snapshot.expectedDateTimestamp) {
|
||||||
|
setExpectedDate(new Date(snapshot.expectedDateTimestamp));
|
||||||
|
} else if (snapshot.expectedDateString) {
|
||||||
|
setExpectedDate(new Date(snapshot.expectedDateString));
|
||||||
|
}
|
||||||
|
|
||||||
|
let startTimeRestored = false;
|
||||||
|
if (snapshot.startTimestamp) {
|
||||||
|
setStartTime(new Date(snapshot.startTimestamp));
|
||||||
|
startTimeRestored = true;
|
||||||
|
} else if (snapshot.startString) {
|
||||||
|
const parsed = new Date(snapshot.startString);
|
||||||
|
if (!isNaN(parsed.getTime())) {
|
||||||
|
setStartTime(parsed);
|
||||||
|
startTimeRestored = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!startTimeRestored) {
|
||||||
|
const startTimeValue = await startTimeField.getValue(deliveryRecordId);
|
||||||
|
if (startTimeValue) {
|
||||||
|
let extractedStartTime: Date | null = null;
|
||||||
|
if (typeof startTimeValue === 'number') {
|
||||||
|
extractedStartTime = new Date(startTimeValue);
|
||||||
|
} else if (Array.isArray(startTimeValue) && startTimeValue.length > 0) {
|
||||||
|
const timestamp = startTimeValue[0];
|
||||||
|
if (typeof timestamp === 'number') {
|
||||||
|
extractedStartTime = new Date(timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (extractedStartTime && !isNaN(extractedStartTime.getTime())) {
|
||||||
|
setStartTime(extractedStartTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimelineResults(snapshot.timelineResults);
|
||||||
|
Modal.confirm({
|
||||||
|
title: '是否调整标签?',
|
||||||
|
content: '选择“是”将允许修改标签并重新生成计划(版本按V2/V3/V4递增)',
|
||||||
|
okText: '是,调整标签',
|
||||||
|
cancelText: '否,直接还原',
|
||||||
|
onOk: async () => {
|
||||||
|
setLabelAdjustmentFlow(true);
|
||||||
|
setTimelineVisible(false);
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({ toastType: 'info', message: '请在下方修改标签后点击重新生成计划' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onCancel: async () => {
|
||||||
|
setLabelAdjustmentFlow(false);
|
||||||
|
setTimelineVisible(true);
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({ toastType: 'success', message: '已按快照一模一样还原流程数据' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTimelineLoading(false);
|
||||||
|
setIsRestoringSnapshot(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('从节点快照快速还原失败,继续旧流程:', e);
|
||||||
|
}
|
||||||
|
|
||||||
const records = await Promise.all(recordIds.map(id => processTable.getRecordById(id)));
|
const records = await Promise.all(recordIds.map(id => processTable.getRecordById(id)));
|
||||||
|
|
||||||
// 优先使用文本2快照一模一样还原
|
// 优先使用文本2快照一模一样还原
|
||||||
@ -523,7 +667,7 @@ export default function App() {
|
|||||||
|
|
||||||
// 如果快照中没有起始时间信息,则从当前选中的货期记录中获取
|
// 如果快照中没有起始时间信息,则从当前选中的货期记录中获取
|
||||||
if (!startTimeRestored) {
|
if (!startTimeRestored) {
|
||||||
const startTimeValue = deliveryRecord?.fields?.[DELIVERY_START_TIME_FIELD_ID];
|
const startTimeValue = await startTimeField.getValue(deliveryRecordId);
|
||||||
if (startTimeValue) {
|
if (startTimeValue) {
|
||||||
let extractedStartTime: Date | null = null;
|
let extractedStartTime: Date | null = null;
|
||||||
if (typeof startTimeValue === 'number') {
|
if (typeof startTimeValue === 'number') {
|
||||||
@ -897,7 +1041,7 @@ export default function App() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 如果没有快照恢复起始时间,则从当前货期记录中获取起始时间
|
// 如果没有快照恢复起始时间,则从当前货期记录中获取起始时间
|
||||||
const startTimeValue = deliveryRecord?.fields?.[DELIVERY_START_TIME_FIELD_ID];
|
const startTimeValue = await startTimeField.getValue(deliveryRecordId);
|
||||||
if (startTimeValue) {
|
if (startTimeValue) {
|
||||||
let extractedStartTime: Date | null = null;
|
let extractedStartTime: Date | null = null;
|
||||||
if (typeof startTimeValue === 'number') {
|
if (typeof startTimeValue === 'number') {
|
||||||
@ -963,6 +1107,7 @@ export default function App() {
|
|||||||
const DELIVERY_TEXT2_FIELD_ID = 'fldG6LZnmU';
|
const DELIVERY_TEXT2_FIELD_ID = 'fldG6LZnmU';
|
||||||
// 记录ID文本字段(货期记录表新增)
|
// 记录ID文本字段(货期记录表新增)
|
||||||
const DELIVERY_RECORD_IDS_FIELD_ID = 'fldq3u7h7H';
|
const DELIVERY_RECORD_IDS_FIELD_ID = 'fldq3u7h7H';
|
||||||
|
const DELIVERY_FACTORY_DEPARTURE_DATE_FIELD_ID = 'fldZFdZDKj';
|
||||||
|
|
||||||
// OMS看板表相关常量(新增)
|
// OMS看板表相关常量(新增)
|
||||||
const OMS_BOARD_TABLE_ID = 'tbl7j8bCpUbFmGuk'; // OMS看板表ID
|
const OMS_BOARD_TABLE_ID = 'tbl7j8bCpUbFmGuk'; // OMS看板表ID
|
||||||
@ -1516,8 +1661,8 @@ export default function App() {
|
|||||||
if (recordId && tableId === DELIVERY_RECORD_TABLE_ID) {
|
if (recordId && tableId === DELIVERY_RECORD_TABLE_ID) {
|
||||||
// 如果选中的是货期记录表的记录,从中获取起始时间
|
// 如果选中的是货期记录表的记录,从中获取起始时间
|
||||||
const deliveryTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
const deliveryTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
||||||
const deliveryRecord = await deliveryTable.getRecordById(recordId);
|
const startTimeField: any = await deliveryTable.getField(DELIVERY_START_TIME_FIELD_ID);
|
||||||
const startTimeValue = deliveryRecord?.fields?.[DELIVERY_START_TIME_FIELD_ID];
|
const startTimeValue = await startTimeField.getValue(recordId);
|
||||||
|
|
||||||
if (startTimeValue) {
|
if (startTimeValue) {
|
||||||
let extractedStartTime: Date | null = null;
|
let extractedStartTime: Date | null = null;
|
||||||
@ -1539,22 +1684,23 @@ export default function App() {
|
|||||||
// 从OMS看板匹配对应的货期记录后,尝试获取其起始时间
|
// 从OMS看板匹配对应的货期记录后,尝试获取其起始时间
|
||||||
try {
|
try {
|
||||||
const omsTable = await bitable.base.getTable(OMS_BOARD_TABLE_ID);
|
const omsTable = await bitable.base.getTable(OMS_BOARD_TABLE_ID);
|
||||||
const omsRecord = await omsTable.getRecordById(recordId);
|
const planTextField: any = await omsTable.getField(OMS_PLAN_TEXT_FIELD_ID);
|
||||||
const planTextRaw = omsRecord?.fields?.[OMS_PLAN_TEXT_FIELD_ID];
|
const planVersionField: any = await omsTable.getField(OMS_PLAN_VERSION_FIELD_ID);
|
||||||
const planVersionRaw = omsRecord?.fields?.[OMS_PLAN_VERSION_FIELD_ID];
|
const planTextRaw = await planTextField.getValue(recordId);
|
||||||
|
const planVersionRaw = await planVersionField.getValue(recordId);
|
||||||
const planText = extractText(planTextRaw)?.trim();
|
const planText = extractText(planTextRaw)?.trim();
|
||||||
let planVersion: number | null = null;
|
let planVersion: number | null = null;
|
||||||
if (typeof planVersionRaw === 'number') {
|
if (typeof planVersionRaw === 'number') {
|
||||||
planVersion = planVersionRaw;
|
planVersion = planVersionRaw;
|
||||||
} else if (typeof planVersionRaw === 'string') {
|
} else if (typeof planVersionRaw === 'string') {
|
||||||
const m = planVersionRaw.match(/\d+/);
|
const m = planVersionRaw.match(/\d+(?:\.\d+)?/);
|
||||||
if (m) planVersion = parseInt(m[0], 10);
|
if (m) planVersion = parseFloat(m[0]);
|
||||||
} else if (planVersionRaw && typeof planVersionRaw === 'object') {
|
} else if (planVersionRaw && typeof planVersionRaw === 'object') {
|
||||||
const v = (planVersionRaw as any).value ?? (planVersionRaw as any).text;
|
const v = (planVersionRaw as any).value ?? (planVersionRaw as any).text;
|
||||||
if (typeof v === 'number') planVersion = v;
|
if (typeof v === 'number') planVersion = v;
|
||||||
else if (typeof v === 'string') {
|
else if (typeof v === 'string') {
|
||||||
const m = v.match(/\d+/);
|
const m = v.match(/\d+(?:\.\d+)?/);
|
||||||
if (m) planVersion = parseInt(m[0], 10);
|
if (m) planVersion = parseFloat(m[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1562,8 +1708,8 @@ export default function App() {
|
|||||||
const deliveryRecordId = await findDeliveryRecordIdByPlan(planText, planVersion);
|
const deliveryRecordId = await findDeliveryRecordIdByPlan(planText, planVersion);
|
||||||
if (deliveryRecordId) {
|
if (deliveryRecordId) {
|
||||||
const deliveryTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
const deliveryTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
||||||
const deliveryRecord = await deliveryTable.getRecordById(deliveryRecordId);
|
const startTimeField: any = await deliveryTable.getField(DELIVERY_START_TIME_FIELD_ID);
|
||||||
const startTimeValue = deliveryRecord?.fields?.[DELIVERY_START_TIME_FIELD_ID];
|
const startTimeValue = await startTimeField.getValue(deliveryRecordId);
|
||||||
if (startTimeValue) {
|
if (startTimeValue) {
|
||||||
let extractedStartTime: Date | null = null;
|
let extractedStartTime: Date | null = null;
|
||||||
if (typeof startTimeValue === 'number') {
|
if (typeof startTimeValue === 'number') {
|
||||||
@ -1597,30 +1743,47 @@ export default function App() {
|
|||||||
const findDeliveryRecordIdByPlan = async (planText: string, planVersion: number): Promise<string | null> => {
|
const findDeliveryRecordIdByPlan = async (planText: string, planVersion: number): Promise<string | null> => {
|
||||||
try {
|
try {
|
||||||
const deliveryTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
const deliveryTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
||||||
// 拉取一定数量的记录进行匹配(如需可优化为分页/索引)
|
const versionField: any = await deliveryTable.getField(DELIVERY_VERSION_FIELD_ID);
|
||||||
const recordsResult = await deliveryTable.getRecords({ pageSize: 5000 });
|
const planFilter = {
|
||||||
const records = recordsResult.records || [];
|
conjunction: 'and',
|
||||||
for (const rec of records) {
|
conditions: [{ fieldId: DELIVERY_RECORD_IDS_FIELD_ID, operator: 'is', value: planText }]
|
||||||
const fields = rec?.fields || {};
|
};
|
||||||
const recordIdsTextVal = fields[DELIVERY_RECORD_IDS_FIELD_ID];
|
const sort = DELIVERY_CREATE_TIME_FIELD_ID
|
||||||
const versionVal = fields[DELIVERY_VERSION_FIELD_ID];
|
? [{ fieldId: DELIVERY_CREATE_TIME_FIELD_ID, desc: true }]
|
||||||
const recordIdsText = extractText(recordIdsTextVal)?.trim();
|
: undefined;
|
||||||
let versionNum: number | null = null;
|
|
||||||
if (typeof versionVal === 'number') versionNum = versionVal;
|
let token: any = undefined;
|
||||||
else if (typeof versionVal === 'string') {
|
const eps = 1e-9;
|
||||||
const m = versionVal.match(/\d+/);
|
for (let i = 0; i < 10000; i++) {
|
||||||
if (m) versionNum = parseInt(m[0], 10);
|
const res: any = await versionField.getFieldValueListByPage({
|
||||||
} else if (versionVal && typeof versionVal === 'object') {
|
pageSize: 200,
|
||||||
const v = (versionVal as any).value ?? (versionVal as any).text;
|
pageToken: token,
|
||||||
if (typeof v === 'number') versionNum = v;
|
filter: planFilter,
|
||||||
else if (typeof v === 'string') {
|
sort,
|
||||||
const m = v.match(/\d+/);
|
stringValue: true
|
||||||
if (m) versionNum = parseInt(m[0], 10);
|
});
|
||||||
|
const fieldValues: any[] = Array.isArray(res?.fieldValues) ? res.fieldValues : [];
|
||||||
|
|
||||||
|
for (const fv of fieldValues) {
|
||||||
|
const recordId = fv?.recordId;
|
||||||
|
const raw = fv?.value;
|
||||||
|
let v: number | null = null;
|
||||||
|
if (typeof raw === 'number') {
|
||||||
|
v = raw;
|
||||||
|
} else {
|
||||||
|
const s = typeof raw === 'string' ? raw : extractText(raw);
|
||||||
|
const m = (s || '').match(/\d+(?:\.\d+)?/);
|
||||||
|
if (m) v = parseFloat(m[0]);
|
||||||
|
}
|
||||||
|
if (v !== null && Math.abs(v - planVersion) < eps) {
|
||||||
|
return recordId || null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (recordIdsText && versionNum !== null && recordIdsText === planText && versionNum === planVersion) {
|
|
||||||
return rec.id || rec.recordId || null;
|
const nextToken = res?.pageToken;
|
||||||
}
|
const hasMore = !!res?.hasMore;
|
||||||
|
token = nextToken;
|
||||||
|
if (!hasMore && !nextToken) break;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -1779,11 +1942,7 @@ export default function App() {
|
|||||||
|
|
||||||
// 1. 先获取匹配的流程节点(复用预览功能的逻辑)
|
// 1. 先获取匹配的流程节点(复用预览功能的逻辑)
|
||||||
const processTable = await bitable.base.getTable(PROCESS_CONFIG_TABLE_ID);
|
const processTable = await bitable.base.getTable(PROCESS_CONFIG_TABLE_ID);
|
||||||
const processRecordsResult = await processTable.getRecords({
|
const processRecords = await fetchAllRecordsByPage(processTable);
|
||||||
pageSize: 5000
|
|
||||||
});
|
|
||||||
|
|
||||||
const processRecords = processRecordsResult.records || [];
|
|
||||||
const matchedProcessNodes: any[] = [];
|
const matchedProcessNodes: any[] = [];
|
||||||
|
|
||||||
// 匹配流程配置节点
|
// 匹配流程配置节点
|
||||||
@ -1965,11 +2124,7 @@ export default function App() {
|
|||||||
console.log('按顺序排列的流程节点:', matchedProcessNodes);
|
console.log('按顺序排列的流程节点:', matchedProcessNodes);
|
||||||
|
|
||||||
// 2. 优化:预先获取所有时效数据并建立索引
|
// 2. 优化:预先获取所有时效数据并建立索引
|
||||||
const timelineRecordsResult = await timelineTable.getRecords({
|
const timelineRecords = await fetchAllRecordsByPage(timelineTable);
|
||||||
pageSize: 5000
|
|
||||||
});
|
|
||||||
|
|
||||||
const timelineRecords = timelineRecordsResult.records || [];
|
|
||||||
|
|
||||||
// 优化2:预处理时效数据,建立节点名称到记录的映射
|
// 优化2:预处理时效数据,建立节点名称到记录的映射
|
||||||
const timelineIndexByNode = new Map<string, any[]>();
|
const timelineIndexByNode = new Map<string, any[]>();
|
||||||
@ -3008,7 +3163,8 @@ export default function App() {
|
|||||||
DELIVERY_CUSTOMER_EXPECTED_DATE_FIELD_ID,
|
DELIVERY_CUSTOMER_EXPECTED_DATE_FIELD_ID,
|
||||||
DELIVERY_NODE_DETAILS_FIELD_ID,
|
DELIVERY_NODE_DETAILS_FIELD_ID,
|
||||||
DELIVERY_ADJUSTMENT_INFO_FIELD_ID, // 添加货期调整信息字段
|
DELIVERY_ADJUSTMENT_INFO_FIELD_ID, // 添加货期调整信息字段
|
||||||
DELIVERY_START_TIME_FIELD_ID // 新增:起始时间字段
|
DELIVERY_START_TIME_FIELD_ID, // 新增:起始时间字段
|
||||||
|
DELIVERY_FACTORY_DEPARTURE_DATE_FIELD_ID
|
||||||
];
|
];
|
||||||
console.log('需要检查的字段ID列表:', fieldsToCheck);
|
console.log('需要检查的字段ID列表:', fieldsToCheck);
|
||||||
|
|
||||||
@ -3028,6 +3184,7 @@ export default function App() {
|
|||||||
const startTimeField = await deliveryRecordTable.getField(DELIVERY_START_TIME_FIELD_ID);
|
const startTimeField = await deliveryRecordTable.getField(DELIVERY_START_TIME_FIELD_ID);
|
||||||
const snapshotField = await deliveryRecordTable.getField(DELIVERY_SNAPSHOT_JSON_FIELD_ID);
|
const snapshotField = await deliveryRecordTable.getField(DELIVERY_SNAPSHOT_JSON_FIELD_ID);
|
||||||
const recordIdsTextField = await deliveryRecordTable.getField(DELIVERY_RECORD_IDS_FIELD_ID);
|
const recordIdsTextField = await deliveryRecordTable.getField(DELIVERY_RECORD_IDS_FIELD_ID);
|
||||||
|
const factoryDepartureDateField = await deliveryRecordTable.getField(DELIVERY_FACTORY_DEPARTURE_DATE_FIELD_ID);
|
||||||
console.log('成功获取所有字段对象');
|
console.log('成功获取所有字段对象');
|
||||||
|
|
||||||
// 检查标签汇总字段的类型
|
// 检查标签汇总字段的类型
|
||||||
@ -3159,33 +3316,28 @@ export default function App() {
|
|||||||
if (expectedDateToUse) {
|
if (expectedDateToUse) {
|
||||||
customerExpectedDate = expectedDateToUse.getTime();
|
customerExpectedDate = expectedDateToUse.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let factoryDepartureDate = null as number | null;
|
||||||
|
const reservationInbound = timelineResults.find(r => r?.nodeName === '预约入库');
|
||||||
|
const reservationEnd = reservationInbound?.estimatedEnd;
|
||||||
|
if (reservationEnd instanceof Date && !isNaN(reservationEnd.getTime())) {
|
||||||
|
factoryDepartureDate = reservationEnd.getTime();
|
||||||
|
} else if (typeof reservationEnd === 'number' && Number.isFinite(reservationEnd)) {
|
||||||
|
factoryDepartureDate = reservationEnd;
|
||||||
|
} else if (typeof reservationEnd === 'string' && reservationEnd.trim() !== '') {
|
||||||
|
const parsed = parseDate(reservationEnd);
|
||||||
|
if (parsed) {
|
||||||
|
factoryDepartureDate = parsed.getTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 创建当前时间戳
|
// 创建当前时间戳
|
||||||
const currentTime = new Date().getTime();
|
const currentTime = new Date().getTime();
|
||||||
|
|
||||||
// 计算版本号(数字)并格式化货期调整信息
|
// 计算版本号(数字)并格式化货期调整信息
|
||||||
let versionNumber = 1;
|
let versionNumber = 1;
|
||||||
try {
|
if (mode === 'adjust' && currentVersionNumber !== null) {
|
||||||
if (mode === 'adjust' && currentVersionNumber !== null) {
|
versionNumber = currentVersionNumber + 1;
|
||||||
// 调整模式:优先使用快照version +1
|
|
||||||
versionNumber = currentVersionNumber + 1;
|
|
||||||
} else if (foreignId) {
|
|
||||||
const existing = await deliveryRecordTable.getRecords({
|
|
||||||
pageSize: 5000,
|
|
||||||
filter: {
|
|
||||||
conjunction: 'and',
|
|
||||||
conditions: [{
|
|
||||||
fieldId: DELIVERY_FOREIGN_ID_FIELD_ID,
|
|
||||||
operator: 'is',
|
|
||||||
value: [foreignId]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const count = existing.records?.length || 0;
|
|
||||||
versionNumber = count + 1;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('计算版本号失败:', e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let adjustmentInfo = `版本:V${versionNumber}`;
|
let adjustmentInfo = `版本:V${versionNumber}`;
|
||||||
@ -3374,6 +3526,7 @@ export default function App() {
|
|||||||
const snapshotCell = await snapshotField.createCell(snapshotJson);
|
const snapshotCell = await snapshotField.createCell(snapshotJson);
|
||||||
const expectedDateCell = expectedDeliveryDate ? await expectedDateField.createCell(expectedDeliveryDate) : null;
|
const expectedDateCell = expectedDeliveryDate ? await expectedDateField.createCell(expectedDeliveryDate) : null;
|
||||||
const customerExpectedDateCell = customerExpectedDate ? await customerExpectedDateField.createCell(customerExpectedDate) : null;
|
const customerExpectedDateCell = customerExpectedDate ? await customerExpectedDateField.createCell(customerExpectedDate) : null;
|
||||||
|
const factoryDepartureDateCell = factoryDepartureDate ? await factoryDepartureDateField.createCell(factoryDepartureDate) : null;
|
||||||
// 对于关联记录字段,确保传入的是记录ID数组
|
// 对于关联记录字段,确保传入的是记录ID数组
|
||||||
const nodeDetailsCell = processRecordIds.length > 0 ?
|
const nodeDetailsCell = processRecordIds.length > 0 ?
|
||||||
await nodeDetailsField.createCell({ recordIds: processRecordIds }) : null;
|
await nodeDetailsField.createCell({ recordIds: processRecordIds }) : null;
|
||||||
@ -3394,22 +3547,13 @@ export default function App() {
|
|||||||
if (labelsCell) recordCells.push(labelsCell);
|
if (labelsCell) recordCells.push(labelsCell);
|
||||||
if (expectedDateCell) recordCells.push(expectedDateCell);
|
if (expectedDateCell) recordCells.push(expectedDateCell);
|
||||||
if (customerExpectedDateCell) recordCells.push(customerExpectedDateCell);
|
if (customerExpectedDateCell) recordCells.push(customerExpectedDateCell);
|
||||||
|
if (factoryDepartureDateCell) recordCells.push(factoryDepartureDateCell);
|
||||||
if (nodeDetailsCell) recordCells.push(nodeDetailsCell);
|
if (nodeDetailsCell) recordCells.push(nodeDetailsCell);
|
||||||
if (adjustmentInfoCell) recordCells.push(adjustmentInfoCell);
|
if (adjustmentInfoCell) recordCells.push(adjustmentInfoCell);
|
||||||
|
|
||||||
// 添加记录到货期记录表
|
// 添加记录到货期记录表
|
||||||
const addedRecord = await deliveryRecordTable.addRecord(recordCells);
|
const addedRecord = await deliveryRecordTable.addRecord(recordCells);
|
||||||
// 保存最近一次写入的记录ID与版本号
|
|
||||||
try {
|
|
||||||
const savedId = typeof addedRecord === 'string'
|
|
||||||
? addedRecord
|
|
||||||
: (((addedRecord as any)?.id || (addedRecord as any)?.recordId) as string);
|
|
||||||
if (savedId) {
|
|
||||||
setLastSavedDeliveryRecordId(savedId);
|
|
||||||
setLastSavedDeliveryVersion(versionNumber);
|
|
||||||
}
|
|
||||||
} catch {}
|
|
||||||
|
|
||||||
return addedRecord;
|
return addedRecord;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('写入货期记录表详细错误:', {
|
console.error('写入货期记录表详细错误:', {
|
||||||
@ -3533,70 +3677,13 @@ export default function App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 先删除该foreign_id的所有现有记录
|
|
||||||
console.log('=== 开始删除现有记录 ===');
|
|
||||||
console.log('使用的foreign_id:', foreignId);
|
|
||||||
try {
|
|
||||||
console.log('正在查询现有记录...');
|
|
||||||
const existingRecords = await processDataTable.getRecords({
|
|
||||||
pageSize: 5000,
|
|
||||||
filter: {
|
|
||||||
conjunction: 'And',
|
|
||||||
conditions: [{
|
|
||||||
fieldId: FOREIGN_ID_FIELD_ID,
|
|
||||||
operator: 'is',
|
|
||||||
value: [foreignId]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('查询到现有记录数量:', existingRecords.records?.length || 0);
|
|
||||||
|
|
||||||
if (existingRecords.records && existingRecords.records.length > 0) {
|
|
||||||
const recordIdsToDelete = existingRecords.records.map(record => record.id);
|
|
||||||
console.log('准备删除的记录ID:', recordIdsToDelete);
|
|
||||||
await processDataTable.deleteRecords(recordIdsToDelete);
|
|
||||||
console.log(`成功删除 ${recordIdsToDelete.length} 条现有记录`);
|
|
||||||
|
|
||||||
if (bitable.ui.showToast) {
|
|
||||||
await bitable.ui.showToast({
|
|
||||||
toastType: 'info',
|
|
||||||
message: `已删除 ${recordIdsToDelete.length} 条现有流程数据`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('没有找到需要删除的现有记录');
|
|
||||||
}
|
|
||||||
} catch (deleteError) {
|
|
||||||
console.error('删除现有记录时出错:', deleteError);
|
|
||||||
// 继续执行,不中断流程
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建页面快照JSON(确保可一模一样还原)
|
// 构建页面快照JSON(确保可一模一样还原)
|
||||||
// 计算版本号:数字。默认按 foreign_id 在货期记录表的记录数量 + 1
|
// 计算版本号:仅在调整模式下递增
|
||||||
let versionNumber = 1;
|
let versionNumber = 1;
|
||||||
try {
|
if (mode === 'adjust' && currentVersionNumber !== null) {
|
||||||
const deliveryRecordTable = await bitable.base.getTable(DELIVERY_RECORD_TABLE_ID);
|
versionNumber = currentVersionNumber + 1;
|
||||||
if (mode === 'adjust' && currentVersionNumber !== null) {
|
|
||||||
// 调整模式:优先使用快照version +1,避免公式字段读取错误
|
|
||||||
versionNumber = currentVersionNumber + 1;
|
|
||||||
} else if (foreignId) {
|
|
||||||
const existing = await deliveryRecordTable.getRecords({
|
|
||||||
pageSize: 5000,
|
|
||||||
filter: {
|
|
||||||
conjunction: 'and',
|
|
||||||
conditions: [{
|
|
||||||
fieldId: DELIVERY_FOREIGN_ID_FIELD_ID,
|
|
||||||
operator: 'is',
|
|
||||||
value: [foreignId]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const count = existing.records?.length || 0;
|
|
||||||
versionNumber = count + 1;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('计算版本号失败:', e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3606,6 +3693,12 @@ export default function App() {
|
|||||||
for (let index = 0; index < timelineResults.length; index++) {
|
for (let index = 0; index < timelineResults.length; index++) {
|
||||||
const result = timelineResults[index];
|
const result = timelineResults[index];
|
||||||
console.log('处理节点数据:', result);
|
console.log('处理节点数据:', result);
|
||||||
|
|
||||||
|
const hasValidTimelineValue = typeof result.timelineValue === 'number' && Number.isFinite(result.timelineValue) && result.timelineValue > 0;
|
||||||
|
if (!hasValidTimelineValue) {
|
||||||
|
console.log(`跳过节点 "${result.nodeName}" - 未匹配到时效值`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// 检查是否有有效的预计完成时间(只检查结束时间)
|
// 检查是否有有效的预计完成时间(只检查结束时间)
|
||||||
const hasValidEndTime = (
|
const hasValidEndTime = (
|
||||||
@ -3653,22 +3746,20 @@ export default function App() {
|
|||||||
|
|
||||||
// 组合所有Cell到一个记录中
|
// 组合所有Cell到一个记录中
|
||||||
const versionCell = await versionField.createCell(versionNumber);
|
const versionCell = await versionField.createCell(versionNumber);
|
||||||
const timelinessCell = (typeof result.timelineValue === 'number')
|
const timelinessCell = await timelinessField.createCell(result.timelineValue);
|
||||||
? await timelinessField.createCell(result.timelineValue)
|
|
||||||
: null;
|
|
||||||
const recordCells = [
|
const recordCells = [
|
||||||
foreignIdCell,
|
foreignIdCell,
|
||||||
processNameCell,
|
processNameCell,
|
||||||
processOrderCell,
|
processOrderCell,
|
||||||
styleCell,
|
styleCell,
|
||||||
colorCell,
|
colorCell,
|
||||||
versionCell
|
versionCell,
|
||||||
|
timelinessCell
|
||||||
];
|
];
|
||||||
|
|
||||||
// 只有当时间戳存在时才添加日期Cell
|
// 只有当时间戳存在时才添加日期Cell
|
||||||
if (startDateCell) recordCells.push(startDateCell);
|
if (startDateCell) recordCells.push(startDateCell);
|
||||||
if (endDateCell) recordCells.push(endDateCell);
|
if (endDateCell) recordCells.push(endDateCell);
|
||||||
if (timelinessCell) recordCells.push(timelinessCell);
|
|
||||||
|
|
||||||
console.log(`准备写入的Cell记录 - ${result.nodeName}:`, recordCells);
|
console.log(`准备写入的Cell记录 - ${result.nodeName}:`, recordCells);
|
||||||
recordCellsToAdd.push(recordCells);
|
recordCellsToAdd.push(recordCells);
|
||||||
@ -3712,7 +3803,7 @@ export default function App() {
|
|||||||
if (bitable.ui.showToast) {
|
if (bitable.ui.showToast) {
|
||||||
await bitable.ui.showToast({
|
await bitable.ui.showToast({
|
||||||
toastType: 'warning',
|
toastType: 'warning',
|
||||||
message: '没有有效的流程数据可以写入 - 所有节点都缺少时效数据'
|
message: '没有有效的流程数据可以写入 - 未匹配到时效值'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
@ -3782,9 +3873,15 @@ export default function App() {
|
|||||||
const batchTable = await bitable.base.getTable(BATCH_TABLE_ID);
|
const batchTable = await bitable.base.getTable(BATCH_TABLE_ID);
|
||||||
const fieldMetaList = await batchTable.getFieldMetaList();
|
const fieldMetaList = await batchTable.getFieldMetaList();
|
||||||
const nameToId = new Map<string, string>();
|
const nameToId = new Map<string, string>();
|
||||||
for (const f of fieldMetaList) nameToId.set(f.name, f.id);
|
for (const meta of (fieldMetaList || [])) {
|
||||||
const res = await batchTable.getRecords({ pageSize: 5000 });
|
if (!meta) continue;
|
||||||
const rows = res.records || [];
|
const nm = (meta as any).name;
|
||||||
|
const id = (meta as any).id;
|
||||||
|
if (typeof nm === 'string' && typeof id === 'string' && nm.trim() && id.trim()) {
|
||||||
|
nameToId.set(nm, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const rows = await fetchAllRecordsByPage(batchTable);
|
||||||
const total = rows.length;
|
const total = rows.length;
|
||||||
const startIndex1 = range?.start && range.start > 0 ? range.start : 1;
|
const startIndex1 = range?.start && range.start > 0 ? range.start : 1;
|
||||||
const endIndex1 = range?.end && range.end > 0 ? range.end : total;
|
const endIndex1 = range?.end && range.end > 0 ? range.end : total;
|
||||||
@ -3933,7 +4030,169 @@ export default function App() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 执行定价数据查询
|
||||||
|
const executeQuery = async (packId: string, packType: string) => {
|
||||||
|
if (queryLoading) return;
|
||||||
|
setQueryLoading(true);
|
||||||
|
try {
|
||||||
|
// 使用 apiService 中的函数
|
||||||
|
const data = await executePricingQuery(packId, packType, selectedLabels);
|
||||||
|
setQueryResults(data);
|
||||||
|
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'success',
|
||||||
|
message: '查询成功'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('数据库查询出错:', error);
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'error',
|
||||||
|
message: `数据库查询失败: ${error.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setQueryLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 执行二次工艺查询
|
||||||
|
const executeSecondaryProcessQueryLocal = async (packId: string, packType: string) => {
|
||||||
|
if (secondaryProcessLoading) return;
|
||||||
|
setSecondaryProcessLoading(true);
|
||||||
|
try {
|
||||||
|
const data = await executeSecondaryProcessQuery(packId, packType);
|
||||||
|
setSecondaryProcessResults(data);
|
||||||
|
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'success',
|
||||||
|
message: '二次工艺查询成功'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('二次工艺查询出错:', error);
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'error',
|
||||||
|
message: `二次工艺查询失败: ${error.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setSecondaryProcessLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 执行定价详情查询
|
||||||
|
const executePricingDetailsQueryLocal = async (packId: string) => {
|
||||||
|
if (pricingDetailsLoading) return;
|
||||||
|
setPricingDetailsLoading(true);
|
||||||
|
try {
|
||||||
|
const data = await executePricingDetailsQuery(packId);
|
||||||
|
setPricingDetailsResults(data);
|
||||||
|
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'success',
|
||||||
|
message: '定价详情查询成功'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('定价详情查询出错:', error);
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'error',
|
||||||
|
message: `定价详情查询失败: ${error.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setPricingDetailsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理数据库查询
|
||||||
|
const handleQueryDatabase = async (record: any) => {
|
||||||
|
// 从记录字段中提取 packId 和 packType
|
||||||
|
let packId = '';
|
||||||
|
let packType = '';
|
||||||
|
|
||||||
|
// 提取 pack_id (fldpvBfeC0)
|
||||||
|
if (record.fields.fldpvBfeC0 && Array.isArray(record.fields.fldpvBfeC0) && record.fields.fldpvBfeC0.length > 0) {
|
||||||
|
packId = record.fields.fldpvBfeC0[0].text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取 pack_type (fldSAF9qXe)
|
||||||
|
if (record.fields.fldSAF9qXe && record.fields.fldSAF9qXe.text) {
|
||||||
|
packType = record.fields.fldSAF9qXe.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!packId || !packType) {
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'error',
|
||||||
|
message: '缺少必要的查询参数 (pack_id 或 pack_type)'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await executeQuery(packId, packType);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理二次工艺查询
|
||||||
|
const handleSecondaryProcessQuery = async (record: any) => {
|
||||||
|
// 从记录字段中提取 packId 和 packType
|
||||||
|
let packId = '';
|
||||||
|
let packType = '';
|
||||||
|
|
||||||
|
// 提取 pack_id (fldpvBfeC0)
|
||||||
|
if (record.fields.fldpvBfeC0 && Array.isArray(record.fields.fldpvBfeC0) && record.fields.fldpvBfeC0.length > 0) {
|
||||||
|
packId = record.fields.fldpvBfeC0[0].text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取 pack_type (fldSAF9qXe)
|
||||||
|
if (record.fields.fldSAF9qXe && record.fields.fldSAF9qXe.text) {
|
||||||
|
packType = record.fields.fldSAF9qXe.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!packId || !packType) {
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'error',
|
||||||
|
message: '缺少必要的查询参数 (pack_id 或 pack_type)'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await executeSecondaryProcessQueryLocal(packId, packType);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理定价详情查询
|
||||||
|
const handlePricingDetailsQuery = async (record: any) => {
|
||||||
|
// 从记录字段中提取 packId
|
||||||
|
let packId = '';
|
||||||
|
|
||||||
|
// 提取 pack_id (fldpvBfeC0)
|
||||||
|
if (record.fields.fldpvBfeC0 && Array.isArray(record.fields.fldpvBfeC0) && record.fields.fldpvBfeC0.length > 0) {
|
||||||
|
packId = record.fields.fldpvBfeC0[0].text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!packId) {
|
||||||
|
if (bitable.ui.showToast) {
|
||||||
|
await bitable.ui.showToast({
|
||||||
|
toastType: 'error',
|
||||||
|
message: '缺少必要的查询参数 (pack_id)'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await executePricingDetailsQueryLocal(packId);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -4173,12 +4432,115 @@ export default function App() {
|
|||||||
const handleClearRecords = () => {
|
const handleClearRecords = () => {
|
||||||
setSelectedRecords([]);
|
setSelectedRecords([]);
|
||||||
setRecordDetails([]);
|
setRecordDetails([]);
|
||||||
|
setQueryResults([]);
|
||||||
|
setSecondaryProcessResults([]);
|
||||||
|
setPricingDetailsResults([]);
|
||||||
// 同时清空标签选择
|
// 同时清空标签选择
|
||||||
setSelectedLabels({});
|
setSelectedLabels({});
|
||||||
setExpectedDate(null);
|
setExpectedDate(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 定价数据表格列定义
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Pack ID',
|
||||||
|
dataIndex: 'pack_id',
|
||||||
|
key: 'pack_id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Pack Type',
|
||||||
|
dataIndex: 'pack_type',
|
||||||
|
key: 'pack_type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '物料编码',
|
||||||
|
dataIndex: 'material_code',
|
||||||
|
key: 'material_code',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '一级分类',
|
||||||
|
dataIndex: 'category1_name',
|
||||||
|
key: 'category1_name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '二级分类',
|
||||||
|
dataIndex: 'category2_name',
|
||||||
|
key: 'category2_name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '三级分类',
|
||||||
|
dataIndex: 'category3_name',
|
||||||
|
key: 'category3_name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '品类属性',
|
||||||
|
dataIndex: '品类属性',
|
||||||
|
key: '品类属性',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 二次工艺表格列定义
|
||||||
|
const secondaryProcessColumns = [
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'id',
|
||||||
|
key: 'id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Foreign ID',
|
||||||
|
dataIndex: 'foreign_id',
|
||||||
|
key: 'foreign_id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Pack Type',
|
||||||
|
dataIndex: 'pack_type',
|
||||||
|
key: 'pack_type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '项目',
|
||||||
|
dataIndex: 'costs_item',
|
||||||
|
key: 'costs_item',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '二次工艺',
|
||||||
|
dataIndex: 'costs_type',
|
||||||
|
key: 'costs_type',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '备注',
|
||||||
|
dataIndex: 'remarks',
|
||||||
|
key: 'remarks',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// 定价详情表格列定义
|
||||||
|
const pricingDetailsColumns = [
|
||||||
|
{
|
||||||
|
title: 'Pack ID',
|
||||||
|
dataIndex: 'pack_id',
|
||||||
|
key: 'pack_id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '倍率',
|
||||||
|
dataIndex: '倍率',
|
||||||
|
key: '倍率',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '加工费',
|
||||||
|
dataIndex: '加工费',
|
||||||
|
key: '加工费',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '总价',
|
||||||
|
dataIndex: '总价',
|
||||||
|
key: '总价',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: '20px' }}>
|
<div style={{ padding: '20px' }}>
|
||||||
@ -4330,30 +4692,6 @@ export default function App() {
|
|||||||
调整流程日期
|
调整流程日期
|
||||||
</Title>
|
</Title>
|
||||||
<Text type="tertiary" style={{ fontSize: '14px' }}>读取货期记录,精确还原时间线</Text>
|
<Text type="tertiary" style={{ fontSize: '14px' }}>读取货期记录,精确还原时间线</Text>
|
||||||
{lastSavedDeliveryRecordId && lastSavedDeliveryVersion !== null && (
|
|
||||||
<Card style={{ marginTop: '12px', padding: '12px', backgroundColor: '#f6f8fa', borderRadius: 8 }}>
|
|
||||||
<Text strong>最近保存的货期记录</Text>
|
|
||||||
<div style={{ marginTop: 8, display: 'flex', gap: 12, flexWrap: 'wrap' }}>
|
|
||||||
<span style={{
|
|
||||||
fontSize: 12,
|
|
||||||
color: '#1f2937',
|
|
||||||
background: 'rgba(245, 158, 11, 0.12)',
|
|
||||||
border: '1px solid rgba(245, 158, 11, 0.32)',
|
|
||||||
borderRadius: 6,
|
|
||||||
padding: '4px 8px',
|
|
||||||
fontWeight: 600
|
|
||||||
}}>版本:V{lastSavedDeliveryVersion}</span>
|
|
||||||
<span style={{
|
|
||||||
fontSize: 12,
|
|
||||||
color: '#111827',
|
|
||||||
background: 'rgba(17, 24, 39, 0.08)',
|
|
||||||
border: '1px solid rgba(17, 24, 39, 0.18)',
|
|
||||||
borderRadius: 6,
|
|
||||||
padding: '4px 8px'
|
|
||||||
}}>record_id:{lastSavedDeliveryRecordId}</span>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* 功能入口切换与调整入口 */}
|
{/* 功能入口切换与调整入口 */}
|
||||||
@ -5534,7 +5872,49 @@ export default function App() {
|
|||||||
{/* 批量处理配置已移除 */}
|
{/* 批量处理配置已移除 */}
|
||||||
</main>
|
</main>
|
||||||
)}
|
)}
|
||||||
|
{mode === 'generate' && (
|
||||||
|
<>
|
||||||
|
{/* 面料数据查询结果 */}
|
||||||
|
{queryResults.length > 0 && (
|
||||||
|
<>
|
||||||
|
<Divider />
|
||||||
|
<Title heading={4}>面料数据查询结果 ({queryResults.length} 条)</Title>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
dataSource={queryResults.map((item, index) => ({ ...item, key: index }))}
|
||||||
|
pagination={{ pageSize: 10 }}
|
||||||
|
style={{ marginTop: '10px' }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{/* 二次工艺查询结果 */}
|
||||||
|
{secondaryProcessResults.length > 0 && (
|
||||||
|
<>
|
||||||
|
<Divider />
|
||||||
|
<Title heading={4}>二次工艺查询结果 ({secondaryProcessResults.length} 条)</Title>
|
||||||
|
<Table
|
||||||
|
columns={secondaryProcessColumns}
|
||||||
|
dataSource={secondaryProcessResults.map((item, index) => ({ ...item, key: index }))}
|
||||||
|
pagination={{ pageSize: 10 }}
|
||||||
|
style={{ marginTop: '10px' }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{/* 工艺价格查询结果 */}
|
||||||
|
{pricingDetailsResults.length > 0 && (
|
||||||
|
<>
|
||||||
|
<Divider />
|
||||||
|
<Title heading={4}>工艺价格查询结果 ({pricingDetailsResults.length} 条)</Title>
|
||||||
|
<Table
|
||||||
|
columns={pricingDetailsColumns}
|
||||||
|
dataSource={pricingDetailsResults.map((item, index) => ({ ...item, key: index }))}
|
||||||
|
pagination={{ pageSize: 10 }}
|
||||||
|
style={{ marginTop: '10px' }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user