diff --git a/src/App.tsx b/src/App.tsx index 10406b2..6b543a3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -60,6 +60,40 @@ export default function App() { return out; }; + const deriveGroupOrderDraftByProcessOrder = (nodes: any[]): ProcessGroupInstance[] => { + const arr = Array.isArray(nodes) ? nodes : []; + const groupToMinOrder = new Map(); + const groupToFirstIndex = new Map(); + for (let i = 0; i < arr.length; i++) { + const r: any = arr[i]; + const g = (typeof r?.processGroup === 'string' ? r.processGroup : extractText(r?.processGroup)).trim(); + if (!g) continue; + if (!groupToFirstIndex.has(g)) groupToFirstIndex.set(g, i); + const n = Number(r?.processOrder); + if (Number.isFinite(n)) { + const prev = groupToMinOrder.get(g); + if (typeof prev === 'undefined' || n < prev) groupToMinOrder.set(g, n); + } + } + const groups = Array.from(groupToFirstIndex.keys()); + groups.sort((a, b) => { + const ao = groupToMinOrder.get(a); + const bo = groupToMinOrder.get(b); + const aHas = typeof ao !== 'undefined'; + const bHas = typeof bo !== 'undefined'; + if (aHas && bHas) { + if (ao !== bo) return ao - bo; + } else if (aHas !== bHas) { + return aHas ? -1 : 1; + } + const ai = groupToFirstIndex.get(a) || 0; + const bi = groupToFirstIndex.get(b) || 0; + if (ai !== bi) return ai - bi; + return a.localeCompare(b, 'zh-Hans-CN'); + }); + return groups.map(g => createProcessGroupInstance(g)); + }; + const applyGroupOrderConfigToTimelineResults = (results: any[], config: ProcessGroupInstance[]) => { const base = Array.isArray(results) ? results : []; const order = Array.isArray(config) ? config : []; @@ -368,16 +402,46 @@ export default function App() { const BATCH_TABLE_ID = 'tblXO7iSxBYxrqtY'; const BATCH_ROW_NUMBER_FIELD_ID = 'fldiqlTVsU'; + const activateTableForPaging = async (table: any) => { + try { + if (typeof (table as any)?.getRecordIdListByPage === 'function') { + await (table as any).getRecordIdListByPage({ pageSize: 1 }); + return; + } + } catch {} + try { + if (typeof (table as any)?.getRecordIdList === 'function') { + await (table as any).getRecordIdList(); + } + } catch {} + }; + + const safeGetRecordsByPage = async (table: any, req: any) => { + const cleaned: any = { ...(req || {}) }; + if (!cleaned.viewId) delete cleaned.viewId; + if (!cleaned.pageToken) delete cleaned.pageToken; + if (!cleaned.pageSize || Number(cleaned.pageSize) <= 0) cleaned.pageSize = 200; + if (Number(cleaned.pageSize) > 200) cleaned.pageSize = 200; + + try { + return await table.getRecordsByPage(cleaned); + } catch (e: any) { + if (e?.code === 12) { + await activateTableForPaging(table); + return await table.getRecordsByPage(cleaned); + } + throw e; + } + }; + const fetchAllRecordsByPage = async (table: any, params?: any) => { let token: any = undefined; let all: any[] = []; for (let i = 0; i < 10000; i++) { const requestedPageSize = Math.min(200, (params && params.pageSize) ? params.pageSize : 200); const req: any = { pageSize: requestedPageSize, ...(params || {}) }; - if (!req.viewId) delete req.viewId; if (token) req.pageToken = token; - else delete req.pageToken; - const res: any = await table.getRecordsByPage(req); + const res: any = await safeGetRecordsByPage(table, req); const recs: any[] = Array.isArray(res?.records) ? res.records : []; all = all.concat(recs); const nextToken = res?.pageToken || res?.nextPageToken; @@ -419,7 +483,7 @@ export default function App() { const total = await getRecordTotalByPage(batchTable); let totalByRowNumber = 0; try { - const rows = await fetchAllRecordsByPage(batchTable); + const rows = await fetchAllRecordsByPage(batchTable, undefined); for (const r of rows) { const no = parseBatchRowNumber((r?.fields || {})[BATCH_ROW_NUMBER_FIELD_ID]); if (no !== null) totalByRowNumber = Math.max(totalByRowNumber, no); @@ -2334,7 +2398,7 @@ export default function App() { .filter((option: any) => option && typeof option.name === 'string') .map((option: any) => ({ label: option.name, value: option.name })); } - const records = await fetchAllRecordsByPage(table); + const records = await fetchAllRecordsByPage(table, undefined); const values = new Set(); for (const r of records) { const raw = (r?.fields || {})[fieldId]; @@ -2554,12 +2618,9 @@ export default function App() { try { let token: any = undefined; for (let i = 0; i < 10000; i++) { - const res: any = await deliveryTable.getRecordsByPage({ - pageSize: 200, - pageToken: token, - filter: planFilter, - sort, - }); + const req: any = { pageSize: 200, filter: planFilter, sort }; + if (token) req.pageToken = token; + const res: any = await safeGetRecordsByPage(deliveryTable, req); const recs: any[] = Array.isArray(res?.records) ? res.records : []; for (const r of recs) { @@ -2620,11 +2681,9 @@ export default function App() { try { let token: any = undefined; for (let i = 0; i < 10000; i++) { - const res: any = await deliveryTable.getRecordsByPage({ - pageSize: 200, - pageToken: token, - sort, - }); + const req: any = { pageSize: 200, sort }; + if (token) req.pageToken = token; + const res: any = await safeGetRecordsByPage(deliveryTable, req); const recs: any[] = Array.isArray(res?.records) ? res.records : []; for (const r of recs) { @@ -2863,7 +2922,7 @@ export default function App() { // 1. 先获取匹配的流程节点(复用预览功能的逻辑) const processTable = await bitable.base.getTable(PROCESS_CONFIG_TABLE_ID); - const processRecords = await fetchAllRecordsByPage(processTable); + const processRecords = await fetchAllRecordsByPage(processTable, undefined); const matchedProcessNodes: any[] = []; // 匹配流程配置节点 @@ -3049,7 +3108,7 @@ export default function App() { ); if (allGroups.length > 1 && groupOrderConfig.length === 0 && showUI) { - const initial = allGroups.map(g => createProcessGroupInstance(g)); + const initial = deriveGroupOrderDraftByProcessOrder(matchedProcessNodes); setGroupOrderDraft(initial); setGroupConfigVisible(true); setTimelineLoading(false); @@ -3117,7 +3176,7 @@ export default function App() { console.log('按顺序排列的流程节点:', orderedProcessNodes); // 2. 优化:预先获取所有时效数据并建立索引 - const timelineRecords = await fetchAllRecordsByPage(timelineTable); + const timelineRecords = await fetchAllRecordsByPage(timelineTable, undefined); // 优化2:预处理时效数据,建立节点名称到记录的映射 const timelineIndexByNode = new Map(); @@ -5334,7 +5393,7 @@ export default function App() { nameToId.set(nm, id); } } - const rows = await fetchAllRecordsByPage(batchTable); + const rows = await fetchAllRecordsByPage(batchTable, undefined); const rowsWithNo = rows.map((row: any, idx: number) => { const f = row?.fields || {}; @@ -6378,7 +6437,7 @@ export default function App() { const existing = Array.isArray(groupOrderConfig) ? groupOrderConfig.filter(inst => groupSet.has((inst?.groupName || '').trim())) : []; - const draft = existing.length > 0 ? existing : deriveGroupOrderDraftFromTimelineResults(base); + const draft = existing.length > 0 ? existing : deriveGroupOrderDraftByProcessOrder(base); setGroupOrderDraft(draft); pendingGroupConfigCalcRef.current = null; setGroupConfigVisible(true);