@chenchaolong/plugin-trade-compliance-workbench 0.1.44 → 0.1.46
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.
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
const [activePage, setActivePage] = React.useState('overview-page')
|
|
71
71
|
const [selectedIds, setSelectedIds] = React.useState([])
|
|
72
72
|
const [statusFilter, setStatusFilter] = React.useState('all')
|
|
73
|
+
const [overviewTab, setOverviewTab] = React.useState('all')
|
|
73
74
|
const [busy, setBusy] = React.useState(false)
|
|
74
75
|
const [query, setQuery] = React.useState('')
|
|
75
76
|
const [pageByList, setPageByList] = React.useState({})
|
|
@@ -103,7 +104,7 @@
|
|
|
103
104
|
}
|
|
104
105
|
}, [])
|
|
105
106
|
|
|
106
|
-
React.useEffect(reportResize, [data, activePage, selectedIds, statusFilter, busy, formDialog, deleteDialog, hsCodeSearch, hsCodeDetailDialog])
|
|
107
|
+
React.useEffect(reportResize, [data, activePage, selectedIds, statusFilter, overviewTab, busy, formDialog, deleteDialog, hsCodeSearch, hsCodeDetailDialog])
|
|
107
108
|
|
|
108
109
|
const reviewItems = data.reviewItems.filter((item) => !isPlaceholderReviewItem(item))
|
|
109
110
|
const pendingItems = reviewItems.filter((item) => (item.reviewStatus || 'pending') === 'pending')
|
|
@@ -646,27 +647,12 @@
|
|
|
646
647
|
)
|
|
647
648
|
),
|
|
648
649
|
h('nav', { className: 'tcw-nav', 'aria-label': '主导航' }, [
|
|
649
|
-
tab('overview-page', '
|
|
650
|
-
tab('controlled-goods-page', '
|
|
651
|
-
tab('products-page', '供应商商品', '
|
|
652
|
-
tab('workbooks-page', '销售发票', '
|
|
653
|
-
tab('hs-code-search-page', '工具', '
|
|
654
|
-
])
|
|
655
|
-
h('section', { className: 'tcw-sidebar-section' },
|
|
656
|
-
h('h2', null, '主流程'),
|
|
657
|
-
h('ol', { className: 'tcw-flow-list' }, [
|
|
658
|
-
'维护管控规则',
|
|
659
|
-
'上传供应商合同',
|
|
660
|
-
'确认 HS 编码候选',
|
|
661
|
-
'审核供应商商品',
|
|
662
|
-
'上传购销合同',
|
|
663
|
-
'生成销售发票'
|
|
664
|
-
].map((item) => h('li', { key: item }, h('span', null), item)))
|
|
665
|
-
),
|
|
666
|
-
h('section', { className: 'tcw-sidebar-section compact' },
|
|
667
|
-
h('h2', null, '数据关系'),
|
|
668
|
-
h('p', null, '管控规则用于匹配供应商商品,已确认商品进入销售发票生成流程。')
|
|
669
|
-
)
|
|
650
|
+
tab('overview-page', '总览', 'dashboard', pendingItems.length, 'blue'),
|
|
651
|
+
tab('controlled-goods-page', '管控商品', 'shield', controlledReviews.length, 'green'),
|
|
652
|
+
tab('products-page', '供应商商品', 'box', supplierReviews.length, 'orange'),
|
|
653
|
+
tab('workbooks-page', '销售发票', 'invoice', salesReviews.length + filteredWorkbooks.length, 'violet'),
|
|
654
|
+
tab('hs-code-search-page', '工具', 'search', null, 'slate')
|
|
655
|
+
])
|
|
670
656
|
)
|
|
671
657
|
}
|
|
672
658
|
|
|
@@ -686,7 +672,7 @@
|
|
|
686
672
|
h('section', { className: 'tcw-assistant-card' },
|
|
687
673
|
h('h3', null, '快捷入口'),
|
|
688
674
|
h('div', { className: 'tcw-assistant-actions' }, [
|
|
689
|
-
h('button', { className: 'tcw-mini-btn', onClick: () => setActivePage('controlled-goods-page') }, '
|
|
675
|
+
h('button', { className: 'tcw-mini-btn', onClick: () => setActivePage('controlled-goods-page') }, '管控商品'),
|
|
690
676
|
h('button', { className: 'tcw-mini-btn', onClick: () => setActivePage('products-page') }, '商品审核'),
|
|
691
677
|
h('button', { className: 'tcw-mini-btn', onClick: () => setActivePage('hs-code-search-page') }, '查 HS 编码')
|
|
692
678
|
])
|
|
@@ -700,28 +686,50 @@
|
|
|
700
686
|
|
|
701
687
|
function tab(key, label, icon, count, tone) {
|
|
702
688
|
return h('button', { key, className: key === activePage ? 'tcw-tab active' : 'tcw-tab', onClick: () => setActivePage(key) },
|
|
703
|
-
h('span', { className: 'tcw-nav-icon ' + (tone || 'blue') }, icon),
|
|
689
|
+
h('span', { className: 'tcw-nav-icon ' + (tone || 'blue') }, iconImage(icon, label, tone)),
|
|
704
690
|
h('span', null, label),
|
|
705
691
|
count == null ? null : h('em', null, count)
|
|
706
692
|
)
|
|
707
693
|
}
|
|
708
694
|
|
|
709
695
|
function renderOverviewPage() {
|
|
696
|
+
const pendingOverviewItems = overviewTab === 'all'
|
|
697
|
+
? pendingItems.slice(0, 12)
|
|
698
|
+
: pendingItems.filter((item) => item.type === overviewTab).slice(0, 12)
|
|
710
699
|
return h('div', { className: 'tcw-page overview-page' },
|
|
711
700
|
h('section', { className: 'tcw-metrics' },
|
|
712
|
-
metric('待审核', pendingItems.length),
|
|
713
|
-
metric('管控识别待审', pendingControlledReviews.length),
|
|
714
|
-
metric('供应商商品待审', pendingSupplierReviews.length),
|
|
715
|
-
metric('销售合同待审', pendingSalesReviews.length),
|
|
716
|
-
metric('已入库管控商品', data.controlledGoods.length),
|
|
717
|
-
metric('已入库供应商商品', data.products.length),
|
|
718
|
-
metric('销售发票历史', data.workbookGenerations.length),
|
|
719
|
-
metric('全部审核记录', reviewItems.length)
|
|
701
|
+
metric('待审核', pendingItems.length, 'dashboard', 'blue'),
|
|
702
|
+
metric('管控识别待审', pendingControlledReviews.length, 'shield', 'green'),
|
|
703
|
+
metric('供应商商品待审', pendingSupplierReviews.length, 'box', 'orange'),
|
|
704
|
+
metric('销售合同待审', pendingSalesReviews.length, 'invoice', 'violet'),
|
|
705
|
+
metric('已入库管控商品', data.controlledGoods.length, 'archive', 'slate'),
|
|
706
|
+
metric('已入库供应商商品', data.products.length, 'supplier', 'green'),
|
|
707
|
+
metric('销售发票历史', data.workbookGenerations.length, 'document', 'violet'),
|
|
708
|
+
metric('全部审核记录', reviewItems.length, 'records', 'blue')
|
|
720
709
|
),
|
|
721
|
-
panel('
|
|
722
|
-
|
|
723
|
-
|
|
710
|
+
panel('待办事项明细',
|
|
711
|
+
h('div', { className: 'tcw-overview-panel' },
|
|
712
|
+
h('div', { className: 'tcw-overview-tabs' }, [
|
|
713
|
+
overviewTabButton('all', '全部', pendingItems.length),
|
|
714
|
+
overviewTabButton('controlled_goods', '管控商品', pendingItems.filter((item) => item.type === 'controlled_goods').length),
|
|
715
|
+
overviewTabButton('supplier_product', '供应商商品', pendingItems.filter((item) => item.type === 'supplier_product').length),
|
|
716
|
+
overviewTabButton('customs_workbook', '销售发票', pendingItems.filter((item) => item.type === 'customs_workbook').length)
|
|
717
|
+
]),
|
|
718
|
+
pendingOverviewItems.length
|
|
719
|
+
? compactReviewList(pendingOverviewItems)
|
|
720
|
+
: empty('暂无待审核记录。智能体识别结果会先出现在这里。')
|
|
721
|
+
)
|
|
722
|
+
)
|
|
724
723
|
)
|
|
724
|
+
|
|
725
|
+
function overviewTabButton(key, label, count) {
|
|
726
|
+
return h('button', {
|
|
727
|
+
key,
|
|
728
|
+
type: 'button',
|
|
729
|
+
className: overviewTab === key ? 'tcw-overview-tab active' : 'tcw-overview-tab',
|
|
730
|
+
onClick: () => setOverviewTab(key)
|
|
731
|
+
}, `${label}${typeof count === 'number' ? ` ${count}` : ''}`)
|
|
732
|
+
}
|
|
725
733
|
}
|
|
726
734
|
|
|
727
735
|
function renderControlledGoodsPage() {
|
|
@@ -1282,8 +1290,42 @@
|
|
|
1282
1290
|
|
|
1283
1291
|
}
|
|
1284
1292
|
|
|
1285
|
-
function metric(label, valueText) {
|
|
1286
|
-
return h('div', { className: 'tcw-metric' },
|
|
1293
|
+
function metric(label, valueText, icon, tone) {
|
|
1294
|
+
return h('div', { className: 'tcw-metric' },
|
|
1295
|
+
h('span', { className: 'tcw-metric-icon ' + (tone || 'blue') }, iconImage(icon, label, tone)),
|
|
1296
|
+
h('div', { className: 'tcw-metric-body' },
|
|
1297
|
+
h('span', null, label),
|
|
1298
|
+
h('strong', null, valueText)
|
|
1299
|
+
)
|
|
1300
|
+
)
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
function iconImage(name, label, tone) {
|
|
1304
|
+
return h('img', { src: iconDataUri(name, tone), alt: label || '', 'aria-hidden': label ? undefined : true })
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
function iconDataUri(name, tone) {
|
|
1308
|
+
const colors = {
|
|
1309
|
+
blue: '#2563eb',
|
|
1310
|
+
green: '#139160',
|
|
1311
|
+
orange: '#e07818',
|
|
1312
|
+
violet: '#7c3aed',
|
|
1313
|
+
slate: '#526174'
|
|
1314
|
+
}
|
|
1315
|
+
const color = colors[tone] || colors.blue
|
|
1316
|
+
const paths = {
|
|
1317
|
+
dashboard: '<rect x="4" y="4" width="7" height="7" rx="1.5"/><rect x="13" y="4" width="7" height="7" rx="1.5"/><rect x="4" y="13" width="7" height="7" rx="1.5"/><rect x="13" y="13" width="7" height="7" rx="1.5"/>',
|
|
1318
|
+
shield: '<path d="M12 3l7 3v5c0 4.8-2.9 8.2-7 10-4.1-1.8-7-5.2-7-10V6l7-3z"/><path d="M9 12l2 2 4-5"/>',
|
|
1319
|
+
box: '<path d="M4 8l8-4 8 4-8 4-8-4z"/><path d="M4 8v8l8 4 8-4V8"/><path d="M12 12v8"/>',
|
|
1320
|
+
invoice: '<path d="M7 3h8l4 4v14l-3-1.5L13 21l-3-1.5L7 21V3z"/><path d="M15 3v5h4"/><path d="M9 11h6"/><path d="M9 15h6"/>',
|
|
1321
|
+
search: '<circle cx="11" cy="11" r="6"/><path d="M16 16l4 4"/>',
|
|
1322
|
+
archive: '<path d="M4 7h16v13H4V7z"/><path d="M3 4h18v3H3z"/><path d="M9 11h6"/>',
|
|
1323
|
+
supplier: '<path d="M4 20V8l8-4 8 4v12"/><path d="M8 20v-7h8v7"/><path d="M10 9h4"/>',
|
|
1324
|
+
document: '<path d="M7 3h7l5 5v13H7V3z"/><path d="M14 3v6h5"/><path d="M9 13h6"/><path d="M9 17h6"/>',
|
|
1325
|
+
records: '<path d="M6 5h12v16H6V5z"/><path d="M9 3h6v4H9z"/><path d="M9 11h6"/><path d="M9 15h6"/>'
|
|
1326
|
+
}
|
|
1327
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${paths[name] || paths.dashboard}</svg>`
|
|
1328
|
+
return 'data:image/svg+xml;utf8,' + encodeURIComponent(svg)
|
|
1287
1329
|
}
|
|
1288
1330
|
|
|
1289
1331
|
function panel(title, content) {
|
|
@@ -1794,8 +1836,8 @@
|
|
|
1794
1836
|
}
|
|
1795
1837
|
|
|
1796
1838
|
function pageTitle(key) {
|
|
1797
|
-
if (key === 'overview-page') return '
|
|
1798
|
-
if (key === 'controlled-goods-page') return '
|
|
1839
|
+
if (key === 'overview-page') return '总览'
|
|
1840
|
+
if (key === 'controlled-goods-page') return '管控商品'
|
|
1799
1841
|
if (key === 'products-page') return '供应商商品'
|
|
1800
1842
|
if (key === 'hs-code-search-page') return '工具'
|
|
1801
1843
|
return '销售发票'
|
|
@@ -1810,15 +1852,15 @@
|
|
|
1810
1852
|
}
|
|
1811
1853
|
|
|
1812
1854
|
function pageBreadcrumb(key) {
|
|
1813
|
-
if (key === 'overview-page') return 'Workspace /
|
|
1814
|
-
if (key === 'controlled-goods-page') return 'Workspace /
|
|
1855
|
+
if (key === 'overview-page') return 'Workspace / 总览'
|
|
1856
|
+
if (key === 'controlled-goods-page') return 'Workspace / 管控商品'
|
|
1815
1857
|
if (key === 'products-page') return 'Workspace / 供应商商品'
|
|
1816
1858
|
if (key === 'workbooks-page') return 'Workspace / 销售发票'
|
|
1817
1859
|
return 'Workspace / 工具'
|
|
1818
1860
|
}
|
|
1819
1861
|
|
|
1820
1862
|
function assistantTip(key) {
|
|
1821
|
-
if (key === 'overview-page') return '
|
|
1863
|
+
if (key === 'overview-page') return '从总览开始,优先确认管控规则和供应商商品,再推进发票生成。'
|
|
1822
1864
|
if (key === 'controlled-goods-page') return '维护管控商品时,建议先核对 HS 编码和关键词,再保存入库。'
|
|
1823
1865
|
if (key === 'products-page') return '供应商商品可先选用候选 HS 编码,再检查英文品名和管控状态。'
|
|
1824
1866
|
if (key === 'workbooks-page') return '购销合同审核完毕后,再生成销售发票,避免后面重改。'
|
|
@@ -1878,9 +1920,38 @@ button, input, textarea, select { font: inherit; letter-spacing: 0; }
|
|
|
1878
1920
|
.tcw-subsection-head h3, .tcw-list-title h3 { margin: 0; font-size: 15px; line-height: 1.3; }
|
|
1879
1921
|
.tcw-subsection-head p, .tcw-list-title span { margin: 0; color: var(--tcw-muted); font-size: 12px; }
|
|
1880
1922
|
.tcw-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
|
|
1881
|
-
.tcw-metric {
|
|
1882
|
-
|
|
1883
|
-
|
|
1923
|
+
.tcw-metric {
|
|
1924
|
+
display: grid;
|
|
1925
|
+
grid-template-columns: 44px minmax(0, 1fr);
|
|
1926
|
+
gap: 10px;
|
|
1927
|
+
align-items: center;
|
|
1928
|
+
border: 1px solid var(--tcw-border);
|
|
1929
|
+
border-radius: 8px;
|
|
1930
|
+
background: var(--tcw-card);
|
|
1931
|
+
padding: 12px;
|
|
1932
|
+
}
|
|
1933
|
+
.tcw-metric-icon {
|
|
1934
|
+
display: grid;
|
|
1935
|
+
place-items: center;
|
|
1936
|
+
width: 44px;
|
|
1937
|
+
height: 44px;
|
|
1938
|
+
border-radius: 10px;
|
|
1939
|
+
font-size: 18px;
|
|
1940
|
+
font-weight: 900;
|
|
1941
|
+
}
|
|
1942
|
+
.tcw-metric-icon img {
|
|
1943
|
+
width: 22px;
|
|
1944
|
+
height: 22px;
|
|
1945
|
+
color: currentColor;
|
|
1946
|
+
}
|
|
1947
|
+
.tcw-metric-icon.blue { background: #e8f0ff; color: var(--tcw-primary); }
|
|
1948
|
+
.tcw-metric-icon.green { background: #e7f8ef; color: var(--tcw-success); }
|
|
1949
|
+
.tcw-metric-icon.orange { background: #fff2df; color: var(--tcw-warning); }
|
|
1950
|
+
.tcw-metric-icon.violet { background: #f1eaff; color: var(--tcw-violet); }
|
|
1951
|
+
.tcw-metric-icon.slate { background: #eef2f6; color: var(--tcw-slate); }
|
|
1952
|
+
.tcw-metric-body { display: grid; gap: 2px; }
|
|
1953
|
+
.tcw-metric-body span { color: var(--tcw-muted); font-size: 12px; }
|
|
1954
|
+
.tcw-metric-body strong { font-size: 22px; line-height: 1; }
|
|
1884
1955
|
.tcw-field { display: grid; gap: 5px; min-width: 0; }
|
|
1885
1956
|
.tcw-field span { color: var(--tcw-muted); font-size: 12px; font-weight: 800; }
|
|
1886
1957
|
.tcw-field-check { align-content: end; }
|
|
@@ -2044,6 +2115,34 @@ body { background: var(--tcw-bg); letter-spacing: 0; }
|
|
|
2044
2115
|
background: #eff6ff;
|
|
2045
2116
|
color: #174ea6;
|
|
2046
2117
|
}
|
|
2118
|
+
.tcw-overview-panel {
|
|
2119
|
+
display: grid;
|
|
2120
|
+
gap: 12px;
|
|
2121
|
+
}
|
|
2122
|
+
.tcw-overview-tabs {
|
|
2123
|
+
display: inline-flex;
|
|
2124
|
+
align-items: center;
|
|
2125
|
+
gap: 0;
|
|
2126
|
+
width: fit-content;
|
|
2127
|
+
border: 1px solid var(--tcw-border);
|
|
2128
|
+
border-radius: 12px;
|
|
2129
|
+
overflow: hidden;
|
|
2130
|
+
background: #fff;
|
|
2131
|
+
}
|
|
2132
|
+
.tcw-overview-tab {
|
|
2133
|
+
min-height: 38px;
|
|
2134
|
+
border: 0;
|
|
2135
|
+
border-right: 1px solid var(--tcw-border);
|
|
2136
|
+
background: #fff;
|
|
2137
|
+
color: var(--tcw-muted);
|
|
2138
|
+
padding: 8px 16px;
|
|
2139
|
+
font-weight: 800;
|
|
2140
|
+
}
|
|
2141
|
+
.tcw-overview-tab:last-child { border-right: 0; }
|
|
2142
|
+
.tcw-overview-tab.active {
|
|
2143
|
+
background: #eff6ff;
|
|
2144
|
+
color: var(--tcw-primary);
|
|
2145
|
+
}
|
|
2047
2146
|
.tcw-tab em {
|
|
2048
2147
|
min-width: 22px;
|
|
2049
2148
|
border-radius: 999px;
|
|
@@ -2063,48 +2162,16 @@ body { background: var(--tcw-bg); letter-spacing: 0; }
|
|
|
2063
2162
|
font-size: 11px;
|
|
2064
2163
|
font-weight: 900;
|
|
2065
2164
|
}
|
|
2165
|
+
.tcw-nav-icon img {
|
|
2166
|
+
width: 16px;
|
|
2167
|
+
height: 16px;
|
|
2168
|
+
color: currentColor;
|
|
2169
|
+
}
|
|
2066
2170
|
.tcw-nav-icon.blue { background: #e8f0ff; color: var(--tcw-primary); }
|
|
2067
2171
|
.tcw-nav-icon.green { background: #e7f8ef; color: var(--tcw-success); }
|
|
2068
2172
|
.tcw-nav-icon.orange { background: #fff2df; color: var(--tcw-warning); }
|
|
2069
2173
|
.tcw-nav-icon.violet { background: #f1eaff; color: var(--tcw-violet); }
|
|
2070
2174
|
.tcw-nav-icon.slate { background: #eef2f6; color: var(--tcw-slate); }
|
|
2071
|
-
.tcw-sidebar-section {
|
|
2072
|
-
display: grid;
|
|
2073
|
-
gap: 8px;
|
|
2074
|
-
border-top: 1px solid var(--tcw-border);
|
|
2075
|
-
padding: 14px 6px 0;
|
|
2076
|
-
}
|
|
2077
|
-
.tcw-sidebar-section h2 {
|
|
2078
|
-
margin: 0;
|
|
2079
|
-
color: var(--tcw-muted);
|
|
2080
|
-
font-size: 12px;
|
|
2081
|
-
}
|
|
2082
|
-
.tcw-sidebar-section.compact p {
|
|
2083
|
-
margin: 0;
|
|
2084
|
-
color: var(--tcw-muted);
|
|
2085
|
-
font-size: 12px;
|
|
2086
|
-
line-height: 1.6;
|
|
2087
|
-
}
|
|
2088
|
-
.tcw-flow-list {
|
|
2089
|
-
display: grid;
|
|
2090
|
-
gap: 8px;
|
|
2091
|
-
margin: 0;
|
|
2092
|
-
padding: 0;
|
|
2093
|
-
list-style: none;
|
|
2094
|
-
color: var(--tcw-text);
|
|
2095
|
-
font-size: 12px;
|
|
2096
|
-
}
|
|
2097
|
-
.tcw-flow-list li {
|
|
2098
|
-
display: flex;
|
|
2099
|
-
gap: 8px;
|
|
2100
|
-
align-items: center;
|
|
2101
|
-
}
|
|
2102
|
-
.tcw-flow-list span {
|
|
2103
|
-
width: 7px;
|
|
2104
|
-
height: 7px;
|
|
2105
|
-
border-radius: 999px;
|
|
2106
|
-
background: var(--tcw-primary);
|
|
2107
|
-
}
|
|
2108
2175
|
.tcw-workspace {
|
|
2109
2176
|
display: grid;
|
|
2110
2177
|
grid-template-rows: auto 1fr;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chenchaolong/plugin-trade-compliance-workbench",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.46",
|
|
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",
|