@chenchaolong/plugin-trade-compliance-workbench 1.0.118 → 1.0.120

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 (54) hide show
  1. package/dist/lib/adapters/pdf-page-renderer.d.ts.map +1 -1
  2. package/dist/lib/adapters/pdf-page-renderer.js +33 -90
  3. package/dist/lib/adapters/pdf-page-renderer.js.map +1 -1
  4. package/dist/lib/constants.d.ts +2 -0
  5. package/dist/lib/constants.d.ts.map +1 -1
  6. package/dist/lib/constants.js +2 -0
  7. package/dist/lib/constants.js.map +1 -1
  8. package/dist/lib/import-jobs/import-command.builder.js +1 -1
  9. package/dist/lib/import-jobs/import-command.builder.js.map +1 -1
  10. package/dist/lib/remote-components/trade-compliance-workbench/app.css +1 -1
  11. package/dist/lib/remote-components/trade-compliance-workbench/app.js +8 -8
  12. package/dist/lib/remote-components/trade-compliance-workbench/preview-source.mjs +25 -0
  13. package/dist/lib/remote-components/trade-compliance-workbench/preview.js +341 -0
  14. package/dist/lib/remote-ui/app-source.d.ts.map +1 -1
  15. package/dist/lib/remote-ui/app-source.js +38 -31
  16. package/dist/lib/remote-ui/app-source.js.map +1 -1
  17. package/dist/lib/remote-ui/components/source-file-preview.d.ts +37 -0
  18. package/dist/lib/remote-ui/components/source-file-preview.d.ts.map +1 -0
  19. package/dist/lib/remote-ui/components/source-file-preview.js +115 -0
  20. package/dist/lib/remote-ui/components/source-file-preview.js.map +1 -0
  21. package/dist/lib/remote-ui/contract-import.d.ts +1 -0
  22. package/dist/lib/remote-ui/contract-import.d.ts.map +1 -1
  23. package/dist/lib/remote-ui/contract-import.js +2 -0
  24. package/dist/lib/remote-ui/contract-import.js.map +1 -1
  25. package/dist/lib/remote-ui/contracts.d.ts +1 -0
  26. package/dist/lib/remote-ui/contracts.d.ts.map +1 -1
  27. package/dist/lib/remote-ui/customer-contract-contracts.d.ts +7 -0
  28. package/dist/lib/remote-ui/customer-contract-contracts.d.ts.map +1 -1
  29. package/dist/lib/remote-ui/pages/catalogs.d.ts +1 -1
  30. package/dist/lib/remote-ui/pages/catalogs.d.ts.map +1 -1
  31. package/dist/lib/remote-ui/pages/catalogs.js +2 -0
  32. package/dist/lib/remote-ui/pages/catalogs.js.map +1 -1
  33. package/dist/lib/remote-ui/pages/contracts.d.ts.map +1 -1
  34. package/dist/lib/remote-ui/pages/contracts.js +2 -1
  35. package/dist/lib/remote-ui/pages/contracts.js.map +1 -1
  36. package/dist/lib/remote-ui/pages/procurement.d.ts +2 -1
  37. package/dist/lib/remote-ui/pages/procurement.d.ts.map +1 -1
  38. package/dist/lib/remote-ui/pages/procurement.js +32 -9
  39. package/dist/lib/remote-ui/pages/procurement.js.map +1 -1
  40. package/dist/lib/remote-ui/procurement-contracts.d.ts +10 -7
  41. package/dist/lib/remote-ui/procurement-contracts.d.ts.map +1 -1
  42. package/dist/lib/remote-ui/styles.css +21 -0
  43. package/dist/lib/workbench-view.provider.d.ts +1 -29
  44. package/dist/lib/workbench-view.provider.d.ts.map +1 -1
  45. package/dist/lib/workbench-view.provider.js +8 -27
  46. package/dist/lib/workbench-view.provider.js.map +1 -1
  47. package/dist/lib/workbench.middleware.d.ts.map +1 -1
  48. package/dist/lib/workbench.middleware.js +38 -22
  49. package/dist/lib/workbench.middleware.js.map +1 -1
  50. package/dist/lib/workbench.service.d.ts +12 -0
  51. package/dist/lib/workbench.service.d.ts.map +1 -1
  52. package/dist/lib/workbench.service.js +70 -17
  53. package/dist/lib/workbench.service.js.map +1 -1
  54. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"app-source.d.ts","sourceRoot":"","sources":["../../../src/lib/remote-ui/app-source.tsx"],"names":[],"mappings":"AA+BA,OAAO,cAAc,CAAA"}
1
+ {"version":3,"file":"app-source.d.ts","sourceRoot":"","sources":["../../../src/lib/remote-ui/app-source.tsx"],"names":[],"mappings":"AAgCA,OAAO,cAAc,CAAA"}
@@ -6,6 +6,7 @@ import { resolvePaginationPageSize } from './contracts.js';
6
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
+ import { configureSourceFilePreviewRuntime } from './components/source-file-preview.js';
9
10
  import { ConfirmDialog, LoadingBlocker, ToastStack } from './components/forms.js';
10
11
  import { TaskStatusMenu } from './components/task-status.js';
11
12
  import { addToast, createToastId, createToastTimerRegistry, removeToast } from './toast-queue.js';
@@ -44,6 +45,32 @@ const procurementPageMeta = {
44
45
  lines: { title: '采购商品列表', subtitle: '查看当前采购订单的商品明细及合规状态。' }
45
46
  };
46
47
  const bridge = createRemoteBridge();
48
+ let sourcePreviewRuntimePromise = null;
49
+ async function ensureSourcePreviewRuntime() {
50
+ const runtimeWindow = window;
51
+ if (runtimeWindow.TradeComplianceSourcePreview)
52
+ return runtimeWindow.TradeComplianceSourcePreview;
53
+ if (sourcePreviewRuntimePromise)
54
+ return sourcePreviewRuntimePromise;
55
+ sourcePreviewRuntimePromise = (async () => {
56
+ const result = asActionResult(unwrapResponse(await bridge.executeAction('load_source_preview_runtime', {})));
57
+ if (result.success === false)
58
+ throw new Error(resolveActionMessage(result) || '文件预览运行时加载失败');
59
+ const script = asRecord(result.data).script;
60
+ if (typeof script !== 'string' || !script.trim())
61
+ throw new Error('文件预览运行时响应不完整');
62
+ const element = document.createElement('script');
63
+ element.dataset.tradeCompliancePreviewRuntime = 'true';
64
+ element.textContent = script;
65
+ document.body.appendChild(element);
66
+ const runtime = runtimeWindow.TradeComplianceSourcePreview;
67
+ if (!runtime)
68
+ throw new Error('文件预览运行时初始化失败');
69
+ return runtime;
70
+ })().catch(error => { sourcePreviewRuntimePromise = null; throw error; });
71
+ return sourcePreviewRuntimePromise;
72
+ }
73
+ configureSourceFilePreviewRuntime(ensureSourcePreviewRuntime);
47
74
  const initialAnalyticsQuery = { filters: {}, page: 1, pageSize: 20 };
48
75
  let summaryRequestSequence = 0;
49
76
  const DOWNLOAD_URL_REVOKE_DELAY_MS = 30_000;
@@ -1504,7 +1531,7 @@ function sameWorkbenchRoute(left, right) {
1504
1531
  }
1505
1532
  function buildTaskStatusItems(tasks, onOpen, onSelect, onDelete) {
1506
1533
  return [...tasks]
1507
- .filter(task => ['QUEUED', 'EXTRACTING', 'AI_PARSING', 'VALIDATING', 'PERSISTING', 'SUCCEEDED', 'FAILED', 'TIMED_OUT'].includes(task.status) || isCatalogAwaitingReviewTask(task))
1534
+ .filter(task => ['QUEUED', 'EXTRACTING', 'AI_PARSING', 'VALIDATING', 'PERSISTING', 'SUCCEEDED', 'FAILED', 'TIMED_OUT'].includes(task.status) || isReviewableImportTask(task))
1508
1535
  .sort((left, right) => String(right.updatedAt ?? right.queuedAt ?? right.createdAt ?? '').localeCompare(String(left.updatedAt ?? left.queuedAt ?? left.createdAt ?? '')))
1509
1536
  .map(task => {
1510
1537
  const tone = taskTone(task.status);
@@ -1542,6 +1569,9 @@ function taskStatusLabel(status) {
1542
1569
  function isCatalogAwaitingReviewTask(task) {
1543
1570
  return task.status === 'AWAITING_REVIEW' && (task.documentType === 'CONTROLLED_CATALOG' || task.documentType === 'SANCTION_CATALOG');
1544
1571
  }
1572
+ function isReviewableImportTask(task) {
1573
+ return isCatalogAwaitingReviewTask(task) || (task.status === 'AWAITING_REVIEW' && (task.documentType === 'PURCHASE_CONTRACT' || task.documentType === 'CUSTOMER_CONTRACT'));
1574
+ }
1545
1575
  function catalogTaskTypeLabel(task) {
1546
1576
  const base = documentTypeLabel(task.documentType);
1547
1577
  if (task.documentType !== 'CONTROLLED_CATALOG')
@@ -1716,13 +1746,13 @@ function ContractUploadCommand({ label, busy, onFile, onError }) {
1716
1746
  void onFile(file).catch(error => onError?.(error instanceof Error ? error.message : '合同上传失败')); } })] });
1717
1747
  }
1718
1748
  async function attachPurchaseSource(draft, task, owner) {
1719
- if (draft.sourceFileUrl || !task.sourceFileId)
1749
+ if (draft.sourcePreview || !task.sourceFileId)
1720
1750
  return draft;
1721
1751
  const preview = await loadSourcePreview(task.sourceFileId, 'purchase', owner);
1752
+ if (preview.previewKind === 'BINARY')
1753
+ return { ...draft, sourcePreview: { kind: 'BINARY', url: preview.url, fileName: preview.fileName, mimeType: preview.mimeType }, sourceFileUrl: preview.url };
1722
1754
  if (preview.previewKind === 'URL')
1723
1755
  return { ...draft, sourceFileUrl: preview.url };
1724
- if (preview.previewKind === 'IMAGES')
1725
- return { ...draft, sourcePreview: { kind: 'IMAGES', pages: preview.pages, originalUrl: preview.originalUrl, pageCount: preview.pageCount }, sourceFileUrl: preview.originalUrl ?? draft.sourceFileUrl ?? null };
1726
1756
  if (preview.previewKind === 'TEXT')
1727
1757
  return { ...draft, sourceFileUrl: textPreviewUrl(task.sourceFileName ?? '采购合同源文件', preview.content) };
1728
1758
  return draft;
@@ -1733,8 +1763,8 @@ async function attachCustomerSource(review, owner) {
1733
1763
  const preview = await loadSourcePreview(review.sourceFileId, 'customer', owner);
1734
1764
  if (preview.previewKind === 'URL')
1735
1765
  return { ...review, sourcePreview: { kind: 'URL', url: preview.url } };
1736
- if (preview.previewKind === 'IMAGES')
1737
- return { ...review, sourcePreview: { kind: 'URL', url: preview.originalUrl ?? preview.pages[0]?.url ?? '' } };
1766
+ if (preview.previewKind === 'BINARY')
1767
+ return { ...review, sourcePreview: { kind: 'BINARY', url: preview.url, fileName: preview.fileName, mimeType: preview.mimeType } };
1738
1768
  if (preview.previewKind === 'TEXT')
1739
1769
  return { ...review, sourcePreview: { kind: 'TEXT', content: preview.content } };
1740
1770
  return { ...review, sourcePreview: { kind: 'UNAVAILABLE', message: preview.message } };
@@ -1746,26 +1776,8 @@ async function loadSourcePreview(sourceFileId, slot, owner) {
1746
1776
  const file = asRecord(result.data);
1747
1777
  if (file.previewKind === 'TEXT' && typeof file.content === 'string')
1748
1778
  return { previewKind: 'TEXT', content: file.content };
1749
- if (file.previewKind === 'IMAGES' && Array.isArray(file.pages)) {
1750
- clearPreviewPageSlots(owner, slot);
1751
- const pages = file.pages.map((page, index) => {
1752
- const record = asRecord(page);
1753
- const base64 = typeof record.base64 === 'string' ? record.base64 : '';
1754
- const mimeType = typeof record.mimeType === 'string' ? record.mimeType : 'image/png';
1755
- const pageNumber = Number(record.pageNumber);
1756
- if (!base64 || !Number.isFinite(pageNumber))
1757
- return null;
1758
- return { pageNumber, url: owner.replace(`${slot}:page:${index}`, blobUrlFromBase64(base64, mimeType)) };
1759
- }).filter((page) => Boolean(page));
1760
- const original = asRecord(file.original);
1761
- const originalUrl = typeof original.base64 === 'string' && typeof original.mimeType === 'string'
1762
- ? owner.replace(`${slot}:original`, blobUrlFromBase64(original.base64, original.mimeType))
1763
- : null;
1764
- if (pages.length)
1765
- return { previewKind: 'IMAGES', pages, originalUrl, pageCount: Number.isFinite(Number(file.pageCount)) ? Number(file.pageCount) : null };
1766
- }
1767
- if (file.previewKind === 'URL' && typeof file.base64 === 'string' && typeof file.mimeType === 'string') {
1768
- return { previewKind: 'URL', url: owner.replace(slot, blobUrlFromBase64(file.base64, file.mimeType)) };
1779
+ if (file.previewKind === 'BINARY' && typeof file.base64 === 'string' && typeof file.mimeType === 'string') {
1780
+ return { previewKind: 'BINARY', url: owner.replace(slot, blobUrlFromBase64(file.base64, file.mimeType)), fileName: typeof file.fileName === 'string' ? file.fileName : '源文件', mimeType: file.mimeType };
1769
1781
  }
1770
1782
  if (file.previewKind === 'UNAVAILABLE')
1771
1783
  return { previewKind: 'UNAVAILABLE', message: typeof file.message === 'string' ? file.message : '源文件暂无法在线预览' };
@@ -1776,11 +1788,6 @@ function blobUrlFromBase64(base64, mimeType) {
1776
1788
  const bytes = Uint8Array.from(binary, character => character.charCodeAt(0));
1777
1789
  return URL.createObjectURL(new Blob([bytes], { type: mimeType }));
1778
1790
  }
1779
- function clearPreviewPageSlots(owner, slot) {
1780
- for (let index = 0; index < 12; index += 1)
1781
- owner.clear(`${slot}:page:${index}`);
1782
- owner.clear(`${slot}:original`);
1783
- }
1784
1791
  function textPreviewUrl(title, content) {
1785
1792
  const html = `<!doctype html><html lang="zh-Hans"><head><meta charset="utf-8"><title>${escapeHtml(title)}</title><style>body{margin:0;padding:16px;font:14px/1.7 system-ui,sans-serif;color:#1f2937;background:#fff}pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}</style></head><body><pre>${escapeHtml(content)}</pre></body></html>`;
1786
1793
  return `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;