@chenchaolong/plugin-trade-compliance-workbench 0.1.22 → 0.1.23
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.
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
const [editItem, setEditItem] = React.useState(null)
|
|
85
85
|
const [editText, setEditText] = React.useState('')
|
|
86
86
|
const pollingRef = React.useRef(null)
|
|
87
|
+
const fileInputsRef = React.useRef({})
|
|
87
88
|
|
|
88
89
|
React.useEffect(() => {
|
|
89
90
|
window.__tradeComplianceSetContext = (nextContext) => {
|
|
@@ -133,24 +134,38 @@
|
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
async function handleFile(actionKey, file) {
|
|
136
|
-
|
|
137
|
+
debugUpload('file change received', { actionKey, hasFile: !!file, busy })
|
|
138
|
+
if (!file) {
|
|
139
|
+
debugUpload('file selection was empty', { actionKey })
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
if (busy) {
|
|
143
|
+
debugUpload('file upload ignored because workbench is busy', { actionKey, fileName: file.name })
|
|
144
|
+
return
|
|
145
|
+
}
|
|
137
146
|
const expectedType = reviewTypeForUploadAction(actionKey)
|
|
138
147
|
const previousCount = countReviewItemsByType(data.reviewItems, expectedType)
|
|
139
148
|
setBusy(true)
|
|
140
149
|
try {
|
|
150
|
+
debugUpload('uploading file to assistant storage', { actionKey, fileName: file.name, size: file.size, type: file.type })
|
|
141
151
|
const uploadResponse = await uploadAgentFile(file)
|
|
142
152
|
const agentFile = getActionDataPayload(uploadResponse)
|
|
153
|
+
debugUpload('assistant storage upload completed', { actionKey, fileName: file.name, hasAgentFile: !!agentFile })
|
|
154
|
+
debugUpload('executing plugin file action', { actionKey, fileName: file.name })
|
|
143
155
|
const response = await executeFileAction(actionKey, file, Object.assign(
|
|
144
156
|
{ name: file.name, fileName: file.name },
|
|
145
157
|
toAgentFileInput(agentFile)
|
|
146
158
|
), {})
|
|
147
159
|
assertActionSuccess(response)
|
|
148
160
|
const actionData = getActionDataPayload(response)
|
|
161
|
+
debugUpload('dispatching assistant commands', { actionKey, fileName: file.name })
|
|
149
162
|
const dispatched = await dispatchAssistantCommands(actionData)
|
|
163
|
+
debugUpload('file workflow completed', { actionKey, fileName: file.name, dispatched })
|
|
150
164
|
showNotice(dispatched ? '文件已发送给智能体解析,识别结果会进入待审核列表。' : '文件已登记,等待识别结果。', 'success')
|
|
151
165
|
await reload()
|
|
152
166
|
if (dispatched && expectedType) startRecognitionPolling(expectedType, previousCount, readExpectedCount(actionData))
|
|
153
167
|
} catch (error) {
|
|
168
|
+
debugUpload('file workflow failed', { actionKey, fileName: file.name, message: getErrorMessage(error) })
|
|
154
169
|
showNotice(getErrorMessage(error), 'error')
|
|
155
170
|
} finally {
|
|
156
171
|
setBusy(false)
|
|
@@ -809,20 +824,43 @@
|
|
|
809
824
|
}
|
|
810
825
|
|
|
811
826
|
function uploadButton(actionKey, label) {
|
|
812
|
-
return h(
|
|
827
|
+
return h(React.Fragment, null,
|
|
813
828
|
h('input', {
|
|
829
|
+
ref: (node) => {
|
|
830
|
+
if (node) fileInputsRef.current[actionKey] = node
|
|
831
|
+
else delete fileInputsRef.current[actionKey]
|
|
832
|
+
},
|
|
833
|
+
className: 'tcw-upload-input',
|
|
814
834
|
type: 'file',
|
|
815
835
|
disabled: busy,
|
|
816
836
|
onChange: (event) => {
|
|
817
837
|
const file = event.target.files && event.target.files[0]
|
|
818
838
|
event.target.value = ''
|
|
839
|
+
debugUpload('file picker returned', { actionKey, hasFile: !!file, fileName: file && file.name, size: file && file.size })
|
|
819
840
|
handleFile(actionKey, file)
|
|
820
841
|
}
|
|
821
842
|
}),
|
|
822
|
-
h('
|
|
843
|
+
h('button', {
|
|
844
|
+
type: 'button',
|
|
845
|
+
className: 'tcw-upload',
|
|
846
|
+
disabled: busy,
|
|
847
|
+
onClick: () => openFilePicker(actionKey)
|
|
848
|
+
}, label)
|
|
823
849
|
)
|
|
824
850
|
}
|
|
825
851
|
|
|
852
|
+
function openFilePicker(actionKey) {
|
|
853
|
+
debugUpload('upload button clicked', { actionKey, busy })
|
|
854
|
+
if (busy) return
|
|
855
|
+
const input = fileInputsRef.current[actionKey]
|
|
856
|
+
if (!input) {
|
|
857
|
+
debugUpload('file input was not registered', { actionKey })
|
|
858
|
+
showNotice('上传控件未准备好,请刷新页面后重试。', 'error')
|
|
859
|
+
return
|
|
860
|
+
}
|
|
861
|
+
input.click()
|
|
862
|
+
}
|
|
863
|
+
|
|
826
864
|
function updateForm(key) {
|
|
827
865
|
return (event) => setForm(Object.assign({}, form, { [key]: event.target.value }))
|
|
828
866
|
}
|
|
@@ -1013,6 +1051,12 @@
|
|
|
1013
1051
|
return error && error.message ? error.message : String(error || '操作失败')
|
|
1014
1052
|
}
|
|
1015
1053
|
|
|
1054
|
+
function debugUpload(message, details) {
|
|
1055
|
+
if (typeof console !== 'undefined' && typeof console.debug === 'function') {
|
|
1056
|
+
console.debug('[trade-compliance-workbench:upload] ' + message, details || {})
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1016
1060
|
function filterItems(items, query, keys) {
|
|
1017
1061
|
const keyword = String(query || '').trim().toLowerCase()
|
|
1018
1062
|
if (!keyword) return items
|
|
@@ -1167,7 +1211,7 @@ button, input { font: inherit; letter-spacing: 0; }
|
|
|
1167
1211
|
.tcw-btn-danger { border-color: color-mix(in srgb, var(--tcw-danger) 35%, var(--tcw-border)); background: color-mix(in srgb, var(--tcw-danger) 6%, var(--tcw-card)); color: var(--tcw-danger); }
|
|
1168
1212
|
.tcw-wide { width: 100%; }
|
|
1169
1213
|
.tcw-upload { border-style: dashed; border-color: color-mix(in srgb, var(--tcw-primary) 42%, var(--tcw-border)); color: var(--tcw-primary); font-weight: 800; }
|
|
1170
|
-
.tcw-upload
|
|
1214
|
+
.tcw-upload-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
|
|
1171
1215
|
.tcw-tabs { display: flex; gap: 6px; overflow-x: auto; border-bottom: 1px solid var(--tcw-border); padding: 0 2px; }
|
|
1172
1216
|
.tcw-tab { min-height: 34px; border: 0; border-bottom: 3px solid transparent; background: transparent; color: var(--tcw-muted); padding: 7px 12px; cursor: pointer; font-weight: 900; }
|
|
1173
1217
|
.tcw-tab.active { border-color: var(--tcw-primary); color: var(--tcw-primary); }
|
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.23",
|
|
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",
|