@chenchaolong/plugin-trade-compliance-workbench 1.0.25 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/lib/remote-components/trade-compliance-workbench/app.css +1 -1
  2. package/dist/lib/remote-components/trade-compliance-workbench/app.js +5 -5
  3. package/dist/lib/remote-ui/action-execution.d.ts +5 -2
  4. package/dist/lib/remote-ui/action-execution.d.ts.map +1 -1
  5. package/dist/lib/remote-ui/action-execution.js +2 -2
  6. package/dist/lib/remote-ui/action-execution.js.map +1 -1
  7. package/dist/lib/remote-ui/app-source.d.ts.map +1 -1
  8. package/dist/lib/remote-ui/app-source.js +122 -28
  9. package/dist/lib/remote-ui/app-source.js.map +1 -1
  10. package/dist/lib/remote-ui/bulk-delete.d.ts +56 -0
  11. package/dist/lib/remote-ui/bulk-delete.d.ts.map +1 -0
  12. package/dist/lib/remote-ui/bulk-delete.js +138 -0
  13. package/dist/lib/remote-ui/bulk-delete.js.map +1 -0
  14. package/dist/lib/remote-ui/components/bulk-delete.d.ts +21 -0
  15. package/dist/lib/remote-ui/components/bulk-delete.d.ts.map +1 -0
  16. package/dist/lib/remote-ui/components/bulk-delete.js +9 -0
  17. package/dist/lib/remote-ui/components/bulk-delete.js.map +1 -0
  18. package/dist/lib/remote-ui/components/data-grid.d.ts +12 -1
  19. package/dist/lib/remote-ui/components/data-grid.d.ts.map +1 -1
  20. package/dist/lib/remote-ui/components/data-grid.js +24 -5
  21. package/dist/lib/remote-ui/components/data-grid.js.map +1 -1
  22. package/dist/lib/remote-ui/components/task-status.d.ts +10 -1
  23. package/dist/lib/remote-ui/components/task-status.d.ts.map +1 -1
  24. package/dist/lib/remote-ui/components/task-status.js +79 -10
  25. package/dist/lib/remote-ui/components/task-status.js.map +1 -1
  26. package/dist/lib/remote-ui/customer-contract-contracts.d.ts +7 -2
  27. package/dist/lib/remote-ui/customer-contract-contracts.d.ts.map +1 -1
  28. package/dist/lib/remote-ui/customer-contract-contracts.js.map +1 -1
  29. package/dist/lib/remote-ui/model.d.ts +1 -0
  30. package/dist/lib/remote-ui/model.d.ts.map +1 -1
  31. package/dist/lib/remote-ui/model.js +3 -0
  32. package/dist/lib/remote-ui/model.js.map +1 -1
  33. package/dist/lib/remote-ui/pages/catalogs.d.ts +31 -3
  34. package/dist/lib/remote-ui/pages/catalogs.d.ts.map +1 -1
  35. package/dist/lib/remote-ui/pages/catalogs.js +119 -9
  36. package/dist/lib/remote-ui/pages/catalogs.js.map +1 -1
  37. package/dist/lib/remote-ui/pages/contracts.d.ts +61 -3
  38. package/dist/lib/remote-ui/pages/contracts.d.ts.map +1 -1
  39. package/dist/lib/remote-ui/pages/contracts.js +203 -9
  40. package/dist/lib/remote-ui/pages/contracts.js.map +1 -1
  41. package/dist/lib/remote-ui/pages/files.d.ts +52 -10
  42. package/dist/lib/remote-ui/pages/files.d.ts.map +1 -1
  43. package/dist/lib/remote-ui/pages/files.js +122 -12
  44. package/dist/lib/remote-ui/pages/files.js.map +1 -1
  45. package/dist/lib/remote-ui/pages/home.js +4 -4
  46. package/dist/lib/remote-ui/pages/home.js.map +1 -1
  47. package/dist/lib/remote-ui/pages/procurement.d.ts +87 -2
  48. package/dist/lib/remote-ui/pages/procurement.d.ts.map +1 -1
  49. package/dist/lib/remote-ui/pages/procurement.js +225 -21
  50. package/dist/lib/remote-ui/pages/procurement.js.map +1 -1
  51. package/dist/lib/remote-ui/pages/settings.d.ts +39 -6
  52. package/dist/lib/remote-ui/pages/settings.d.ts.map +1 -1
  53. package/dist/lib/remote-ui/pages/settings.js +94 -5
  54. package/dist/lib/remote-ui/pages/settings.js.map +1 -1
  55. package/dist/lib/remote-ui/procurement-contracts.d.ts +6 -2
  56. package/dist/lib/remote-ui/procurement-contracts.d.ts.map +1 -1
  57. package/dist/lib/remote-ui/procurement-contracts.js +11 -1
  58. package/dist/lib/remote-ui/procurement-contracts.js.map +1 -1
  59. package/dist/lib/remote-ui/styles.css +30 -11
  60. package/package.json +2 -1
@@ -13,14 +13,17 @@ type ActionNotificationPolicy = 'silent' | {
13
13
  tone: 'success';
14
14
  fallback: string;
15
15
  };
16
+ export type ActionExecutionOptions = {
17
+ suppressRefresh?: boolean;
18
+ };
16
19
  export declare const ACTION_NOTIFICATION_POLICIES: Record<WorkbenchActionKey, ActionNotificationPolicy>;
17
- export declare function executeWorkbenchAction<T>({ actionKey, mutate, refresh, notify, onResult, resolveMessage }: {
20
+ export declare function executeWorkbenchAction<T>({ actionKey, mutate, refresh, notify, onResult, resolveMessage, suppressRefresh }: {
18
21
  actionKey: WorkbenchActionKey;
19
22
  mutate: () => Promise<ActionResult<T>>;
20
23
  refresh: () => void | Promise<void>;
21
24
  notify?: Notify;
22
25
  onResult?: (result: ActionResult<T>) => void;
23
26
  resolveMessage?: (result: ActionResult<T>) => string;
24
- }): Promise<ActionResult<T>>;
27
+ } & ActionExecutionOptions): Promise<ActionResult<T>>;
25
28
  export {};
26
29
  //# sourceMappingURL=action-execution.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"action-execution.d.ts","sourceRoot":"","sources":["../../../src/lib/remote-ui/action-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AAC/F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAE9C,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI;IACtC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,CAAC,CAAA;IACR,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,wBAAwB,GAAG,QAAQ,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhF,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAsC7F,CAAA;AAiBD,wBAAsB,sBAAsB,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAqC,EAAE,EAAE;IACvI,SAAS,EAAE,kBAAkB,CAAA;IAC7B,MAAM,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IACtC,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC5C,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,CAAA;CACrD,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAiB3B"}
1
+ {"version":3,"file":"action-execution.d.ts","sourceRoot":"","sources":["../../../src/lib/remote-ui/action-execution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AAC/F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAE9C,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI;IACtC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,CAAC,CAAA;IACR,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,wBAAwB,GAAG,QAAQ,GAAG;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AAChF,MAAM,MAAM,sBAAsB,GAAG;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAElE,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAAC,kBAAkB,EAAE,wBAAwB,CAsC7F,CAAA;AAiBD,wBAAsB,sBAAsB,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAqC,EAAE,eAAe,EAAE,EAAE;IACxJ,SAAS,EAAE,kBAAkB,CAAA;IAC7B,MAAM,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IACtC,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,IAAI,CAAA;IAC5C,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,MAAM,CAAA;CACrD,GAAG,sBAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAiBpD"}
@@ -52,7 +52,7 @@ const refreshActions = new Set([
52
52
  'update_customer_contract_review',
53
53
  'delete_entity'
54
54
  ]);
55
- export async function executeWorkbenchAction({ actionKey, mutate, refresh, notify, onResult, resolveMessage = defaultActionMessage }) {
55
+ export async function executeWorkbenchAction({ actionKey, mutate, refresh, notify, onResult, resolveMessage = defaultActionMessage, suppressRefresh }) {
56
56
  try {
57
57
  if (!isWorkbenchActionKey(actionKey))
58
58
  throw new Error(`未配置操作通知策略:${String(actionKey)}`);
@@ -61,7 +61,7 @@ export async function executeWorkbenchAction({ actionKey, mutate, refresh, notif
61
61
  if (result.success === false)
62
62
  throw new Error(resolveMessage(result) || '操作失败');
63
63
  onResult?.(result);
64
- if (result.refresh && refreshActions.has(actionKey)) {
64
+ if (result.refresh && refreshActions.has(actionKey) && !suppressRefresh) {
65
65
  try {
66
66
  await refresh();
67
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"action-execution.js","sourceRoot":"","sources":["../../../src/lib/remote-ui/action-execution.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"action-execution.js","sourceRoot":"","sources":["../../../src/lib/remote-ui/action-execution.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"app-source.d.ts","sourceRoot":"","sources":["../../../src/lib/remote-ui/app-source.tsx"],"names":[],"mappings":"AA8BA,OAAO,cAAc,CAAA"}
1
+ {"version":3,"file":"app-source.d.ts","sourceRoot":"","sources":["../../../src/lib/remote-ui/app-source.tsx"],"names":[],"mappings":"AA+BA,OAAO,cAAc,CAAA"}
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import { createRoot } from 'react-dom/client';
4
4
  import { createRemoteBridge } from './bridge.js';
5
5
  import { resolvePaginationPageSize } from './contracts.js';
6
- import { clampPageAfterSingleDeletion, createBlobUrlOwner, createKeyedLatestRequestGate, createLatestCommittedRequest, createLatestRequestGate, generatedFileHistoryKey, normalizeWorkbenchData, routeDataRequest, runKeyedLatestRequest, unwrapResponse } from './model.js';
6
+ import { clampPageAfterSingleDeletion, createBlobUrlOwner, createKeyedLatestRequestGate, createLatestCommittedRequest, createLatestRequestGate, generatedFileHistoryKey, isCurrentSettingsRouteRevision, normalizeWorkbenchData, routeDataRequest, runKeyedLatestRequest, unwrapResponse } from './model.js';
7
7
  import { encodeViewFilters } from '../view-parameters.js';
8
8
  import { InfoNotice } from './components/data-grid.js';
9
9
  import { LoadingBlocker, ToastStack } from './components/forms.js';
@@ -13,8 +13,9 @@ import { buildBreadcrumbs, WorkbenchShell } from './components/layout.js';
13
13
  import { CatalogCommands, CatalogImportError, ControlledGoodsPage, findActiveCatalogImportTasks, findLatestFailedCatalogImportTask, runCatalogImportOrchestration, SanctionedCompaniesPage } from './pages/catalogs.js';
14
14
  import { HomePage } from './pages/home.js';
15
15
  import { ProcurementPage } from './pages/procurement.js';
16
+ import { procurementRouteForQuery } from './procurement-contracts.js';
16
17
  import { adaptPurchaseReview } from './purchase-review-adapter.js';
17
- import { CustomerContractsPage, adaptCustomerContractReview } from './pages/contracts.js';
18
+ import { CustomerContractsPage, adaptCustomerContractReview, createCustomerContractQueryCancelCoordinator, customerContractRouteEntryQuery, reconcileLatestCustomerContractQuery } from './pages/contracts.js';
18
19
  import { SalesPage } from './pages/sales.js';
19
20
  import { SalesFilesPage } from './pages/files.js';
20
21
  import { AnalyticsPage, AnalyticsPrototypeBoard } from './pages/analytics.js';
@@ -23,6 +24,7 @@ import { ContractImportError, findRecoverableContractImport, findResumableContra
23
24
  import { createTaskChatSynchronizer, importTaskFromStart, importTaskProgressPercent, isLocalUploadPlaceholder, mergeImportTaskItems, removeImportTaskItem } from './import-task-status.js';
24
25
  import { compareTaskBusinessOrder, createPendingResultQueue, createPollingTaskTracker, isAbortError, isPollingObservationTimeout, submitAndRefreshTaskState } from './polling.js';
25
26
  import { ACTION_NOTIFICATION_POLICIES, executeWorkbenchAction } from './action-execution.js';
27
+ import { createDeferredBulkReconcileCoordinator, runBulkDelete } from './bulk-delete.js';
26
28
  import './styles.css';
27
29
  const pageMeta = {
28
30
  home: { title: '首页', subtitle: '查看系统风险操作提示与外贸合规业务流程。' },
@@ -60,6 +62,7 @@ let excelEditorRuntimePromise = null;
60
62
  function App() {
61
63
  const [route, setRoute] = React.useState({ type: 'page', page: 'home' });
62
64
  const routeRef = React.useRef(route);
65
+ const routeRevisionRef = React.useRef(0);
63
66
  const contextRef = React.useRef(null);
64
67
  const requestGateRef = React.useRef(createLatestRequestGate());
65
68
  const taskStateRequestGateRef = React.useRef(createLatestRequestGate());
@@ -68,7 +71,15 @@ function App() {
68
71
  const settingsRatesRequestGateRef = React.useRef(createLatestRequestGate());
69
72
  const generatedFilesRequestGateRef = React.useRef(createKeyedLatestRequestGate());
70
73
  const activeGeneratedFilesKeyRef = React.useRef(null);
74
+ const latestGeneratedFilesQueryRef = React.useRef({ page: 1, pageSize: 20, filters: {} });
75
+ const generatedFilesBulkViewActiveRef = React.useRef(false);
76
+ const generatedFilesBulkReconcileRef = React.useRef(createDeferredBulkReconcileCoordinator());
77
+ const latestCustomerContractQueryRef = React.useRef({ page: 1, pageSize: 20, filters: {} });
78
+ const customerContractQueryCancelCoordinatorRef = React.useRef(createCustomerContractQueryCancelCoordinator());
71
79
  const settingsRatesQueryRef = React.useRef({ page: 1, pageSize: 20 });
80
+ const latestSettingsRatesQueryRef = React.useRef({ page: 1, pageSize: 20 });
81
+ const settingsRatesBulkViewActiveRef = React.useRef(false);
82
+ const settingsRatesBulkReconcileRef = React.useRef(createDeferredBulkReconcileCoordinator());
72
83
  const analyticsRequestsRef = React.useRef(createLatestCommittedRequest(initialAnalyticsQuery));
73
84
  const [analyticsCommittedQuery, setAnalyticsCommittedQuery] = React.useState(initialAnalyticsQuery);
74
85
  const analyticsPrototypeListenerCleanupRef = React.useRef(null);
@@ -80,6 +91,11 @@ function App() {
80
91
  const deletedImportTaskIdsRef = React.useRef(new Set());
81
92
  const [busy, setBusy] = React.useState(false);
82
93
  const [actionBusy, setActionBusy] = React.useState(false);
94
+ const [customerContractBulkBusy, setCustomerContractBulkBusy] = React.useState(false);
95
+ const [salesFileBulkBusy, setSalesFileBulkBusy] = React.useState(false);
96
+ const [settingsRateBulkBusy, setSettingsRateBulkBusy] = React.useState(false);
97
+ const [salesFileBulkReconcileBusy, setSalesFileBulkReconcileBusy] = React.useState(false);
98
+ const [settingsRateBulkReconcileBusy, setSettingsRateBulkReconcileBusy] = React.useState(false);
83
99
  const [catalogCommand, setCatalogCommand] = React.useState(null);
84
100
  const [importCompletions, setImportCompletions] = React.useState({ CONTROLLED_CATALOG: null, SANCTION_CATALOG: null });
85
101
  const [importFailures, setImportFailures] = React.useState({ CONTROLLED_CATALOG: null, SANCTION_CATALOG: null });
@@ -208,7 +224,7 @@ function App() {
208
224
  const requestedPageSize = resolvePaginationPageSize(pageSize);
209
225
  const request = routeDataRequest(targetRoute, page, requestedPageSize, filters);
210
226
  if (!request)
211
- return;
227
+ return false;
212
228
  const collection = String(asRecord(request.parameters).collection);
213
229
  const requests = collection === 'analytics' ? analyticsRequestsRef.current : routeRequestGateRef.current;
214
230
  const analyticsCandidate = collection === 'analytics' ? analyticsQueryFromRoute(page, requestedPageSize, filters) : null;
@@ -217,16 +233,18 @@ function App() {
217
233
  try {
218
234
  const payload = asRecord(unwrapResponse(await bridge.requestData(request)));
219
235
  if (!requests.commit(requestId))
220
- return;
236
+ return false;
221
237
  if (routeRef.current !== targetRoute && JSON.stringify(routeRef.current) !== JSON.stringify(targetRoute))
222
- return;
238
+ return false;
223
239
  if (collection === 'analytics') {
224
240
  setAnalyticsCommittedQuery(analyticsRequestsRef.current.committed());
225
241
  setData(current => ({ ...current, analytics: normalizeWorkbenchData({ summary: { analytics: payload } }).analytics }));
226
242
  }
227
243
  else if (collection === 'settings') {
228
244
  const settings = normalizeWorkbenchData({ summary: { settings: payload } }).settings;
229
- settingsRatesQueryRef.current = { page: settings.rates.page, pageSize: settings.rates.pageSize };
245
+ const committedRatesQuery = { page: settings.rates.page, pageSize: settings.rates.pageSize };
246
+ settingsRatesQueryRef.current = committedRatesQuery;
247
+ latestSettingsRatesQueryRef.current = committedRatesQuery;
230
248
  setData(current => ({ ...current, settings }));
231
249
  }
232
250
  else
@@ -244,6 +262,7 @@ function App() {
244
262
  order: payload.order && typeof payload.order === 'object' ? payload.order : null,
245
263
  metrics: payload.metrics && typeof payload.metrics === 'object' ? payload.metrics : targetRoute.level === 'orders' ? null : current.metrics
246
264
  }));
265
+ return true;
247
266
  }
248
267
  catch (error) {
249
268
  if (requests.isLatest(requestId)) {
@@ -251,6 +270,7 @@ function App() {
251
270
  setAnalyticsCommittedQuery({ ...analyticsRequestsRef.current.committed() });
252
271
  setToast({ message: error instanceof Error ? `页面加载失败:${error.message}` : '页面加载失败', tone: 'error' });
253
272
  }
273
+ return false;
254
274
  }
255
275
  finally {
256
276
  requests.finish(requestId);
@@ -387,7 +407,7 @@ function App() {
387
407
  React.useEffect(() => {
388
408
  toastTimers.sync(toasts);
389
409
  }, [toastTimers, toasts]);
390
- const executeAction = React.useCallback(async (actionKey, input) => {
410
+ const executeAction = React.useCallback(async (actionKey, input, options = {}) => {
391
411
  const blocksPage = ACTION_NOTIFICATION_POLICIES[actionKey] !== 'silent';
392
412
  if (blocksPage)
393
413
  setActionBusy(true);
@@ -399,7 +419,8 @@ function App() {
399
419
  notify: setToast,
400
420
  resolveMessage: resolveActionMessage,
401
421
  onResult: result => { if (actionKey === 'download_import_issues' || actionKey === 'download_sales_file')
402
- downloadActionFile(result.data); }
422
+ downloadActionFile(result.data); },
423
+ ...options
403
424
  });
404
425
  }
405
426
  finally {
@@ -407,7 +428,7 @@ function App() {
407
428
  setActionBusy(false);
408
429
  }
409
430
  }, [load]);
410
- const executeSalesFileAction = React.useCallback((actionKey, input) => executeAction(actionKey, input), [executeAction]);
431
+ const executeSalesFileAction = React.useCallback((actionKey, input, options = {}) => executeAction(actionKey, input, options), [executeAction]);
411
432
  const schedulePendingReviewPresentation = React.useCallback(() => {
412
433
  if (reviewPresentationTimerRef.current != null)
413
434
  return;
@@ -659,7 +680,7 @@ function App() {
659
680
  throw error;
660
681
  }
661
682
  }, [loadTaskState, notifyTaskRecoveryRefreshError]);
662
- const deleteImportTask = React.useCallback(async (task) => {
683
+ const deleteImportTaskRecord = React.useCallback(async (task, options) => {
663
684
  const result = asActionResult(unwrapResponse(await bridge.executeAction('delete_import_task', { taskId: task.id })));
664
685
  if (result.success === false)
665
686
  throw actionResponseError(result, '任务删除失败');
@@ -676,8 +697,23 @@ function App() {
676
697
  clientMessageId: `trade-task:${task.id}:deleted`
677
698
  }).catch(() => undefined);
678
699
  }
679
- await loadTaskState();
700
+ if (options.refresh)
701
+ await loadTaskState();
680
702
  }, [loadTaskState, removeLocalImportTask]);
703
+ const deleteImportTask = React.useCallback(async (task) => {
704
+ await deleteImportTaskRecord(task, { refresh: true });
705
+ }, [deleteImportTaskRecord]);
706
+ const bulkDeleteImportTasks = React.useCallback(async (items) => {
707
+ const tasksById = new Map(data.importTasks.items.map(task => [task.id, task]));
708
+ const result = await runBulkDelete(items.map(item => item.id), async (id) => {
709
+ const task = tasksById.get(id);
710
+ if (!task)
711
+ throw new Error('任务已不存在');
712
+ await deleteImportTaskRecord(task, { refresh: false });
713
+ });
714
+ await loadTaskState();
715
+ return result.failed.map(failure => ({ id: failure.key, message: failure.message }));
716
+ }, [data.importTasks.items, deleteImportTaskRecord, loadTaskState]);
681
717
  const openImportTaskFromStatus = React.useCallback(async (task) => {
682
718
  if (task.status === 'FAILED' || task.status === 'TIMED_OUT') {
683
719
  if (task.documentType === 'PURCHASE_CONTRACT' || task.documentType === 'CUSTOMER_CONTRACT')
@@ -906,13 +942,13 @@ function App() {
906
942
  const maxPage = Math.max(1, Math.ceil(total / requestedPageSize));
907
943
  if (query.page > maxPage) {
908
944
  if (!gate.isLatest(requestId))
909
- return;
945
+ return false;
910
946
  committedPage = maxPage;
911
947
  payload = await requestCatalogPage(maxPage);
912
948
  total = numberValue(payload.total, 0);
913
949
  }
914
950
  if (!gate.isLatest(requestId))
915
- return;
951
+ return false;
916
952
  setData((current) => ({
917
953
  ...current,
918
954
  [collection]: {
@@ -923,10 +959,12 @@ function App() {
923
959
  pageSize: requestedPageSize
924
960
  }
925
961
  }));
962
+ return true;
926
963
  }
927
964
  catch (error) {
928
965
  if (gate.isLatest(requestId))
929
966
  setToast({ message: error instanceof Error ? `查询失败:${error.message}` : '查询失败', tone: 'error' });
967
+ return false;
930
968
  }
931
969
  finally {
932
970
  gate.finish(requestId);
@@ -934,44 +972,69 @@ function App() {
934
972
  }
935
973
  }, []);
936
974
  const queryMonthlyRates = React.useCallback(async (query) => {
975
+ latestSettingsRatesQueryRef.current = query;
937
976
  const requestedPageSize = resolvePaginationPageSize(query.pageSize);
938
977
  const gate = settingsRatesRequestGateRef.current;
978
+ const requestRouteRevision = routeRevisionRef.current;
939
979
  const requestId = gate.begin();
940
980
  setBusy(true);
941
981
  try {
942
982
  const payload = asRecord(unwrapResponse(await bridge.requestData({ page: query.page, pageSize: requestedPageSize, parameters: { collection: 'monthlyRates' } })));
943
983
  if (!gate.commit(requestId))
944
- return;
945
- settingsRatesQueryRef.current = { page: numberValue(payload.page, query.page), pageSize: requestedPageSize };
984
+ return false;
985
+ if (!isCurrentSettingsRouteRevision(requestRouteRevision, routeRevisionRef.current, routeRef.current))
986
+ return false;
987
+ const committedRatesQuery = { page: numberValue(payload.page, query.page), pageSize: requestedPageSize };
988
+ settingsRatesQueryRef.current = committedRatesQuery;
989
+ latestSettingsRatesQueryRef.current = committedRatesQuery;
946
990
  setData(current => ({ ...current, settings: normalizeWorkbenchData({ summary: { settings: { ...current.settings, rates: { ...payload, pageSize: requestedPageSize } } } }).settings }));
991
+ return true;
947
992
  }
948
993
  catch (error) {
949
994
  if (gate.isLatest(requestId))
950
995
  setToast({ message: error instanceof Error ? `月度汇率加载失败:${error.message}` : '月度汇率加载失败', tone: 'error' });
996
+ return false;
951
997
  }
952
998
  finally {
953
999
  gate.finish(requestId);
954
1000
  setBusy(gate.activeCount() + requestGateRef.current.activeCount() + routeRequestGateRef.current.activeCount() > 0);
955
1001
  }
956
1002
  }, []);
957
- const queryProcurement = React.useCallback(async (_collection, query) => {
958
- await loadRoute(routeRef.current, query.page, query.pageSize, query.filters);
959
- }, [loadImportTasksFallback, loadRoute]);
1003
+ const queryProcurement = React.useCallback(async (collection, query) => {
1004
+ const targetRoute = procurementRouteForQuery(collection, query);
1005
+ if (!targetRoute)
1006
+ return false;
1007
+ return await loadRoute(targetRoute, query.page, query.pageSize, query.filters);
1008
+ }, [loadRoute]);
960
1009
  const queryCustomerContracts = React.useCallback(async (query) => {
961
- await loadRoute(routeRef.current, query.page, query.pageSize, query.filters);
1010
+ latestCustomerContractQueryRef.current = query;
1011
+ return await loadRoute({ type: 'page', page: 'customer-contract-review' }, query.page, query.pageSize, query.filters);
962
1012
  }, [loadRoute]);
1013
+ const rememberCustomerContractQuery = React.useCallback((query) => {
1014
+ latestCustomerContractQueryRef.current = query;
1015
+ }, []);
1016
+ const registerCustomerContractQueryCancel = React.useCallback((cancel) => customerContractQueryCancelCoordinatorRef.current.register(cancel), []);
1017
+ const reconcileCustomerContractsAfterBulk = React.useCallback(() => {
1018
+ const isActive = routeRef.current.type === 'page' && routeRef.current.page === 'customer-contract-review';
1019
+ if (isActive)
1020
+ customerContractQueryCancelCoordinatorRef.current.cancelCurrent();
1021
+ return reconcileLatestCustomerContractQuery({
1022
+ isActive: () => isActive,
1023
+ latestQuery: () => latestCustomerContractQueryRef.current,
1024
+ query: queryCustomerContracts
1025
+ });
1026
+ }, [queryCustomerContracts]);
963
1027
  const querySales = React.useCallback(async (_collection, query) => {
964
1028
  await loadRoute(routeRef.current, query.page, query.pageSize, query.filters);
965
1029
  }, [loadRoute]);
966
1030
  const querySalesFiles = React.useCallback(async (collection, query) => {
967
1031
  const requestedPageSize = resolvePaginationPageSize(query.pageSize);
968
- if (collection === 'salesFileOrders') {
969
- await loadRoute({ type: 'page', page: 'sales-files' }, query.page, requestedPageSize, query.filters);
970
- return;
971
- }
1032
+ if (collection === 'salesFileOrders')
1033
+ return await loadRoute({ type: 'page', page: 'sales-files' }, query.page, requestedPageSize, query.filters);
1034
+ latestGeneratedFilesQueryRef.current = { ...query, pageSize: requestedPageSize };
972
1035
  const key = generatedFileHistoryKey(query.parameters);
973
1036
  activeGeneratedFilesKeyRef.current = key;
974
- await runKeyedLatestRequest({
1037
+ return await runKeyedLatestRequest({
975
1038
  gate: generatedFilesRequestGateRef.current,
976
1039
  key,
977
1040
  request: async () => asRecord(unwrapResponse(await bridge.requestData({ page: query.page, pageSize: requestedPageSize, parameters: { collection, ...query.parameters, filters: encodeViewFilters(query.filters) } }))),
@@ -982,6 +1045,30 @@ function App() {
982
1045
  onFinish: () => setBusy(generatedFilesRequestGateRef.current.activeCount() + requestGateRef.current.activeCount() + routeRequestGateRef.current.activeCount() + analyticsRequestsRef.current.activeCount() > 0)
983
1046
  });
984
1047
  }, [loadRoute]);
1048
+ const generatedFilesBulkReconcileOptions = React.useCallback(() => ({
1049
+ isActive: () => routeRef.current.type === 'page' && routeRef.current.page === 'sales-files' && generatedFilesBulkViewActiveRef.current,
1050
+ latestQuery: () => latestGeneratedFilesQueryRef.current,
1051
+ query: (query) => querySalesFiles('generatedFiles', query),
1052
+ onBusyChange: setSalesFileBulkReconcileBusy
1053
+ }), [querySalesFiles]);
1054
+ const settingsRatesBulkReconcileOptions = React.useCallback(() => ({
1055
+ isActive: () => routeRef.current.type === 'page' && routeRef.current.page === 'settings' && settingsRatesBulkViewActiveRef.current,
1056
+ latestQuery: () => latestSettingsRatesQueryRef.current,
1057
+ query: queryMonthlyRates,
1058
+ onBusyChange: setSettingsRateBulkReconcileBusy
1059
+ }), [queryMonthlyRates]);
1060
+ const setGeneratedFilesBulkViewActive = React.useCallback((active) => {
1061
+ generatedFilesBulkViewActiveRef.current = active;
1062
+ if (active)
1063
+ void generatedFilesBulkReconcileRef.current.activate(generatedFilesBulkReconcileOptions());
1064
+ }, [generatedFilesBulkReconcileOptions]);
1065
+ const setSettingsRatesBulkViewActive = React.useCallback((active) => {
1066
+ settingsRatesBulkViewActiveRef.current = active;
1067
+ if (active)
1068
+ void settingsRatesBulkReconcileRef.current.activate(settingsRatesBulkReconcileOptions());
1069
+ }, [settingsRatesBulkReconcileOptions]);
1070
+ const reconcileGeneratedFilesAfterBulk = React.useCallback(() => generatedFilesBulkReconcileRef.current.reconcile(generatedFilesBulkReconcileOptions()), [generatedFilesBulkReconcileOptions]);
1071
+ const reconcileSettingsRatesAfterBulk = React.useCallback(() => settingsRatesBulkReconcileRef.current.reconcile(settingsRatesBulkReconcileOptions()), [settingsRatesBulkReconcileOptions]);
985
1072
  const queryAnalytics = React.useCallback(async (query) => {
986
1073
  const requestedQuery = { ...query, pageSize: resolvePaginationPageSize(query.pageSize) };
987
1074
  const requests = analyticsRequestsRef.current;
@@ -1041,10 +1128,12 @@ function App() {
1041
1128
  throw new Error(resolveActionMessage(result) || '恢复系统默认失败');
1042
1129
  await loadRoute({ type: 'page', page: 'settings' }, settingsRatesQueryRef.current.page, settingsRatesQueryRef.current.pageSize);
1043
1130
  }, [loadRoute]);
1044
- const deleteSettingsRate = React.useCallback(async (request) => {
1131
+ const deleteSettingsRate = React.useCallback(async (request, options = {}) => {
1045
1132
  const result = asActionResult(unwrapResponse(await bridge.executeAction('delete_settings_rate', request)));
1046
1133
  if (result.success === false)
1047
1134
  throw new Error(resolveActionMessage(result) || '月度汇率删除失败');
1135
+ if (options.suppressRefresh)
1136
+ return;
1048
1137
  const { page, pageSize } = settingsRatesQueryRef.current;
1049
1138
  const clampedPage = clampPageAfterSingleDeletion(page, pageSize, data.settings.rates.total);
1050
1139
  await loadRoute({ type: 'page', page: 'settings' }, clampedPage, pageSize);
@@ -1080,6 +1169,11 @@ function App() {
1080
1169
  setActiveSalesFileOrder(order);
1081
1170
  }, []);
1082
1171
  const changeRoute = React.useCallback((nextRoute) => {
1172
+ routeRevisionRef.current += 1;
1173
+ settingsRatesRequestGateRef.current.invalidate();
1174
+ latestCustomerContractQueryRef.current = customerContractRouteEntryQuery(nextRoute) ?? latestCustomerContractQueryRef.current;
1175
+ if (nextRoute.type === 'page' && nextRoute.page === 'settings')
1176
+ latestSettingsRatesQueryRef.current = { page: 1, pageSize: 20 };
1083
1177
  routeRef.current = nextRoute;
1084
1178
  setRoute(nextRoute);
1085
1179
  void loadRoute(nextRoute);
@@ -1093,11 +1187,11 @@ function App() {
1093
1187
  ? _jsx(ContractUploadCommand, { label: "\u4E0A\u4F20\u91C7\u8D2D\u5408\u540C", busy: busy || actionBusy, onFile: file => executeFileAction('upload_purchase_contract', file, { documentType: 'PURCHASE_CONTRACT' }), onError: message => setToast({ message, tone: 'error' }) })
1094
1188
  : undefined
1095
1189
  : page === 'customer-contract-review'
1096
- ? _jsx(ContractUploadCommand, { label: "\u4E0A\u4F20\u5BA2\u6237\u5408\u540C", busy: busy || actionBusy, onFile: file => executeFileAction('upload_customer_contract', file, { documentType: 'CUSTOMER_CONTRACT' }), onError: message => setToast({ message, tone: 'error' }) })
1190
+ ? _jsx(ContractUploadCommand, { label: "\u4E0A\u4F20\u5BA2\u6237\u5408\u540C", busy: busy || actionBusy || customerContractBulkBusy, onFile: file => executeFileAction('upload_customer_contract', file, { documentType: 'CUSTOMER_CONTRACT' }), onError: message => setToast({ message, tone: 'error' }) })
1097
1191
  : undefined;
1098
1192
  if (analyticsPrototypeVisible)
1099
- return (_jsxs(_Fragment, { children: [_jsx(WorkbenchShell, { route: route, breadcrumbs: buildBreadcrumbs(route), title: meta.title, topbarActions: _jsx(TaskStatusMenu, { items: taskStatusItems, busy: busy || actionBusy, onActionError: notifyTaskStatusActionError }), onRouteChange: changeRoute, onRefresh: () => void load(), children: _jsx(AnalyticsPrototypeBoard, { onClose: () => setAnalyticsPrototypeVisible(false) }) }), _jsx(LoadingBlocker, { visible: busy || actionBusy, label: actionBusy ? '操作处理中' : '数据加载中' }), _jsx(ToastStack, { items: toasts, onClose: closeToast })] }));
1100
- return (_jsxs(_Fragment, { children: [_jsxs(WorkbenchShell, { route: route, breadcrumbs: buildBreadcrumbs(route), title: meta.title, subtitle: page === 'home' ? undefined : meta.subtitle, topbarActions: _jsx(TaskStatusMenu, { items: taskStatusItems, busy: busy || actionBusy, onActionError: notifyTaskStatusActionError }), commands: (page === 'controlled-goods' || page === 'sanctioned-companies') ? _jsx(CatalogCommands, { busy: busy || actionBusy, onUpload: () => setCatalogCommand('upload'), onCreate: () => setCatalogCommand('create') }) : contractCommands, busy: busy || actionBusy, onRouteChange: changeRoute, onRefresh: () => void load(), children: [page === 'home' && _jsx(HomePage, {}), page === 'controlled-goods' && _jsx(ControlledGoodsPage, { collection: data.controlledGoods, batches: data.controlledBatches.items, busy: busy || actionBusy, onAction: executeAction, onFileAction: executeCatalogFileAction, onRefresh: load, onQuery: (query) => queryCatalog('controlledGoods', query), onIssueQuery: queryImportIssues, importCompletion: importCompletions.CONTROLLED_CATALOG, importFailure: importFailures.CONTROLLED_CATALOG, onRetryImport: retryImport, command: catalogCommand, onCommandHandled: () => setCatalogCommand(null), onNotify: setToast }), page === 'sanctioned-companies' && _jsx(SanctionedCompaniesPage, { collection: data.sanctionedCompanies, batches: data.sanctionBatches.items, busy: busy || actionBusy, onAction: executeAction, onFileAction: executeCatalogFileAction, onRefresh: load, onQuery: (query) => queryCatalog('sanctionedCompanies', query), onIssueQuery: queryImportIssues, importCompletion: importCompletions.SANCTION_CATALOG, importFailure: importFailures.SANCTION_CATALOG, onRetryImport: retryImport, command: catalogCommand, onCommandHandled: () => setCatalogCommand(null), onNotify: setToast }), page === 'procurement' && route.type === 'procurement' && _jsx(ProcurementPage, { route: route, suppliers: data.suppliers, purchaseOrders: data.purchaseOrders, purchaseLines: data.purchaseLines, supplier: procurementContext.supplier, order: procurementContext.order, metrics: procurementContext.metrics, importTask: purchaseImportTask, reviewDraft: purchaseReviewDraft, busy: busy || actionBusy, onQuery: queryProcurement, onAction: executeAction, onFileAction: executeFileAction, onRouteChange: changeRoute, onRetryImport: retryContractImport, onReviewClose: closePurchaseReview, onNotify: setToast }), page === 'customer-contract-review' && _jsx(CustomerContractsPage, { collection: data.customerContracts, busy: busy || actionBusy, importReviewState: customerImportState, onQuery: queryCustomerContracts, onAction: executeAction, onFileAction: executeFileAction, onReanalyze: reanalyzeCustomerContract, onLoadReview: loadCustomerContractReview, onReviewClose: closeCustomerReview, reanalysisState: customerReanalysisState, onRetryImport: retryContractImport, onNotify: setToast }), page === 'sales' && route.type === 'sales' && _jsx(SalesPage, { route: route, customers: data.salesCustomers, orders: data.salesOrders, lines: data.salesLines, busy: busy || actionBusy, onQuery: querySales, onAction: executeAction, onRouteChange: changeRoute, onOpenFiles: openSalesFiles, onNotify: setToast }), page === 'sales-files' && _jsx(SalesFilesPage, { orders: data.salesFileOrders, history: data.generatedFiles, activeOrder: activeSalesFileOrder, visualPrototypeState: salesFilesPrototypeState, onPrototypeStateClose: () => setSalesFilesPrototypeState(undefined), banks: data.settings.banks, busy: busy || actionBusy, onQuery: querySalesFiles, onAction: executeSalesFileAction, onOpenSalesOrder: selectSalesFileOrder, onDownload: file => executeAction('download_sales_file', { id: file.id }).then(() => undefined), onEdit: async (file) => setEditingSalesFile(file), onNotify: setToast }), page === 'analytics' && _jsx(AnalyticsPage, { data: data.analytics, committedQuery: analyticsCommittedQuery, busy: busy || actionBusy, error: analyticsError, onQuery: queryAnalytics, onExportXlsx: exportAnalytics }), page === 'settings' && _jsx(SettingsPage, { data: data.settings, busy: busy || actionBusy, onSave: saveSettings, onRestoreDefault: restoreSettings, onDeleteRate: deleteSettingsRate, onRateQuery: queryMonthlyRates, onUploadLogo: uploadCompanyLogo, onDiscardLogo: discardCompanyLogo, onNotify: setToast }), !['home', 'controlled-goods', 'sanctioned-companies', 'procurement', 'customer-contract-review', 'sales', 'sales-files', 'analytics', 'settings'].includes(page) && _jsxs("section", { className: "tcw-page-placeholder", "data-page": page, children: [_jsx(InfoNotice, { children: "\u9875\u9762\u57FA\u7840\u7ED3\u6784\u5DF2\u5C31\u7EEA\uFF0C\u4E1A\u52A1\u5185\u5BB9\u5C06\u5728\u5BF9\u5E94\u9875\u9762\u6A21\u5757\u4E2D\u52A0\u8F7D\u3002" }), _jsx("div", { className: "tcw-placeholder-body", "aria-label": `${meta.title}页面内容` })] })] }), _jsx(LoadingBlocker, { visible: busy || actionBusy, label: actionBusy ? '操作处理中' : '数据加载中' }), _jsx(ToastStack, { items: toasts, onClose: closeToast }), editingSalesFile && _jsx(SalesFileEditor, { file: editingSalesFile, onNotify: setToast, onClose: () => setEditingSalesFile(null), onSaved: () => { setEditingSalesFile(null); if (activeSalesFileOrder)
1193
+ return (_jsxs(_Fragment, { children: [_jsx(WorkbenchShell, { route: route, breadcrumbs: buildBreadcrumbs(route), title: meta.title, topbarActions: _jsx(TaskStatusMenu, { items: taskStatusItems, busy: busy || actionBusy, onBulkDelete: bulkDeleteImportTasks, onActionError: notifyTaskStatusActionError }), onRouteChange: changeRoute, onRefresh: () => void load(), children: _jsx(AnalyticsPrototypeBoard, { onClose: () => setAnalyticsPrototypeVisible(false) }) }), _jsx(LoadingBlocker, { visible: busy || actionBusy || customerContractBulkBusy, label: actionBusy || customerContractBulkBusy ? '操作处理中' : '数据加载中' }), _jsx(ToastStack, { items: toasts, onClose: closeToast })] }));
1194
+ return (_jsxs(_Fragment, { children: [_jsxs(WorkbenchShell, { route: route, breadcrumbs: buildBreadcrumbs(route), title: meta.title, subtitle: page === 'home' ? undefined : meta.subtitle, topbarActions: _jsx(TaskStatusMenu, { items: taskStatusItems, busy: busy || actionBusy, onBulkDelete: bulkDeleteImportTasks, onActionError: notifyTaskStatusActionError }), commands: (page === 'controlled-goods' || page === 'sanctioned-companies') ? _jsx(CatalogCommands, { busy: busy || actionBusy, onUpload: () => setCatalogCommand('upload'), onCreate: () => setCatalogCommand('create') }) : contractCommands, busy: busy || actionBusy, onRouteChange: changeRoute, onRefresh: () => void load(), children: [page === 'home' && _jsx(HomePage, {}), page === 'controlled-goods' && _jsx(ControlledGoodsPage, { collection: data.controlledGoods, batches: data.controlledBatches.items, busy: busy || actionBusy, onAction: executeAction, onFileAction: executeCatalogFileAction, onRefresh: load, onQuery: (query) => queryCatalog('controlledGoods', query), onIssueQuery: queryImportIssues, importCompletion: importCompletions.CONTROLLED_CATALOG, importFailure: importFailures.CONTROLLED_CATALOG, onRetryImport: retryImport, command: catalogCommand, onCommandHandled: () => setCatalogCommand(null), onNotify: setToast }), page === 'sanctioned-companies' && _jsx(SanctionedCompaniesPage, { collection: data.sanctionedCompanies, batches: data.sanctionBatches.items, busy: busy || actionBusy, onAction: executeAction, onFileAction: executeCatalogFileAction, onRefresh: load, onQuery: (query) => queryCatalog('sanctionedCompanies', query), onIssueQuery: queryImportIssues, importCompletion: importCompletions.SANCTION_CATALOG, importFailure: importFailures.SANCTION_CATALOG, onRetryImport: retryImport, command: catalogCommand, onCommandHandled: () => setCatalogCommand(null), onNotify: setToast }), page === 'procurement' && route.type === 'procurement' && _jsx(ProcurementPage, { route: route, suppliers: data.suppliers, purchaseOrders: data.purchaseOrders, purchaseLines: data.purchaseLines, supplier: procurementContext.supplier, order: procurementContext.order, metrics: procurementContext.metrics, importTask: purchaseImportTask, reviewDraft: purchaseReviewDraft, busy: busy || actionBusy, onQuery: queryProcurement, onAction: executeAction, onFileAction: executeFileAction, onRouteChange: changeRoute, onRetryImport: retryContractImport, onReviewClose: closePurchaseReview, onNotify: setToast }), page === 'customer-contract-review' && _jsx(CustomerContractsPage, { collection: data.customerContracts, busy: busy || actionBusy || customerContractBulkBusy, importReviewState: customerImportState, onQuery: queryCustomerContracts, onAction: executeAction, onFileAction: executeFileAction, onReanalyze: reanalyzeCustomerContract, onLoadReview: loadCustomerContractReview, onReviewClose: closeCustomerReview, reanalysisState: customerReanalysisState, onRetryImport: retryContractImport, onQueryRequested: rememberCustomerContractQuery, onQueryCancelRegistration: registerCustomerContractQueryCancel, onBulkReconcile: reconcileCustomerContractsAfterBulk, onBulkBusyChange: setCustomerContractBulkBusy, onNotify: setToast }), page === 'sales' && route.type === 'sales' && _jsx(SalesPage, { route: route, customers: data.salesCustomers, orders: data.salesOrders, lines: data.salesLines, busy: busy || actionBusy, onQuery: querySales, onAction: executeAction, onRouteChange: changeRoute, onOpenFiles: openSalesFiles, onNotify: setToast }), page === 'sales-files' && _jsx(SalesFilesPage, { orders: data.salesFileOrders, history: data.generatedFiles, activeOrder: activeSalesFileOrder, visualPrototypeState: salesFilesPrototypeState, onPrototypeStateClose: () => setSalesFilesPrototypeState(undefined), banks: data.settings.banks, busy: busy || actionBusy, externalBulkBusy: salesFileBulkBusy || salesFileBulkReconcileBusy, onQuery: querySalesFiles, onBulkReconcile: reconcileGeneratedFilesAfterBulk, onBulkBusyChange: setSalesFileBulkBusy, onBulkViewActiveChange: setGeneratedFilesBulkViewActive, onAction: executeSalesFileAction, onOpenSalesOrder: selectSalesFileOrder, onDownload: file => executeAction('download_sales_file', { id: file.id }).then(() => undefined), onEdit: async (file) => setEditingSalesFile(file), onNotify: setToast }), page === 'analytics' && _jsx(AnalyticsPage, { data: data.analytics, committedQuery: analyticsCommittedQuery, busy: busy || actionBusy, error: analyticsError, onQuery: queryAnalytics, onExportXlsx: exportAnalytics }), page === 'settings' && _jsx(SettingsPage, { data: data.settings, busy: busy || actionBusy, externalBulkBusy: settingsRateBulkBusy || settingsRateBulkReconcileBusy, onSave: saveSettings, onRestoreDefault: restoreSettings, onDeleteRate: deleteSettingsRate, onRateQuery: queryMonthlyRates, onBulkReconcile: reconcileSettingsRatesAfterBulk, onBulkBusyChange: setSettingsRateBulkBusy, onBulkViewActiveChange: setSettingsRatesBulkViewActive, onUploadLogo: uploadCompanyLogo, onDiscardLogo: discardCompanyLogo, onNotify: setToast }), !['home', 'controlled-goods', 'sanctioned-companies', 'procurement', 'customer-contract-review', 'sales', 'sales-files', 'analytics', 'settings'].includes(page) && _jsxs("section", { className: "tcw-page-placeholder", "data-page": page, children: [_jsx(InfoNotice, { children: "\u9875\u9762\u57FA\u7840\u7ED3\u6784\u5DF2\u5C31\u7EEA\uFF0C\u4E1A\u52A1\u5185\u5BB9\u5C06\u5728\u5BF9\u5E94\u9875\u9762\u6A21\u5757\u4E2D\u52A0\u8F7D\u3002" }), _jsx("div", { className: "tcw-placeholder-body", "aria-label": `${meta.title}页面内容` })] })] }), _jsx(LoadingBlocker, { visible: busy || actionBusy || customerContractBulkBusy, label: actionBusy || customerContractBulkBusy ? '操作处理中' : '数据加载中' }), _jsx(ToastStack, { items: toasts, onClose: closeToast }), editingSalesFile && _jsx(SalesFileEditor, { file: editingSalesFile, onNotify: setToast, onClose: () => setEditingSalesFile(null), onSaved: () => { setEditingSalesFile(null); if (activeSalesFileOrder)
1101
1195
  void querySalesFiles('generatedFiles', { page: 1, pageSize: 20, filters: {}, parameters: { customerContractId: activeSalesFileOrder.customerContractId, purchaseOrderId: activeSalesFileOrder.purchaseOrderId } }); } })] }));
1102
1196
  }
1103
1197
  function routePage(route) {