@chenchaolong/plugin-trade-compliance-workbench 0.1.0 → 0.1.2

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.
@@ -1,49 +1,638 @@
1
- (function () {
2
- const root = document.getElementById('root')
1
+ ;(function () {
2
+ const CHANNEL = 'xpertai.remote_component'
3
+ const VERSION = 1
3
4
  const h = React.createElement
5
+ let instanceId = null
6
+ let requestSequence = 0
7
+ const pending = new Map()
8
+
9
+ injectStyles()
10
+
11
+ function isObject(value) {
12
+ return value && typeof value === 'object' && !Array.isArray(value)
13
+ }
14
+
15
+ function post(type, body, transfer) {
16
+ if (!instanceId && type !== 'ready') return
17
+ parent.postMessage(Object.assign({ channel: CHANNEL, protocolVersion: VERSION, instanceId, type }, body || {}), '*', transfer || [])
18
+ }
19
+
20
+ function request(type, body, transfer) {
21
+ const requestId = String(++requestSequence)
22
+ return new Promise((resolve, reject) => {
23
+ pending.set(requestId, { resolve, reject })
24
+ post(type, Object.assign({ requestId }, body || {}), transfer)
25
+ setTimeout(() => {
26
+ if (!pending.has(requestId)) return
27
+ pending.delete(requestId)
28
+ reject(new Error('请求超时'))
29
+ }, 30000)
30
+ })
31
+ }
32
+
33
+ function reportResize() {
34
+ const height = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight, 720)
35
+ post('resize', { height })
36
+ }
37
+
38
+ async function toFilePayload(file) {
39
+ const buffer = await file.arrayBuffer()
40
+ return {
41
+ payload: {
42
+ name: file.name,
43
+ type: file.type,
44
+ size: file.size,
45
+ lastModified: file.lastModified,
46
+ buffer
47
+ },
48
+ transfer: [buffer]
49
+ }
50
+ }
51
+
52
+ function executeAction(actionKey, targetId, input, parameters) {
53
+ return request('executeAction', { actionKey, targetId, input, parameters })
54
+ }
55
+
56
+ async function executeFileAction(actionKey, file, input, parameters) {
57
+ const filePayload = await toFilePayload(file)
58
+ return request('executeFileAction', { actionKey, file: filePayload.payload, input, parameters }, filePayload.transfer)
59
+ }
60
+
61
+ function notify(level, message) {
62
+ post('notify', { level, message })
63
+ }
4
64
 
5
65
  function App() {
6
- const tabs = ['管控商品管理', '商品管理', '报关资料生成']
7
- return h('div', { style: styles.shell },
8
- h('header', { style: styles.header },
9
- h('div', null,
10
- h('h1', { style: styles.title }, 'Trade Compliance Workbench'),
11
- h('p', { style: styles.subtitle }, '外贸合规工作台:管控商品、供应商商品和报关资料生成')
66
+ const [context, setContext] = React.useState(null)
67
+ const [data, setData] = React.useState(normalizeData(null))
68
+ const [activePage, setActivePage] = React.useState('controlled-goods-page')
69
+ const [selectedReviewId, setSelectedReviewId] = React.useState(null)
70
+ const [busy, setBusy] = React.useState(false)
71
+ const [notice, setNotice] = React.useState('')
72
+ const [query, setQuery] = React.useState('')
73
+ const [form, setForm] = React.useState({ productName: '', hsCode: '', keywords: '', controlNote: '', enabled: true })
74
+
75
+ React.useEffect(() => {
76
+ window.__tradeComplianceSetContext = (nextContext) => {
77
+ setContext(nextContext)
78
+ setData(normalizeData(nextContext && nextContext.payload))
79
+ setTimeout(() => reload(nextContext), 0)
80
+ }
81
+ window.__tradeComplianceHostEvent = () => reload()
82
+ post('ready')
83
+ return () => {
84
+ window.__tradeComplianceSetContext = null
85
+ window.__tradeComplianceHostEvent = null
86
+ }
87
+ }, [])
88
+
89
+ React.useEffect(reportResize, [data, activePage, selectedReviewId, busy, notice])
90
+
91
+ const reviewItems = data.reviewItems
92
+ const pendingItems = reviewItems.filter((item) => (item.reviewStatus || 'pending') === 'pending')
93
+ const selectedReview = reviewItems.find((item) => item.id === selectedReviewId) || pendingItems[0] || reviewItems[0] || null
94
+ const filteredControlledGoods = filterItems(data.controlledGoods, query, ['productName', 'hsCode', 'controlNote'])
95
+ const filteredProducts = filterItems(data.products, query, ['supplierName', 'productName', 'model', 'enrichedHsCode', 'englishName'])
96
+ const filteredWorkbooks = filterItems(data.workbookGenerations, query, ['fileName', 'invoiceNo', 'contractNo', 'sourceFileName'])
97
+
98
+ async function reload(nextContext) {
99
+ const activeContext = nextContext || context
100
+ if (!activeContext) return
101
+ setBusy(true)
102
+ try {
103
+ const response = await request('requestData', { query: { page: 1, pageSize: 100, search: query, parameters: {} } })
104
+ setData(normalizeData(getResponsePayload(response)))
105
+ } catch (error) {
106
+ showNotice('刷新失败:' + getErrorMessage(error), 'error')
107
+ } finally {
108
+ setBusy(false)
109
+ }
110
+ }
111
+
112
+ async function handleFile(actionKey, file) {
113
+ if (!file || busy) return
114
+ setBusy(true)
115
+ try {
116
+ const response = await executeFileAction(actionKey, file, { name: file.name, fileName: file.name }, {})
117
+ assertActionSuccess(response)
118
+ showNotice('文件已提交,识别结果会进入待审核列表。', 'success')
119
+ await reload()
120
+ } catch (error) {
121
+ showNotice(getErrorMessage(error), 'error')
122
+ } finally {
123
+ setBusy(false)
124
+ }
125
+ }
126
+
127
+ async function saveControlledGoods(event) {
128
+ event.preventDefault()
129
+ if (!form.productName.trim() || busy) return
130
+ setBusy(true)
131
+ try {
132
+ const response = await executeAction('save_controlled_goods', null, {
133
+ productName: form.productName.trim(),
134
+ hsCode: form.hsCode.trim() || undefined,
135
+ keywords: form.keywords.split(/[,\s,、]+/).map((item) => item.trim()).filter(Boolean),
136
+ controlNote: form.controlNote.trim() || undefined,
137
+ enabled: form.enabled
138
+ }, {})
139
+ assertActionSuccess(response)
140
+ setForm({ productName: '', hsCode: '', keywords: '', controlNote: '', enabled: true })
141
+ showNotice('管控商品已保存。', 'success')
142
+ await reload()
143
+ } catch (error) {
144
+ showNotice(getErrorMessage(error), 'error')
145
+ } finally {
146
+ setBusy(false)
147
+ }
148
+ }
149
+
150
+ async function confirmReview(item) {
151
+ if (!item || !item.id || busy) return
152
+ setBusy(true)
153
+ try {
154
+ const confirmedData = Object.assign({}, item.defaultData || {}, item.extractedData || {}, item.confirmedData || {})
155
+ const response = await executeAction('confirm_review_item', item.id, { itemId: item.id, confirmedData }, {})
156
+ assertActionSuccess(response)
157
+ showNotice('审核项已确认。', 'success')
158
+ await reload()
159
+ } catch (error) {
160
+ showNotice(getErrorMessage(error), 'error')
161
+ } finally {
162
+ setBusy(false)
163
+ }
164
+ }
165
+
166
+ async function generateWorkbook() {
167
+ if (busy) return
168
+ const salesItem = reviewItems.find((item) => item.type === 'customs_workbook')
169
+ setBusy(true)
170
+ try {
171
+ const base = Object.assign({}, salesItem && salesItem.defaultData, salesItem && salesItem.extractedData, salesItem && salesItem.confirmedData)
172
+ const invoiceNo = base.invoiceNo || ('INV-' + new Date().toISOString().slice(0, 10).replace(/-/g, ''))
173
+ const response = await executeAction('generate_customs_workbook', null, {
174
+ invoiceNo,
175
+ contractNo: base.contractNo,
176
+ sourceFileName: base.sourceFileName,
177
+ fileName: invoiceNo + '-销售发票.xlsx',
178
+ workbookData: base
179
+ }, {})
180
+ assertActionSuccess(response)
181
+ showNotice('销售发票已生成并写入历史。', 'success')
182
+ await reload()
183
+ } catch (error) {
184
+ showNotice(getErrorMessage(error), 'error')
185
+ } finally {
186
+ setBusy(false)
187
+ }
188
+ }
189
+
190
+ function showNotice(message, level) {
191
+ setNotice((level === 'error' ? '错误:' : '') + message)
192
+ notify(level || 'info', message)
193
+ setTimeout(() => setNotice(''), 4000)
194
+ }
195
+
196
+ return h('div', { className: 'tcw-shell' },
197
+ h('header', { className: 'tcw-header' },
198
+ h('div', { className: 'tcw-title-block' },
199
+ h('span', { className: 'tcw-kicker' }, '外贸合规工作台'),
200
+ h('h1', null, 'Trade Compliance Workbench'),
201
+ h('p', null, '管控商品维护、供应商商品审核、销售发票生成')
202
+ ),
203
+ h('div', { className: 'tcw-header-actions' },
204
+ h('input', {
205
+ className: 'tcw-search',
206
+ value: query,
207
+ placeholder: '搜索商品、供应商、海关编码',
208
+ onChange: (event) => setQuery(event.target.value)
209
+ }),
210
+ h('button', { className: 'tcw-btn tcw-btn-soft', disabled: busy, onClick: () => reload() }, busy ? '处理中' : '刷新')
12
211
  )
13
212
  ),
14
- h('nav', { style: styles.tabs }, tabs.map((tab, index) =>
15
- h('button', { key: tab, style: index === 0 ? styles.activeTab : styles.tab }, tab)
16
- )),
17
- h('main', { style: styles.grid },
18
- h('section', { style: styles.panel },
19
- h('h2', { style: styles.panelTitle }, '待审核列表'),
20
- h('div', { style: styles.row }, '数字计算机 | 8471501010 | 明确命中 | 待确认'),
21
- h('div', { style: styles.row }, '服务器 | HPC-8208 | 疑似管控 | 待确认'),
22
- h('div', { style: styles.row }, 'INV-2026-001 | 报关资料 | 待生成')
213
+ notice ? h('div', { className: 'tcw-notice' }, notice) : null,
214
+ h('section', { className: 'tcw-metrics' },
215
+ metric('待审核', pendingItems.length),
216
+ metric('管控商品', data.controlledGoods.length),
217
+ metric('供应商商品', data.products.length),
218
+ metric('发票历史', data.workbookGenerations.length)
219
+ ),
220
+ h('nav', { className: 'tcw-tabs' }, [
221
+ tab('controlled-goods-page', '管控商品管理'),
222
+ tab('products-page', '商品管理'),
223
+ tab('workbooks-page', '生成销售发票')
224
+ ]),
225
+ h('main', { className: 'tcw-main' },
226
+ h('section', { className: 'tcw-content' },
227
+ activePage === 'controlled-goods-page' ? renderControlledGoodsPage() : null,
228
+ activePage === 'products-page' ? renderProductsPage() : null,
229
+ activePage === 'workbooks-page' ? renderWorkbooksPage() : null
230
+ ),
231
+ renderReviewDrawer(selectedReview)
232
+ )
233
+ )
234
+
235
+ function tab(key, label) {
236
+ return h('button', {
237
+ key,
238
+ className: key === activePage ? 'tcw-tab active' : 'tcw-tab',
239
+ onClick: () => setActivePage(key)
240
+ }, label)
241
+ }
242
+
243
+ function renderControlledGoodsPage() {
244
+ return h('div', { className: 'tcw-page controlled-goods-page' },
245
+ h('div', { className: 'tcw-page-head' },
246
+ h('div', null, h('h2', null, '管控商品管理'), h('p', null, '上传目录文件识别管控商品,也可以人工维护规则。')),
247
+ uploadButton('upload_controlled_goods_file', '上传管控商品文件', 'accept-pdf-doc-xls')
248
+ ),
249
+ h('form', { className: 'tcw-form', onSubmit: saveControlledGoods },
250
+ field('商品名称', h('input', { value: form.productName, onChange: updateForm('productName'), placeholder: '例如:高性能服务器' })),
251
+ field('海关编码', h('input', { value: form.hsCode, onChange: updateForm('hsCode'), placeholder: '例如:8471501010' })),
252
+ field('关键词', h('input', { value: form.keywords, onChange: updateForm('keywords'), placeholder: '逗号或空格分隔' })),
253
+ field('管控说明', h('input', { value: form.controlNote, onChange: updateForm('controlNote'), placeholder: '许可证、两用物项、禁限说明' })),
254
+ h('label', { className: 'tcw-check' }, h('input', { type: 'checkbox', checked: form.enabled, onChange: (event) => setForm(Object.assign({}, form, { enabled: event.target.checked })) }), '启用'),
255
+ h('button', { className: 'tcw-btn tcw-btn-primary', disabled: busy || !form.productName.trim(), type: 'submit' }, '保存')
23
256
  ),
24
- h('aside', { style: styles.panel },
25
- h('h2', { style: styles.panelTitle }, '详情抽屉'),
26
- h('p', null, '展示原始证据、识别值、默认值、人工确认值和管控命中依据。'),
27
- h('button', { style: styles.primary }, '确认当前记录')
257
+ table(['商品名称', '海关编码', '关键词', '状态', '管控说明'], filteredControlledGoods, (item) => [
258
+ value(item.productName),
259
+ value(item.hsCode),
260
+ Array.isArray(item.keywords) ? item.keywords.join('') : '-',
261
+ status(item.enabled === false ? '停用' : '启用', item.enabled === false ? 'muted' : 'ok'),
262
+ value(item.controlNote)
263
+ ], '暂无管控商品,先上传目录或手动新增。')
264
+ )
265
+ }
266
+
267
+ function renderProductsPage() {
268
+ const groups = groupBy(filteredProducts, (item) => value(item.supplierName, '未识别供应商'))
269
+ return h('div', { className: 'tcw-page products-page' },
270
+ h('div', { className: 'tcw-page-head' },
271
+ h('div', null, h('h2', null, '商品管理'), h('p', null, '上传供应商合同后,商品信息按供应商归类并进入审核。')),
272
+ uploadButton('upload_supplier_contract', '上传供应商合同', 'accept-doc-xls-pdf')
273
+ ),
274
+ Object.keys(groups).length === 0
275
+ ? empty('暂无供应商商品,上传供应商合同后在这里审核。')
276
+ : Object.keys(groups).sort().map((supplier) =>
277
+ h('section', { className: 'tcw-supplier-block', key: supplier },
278
+ h('div', { className: 'tcw-supplier-head' }, h('strong', null, supplier), h('span', null, groups[supplier].length + ' 个商品')),
279
+ table(['商品', '型号', '海关编码', '退税率', '英文品名', '管控状态'], groups[supplier], (item) => [
280
+ value(item.productName),
281
+ value(item.model),
282
+ value(item.enrichedHsCode || item.contractHsCode),
283
+ value(item.taxRefundRate),
284
+ value(item.englishName),
285
+ status(controlStatusText(item.controlledStatus), controlStatusLevel(item.controlledStatus))
286
+ ])
287
+ )
288
+ )
289
+ )
290
+ }
291
+
292
+ function renderWorkbooksPage() {
293
+ const salesReviews = reviewItems.filter((item) => item.type === 'customs_workbook')
294
+ return h('div', { className: 'tcw-page workbooks-page' },
295
+ h('div', { className: 'tcw-page-head' },
296
+ h('div', null, h('h2', null, '生成销售发票'), h('p', null, '上传购销合同识别发票字段,审核后生成固定模板 Excel。')),
297
+ h('div', { className: 'tcw-button-row' },
298
+ uploadButton('upload_sales_contract', '上传购销合同', 'accept-doc-xls-pdf'),
299
+ h('button', { className: 'tcw-btn tcw-btn-primary', disabled: busy, onClick: generateWorkbook }, '生成销售发票')
300
+ )
301
+ ),
302
+ h('div', { className: 'tcw-split' },
303
+ h('section', null,
304
+ h('h3', null, '购销合同识别历史'),
305
+ table(['文件/标题', '审核状态', '发票号', '合同号'], salesReviews, (item) => [
306
+ value(item.title),
307
+ status(reviewStatusText(item.reviewStatus), item.reviewStatus === 'confirmed' ? 'ok' : 'warn'),
308
+ value(readMerged(item).invoiceNo),
309
+ value(readMerged(item).contractNo)
310
+ ], '暂无购销合同上传记录。')
311
+ ),
312
+ h('section', null,
313
+ h('h3', null, '已生成销售发票'),
314
+ table(['文件名', '发票号', '合同号', '模板工作表', '状态'], filteredWorkbooks, (item) => [
315
+ value(item.fileName),
316
+ value(item.invoiceNo),
317
+ value(item.contractNo),
318
+ Array.isArray(item.sheetNames) ? item.sheetNames.join('、') : '-',
319
+ status(value(item.status, 'generated'), 'ok')
320
+ ], '暂无销售发票生成历史。')
321
+ )
28
322
  )
29
323
  )
324
+ }
325
+
326
+ function renderReviewDrawer(item) {
327
+ return h('aside', { className: 'tcw-drawer' },
328
+ h('div', { className: 'tcw-drawer-head' },
329
+ h('div', null, h('h2', null, '对比审核'), h('p', null, item ? item.title : '暂无待审核信息')),
330
+ item ? status(reviewStatusText(item.reviewStatus), item.reviewStatus === 'confirmed' ? 'ok' : 'warn') : null
331
+ ),
332
+ !item ? empty('上传文件或等待智能体识别后,审核项会显示在这里。') : [
333
+ h('div', { className: 'tcw-review-list', key: 'list' },
334
+ reviewItems.slice(0, 8).map((review) =>
335
+ h('button', {
336
+ className: review.id === item.id ? 'tcw-review-chip active' : 'tcw-review-chip',
337
+ key: review.id || review.title,
338
+ onClick: () => setSelectedReviewId(review.id || null)
339
+ }, h('span', null, reviewTypeText(review.type)), h('strong', null, review.title))
340
+ )
341
+ ),
342
+ compareBlock('识别值', item.extractedData),
343
+ compareBlock('默认值', item.defaultData),
344
+ compareBlock('人工确认值', item.confirmedData),
345
+ h('div', { className: 'tcw-evidence', key: 'evidence' },
346
+ h('span', null, '来源证据'),
347
+ h('strong', null, value(item.sourceLocation || readMerged(item).sourceFileName))
348
+ ),
349
+ h('button', { className: 'tcw-btn tcw-btn-primary tcw-wide', key: 'confirm', disabled: busy || item.reviewStatus === 'confirmed', onClick: () => confirmReview(item) }, item.reviewStatus === 'confirmed' ? '已确认' : '确认当前记录')
350
+ ]
351
+ )
352
+ }
353
+
354
+ function uploadButton(actionKey, label, inputClass) {
355
+ const id = actionKey + '-input'
356
+ return h('label', { className: 'tcw-upload' },
357
+ h('input', {
358
+ id,
359
+ className: inputClass,
360
+ type: 'file',
361
+ disabled: busy,
362
+ onChange: (event) => {
363
+ const file = event.target.files && event.target.files[0]
364
+ event.target.value = ''
365
+ handleFile(actionKey, file)
366
+ }
367
+ }),
368
+ h('span', null, label)
369
+ )
370
+ }
371
+
372
+ function updateForm(key) {
373
+ return (event) => setForm(Object.assign({}, form, { [key]: event.target.value }))
374
+ }
375
+ }
376
+
377
+ function metric(label, valueText) {
378
+ return h('div', { className: 'tcw-metric' }, h('span', null, label), h('strong', null, valueText))
379
+ }
380
+
381
+ function field(label, child) {
382
+ return h('label', { className: 'tcw-field' }, h('span', null, label), child)
383
+ }
384
+
385
+ function table(headers, rows, mapRow, emptyText) {
386
+ if (!rows || rows.length === 0) return empty(emptyText || '暂无数据。')
387
+ return h('div', { className: 'tcw-table-wrap' },
388
+ h('table', { className: 'tcw-table' },
389
+ h('thead', null, h('tr', null, headers.map((item) => h('th', { key: item }, item)))),
390
+ h('tbody', null, rows.map((row, index) => h('tr', { key: row.id || index }, mapRow(row).map((cell, cellIndex) => h('td', { key: cellIndex }, cell)))))
391
+ )
392
+ )
393
+ }
394
+
395
+ function compareBlock(label, data) {
396
+ const entries = Object.entries(isObject(data) ? data : {})
397
+ return h('section', { className: 'tcw-compare', key: label },
398
+ h('h3', null, label),
399
+ entries.length === 0 ? h('p', null, '暂无') : entries.slice(0, 12).map(([key, val]) =>
400
+ h('div', { className: 'tcw-kv', key }, h('span', null, key), h('strong', null, stringify(val)))
401
+ )
30
402
  )
31
403
  }
32
404
 
33
- const styles = {
34
- shell: { fontFamily: 'Inter, system-ui, sans-serif', padding: 24, color: '#172033', background: '#f7f8fb', minHeight: '100vh' },
35
- header: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 18 },
36
- title: { margin: 0, fontSize: 24 },
37
- subtitle: { margin: '6px 0 0', color: '#64748b' },
38
- tabs: { display: 'flex', gap: 8, marginBottom: 18 },
39
- tab: { border: '1px solid #d7dde8', background: '#fff', padding: '8px 12px', borderRadius: 6 },
40
- activeTab: { border: '1px solid #0f766e', background: '#e6fffb', color: '#0f766e', padding: '8px 12px', borderRadius: 6 },
41
- grid: { display: 'grid', gridTemplateColumns: '1.4fr .8fr', gap: 16 },
42
- panel: { background: '#fff', border: '1px solid #e2e8f0', borderRadius: 8, padding: 16 },
43
- panelTitle: { margin: '0 0 12px', fontSize: 16 },
44
- row: { padding: 12, border: '1px solid #edf2f7', borderRadius: 6, marginBottom: 8 },
45
- primary: { background: '#0f766e', color: '#fff', border: 0, borderRadius: 6, padding: '8px 12px' }
405
+ function status(text, level) {
406
+ return h('span', { className: 'tcw-status ' + (level || 'muted') }, text)
46
407
  }
47
408
 
48
- ReactDOM.render(h(App), root)
409
+ function empty(text) {
410
+ return h('div', { className: 'tcw-empty' }, text)
411
+ }
412
+
413
+ function normalizeData(payload) {
414
+ const body = payload && payload.summary ? payload.summary : payload || {}
415
+ return {
416
+ reviewItems: Array.isArray(body.reviewItems) ? body.reviewItems : [],
417
+ controlledGoods: Array.isArray(body.controlledGoods) ? body.controlledGoods : [],
418
+ products: Array.isArray(body.products) ? body.products : [],
419
+ workbookGenerations: Array.isArray(body.workbookGenerations) ? body.workbookGenerations : []
420
+ }
421
+ }
422
+
423
+ function getResponsePayload(response) {
424
+ if (!response) return null
425
+ if (Object.prototype.hasOwnProperty.call(response, 'payload')) return response.payload
426
+ if (Object.prototype.hasOwnProperty.call(response, 'data')) return response.data
427
+ if (response.result) return response.result
428
+ return response
429
+ }
430
+
431
+ function assertActionSuccess(response) {
432
+ const payload = getResponsePayload(response)
433
+ if (payload && payload.success === false) {
434
+ throw new Error(resolveMessage(payload.message) || '操作失败')
435
+ }
436
+ }
437
+
438
+ function resolveMessage(message) {
439
+ if (!message) return ''
440
+ if (typeof message === 'string') return message
441
+ if (typeof message.zh_Hans === 'string') return message.zh_Hans
442
+ if (typeof message.en_US === 'string') return message.en_US
443
+ return ''
444
+ }
445
+
446
+ function getErrorMessage(error) {
447
+ return error && error.message ? error.message : String(error || '操作失败')
448
+ }
449
+
450
+ function filterItems(items, query, keys) {
451
+ const keyword = String(query || '').trim().toLowerCase()
452
+ if (!keyword) return items
453
+ return items.filter((item) => keys.some((key) => String(item && item[key] || '').toLowerCase().includes(keyword)))
454
+ }
455
+
456
+ function groupBy(items, keyFn) {
457
+ return items.reduce((acc, item) => {
458
+ const key = keyFn(item)
459
+ acc[key] = acc[key] || []
460
+ acc[key].push(item)
461
+ return acc
462
+ }, {})
463
+ }
464
+
465
+ function readMerged(item) {
466
+ return Object.assign({}, item && item.defaultData, item && item.extractedData, item && item.confirmedData)
467
+ }
468
+
469
+ function value(input, fallback) {
470
+ if (input === 0) return '0'
471
+ return input == null || input === '' ? (fallback || '-') : String(input)
472
+ }
473
+
474
+ function stringify(input) {
475
+ if (input == null || input === '') return '-'
476
+ if (typeof input === 'object') return JSON.stringify(input)
477
+ return String(input)
478
+ }
479
+
480
+ function reviewTypeText(type) {
481
+ if (type === 'controlled_goods') return '管控'
482
+ if (type === 'supplier_product') return '商品'
483
+ if (type === 'customs_workbook') return '发票'
484
+ return value(type)
485
+ }
486
+
487
+ function reviewStatusText(statusText) {
488
+ if (statusText === 'confirmed') return '已确认'
489
+ if (statusText === 'rejected') return '已驳回'
490
+ if (statusText === 'needs_revision') return '需修订'
491
+ return '待审核'
492
+ }
493
+
494
+ function controlStatusText(statusText) {
495
+ if (statusText === 'controlled') return '管控'
496
+ if (statusText === 'suspected') return '疑似管控'
497
+ if (statusText === 'not_controlled') return '非管控'
498
+ return '未检查'
499
+ }
500
+
501
+ function controlStatusLevel(statusText) {
502
+ if (statusText === 'controlled') return 'danger'
503
+ if (statusText === 'suspected') return 'warn'
504
+ if (statusText === 'not_controlled') return 'ok'
505
+ return 'muted'
506
+ }
507
+
508
+ function injectStyles() {
509
+ const style = document.createElement('style')
510
+ style.textContent = `
511
+ :root {
512
+ color-scheme: light;
513
+ --tcw-bg: #f4f6f8;
514
+ --tcw-card: #ffffff;
515
+ --tcw-card-soft: #f8fafb;
516
+ --tcw-text: #17202e;
517
+ --tcw-muted: #5d6b7a;
518
+ --tcw-border: #dbe2ea;
519
+ --tcw-primary: #176b87;
520
+ --tcw-primary-dark: #0f5167;
521
+ --tcw-success: #1b7f4c;
522
+ --tcw-warning: #a35f00;
523
+ --tcw-danger: #b42318;
524
+ }
525
+ * { box-sizing: border-box; }
526
+ body { margin: 0; background: var(--tcw-bg); color: var(--tcw-text); font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
527
+ button, input { font: inherit; letter-spacing: 0; }
528
+ .tcw-shell { display: grid; gap: 14px; min-height: 100vh; padding: 18px; }
529
+ .tcw-header { display: grid; grid-template-columns: minmax(0, 1fr) minmax(360px, 520px); gap: 16px; align-items: end; }
530
+ .tcw-title-block { display: grid; gap: 5px; }
531
+ .tcw-kicker { color: var(--tcw-primary); font-size: 12px; font-weight: 800; }
532
+ .tcw-title-block h1 { margin: 0; font-size: 24px; line-height: 1.25; }
533
+ .tcw-title-block p, .tcw-page-head p, .tcw-drawer-head p { margin: 0; color: var(--tcw-muted); font-size: 13px; }
534
+ .tcw-header-actions { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; }
535
+ .tcw-search, .tcw-field input { width: 100%; min-height: 36px; border: 1px solid var(--tcw-border); border-radius: 6px; background: var(--tcw-card); color: var(--tcw-text); padding: 8px 10px; }
536
+ .tcw-btn, .tcw-upload { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 36px; border: 1px solid var(--tcw-border); border-radius: 6px; background: var(--tcw-card); color: var(--tcw-text); padding: 8px 12px; cursor: pointer; white-space: nowrap; }
537
+ .tcw-btn:disabled, .tcw-upload:has(input:disabled) { cursor: not-allowed; opacity: .55; }
538
+ .tcw-btn-primary { border-color: var(--tcw-primary); background: var(--tcw-primary); color: #fff; }
539
+ .tcw-btn-primary:hover:not(:disabled) { background: var(--tcw-primary-dark); }
540
+ .tcw-btn-soft { background: var(--tcw-card-soft); }
541
+ .tcw-wide { width: 100%; }
542
+ .tcw-upload { border-style: dashed; border-color: color-mix(in srgb, var(--tcw-primary) 42%, var(--tcw-border)); color: var(--tcw-primary); font-weight: 700; }
543
+ .tcw-upload input { display: none; }
544
+ .tcw-notice { border: 1px solid color-mix(in srgb, var(--tcw-primary) 26%, var(--tcw-border)); border-radius: 6px; background: color-mix(in srgb, var(--tcw-primary) 8%, var(--tcw-card)); padding: 10px 12px; color: var(--tcw-primary-dark); font-size: 13px; }
545
+ .tcw-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
546
+ .tcw-metric { display: grid; gap: 4px; border: 1px solid var(--tcw-border); border-radius: 8px; background: var(--tcw-card); padding: 12px; }
547
+ .tcw-metric span { color: var(--tcw-muted); font-size: 12px; }
548
+ .tcw-metric strong { font-size: 22px; line-height: 1; }
549
+ .tcw-tabs { display: flex; gap: 8px; border-bottom: 1px solid var(--tcw-border); }
550
+ .tcw-tab { min-height: 38px; border: 0; border-bottom: 3px solid transparent; background: transparent; color: var(--tcw-muted); padding: 8px 12px; cursor: pointer; font-weight: 800; }
551
+ .tcw-tab.active { border-color: var(--tcw-primary); color: var(--tcw-primary); }
552
+ .tcw-main { display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 390px); gap: 14px; align-items: start; }
553
+ .tcw-content, .tcw-drawer, .tcw-supplier-block { border: 1px solid var(--tcw-border); border-radius: 8px; background: var(--tcw-card); }
554
+ .tcw-content { min-width: 0; padding: 14px; }
555
+ .tcw-page { display: grid; gap: 14px; }
556
+ .tcw-page-head, .tcw-drawer-head, .tcw-supplier-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
557
+ .tcw-page-head h2, .tcw-drawer-head h2, .tcw-split h3 { margin: 0 0 5px; font-size: 17px; line-height: 1.35; }
558
+ .tcw-button-row { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
559
+ .tcw-form { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)) auto auto; gap: 10px; align-items: end; border: 1px solid var(--tcw-border); border-radius: 8px; background: var(--tcw-card-soft); padding: 12px; }
560
+ .tcw-field { display: grid; gap: 5px; min-width: 0; }
561
+ .tcw-field span { color: var(--tcw-muted); font-size: 12px; font-weight: 700; }
562
+ .tcw-check { display: inline-flex; align-items: center; gap: 6px; min-height: 36px; color: var(--tcw-muted); font-size: 13px; }
563
+ .tcw-table-wrap { overflow: auto; border: 1px solid var(--tcw-border); border-radius: 8px; }
564
+ .tcw-table { width: 100%; min-width: 760px; border-collapse: collapse; font-size: 12px; }
565
+ .tcw-table th, .tcw-table td { border-bottom: 1px solid var(--tcw-border); padding: 10px; text-align: left; vertical-align: top; }
566
+ .tcw-table th { background: var(--tcw-card-soft); color: var(--tcw-muted); font-size: 11px; font-weight: 900; }
567
+ .tcw-table tr:last-child td { border-bottom: 0; }
568
+ .tcw-empty { display: grid; place-items: center; min-height: 110px; border: 1px dashed var(--tcw-border); border-radius: 8px; background: var(--tcw-card-soft); color: var(--tcw-muted); padding: 18px; text-align: center; }
569
+ .tcw-supplier-block { display: grid; gap: 10px; padding: 12px; }
570
+ .tcw-supplier-head strong { font-size: 15px; }
571
+ .tcw-supplier-head span { color: var(--tcw-muted); font-size: 12px; }
572
+ .tcw-split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; }
573
+ .tcw-drawer { position: sticky; top: 12px; display: grid; gap: 12px; padding: 14px; }
574
+ .tcw-review-list { display: grid; gap: 7px; max-height: 220px; overflow: auto; }
575
+ .tcw-review-chip { display: grid; grid-template-columns: 42px minmax(0, 1fr); gap: 8px; width: 100%; border: 1px solid var(--tcw-border); border-radius: 6px; background: var(--tcw-card-soft); padding: 8px; cursor: pointer; text-align: left; }
576
+ .tcw-review-chip.active { border-color: var(--tcw-primary); background: color-mix(in srgb, var(--tcw-primary) 7%, var(--tcw-card)); }
577
+ .tcw-review-chip span { color: var(--tcw-primary); font-size: 12px; font-weight: 900; }
578
+ .tcw-review-chip strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
579
+ .tcw-compare { display: grid; gap: 6px; border-top: 1px solid var(--tcw-border); padding-top: 10px; }
580
+ .tcw-compare h3 { margin: 0; font-size: 13px; }
581
+ .tcw-kv { display: grid; grid-template-columns: minmax(92px, .38fr) minmax(0, 1fr); gap: 8px; border: 1px solid var(--tcw-border); border-radius: 6px; background: var(--tcw-card-soft); padding: 7px 8px; }
582
+ .tcw-kv span { color: var(--tcw-muted); font-size: 11px; }
583
+ .tcw-kv strong { overflow-wrap: anywhere; font-size: 12px; font-weight: 700; }
584
+ .tcw-evidence { display: grid; gap: 4px; border: 1px solid color-mix(in srgb, var(--tcw-primary) 24%, var(--tcw-border)); border-radius: 6px; background: color-mix(in srgb, var(--tcw-primary) 6%, var(--tcw-card)); padding: 10px; }
585
+ .tcw-evidence span { color: var(--tcw-muted); font-size: 11px; font-weight: 800; }
586
+ .tcw-evidence strong { overflow-wrap: anywhere; font-size: 12px; }
587
+ .tcw-status { display: inline-flex; width: fit-content; align-items: center; border-radius: 999px; padding: 3px 8px; font-size: 11px; font-weight: 900; }
588
+ .tcw-status.ok { background: #e8f7ef; color: var(--tcw-success); }
589
+ .tcw-status.warn { background: #fff4df; color: var(--tcw-warning); }
590
+ .tcw-status.danger { background: #fde8e6; color: var(--tcw-danger); }
591
+ .tcw-status.muted { background: #eef2f6; color: var(--tcw-muted); }
592
+ @media (max-width: 980px) {
593
+ .tcw-header, .tcw-main, .tcw-form, .tcw-split { grid-template-columns: 1fr; }
594
+ .tcw-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
595
+ .tcw-drawer { position: static; }
596
+ }
597
+ `
598
+ document.head.appendChild(style)
599
+ }
600
+
601
+ window.addEventListener('message', (event) => {
602
+ const message = event.data
603
+ if (!isObject(message) || message.channel !== CHANNEL || message.protocolVersion !== VERSION) return
604
+ if (message.type === 'init') {
605
+ instanceId = message.instanceId
606
+ if (window.XpertRemoteUI && typeof window.XpertRemoteUI.applyTheme === 'function') {
607
+ window.XpertRemoteUI.applyTheme(message.theme)
608
+ }
609
+ if (window.__tradeComplianceSetContext) {
610
+ window.__tradeComplianceSetContext({
611
+ manifest: message.manifest,
612
+ payload: message.payload,
613
+ initialQuery: message.initialQuery || {},
614
+ locale: message.locale,
615
+ theme: message.theme
616
+ })
617
+ }
618
+ setTimeout(reportResize, 0)
619
+ return
620
+ }
621
+ if (message.instanceId !== instanceId) return
622
+ if (message.type === 'hostEvent') {
623
+ if (window.__tradeComplianceHostEvent) window.__tradeComplianceHostEvent(message.event)
624
+ return
625
+ }
626
+ if (message.requestId && pending.has(message.requestId)) {
627
+ const item = pending.get(message.requestId)
628
+ pending.delete(message.requestId)
629
+ if (message.type === 'error') {
630
+ item.reject(new Error(message.message || '远程请求失败'))
631
+ } else {
632
+ item.resolve(message)
633
+ }
634
+ }
635
+ })
636
+
637
+ ReactDOM.render(h(App), document.getElementById('root'))
49
638
  })()
@@ -1,5 +1,5 @@
1
1
  import type { XpertExtensionViewManifest, XpertRemoteComponentEntry, XpertRemoteComponentViewSchema, XpertResolvedViewHostContext, XpertViewActionRequest, XpertViewActionResult, XpertViewDataResult, XpertViewQuery } from '@xpert-ai/contracts';
2
- import { IXpertViewExtensionProvider } from '@xpert-ai/plugin-sdk';
2
+ import { IXpertViewExtensionProvider, XpertViewFileActionFile } from '@xpert-ai/plugin-sdk';
3
3
  import { TradeComplianceWorkbenchService } from './trade-compliance-workbench.service.js';
4
4
  export declare class TradeComplianceWorkbenchViewProvider implements IXpertViewExtensionProvider {
5
5
  private readonly service;
@@ -9,5 +9,6 @@ export declare class TradeComplianceWorkbenchViewProvider implements IXpertViewE
9
9
  getRemoteComponentEntry(_context: XpertResolvedViewHostContext, viewKey: string, component: XpertRemoteComponentViewSchema['component']): Promise<XpertRemoteComponentEntry>;
10
10
  getViewData(context: XpertResolvedViewHostContext, _viewKey: string, _query: XpertViewQuery): Promise<XpertViewDataResult>;
11
11
  executeViewAction(context: XpertResolvedViewHostContext, _viewKey: string, actionKey: string, request: XpertViewActionRequest): Promise<XpertViewActionResult>;
12
+ executeViewFileAction(context: XpertResolvedViewHostContext, viewKey: string, actionKey: string, request: XpertViewActionRequest, file: XpertViewFileActionFile): Promise<XpertViewActionResult>;
12
13
  }
13
14
  //# sourceMappingURL=trade-compliance-workbench-view.provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trade-compliance-workbench-view.provider.d.ts","sourceRoot":"","sources":["../../src/lib/trade-compliance-workbench-view.provider.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,yBAAyB,EACzB,8BAA8B,EAC9B,4BAA4B,EAC5B,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACf,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,2BAA2B,EAG5B,MAAM,sBAAsB,CAAA;AAW7B,OAAO,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAA;AAQzF,qBAEa,oCAAqC,YAAW,2BAA2B;IAC1E,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,+BAA+B;IAErE,QAAQ,CAAC,OAAO,EAAE,4BAA4B;IAI9C,gBAAgB,CAAC,QAAQ,EAAE,4BAA4B,EAAE,IAAI,EAAE,MAAM,GAAG,0BAA0B,EAAE;IAsF9F,uBAAuB,CAC3B,QAAQ,EAAE,4BAA4B,EACtC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,8BAA8B,CAAC,WAAW,CAAC,GACrD,OAAO,CAAC,yBAAyB,CAAC;IAwB/B,WAAW,CACf,OAAO,EAAE,4BAA4B,EACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,mBAAmB,CAAC;IAoBzB,iBAAiB,CACrB,OAAO,EAAE,4BAA4B,EACrC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC;CAsBlC"}
1
+ {"version":3,"file":"trade-compliance-workbench-view.provider.d.ts","sourceRoot":"","sources":["../../src/lib/trade-compliance-workbench-view.provider.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,0BAA0B,EAC1B,yBAAyB,EACzB,8BAA8B,EAC9B,4BAA4B,EAC5B,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACf,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,2BAA2B,EAG3B,uBAAuB,EACxB,MAAM,sBAAsB,CAAA;AAW7B,OAAO,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAA;AAQzF,qBAEa,oCAAqC,YAAW,2BAA2B;IAC1E,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,+BAA+B;IAErE,QAAQ,CAAC,OAAO,EAAE,4BAA4B;IAI9C,gBAAgB,CAAC,QAAQ,EAAE,4BAA4B,EAAE,IAAI,EAAE,MAAM,GAAG,0BAA0B,EAAE;IAuF9F,uBAAuB,CAC3B,QAAQ,EAAE,4BAA4B,EACtC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,8BAA8B,CAAC,WAAW,CAAC,GACrD,OAAO,CAAC,yBAAyB,CAAC;IAwB/B,WAAW,CACf,OAAO,EAAE,4BAA4B,EACrC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,mBAAmB,CAAC;IAoBzB,iBAAiB,CACrB,OAAO,EAAE,4BAA4B,EACrC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC;IAuD3B,qBAAqB,CACzB,OAAO,EAAE,4BAA4B,EACrC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;CA4ElC"}
@@ -94,6 +94,7 @@ let TradeComplianceWorkbenchViewProvider = class TradeComplianceWorkbenchViewPro
94
94
  },
95
95
  { key: 'confirm_review_item', label: text('Confirm Item', '确认单条'), icon: 'ri-check-line', actionType: 'invoke' },
96
96
  { key: 'confirm_review_items', label: text('Confirm Selected', '批量确认'), icon: 'ri-check-double-line', actionType: 'invoke' },
97
+ { key: 'save_controlled_goods', label: text('Save Controlled Goods', '保存管控商品'), icon: 'ri-save-line', actionType: 'invoke' },
97
98
  { key: 'generate_customs_workbook', label: text('Generate Workbook', '生成报关资料'), icon: 'ri-file-excel-line', actionType: 'invoke' }
98
99
  ]
99
100
  }
@@ -155,12 +156,116 @@ let TradeComplianceWorkbenchViewProvider = class TradeComplianceWorkbenchViewPro
155
156
  if (actionKey === 'refresh') {
156
157
  return { success: true, message: text('Refreshed', '已刷新'), refresh: true };
157
158
  }
159
+ if (actionKey === 'save_controlled_goods') {
160
+ const productName = readString(request.input, 'productName');
161
+ if (!productName) {
162
+ return failure('productName is required', '缺少商品名称');
163
+ }
164
+ return success(await this.service.saveControlledGoods(scope, {
165
+ productName,
166
+ hsCode: readString(request.input, 'hsCode'),
167
+ keywords: readStringArray(request.input, 'keywords'),
168
+ controlNote: readString(request.input, 'controlNote'),
169
+ enabled: readBoolean(request.input, 'enabled') ?? true,
170
+ sourceFileName: readString(request.input, 'sourceFileName'),
171
+ sourceLocation: readString(request.input, 'sourceLocation')
172
+ }));
173
+ }
174
+ if (actionKey === 'generate_customs_workbook') {
175
+ const now = new Date();
176
+ const invoiceNo = readString(request.input, 'invoiceNo') ?? `INV-${now.toISOString().slice(0, 10).replace(/-/g, '')}`;
177
+ const result = await this.service.recordWorkbookGeneration(scope, {
178
+ sourceFileName: readString(request.input, 'sourceFileName') ?? readString(request.input, 'contractName'),
179
+ invoiceNo,
180
+ contractNo: readString(request.input, 'contractNo'),
181
+ fileName: readString(request.input, 'fileName') ?? `${invoiceNo}-销售发票.xlsx`,
182
+ sheetNames: ['销售发票'],
183
+ workbookData: readRecord(request.input, 'workbookData') ?? {
184
+ invoiceNo,
185
+ contractNo: readString(request.input, 'contractNo'),
186
+ generatedFrom: 'trade-compliance-workbench'
187
+ }
188
+ });
189
+ return success(result);
190
+ }
158
191
  return {
159
192
  success: true,
160
193
  message: text('Action accepted', '操作已接收'),
161
194
  refresh: true
162
195
  };
163
196
  }
197
+ async executeViewFileAction(context, viewKey, actionKey, request, file) {
198
+ if (viewKey !== TRADE_COMPLIANCE_VIEW_KEY) {
199
+ return failure('Unsupported view', '不支持的视图');
200
+ }
201
+ const scope = scopeFromContext(context);
202
+ const fileName = getFileDisplayName(file, request.input);
203
+ if (actionKey === 'upload_controlled_goods_file') {
204
+ return success(await this.service.createReviewBatch(scope, {
205
+ type: 'controlled_goods_file',
206
+ sourceFileName: fileName,
207
+ metadata: { fileName, size: getFileSize(file), mimeType: getFileMimeType(file) },
208
+ items: [{
209
+ type: 'controlled_goods',
210
+ title: `管控商品文件:${fileName}`,
211
+ extractedData: { sourceFileName: fileName },
212
+ defaultData: { enabled: true },
213
+ fields: [
214
+ { key: 'productName', label: '商品名称', required: true },
215
+ { key: 'hsCode', label: '海关编码' },
216
+ { key: 'controlNote', label: '管控说明' }
217
+ ],
218
+ sourceLocation: fileName
219
+ }]
220
+ }));
221
+ }
222
+ if (actionKey === 'upload_supplier_contract') {
223
+ return success(await this.service.createReviewBatch(scope, {
224
+ type: 'supplier_contract',
225
+ sourceFileName: fileName,
226
+ metadata: { fileName, size: getFileSize(file), mimeType: getFileMimeType(file) },
227
+ items: [{
228
+ type: 'supplier_product',
229
+ title: `供应商合同:${fileName}`,
230
+ extractedData: { sourceFileName: fileName },
231
+ defaultData: { controlledStatus: 'unchecked' },
232
+ fields: [
233
+ { key: 'supplierName', label: '供应商', required: true },
234
+ { key: 'productName', label: '商品名称', required: true },
235
+ { key: 'model', label: '型号' },
236
+ { key: 'enrichedHsCode', label: '海关编码' },
237
+ { key: 'taxRefundRate', label: '退税率' },
238
+ { key: 'englishName', label: '英文品名' },
239
+ { key: 'controlledStatus', label: '管控状态' },
240
+ { key: 'controlNote', label: '管控说明' }
241
+ ],
242
+ sourceLocation: fileName
243
+ }]
244
+ }));
245
+ }
246
+ if (actionKey === 'upload_sales_contract') {
247
+ return success(await this.service.createReviewBatch(scope, {
248
+ type: 'sales_contract',
249
+ sourceFileName: fileName,
250
+ metadata: { fileName, size: getFileSize(file), mimeType: getFileMimeType(file) },
251
+ items: [{
252
+ type: 'customs_workbook',
253
+ title: `购销合同:${fileName}`,
254
+ extractedData: { sourceFileName: fileName },
255
+ defaultData: { currency: 'USD' },
256
+ fields: [
257
+ { key: 'invoiceNo', label: '发票号' },
258
+ { key: 'contractNo', label: '合同号' },
259
+ { key: 'buyerName', label: '买方' },
260
+ { key: 'sellerName', label: '卖方' },
261
+ { key: 'items', label: '商品明细' }
262
+ ],
263
+ sourceLocation: fileName
264
+ }]
265
+ }));
266
+ }
267
+ return failure('Unsupported file action', '不支持的文件操作');
268
+ }
164
269
  };
165
270
  TradeComplianceWorkbenchViewProvider = __decorate([
166
271
  Injectable(),
@@ -169,7 +274,8 @@ TradeComplianceWorkbenchViewProvider = __decorate([
169
274
  ], TradeComplianceWorkbenchViewProvider);
170
275
  export { TradeComplianceWorkbenchViewProvider };
171
276
  async function readPackageFile(packageName, filePath) {
172
- return readFile(requireFromHere.resolve(join(packageName, filePath)), 'utf8');
277
+ const packageRoot = dirname(requireFromHere.resolve(`${packageName}/package.json`));
278
+ return readFile(join(packageRoot, filePath), 'utf8');
173
279
  }
174
280
  function scopeFromContext(context) {
175
281
  return {
@@ -208,4 +314,33 @@ function readStringArray(input, key) {
208
314
  const value = typeof input === 'object' && input != null ? Reflect.get(input, key) : undefined;
209
315
  return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : [];
210
316
  }
317
+ function readBoolean(input, key) {
318
+ const value = typeof input === 'object' && input != null ? Reflect.get(input, key) : undefined;
319
+ return typeof value === 'boolean' ? value : undefined;
320
+ }
321
+ function getFileDisplayName(file, input) {
322
+ return readString(input, 'name') ?? readString(input, 'fileName') ?? getFileName(file) ?? 'uploaded-document';
323
+ }
324
+ function getFileName(file) {
325
+ const record = file;
326
+ return typeof record.name === 'string'
327
+ ? record.name
328
+ : typeof record.originalname === 'string'
329
+ ? record.originalname
330
+ : typeof record.originalName === 'string'
331
+ ? record.originalName
332
+ : undefined;
333
+ }
334
+ function getFileMimeType(file) {
335
+ const record = file;
336
+ return typeof record.mimetype === 'string'
337
+ ? record.mimetype
338
+ : typeof record.type === 'string'
339
+ ? record.type
340
+ : undefined;
341
+ }
342
+ function getFileSize(file) {
343
+ const record = file;
344
+ return typeof record.size === 'number' ? record.size : undefined;
345
+ }
211
346
  //# sourceMappingURL=trade-compliance-workbench-view.provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"trade-compliance-workbench-view.provider.js","sourceRoot":"","sources":["../../src/lib/trade-compliance-workbench-view.provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trade-compliance-workbench-view.provider.js","sourceRoot":"","sources":["../../src/lib/trade-compliance-workbench-view.provider.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chenchaolong/plugin-trade-compliance-workbench",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Trade Compliance Workbench app plugin for controlled goods review, supplier product management, and customs workbook generation.",
5
5
  "author": {
6
6
  "name": "XpertAI",
@@ -9,7 +9,7 @@
9
9
  "license": "AGPL-3.0",
10
10
  "repository": {
11
11
  "type": "git",
12
- "url": "https://github.com/xpert-ai/xpert-plugins.git",
12
+ "url": "git+https://github.com/xpert-ai/xpert-plugins.git",
13
13
  "directory": "community/apps/trade-compliance-workbench"
14
14
  },
15
15
  "bugs": {
@@ -35,7 +35,7 @@
35
35
  "scripts": {
36
36
  "build": "tsc -p tsconfig.lib.json && node scripts/copy-assets.mjs",
37
37
  "lint": "echo \"(todo) add lint\"",
38
- "test": "tsc -p tsconfig.spec.json --noEmit"
38
+ "test": "tsc -p tsconfig.spec.json --noEmit && node scripts/verify-remote-app.mjs"
39
39
  },
40
40
  "xpert": {
41
41
  "plugin": {