@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
- if (!file || busy) return
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('label', { className: 'tcw-upload' },
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('span', null, label)
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 input { display: none; }
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.22",
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",