@chenchaolong/plugin-trade-compliance-workbench 0.1.47 → 0.1.48
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.
|
@@ -194,15 +194,17 @@
|
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
async function searchSupplierHsCandidatesForForm() {
|
|
197
|
+
async function searchSupplierHsCandidatesForForm(page) {
|
|
198
198
|
if (!formDialog || formDialog.type !== 'supplier_product' || busy) return
|
|
199
199
|
const keyword = String(formDialog.hsCandidateKeyword || buildSupplierHsCandidateKeyword(formDialog.values) || '').trim()
|
|
200
200
|
if (!keyword) {
|
|
201
201
|
setFormDialog(Object.assign({}, formDialog, { hsCandidateError: '请输入商品名称、型号或海关编码后再查询。' }))
|
|
202
202
|
return
|
|
203
203
|
}
|
|
204
|
+
const nextPage = Math.max(1, Number(page) || 1)
|
|
204
205
|
setFormDialog(Object.assign({}, formDialog, {
|
|
205
206
|
hsCandidateKeyword: keyword,
|
|
207
|
+
hsCandidatePage: nextPage,
|
|
206
208
|
hsCandidateLoading: true,
|
|
207
209
|
hsCandidateError: '',
|
|
208
210
|
hsCandidateStatus: ''
|
|
@@ -210,20 +212,22 @@
|
|
|
210
212
|
try {
|
|
211
213
|
const response = await executeAction('search_hs_code', null, {
|
|
212
214
|
keywords: keyword,
|
|
213
|
-
page:
|
|
215
|
+
page: nextPage,
|
|
214
216
|
filterFailureCode: true,
|
|
215
217
|
displayChapter: false,
|
|
216
218
|
displayEnName: true
|
|
217
219
|
}, {})
|
|
218
220
|
assertActionSuccess(response)
|
|
219
221
|
const result = getActionDataPayload(response)
|
|
220
|
-
const candidates = Array.isArray(result && result.results) ? result.results
|
|
222
|
+
const candidates = Array.isArray(result && result.results) ? result.results : []
|
|
221
223
|
setFormDialog((current) => current ? Object.assign({}, current, {
|
|
222
224
|
hsCandidateKeyword: keyword,
|
|
225
|
+
hsCandidatePage: nextPage,
|
|
223
226
|
hsCandidateLoading: false,
|
|
224
227
|
hsCandidateError: '',
|
|
225
228
|
hsCandidateStatus: candidates.length ? 'pending_confirmation' : 'not_found',
|
|
226
|
-
hsCandidates: candidates
|
|
229
|
+
hsCandidates: candidates,
|
|
230
|
+
hsCandidatePagination: result && result.pagination ? result.pagination : null
|
|
227
231
|
}) : current)
|
|
228
232
|
} catch (error) {
|
|
229
233
|
setFormDialog((current) => current ? Object.assign({}, current, {
|
|
@@ -466,6 +470,8 @@
|
|
|
466
470
|
values: valuesFromItem(item.type, item),
|
|
467
471
|
hsCandidates: Array.isArray(merged.hsCodeCandidates) ? merged.hsCodeCandidates : [],
|
|
468
472
|
hsCandidateKeyword: merged.hsCodeLookupKeyword || buildSupplierHsCandidateKeyword(merged),
|
|
473
|
+
hsCandidatePage: 1,
|
|
474
|
+
hsCandidatePagination: null,
|
|
469
475
|
hsCandidateStatus: merged.hsCodeLookupStatus || '',
|
|
470
476
|
hsCandidateError: merged.hsCodeLookupError || '',
|
|
471
477
|
hsCandidateLoading: false
|
|
@@ -480,6 +486,8 @@
|
|
|
480
486
|
values: emptyFormValues(type),
|
|
481
487
|
hsCandidates: [],
|
|
482
488
|
hsCandidateKeyword: '',
|
|
489
|
+
hsCandidatePage: 1,
|
|
490
|
+
hsCandidatePagination: null,
|
|
483
491
|
hsCandidateStatus: '',
|
|
484
492
|
hsCandidateError: '',
|
|
485
493
|
hsCandidateLoading: false
|
|
@@ -1100,7 +1108,7 @@
|
|
|
1100
1108
|
const fields = formDialog.type === 'controlled_goods' ? controlledGoodsFormFields : supplierProductFormFields
|
|
1101
1109
|
const title = `${formDialog.mode === 'create' ? '新增' : '编辑'}${formDialog.type === 'controlled_goods' ? '管控商品' : '供应商商品'}`
|
|
1102
1110
|
return h('div', { className: 'tcw-modal-backdrop' },
|
|
1103
|
-
h('form', { className: 'tcw-modal tcw-form-modal', onSubmit: saveProductForm },
|
|
1111
|
+
h('form', { className: formDialog.type === 'supplier_product' ? 'tcw-modal tcw-form-modal tcw-form-modal-supplier' : 'tcw-modal tcw-form-modal', onSubmit: saveProductForm },
|
|
1104
1112
|
h('div', { className: 'tcw-modal-head' },
|
|
1105
1113
|
h('h2', null, title),
|
|
1106
1114
|
h('button', { type: 'button', className: 'tcw-icon-btn', onClick: () => setFormDialog(null) }, '×')
|
|
@@ -1119,6 +1127,7 @@
|
|
|
1119
1127
|
|
|
1120
1128
|
function renderSupplierHsCandidatePanel() {
|
|
1121
1129
|
const candidates = Array.isArray(formDialog.hsCandidates) ? formDialog.hsCandidates : []
|
|
1130
|
+
const pagination = formDialog.hsCandidatePagination || null
|
|
1122
1131
|
return h('section', { className: 'tcw-hs-candidate-panel' },
|
|
1123
1132
|
h('div', { className: 'tcw-subsection-head' },
|
|
1124
1133
|
h('div', null,
|
|
@@ -1132,23 +1141,46 @@
|
|
|
1132
1141
|
placeholder: '商品名称、型号或海关编码',
|
|
1133
1142
|
onChange: (event) => setFormDialog(Object.assign({}, formDialog, { hsCandidateKeyword: event.target.value }))
|
|
1134
1143
|
}),
|
|
1135
|
-
h('button', { type: 'button', className: 'tcw-mini-btn', disabled: busy || formDialog.hsCandidateLoading, onClick: searchSupplierHsCandidatesForForm }, formDialog.hsCandidateLoading ? '查询中' : '查询')
|
|
1144
|
+
h('button', { type: 'button', className: 'tcw-mini-btn', disabled: busy || formDialog.hsCandidateLoading, onClick: () => searchSupplierHsCandidatesForForm(1) }, formDialog.hsCandidateLoading ? '查询中' : '查询')
|
|
1136
1145
|
)
|
|
1137
1146
|
),
|
|
1138
1147
|
formDialog.hsCandidateError ? h('div', { className: 'tcw-error' }, formDialog.hsCandidateError) : null,
|
|
1139
|
-
candidates.length ?
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
h('
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1148
|
+
candidates.length ? h('div', { className: 'tcw-hs-candidate-result' },
|
|
1149
|
+
table(['编码', '商品名称', '英文名称', '单位', '退税率', '监管', '检验检疫', '操作'], candidates, (candidate) => [
|
|
1150
|
+
h('strong', { className: 'tcw-hs-code-text' }, value(candidate.code)),
|
|
1151
|
+
value(candidate.name),
|
|
1152
|
+
value(candidate.englishName),
|
|
1153
|
+
value(candidate.unit),
|
|
1154
|
+
value(candidate.taxRefundRate),
|
|
1155
|
+
value(candidate.regulatoryConditions),
|
|
1156
|
+
value(candidate.inspectionQuarantine),
|
|
1157
|
+
h('div', { className: 'tcw-row-actions' },
|
|
1158
|
+
h('button', { type: 'button', className: 'tcw-mini-btn', onClick: () => selectHsCandidate(candidate) }, '选用'),
|
|
1159
|
+
h('button', { type: 'button', className: 'tcw-mini-btn', disabled: !candidate.code && !candidate.detailUrl, onClick: () => loadHsCodeDetail(candidate) }, '详情')
|
|
1160
|
+
)
|
|
1161
|
+
], '暂无候选编码。'),
|
|
1162
|
+
renderSupplierHsCandidatePagination(pagination)
|
|
1163
|
+
) : empty('暂无候选编码,可调整关键词后查询。')
|
|
1164
|
+
)
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
function renderSupplierHsCandidatePagination(pagination) {
|
|
1168
|
+
if (!pagination || (!pagination.hasPrevious && !pagination.hasNext && (!pagination.pages || pagination.pages.length <= 1))) return null
|
|
1169
|
+
const pages = Array.isArray(pagination.pages) ? pagination.pages.filter((item) => item.page) : []
|
|
1170
|
+
const visiblePages = pages.filter((item, index, arr) => arr.findIndex((candidate) => candidate.page === item.page) === index).slice(0, 10)
|
|
1171
|
+
const currentPage = pagination.currentPage || formDialog.hsCandidatePage || 1
|
|
1172
|
+
return h('div', { className: 'tcw-pagination hs-code-pagination' },
|
|
1173
|
+
h('span', null, `第 ${currentPage} 页`),
|
|
1174
|
+
h('div', { className: 'tcw-page-buttons' },
|
|
1175
|
+
h('button', { className: 'tcw-mini-btn', disabled: formDialog.hsCandidateLoading || !pagination.hasPrevious, onClick: () => searchSupplierHsCandidatesForForm(currentPage - 1) }, '上一页'),
|
|
1176
|
+
visiblePages.map((item) => h('button', {
|
|
1177
|
+
key: item.page,
|
|
1178
|
+
className: item.current ? 'tcw-mini-btn active' : 'tcw-mini-btn',
|
|
1179
|
+
disabled: formDialog.hsCandidateLoading || item.current,
|
|
1180
|
+
onClick: () => searchSupplierHsCandidatesForForm(item.page)
|
|
1181
|
+
}, String(item.page))),
|
|
1182
|
+
h('button', { className: 'tcw-mini-btn', disabled: formDialog.hsCandidateLoading || !pagination.hasNext, onClick: () => searchSupplierHsCandidatesForForm(currentPage + 1) }, '下一页')
|
|
1183
|
+
)
|
|
1152
1184
|
)
|
|
1153
1185
|
}
|
|
1154
1186
|
|
|
@@ -1950,6 +1982,12 @@ button, input, textarea, select { font: inherit; letter-spacing: 0; }
|
|
|
1950
1982
|
.tcw-modal-backdrop { position: fixed; inset: 0; z-index: 10; display: grid; place-items: center; background: rgba(15, 23, 42, .32); padding: 20px; }
|
|
1951
1983
|
.tcw-modal { display: grid; gap: 12px; width: min(900px, 100%); max-height: calc(100vh - 48px); overflow: auto; border: 1px solid var(--tcw-border); border-radius: 8px; background: var(--tcw-card); padding: 16px; box-shadow: 0 18px 48px rgba(15, 23, 42, .18); }
|
|
1952
1984
|
.tcw-form-modal { width: min(960px, 100%); }
|
|
1985
|
+
.tcw-form-modal-supplier {
|
|
1986
|
+
width: min(1180px, calc(100vw - 96px));
|
|
1987
|
+
max-height: min(760px, calc(100vh - 56px));
|
|
1988
|
+
gap: 10px;
|
|
1989
|
+
padding: 14px;
|
|
1990
|
+
}
|
|
1953
1991
|
.tcw-confirm-modal { width: min(480px, 100%); }
|
|
1954
1992
|
.tcw-hs-detail-modal { width: min(980px, 100%); }
|
|
1955
1993
|
.tcw-modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
|
|
@@ -1959,6 +1997,61 @@ button, input, textarea, select { font: inherit; letter-spacing: 0; }
|
|
|
1959
1997
|
.tcw-edit-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
|
|
1960
1998
|
.tcw-edit-grid-two { grid-template-columns: repeat(2, minmax(260px, 1fr)); }
|
|
1961
1999
|
.tcw-field-wide { grid-column: 1 / -1; }
|
|
2000
|
+
.tcw-form-modal-supplier .tcw-modal-head h2 { font-size: 17px; }
|
|
2001
|
+
.tcw-form-modal-supplier .tcw-edit-grid-two {
|
|
2002
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
2003
|
+
gap: 8px 12px;
|
|
2004
|
+
}
|
|
2005
|
+
.tcw-form-modal-supplier .tcw-field { gap: 4px; }
|
|
2006
|
+
.tcw-form-modal-supplier .tcw-field span { font-size: 11px; }
|
|
2007
|
+
.tcw-form-modal-supplier .tcw-field input,
|
|
2008
|
+
.tcw-form-modal-supplier .tcw-field select {
|
|
2009
|
+
min-height: 32px;
|
|
2010
|
+
padding: 6px 9px;
|
|
2011
|
+
}
|
|
2012
|
+
.tcw-form-modal-supplier .tcw-field textarea {
|
|
2013
|
+
min-height: 58px;
|
|
2014
|
+
padding: 7px 9px;
|
|
2015
|
+
}
|
|
2016
|
+
.tcw-form-modal-supplier .tcw-field-wide {
|
|
2017
|
+
grid-column: span 3;
|
|
2018
|
+
}
|
|
2019
|
+
.tcw-form-modal-supplier .tcw-hs-candidate-panel {
|
|
2020
|
+
display: grid;
|
|
2021
|
+
grid-template-columns: minmax(0, 1fr) minmax(320px, .55fr);
|
|
2022
|
+
gap: 10px;
|
|
2023
|
+
align-items: start;
|
|
2024
|
+
border-top: 1px solid var(--tcw-border);
|
|
2025
|
+
padding-top: 10px;
|
|
2026
|
+
}
|
|
2027
|
+
.tcw-form-modal-supplier .tcw-hs-candidate-panel > .tcw-subsection-head {
|
|
2028
|
+
align-items: center;
|
|
2029
|
+
}
|
|
2030
|
+
.tcw-form-modal-supplier .tcw-hs-candidate-panel > .tcw-table-wrap,
|
|
2031
|
+
.tcw-form-modal-supplier .tcw-hs-candidate-panel > .tcw-empty,
|
|
2032
|
+
.tcw-form-modal-supplier .tcw-hs-candidate-panel > .tcw-error {
|
|
2033
|
+
grid-column: 1 / -1;
|
|
2034
|
+
max-height: 210px;
|
|
2035
|
+
overflow: auto;
|
|
2036
|
+
}
|
|
2037
|
+
.tcw-form-modal-supplier .tcw-hs-candidate-result {
|
|
2038
|
+
display: grid;
|
|
2039
|
+
gap: 8px;
|
|
2040
|
+
grid-column: 1 / -1;
|
|
2041
|
+
}
|
|
2042
|
+
.tcw-form-modal-supplier .tcw-hs-candidate-result .tcw-table-wrap {
|
|
2043
|
+
max-height: 210px;
|
|
2044
|
+
}
|
|
2045
|
+
.tcw-form-modal-supplier .tcw-hs-candidate-search {
|
|
2046
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
2047
|
+
}
|
|
2048
|
+
.tcw-form-modal-supplier .tcw-modal-actions {
|
|
2049
|
+
position: sticky;
|
|
2050
|
+
bottom: -14px;
|
|
2051
|
+
border-top: 1px solid var(--tcw-border);
|
|
2052
|
+
background: var(--tcw-card);
|
|
2053
|
+
padding-top: 10px;
|
|
2054
|
+
}
|
|
1962
2055
|
.tcw-confirm-text { margin: 0; color: var(--tcw-text); font-size: 14px; line-height: 1.7; }
|
|
1963
2056
|
.tcw-detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
|
|
1964
2057
|
.tcw-detail-field { display: grid; grid-template-columns: 108px minmax(0, 1fr); gap: 8px; align-items: start; border: 1px solid var(--tcw-border); border-radius: 6px; background: var(--tcw-soft); padding: 8px 10px; }
|
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.48",
|
|
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",
|