@chenchaolong/plugin-trade-compliance-workbench 1.0.51 → 1.0.53
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.
- package/README.md +2 -2
- package/dist/lib/analytics-export.d.ts.map +1 -1
- package/dist/lib/analytics-export.js +1 -3
- package/dist/lib/analytics-export.js.map +1 -1
- package/dist/lib/analytics-query.d.ts.map +1 -1
- package/dist/lib/analytics-query.js +13 -20
- package/dist/lib/analytics-query.js.map +1 -1
- package/dist/lib/catalog-import/confidence.d.ts +1 -0
- package/dist/lib/catalog-import/confidence.d.ts.map +1 -1
- package/dist/lib/catalog-import/confidence.js +12 -0
- package/dist/lib/catalog-import/confidence.js.map +1 -1
- package/dist/lib/catalog-import/docx.parser.d.ts.map +1 -1
- package/dist/lib/catalog-import/docx.parser.js +7 -6
- package/dist/lib/catalog-import/docx.parser.js.map +1 -1
- package/dist/lib/catalog-import/pdf-layout.parser.d.ts.map +1 -1
- package/dist/lib/catalog-import/pdf-layout.parser.js +8 -7
- package/dist/lib/catalog-import/pdf-layout.parser.js.map +1 -1
- package/dist/lib/catalog-import/spreadsheet.parser.d.ts.map +1 -1
- package/dist/lib/catalog-import/spreadsheet.parser.js +12 -13
- package/dist/lib/catalog-import/spreadsheet.parser.js.map +1 -1
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +1 -0
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/demo-data.definitions.js +1 -1
- package/dist/lib/demo-data.definitions.js.map +1 -1
- package/dist/lib/entities/catalog.entity.d.ts +7 -1
- package/dist/lib/entities/catalog.entity.d.ts.map +1 -1
- package/dist/lib/entities/catalog.entity.js +26 -2
- package/dist/lib/entities/catalog.entity.js.map +1 -1
- package/dist/lib/entities/customer.entity.js.map +1 -1
- package/dist/lib/entities/procurement.entity.js.map +1 -1
- package/dist/lib/import-jobs/import-command.builder.js +2 -2
- package/dist/lib/import-jobs/import-command.builder.js.map +1 -1
- package/dist/lib/import-jobs/import-job-callback.processor.d.ts.map +1 -1
- package/dist/lib/import-jobs/import-job-callback.processor.js +2 -0
- package/dist/lib/import-jobs/import-job-callback.processor.js.map +1 -1
- package/dist/lib/remote-components/trade-compliance-workbench/app.css +1 -1
- package/dist/lib/remote-components/trade-compliance-workbench/app.js +8 -8
- package/dist/lib/remote-components/trade-compliance-workbench/editor-source.mjs +17 -1
- package/dist/lib/remote-components/trade-compliance-workbench/editor.js +100 -100
- package/dist/lib/remote-ui/action-execution.d.ts +3 -0
- package/dist/lib/remote-ui/action-execution.d.ts.map +1 -1
- package/dist/lib/remote-ui/action-execution.js +21 -1
- package/dist/lib/remote-ui/action-execution.js.map +1 -1
- package/dist/lib/remote-ui/app-source.js +178 -153
- package/dist/lib/remote-ui/app-source.js.map +1 -1
- package/dist/lib/remote-ui/bridge.d.ts.map +1 -1
- package/dist/lib/remote-ui/components/forms.d.ts +5 -2
- package/dist/lib/remote-ui/components/forms.d.ts.map +1 -1
- package/dist/lib/remote-ui/components/forms.js +4 -4
- package/dist/lib/remote-ui/components/forms.js.map +1 -1
- package/dist/lib/remote-ui/components/layout.d.ts.map +1 -1
- package/dist/lib/remote-ui/components/layout.js +31 -4
- package/dist/lib/remote-ui/components/layout.js.map +1 -1
- package/dist/lib/remote-ui/components/task-status.js +2 -2
- package/dist/lib/remote-ui/components/task-status.js.map +1 -1
- package/dist/lib/remote-ui/contract-import.d.ts +1 -0
- package/dist/lib/remote-ui/contract-import.d.ts.map +1 -1
- package/dist/lib/remote-ui/contract-import.js +3 -1
- package/dist/lib/remote-ui/contract-import.js.map +1 -1
- package/dist/lib/remote-ui/contracts.d.ts +21 -0
- package/dist/lib/remote-ui/contracts.d.ts.map +1 -1
- package/dist/lib/remote-ui/import-task-status.d.ts +5 -2
- package/dist/lib/remote-ui/import-task-status.d.ts.map +1 -1
- package/dist/lib/remote-ui/import-task-status.js +13 -8
- package/dist/lib/remote-ui/import-task-status.js.map +1 -1
- package/dist/lib/remote-ui/pages/analytics-detail-list.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/analytics-detail-list.js.map +1 -1
- package/dist/lib/remote-ui/pages/catalog-import-history.d.ts +63 -0
- package/dist/lib/remote-ui/pages/catalog-import-history.d.ts.map +1 -0
- package/dist/lib/remote-ui/pages/catalog-import-history.js +158 -0
- package/dist/lib/remote-ui/pages/catalog-import-history.js.map +1 -0
- package/dist/lib/remote-ui/pages/catalogs.css +164 -0
- package/dist/lib/remote-ui/pages/catalogs.d.ts +12 -6
- package/dist/lib/remote-ui/pages/catalogs.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/catalogs.js +79 -23
- package/dist/lib/remote-ui/pages/catalogs.js.map +1 -1
- package/dist/lib/remote-ui/pages/contracts.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/contracts.js +0 -16
- package/dist/lib/remote-ui/pages/contracts.js.map +1 -1
- package/dist/lib/remote-ui/pages/files-prototype.css +2 -2
- package/dist/lib/remote-ui/pages/files.d.ts +1 -1
- package/dist/lib/remote-ui/pages/files.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/files.js +6 -6
- package/dist/lib/remote-ui/pages/files.js.map +1 -1
- package/dist/lib/remote-ui/pages/home.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/home.js +2 -2
- package/dist/lib/remote-ui/pages/home.js.map +1 -1
- package/dist/lib/remote-ui/pages/procurement.d.ts +6 -1
- package/dist/lib/remote-ui/pages/procurement.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/procurement.js +77 -16
- package/dist/lib/remote-ui/pages/procurement.js.map +1 -1
- package/dist/lib/remote-ui/pages/sales.d.ts +4 -1
- package/dist/lib/remote-ui/pages/sales.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/sales.js +9 -4
- package/dist/lib/remote-ui/pages/sales.js.map +1 -1
- package/dist/lib/remote-ui/procurement-contracts.d.ts +7 -1
- package/dist/lib/remote-ui/procurement-contracts.d.ts.map +1 -1
- package/dist/lib/remote-ui/procurement-contracts.js.map +1 -1
- package/dist/lib/remote-ui/sidebar-state.d.ts +1 -0
- package/dist/lib/remote-ui/sidebar-state.d.ts.map +1 -1
- package/dist/lib/remote-ui/sidebar-state.js +3 -0
- package/dist/lib/remote-ui/sidebar-state.js.map +1 -1
- package/dist/lib/remote-ui/styles.css +1 -1
- package/dist/lib/sales-file.service.d.ts.map +1 -1
- package/dist/lib/sales-file.service.js +33 -1
- package/dist/lib/sales-file.service.js.map +1 -1
- package/dist/lib/schema-maintenance.d.ts.map +1 -1
- package/dist/lib/schema-maintenance.js +125 -0
- package/dist/lib/schema-maintenance.js.map +1 -1
- package/dist/lib/types.d.ts +3 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +1 -0
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/workbench-action-contract.d.ts +1 -1
- package/dist/lib/workbench-action-contract.d.ts.map +1 -1
- package/dist/lib/workbench-action-contract.js +3 -1
- package/dist/lib/workbench-action-contract.js.map +1 -1
- package/dist/lib/workbench-view.provider.d.ts +19 -9
- package/dist/lib/workbench-view.provider.d.ts.map +1 -1
- package/dist/lib/workbench-view.provider.js +43 -7
- package/dist/lib/workbench-view.provider.js.map +1 -1
- package/dist/lib/workbench.middleware.js +8 -8
- package/dist/lib/workbench.middleware.js.map +1 -1
- package/dist/lib/workbench.service.d.ts +44 -3
- package/dist/lib/workbench.service.d.ts.map +1 -1
- package/dist/lib/workbench.service.js +788 -152
- package/dist/lib/workbench.service.js.map +1 -1
- package/package.json +2 -1
|
@@ -11,6 +11,8 @@ import { abortablePollingDelay, createPollingObservation, pollWithRetry } from '
|
|
|
11
11
|
import { runNotifiedOperation } from '../toast-queue.js';
|
|
12
12
|
import { BulkDeleteDialog } from '../components/bulk-delete.js';
|
|
13
13
|
import { pageAfterBulkDelete, runBulkDelete, toggleBulkKey, toggleBulkPage } from '../bulk-delete.js';
|
|
14
|
+
import { CatalogImportHistoryDialog, catalogBatchCollectionQuery, isCatalogBatchReadOnly, runStalledCatalogRecovery } from './catalog-import-history.js';
|
|
15
|
+
export { CatalogImportHistoryDialog, cancelCatalogRecoveryConfirmation, catalogBatchCollectionQuery, catalogBatchLifecycleLabel, catalogRecoveryControlState, confirmCatalogRecovery, isCatalogBatchReadOnly, isStalledCatalogImportTask, openCatalogRecoveryConfirmation, runStalledCatalogRecovery } from './catalog-import-history.js';
|
|
14
16
|
const PAGE_SIZE = 20;
|
|
15
17
|
const ACCEPTED_CATALOG_FILES = '.pdf,.doc,.docx,.xls,.xlsx,.png,.jpg,.jpeg,.webp';
|
|
16
18
|
const formatNotice = () => `支持 PDF、DOC、DOCX、XLS、XLSX、PNG、JPEG、WEBP,单文件最大 ${getConfiguredUploadPolicy().maxUploadMb} MB。`;
|
|
@@ -46,7 +48,7 @@ export const sanctionedCompanyFilterMappings = {
|
|
|
46
48
|
countryOrRegion: { type: 'fuzzy', accessor: 'countryOrRegion' },
|
|
47
49
|
effectiveDate: { type: 'range', accessor: 'effectiveDate' }
|
|
48
50
|
};
|
|
49
|
-
export function createCatalogActionApi({ onAction, onFileAction
|
|
51
|
+
export function createCatalogActionApi({ onAction, onFileAction }) {
|
|
50
52
|
const mutate = async (actionKey, input, options) => {
|
|
51
53
|
const response = options ? await onAction(actionKey, input, options) : await onAction(actionKey, input);
|
|
52
54
|
assertActionSucceeded(response);
|
|
@@ -62,8 +64,8 @@ export function createCatalogActionApi({ onAction, onFileAction, onRefresh }) {
|
|
|
62
64
|
uploadSanctionCatalog: (file, input) => mutateFile('upload_sanction_catalog', file, input),
|
|
63
65
|
saveControlledGoods: (input) => mutate('save_controlled_goods', { ...input, sourceType: 'MANUAL_ENTRY' }),
|
|
64
66
|
updateControlledGoods: (input) => mutate('update_controlled_goods', input),
|
|
65
|
-
saveSanctionedCompany: (input) => mutate('save_sanctioned_company', { ...input, sourceType: 'MANUAL_ENTRY' }),
|
|
66
|
-
updateSanctionedCompany: (input) => mutate('update_sanctioned_company', input),
|
|
67
|
+
saveSanctionedCompany: (input) => mutate('save_sanctioned_company', { ...sanitizeSanctionedCompanyInput(input), sourceType: 'MANUAL_ENTRY' }),
|
|
68
|
+
updateSanctionedCompany: (input) => mutate('update_sanctioned_company', sanitizeSanctionedCompanyInput(input)),
|
|
67
69
|
deleteEntity: (entityType, id, options) => mutate('delete_entity', { entityType, id }, options),
|
|
68
70
|
searchHsCode: (keywords, page = 1) => onAction('search_hs_code', { keywords, page }),
|
|
69
71
|
getHsCodeDetail: (input) => onAction('get_hs_code_detail', input),
|
|
@@ -75,6 +77,10 @@ export function createCatalogActionApi({ onAction, onFileAction, onRefresh }) {
|
|
|
75
77
|
retryImportTask: (taskId) => onAction('retry_import_task', { taskId })
|
|
76
78
|
};
|
|
77
79
|
}
|
|
80
|
+
function sanitizeSanctionedCompanyInput(input) {
|
|
81
|
+
const { sanctionListSource: _sanctionListSource, ...rest } = input;
|
|
82
|
+
return rest;
|
|
83
|
+
}
|
|
78
84
|
export function createCatalogSelectionQuery(query, clearSelection) {
|
|
79
85
|
return async (request) => {
|
|
80
86
|
clearSelection();
|
|
@@ -238,6 +244,33 @@ export function attachBatchFileNames(rows, batches) {
|
|
|
238
244
|
const fileNames = new Map(batches.map((batch) => [batch.id, batch.sourceFileName]));
|
|
239
245
|
return rows.map((row) => ({ ...row, sourceFileName: row.batchId && fileNames.has(row.batchId) ? fileNames.get(row.batchId) : row.sourceFileName }));
|
|
240
246
|
}
|
|
247
|
+
function useCatalogImportHistory(documentType, query) {
|
|
248
|
+
const [state, setState] = React.useState({ open: false, collection: { items: [], page: 1, pageSize: PAGE_SIZE }, loading: false, error: '' });
|
|
249
|
+
const load = React.useCallback(async (page = 1, pageSize = PAGE_SIZE) => {
|
|
250
|
+
setState(current => ({ ...current, open: true, loading: true, error: '' }));
|
|
251
|
+
if (!query) {
|
|
252
|
+
setState(current => ({ ...current, loading: false, error: '导入记录查询暂不可用' }));
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
const collection = await query({ documentType, page, pageSize });
|
|
257
|
+
setState({ open: true, collection, loading: false, error: '' });
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
catch (cause) {
|
|
261
|
+
setState(current => ({ ...current, loading: false, error: errorMessage(cause, '导入记录加载失败') }));
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
}, [documentType, query]);
|
|
265
|
+
const open = React.useCallback(() => { void load(); }, [load]);
|
|
266
|
+
const close = React.useCallback(() => setState(current => ({ ...current, open: false })), []);
|
|
267
|
+
return {
|
|
268
|
+
state,
|
|
269
|
+
open,
|
|
270
|
+
close,
|
|
271
|
+
load
|
|
272
|
+
};
|
|
273
|
+
}
|
|
241
274
|
export async function loadCatalogImportIssues(onIssueQuery, query) {
|
|
242
275
|
try {
|
|
243
276
|
return { collection: await onIssueQuery(query), error: '' };
|
|
@@ -267,6 +300,7 @@ export function createCatalogIssueRequestController(commit) {
|
|
|
267
300
|
}
|
|
268
301
|
export function ControlledGoodsPage(props) {
|
|
269
302
|
const [filters, setFilters] = React.useState({});
|
|
303
|
+
const [activeBatch, setActiveBatch] = React.useState(null);
|
|
270
304
|
const [selectedIds, setSelectedIds] = React.useState(new Set());
|
|
271
305
|
const [bulkOpen, setBulkOpen] = React.useState(false);
|
|
272
306
|
const [bulkBusy, setBulkBusy] = React.useState(false);
|
|
@@ -283,6 +317,17 @@ export function ControlledGoodsPage(props) {
|
|
|
283
317
|
const api = React.useMemo(() => createCatalogActionApi(props), [props.onAction, props.onFileAction, props.onRefresh]);
|
|
284
318
|
const rows = attachBatchFileNames(props.collection.items, props.batches);
|
|
285
319
|
const pagination = collectionPagination(props.collection);
|
|
320
|
+
const history = useCatalogImportHistory('CONTROLLED_CATALOG', props.onHistoryQuery);
|
|
321
|
+
const resolveStalledImport = async (task, decision, onCommitted) => {
|
|
322
|
+
if (!props.onResolveStalledImport || !props.onRefreshTasks)
|
|
323
|
+
return { committed: false, refreshed: false, outcome: null };
|
|
324
|
+
return await runStalledCatalogRecovery({
|
|
325
|
+
task, decision, resolve: props.onResolveStalledImport, onCommitted, refreshTask: props.onRefreshTasks,
|
|
326
|
+
refreshCatalog: () => query(pagination.page, filters, pagination.pageSize),
|
|
327
|
+
refreshHistory: () => history.load(Number(history.state.collection.page) || 1, collectionPagination(history.state.collection).pageSize),
|
|
328
|
+
notify: props.onNotify
|
|
329
|
+
});
|
|
330
|
+
};
|
|
286
331
|
React.useEffect(() => {
|
|
287
332
|
const reconciled = reconcileCatalogBulkState(selectedIds, bulkFailures, rows);
|
|
288
333
|
if (reconciled.selectedIds !== selectedIds)
|
|
@@ -295,11 +340,13 @@ export function ControlledGoodsPage(props) {
|
|
|
295
340
|
setUploadOpen(true);
|
|
296
341
|
if (props.command === 'create')
|
|
297
342
|
setForm({ mode: 'create', item: null });
|
|
343
|
+
if (props.command === 'history')
|
|
344
|
+
history.open();
|
|
298
345
|
if (props.command)
|
|
299
346
|
props.onCommandHandled?.();
|
|
300
|
-
}, [props.command, props.onCommandHandled]);
|
|
347
|
+
}, [props.command, props.onCommandHandled, history.open]);
|
|
301
348
|
const selectionQuery = React.useMemo(() => createCatalogSelectionQuery(props.onQuery, () => setSelectedIds(new Set())), [props.onQuery]);
|
|
302
|
-
const query = React.useCallback((page, nextFilters, pageSize) => selectionQuery({ page, pageSize, filters: nextFilters }), [selectionQuery]);
|
|
349
|
+
const query = React.useCallback((page, nextFilters, pageSize) => selectionQuery({ page, pageSize, filters: nextFilters, ...(activeBatch ? { batchId: activeBatch.id } : {}) }), [selectionQuery, activeBatch]);
|
|
303
350
|
const completionRefreshRef = React.useRef();
|
|
304
351
|
if (!completionRefreshRef.current)
|
|
305
352
|
completionRefreshRef.current = createCatalogCompletionRefresh((page, nextFilters, pageSize) => void query(page, nextFilters, pageSize));
|
|
@@ -330,7 +377,7 @@ export function ControlledGoodsPage(props) {
|
|
|
330
377
|
{ type: 'ellipsis', key: 'sourceFileName', header: '来源文件', width: 190, maxWidth: 190 },
|
|
331
378
|
{ type: 'text', key: 'updatedAt', header: '更新时间', width: 170, truncate: false, format: formatBeijingDateTime }
|
|
332
379
|
];
|
|
333
|
-
return (_jsxs("section", { className: "tcw-catalog-page tcw-catalog-page--controlled", "aria-label": "\u7BA1\u63A7\u5546\u54C1\u76EE\u5F55", children: [_jsx(FilterPanel, { definitions: controlledGoodsFilters, values: filters, onChange: changeFilter, onQuery: () => scheduler.flush(filters, pagination.pageSize), onReset: () => { setFilters({});
|
|
380
|
+
return (_jsxs("section", { className: "tcw-catalog-page tcw-catalog-page--controlled", "aria-label": "\u7BA1\u63A7\u5546\u54C1\u76EE\u5F55", children: [_jsx(FilterPanel, { definitions: controlledGoodsFilters, values: filters, onChange: changeFilter, onQuery: () => scheduler.flush(filters, pagination.pageSize), onReset: () => { setActiveBatch(null); setFilters({}); void selectionQuery({ page: 1, pageSize: pagination.pageSize, filters: {} }); } }), _jsx(InfoNotice, { children: formatNotice() }), activeBatch && _jsxs("div", { className: "tcw-catalog-batch-filter", children: [_jsxs("span", { children: [_jsx("i", { className: "ri-history-line", "aria-hidden": "true" }), "\u6B63\u5728\u67E5\u770B\u5BFC\u5165\u6279\u6B21\uFF1A", _jsx("strong", { children: activeBatch.sourceFileName || activeBatch.id }), activeBatch.deletedAt && _jsx("em", { children: "\u5DF2\u66FF\u6362" })] }), _jsxs("button", { type: "button", className: "tcw-button tcw-button--secondary", onClick: () => { setActiveBatch(null); setFilters({}); void selectionQuery({ page: 1, pageSize: pagination.pageSize, filters: {} }); }, children: [_jsx("i", { className: "ri-close-line", "aria-hidden": "true" }), "\u9000\u51FA\u6279\u6B21\u67E5\u770B"] })] }), props.importFailure?.documentType === 'CONTROLLED_CATALOG' && _jsx(CatalogImportStatusNotice, { task: props.importFailure, busy: props.busy, onRetry: props.onRetryImport, onNotify: props.onNotify }), displayedSummary && _jsx(CatalogImportSummaryNotice, { documentType: "CONTROLLED_CATALOG", batch: displayedSummary, busy: props.busy, onDownload: (documentType, batchId) => api.downloadImportIssues(documentType, batchId), onView: (batchId, issueType) => queryIssues(batchId, issueType), onNotify: props.onNotify }), _jsx(DataGrid, { columns: columns, rows: rows, rowKey: "id", selection: activeBatch && isCatalogBatchReadOnly(activeBatch) ? undefined : {
|
|
334
381
|
selectedKeys: selectedIds,
|
|
335
382
|
onToggle: (id) => setSelectedIds(current => toggleBulkKey(current, id)),
|
|
336
383
|
onTogglePage: () => setSelectedIds(current => toggleBulkPage(current, rows.map(row => row.id))),
|
|
@@ -338,7 +385,7 @@ export function ControlledGoodsPage(props) {
|
|
|
338
385
|
onDelete: () => { setBulkFailures([]); setBulkOpen(true); },
|
|
339
386
|
labelFor: (row) => `选择管控商品:${row.productName || '未命名记录'}`,
|
|
340
387
|
disabled: props.busy || bulkBusy
|
|
341
|
-
}, actionWidth: 160, actions: (row) => _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "tcw-catalog-operation-button", disabled: props.busy || bulkBusy, onClick: () => setForm({ mode: 'review', item: row }), children: [_jsx("i", { className: "ri-edit-line", "aria-hidden": "true" }), "\u5BA1\u6838"] }), _jsxs("button", { type: "button", className: "tcw-catalog-operation-button is-danger", disabled: props.busy || bulkBusy, onClick: () => setDeleteItem(row), children: [_jsx("i", { className: "ri-delete-bin-line", "aria-hidden": "true" }), "\u5220\u9664"] })] }), pagination: pagination, onPageChange: (nextPage) => scheduler.page(nextPage, filters, pagination.pageSize), onPageSizeChange: (pageSize) => scheduler.pageSize(pageSize, filters), emptyText: "\u6682\u65E0\u7BA1\u63A7\u5546\u54C1\u6570\u636E" }), _jsx(CatalogUploadDialog, { open: uploadOpen, kind: "controlled", batches: props.batches, busy: props.busy, onClose: () => setUploadOpen(false), onNotify: props.onNotify, onUpload: async (file, input) => {
|
|
388
|
+
}, actionWidth: 160, actions: activeBatch && isCatalogBatchReadOnly(activeBatch) ? undefined : (row) => _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "tcw-catalog-operation-button", disabled: props.busy || bulkBusy, onClick: () => setForm({ mode: 'review', item: row }), children: [_jsx("i", { className: "ri-edit-line", "aria-hidden": "true" }), "\u5BA1\u6838"] }), _jsxs("button", { type: "button", className: "tcw-catalog-operation-button is-danger", disabled: props.busy || bulkBusy, onClick: () => setDeleteItem(row), children: [_jsx("i", { className: "ri-delete-bin-line", "aria-hidden": "true" }), "\u5220\u9664"] })] }), pagination: pagination, onPageChange: (nextPage) => scheduler.page(nextPage, filters, pagination.pageSize), onPageSizeChange: (pageSize) => scheduler.pageSize(pageSize, filters), emptyText: "\u6682\u65E0\u7BA1\u63A7\u5546\u54C1\u6570\u636E" }), _jsx(CatalogUploadDialog, { open: uploadOpen, kind: "controlled", batches: props.batches, busy: props.busy, onClose: () => setUploadOpen(false), onNotify: props.onNotify, onUpload: async (file, input) => {
|
|
342
389
|
const response = await api.uploadControlledCatalog(file, input);
|
|
343
390
|
const completion = asImportCompletion(response.data);
|
|
344
391
|
if (completion.batch)
|
|
@@ -383,10 +430,11 @@ export function ControlledGoodsPage(props) {
|
|
|
383
430
|
void queryIssues(issueState.batchId, issueType); }, onPageChange: (page) => { if (issueState)
|
|
384
431
|
void queryIssues(issueState.batchId, issueState.issueType, page, collectionPagination(issueState.collection).pageSize); }, onPageSizeChange: (pageSize) => { if (issueState)
|
|
385
432
|
void queryIssues(issueState.batchId, issueState.issueType, 1, pageSize); }, onRetry: () => { if (issueState)
|
|
386
|
-
void queryIssues(issueState.batchId, issueState.issueType, Number(issueState.collection.page) || 1, collectionPagination(issueState.collection).pageSize); } })] }));
|
|
433
|
+
void queryIssues(issueState.batchId, issueState.issueType, Number(issueState.collection.page) || 1, collectionPagination(issueState.collection).pageSize); } }), _jsx(CatalogImportHistoryDialog, { open: history.state.open, documentType: "CONTROLLED_CATALOG", collection: history.state.collection, tasks: props.tasks, loading: history.state.loading, error: history.state.error, busy: props.busy, onClose: history.close, onPageChange: (page) => void history.load(page, collectionPagination(history.state.collection).pageSize), onPageSizeChange: (pageSize) => void history.load(1, pageSize), onRetry: () => void history.load(Number(history.state.collection.page) || 1, collectionPagination(history.state.collection).pageSize), onViewIssues: (batch, issueType) => { history.close(); void queryIssues(batch.id, issueType); }, onDownloadIssues: (batch) => void api.downloadImportIssues('CONTROLLED_CATALOG', batch.id).catch(cause => props.onNotify?.({ message: errorMessage(cause, '异常明细下载失败'), tone: 'error' })), onViewRecords: (batch) => { history.close(); setActiveBatch(batch); setFilters({}); void selectionQuery(catalogBatchCollectionQuery(batch.id, pagination.pageSize)); }, onResolveStalledImport: props.onResolveStalledImport && props.onRefreshTasks ? resolveStalledImport : undefined })] }));
|
|
387
434
|
}
|
|
388
435
|
export function SanctionedCompaniesPage(props) {
|
|
389
436
|
const [filters, setFilters] = React.useState({});
|
|
437
|
+
const [activeBatch, setActiveBatch] = React.useState(null);
|
|
390
438
|
const [selectedIds, setSelectedIds] = React.useState(new Set());
|
|
391
439
|
const [bulkOpen, setBulkOpen] = React.useState(false);
|
|
392
440
|
const [bulkBusy, setBulkBusy] = React.useState(false);
|
|
@@ -402,6 +450,17 @@ export function SanctionedCompaniesPage(props) {
|
|
|
402
450
|
const api = React.useMemo(() => createCatalogActionApi(props), [props.onAction, props.onFileAction, props.onRefresh]);
|
|
403
451
|
const rows = attachBatchFileNames(props.collection.items, props.batches);
|
|
404
452
|
const pagination = collectionPagination(props.collection);
|
|
453
|
+
const history = useCatalogImportHistory('SANCTION_CATALOG', props.onHistoryQuery);
|
|
454
|
+
const resolveStalledImport = async (task, decision, onCommitted) => {
|
|
455
|
+
if (!props.onResolveStalledImport || !props.onRefreshTasks)
|
|
456
|
+
return { committed: false, refreshed: false, outcome: null };
|
|
457
|
+
return await runStalledCatalogRecovery({
|
|
458
|
+
task, decision, resolve: props.onResolveStalledImport, onCommitted, refreshTask: props.onRefreshTasks,
|
|
459
|
+
refreshCatalog: () => query(pagination.page, filters, pagination.pageSize),
|
|
460
|
+
refreshHistory: () => history.load(Number(history.state.collection.page) || 1, collectionPagination(history.state.collection).pageSize),
|
|
461
|
+
notify: props.onNotify
|
|
462
|
+
});
|
|
463
|
+
};
|
|
405
464
|
React.useEffect(() => {
|
|
406
465
|
const reconciled = reconcileCatalogBulkState(selectedIds, bulkFailures, rows);
|
|
407
466
|
if (reconciled.selectedIds !== selectedIds)
|
|
@@ -414,11 +473,13 @@ export function SanctionedCompaniesPage(props) {
|
|
|
414
473
|
setUploadOpen(true);
|
|
415
474
|
if (props.command === 'create')
|
|
416
475
|
setForm({ mode: 'create', item: null });
|
|
476
|
+
if (props.command === 'history')
|
|
477
|
+
history.open();
|
|
417
478
|
if (props.command)
|
|
418
479
|
props.onCommandHandled?.();
|
|
419
|
-
}, [props.command, props.onCommandHandled]);
|
|
480
|
+
}, [props.command, props.onCommandHandled, history.open]);
|
|
420
481
|
const selectionQuery = React.useMemo(() => createCatalogSelectionQuery(props.onQuery, () => setSelectedIds(new Set())), [props.onQuery]);
|
|
421
|
-
const query = React.useCallback((page, nextFilters, pageSize) => selectionQuery({ page, pageSize, filters: nextFilters }), [selectionQuery]);
|
|
482
|
+
const query = React.useCallback((page, nextFilters, pageSize) => selectionQuery({ page, pageSize, filters: nextFilters, ...(activeBatch ? { batchId: activeBatch.id } : {}) }), [selectionQuery, activeBatch]);
|
|
422
483
|
const completionRefreshRef = React.useRef();
|
|
423
484
|
if (!completionRefreshRef.current)
|
|
424
485
|
completionRefreshRef.current = createCatalogCompletionRefresh((page, nextFilters, pageSize) => void query(page, nextFilters, pageSize));
|
|
@@ -443,14 +504,13 @@ export function SanctionedCompaniesPage(props) {
|
|
|
443
504
|
const columns = [
|
|
444
505
|
{ type: 'custom', key: 'companyName', header: '公司名称', width: 210, title: (_, row) => row.companyName || undefined, render: (_, row) => _jsx(LinkButton, { iconClass: "ri-eye-line", title: row.companyName || '—', ariaLabel: `查看制裁公司详情:${row.companyName || '—'}`, onClick: () => setForm({ mode: 'detail', item: row }), children: row.companyName || '—' }) },
|
|
445
506
|
{ type: 'text', key: 'countryOrRegion', header: '国家或地区', width: 120 },
|
|
446
|
-
{ type: 'ellipsis', key: 'sanctionListSource', header: '制裁名单来源', width: 190, maxWidth: 190 },
|
|
447
507
|
{ type: 'text', key: 'effectiveDate', header: '生效日期', width: 120, truncate: false, format: formatBusinessDate },
|
|
448
508
|
{ type: 'ellipsis', key: 'sanctionReason', header: '制裁原因', width: 220, maxWidth: 220 },
|
|
449
509
|
{ type: 'text', key: 'sourceType', header: '来源类型', width: 110, truncate: false, format: (value) => labelFor(value, sourceTypeLabels) },
|
|
450
510
|
{ type: 'ellipsis', key: 'sourceFileName', header: '来源文件', width: 190, maxWidth: 190 },
|
|
451
511
|
{ type: 'text', key: 'updatedAt', header: '更新时间', width: 170, truncate: false, format: formatBeijingDateTime }
|
|
452
512
|
];
|
|
453
|
-
return (_jsxs("section", { className: "tcw-catalog-page tcw-catalog-page--sanction", "aria-label": "\u516C\u53F8\u5236\u88C1\u76EE\u5F55", children: [_jsx(FilterPanel, { definitions: sanctionedCompanyFilters, values: filters, onChange: changeFilter, onQuery: () => scheduler.flush(filters, pagination.pageSize), onReset: () => { setFilters({});
|
|
513
|
+
return (_jsxs("section", { className: "tcw-catalog-page tcw-catalog-page--sanction", "aria-label": "\u516C\u53F8\u5236\u88C1\u76EE\u5F55", children: [_jsx(FilterPanel, { definitions: sanctionedCompanyFilters, values: filters, onChange: changeFilter, onQuery: () => scheduler.flush(filters, pagination.pageSize), onReset: () => { setActiveBatch(null); setFilters({}); void selectionQuery({ page: 1, pageSize: pagination.pageSize, filters: {} }); } }), _jsx(InfoNotice, { children: formatNotice() }), activeBatch && _jsxs("div", { className: "tcw-catalog-batch-filter", children: [_jsxs("span", { children: [_jsx("i", { className: "ri-history-line", "aria-hidden": "true" }), "\u6B63\u5728\u67E5\u770B\u5BFC\u5165\u6279\u6B21\uFF1A", _jsx("strong", { children: activeBatch.sourceFileName || activeBatch.id }), activeBatch.deletedAt && _jsx("em", { children: "\u5DF2\u66FF\u6362" })] }), _jsxs("button", { type: "button", className: "tcw-button tcw-button--secondary", onClick: () => { setActiveBatch(null); setFilters({}); void selectionQuery({ page: 1, pageSize: pagination.pageSize, filters: {} }); }, children: [_jsx("i", { className: "ri-close-line", "aria-hidden": "true" }), "\u9000\u51FA\u6279\u6B21\u67E5\u770B"] })] }), props.importFailure?.documentType === 'SANCTION_CATALOG' && _jsx(CatalogImportStatusNotice, { task: props.importFailure, busy: props.busy, onRetry: props.onRetryImport, onNotify: props.onNotify }), displayedSummary && _jsx(CatalogImportSummaryNotice, { documentType: "SANCTION_CATALOG", batch: displayedSummary, busy: props.busy, onDownload: (documentType, batchId) => api.downloadImportIssues(documentType, batchId), onView: (batchId, issueType) => queryIssues(batchId, issueType), onNotify: props.onNotify }), _jsx(DataGrid, { columns: columns, rows: rows, rowKey: "id", selection: activeBatch && isCatalogBatchReadOnly(activeBatch) ? undefined : {
|
|
454
514
|
selectedKeys: selectedIds,
|
|
455
515
|
onToggle: (id) => setSelectedIds(current => toggleBulkKey(current, id)),
|
|
456
516
|
onTogglePage: () => setSelectedIds(current => toggleBulkPage(current, rows.map(row => row.id))),
|
|
@@ -458,7 +518,7 @@ export function SanctionedCompaniesPage(props) {
|
|
|
458
518
|
onDelete: () => { setBulkFailures([]); setBulkOpen(true); },
|
|
459
519
|
labelFor: (row) => `选择制裁公司:${row.companyName || '未命名记录'}`,
|
|
460
520
|
disabled: props.busy || bulkBusy
|
|
461
|
-
}, actionWidth: 160, actions: (row) => _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "tcw-catalog-operation-button", disabled: props.busy || bulkBusy, onClick: () => setForm({ mode: 'review', item: row }), children: [_jsx("i", { className: "ri-edit-line", "aria-hidden": "true" }), "\u5BA1\u6838"] }), _jsxs("button", { type: "button", className: "tcw-catalog-operation-button is-danger", disabled: props.busy || bulkBusy, onClick: () => setDeleteItem(row), children: [_jsx("i", { className: "ri-delete-bin-line", "aria-hidden": "true" }), "\u5220\u9664"] })] }), pagination: pagination, onPageChange: (nextPage) => scheduler.page(nextPage, filters, pagination.pageSize), onPageSizeChange: (pageSize) => scheduler.pageSize(pageSize, filters), emptyText: "\u6682\u65E0\u5236\u88C1\u516C\u53F8\u6570\u636E" }), _jsx(CatalogUploadDialog, { open: uploadOpen, kind: "sanction", batches: props.batches, busy: props.busy, onClose: () => setUploadOpen(false), onNotify: props.onNotify, onUpload: async (file, input) => {
|
|
521
|
+
}, actionWidth: 160, actions: activeBatch && isCatalogBatchReadOnly(activeBatch) ? undefined : (row) => _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "tcw-catalog-operation-button", disabled: props.busy || bulkBusy, onClick: () => setForm({ mode: 'review', item: row }), children: [_jsx("i", { className: "ri-edit-line", "aria-hidden": "true" }), "\u5BA1\u6838"] }), _jsxs("button", { type: "button", className: "tcw-catalog-operation-button is-danger", disabled: props.busy || bulkBusy, onClick: () => setDeleteItem(row), children: [_jsx("i", { className: "ri-delete-bin-line", "aria-hidden": "true" }), "\u5220\u9664"] })] }), pagination: pagination, onPageChange: (nextPage) => scheduler.page(nextPage, filters, pagination.pageSize), onPageSizeChange: (pageSize) => scheduler.pageSize(pageSize, filters), emptyText: "\u6682\u65E0\u5236\u88C1\u516C\u53F8\u6570\u636E" }), _jsx(CatalogUploadDialog, { open: uploadOpen, kind: "sanction", batches: props.batches, busy: props.busy, onClose: () => setUploadOpen(false), onNotify: props.onNotify, onUpload: async (file, input) => {
|
|
462
522
|
const response = await api.uploadSanctionCatalog(file, input);
|
|
463
523
|
const completion = asImportCompletion(response.data);
|
|
464
524
|
if (completion.batch)
|
|
@@ -489,10 +549,10 @@ export function SanctionedCompaniesPage(props) {
|
|
|
489
549
|
void queryIssues(issueState.batchId, issueType); }, onPageChange: (page) => { if (issueState)
|
|
490
550
|
void queryIssues(issueState.batchId, issueState.issueType, page, collectionPagination(issueState.collection).pageSize); }, onPageSizeChange: (pageSize) => { if (issueState)
|
|
491
551
|
void queryIssues(issueState.batchId, issueState.issueType, 1, pageSize); }, onRetry: () => { if (issueState)
|
|
492
|
-
void queryIssues(issueState.batchId, issueState.issueType, Number(issueState.collection.page) || 1, collectionPagination(issueState.collection).pageSize); } })] }));
|
|
552
|
+
void queryIssues(issueState.batchId, issueState.issueType, Number(issueState.collection.page) || 1, collectionPagination(issueState.collection).pageSize); } }), _jsx(CatalogImportHistoryDialog, { open: history.state.open, documentType: "SANCTION_CATALOG", collection: history.state.collection, tasks: props.tasks, loading: history.state.loading, error: history.state.error, busy: props.busy, onClose: history.close, onPageChange: (page) => void history.load(page, collectionPagination(history.state.collection).pageSize), onPageSizeChange: (pageSize) => void history.load(1, pageSize), onRetry: () => void history.load(Number(history.state.collection.page) || 1, collectionPagination(history.state.collection).pageSize), onViewIssues: (batch, issueType) => { history.close(); void queryIssues(batch.id, issueType); }, onDownloadIssues: (batch) => void api.downloadImportIssues('SANCTION_CATALOG', batch.id).catch(cause => props.onNotify?.({ message: errorMessage(cause, '异常明细下载失败'), tone: 'error' })), onViewRecords: (batch) => { history.close(); setActiveBatch(batch); setFilters({}); void selectionQuery(catalogBatchCollectionQuery(batch.id, pagination.pageSize)); }, onResolveStalledImport: props.onResolveStalledImport && props.onRefreshTasks ? resolveStalledImport : undefined })] }));
|
|
493
553
|
}
|
|
494
|
-
export function CatalogCommands({ busy, onUpload, onCreate }) {
|
|
495
|
-
return _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "tcw-button tcw-button--primary", disabled: busy, onClick: onUpload, children: [_jsx("i", { className: "ri-upload-cloud-2-line", "aria-hidden": "true" }), "\u4E0A\u4F20\u76EE\u5F55\u6587\u4EF6"] }), _jsxs("button", { type: "button", className: "tcw-button tcw-button--secondary", disabled: busy, onClick: onCreate, children: [_jsx("i", { className: "ri-add-line", "aria-hidden": "true" }), "\u624B\u5DE5\u65B0\u589E"] })] });
|
|
554
|
+
export function CatalogCommands({ busy, onUpload, onCreate, onHistory }) {
|
|
555
|
+
return _jsxs(_Fragment, { children: [_jsxs("button", { type: "button", className: "tcw-button tcw-button--primary", disabled: busy, onClick: onUpload, children: [_jsx("i", { className: "ri-upload-cloud-2-line", "aria-hidden": "true" }), "\u4E0A\u4F20\u76EE\u5F55\u6587\u4EF6"] }), _jsxs("button", { type: "button", className: "tcw-button tcw-button--secondary", disabled: busy, onClick: onCreate, children: [_jsx("i", { className: "ri-add-line", "aria-hidden": "true" }), "\u624B\u5DE5\u65B0\u589E"] }), _jsxs("button", { type: "button", className: "tcw-button tcw-button--secondary", disabled: busy, onClick: onHistory, children: [_jsx("i", { className: "ri-history-line", "aria-hidden": "true" }), "\u5BFC\u5165\u8BB0\u5F55"] })] });
|
|
496
556
|
}
|
|
497
557
|
export function CatalogUploadDialog({ open, kind, batches, busy = false, onClose, onUpload, onNotify }) {
|
|
498
558
|
const [state, dispatch] = React.useReducer(catalogUploadReducer, initialCatalogUploadState);
|
|
@@ -601,13 +661,13 @@ export function SanctionedCompanyDialog({ open, mode, item, busy = false, onClos
|
|
|
601
661
|
return (_jsx(Modal, { open: open, title: title, size: withEvidence ? 'wide' : 'normal', onClose: onClose, footer: footer, children: _jsx("div", { className: `tcw-catalog-dialog ${withEvidence ? 'tcw-catalog-dialog--review tcw-catalog-dialog--sanction-review' : 'tcw-catalog-dialog--sanction-create'}`, children: withEvidence ? _jsx(ReviewSplit, { editor: _jsxs(_Fragment, { children: [editor, error && _jsx("p", { role: "alert", children: error })] }), source: _jsx(SourceEvidence, { item: item }), editorTitle: "\u7F16\u8F91\u4FE1\u606F", sourceTitle: "\u6765\u6E90\u8BC1\u636E\uFF08\u53EA\u8BFB\uFF09" }) : _jsxs(_Fragment, { children: [mode === 'create' && _jsx(CatalogManualSource, {}), editor, error && _jsx("p", { role: "alert", children: error })] }) }) }));
|
|
602
662
|
}
|
|
603
663
|
export function validateSanctionedCompanyInput(input) {
|
|
604
|
-
if (!input.companyName.trim() || !input.
|
|
605
|
-
return '
|
|
664
|
+
if (!input.companyName.trim() || !input.effectiveDate?.trim() || !input.sanctionReason?.trim()) {
|
|
665
|
+
return '公司名称、发布/生效日期和制裁原因为必填项';
|
|
606
666
|
}
|
|
607
667
|
return '';
|
|
608
668
|
}
|
|
609
669
|
function SanctionedCompanyFields({ value, disabled, singleLineReason, onChange }) {
|
|
610
|
-
return _jsxs(FieldGrid, { columns: 1, children: [_jsx(FormField, { label: "\u516C\u53F8\u540D\u79F0", required: true, children: _jsx("input", { disabled: disabled, placeholder: "\u8BF7\u8F93\u5165\u516C\u53F8\u540D\u79F0", value: value.companyName, onChange: (event) => onChange({ ...value, companyName: event.target.value }) }) }), _jsx(FormField, { label: "\u56FD\u5BB6\u6216\u5730\u533A", children: _jsx("input", { disabled: disabled, placeholder: "\u8BF7\u8F93\u5165\u56FD\u5BB6\u6216\u5730\u533A", value: value.countryOrRegion ?? '', onChange: (event) => onChange({ ...value, countryOrRegion: event.target.value }) }) }), _jsx(FormField, { label: "\
|
|
670
|
+
return _jsxs(FieldGrid, { columns: 1, children: [_jsx(FormField, { label: "\u516C\u53F8\u540D\u79F0", required: true, children: _jsx("input", { disabled: disabled, placeholder: "\u8BF7\u8F93\u5165\u516C\u53F8\u540D\u79F0", value: value.companyName, onChange: (event) => onChange({ ...value, companyName: event.target.value }) }) }), _jsx(FormField, { label: "\u56FD\u5BB6\u6216\u5730\u533A", children: _jsx("input", { disabled: disabled, placeholder: "\u8BF7\u8F93\u5165\u56FD\u5BB6\u6216\u5730\u533A", value: value.countryOrRegion ?? '', onChange: (event) => onChange({ ...value, countryOrRegion: event.target.value }) }) }), _jsx(FormField, { label: "\u53D1\u5E03/\u751F\u6548\u65E5\u671F", required: true, children: _jsx("input", { type: "date", disabled: disabled, value: value.effectiveDate ?? '', onChange: (event) => onChange({ ...value, effectiveDate: event.target.value }) }) }), _jsx(FormField, { label: "\u5236\u88C1\u539F\u56E0", required: true, children: singleLineReason ? _jsx("input", { disabled: disabled, maxLength: 500, placeholder: "\u8BF7\u8F93\u5165\u5236\u88C1\u539F\u56E0", value: value.sanctionReason ?? '', onChange: (event) => onChange({ ...value, sanctionReason: event.target.value }) }) : _jsxs("div", { className: "tcw-counted-textarea", children: [_jsx("textarea", { disabled: disabled, rows: 4, maxLength: 500, placeholder: "\u8BF7\u8F93\u5165\u5236\u88C1\u539F\u56E0", value: value.sanctionReason ?? '', onChange: (event) => onChange({ ...value, sanctionReason: event.target.value }) }), _jsxs("small", { className: "tcw-character-count", children: [value.sanctionReason?.length ?? 0, "/500"] })] }) }), _jsx(FormField, { label: "\u5907\u6CE8", children: _jsxs("div", { className: "tcw-counted-textarea", children: [_jsx("textarea", { disabled: disabled, rows: 3, maxLength: 500, placeholder: "\u8BF7\u8F93\u5165\u5907\u6CE8\uFF08\u53EF\u9009\uFF09", value: value.remarks ?? '', onChange: (event) => onChange({ ...value, remarks: event.target.value }) }), _jsxs("small", { className: "tcw-character-count", children: [value.remarks?.length ?? 0, "/500"] })] }) })] });
|
|
611
671
|
}
|
|
612
672
|
function CatalogManualSource() {
|
|
613
673
|
return _jsxs("div", { className: "tcw-catalog-manual-source", "aria-label": "\u6765\u6E90\u7C7B\u578B\uFF1A\u624B\u5DE5\u65B0\u589E", children: [_jsx("span", { children: "\u6765\u6E90\u7C7B\u578B\uFF1A" }), _jsx("strong", { className: "tcw-catalog-source-badge", children: "\u624B\u5DE5\u65B0\u589E" })] });
|
|
@@ -770,7 +830,6 @@ function sanctionedForm(item) {
|
|
|
770
830
|
return {
|
|
771
831
|
companyName: item?.companyName ?? '',
|
|
772
832
|
countryOrRegion: item?.countryOrRegion ?? '',
|
|
773
|
-
sanctionListSource: item?.sanctionListSource ?? '',
|
|
774
833
|
effectiveDate: item?.effectiveDate ?? '',
|
|
775
834
|
sanctionReason: item?.sanctionReason ?? '',
|
|
776
835
|
remarks: item?.remarks ?? ''
|
|
@@ -819,7 +878,4 @@ function asImportCompletion(value) {
|
|
|
819
878
|
function isCatalogImportStartData(value) {
|
|
820
879
|
return isRecord(value) && isRecord(value.task) && typeof value.task.id === 'string' && typeof value.task.documentType === 'string' && typeof value.task.status === 'string';
|
|
821
880
|
}
|
|
822
|
-
function delay(milliseconds) {
|
|
823
|
-
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
824
|
-
}
|
|
825
881
|
//# sourceMappingURL=catalogs.js.map
|