@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.
- package/dist/lib/adapters/pdf-page-renderer.d.ts.map +1 -1
- package/dist/lib/adapters/pdf-page-renderer.js +33 -90
- package/dist/lib/adapters/pdf-page-renderer.js.map +1 -1
- package/dist/lib/constants.d.ts +2 -0
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +2 -0
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/import-jobs/import-command.builder.js +1 -1
- package/dist/lib/import-jobs/import-command.builder.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/preview-source.mjs +25 -0
- package/dist/lib/remote-components/trade-compliance-workbench/preview.js +341 -0
- package/dist/lib/remote-ui/app-source.d.ts.map +1 -1
- package/dist/lib/remote-ui/app-source.js +38 -31
- package/dist/lib/remote-ui/app-source.js.map +1 -1
- package/dist/lib/remote-ui/components/source-file-preview.d.ts +37 -0
- package/dist/lib/remote-ui/components/source-file-preview.d.ts.map +1 -0
- package/dist/lib/remote-ui/components/source-file-preview.js +115 -0
- package/dist/lib/remote-ui/components/source-file-preview.js.map +1 -0
- 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 +2 -0
- package/dist/lib/remote-ui/contract-import.js.map +1 -1
- package/dist/lib/remote-ui/contracts.d.ts +1 -0
- package/dist/lib/remote-ui/contracts.d.ts.map +1 -1
- package/dist/lib/remote-ui/customer-contract-contracts.d.ts +7 -0
- package/dist/lib/remote-ui/customer-contract-contracts.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/catalogs.d.ts +1 -1
- package/dist/lib/remote-ui/pages/catalogs.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/catalogs.js +2 -0
- 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 +2 -1
- package/dist/lib/remote-ui/pages/contracts.js.map +1 -1
- package/dist/lib/remote-ui/pages/procurement.d.ts +2 -1
- package/dist/lib/remote-ui/pages/procurement.d.ts.map +1 -1
- package/dist/lib/remote-ui/pages/procurement.js +32 -9
- package/dist/lib/remote-ui/pages/procurement.js.map +1 -1
- package/dist/lib/remote-ui/procurement-contracts.d.ts +10 -7
- package/dist/lib/remote-ui/procurement-contracts.d.ts.map +1 -1
- package/dist/lib/remote-ui/styles.css +21 -0
- package/dist/lib/workbench-view.provider.d.ts +1 -29
- package/dist/lib/workbench-view.provider.d.ts.map +1 -1
- package/dist/lib/workbench-view.provider.js +8 -27
- package/dist/lib/workbench-view.provider.js.map +1 -1
- package/dist/lib/workbench.middleware.d.ts.map +1 -1
- package/dist/lib/workbench.middleware.js +38 -22
- package/dist/lib/workbench.middleware.js.map +1 -1
- package/dist/lib/workbench.service.d.ts +12 -0
- package/dist/lib/workbench.service.d.ts.map +1 -1
- package/dist/lib/workbench.service.js +70 -17
- package/dist/lib/workbench.service.js.map +1 -1
- 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":"
|
|
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) ||
|
|
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.
|
|
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 === '
|
|
1737
|
-
return { ...review, sourcePreview: { kind: '
|
|
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 === '
|
|
1750
|
-
|
|
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)}`;
|