From ede9a87b97883bf39253c93ceb37377bdc02ccd0 Mon Sep 17 00:00:00 2001 From: yml2213 Date: Sat, 12 Sep 2026 16:25:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(pdd):=20=E6=94=AF=E6=8C=81=E6=A0=B9?= =?UTF-8?q?=E6=8D=AE=E6=95=B0=E6=8D=AE=E5=BA=93=E5=B7=B2=E6=9C=89=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=E8=87=AA=E9=80=82=E5=BA=94=E7=BF=BB=E9=A1=B5=E6=8B=89?= =?UTF-8?q?=E5=8F=96=EF=BC=8C=E9=98=B2=E9=AB=98=E5=B3=B0=E6=BC=8F=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增数据库批量排查已有订单接口 findExistingPlatformOrderIds,利用 B-Tree 索引毫秒级判定当前页订单是否存在; 2. 优化 syncStoreOrders 支持自适应翻页拉取:当第 1 页全部为新订单时,自适应向后递增翻页拉取(支持 maxPages 默认 5 页,平滑限速 300ms); 3. 翻页终止自适应判定:当拉取到包含数据库已有旧订单的页面时立即 break 停止翻页,兼顾高性能与不漏单; 4. 扩展全局配置支持 maxPages(自适应最大翻页页数),支持后台管理员在 UI 设置与立即拉单参数联动; 5. 新增单元测试 pdd-sync-service.test.ts,验证全部新订单自适应翻页与命中已有订单提前终止行为。 --- apps/backend/src/repositories/order-repo.ts | 23 ++ .../src/routes/admin/platform-config/pdd.ts | 6 +- .../pdd/pdd-source-config-service.ts | 8 + .../platforms/pdd/pdd-sync-service.test.ts | 157 ++++++++++++ .../platforms/pdd/pdd-sync-service.ts | 238 +++++++++++++----- .../services/scheduler/pdd-order-sync-job.ts | 3 +- .../pages/admin/platform/PddPlatformPanel.tsx | 44 +++- .../src/services/admin/platform-config/pdd.ts | 2 +- .../src/types/admin/platform-config/pdd.ts | 2 + 9 files changed, 405 insertions(+), 78 deletions(-) create mode 100644 apps/backend/src/services/platforms/pdd/pdd-sync-service.test.ts diff --git a/apps/backend/src/repositories/order-repo.ts b/apps/backend/src/repositories/order-repo.ts index 1fb356f4..893df946 100644 --- a/apps/backend/src/repositories/order-repo.ts +++ b/apps/backend/src/repositories/order-repo.ts @@ -86,6 +86,29 @@ export async function findLatestOrderByAnyPlatformOrderId( return result.rows[0] || null } + +export async function findExistingPlatformOrderIds({ + provider = 'pdd', + platform = 'pdd', + platformOrderIds, +}: { + provider?: string + platform: string + platformOrderIds: string[] +}): Promise> { + if (!platformOrderIds || platformOrderIds.length === 0) { + return new Set() + } + const result = await query<{ platform_order_id: string }>( + ` + SELECT platform_order_id + FROM orders + WHERE provider = $1 AND platform = $2 AND platform_order_id = ANY($3::text[]) + `, + [provider, platform, platformOrderIds], + ) + return new Set(result.rows.map((r) => String(r.platform_order_id))) +} export async function createOrder(input: OrderCreateInput): Promise { return createOrderWithExecutor(query, input) } diff --git a/apps/backend/src/routes/admin/platform-config/pdd.ts b/apps/backend/src/routes/admin/platform-config/pdd.ts index 02f54923..ef45957e 100644 --- a/apps/backend/src/routes/admin/platform-config/pdd.ts +++ b/apps/backend/src/routes/admin/platform-config/pdd.ts @@ -180,11 +180,13 @@ router.post( const body = (req.body || {}) as { shopId?: string pageSize?: number + maxPages?: number orderType?: number } const shopId = String(body.shopId || '').trim() const config = getPddSourcesConfig() const pageSize = Math.min(100, Math.max(1, Number(body.pageSize || config.pageSize || 50))) + const maxPages = Math.min(20, Math.max(1, Number(body.maxPages || config.maxPages || 5))) const orderType = Number(body.orderType ?? config.orderType ?? 2) if (shopId) { @@ -195,10 +197,10 @@ router.post( errorCode: 'pdd_store_not_found', }) } - return syncStoreOrders(store, { pageSize, orderType }) + return syncStoreOrders(store, { pageSize, maxPages, orderType }) } - return syncAllPddStores({ pageSize, orderType }) + return syncAllPddStores({ pageSize, maxPages, orderType }) }, { successMessage: '拼多多同步已触发', diff --git a/apps/backend/src/services/platforms/pdd/pdd-source-config-service.ts b/apps/backend/src/services/platforms/pdd/pdd-source-config-service.ts index 77225744..f231081c 100644 --- a/apps/backend/src/services/platforms/pdd/pdd-source-config-service.ts +++ b/apps/backend/src/services/platforms/pdd/pdd-source-config-service.ts @@ -33,6 +33,7 @@ export interface PddSourcesConfig { pollIntervalSeconds: number orderType: number // 0: 全部, 1: 待发货, 2: 已发货 (默认 2) pageSize: number // 单次拉取数量 (默认 50) + maxPages?: number // 自适应翻页最大页数 (默认 5) stores: PddStoreConfigItem[] } @@ -227,11 +228,17 @@ export function normalizePddSourcesConfig(rawValue: unknown): PddSourcesConfig { ? Math.min(100, Math.max(10, rawPageSize)) : 50 + const rawMaxPages = Number(source.maxPages) + const maxPages = Number.isInteger(rawMaxPages) + ? Math.min(20, Math.max(1, rawMaxPages)) + : 5 + return { enabled: source.enabled !== false, pollIntervalSeconds, orderType, pageSize, + maxPages, stores, } } @@ -242,6 +249,7 @@ function createDefaultPddSourcesConfig(): PddSourcesConfig { pollIntervalSeconds: 20, orderType: 2, pageSize: 50, + maxPages: 5, stores: [], } } diff --git a/apps/backend/src/services/platforms/pdd/pdd-sync-service.test.ts b/apps/backend/src/services/platforms/pdd/pdd-sync-service.test.ts new file mode 100644 index 00000000..1c08e8c8 --- /dev/null +++ b/apps/backend/src/services/platforms/pdd/pdd-sync-service.test.ts @@ -0,0 +1,157 @@ +import test from 'node:test' +import assert from 'node:assert/strict' + +import { syncStoreOrders } from './pdd-sync-service.js' +import { PddClient } from './pdd-client.js' +import type { PddStoreConfigItem } from './pdd-source-config-service.js' + +const testStore: PddStoreConfigItem = { + shopId: 'test_store_1', + shopName: '测试拼多多店铺', + cookie: 'pdd_user_id=123; PASS_ID=abc;', + userAgent: 'Mozilla/5.0', + enabled: true, +} + +test('syncStoreOrders performs adaptive pagination when page 1 contains only new orders', async () => { + const pagesQueried: number[] = [] + + // Mock client queryRecentOrders + const originalQuery = PddClient.prototype.queryRecentOrders + PddClient.prototype.queryRecentOrders = async function (options) { + pagesQueried.push(options.pageNumber || 1) + if (options.pageNumber === 1) { + // Page 1: 50 new orders + return { + total: 100, + items: Array.from({ length: 50 }, (_, i) => ({ + order_sn: `sn_page1_${i + 1}`, + order_status: 2, + order_amount: 1000, + goods_id: 123, + goods_name: '测试商品', + })), + } + } else if (options.pageNumber === 2) { + // Page 2: 50 orders, contains existing order + return { + total: 100, + items: Array.from({ length: 50 }, (_, i) => ({ + order_sn: `sn_page2_${i + 1}`, + order_status: 2, + order_amount: 1000, + goods_id: 123, + goods_name: '测试商品', + })), + } + } + return { total: 100, items: [] } + } + + try { + const result = await syncStoreOrders(testStore, { + pageSize: 50, + maxPages: 5, + checkExistingOrderIds: async (orderSns: string[]) => { + // Page 1 has 0 existing in DB. Page 2 has sn_page2_50 in DB. + const existing = new Set() + if (orderSns.includes('sn_page2_50')) { + existing.add('sn_page2_50') + } + return existing + }, + upsertFn: async () => { + return { + ignored: false, + order: {} as any, + orderItems: [], + tasks: [], + } + }, + }) + + assert.equal(result.pagesFetched, 2, 'Should have fetched exactly 2 pages') + assert.deepEqual(pagesQueried, [1, 2], 'Should have queried page 1 then page 2') + assert.equal(result.fetchedCount, 100, 'Total fetched items should be 100') + assert.equal(result.upsertedCount, 100, 'Total upserted should be 100') + } finally { + PddClient.prototype.queryRecentOrders = originalQuery + } +}) + +test('syncStoreOrders stops on page 1 if page 1 already contains existing orders', async () => { + const pagesQueried: number[] = [] + + const originalQuery = PddClient.prototype.queryRecentOrders + PddClient.prototype.queryRecentOrders = async function (options) { + pagesQueried.push(options.pageNumber || 1) + return { + total: 100, + items: Array.from({ length: 50 }, (_, i) => ({ + order_sn: `sn_page1_${i + 1}`, + order_status: 2, + order_amount: 1000, + goods_id: 123, + goods_name: '测试商品', + })), + } + } + + try { + const result = await syncStoreOrders(testStore, { + pageSize: 50, + maxPages: 5, + checkExistingOrderIds: async () => { + // Page 1 has an existing order in DB! + return new Set(['sn_page1_10']) + }, + upsertFn: async () => { + return { + ignored: false, + order: {} as any, + orderItems: [], + tasks: [], + } + }, + }) + + assert.equal(result.pagesFetched, 1, 'Should stop at page 1') + assert.deepEqual(pagesQueried, [1], 'Should query page 1 only') + assert.equal(result.fetchedCount, 50) + } finally { + PddClient.prototype.queryRecentOrders = originalQuery + } +}) + +test('syncStoreOrders stops on page 1 if explicit pageNumber > 1 is specified', async () => { + const pagesQueried: number[] = [] + + const originalQuery = PddClient.prototype.queryRecentOrders + PddClient.prototype.queryRecentOrders = async function (options) { + pagesQueried.push(options.pageNumber || 1) + return { + total: 100, + items: Array.from({ length: 50 }, (_, i) => ({ + order_sn: `sn_page2_${i + 1}`, + order_status: 2, + order_amount: 1000, + goods_id: 123, + goods_name: '测试商品', + })), + } + } + + try { + const result = await syncStoreOrders(testStore, { + pageNumber: 2, + pageSize: 50, + checkExistingOrderIds: async () => new Set(), // even if all are new + upsertFn: async () => ({ ignored: false, order: {} as any, orderItems: [], tasks: [] }), + }) + + assert.equal(result.pagesFetched, 1, 'Should only fetch the explicit page') + assert.deepEqual(pagesQueried, [2], 'Should only query page 2') + } finally { + PddClient.prototype.queryRecentOrders = originalQuery + } +}) diff --git a/apps/backend/src/services/platforms/pdd/pdd-sync-service.ts b/apps/backend/src/services/platforms/pdd/pdd-sync-service.ts index e94040a6..b1a2de3b 100644 --- a/apps/backend/src/services/platforms/pdd/pdd-sync-service.ts +++ b/apps/backend/src/services/platforms/pdd/pdd-sync-service.ts @@ -5,11 +5,13 @@ * Core Workflow / 核心流程: * 1. Pull recent orders from PDD MMS API using anti-content engine. * 调用基于纯算 anti-content 的 MMS 客户端拉取近期待发货订单。 - * 2. Map PDD payload to platform SourceOrderEvent. + * 2. Adaptive pagination: If all orders on the first page are brand-new, auto-page to pull older orders until hitting existing records. + * 自适应翻页拉取:当第一页(及后续页)全为新订单时,自适应继续翻页拉取,直至命中数据库已有订单或达到上限。 + * 3. Map PDD payload to platform SourceOrderEvent. * 将原始报文转化为 order_site 统一标准进单事件。 - * 3. In-memory ingestion via upsertOrderFromSource(). + * 4. In-memory ingestion via upsertOrderFromSource(). * 内存直调平台核心 upsertOrderFromSource(),自动入库并触发打手大厅工单分发。 - * 4. Staggered multi-store scheduling & risk control. + * 5. Staggered multi-store scheduling & risk control. * 多店铺错峰拉取与优雅异常处理。 */ @@ -20,6 +22,7 @@ import { updatePddStoreCheckStatus, type PddStoreConfigItem, } from './pdd-source-config-service.js' +import { findExistingPlatformOrderIds } from '../../../repositories/order-repo.js' import { notifyPddCookieExpired } from '../../notification/domain-notifications.js' import { upsertOrderFromSource } from '../../order/order-service.js' import { logError, logInfo, logWarn } from '../../../utils/logger.js' @@ -27,9 +30,12 @@ import { logError, logInfo, logWarn } from '../../../utils/logger.js' export interface SyncStoreOrdersOptions { pageNumber?: number | undefined pageSize?: number | undefined + maxPages?: number | undefined orderType?: number | undefined // 2: 已发货 (默认), 1: 待发货, 0: 全部 startTime?: number | undefined endTime?: number | undefined + checkExistingOrderIds?: ((orderSns: string[]) => Promise>) | undefined + upsertFn?: typeof upsertOrderFromSource | undefined } export interface SyncStoreResult { @@ -40,6 +46,7 @@ export interface SyncStoreResult { upsertedCount: number ignoredCount: number failedCount: number + pagesFetched: number error?: string | undefined } @@ -51,8 +58,8 @@ export interface SyncAllStoresResult { } /** - * Synchronize orders for a single PDD store. - * 同步单个拼多多店铺的订单并触发进单流程。 + * Synchronize orders for a single PDD store with adaptive pagination. + * 同步单个拼多多店铺的订单并触发进单流程(支持自适应翻页拉取)。 */ export async function syncStoreOrders( store: PddStoreConfigItem, @@ -71,6 +78,7 @@ export async function syncStoreOrders( upsertedCount: 0, ignoredCount: 0, failedCount: 0, + pagesFetched: 0, error: 'cookie_missing', } } @@ -78,82 +86,182 @@ export async function syncStoreOrders( const client = new PddClient(store) const sourcesConfig = getPddSourcesConfig() const pageSize = Math.min(100, Math.max(1, Number(options.pageSize || sourcesConfig.pageSize || 50))) - const pageNumber = Math.max(1, Number(options.pageNumber || 1)) + const initialPage = Math.max(1, Number(options.pageNumber || 1)) const orderType = options.orderType ?? sourcesConfig.orderType ?? 2 // 2: 已发货 (Shipped, default) - try { - const queryOptions: QueryOrdersOptions = { - pageNumber, - pageSize, - orderType, - } - if (options.startTime !== undefined) { - queryOptions.startTime = options.startTime - } - if (options.endTime !== undefined) { - queryOptions.endTime = options.endTime - } + // Determine whether to allow adaptive multi-page pulling + // 若传入明确的指定页码且 > 1,则仅拉取该指定页;否则执行自适应翻页(默认上限 5 页,最大支持 20 页) + const isExplicitSinglePage = options.pageNumber !== undefined && options.pageNumber > 1 + const maxPages = isExplicitSinglePage + ? 1 + : Math.min(20, Math.max(1, Number(options.maxPages || sourcesConfig.maxPages || 5))) - const queryResult = await client.queryRecentOrders(queryOptions) + let currentPage = initialPage + let pagesFetched = 0 + let totalReported = 0 + let totalFetched = 0 + let totalUpserted = 0 + let totalIgnored = 0 + let totalFailed = 0 + + try { + while (pagesFetched < maxPages) { + const queryOptions: QueryOrdersOptions = { + pageNumber: currentPage, + pageSize, + orderType, + } + if (options.startTime !== undefined) { + queryOptions.startTime = options.startTime + } + if (options.endTime !== undefined) { + queryOptions.endTime = options.endTime + } + + const queryResult = await client.queryRecentOrders(queryOptions) + totalReported = queryResult.total + const items = queryResult.items || [] + pagesFetched++ + + if (items.length === 0) { + break + } + + totalFetched += items.length + + // 提取本页订单号并批量排查数据库已有状态 + const pageOrderSns = items + .map((item) => String(item.order_sn || '').trim()) + .filter(Boolean) + + const checkExisting = + options.checkExistingOrderIds || + ((sns: string[]) => + findExistingPlatformOrderIds({ + provider: 'pdd', + platform: 'pdd', + platformOrderIds: sns, + })) + const existingOrderSns = await checkExisting(pageOrderSns) + + const existingCountOnPage = existingOrderSns.size + const newCountOnPage = pageOrderSns.length - existingCountOnPage + + const doUpsert = options.upsertFn || upsertOrderFromSource + + // 执行当前页订单进单入库 + for (const rawItem of items) { + try { + const sourceEvent = mapPddOrderToSourceEvent(rawItem, { shopId, shopName }) + const result = await doUpsert(sourceEvent, { + sourceLabel: `pdd_${shopId}`, + }) + + if (result.ignored) { + totalIgnored++ + } else { + totalUpserted++ + } + } catch (upsertErr) { + totalFailed++ + logError('[pdd-sync]', `拼多多订单进单失败: ${rawItem.order_sn}`, { + shopId, + orderSn: rawItem.order_sn, + error: upsertErr instanceof Error ? upsertErr.message : String(upsertErr), + }) + } + } + + logInfo( + '[pdd-sync]', + `店铺 ${shopName} 第 ${currentPage} 页处理完成 (本页拉取: ${items.length}, 新单: ${newCountOnPage}, 库中已有: ${existingCountOnPage})`, + { + shopId, + currentPage, + pageItems: items.length, + newCountOnPage, + existingCountOnPage, + }, + ) + + // 自适应翻页终止条件判断: + // 1. 若外部指定单页拉取,立即终止 + if (isExplicitSinglePage) { + break + } + + // 2. 若当前页中已经出现了数据库中已存在的旧订单,说明拉单时间线已触及上次同步断点 + // (拼多多按时间倒序排列,后续页码必然全为更早的已存历史订单,无需继续翻页) + if (existingCountOnPage > 0) { + break + } + + // 3. 若本页订单数不足 pageSize,说明拼多多后台当前条件已无更多订单 + if (items.length < pageSize) { + break + } + + // 4. 若已拉取条数达到店铺总订单数上限,终止 + if (totalFetched >= totalReported) { + break + } + + // 5. 若已达最大翻页限制,终止并记录日志 + if (pagesFetched >= maxPages) { + logInfo('[pdd-sync]', `店铺 ${shopName} 达到自适应翻页上限 (${maxPages}页),停止继续翻页`, { + shopId, + pagesFetched, + totalFetched, + }) + break + } + + // 本页全为全新订单!说明有积压新单未拉完,自适应翻页拉取下一页 + logInfo( + '[pdd-sync]', + `店铺 ${shopName} 第 ${currentPage} 页全为新订单 (${newCountOnPage}条),自适应翻页拉取第 ${currentPage + 1} 页...`, + { shopId, nextPage: currentPage + 1 }, + ) + currentPage++ + + // 翻页平滑限速 300ms,避免触发拼多多频控 + await new Promise((resolve) => setTimeout(resolve, 300)) + } // Update persistent check status to valid / 更新持久化校验状态为有效 await updatePddStoreCheckStatus(shopId, { cookieValid: true, - cookieCheckMessage: `同步正常 (在售/历史: ${queryResult.total})`, + cookieCheckMessage: `同步正常 (在售/历史: ${totalReported})`, lastCheckedAt: new Date().toISOString(), - totalOrders: queryResult.total, + totalOrders: totalReported, }).catch(() => null) - const { total, items } = queryResult - let upsertedCount = 0 - let ignoredCount = 0 - let failedCount = 0 - - for (const rawItem of items) { - try { - const sourceEvent = mapPddOrderToSourceEvent(rawItem, { shopId, shopName }) - const result = await upsertOrderFromSource(sourceEvent, { - sourceLabel: `pdd_${shopId}`, - }) - - if (result.ignored) { - ignoredCount++ - } else { - upsertedCount++ - } - } catch (upsertErr) { - failedCount++ - logError('[pdd-sync]', `拼多多订单进单失败: ${rawItem.order_sn}`, { - shopId, - orderSn: rawItem.order_sn, - error: upsertErr instanceof Error ? upsertErr.message : String(upsertErr), - }) - } - } - - logInfo('[pdd-sync]', `店铺 ${shopName} 同步完成`, { + logInfo('[pdd-sync]', `店铺 ${shopName} 同步完成 (共拉取 ${pagesFetched} 页)`, { shopId, - total, - fetchedCount: items.length, - upsertedCount, - ignoredCount, - failedCount, + total: totalReported, + pagesFetched, + fetchedCount: totalFetched, + upsertedCount: totalUpserted, + ignoredCount: totalIgnored, + failedCount: totalFailed, }) return { shopId, shopName, - total, - fetchedCount: items.length, - upsertedCount, - ignoredCount, - failedCount, + total: totalReported, + fetchedCount: totalFetched, + upsertedCount: totalUpserted, + ignoredCount: totalIgnored, + failedCount: totalFailed, + pagesFetched, } } catch (err) { const errMsg = err instanceof Error ? err.message : String(err) logError('[pdd-sync]', `店铺 ${shopName} 拉取订单异常`, { shopId, error: errMsg, + pagesFetched, }) // If login expired or risk-controlled, mark cookie as invalid and notify admins @@ -177,14 +285,16 @@ export async function syncStoreOrders( message: errMsg, }) } + return { shopId, shopName, - total: 0, - fetchedCount: 0, - upsertedCount: 0, - ignoredCount: 0, - failedCount: 0, + total: totalReported, + fetchedCount: totalFetched, + upsertedCount: totalUpserted, + ignoredCount: totalIgnored, + failedCount: totalFailed, + pagesFetched, error: errMsg, } } diff --git a/apps/backend/src/services/scheduler/pdd-order-sync-job.ts b/apps/backend/src/services/scheduler/pdd-order-sync-job.ts index d5aa4cc3..e2905971 100644 --- a/apps/backend/src/services/scheduler/pdd-order-sync-job.ts +++ b/apps/backend/src/services/scheduler/pdd-order-sync-job.ts @@ -15,9 +15,10 @@ export async function runPddOrderSyncJob(job: JsonObject) { : {} const sourcesConfig = getPddSourcesConfig() const pageSize = Math.min(100, Math.max(1, Number(config.pageSize || sourcesConfig.pageSize || 50))) + const maxPages = Math.min(20, Math.max(1, Number(config.maxPages || sourcesConfig.maxPages || 5))) const orderType = Number(config.orderType ?? sourcesConfig.orderType ?? 2) - const syncResult = await syncAllPddStores({ pageSize, orderType }) + const syncResult = await syncAllPddStores({ pageSize, maxPages, orderType }) if (!syncResult.enabled) { return { diff --git a/apps/frontend/src/pages/admin/platform/PddPlatformPanel.tsx b/apps/frontend/src/pages/admin/platform/PddPlatformPanel.tsx index 1eca7fcf..217d070a 100644 --- a/apps/frontend/src/pages/admin/platform/PddPlatformPanel.tsx +++ b/apps/frontend/src/pages/admin/platform/PddPlatformPanel.tsx @@ -98,6 +98,7 @@ export function PddPlatformPanel() { pollIntervalSeconds: 20, orderType: 2, pageSize: 50, + maxPages: 5, stores: [], }) @@ -168,6 +169,7 @@ export function PddPlatformPanel() { try { const response = await triggerAdminPddSync({ pageSize: config.pageSize || 50, + maxPages: config.maxPages || 5, orderType: config.orderType ?? 2, }) const data = response?.data as AdminPddSyncAllResponse | undefined @@ -201,12 +203,14 @@ export function PddPlatformPanel() { const response = await triggerAdminPddSync({ shopId: store.shopId, pageSize: config.pageSize || 50, + maxPages: config.maxPages || 5, orderType: config.orderType ?? 2, }) const data = response?.data as AdminPddSyncResult | undefined if (data) { + const pagesText = data.pagesFetched && data.pagesFetched > 1 ? `(自适应拉取 ${data.pagesFetched} 页)` : "" showSuccess( - `店铺【${store.shopName}】同步完成:抓取 ${data.fetchedCount} 笔,入库/更新 ${data.upsertedCount} 笔`, + `店铺【${store.shopName}】同步完成${pagesText}:抓取 ${data.fetchedCount} 笔,入库/更新 ${data.upsertedCount} 笔`, ) } else { showSuccess(`店铺【${store.shopName}】同步已触发`) @@ -786,8 +790,8 @@ export function PddPlatformPanel() { } > - - + + 自动拉单调度状态 @@ -802,7 +806,7 @@ export function PddPlatformPanel() { - + 抓取订单状态