@gientech/modual 1.9.4-fix.1 → 1.9.4-fix.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.
Files changed (432) hide show
  1. package/package.json +43 -106
  2. package/.editorconfig +0 -38
  3. package/.prettierignore +0 -16
  4. package/.prettierrc +0 -17
  5. package/USAGE.md +0 -247
  6. package/bash.exe.stackdump +0 -40
  7. package/components.json +0 -21
  8. package/dist/README.md +0 -643
  9. package/dist/package.json +0 -68
  10. package/doc_assets/2.png +0 -0
  11. package/doc_assets/demo.md +0 -27
  12. package/doc_assets/demos/dist-app/assets/index.Dh-ZAS9Z.css +0 -2
  13. package/doc_assets/demos/dist-app/assets/index.Dv8KVW18.js +0 -23699
  14. package/doc_assets/demos/dist-app/assets/index.Dv8KVW18.js.map +0 -1
  15. package/doc_assets/demos/dist-app/index.html +0 -14
  16. package/doc_assets/demos/dist-app/vite.svg +0 -1
  17. package/doc_assets/images/1.png +0 -0
  18. package/doc_assets/images/3.png +0 -0
  19. package/doc_assets/images/component-screenshot.png +0 -1
  20. package/doc_assets/install.md +0 -5
  21. package/doc_assets//346/226/271/346/241/210//344/274/230/345/214/226/346/226/271/346/241/210-/345/244/232/344/274/232/350/257/235SSE/350/277/236/346/216/245/347/256/241/347/220/206.md +0 -504
  22. package/eslint.config.js +0 -92
  23. package/index.html +0 -13
  24. package/package.json.demo-backup +0 -109
  25. package/postcss.config.cjs +0 -19
  26. package/public/icons/answerAwartar.png +0 -0
  27. package/public/icons/docx-file.png +0 -0
  28. package/public/icons/folder.png +0 -0
  29. package/public/icons/html.png +0 -0
  30. package/public/icons/image.png +0 -0
  31. package/public/icons/jpg-file.png +0 -0
  32. package/public/icons/json.png +0 -0
  33. package/public/icons/md.png +0 -0
  34. package/public/icons/pdf.png +0 -0
  35. package/public/icons/pptx.png +0 -0
  36. package/public/icons/questionAwartar.png +0 -0
  37. package/public/icons/sheets.png +0 -0
  38. package/public/icons/txt.png +0 -0
  39. package/public/icons/xlsx.png +0 -0
  40. package/public/vite.svg +0 -1
  41. package/public/worker/pdf.worker.min.js +0 -22
  42. package/rag/assets/Doris.3ZRHc3Fu.png +0 -0
  43. package/rag/assets/PostgreSQL.DuLqLAFX.png +0 -0
  44. package/rag/assets/SQLServer.CWyNu24v.png +0 -0
  45. package/rag/assets/empty.BfkDKJsb.png +0 -0
  46. package/rag/assets/homeBg.Mr_kGuA9.png +0 -0
  47. package/rag/assets/index.Bd0tNzw0.js +0 -2797
  48. package/rag/assets/index.D6t67hlu.css +0 -1
  49. package/rag/assets/left.KBHV5h7q.jpg +0 -0
  50. package/rag/assets/logoImg.Gmp_tdkD.png +0 -0
  51. package/rag/assets/worker-BbpylX7l.DptbXke_.js +0 -13
  52. package/rag/icons/answerAwartar.png +0 -0
  53. package/rag/icons/docx-file.png +0 -0
  54. package/rag/icons/folder.png +0 -0
  55. package/rag/icons/html.png +0 -0
  56. package/rag/icons/image.png +0 -0
  57. package/rag/icons/jpg-file.png +0 -0
  58. package/rag/icons/json.png +0 -0
  59. package/rag/icons/md.png +0 -0
  60. package/rag/icons/pdf.png +0 -0
  61. package/rag/icons/pptx.png +0 -0
  62. package/rag/icons/questionAwartar.png +0 -0
  63. package/rag/icons/sheets.png +0 -0
  64. package/rag/icons/txt.png +0 -0
  65. package/rag/icons/xlsx.png +0 -0
  66. package/scripts/README.md +0 -133
  67. package/scripts/build-demo.js +0 -88
  68. package/scripts/decrypt-api-key.js +0 -95
  69. package/scripts/demo-selector.js +0 -216
  70. package/scripts/dev-demo.js +0 -76
  71. package/scripts/preview-demo.js +0 -130
  72. package/scripts/run-demo.bat +0 -34
  73. package/src/assets/img/close.png +0 -0
  74. package/src/assets/img/database.png +0 -0
  75. package/src/assets/img/downArrow.png +0 -0
  76. package/src/assets/img/downLoad.png +0 -0
  77. package/src/assets/img/excel.png +0 -0
  78. package/src/assets/img/graphIcon.png +0 -0
  79. package/src/assets/img/img.png +0 -0
  80. package/src/assets/img/pdf.png +0 -0
  81. package/src/assets/img/ppt.png +0 -0
  82. package/src/assets/img/singleQa.png +0 -0
  83. package/src/assets/img/txt.png +0 -0
  84. package/src/assets/img/webSearch.png +0 -0
  85. package/src/assets/img/word.png +0 -0
  86. package/src/assets/login/homeBg.png +0 -0
  87. package/src/assets/login/left.jpg +0 -0
  88. package/src/assets/login/logoImg.png +0 -0
  89. package/src/examples/ConversationAssistantPage/index.tsx +0 -41
  90. package/src/examples/Demo/index.tsx +0 -12
  91. package/src/examples/LoginPage/index.tsx +0 -18
  92. package/src/examples/chat/components/DrawerGraphPreview.tsx +0 -78
  93. package/src/examples/chat/index.tsx +0 -162
  94. package/src/examples/chat/logo03.png +0 -0
  95. package/src/examples/gientechStreamFilesReader/index.tsx +0 -951
  96. package/src/examples/headlessChat/index.tsx +0 -218
  97. package/src/examples/ragDatabaseDataPage/index.tsx +0 -40
  98. package/src/examples/ragDatabaseIdPage/index.tsx +0 -47
  99. package/src/examples/ragDatabasePage/index.tsx +0 -36
  100. package/src/examples/ragModelManagePage/index.tsx +0 -37
  101. package/src/examples/ragSearchPage/index.tsx +0 -0
  102. package/src/examples/ragSensitiveWordsPage/index.tsx +0 -32
  103. package/src/examples/streamFiles/index.tsx +0 -417
  104. package/src/lib_enter.ts +0 -43
  105. package/src/main.tsx +0 -5
  106. package/src/main.tsx.backup +0 -5
  107. package/src/modules/assistantConfig/assets/databse.svg +0 -6
  108. package/src/modules/assistantConfig/assets/empty.png +0 -0
  109. package/src/modules/assistantConfig/assets/graph.svg +0 -4
  110. package/src/modules/assistantConfig/assets/knowledge.svg +0 -4
  111. package/src/modules/assistantConfig/assets/sensitive.svg +0 -5
  112. package/src/modules/assistantConfig/components/Database.tsx +0 -171
  113. package/src/modules/assistantConfig/components/Graph.tsx +0 -177
  114. package/src/modules/assistantConfig/components/Knowledge.tsx +0 -276
  115. package/src/modules/assistantConfig/components/NotFoundContent.tsx +0 -21
  116. package/src/modules/assistantConfig/components/Paragraph.tsx +0 -51
  117. package/src/modules/assistantConfig/components/ParamsItem.tsx +0 -39
  118. package/src/modules/assistantConfig/components/ResourceBinderItem.tsx +0 -133
  119. package/src/modules/assistantConfig/components/SearchableSelector.tsx +0 -500
  120. package/src/modules/assistantConfig/components/Sensitive.tsx +0 -221
  121. package/src/modules/assistantConfig/components/SliderInput.tsx +0 -65
  122. package/src/modules/assistantConfig/constants.tsx +0 -75
  123. package/src/modules/assistantConfig/index.tsx +0 -706
  124. package/src/modules/assistantConfig/server.ts +0 -262
  125. package/src/modules/chat/Conversations/Item.tsx +0 -167
  126. package/src/modules/chat/Conversations/List.tsx +0 -210
  127. package/src/modules/chat/Conversations/groupByTime.ts +0 -39
  128. package/src/modules/chat/Conversations/index.tsx +0 -252
  129. package/src/modules/chat/ReferenceBar.tsx +0 -622
  130. package/src/modules/chat/constants.tsx +0 -56
  131. package/src/modules/chat/data.txt +0 -82
  132. package/src/modules/chat/index.tsx +0 -2087
  133. package/src/modules/chat/referenceCom/DeleteModal.tsx +0 -75
  134. package/src/modules/chat/referenceCom/DrawerContent.tsx +0 -136
  135. package/src/modules/chat/referenceCom/DrawerDatabase.tsx +0 -102
  136. package/src/modules/chat/referenceCom/DrawerGraphPreview.tsx +0 -86
  137. package/src/modules/chat/referenceCom/DrawerPreview.tsx +0 -73
  138. package/src/modules/chat/referenceCom/DrawerTitle.tsx +0 -26
  139. package/src/modules/chat/referenceCom/RenameModal.tsx +0 -86
  140. package/src/modules/chat/referenceCom/TagCom.tsx +0 -30
  141. package/src/modules/chat/style.less +0 -3
  142. package/src/modules/chat/types.ts +0 -17
  143. package/src/modules/chat/utils/index.ts +0 -348
  144. package/src/modules/database/CreateModal.tsx +0 -403
  145. package/src/modules/database/assets/Doris.png +0 -0
  146. package/src/modules/database/assets/PostgreSQL.png +0 -0
  147. package/src/modules/database/assets/SQLServer.png +0 -0
  148. package/src/modules/database/assets/database.svg +0 -11
  149. package/src/modules/database/assets/database_add.svg +0 -53
  150. package/src/modules/database/assets/database_connect.svg +0 -66
  151. package/src/modules/database/assets/database_upload.svg +0 -29
  152. package/src/modules/database/assets/empty.png +0 -0
  153. package/src/modules/database/assets/mysql.svg +0 -14
  154. package/src/modules/database/index.tsx +0 -477
  155. package/src/modules/database/server.ts +0 -196
  156. package/src/modules/databaseId/CustomCom.tsx +0 -156
  157. package/src/modules/databaseId/EditConfig.tsx +0 -280
  158. package/src/modules/databaseId/UploadDrawer.tsx +0 -535
  159. package/src/modules/databaseId/assets/aiOptimize.svg +0 -10
  160. package/src/modules/databaseId/assets/empty.png +0 -0
  161. package/src/modules/databaseId/assets/template.svg +0 -6
  162. package/src/modules/databaseId/assets/upload.svg +0 -9
  163. package/src/modules/databaseId/assets/useTemp.svg +0 -6
  164. package/src/modules/databaseId/index.tsx +0 -769
  165. package/src/modules/databaseId/server.ts +0 -286
  166. package/src/modules/databaseId/style.css +0 -5
  167. package/src/modules/databaseTable/EditRowDrawer.tsx +0 -124
  168. package/src/modules/databaseTable/index.tsx +0 -359
  169. package/src/modules/databaseTable/server.ts +0 -180
  170. package/src/modules/headlessChat/ReferenceBar.tsx +0 -783
  171. package/src/modules/headlessChat/constants.tsx +0 -32
  172. package/src/modules/headlessChat/index.tsx +0 -1411
  173. package/src/modules/headlessChat/referenceCom/DeleteModal.tsx +0 -75
  174. package/src/modules/headlessChat/referenceCom/DrawerContent.tsx +0 -136
  175. package/src/modules/headlessChat/referenceCom/DrawerDatabase.tsx +0 -102
  176. package/src/modules/headlessChat/referenceCom/DrawerGraphPreview.tsx +0 -86
  177. package/src/modules/headlessChat/referenceCom/DrawerPreview.tsx +0 -73
  178. package/src/modules/headlessChat/referenceCom/DrawerTitle.tsx +0 -26
  179. package/src/modules/headlessChat/referenceCom/RenameModal.tsx +0 -86
  180. package/src/modules/headlessChat/referenceCom/TagCom.tsx +0 -30
  181. package/src/modules/headlessChat/style.less +0 -3
  182. package/src/modules/headlessChat/types.ts +0 -23
  183. package/src/modules/headlessChat/utils/index.ts +0 -348
  184. package/src/modules/login/components/Login/LoginBox/index.tsx +0 -102
  185. package/src/modules/login/components/Login/RegisterBox/index.tsx +0 -180
  186. package/src/modules/login/components/Login/index.tsx +0 -100
  187. package/src/modules/login/index.tsx +0 -106
  188. package/src/modules/login/style.css +0 -3
  189. package/src/modules/login/useServices.ts +0 -53
  190. package/src/modules/login/utils.ts +0 -42
  191. package/src/modules/modelManage/ConfigDrawer.tsx +0 -249
  192. package/src/modules/modelManage/ReplaceModal.tsx +0 -124
  193. package/src/modules/modelManage/assets/empty.png +0 -0
  194. package/src/modules/modelManage/const.ts +0 -51
  195. package/src/modules/modelManage/index.tsx +0 -599
  196. package/src/modules/modelManage/server.ts +0 -223
  197. package/src/modules/nodegraph/index.tsx +0 -1
  198. package/src/modules/search/assets/Icon-history.svg +0 -8
  199. package/src/modules/search/assets/answerAwartar.png +0 -0
  200. package/src/modules/search/assets/doc.png +0 -0
  201. package/src/modules/search/assets/genera.gif +0 -0
  202. package/src/modules/search/assets/icon-robot.svg +0 -9
  203. package/src/modules/search/assets/icon-search-bar.svg +0 -14
  204. package/src/modules/search/assets/icon-sub-title.svg +0 -3
  205. package/src/modules/search/assets/icon-title.svg +0 -9
  206. package/src/modules/search/assets/icon-zoomOut.svg +0 -9
  207. package/src/modules/search/assets/iconAi.svg +0 -9
  208. package/src/modules/search/assets/pdf.png +0 -0
  209. package/src/modules/search/assets/ppt.png +0 -0
  210. package/src/modules/search/assets/search.svg +0 -3
  211. package/src/modules/search/assets/selected.svg +0 -4
  212. package/src/modules/search/assets/txt.png +0 -0
  213. package/src/modules/search/assets/xls.png +0 -0
  214. package/src/modules/search/components/AssisSelect.tsx +0 -137
  215. package/src/modules/search/components/Editor/ChatViewEditor.tsx +0 -261
  216. package/src/modules/search/components/Editor/aichat.css +0 -1
  217. package/src/modules/search/components/Editor/constant.ts +0 -13
  218. package/src/modules/search/components/Editor/index.tsx +0 -113
  219. package/src/modules/search/components/Editor/plugins/autofomatRules.ts +0 -332
  220. package/src/modules/search/components/Editor/plugins/convertImgPlugins.tsx +0 -20
  221. package/src/modules/search/components/Editor/plugins/createIndexes.tsx +0 -38
  222. package/src/modules/search/components/Editor/plugins/displayer.ts +0 -298
  223. package/src/modules/search/components/Editor/plugins/imageClick.tsx +0 -32
  224. package/src/modules/search/components/Editor/plugins/myplugin.tsx +0 -98
  225. package/src/modules/search/components/Editor/ui/avatar.tsx +0 -19
  226. package/src/modules/search/components/Editor/ui/blockquote-element.tsx +0 -21
  227. package/src/modules/search/components/Editor/ui/button.tsx +0 -58
  228. package/src/modules/search/components/Editor/ui/calendar.tsx +0 -68
  229. package/src/modules/search/components/Editor/ui/caption.tsx +0 -46
  230. package/src/modules/search/components/Editor/ui/checkbox.tsx +0 -27
  231. package/src/modules/search/components/Editor/ui/code-block-combobox.tsx +0 -188
  232. package/src/modules/search/components/Editor/ui/code-block-element.css +0 -434
  233. package/src/modules/search/components/Editor/ui/code-block-element.tsx +0 -39
  234. package/src/modules/search/components/Editor/ui/code-leaf.tsx +0 -24
  235. package/src/modules/search/components/Editor/ui/code-line-element.tsx +0 -10
  236. package/src/modules/search/components/Editor/ui/code-syntax-leaf.tsx +0 -21
  237. package/src/modules/search/components/Editor/ui/column-element.tsx +0 -30
  238. package/src/modules/search/components/Editor/ui/column-group-element.tsx +0 -94
  239. package/src/modules/search/components/Editor/ui/command.tsx +0 -75
  240. package/src/modules/search/components/Editor/ui/comment-avatar.tsx +0 -22
  241. package/src/modules/search/components/Editor/ui/comment-create-form.tsx +0 -37
  242. package/src/modules/search/components/Editor/ui/comment-item.tsx +0 -74
  243. package/src/modules/search/components/Editor/ui/comment-leaf.tsx +0 -49
  244. package/src/modules/search/components/Editor/ui/comment-more-dropdown.tsx +0 -42
  245. package/src/modules/search/components/Editor/ui/comment-reply-items.tsx +0 -22
  246. package/src/modules/search/components/Editor/ui/comment-resolve-button.tsx +0 -32
  247. package/src/modules/search/components/Editor/ui/comment-value.tsx +0 -34
  248. package/src/modules/search/components/Editor/ui/comments-popover.tsx +0 -63
  249. package/src/modules/search/components/Editor/ui/date-element.tsx +0 -83
  250. package/src/modules/search/components/Editor/ui/dialog.tsx +0 -63
  251. package/src/modules/search/components/Editor/ui/draggable.tsx +0 -177
  252. package/src/modules/search/components/Editor/ui/dropdown-menu.tsx +0 -180
  253. package/src/modules/search/components/Editor/ui/emoji-input-element.tsx +0 -85
  254. package/src/modules/search/components/Editor/ui/excalidraw-element.tsx +0 -28
  255. package/src/modules/search/components/Editor/ui/fixed-toolbar-buttons.tsx +0 -76
  256. package/src/modules/search/components/Editor/ui/fixed-toolbar.tsx +0 -8
  257. package/src/modules/search/components/Editor/ui/floating-toolbar-buttons.tsx +0 -51
  258. package/src/modules/search/components/Editor/ui/floating-toolbar.tsx +0 -77
  259. package/src/modules/search/components/Editor/ui/heading-element.tsx +0 -48
  260. package/src/modules/search/components/Editor/ui/highlight-leaf.tsx +0 -17
  261. package/src/modules/search/components/Editor/ui/hr-element.tsx +0 -30
  262. package/src/modules/search/components/Editor/ui/icons.tsx +0 -267
  263. package/src/modules/search/components/Editor/ui/image-element.tsx +0 -74
  264. package/src/modules/search/components/Editor/ui/inline-combobox.tsx +0 -368
  265. package/src/modules/search/components/Editor/ui/input.tsx +0 -25
  266. package/src/modules/search/components/Editor/ui/insert-dropdown-menu.tsx +0 -218
  267. package/src/modules/search/components/Editor/ui/kbd-leaf.tsx +0 -20
  268. package/src/modules/search/components/Editor/ui/link-element.tsx +0 -29
  269. package/src/modules/search/components/Editor/ui/link-floating-toolbar.tsx +0 -161
  270. package/src/modules/search/components/Editor/ui/list-element.tsx +0 -30
  271. package/src/modules/search/components/Editor/ui/mark-toolbar-button.tsx +0 -24
  272. package/src/modules/search/components/Editor/ui/media-embed-element.tsx +0 -133
  273. package/src/modules/search/components/Editor/ui/media-popover.tsx +0 -97
  274. package/src/modules/search/components/Editor/ui/mention-element.tsx +0 -43
  275. package/src/modules/search/components/Editor/ui/mention-input-element.tsx +0 -141
  276. package/src/modules/search/components/Editor/ui/mode-dropdown-menu.tsx +0 -93
  277. package/src/modules/search/components/Editor/ui/more-dropdown-menu.tsx +0 -67
  278. package/src/modules/search/components/Editor/ui/paragraph-element.tsx +0 -4
  279. package/src/modules/search/components/Editor/ui/placeholder.tsx +0 -52
  280. package/src/modules/search/components/Editor/ui/popover.tsx +0 -32
  281. package/src/modules/search/components/Editor/ui/resizable.tsx +0 -66
  282. package/src/modules/search/components/Editor/ui/separator.tsx +0 -25
  283. package/src/modules/search/components/Editor/ui/style.less +0 -12
  284. package/src/modules/search/components/Editor/ui/table-cell-element.tsx +0 -143
  285. package/src/modules/search/components/Editor/ui/table-element.tsx +0 -243
  286. package/src/modules/search/components/Editor/ui/table-row-element.tsx +0 -22
  287. package/src/modules/search/components/Editor/ui/tableValue.tsx +0 -135
  288. package/src/modules/search/components/Editor/ui/todo-list-element.tsx +0 -43
  289. package/src/modules/search/components/Editor/ui/toggle-element.tsx +0 -31
  290. package/src/modules/search/components/Editor/ui/toolbar.tsx +0 -157
  291. package/src/modules/search/components/Editor/ui/tooltip.tsx +0 -65
  292. package/src/modules/search/components/Editor/ui/turn-into-dropdown-menu.tsx +0 -160
  293. package/src/modules/search/components/Editor/ui/with-draggables.tsx +0 -175
  294. package/src/modules/search/components/FileList.tsx +0 -287
  295. package/src/modules/search/components/ImageGroupView/index.tsx +0 -85
  296. package/src/modules/search/components/ResultContent.tsx +0 -232
  297. package/src/modules/search/components/SearchInput.tsx +0 -232
  298. package/src/modules/search/components/SearchLanding.tsx +0 -74
  299. package/src/modules/search/components/SearchView.tsx +0 -563
  300. package/src/modules/search/components/SimpleEditor.tsx +0 -158
  301. package/src/modules/search/components/SimpleFileList.tsx +0 -215
  302. package/src/modules/search/index.tsx +0 -10
  303. package/src/modules/search/reademe.md +0 -1
  304. package/src/modules/search/servers/apis.tsx +0 -19
  305. package/src/modules/search/servers/index.ts +0 -184
  306. package/src/modules/search/style.less +0 -503
  307. package/src/modules/search/type.ts +0 -22
  308. package/src/modules/search/utils.ts +0 -34
  309. package/src/modules/sensitive/index.tsx +0 -313
  310. package/src/modules/sensitive/server.ts +0 -122
  311. package/src/modules/streamFilesReader/GientechStreamReader.tsx +0 -1625
  312. package/src/modules/streamFilesReader/components/Header/Toolbar.tsx +0 -0
  313. package/src/modules/streamFilesReader/components/Header/index.tsx +0 -297
  314. package/src/modules/streamFilesReader/index.tsx +0 -3
  315. package/src/style.css +0 -6
  316. package/src/type.d.ts +0 -0
  317. package/src/utils/commonFn.tsx +0 -111
  318. package/src/utils/decryptApiKey.ts +0 -40
  319. package/src/utils/gientechCommon/components/AppError.tsx +0 -32
  320. package/src/utils/gientechCommon/components/AppLoading.tsx +0 -75
  321. package/src/utils/gientechCommon/components/DeleteModal.tsx +0 -75
  322. package/src/utils/gientechCommon/components/DisplayError.tsx +0 -33
  323. package/src/utils/gientechCommon/components/DisplayLoading.tsx +0 -38
  324. package/src/utils/gientechCommon/components/FeedBackModal.tsx +0 -318
  325. package/src/utils/gientechCommon/components/FileCardCommon.tsx +0 -82
  326. package/src/utils/gientechCommon/components/FileManager/index.tsx +0 -390
  327. package/src/utils/gientechCommon/components/FileManager/style.css +0 -5
  328. package/src/utils/gientechCommon/components/Messages/GientechNewChatWelcome.tsx +0 -581
  329. package/src/utils/gientechCommon/components/Messages/ReferenceCard.tsx +0 -339
  330. package/src/utils/gientechCommon/components/Messages/RetriveItem.tsx +0 -245
  331. package/src/utils/gientechCommon/components/Messages/WebRetriveItem.tsx +0 -209
  332. package/src/utils/gientechCommon/components/Messages/defaultBot.png +0 -0
  333. package/src/utils/gientechCommon/components/Messages/defaultStyleSet.tsx +0 -148
  334. package/src/utils/gientechCommon/components/Messages/defaultWeLogo.svg +0 -14
  335. package/src/utils/gientechCommon/components/RenameModal.tsx +0 -86
  336. package/src/utils/gientechCommon/components/style.less +0 -11
  337. package/src/utils/gientechCommon/configs/commonConfig.ts +0 -2
  338. package/src/utils/gientechCommon/configs/senderConfig.ts +0 -0
  339. package/src/utils/gientechCommon/configs/stylesConfig.ts +0 -142
  340. package/src/utils/gientechCommon/hooks/AichatUseController.tsx +0 -417
  341. package/src/utils/gientechCommon/slate/converters/deserializers.ts +0 -763
  342. package/src/utils/gientechCommon/slate/converters/mockData.ts +0 -232
  343. package/src/utils/gientechCommon/slate/converters/slateConverters.ts +0 -258
  344. package/src/utils/gientechCommon/slate/richElements/index.tsx +0 -499
  345. package/src/utils/gientechCommon/utils/request.ts +0 -37
  346. package/src/utils/gientechCommon/utils/serverFn.ts +0 -172
  347. package/src/utils/index.tsx +0 -132
  348. package/src/utils/testconfigs/demologin/index.tsx +0 -32
  349. package/src/utils/testconfigs/index.ts +0 -59
  350. package/src/vite-env.d.ts +0 -11
  351. package/stats.html +0 -4949
  352. package/tailwind.config.js +0 -170
  353. package/tsconfig.app.json +0 -30
  354. package/tsconfig.app.tsbuildinfo +0 -11
  355. package/tsconfig.json +0 -13
  356. package/tsconfig.node.json +0 -22
  357. package/tsconfig.node.tsbuildinfo +0 -1
  358. package/vite.config.app.ts +0 -93
  359. package/vite.config.ts +0 -231
  360. package/workflows/release.yml +0 -60
  361. package//346/215/242/350/241/214/346/240/274/345/274/217/344/277/235/346/214/201/344/274/230/345/214/226/346/226/271/346/241/210.md +0 -359
  362. /package/{dist/assets → assets}/Doris.png +0 -0
  363. /package/{dist/assets → assets}/GientechStreamReader-DydY9Vu3.js +0 -0
  364. /package/{dist/assets → assets}/PostgreSQL.png +0 -0
  365. /package/{dist/assets → assets}/SQLServer.png +0 -0
  366. /package/{dist/assets → assets}/database.svg +0 -0
  367. /package/{dist/assets → assets}/database_add.svg +0 -0
  368. /package/{dist/assets → assets}/database_connect.svg +0 -0
  369. /package/{dist/assets → assets}/database_upload.svg +0 -0
  370. /package/{dist/assets → assets}/databse.svg +0 -0
  371. /package/{dist/assets → assets}/defaultWeLogo.svg +0 -0
  372. /package/{dist/assets → assets}/empty.png +0 -0
  373. /package/{dist/assets → assets}/graph.svg +0 -0
  374. /package/{dist/assets → assets}/homeBg.png +0 -0
  375. /package/{dist/assets → assets}/index-4Ac00q5P.js +0 -0
  376. /package/{dist/assets → assets}/index-7FYeBShT.js +0 -0
  377. /package/{dist/assets → assets}/index-B2rczyCX.js +0 -0
  378. /package/{dist/assets → assets}/index-CQMGllKT.js +0 -0
  379. /package/{dist/assets → assets}/index-CpW6Dhpp.js +0 -0
  380. /package/{dist/assets → assets}/index-CwGOSlVC.js +0 -0
  381. /package/{dist/assets → assets}/index-DBPtDW8Y.js +0 -0
  382. /package/{dist/assets → assets}/index-DJPAws60.js +0 -0
  383. /package/{dist/assets → assets}/index-antI2hFx.js +0 -0
  384. /package/{dist/assets → assets}/index-q0nZjKAG.js +0 -0
  385. /package/{dist/assets → assets}/index-rkRJ-e_U.js +0 -0
  386. /package/{dist/assets → assets}/knowledge.svg +0 -0
  387. /package/{dist/assets → assets}/left.jpg +0 -0
  388. /package/{dist/assets → assets}/logoImg.png +0 -0
  389. /package/{dist/assets → assets}/mysql.svg +0 -0
  390. /package/{dist/assets → assets}/plus-qlmqrjBc.js +0 -0
  391. /package/{dist/assets → assets}/sensitive.svg +0 -0
  392. /package/{dist/assets → assets}/style-BeYL_E4J.js +0 -0
  393. /package/{dist/assets → assets}/style.css +0 -0
  394. /package/{dist/assets → assets}/style2.css +0 -0
  395. /package/{dist/assets → assets}/style3.css +0 -0
  396. /package/{dist/assets → assets}/style4.css +0 -0
  397. /package/{dist/assets → assets}/worker-BbpylX7l.js +0 -0
  398. /package/{dist/assets → assets}/x-DxuhxSb6.js +0 -0
  399. /package/{dist/assistantConfig.d.ts → assistantConfig.d.ts} +0 -0
  400. /package/{dist/assistantConfig.js → assistantConfig.js} +0 -0
  401. /package/{dist/chat.d.ts → chat.d.ts} +0 -0
  402. /package/{dist/chat.js → chat.js} +0 -0
  403. /package/{dist/database.d.ts → database.d.ts} +0 -0
  404. /package/{dist/database.js → database.js} +0 -0
  405. /package/{dist/databaseId.d.ts → databaseId.d.ts} +0 -0
  406. /package/{dist/databaseId.js → databaseId.js} +0 -0
  407. /package/{dist/databaseTable.d.ts → databaseTable.d.ts} +0 -0
  408. /package/{dist/databaseTable.js → databaseTable.js} +0 -0
  409. /package/{dist/icons → icons}/answerAwartar.png +0 -0
  410. /package/{dist/icons → icons}/docx-file.png +0 -0
  411. /package/{dist/icons → icons}/folder.png +0 -0
  412. /package/{dist/icons → icons}/html.png +0 -0
  413. /package/{dist/icons → icons}/image.png +0 -0
  414. /package/{dist/icons → icons}/jpg-file.png +0 -0
  415. /package/{dist/icons → icons}/json.png +0 -0
  416. /package/{dist/icons → icons}/md.png +0 -0
  417. /package/{dist/icons → icons}/pdf.png +0 -0
  418. /package/{dist/icons → icons}/pptx.png +0 -0
  419. /package/{dist/icons → icons}/questionAwartar.png +0 -0
  420. /package/{dist/icons → icons}/sheets.png +0 -0
  421. /package/{dist/icons → icons}/txt.png +0 -0
  422. /package/{dist/icons → icons}/xlsx.png +0 -0
  423. /package/{dist/index.d.ts → index.d.ts} +0 -0
  424. /package/{dist/index.js → index.js} +0 -0
  425. /package/{dist/modelManage.d.ts → modelManage.d.ts} +0 -0
  426. /package/{dist/modelManage.js → modelManage.js} +0 -0
  427. /package/{dist/sensitive.d.ts → sensitive.d.ts} +0 -0
  428. /package/{dist/sensitive.js → sensitive.js} +0 -0
  429. /package/{dist/streamFilesReader.d.ts → streamFilesReader.d.ts} +0 -0
  430. /package/{dist/streamFilesReader.js → streamFilesReader.js} +0 -0
  431. /package/{dist/vite.svg → vite.svg} +0 -0
  432. /package/{dist/worker → worker}/pdf.worker.min.js +0 -0
@@ -1,2087 +0,0 @@
1
- import React, { useEffect, useState, useMemo, useRef } from 'react';
2
- import axios from 'axios';
3
- import { AiChat, type AppStatusManager } from '@mxmweb/aichat';
4
- import { ChatMessageAdapter } from '@mxmweb/rtext';
5
- import { message } from 'antd';
6
- import { uid } from 'uid';
7
- import { History } from 'lucide-react';
8
-
9
- import { defaultTheme, deepMergeTheme, type Styles } from '@mxmweb/zui';
10
- import { DefaultSenderConfig } from './constants';
11
- import GientechConversationPanel from './Conversations';
12
- import {
13
- convertQueryReplyPairListToMessages,
14
- getFileTypeByName,
15
- toCopy,
16
- } from '../../utils/commonFn';
17
- import {
18
- getFeedbackList,
19
- handleCancelFeedBack,
20
- handleDeleteConversation,
21
- handleFeedBack,
22
- handleRename,
23
- removeFilefromTempUpload,
24
- handleCreateConversation,
25
- } from '../../utils/gientechCommon/utils/serverFn';
26
-
27
- import GientechNewChatWelcome from '../../utils/gientechCommon/components/Messages/GientechNewChatWelcome';
28
- import AichatUseController from '../../utils/gientechCommon/hooks/AichatUseController';
29
- import FeedBackModal from '../../utils/gientechCommon/components/FeedBackModal';
30
- import FileManager from '../../utils/gientechCommon/components/FileManager';
31
- import AppLoading from '../../utils/gientechCommon/components/AppLoading';
32
- import DisplayLoading from '../../utils/gientechCommon/components/DisplayLoading';
33
- import AppError from '../../utils/gientechCommon/components/AppError';
34
- import DisplayError from '../../utils/gientechCommon/components/DisplayError';
35
- import { maxPollCount, maxPollInterval } from '../../utils/gientechCommon/configs/commonConfig';
36
- import { RenameModal } from '../../utils/gientechCommon/components/RenameModal';
37
- import { DeleteModal } from '../../utils/gientechCommon/components/DeleteModal';
38
- import { ReferenceBar } from './ReferenceBar';
39
- import '@mxmweb/rtext/style.css';
40
- import '@mxmweb/aichat/style.css';
41
- import '@mxmweb/zui/style.css';
42
- export enum DrawerType {
43
- REFERENCELIST = 'referencelist',
44
- }
45
-
46
- interface SenderConfig {
47
- actions?: Array<{
48
- name: string;
49
- icon?: React.ReactNode;
50
- badgeCount?: number;
51
- enabled?: boolean;
52
- [key: string]: any;
53
- }>;
54
- switchs?: Array<{
55
- name: string;
56
- label: string;
57
- enabled?: boolean;
58
- [key: string]: any;
59
- }>;
60
- [key: string]: any;
61
- }
62
-
63
- // 自定义组件接口
64
- interface CustomComponents {
65
- LogoBox?: React.ComponentType<any> | null;
66
- AiChatBox?: React.ComponentType<any>;
67
- UserChatBox?: React.ComponentType<any>;
68
- WelcomeComponent?: React.ComponentType<any>;
69
- DisplayLoading?: React.ComponentType<any>;
70
- DisplayError?: React.ComponentType<any>;
71
- AppError?: React.ComponentType<any>;
72
- AppLoading?: React.ComponentType<any>;
73
- [key: string]: React.ComponentType<any> | null | undefined;
74
- }
75
-
76
- interface GientechChatAdopterProps {
77
- token: string;
78
- url?: string;
79
- CSRFToken?: string;
80
- styles?: Styles;
81
- eventsEmit?: (eventName: string, data: any) => void;
82
- CustomComponents?: CustomComponents;
83
- senderConfig?: SenderConfig;
84
- appLoadingConfig?: {
85
- title?: string;
86
- subtitle?: string;
87
- };
88
- [key: string]: any;
89
- }
90
-
91
- export interface SidebarTabConfig {
92
- key: string;
93
- type: 'custom' | 'form';
94
- label: string;
95
- icon: React.ReactNode;
96
- enabled?: boolean;
97
- component?: React.ReactNode; // type=custom
98
- formConfig?: any[]; // type=form
99
- initialValues?: Record<string, any>;
100
- onChange?: (values: any) => void;
101
- [key: string]: any;
102
- }
103
-
104
- export default function withGientechChatAdopter(WrappedComponent = AiChat) {
105
- /**
106
- * GientechChatAdopter 高阶组件
107
- * 封装了与Gientech后端服务的接口对接、状态管理、事件处理等核心业务逻辑
108
- * @param {React.ComponentType} WrappedComponent - 需要包裹的基础聊天组件,默认为 AiChat
109
- */
110
- return function GientechChatAdopter({
111
- token,
112
- url = 'http://localhost:8888',
113
- styles,
114
- CSRFToken,
115
- eventsEmit,
116
- scrollOld,
117
- ...rest
118
- }: GientechChatAdopterProps) {
119
- // 统一归一化样式:使用 UI 库的 deepMergeTheme
120
- const normalizedStyles: Styles = useMemo(() => {
121
- const baseStyles: Styles = { theme: defaultTheme, mode: 'light' };
122
- return deepMergeTheme(baseStyles, styles);
123
- }, [styles]);
124
- const [isRenameModalOpen, setisRenameModalOpen] = useState(false);
125
- const [isRemoveModalOpen, setisRemoveModalOpen] = useState(false);
126
- const [curEditData, setCurEditData] = useState<any>(null);
127
- // =================================================================
128
- // State Management - 状态管理
129
- // =================================================================
130
- const [conversationList, setConversationList] = useState<any[]>([]); // 对话列表
131
- // 会话列表分页状态
132
- const [convPageNo, setConvPageNo] = useState<number>(1);
133
- const [convPageSize] = useState<number>(16);
134
- const [convTotal, setConvTotal] = useState<number>(0);
135
- const [convLoading, setConvLoading] = useState<boolean>(false);
136
- const [chatData, setChatData] = useState<any[]>([]); // 所有对话的聊天记录
137
- const [activeSessionId, setActiveSessionId] = useState<string | undefined>(undefined); // 当前激活的对话ID
138
- const [recommandQuestions, setRecommandQuestions] = useState<any[]>([]); // 推荐问题列表
139
- const [assistantList, setAssistantList] = useState<any[]>([]); // 智能体(助手)列表
140
- const [newAssistantId, setNewAssistantId] = useState<string | undefined>(undefined); // 新建对话时选择的智能体ID
141
- const [fileManagerOpen, setFileManagerOpen] = useState<boolean>(false); // 文件管理器抽屉的开关状态
142
- const [appStatus, setAppStatus] = useState<AppStatusManager>({
143
- display: 'ready', // 主聊天区域状态: ready, loading, processing, error, uploading
144
- sender: 'ready', // 发送器状态: ready, processing, error, uploading
145
- app: 'initializing', // 应用整体状态: initializing, ready, error
146
- });
147
- const [pendingFiles, setPendingFiles] = useState<any[]>([]); // 准备上传的文件列表
148
- // 发送器配置支持外部传入
149
- // 深度合并工具,customConfig 有的字段覆盖 defaultConfig
150
- function deepMerge(defaultConfig: any, customConfig: any): any {
151
- if (!customConfig) return defaultConfig;
152
- const result: any = Array.isArray(defaultConfig) ? [...defaultConfig] : { ...defaultConfig };
153
- for (const key in customConfig) {
154
- if (
155
- customConfig[key] !== undefined &&
156
- customConfig[key] !== null &&
157
- Object.prototype.hasOwnProperty.call(customConfig, key)
158
- ) {
159
- if (
160
- typeof defaultConfig[key] === 'object' &&
161
- defaultConfig[key] !== null &&
162
- !Array.isArray(defaultConfig[key]) &&
163
- typeof customConfig[key] === 'object' &&
164
- customConfig[key] !== null &&
165
- !Array.isArray(customConfig[key])
166
- ) {
167
- result[key] = deepMerge(defaultConfig[key], customConfig[key]);
168
- } else {
169
- result[key] = customConfig[key];
170
- }
171
- }
172
- }
173
- return result;
174
- }
175
-
176
- // 发送器配置支持外部传入,merge 默认和外部
177
- const [dynamicSenderConfig, setDynamicSenderConfig] = useState(() =>
178
- deepMerge(DefaultSenderConfig, rest.senderConfig)
179
- );
180
-
181
- // 监听外部 senderConfig 变化自动 merge
182
- useEffect(() => {
183
- if (rest.senderConfig) {
184
- // console.log('hahah', dynamicSenderConfig, rest.senderConfig);
185
- setDynamicSenderConfig(deepMerge(DefaultSenderConfig, rest.senderConfig));
186
- }
187
- }, [rest.senderConfig]);
188
- const [fileStatuses, setFileStatuses] = useState<any[]>([]); // 用于跟踪每个上传文件的状态
189
- const [fileManagerData, setFileManagerData] = useState<{ uploadedFiles: any[] }>(() => {
190
- let uploaded: any[] = [];
191
- return { uploadedFiles: uploaded };
192
- });
193
-
194
- useEffect(() => {
195
- if (!activeSessionId) return;
196
- const conv = chatData.find((c: any) => c.id === activeSessionId);
197
- let uploaded: any[] = [];
198
- let hasReference = false;
199
- if (conv && conv.messages) {
200
- const lastAiMsg = [...(conv.messages || [])]
201
- .reverse()
202
- .find((msg: any) => msg.istype === 'ai');
203
- if (lastAiMsg?.reference && lastAiMsg.resultType === 5) {
204
- hasReference = true;
205
- try {
206
- const fileList = JSON.parse(lastAiMsg.reference);
207
- uploaded = fileList.map((f: any) => normalizeFileItem(f));
208
- } catch (e) {}
209
- }
210
- }
211
- if (hasReference) {
212
- setFileManagerData({ uploadedFiles: uploaded });
213
- }
214
- // 否则不动,保持原有 uploadedFiles
215
- }, [chatData]);
216
-
217
- useEffect(() => {
218
- setFileManagerData({ uploadedFiles: [] });
219
- }, [activeSessionId]);
220
-
221
- // 新增:全局管理助手选中状态,彻底解决子组件重建跳回默认
222
- const [selectedAssistantId, setSelectedAssistantId] = React.useState(() => {
223
- if (!assistantList || assistantList.length === 0) return undefined;
224
- const defaultItem = assistantList.find(item => item.isDefault);
225
- return defaultItem ? defaultItem.id : assistantList[0]?.id;
226
- });
227
-
228
- // 监听 assistantList 变化,自动选中默认助手
229
- React.useEffect(() => {
230
- if (!assistantList || assistantList.length === 0) return;
231
- const exists = assistantList.some(item => item.id === selectedAssistantId);
232
- if (!selectedAssistantId || !exists) {
233
- const defaultItem = assistantList.find(item => item.isDefault);
234
- setSelectedAssistantId(defaultItem ? defaultItem.id : assistantList[0].id);
235
- }
236
- }, [assistantList]);
237
-
238
- // 新增:记录 sender switchs 的选中状态
239
- const [senderSwitchValues, setSenderSwitchValues] = useState<{ [key: string]: boolean }>({});
240
-
241
- // =================================================================
242
- // Refs - 引用
243
- // =================================================================
244
- const prevActiveSessionId = useRef<string | undefined>(undefined); // 记录上一个激活的对话ID,用于对比变化
245
- const setUploadedFilesRef = useRef<(files: any[]) => void>(undefined); // 引用核心组件的文件上传方法
246
- const removeFileRef = useRef<(fileObj: any, idx: number, _type: string) => void>(undefined); // 引用核心组件的文件移除方法
247
- const deleteData = useRef({ sessionId: '' }); // 暂存待删除的对话数据
248
- const confirmed = useRef<any>(null); // 暂存 antd Modal.confirm 的引用
249
- const [feedParam, setFeedParam] = useState<{
250
- queryId?: number | string | undefined;
251
- restult?: number;
252
- }>({});
253
- const [openFeed, setOpenFeed] = useState(false);
254
- const [feedBackList, setFeedBackList] = useState<any>([]);
255
- const stoppedRef = useRef(false);
256
-
257
- // =================================================================
258
- // Custom Hooks - 自定义钩子
259
- // =================================================================
260
- // 引入SSE控制器,封装了流式请求、消息管理等复杂逻辑
261
- const {
262
- api_startChat_re,
263
- addEmptyMessage,
264
- setLastEmptyMessage,
265
- stopStream,
266
- cancelStreamBySessionId,
267
- } = AichatUseController({
268
- baseUrl: url,
269
- CSRFToken: CSRFToken,
270
- token,
271
- setChatData,
272
- activeSessionId,
273
- setAppStatus,
274
- setConversationList,
275
- });
276
-
277
- // =================================================================
278
- // Memoized Values - 缓存计算值
279
- // =================================================================
280
-
281
- /**
282
- * 将智能体列表转换为以ID为键的Map,便于快速查找
283
- */
284
- const assistantMap = useMemo(() => {
285
- const map: Record<string, any> = {};
286
- (assistantList || []).forEach(item => {
287
- map[item.id] = item;
288
- });
289
- return map;
290
- }, [assistantList]);
291
-
292
- /**
293
- * 根据 activeSessionId 从 chatData 中筛选出当前对话的数据, 并合并智能体信息
294
- */
295
- const currentChatData = useMemo(() => {
296
- const data = chatData.find((c: any) => c.id === activeSessionId) || {
297
- id: activeSessionId,
298
- messages: [],
299
- };
300
- const assistantInfo = data.configId ? assistantMap[data.configId] : null;
301
- return {
302
- ...data,
303
- assistantInfo,
304
- };
305
- }, [chatData, activeSessionId, assistantMap]);
306
-
307
- const is_download = useMemo(() => {
308
- if (currentChatData.configId && assistantMap) {
309
- const curAssist = assistantMap[currentChatData.configId];
310
- if (curAssist?.configJson) {
311
- const config = JSON.parse(curAssist.configJson);
312
- return config.is_download;
313
- }
314
- return false;
315
- } else {
316
- return false;
317
- }
318
- }, [currentChatData.configId, assistantMap]);
319
-
320
- const is_enableThinking = useMemo(() => {
321
- //console.log('is_enableThinking',currentChatData.configId,assistantMap,newAssistantId)
322
- if ((currentChatData.configId || newAssistantId) && assistantMap) {
323
- const curAssist = assistantMap[currentChatData.configId];
324
- if (curAssist?.configJson) {
325
- const config = JSON.parse(curAssist.configJson);
326
- console.log('is_enableThinking', currentChatData.configId, assistantMap, newAssistantId);
327
- return config.thinking ? true : false;
328
- } else {
329
- // const curAssist = assistantMap[newAssistantId]
330
- //console.log('newAssistantId',newAssistantId)
331
- if (newAssistantId) {
332
- const curAssist = assistantMap[newAssistantId];
333
- if (curAssist?.configJson) {
334
- const config = JSON.parse(curAssist.configJson);
335
- return config.thinking ? true : false;
336
- }
337
- }
338
- }
339
- }
340
- return false;
341
- }, [currentChatData.configId, assistantMap, newAssistantId]);
342
-
343
- // 合并文件工具,避免重复,且保证每个文件有 file 字段
344
- function mergeFiles(oldFiles: any[], newFiles: any[]) {
345
- const map = new Map();
346
- oldFiles.forEach(f => map.set(f.uid, normalizeFileItem(f)));
347
- newFiles.forEach(f => map.set(f.uid, normalizeFileItem(f)));
348
- // console.log(Array.from(map.values()),'``````````````````9929312830918309812903819023890128390')
349
- return Array.from(map.values());
350
- }
351
-
352
- // 文件结构标准化,保证有 file 字段
353
- function normalizeFileItem(f: any) {
354
- if (!f) return f;
355
- if (f.file && f.file.name) return f;
356
- // 兼容后端返回的扁平对象,优先 name,其次 fileName
357
- const name = f.name || f.fileName || '';
358
- return {
359
- ...f,
360
- url: f.filePath || '',
361
- uid: f.uid || '',
362
- file: {
363
- name,
364
- size:
365
- typeof f.size === 'string' && f.size.endsWith('MB')
366
- ? Number(f.size.replace('MB', '')) * 1024 * 1024
367
- : f.size || 0,
368
- type: f.type || '',
369
- },
370
- name, // 兜底 name 字段,供 UI 使用
371
- };
372
- }
373
-
374
- // =================================================================
375
- // Side Effects (useEffect) - 副作用钩子
376
- // =================================================================
377
-
378
- /**
379
- * 跟踪 activeSessionId 的变化:
380
- * 1. 清理上一个无消息的临时会话
381
- * 2. 更新推荐问题
382
- */
383
- useEffect(() => {
384
- // 切换会话时,检查上一个会话是否为临时且无消息
385
- if (prevActiveSessionId.current && prevActiveSessionId.current !== activeSessionId) {
386
- const prevId = prevActiveSessionId.current;
387
- const prevConv = conversationList.find(c => c.sessionId === prevId && c.isNew);
388
- const prevChat = chatData.find(c => c.id === prevId && c.isNew);
389
- const prevHasMsg = prevChat && prevChat.messages && prevChat.messages.length > 0;
390
- // 如果是临时的且没有消息,则自动删除
391
- if (prevConv && !prevHasMsg) {
392
- setConversationList(list => list.filter(c => c.sessionId !== prevId));
393
- setChatData(list => list.filter(c => c.id !== prevId));
394
- }
395
- }
396
- prevActiveSessionId.current = activeSessionId;
397
-
398
- // 更新推荐问题为当前对话的最后一个推荐问题
399
- const historyRQ =
400
- currentChatData.messages && currentChatData.messages.length > 0
401
- ? currentChatData.messages[currentChatData.messages.length - 1].recommendQuestion
402
- : [];
403
- setRecommandQuestions(historyRQ);
404
- }, [activeSessionId, conversationList, chatData, currentChatData.messages]);
405
-
406
- /**
407
- * 拉取会话列表分页
408
- */
409
- const fetchConversationPage = async (pageNo: number) => {
410
- if (convLoading) return;
411
- setConvLoading(true);
412
- try {
413
- const res = await axios.get(
414
- `${url}/qa/dialogue/list?pageNo=${pageNo}&pageSize=${convPageSize}&sysType=INT_SESSION`,
415
- { headers: { Authorization: token } }
416
- );
417
- const records = res?.data?.data?.records || [];
418
- const total = res?.data?.data?.total || 0;
419
- setConvTotal(total);
420
- setConversationList(prev => {
421
- // 去重合并(以 sessionId 为准)
422
- const map = new Map<string, any>();
423
- [...prev, ...records].forEach((it: any) => {
424
- map.set(it.sessionId, it);
425
- });
426
- return Array.from(map.values());
427
- });
428
- setConvPageNo(pageNo);
429
- } catch (_) {
430
- // 忽略,错误态交由上层处理
431
- } finally {
432
- setConvLoading(false);
433
- }
434
- };
435
-
436
- /**
437
- * 首次加载:并发拉取助手列表与会话第一页
438
- */
439
- useEffect(() => {
440
- setAppStatus(prev => ({ ...prev, app: 'initializing' }));
441
- // 助手列表
442
- axios
443
- .get(`${url}/qa/search/config/helper/list?pageNo=1&pageSize=3000`, {
444
- headers: { Authorization: token },
445
- })
446
- .then(assistantRes => {
447
- setAssistantList(assistantRes.data.data || []);
448
- })
449
- .catch(() => {});
450
-
451
- // 会话第一页
452
- fetchConversationPage(1)
453
- .then(() => {
454
- if (!activeSessionId) {
455
- handleConversationCreate({});
456
- }
457
- setAppStatus(prev => ({ ...prev, app: 'ready' }));
458
- })
459
- .catch(() => {
460
- setAppStatus(prev => ({ ...prev, app: 'error' }));
461
- });
462
- }, []);
463
-
464
- /**
465
- * 当 activeSessionId 变化时,获取对应的聊天记录
466
- */
467
- useEffect(() => {
468
- if (!activeSessionId) return;
469
-
470
- setAppStatus(prev => ({ ...prev, display: 'loading' }));
471
- axios
472
- .get(`${url}/qa/dialogue/getDialogBySessionId?sessionId=${activeSessionId}`, {
473
- headers: { Authorization: token },
474
- })
475
- .then(res => {
476
- // const r = {
477
- // data: {
478
- // success: true,
479
- // errorMsg: null,
480
- // errorCode: null,
481
- // data: {
482
- // label: '控制器起不来(控制器右上角RDY灯不亮)',
483
- // sessionId: '3d752532b3d4510867288e5ac5cb3833',
484
- // gmtCreate: '2025-11-06 14:30:43',
485
- // gmtModified: '2025-11-06 14:30:43',
486
- // createBy: 'admin',
487
- // updateBy: 'admin',
488
- // filePath: 'http://10.160.33.221:9000',
489
- // configId: 703,
490
- // kbId: null,
491
- // queryReplyPairList: [
492
- // {
493
- // query: {
494
- // id: 27665,
495
- // gmtCreate: '2025-11-06T06:31:05.000+00:00',
496
- // content: '控制器起不来(控制器右上角RDY灯不亮)',
497
- // type: 'text',
498
- // queryId: 'query-2532b3d4510867288e5ac5cb38338870',
499
- // audioUrl: '',
500
- // filePaths: null,
501
- // currentFiles: null,
502
- // },
503
- // reply: {
504
- // id: 27638,
505
- // gmtCreate: '2025-11-06T06:31:15.000+00:00',
506
- // content:
507
- // '<think>\n好的,我现在需要回答用户的问题:“控制器起不来(控制器右上角RDY灯不亮)”。首先,我要查看提供的参考资料,看看是否有相关信息。\n\n参考资料0提到了现象“控制器起不来(控制器右上角RDY灯不亮)”,并关联到“包含”和“产生”关系,但没有提供处理方法。参考资料1和2都详细描述了这个现象,并且都给出了处理方法:检查NT255模块是否报红,更换模块,并特别提到机舱检查FS211/N模块。这些处理方法的ID都是10001,说明是同一个解决方案。\n\n用户的问题没有指定版本,根据规则2,我应该使用最新的版本信息。不过,参考资料中没有明确的版本日期,所以只能假设它们都是最新的。因此,我应该综合所有参考资料的信息,提供处理方法。\n\n最后,我需要按照要求,用简洁的语言回答,并标注来源。由于处理方法在参考资料1和2中都有,我会引用这两个来源。\n\n\n</think>\n\n控制器起不来(控制器右上角RDY灯不亮)的处理方法如下:\n\n1. 检查NT255模块是否报红(ERR灯是否亮红)[retrive-tag id="2290607639633892359" image_urls="" fromType="2"][1][/retrive-tag][retrive-tag id="439368868506707299" image_urls="" fromType="2"][2][/retrive-tag]。\n2. 更换NT255模块(注:机舱检查FS211/N模块)[retrive-tag id="2290607639633892359" image_urls="" fromType="2"][1][/retrive-tag][retrive-tag id="439368868506707299" image_urls="" fromType="2"][2][/retrive-tag]。\n\n这些步骤可以帮助解决控制器无法启动的问题。',
508
- // type: 'text',
509
- // reference: '[]',
510
- // webReference: '[]',
511
- // graphReference:
512
- // '[{"cyphers":["match (n:`组件`)-[e]-(m) where id(n) == \\"组件101\\" return n,e,m;","match (n:`现象`)-[e]-(m) where id(n) == \\"现象1001\\" return n,e,m;","match (n:`现象`)-[e]-(m) where id(n) == \\"现象1001\\" return n,e,m;"],"fetchUrl":"https://10.160.33.150:30001/jinxin_graph/proxy/search/graph/search/cypherSearch4Rag","graphName":"故障处理图谱","id":"1952195957278367755","traceNodes":[{"graphId":"1952195957278367755","id":"3484145002858895870","name":"控制器","nodeType":"组件","vid":"组件101"},{"graphId":"1952195957278367755","id":"2290607639633892359","name":"控制器起不来(控制器右上角RDY灯不亮)","nodeType":"现象","vid":"现象1001"},{"graphId":"1952195957278367755","id":"439368868506707299","name":"控制器起不来(控制器右上角RDY灯不亮)","nodeType":"现象","vid":"现象1001"}]}]',
513
- // queryId: 'query-2532b3d4510867288e5ac5cb38338870',
514
- // feedbackResult: null,
515
- // feedbackId: null,
516
- // parsedFilePaths: null,
517
- // recommendQuestion:
518
- // '["在检查NT255模块时,ERR灯亮红可能表示哪些具体问题?","更换NT255模块时需要注意哪些步骤或注意事项?","除了检查和更换NT255模块,还有哪些方法可以排查控制器无法启动的问题?"]',
519
- // llmType: 1,
520
- // resultType: 1,
521
- // respTime: 32453,
522
- // tokens: 824,
523
- // },
524
- // },
525
- // ],
526
- // searchConfigDTO: {
527
- // id: 703,
528
- // status: 1,
529
- // isDefault: 0,
530
- // configJson:
531
- // '{"status":1,"defaultAnswer":"您好!我注意到您的消息中可能包含了一些敏感的内容。为了保证社区的友好氛围,我们无法继续就此话题进行讨论。如果您有其他问题或需要帮助,我很乐意继续为您服务!谢谢您的理解和支持。","dependOnKb":1,"isDel":1,"config_name":"图谱测试","model_name":"deepseek-distill-qwen32b","plan_model_name":"deepseek-distill-qwen32b","prologue":"你好","system_prompt":"","recommend_model_name":"deepseek-distill-qwen32b","temperature":0.3,"top_p":0.8,"top_k":10,"score_threshold":0.1,"max_tokens":4096,"max_round":5,"rerank_model_name":"bge-reranker-v2-m3_xinference","knowledge_base_name_source":"","graph_nb_name":[{"graph_name":"故障处理图谱","index_name":"1952195957278367755"}],"thinking":false,"knowledge_base_name":"","selectedKnowledgeBase":[],"enabled_graph":false,"enabled_nb_graph":true,"need_trace_source":true,"trace_by_llm":true,"is_download":false,"search_policy":1,"enabled_question_rewrite":false,"enabled_faq":true,"enabled_rerank":true,"rerank":false}',
532
- // name: '图谱测试',
533
- // des: null,
534
- // createBy: 'admin',
535
- // gmtCreate: '2025-11-05 19:37:54',
536
- // permission: null,
537
- // sensitiveWordIds: '',
538
- // defaultAnswer:
539
- // '您好!我注意到您的消息中可能包含了一些敏感的内容。为了保证社区的友好氛围,我们无法继续就此话题进行讨论。如果您有其他问题或需要帮助,我很乐意继续为您服务!谢谢您的理解和支持。',
540
- // model: false,
541
- // enabledFaq: 0,
542
- // dependOnKb: 1,
543
- // isDel: 1,
544
- // },
545
- // },
546
- // },
547
- // };
548
- // 如果会话没有数据(例如新建的),直接返回
549
-
550
- if (!res.data.data) {
551
- setAppStatus(prev => ({ ...prev, display: 'ready' }));
552
- return;
553
- }
554
- // 解析消息数据
555
- const queryReplyPairList = res.data.data?.queryReplyPairList || [];
556
- const messages = convertQueryReplyPairListToMessages(queryReplyPairList);
557
- const {
558
- sessionId,
559
- searchConfigDTO,
560
- filePath,
561
- configId,
562
- reference,
563
- webReference,
564
- uploadedFiles,
565
- fileList,
566
- currentFiles,
567
- } = res.data.data;
568
-
569
- // === 文件数据补全 ===
570
- // 1. reference(AI消息)
571
- if (messages.length > 0) {
572
- // 找到最后一条 AI 消息的索引(从后往前找)
573
- const lastAiIndex =
574
- messages.length - 1 - [...messages].reverse().findIndex(m => m.istype === 'ai');
575
-
576
- // 确保找到的是有效的 AI 消息
577
- if (
578
- lastAiIndex >= 0 &&
579
- lastAiIndex < messages.length &&
580
- messages[lastAiIndex].istype === 'ai'
581
- ) {
582
- if (reference) {
583
- messages[lastAiIndex].reference = reference;
584
- }
585
- if (webReference) {
586
- messages[lastAiIndex].webReference = webReference;
587
- }
588
- }
589
- }
590
- // 2. currentFiles/fileList/uploadedFiles(user消息)
591
- const filesData = currentFiles || fileList || uploadedFiles;
592
- if (filesData && messages.length > 0) {
593
- const lastUserIdx = [...messages].reverse().findIndex(m => m.istype === 'user');
594
- if (lastUserIdx !== -1) {
595
- console.log(messages[messages.length - 1 - lastUserIdx].currentFiles, 'filesData');
596
- messages[messages.length - 1 - lastUserIdx].currentFiles = filesData;
597
- }
598
- }
599
-
600
- // 更新对话列表中的对应项的元数据
601
- const item = conversationList.find(item => item.sessionId === sessionId);
602
- if (item) {
603
- // console.log(item,'你大爷')
604
- setConversationList(list =>
605
- list.map(item =>
606
- item.sessionId === sessionId
607
- ? { ...item, searchConfigDTO, filePath, configId }
608
- : item
609
- )
610
- );
611
- }
612
-
613
- // 构造当前对话的完整数据
614
- const conversationConfig = {
615
- configId: res.data.data.configId,
616
- filePath: res.data.data.filePath,
617
- searchConfigDTO: res.data.data.searchConfigDTO || {},
618
- sessionId: res.data.data.sessionId,
619
- label: res.data.data.label,
620
- kbId: res.data.data.kbId,
621
- };
622
-
623
- // 更新聊天数据
624
- setChatData(prev => {
625
- const others = prev.filter((c: any) => c.id !== activeSessionId);
626
-
627
- const newChatData = [
628
- { id: activeSessionId, messages, ...conversationConfig },
629
- ...others,
630
- ];
631
- return newChatData;
632
- });
633
- setAppStatus(prev => ({ ...prev, display: 'ready' }));
634
- })
635
- .catch(err => {
636
- console.error('获取聊天数据失败:', err);
637
- if (err.response && err.response.status === 404) {
638
- // 404 表示会话在后端不存在,按新建会话处理
639
- handleConversationCreate({});
640
- }
641
- setAppStatus(prev => ({ ...prev, display: 'error' }));
642
- });
643
- }, [activeSessionId, url, token]);
644
-
645
- /**
646
- * 监听文件数据变化,更新Sender上的角标
647
- */
648
- useEffect(() => {
649
- const totalFiles = fileManagerData.uploadedFiles.length;
650
- setDynamicSenderConfig((prev: any) => {
651
- const actions = Array.isArray(prev.actions) ? prev.actions : [];
652
- const newConfig = {
653
- ...prev,
654
- actions: actions.map((action: any) =>
655
- action.name === 'history' ? { ...action, badgeCount: totalFiles } : action
656
- ),
657
- };
658
- return newConfig;
659
- });
660
- }, [fileManagerData.uploadedFiles]);
661
- useEffect(() => {
662
- getFeedbackList({ url, token }, data => {
663
- setFeedBackList(data);
664
- });
665
- }, []);
666
-
667
- /**
668
- * 实时同步 fileStatuses 到当前消息的 currentFiles,便于消息区细致显示每个文件的处理状态
669
- */
670
- React.useEffect(() => {
671
- if (!fileStatuses.length) return;
672
- setChatData(chatList => {
673
- if (!chatList[0]) return chatList;
674
- const { messages } = chatList[0];
675
- for (let i = messages.length - 1; i >= 0; i--) {
676
- if (messages[i].istype === 'user') {
677
- const oldFiles = messages[i].currentFiles || [];
678
- messages[i].currentFiles = fileStatuses.map((f: any) => {
679
- const old = oldFiles.find((of: any) => of.uid === f.uid);
680
- return {
681
- name: f.file?.name || f.name,
682
- size: f.file?.size || f.size,
683
- type: f.file?.type || f.type,
684
- status: f.status,
685
- uid: f.uid,
686
- url: f.url || old?.url || '', // 优先用已有 url
687
- };
688
- });
689
- break;
690
- }
691
- }
692
- return [...chatList];
693
- });
694
- }, [fileStatuses]);
695
-
696
- // =================================================================
697
- // Core Functions - 核心功能函数
698
- // =================================================================
699
-
700
- // 1. 在组件作用域定义控制器和轮询停止标志
701
- let uploadController: AbortController | null = null;
702
- let stopPoll: (() => void) | null = null;
703
-
704
- /**
705
- * 轮询文件解析状态
706
- * @param {string[]} uids - 文件UID列表
707
- * @param {(serverStatuses: any[]) => void} onStatusUpdate - 每次获取到新状态后的回调
708
- * @param {() => void} onComplete - 所有文件解析完成后的回调
709
- * @param {(errorMsg: string) => void} onFail - 轮询失败或超时的回调
710
- */
711
- const pollFileStatus = (
712
- uids: string[],
713
- onStatusUpdate: (serverStatuses: any[]) => void,
714
- onComplete: () => void,
715
- onFail: (errorMsg: string) => void
716
- ) => {
717
- const uidsString = uids.join(',');
718
- let pollCount = 0;
719
- // const maxPollCount = 3000;
720
- stopPoll = () => {
721
- stoppedRef.current = true;
722
- };
723
-
724
- const checkStatus = async () => {
725
- if (stoppedRef.current) return;
726
- if (pollCount >= maxPollCount) {
727
- if (!stoppedRef.current) onFail('文件解析超时,请稍后重试');
728
- return;
729
- }
730
- pollCount++;
731
- try {
732
- const res = await axios.get(
733
- `${url}/index/knowledgeBase/file/getFileStatusByUids?uids=${uidsString}`,
734
- {
735
- headers: { Authorization: token },
736
- }
737
- );
738
- if (stoppedRef.current) return;
739
- if (res.data.success) {
740
- const statuses = res.data.data;
741
- if (!stoppedRef.current) onStatusUpdate(statuses);
742
- const allDone = statuses.every((file: any) => file.status === 3);
743
- if (allDone) {
744
- if (!stoppedRef.current) onComplete();
745
- } else {
746
- if (!stoppedRef.current) setTimeout(checkStatus, maxPollInterval);
747
- }
748
- } else {
749
- if (!stoppedRef.current) onFail(res.data.errorMsg || '查询文件状态失败');
750
- }
751
- } catch (error) {
752
- if (stoppedRef.current) return;
753
- onFail('查询文件状态时发生网络错误');
754
- }
755
- };
756
- checkStatus();
757
- };
758
-
759
- /**
760
- * 设置消息的反馈结果(赞/踩)
761
- * @param {string} queryId - 消息ID
762
- * @param {number} result - 反馈结果 (1: 赞, -1: 踩)
763
- */
764
- const setFeed = (queryId: any, restult: any) => {
765
- setChatData(chatList => {
766
- const newList = [...chatList];
767
- if (!newList[0]) return newList;
768
- newList[0] = {
769
- ...newList[0],
770
- messages: newList[0].messages.map((item: any) => {
771
- if (item.queryId === queryId) {
772
- return {
773
- ...item,
774
- feedbackResult: restult,
775
- };
776
- }
777
- return item;
778
- }),
779
- };
780
- return newList;
781
- });
782
- };
783
-
784
- /**
785
- * 获取指定queryId的推荐问题
786
- * @param {string} queryId - 消息ID
787
- */
788
- const fetchRecommendQuestions = async (queryId: string) => {
789
- if (!queryId) return;
790
- try {
791
- // 需要携带当前 configId
792
- const configId =
793
- currentChatData?.configId || assistantMap?.[currentChatData?.configId || '']?.id || '';
794
- const res = await axios.get(
795
- `${url}/qa/ai/recommendQuestion?queryId=${queryId}&configId=${configId || ''}`.replace(
796
- /\?&/,
797
- '?'
798
- ),
799
- {
800
- headers: { Authorization: token },
801
- }
802
- );
803
- setRecommandQuestions(res.data?.data || []);
804
- } catch (e) {
805
- setRecommandQuestions([]);
806
- }
807
- };
808
-
809
- /**
810
- * 处理重新发送消息逻辑
811
- */
812
- function handleReSenderSend(data: any) {
813
- const { content, audioUrl, filePaths, queryId } = data;
814
- if (!activeSessionId || !queryId) return;
815
-
816
- // 从当前会话中按 queryId 定位本次 AI 回复
817
- const msgs = currentChatData?.messages || [];
818
- const aiIdx = msgs.findIndex(
819
- (m: any) => m?.queryId === queryId && (m?.istype === 'ai' || m?.isUser === false)
820
- );
821
-
822
- // 回溯上一条用户消息
823
- let userMsg: any | undefined;
824
- if (aiIdx > 0) {
825
- for (let i = aiIdx - 1; i >= 0; i -= 1) {
826
- const m = msgs[i];
827
- if (m?.istype === 'user' || m?.isUser === true) {
828
- userMsg = m;
829
- break;
830
- }
831
- }
832
- }
833
-
834
- const question = userMsg?.content ?? content;
835
- if (!question) return;
836
-
837
- const sourceFilePaths = userMsg?.filePaths ?? filePaths;
838
- const _fileUids = (
839
- typeof sourceFilePaths === 'string' && sourceFilePaths
840
- ? JSON.parse(sourceFilePaths)
841
- : sourceFilePaths || []
842
- ).map((item: any) => item.uid);
843
- const now = Date.now();
844
- setLastEmptyMessage({ now });
845
- setAppStatus(pre => {
846
- return {
847
- ...pre,
848
- display: 'processing',
849
- sender: 'processing',
850
- };
851
- });
852
-
853
- data.clearFn && data.clearFn();
854
- setConversationList(list =>
855
- list.map(c => (c.sessionId === activeSessionId ? { ...c, gmtModified: now } : c))
856
- );
857
-
858
- api_startChat_re(
859
- {
860
- configId: currentChatData.configId,
861
- content: question,
862
- fileUids: _fileUids,
863
- lastDate: now,
864
- name: currentChatData.label || '',
865
- queryId: queryId,
866
- sessionId: String(activeSessionId || ''),
867
- type: (userMsg?.audioUrl ?? audioUrl) ? 'audioUrl' : 'text',
868
- audioUrl: (userMsg?.audioUrl ?? audioUrl) || '',
869
- enableThinking: !!senderSwitchValues.reasoning,
870
- enableWebsearch: !!senderSwitchValues.netSearch,
871
- qaChannel: senderSwitchValues.qaChannel,
872
- } as any,
873
- gmtModified => {
874
- // 只在AI回复完成后请求推荐问题
875
- fetchRecommendQuestions(queryId);
876
- }
877
- );
878
- }
879
-
880
- // 提取发消息逻辑,确保只有有sessionId时才调用
881
- async function handleSenderSend(data: any, clearFn: () => void) {
882
- // 找到当前会话
883
- if (!activeSessionId) return;
884
- const openEvent = new CustomEvent('aichat:right_set', {
885
- detail: { collapsed: true },
886
- });
887
- window.dispatchEvent(openEvent);
888
- const conv = conversationList.find(c => c.sessionId === activeSessionId);
889
- //console.log('zheli是啥',conv)
890
- if (conv && conv.isNew) {
891
- // 还没落库,先调 create
892
- let createSuccess = false;
893
- // 优先用用户选择的助手newAssistantId,否则用当前会话的configId
894
- const configIdToUse = newAssistantId || conv.configId;
895
- // 用用户输入内容截取20字作为label
896
- const labelToUse =
897
- data && data.content ? data.content.slice(0, 20) : conv.label || '未命名会话';
898
- await new Promise<void>((resolve, reject) => {
899
- handleCreateConversation(
900
- { url, token, CSRFToken },
901
- {
902
- label: labelToUse,
903
- sessionId: conv.sessionId,
904
- sysType: 'INT_SESSION',
905
- configId: configIdToUse,
906
- },
907
- (res: any) => {
908
- if (res && res.data && res.data.sessionId) {
909
- // create成功,标记已落库并更新label/configId
910
- setConversationList(list =>
911
- list.map(c =>
912
- c.sessionId === conv.sessionId
913
- ? { ...c, isNew: false, configId: configIdToUse, label: labelToUse }
914
- : c
915
- )
916
- );
917
- setChatData(list =>
918
- list.map(c =>
919
- c.id === conv.sessionId
920
- ? { ...c, isNew: false, configId: configIdToUse, label: labelToUse }
921
- : c
922
- )
923
- );
924
- createSuccess = true;
925
- resolve();
926
- } else {
927
- message.error('创建会话失败,请重试');
928
- reject();
929
- }
930
- }
931
- );
932
- });
933
- if (!createSuccess) return;
934
- // 继续发消息
935
- sendMessageWithSessionId(activeSessionId as string, data, clearFn, configIdToUse);
936
- return;
937
- }
938
- // 已落库,直接发消息
939
- sendMessageWithSessionId(activeSessionId as string, data, clearFn);
940
- }
941
-
942
- // 修改sendMessageWithSessionId,发消息时用本地会话的configId
943
- function sendMessageWithSessionId(
944
- sessionId: string,
945
- data: any,
946
- clearFn: () => void,
947
- configIdOverride?: string
948
- ) {
949
- const queryId = 'query-' + uid(32);
950
- // 优先用参数传递的 configId
951
- const conv = conversationList.find(c => c.sessionId === sessionId);
952
- const configIdToUse = configIdOverride || conv?.configId || currentChatData.configId;
953
- console.log('助手配置详情', configIdToUse);
954
-
955
- // === 数据流保障:明确保留内容格式,不进行任何 trim 或替换处理 ===
956
- // 确保换行符、空格等格式完整保留,直接传递到后端
957
- const rawContent = data.content || data.text || '';
958
- const preservedContent = typeof rawContent === 'string' ? rawContent : String(rawContent);
959
-
960
- const label = preservedContent ? preservedContent.slice(0, 20) : '未命名会话';
961
- let localCurrentFiles = undefined;
962
- if (data.files && data.files.length > 0) {
963
- localCurrentFiles = data.files.map((fileItem: any) => ({
964
- name: fileItem.file.name,
965
- size: fileItem.file.size,
966
- type: fileItem.file.type,
967
- filePath: fileItem.filePath || '',
968
- convertedFilePath: fileItem.convertedFilePath || '',
969
- uid: fileItem.uid || '',
970
- }));
971
- }
972
- console.log('本地文件上传', data.files);
973
- addEmptyMessage({
974
- content: preservedContent, // 使用保留格式的内容,确保换行和空格完整保留
975
- queryId,
976
- currentFiles: localCurrentFiles,
977
- filePaths: localCurrentFiles ? JSON.stringify(localCurrentFiles) : undefined,
978
- });
979
- // === 新增:如果当前会话是未命名且isNew,首次提问后自动改名并去除isNew ===
980
- setConversationList(list =>
981
- list.map(c =>
982
- c.sessionId === sessionId && c.label === '未命名会话' && c.isNew
983
- ? { ...c, label, gmtModified: Date.now(), isNew: false }
984
- : c
985
- )
986
- );
987
- setChatData(list =>
988
- list.map(c =>
989
- c.id === sessionId && c.label === '未命名会话' && c.isNew
990
- ? { ...c, label, isNew: false }
991
- : c
992
- )
993
- );
994
- // 2. 文件上传逻辑 ---
995
- if (data.files && data.files.length > 0) {
996
- setAppStatus(pre => ({ ...pre, sender: 'uploading', display: 'uploading' }));
997
- uploadController = new AbortController();
998
- stoppedRef.current = false;
999
- const clientFileUids = data.files.map(
1000
- () => `rc-upload-${Date.now()}-${Math.random().toString(36).slice(2)}`
1001
- );
1002
- const initialFileStatuses = data.files.map((fileItem: any, index: number) => ({
1003
- ...fileItem,
1004
- uid: clientFileUids[index],
1005
- status: 'uploading',
1006
- }));
1007
- setFileStatuses(initialFileStatuses);
1008
- const formData = new FormData();
1009
- data.files.forEach((fileItem: any) => {
1010
- formData.append('files', fileItem.file);
1011
- });
1012
- const sessionIdStr = String(sessionId || '');
1013
- formData.append('sessionId', sessionIdStr);
1014
- formData.append('uids', clientFileUids.join(','));
1015
- axios
1016
- .post(`${url}/index/knowledgeBase/file/uploadFiles`, formData, {
1017
- headers: {
1018
- Authorization: token,
1019
- 'Content-Type': 'multipart/form-data',
1020
- },
1021
- signal: uploadController.signal,
1022
- })
1023
- .then(response => {
1024
- console.log('文件上传的打印结果', response);
1025
- if (stoppedRef.current) return;
1026
- if (
1027
- response.data.success &&
1028
- Array.isArray(response.data.data) &&
1029
- response.data.data.length > 0
1030
- ) {
1031
- // === 新增:合并后端返回字段到 fileStatuses ===
1032
- setFileStatuses(prev => {
1033
- return prev.map(localFile => {
1034
- const serverFile = response.data.data.find((f: any) => f.uid === localFile.uid);
1035
- return serverFile ? { ...localFile, ...serverFile } : localFile;
1036
- });
1037
- });
1038
- setAppStatus(pre => ({ ...pre, sender: 'processing', display: 'analyzing' }));
1039
- setFileStatuses(prev => prev.map(f => ({ ...f, status: 'parsing' })));
1040
- const uploadedFilesData = response.data.data;
1041
- const serverUids = uploadedFilesData.map((f: any) => f.uid);
1042
- pollFileStatus(
1043
- serverUids,
1044
- serverStatuses => {
1045
- setFileStatuses(currentLocalStatuses => {
1046
- return currentLocalStatuses.map(localFile => {
1047
- const correspondingServerFile = serverStatuses.find(
1048
- (sf: any) => sf.uid === localFile.uid
1049
- );
1050
- if (correspondingServerFile) {
1051
- switch (correspondingServerFile.status) {
1052
- case 3:
1053
- return { ...localFile, status: 'done' };
1054
- case 4:
1055
- return { ...localFile, status: 'error' };
1056
- case 1:
1057
- case 2:
1058
- default:
1059
- return { ...localFile, status: 'parsing' };
1060
- }
1061
- }
1062
- return localFile;
1063
- });
1064
- });
1065
- // === 新增:全部完成时清空 sender 区 ===
1066
- const allDone =
1067
- serverStatuses.length > 0 &&
1068
- serverStatuses.every((file: any) => file.status === 3);
1069
- if (allDone) {
1070
- setFileStatuses([]);
1071
- // 上传完成后合并新文件到 uploadedFiles,保证结构统一
1072
- const map = new Map();
1073
- (serverStatuses || []).forEach((item: any) => {
1074
- map.set(item.id, item);
1075
- });
1076
- setFileManagerData(prev => {
1077
- const r = mergeFiles(prev.uploadedFiles, uploadedFilesData);
1078
-
1079
- return {
1080
- uploadedFiles: r.map(item => {
1081
- return {
1082
- ...item,
1083
- pdfPages: map.get(item.id)?.pdfPages || 0, // 保留后端返回的 pdfPages 字段
1084
- };
1085
- }),
1086
- };
1087
- });
1088
- }
1089
- },
1090
- // onComplete: 全部解析成功后才发起AI请求
1091
- () => {
1092
- clearFn?.();
1093
- setAppStatus(pre => ({ ...pre, sender: 'processing', display: 'processing' }));
1094
- // === 新增:回填 filePath 到 fileStatuses ===
1095
- setFileStatuses(prev => {
1096
- return prev.map(localFile => {
1097
- const serverFile = uploadedFilesData.find(
1098
- (f: any) => f.uid === localFile.uid
1099
- );
1100
-
1101
- if (serverFile) {
1102
- return {
1103
- ...localFile,
1104
- ...serverFile, // 合并后端所有字段
1105
- url: serverFile.filePath, // 兼容 url 字段
1106
- filePath: serverFile.filePath,
1107
- name: serverFile.fileName || localFile.name,
1108
- convertedFilePath:
1109
- serverFile.convertedFilePath || localFile.convertedFilePath,
1110
- };
1111
- }
1112
- return localFile;
1113
- });
1114
- });
1115
- // === 同步 currentFiles 字段到 chatData ===
1116
- setChatData(chatList => {
1117
- if (!chatList[0]) return chatList;
1118
- const { messages } = chatList[0];
1119
- for (let i = messages.length - 1; i >= 0; i--) {
1120
- if (messages[i].istype === 'user') {
1121
- const oldFiles = messages[i].currentFiles || [];
1122
- messages[i].currentFiles = oldFiles.map((localFile: any) => {
1123
- const serverFile = uploadedFilesData.find(
1124
- (f: any) => f.uid === localFile.uid
1125
- );
1126
- return serverFile ? { ...localFile, ...serverFile } : localFile;
1127
- });
1128
- break;
1129
- }
1130
- }
1131
- return [...chatList];
1132
- });
1133
- // === 发起AI请求 ===
1134
- const now = Date.now();
1135
- api_startChat_re(
1136
- {
1137
- configId: configIdToUse,
1138
- content: preservedContent, // 使用保留格式的内容,确保换行和空格完整传递到后端
1139
- fileUids: serverUids,
1140
- lastDate: now,
1141
- name: label,
1142
- queryId: queryId,
1143
- sessionId: String(sessionId || ''),
1144
- type: 'text',
1145
- audioUrl: '',
1146
- enableThinking: !!senderSwitchValues.reasoning,
1147
- enableWebsearch: !!senderSwitchValues.netSearch,
1148
- qaChannel: senderSwitchValues.qaChannel,
1149
- } as any,
1150
- gmtModified => {
1151
- fetchRecommendQuestions(queryId);
1152
- }
1153
- );
1154
- },
1155
- (errorMsg: string) => {
1156
- setAppStatus(pre => ({ ...pre, display: 'ready', sender: 'ready' }));
1157
- setFileStatuses(prev =>
1158
- prev.map(f => ({ ...f, status: 'error', message: errorMsg }))
1159
- );
1160
- }
1161
- );
1162
- } else {
1163
- const errorMsg = response.data.errorMsg || '文件上传失败';
1164
- setAppStatus(pre => ({ ...pre, display: 'error', sender: 'ready' }));
1165
- setFileStatuses(prev =>
1166
- prev.map(f => ({ ...f, status: 'error', message: errorMsg }))
1167
- );
1168
- }
1169
- })
1170
- .catch(error => {
1171
- // 检查是否为文件大小超限错误 (413)
1172
- if (error?.response?.status === 413) {
1173
- if (error?.response?.statusText.includes('Request Entity Too Large')) {
1174
- message.error('文件超过最大可上传限制');
1175
- }
1176
- } else {
1177
- // 其他错误显示通用网络错误提示
1178
- message.error('网络错误');
1179
- }
1180
-
1181
- setAppStatus(pre => ({ ...pre, display: 'error', sender: 'ready' }));
1182
- setFileStatuses(prev =>
1183
- prev.map(f => ({ ...f, status: 'error', message: '网络错误' }))
1184
- );
1185
- });
1186
- return;
1187
- }
1188
- // 3. 无文件,直接发起AI请求
1189
- setAppStatus(pre => ({ ...pre, display: 'processing', sender: 'processing' }));
1190
- const now = Date.now();
1191
- setConversationList(list =>
1192
- list.map(c => (c.sessionId === sessionId ? { ...c, gmtModified: now } : c))
1193
- );
1194
- clearFn?.();
1195
- api_startChat_re(
1196
- {
1197
- configId: configIdToUse,
1198
- content: preservedContent, // 使用保留格式的内容,确保换行和空格完整传递到后端
1199
- fileUids: [],
1200
- lastDate: now,
1201
- name: label,
1202
- queryId: queryId,
1203
- sessionId: String(sessionId || ''),
1204
- type: 'text',
1205
- audioUrl: '',
1206
- enableThinking: !!senderSwitchValues.reasoning,
1207
- enableWebsearch: !!senderSwitchValues.netSearch,
1208
- qaChannel: senderSwitchValues.qaChannel,
1209
- } as any,
1210
- gmtModified => {
1211
- fetchRecommendQuestions(queryId);
1212
- }
1213
- );
1214
- }
1215
-
1216
- // =================================================================
1217
- // Event Handlers - 事件处理器
1218
- // =================================================================
1219
-
1220
- /**
1221
- * 处理点赞反馈
1222
- */
1223
- function handleThumbsup(data: any) {
1224
- if (data.restult == 1) {
1225
- handleCancelFeedBack({ url, token, CSRFToken }, { queryId: data.queryId }, () => {
1226
- setFeed(data.queryId, null);
1227
- });
1228
- } else {
1229
- handleFeedBack({ url, token, CSRFToken }, { restult: 1, queryId: data.queryId }, () => {
1230
- setFeed(data.queryId, 1);
1231
- });
1232
- }
1233
- }
1234
-
1235
- /**
1236
- * 处理新建一个临时会话
1237
- */
1238
- function handleConversationCreate(data: any) {
1239
- const sessionId = uid(32);
1240
- // 新会话对象,等待用户输入后再发起创建请求
1241
- const newConversation = {
1242
- sessionId,
1243
- label: '未命名会话',
1244
- gmtModified: Date.now(),
1245
- searchConfigDTO: {},
1246
- filePath: '',
1247
- configId: '',
1248
- isNew: true, // 标记为新会话
1249
- };
1250
- // 在列表顶部插入新会话
1251
- setConversationList(list => [{ ...newConversation, messages: [] }, ...list]);
1252
- setChatData(list => [{ id: sessionId, messages: [], ...newConversation }, ...list]);
1253
- // 激活新会话
1254
- setActiveSessionId(sessionId);
1255
- }
1256
-
1257
- /**
1258
- * 文件管理器:处理文件选择后的上传
1259
- */
1260
- const handleFileManagerUpload = (fileList: FileList) => {
1261
- // 1. 收集所有已经存在的文件名
1262
- const existingFileNames = new Set<string>([
1263
- ...fileManagerData.uploadedFiles.map((f: any) => f.file.name as string),
1264
- ...pendingFiles.map((f: any) => f.file.name as string),
1265
- ]);
1266
-
1267
- const newFiles: { file: File; type: string; status: string; preview?: string }[] = [];
1268
- const duplicateFileNames = new Set<string>();
1269
-
1270
- // 2. 遍历新选择的文件,筛选出重复项和有效项
1271
- Array.from(fileList).forEach(file => {
1272
- if (existingFileNames.has(file.name)) {
1273
- duplicateFileNames.add(file.name);
1274
- } else {
1275
- newFiles.push({
1276
- file,
1277
- type: getFileTypeByName(file.name),
1278
- status: 'pending',
1279
- preview: file.type.startsWith('image') ? URL.createObjectURL(file) : undefined,
1280
- });
1281
- existingFileNames.add(file.name); // 添加到Set中,以防本次上传的文件之间有重复
1282
- }
1283
- });
1284
-
1285
- // 3. 如果有重复,发出警告
1286
- if (duplicateFileNames.size > 0) {
1287
- message.warning(`不能上传同名文件: ${Array.from(duplicateFileNames).join(', ')}`);
1288
- }
1289
-
1290
- // 4. 将有效的文件添加到待上传列表
1291
- if (newFiles.length > 0) {
1292
- setPendingFiles(prev => [...prev, ...newFiles]);
1293
- // 直接同步到核心发送器组件
1294
- setUploadedFilesRef.current?.(newFiles);
1295
- }
1296
- };
1297
-
1298
- /**
1299
- * 文件管理器:处理文件移除
1300
- */
1301
- const handleFileManagerRemove = (fileObj: any, idx: number, _type: string) => {
1302
- removeFileRef.current?.(fileObj, idx, _type);
1303
- };
1304
-
1305
- /**
1306
- * 处理会话列表项点击
1307
- */
1308
- function handleItemClick(data: any) {
1309
- if (data?.sessionId && data.sessionId !== activeSessionId) {
1310
- // 如果切换会话时,有正在进行的流式请求(且请求属于当前会话),则取消它
1311
- // 这样可以防止在流式输出开始前切换会话时,后续数据写入错误的会话
1312
- if (activeSessionId) {
1313
- cancelStreamBySessionId(activeSessionId);
1314
- }
1315
- setActiveSessionId(data.sessionId);
1316
- setAppStatus(prev => ({ ...prev, sender: 'ready' }));
1317
- // 点击会话时,使用其最后一条AI消息的推荐问题
1318
- const conv = chatData.find(c => c.id === data.sessionId);
1319
- if (conv && conv.messages && conv.messages.length > 0) {
1320
- const lastAiMsg = [...conv.messages].reverse().find((m: any) => m.istype === 'ai');
1321
- if (lastAiMsg && lastAiMsg.recommendQuestion) {
1322
- setRecommandQuestions(lastAiMsg.recommendQuestion);
1323
- } else {
1324
- setRecommandQuestions([]);
1325
- }
1326
- } else {
1327
- setRecommandQuestions([]);
1328
- }
1329
- }
1330
- }
1331
-
1332
- // =================================================================
1333
- // Async Data Operations - 异步数据操作 (供事件发射器使用)
1334
- // =================================================================
1335
-
1336
- /**
1337
- * 异步删除会话接口
1338
- */
1339
- const async_deleteConversation = async (sessionId: string) => {
1340
- return new Promise((resolve, reject) => {
1341
- handleDeleteConversation({ url, token, CSRFToken }, { sessionId }, (res: any) => {
1342
- if (res) {
1343
- message.success('删除成功!');
1344
- resolve(res);
1345
- } else {
1346
- message.error('删除失败!');
1347
- reject(res);
1348
- }
1349
- });
1350
- });
1351
- };
1352
- /**
1353
- * 异步刷新会话列表接口
1354
- */
1355
- const async_refreshConversationList = async () => {
1356
- try {
1357
- // 重置为第一页
1358
- setConversationList([]);
1359
- setConvTotal(0);
1360
- await fetchConversationPage(1);
1361
- return [];
1362
- } catch (e) {
1363
- message.error('刷新会话列表失败');
1364
- throw e;
1365
- }
1366
- };
1367
-
1368
- /**
1369
- * 异步重命名会话接口
1370
- */
1371
- const async_renameConversation = async (sessionId: string, newLabel: string) => {
1372
- return new Promise((resolve, reject) => {
1373
- handleRename({ url, token, CSRFToken }, { label: newLabel, sessionId }, res => {
1374
- if (res) {
1375
- // 成功后立即更新本地状态
1376
- const now = Date.now();
1377
- setConversationList(list =>
1378
- list.map(item =>
1379
- item.sessionId === sessionId ? { ...item, label: newLabel, gmtModified: now } : item
1380
- )
1381
- );
1382
- message.success('重命名成功!');
1383
- resolve(res);
1384
- } else {
1385
- message.error('重命名失败');
1386
- reject(res);
1387
- }
1388
- });
1389
- });
1390
- };
1391
-
1392
- // =================================================================
1393
- // Local State Updaters - 本地状态更新 (供事件发射器使用)
1394
- // =================================================================
1395
-
1396
- /**
1397
- * 从本地状态中移除会话项
1398
- */
1399
- const fn_removeItemFromList = (sessionId: string) => {
1400
- setConversationList(list => {
1401
- const newList = list.filter(c => c.sessionId !== sessionId);
1402
- // 如果删除的是当前会话,则激活列表中的第一个
1403
- if (activeSessionId === sessionId) {
1404
- if (newList.length > 0) {
1405
- setActiveSessionId(newList[0].sessionId);
1406
- } else {
1407
- // 如果列表空了,则新建一个
1408
- handleConversationCreate({});
1409
- }
1410
- }
1411
- return newList;
1412
- });
1413
- };
1414
-
1415
- /**
1416
- * 在本地状态中重命名会话项
1417
- */
1418
- const fn_renameItemInList = (sessionId: string, newLabel: string) => {
1419
- const now = Date.now();
1420
- setConversationList(list =>
1421
- list.map(item =>
1422
- item.sessionId === sessionId ? { ...item, label: newLabel, gmtModified: now } : item
1423
- )
1424
- );
1425
- };
1426
-
1427
- const handleFeedDownConfirm = (data: any) => {
1428
- handleFeedBack({ url, token, CSRFToken }, { ...data, ...feedParam, restult: 0 }, () => {
1429
- setFeed(feedParam.queryId, 0);
1430
- });
1431
- };
1432
-
1433
- const editDialog = (data: any) => {
1434
- const newLabel = data.new_name;
1435
- const oldLabel = curEditData.data.label;
1436
- if (newLabel && newLabel !== oldLabel) {
1437
- curEditData
1438
- .async_renameConversation(newLabel)
1439
- .then(() => {
1440
- curEditData.fn_renameItemInList(newLabel);
1441
- setisRenameModalOpen(false);
1442
- })
1443
- .catch(() => {
1444
- // 重命名失败
1445
- });
1446
- } else {
1447
- setisRenameModalOpen(false);
1448
- }
1449
- };
1450
-
1451
- const editRemove = (data: any) => {
1452
- curEditData
1453
- .async_deleteConversation()
1454
- .then(() => {
1455
- curEditData.fn_removeItemFromList();
1456
- setisRemoveModalOpen(false);
1457
- })
1458
- .catch(() => {
1459
- // 删除失败
1460
- });
1461
- };
1462
-
1463
- const handleEvent = (type: string, data?: any) => {
1464
- console.log(type, data);
1465
- switch (type) {
1466
- case 'close_remove':
1467
- setisRemoveModalOpen(false);
1468
- break;
1469
- case 'close_rename':
1470
- setisRenameModalOpen(false);
1471
- break;
1472
- case 'ok_rename':
1473
- editDialog(data);
1474
- break;
1475
- case 'ok_remove':
1476
- editRemove(data);
1477
- break;
1478
- }
1479
- };
1480
-
1481
- // =================================================================
1482
- // Event Emitter - 事件分发器
1483
- // =================================================================
1484
-
1485
- const getDataBaseData = async ({ url, params, replacePredataFunction }: any) => {
1486
- try {
1487
- const res = await axios.post(url, params, {
1488
- headers: { Authorization: token },
1489
- });
1490
- const data = res?.data?.data?.data;
1491
- if (data) {
1492
- replacePredataFunction(data);
1493
- }
1494
- } catch (error) {
1495
- console.log('error', error);
1496
- }
1497
- };
1498
-
1499
- /**
1500
- * 统一事件分发器,连接业务逻辑与所有子组件的事件
1501
- * @param {string} eventName - 事件名称
1502
- * @param {any} data - 事件数据
1503
- */
1504
- const mergedEventsEmit = (eventName: string, data: any) => {
1505
- console.log(`[Event] ${eventName}`, data);
1506
- switch (eventName) {
1507
- case 'conversations:load_more': {
1508
- const hasMore = conversationList.length < convTotal;
1509
- if (hasMore && !convLoading) {
1510
- fetchConversationPage(convPageNo + 1);
1511
- }
1512
- break;
1513
- }
1514
- case 'retrieve-sql-data:pagingation_click':
1515
- const { page, pageSize, fetchUrl, source, replacePredataFunction } = data;
1516
- getDataBaseData({
1517
- url: `${url}${fetchUrl}`,
1518
- replacePredataFunction,
1519
- params: { pageNo: page, pageSize, convertedFilePath: source, stream: false },
1520
- });
1521
- break;
1522
- case 'web_referenceFile_title:click':
1523
- if (!data?.data?.link) return console.error('没有网页地址');
1524
- window.open(data.data.link, '_blank');
1525
- break;
1526
- // --- 对话列表事件 ---
1527
- case 'conversation:item_click':
1528
- handleItemClick(data);
1529
- break;
1530
-
1531
- case 'files:finished_animation_complete':
1532
- setFileStatuses([]);
1533
- break;
1534
-
1535
- case 'conversation:create':
1536
- handleConversationCreate(data);
1537
- break;
1538
- case 'conversation:new_assistant_change':
1539
- setNewAssistantId(data.assistantId);
1540
- break;
1541
- case 'conversations:rename_icon_clicked':
1542
- setCurEditData({
1543
- data,
1544
- async_renameConversation: (newLabel: string) =>
1545
- async_renameConversation(data.sessionId, newLabel),
1546
- fn_renameItemInList: (newLabel: string) =>
1547
- fn_renameItemInList(data.sessionId, newLabel),
1548
- });
1549
- setisRenameModalOpen(true);
1550
- break;
1551
- case 'conversations:delete_icon_clicked':
1552
- setCurEditData({
1553
- data,
1554
- async_deleteConversation: () => async_deleteConversation(data.sessionId),
1555
- async_refreshConversationList,
1556
- fn_removeItemFromList: () => fn_removeItemFromList(data.sessionId),
1557
- });
1558
- setisRemoveModalOpen(true);
1559
- break;
1560
- case 'sender:send':
1561
- handleSenderSend(data, data.clearFn);
1562
- break;
1563
- case 'sender:send_recommandQuestion': {
1564
- // 旧链路:来自 Sender 的推荐问题,可能已经在 AiChat 内转发为 sender:send
1565
- // 这里兜底处理,确保能直接触发发送
1566
- const content = (data?.content ?? '').toString();
1567
- if (!content) break;
1568
- handleSenderSend({ content }, () => {});
1569
- break;
1570
- }
1571
- case 'chatbox:follow_up_question_click': {
1572
- // 新链路:来自 ChatMessageAdapter 的追问点击
1573
- const content = (data?.question ?? data?.content ?? '').toString();
1574
- if (!content) break;
1575
- handleSenderSend({ content }, () => {});
1576
- break;
1577
- }
1578
- case 'sender:action_history':
1579
- setFileManagerOpen(true);
1580
- break;
1581
- case 'sender:stop':
1582
- stoppedRef.current = true;
1583
- if (uploadController) {
1584
- uploadController.abort();
1585
- uploadController = null;
1586
- }
1587
- if (stopPoll) {
1588
- stopPoll();
1589
- stopPoll = null;
1590
- }
1591
- setAppStatus(pre => ({ ...pre, display: 'ready', sender: 'ready' }));
1592
- setFileStatuses([]);
1593
- stopStream?.();
1594
- break;
1595
- case 'sender:clear':
1596
- data.clearFn?.();
1597
- break;
1598
- case 'sender:configChange':
1599
- // 配置项变化,记录最新 switch 状态
1600
- if (data && data.all) {
1601
- setSenderSwitchValues(data.all);
1602
- }
1603
- break;
1604
-
1605
- // --- 消息卡片事件 ---
1606
- case 'action_copy:click':
1607
- if (data) {
1608
- toCopy(data.content, data.event);
1609
- }
1610
- break;
1611
- case 'chatbox:copy': {
1612
- const text = data?.content || '';
1613
- if (!text) break;
1614
- // 直接使用 Clipboard API,避免依赖 event.currentTarget
1615
- const copyByClipboardApi = async (t: string) => {
1616
- try {
1617
- await navigator.clipboard.writeText(t);
1618
- message.success('已复制到剪贴板');
1619
- return true;
1620
- } catch (_) {
1621
- return false;
1622
- }
1623
- };
1624
- const fallbackCopy = (t: string) => {
1625
- const textarea = document.createElement('textarea');
1626
- textarea.value = t;
1627
- textarea.style.position = 'fixed';
1628
- textarea.style.opacity = '0';
1629
- document.body.appendChild(textarea);
1630
- textarea.focus();
1631
- textarea.select();
1632
- try {
1633
- document.execCommand('copy');
1634
- message.success('已复制到剪贴板');
1635
- } catch (_) {
1636
- message.error('复制失败');
1637
- }
1638
- document.body.removeChild(textarea);
1639
- };
1640
- copyByClipboardApi(text).then(ok => {
1641
- if (!ok) fallbackCopy(text);
1642
- });
1643
- break;
1644
- }
1645
- case 'chatbox:repeat':
1646
- console.log(data, 'sdkflskdjflksdjfklsdjlfkjsdklfjsdklfjlks');
1647
- handleReSenderSend(data);
1648
- break;
1649
- case 'action_thumbsup':
1650
- handleThumbsup(data);
1651
- break;
1652
- case 'chatbox:like':
1653
- handleThumbsup({ queryId: data?.queryId, restult: data?.result });
1654
- break;
1655
- case 'action_thumbsdown':
1656
- if (data.restult === 0) {
1657
- handleCancelFeedBack({ url, token, CSRFToken }, { queryId: data.queryId }, () => {
1658
- setFeed(data.queryId, null);
1659
- });
1660
- } else {
1661
- setFeedParam(data);
1662
- setOpenFeed(true);
1663
- }
1664
- break;
1665
- case 'chatbox:dislike':
1666
- if (data?.result === 0) {
1667
- handleCancelFeedBack({ url, token, CSRFToken }, { queryId: data.queryId }, () => {
1668
- setFeed(data.queryId, null);
1669
- });
1670
- } else {
1671
- setFeedParam({ queryId: data?.queryId });
1672
- setOpenFeed(true);
1673
- }
1674
- break;
1675
- case 'action_retrive_tag':
1676
- // 处理 retrive-tag 点击事件,透传给父组件
1677
- eventsEmit?.('action_retrive_tag', data);
1678
- break;
1679
- case 'referenceFile_view':
1680
- // 处理文件预览事件,透传给父组件
1681
- eventsEmit?.('referenceFile_view', data);
1682
- break;
1683
- case 'referenceFile_question':
1684
- // 处理单文档对话事件,透传给父组件
1685
- console.log(data, 'zhezhhzhzh');
1686
- eventsEmit?.('referenceFile_question', data);
1687
- break;
1688
- case 'referenceFile_download':
1689
- // 处理文件下载事件,透传给父组件
1690
- eventsEmit?.('referenceFile_download', data);
1691
- break;
1692
- case 'references:click': {
1693
- // 使用 AiChat 内置的右侧栏事件
1694
- const Content = () => {
1695
- // const safe = (() => {
1696
- // try {
1697
- // return typeof data === 'string' ? data : JSON.stringify(data, null, 2);
1698
- // } catch (e) {
1699
- // return String(data);
1700
- // }
1701
- // })();
1702
- return (
1703
- <ReferenceBar
1704
- type={DrawerType.REFERENCELIST}
1705
- data={data}
1706
- token={token}
1707
- eventsEmit={eventsEmit}
1708
- is_download={is_download}
1709
- />
1710
- );
1711
- };
1712
- const setContentEvent = new CustomEvent('aichat:right_set_content', {
1713
- detail: { content: <Content /> },
1714
- });
1715
- window.dispatchEvent(setContentEvent);
1716
- const openEvent = new CustomEvent('aichat:right_set', {
1717
- detail: { collapsed: false },
1718
- });
1719
- window.dispatchEvent(openEvent);
1720
- break;
1721
- }
1722
- case 'retrive_tag:click':
1723
- // 处理 retrive-tag 点击事件,透传给父组件
1724
- eventsEmit?.('retrive_tag:click', data);
1725
- break;
1726
- // --- 文件管理器事件 ---
1727
- case 'fileManager:change': {
1728
- const files = Array.isArray(data?.uploadedFiles) ? data.uploadedFiles : [];
1729
- setPendingFiles(files);
1730
- // 保存核心组件传递的文件处理函数引用
1731
- if (typeof data?.setUploadedFiles === 'function') {
1732
- setUploadedFilesRef.current = data.setUploadedFiles;
1733
- removeFileRef.current = data.removeFile;
1734
- }
1735
- break;
1736
- }
1737
-
1738
- // --- 文件管理器上传文件删除事件,透传到业务层 ---
1739
- case 'uploaded_file:removeFromTemp': {
1740
- console.log('[DEBUG] mergedEventsEmit uploaded_file:removeFromTemp 事件', data);
1741
-
1742
- const uid = data?.file?.uid;
1743
- if (!uid) {
1744
- console.warn('[DEBUG] 缺少uid,无法删除临时文件', data);
1745
- break;
1746
- }
1747
- // 获取当前对话最后一条 AI 消息的 queryId
1748
- const lastAiMsg = [...(currentChatData.messages || [])]
1749
- .reverse()
1750
- .find((msg: any) => msg.istype === 'user');
1751
- const queryId = lastAiMsg?.queryId;
1752
-
1753
- removeFilefromTempUpload({ url, token, CSRFToken }, { uid, queryId }, (success, res) => {
1754
- if (success) {
1755
- message.success('文件已从临时知识库移除');
1756
- // 用后端返回的新data数组(新文件列表)更新本地uploadedFiles
1757
- //console.log('[DEBUG] removeFilefromTempUpload 回调 true,res:', res, Array.isArray(res.data && res.data.data));
1758
- if (res && Array.isArray(res.data && res.data.data)) {
1759
- const uploaded = res.data.data.map((f: any) => {
1760
- const fileName = f.name || f.fileName || '';
1761
- return {
1762
- file: {
1763
- name: fileName,
1764
- size: Number(f.size?.replace('MB', '')) * 1024 * 1024 || 0,
1765
- type: f.type,
1766
- } as File,
1767
- type: getFileTypeByName(fileName),
1768
- status: 'uploaded' as const,
1769
- url: f.filePath,
1770
- convertedFilePath: f.convertedFilePath,
1771
- uid: f.uid,
1772
- preview: f.type === 'image' ? f.filePath : undefined,
1773
- };
1774
- });
1775
- // console.log('[DEBUG] uploaded 构造完成:', uploaded, '当前 fileManagerData:', fileManagerData);
1776
- setFileManagerData({ uploadedFiles: uploaded });
1777
- } else {
1778
- }
1779
- } else {
1780
- console.log('[DEBUG] removeFilefromTempUpload 回调 false,res:', res);
1781
- message.error('文件移除失败');
1782
- }
1783
- });
1784
- break;
1785
- }
1786
- case 'uploaded_file:remove_batch':
1787
- break;
1788
-
1789
- default:
1790
- // 其他未处理事件可继续向上层抛出
1791
- eventsEmit?.(eventName, data);
1792
- }
1793
- };
1794
-
1795
- // =================================================================
1796
- // Component & UI Configuration - 组件及UI配置
1797
- // =================================================================
1798
-
1799
- /**
1800
- * Sidebar 配置
1801
- */
1802
- const sidebar: SidebarTabConfig[] = [
1803
- {
1804
- key: 'conversations',
1805
- type: 'custom',
1806
- label: '对话历史',
1807
- icon: <History size={16} />,
1808
- enabled: true,
1809
- component: (
1810
- <GientechConversationPanel
1811
- data={conversationList}
1812
- assistantList={assistantList}
1813
- activedItem={activeSessionId || ''}
1814
- hasMore={conversationList.length < convTotal}
1815
- loadingMore={convLoading}
1816
- sortRules={[
1817
- { label: '当天', dayPeriod: 1 },
1818
- { label: '3天', dayPeriod: 3 },
1819
- { label: '7天', dayPeriod: 7 },
1820
- { label: '30天', dayPeriod: 30 },
1821
- ]}
1822
- eventsEmit={mergedEventsEmit}
1823
- styles={normalizedStyles.theme}
1824
- />
1825
- ),
1826
- },
1827
- ];
1828
-
1829
- /**
1830
- * 业务层自定义组件
1831
- */
1832
- const WelcomeComponent = React.useCallback(() => {
1833
- return (
1834
- <GientechNewChatWelcome
1835
- eventsEmit={mergedEventsEmit}
1836
- assistantList={assistantList}
1837
- styles={normalizedStyles}
1838
- selectedId={selectedAssistantId}
1839
- onSelectAssistant={setSelectedAssistantId}
1840
- productLogo={rest?.productLogo}
1841
- />
1842
- );
1843
- }, [mergedEventsEmit, assistantList, normalizedStyles, selectedAssistantId, rest?.productLogo]);
1844
-
1845
- const businessCustomComponents = React.useMemo(
1846
- () => ({
1847
- AiChatBox: (msg: any, idx: number) => {
1848
- const isLastMessage = idx === (currentChatData?.messages?.length || 0) - 1;
1849
-
1850
- // 根据消息的 status 和 appStatus 来确定 displayStatus
1851
- let displayStatus = 'ready';
1852
- if (isLastMessage) {
1853
- // 优先使用消息的 status 字段
1854
- if (msg.status !== undefined) {
1855
- switch (msg.status) {
1856
- case 0: // StatusType.Pending
1857
- displayStatus = 'thinking';
1858
- break;
1859
- case 1: // StatusType.Process
1860
- displayStatus = 'processing';
1861
- break;
1862
- case 2: // StatusType.Done
1863
- displayStatus = 'ready';
1864
- break;
1865
- case 3: // StatusType.Error
1866
- displayStatus = 'error';
1867
- break;
1868
- default:
1869
- displayStatus = appStatus.display;
1870
- }
1871
- } else {
1872
- // 如果没有 status 字段,使用 appStatus.display
1873
- displayStatus = appStatus.display;
1874
- }
1875
- }
1876
- // 将推荐问题强制转换为数组,避免切换会话时报 .map 错误
1877
- let safeFollowUps: string[] = [];
1878
- if (Array.isArray(recommandQuestions)) {
1879
- safeFollowUps = recommandQuestions as string[];
1880
- } else if (typeof recommandQuestions === 'string') {
1881
- try {
1882
- safeFollowUps = JSON.parse(recommandQuestions) || [];
1883
- } catch {
1884
- safeFollowUps = [];
1885
- }
1886
- }
1887
- // 保证传入 ChatMessageAdapter 的 reference/webReference/graphReference 始终是有效的 JSON 字符串
1888
- const safeReference = (() => {
1889
- const r = (msg as any)?.reference;
1890
- if (!r) return '[]';
1891
- if (typeof r === 'string') {
1892
- try {
1893
- JSON.parse(r);
1894
- return r;
1895
- } catch {
1896
- return '[]';
1897
- }
1898
- }
1899
- try {
1900
- return JSON.stringify(r);
1901
- } catch {
1902
- return '[]';
1903
- }
1904
- })();
1905
- const safeWebReference = (() => {
1906
- const r = (msg as any)?.webReference;
1907
- if (!r) return '[]';
1908
- if (typeof r === 'string') {
1909
- try {
1910
- JSON.parse(r);
1911
- return r;
1912
- } catch {
1913
- return '[]';
1914
- }
1915
- }
1916
- try {
1917
- return JSON.stringify(r);
1918
- } catch {
1919
- return '[]';
1920
- }
1921
- })();
1922
- const safeGraphReference = (() => {
1923
- const r = (msg as any)?.graphReference;
1924
- if (!r) return '[]';
1925
- if (typeof r === 'string') {
1926
- try {
1927
- JSON.parse(r);
1928
- return r;
1929
- } catch {
1930
- return '[]';
1931
- }
1932
- }
1933
- try {
1934
- return JSON.stringify(r);
1935
- } catch {
1936
- return '[]';
1937
- }
1938
- })();
1939
- return (
1940
- <ChatMessageAdapter
1941
- key={`${msg?.queryId || msg?.id || idx}-${msg?.istype || 'unknown'}`}
1942
- {...msg}
1943
- referenceMode="button"
1944
- reference={safeReference}
1945
- webReference={safeWebReference}
1946
- graphReference={safeGraphReference}
1947
- contentType="stream" // 添加 contentType 确保 slateContent 能正确生成
1948
- displayStatus={displayStatus}
1949
- eventsEmit={mergedEventsEmit}
1950
- // 仅最后一条 AI 消息展示追问
1951
- isLast={isLastMessage && msg?.istype === 'ai'}
1952
- followUpQuestions={isLastMessage && msg?.istype === 'ai' ? safeFollowUps : []}
1953
- defaultAnswer={
1954
- currentChatData?.searchConfigDTO?.defaultAnswer ||
1955
- '不知道什么原因我们没能查到你要的问题*-*'
1956
- }
1957
- is_download={is_download}
1958
- styles={normalizedStyles as any}
1959
- />
1960
- );
1961
- },
1962
- LogoBox: (props: any) => {
1963
- if (props && props.LogoBox === null) return null;
1964
- if (props && typeof props.LogoBox === 'function') return <props.LogoBox />;
1965
- return <div className="text-2xl w-full text-center font-bold">小鲸智能助手</div>;
1966
- },
1967
- DisplayLoading: () => <DisplayLoading />,
1968
- DisplayError: () => <DisplayError />,
1969
- AppError: () => (
1970
- <AppError
1971
- msg="应用初始化失败"
1972
- subMsg="无法完成应用初始化,这可能是由于网络连接问题或服务配置错误导致的。请检查您的网络连接并重试。"
1973
- />
1974
- ),
1975
- AppLoading: () => (
1976
- <AppLoading
1977
- title={rest?.appLoadingConfig?.title}
1978
- subtitle={rest?.appLoadingConfig?.subtitle || ''}
1979
- />
1980
- ),
1981
- UserChatBox: (msg: any, idx: number) => {
1982
- return (
1983
- <ChatMessageAdapter
1984
- key={`${msg?.queryId || msg?.id || idx}-user`}
1985
- {...msg}
1986
- referenceMode="button"
1987
- contentType="plainText"
1988
- isUser={true}
1989
- displayStatus="ready"
1990
- eventsEmit={mergedEventsEmit}
1991
- styles={normalizedStyles as any}
1992
- fileManagerData={fileManagerData}
1993
- />
1994
- );
1995
- },
1996
- WelcomeComponent,
1997
- }),
1998
- [
1999
- WelcomeComponent,
2000
- currentChatData,
2001
- appStatus.display,
2002
- mergedEventsEmit,
2003
- normalizedStyles,
2004
- is_download,
2005
- fileManagerData,
2006
- ]
2007
- );
2008
-
2009
- /**
2010
- * 合并外部传入和业务默认的自定义组件,外部优先
2011
- */
2012
- const mergedCustomComponents: { [key: string]: any } = {
2013
- ...businessCustomComponents,
2014
- ...(rest.CustomComponents || {}),
2015
- };
2016
-
2017
- useEffect(() => {
2018
- setDynamicSenderConfig((prev: any) => {
2019
- const switchs = Array.isArray(prev.switchs)
2020
- ? prev.switchs.map((item: any) =>
2021
- item.name === 'reasoning' ? { ...item, enabled: is_enableThinking } : item
2022
- )
2023
- : [];
2024
- return {
2025
- ...prev,
2026
- switchs,
2027
- };
2028
- });
2029
- }, [is_enableThinking]);
2030
- // =================================================================
2031
- // Render - 渲染
2032
- // =================================================================
2033
- return (
2034
- <div style={{ height: '100%', minWidth: '1116px', overflow: 'hidden' }}>
2035
- <FileManager
2036
- open={fileManagerOpen}
2037
- onCancel={() => setFileManagerOpen(false)}
2038
- files={fileManagerData.uploadedFiles}
2039
- currentFiles={pendingFiles}
2040
- onUpload={handleFileManagerUpload}
2041
- onRemoveFile={handleFileManagerRemove}
2042
- styles={normalizedStyles}
2043
- eventsEmit={mergedEventsEmit}
2044
- />
2045
-
2046
- {/* 右侧栏由 AiChat 内置事件控制,此处不再使用 antd Drawer */}
2047
-
2048
- <WrappedComponent
2049
- {...rest}
2050
- status={appStatus}
2051
- chatData={currentChatData}
2052
- sidebar={sidebar}
2053
- recommandQuestions={[]}
2054
- eventsEmit={mergedEventsEmit}
2055
- styles={normalizedStyles as any}
2056
- senderConfig={dynamicSenderConfig}
2057
- fileUploadStatus={fileStatuses}
2058
- CustomComponents={mergedCustomComponents}
2059
- activeSessionId={activeSessionId}
2060
- scrollOld={scrollOld}
2061
- rightbarWidth={'400px'}
2062
- />
2063
- <FeedBackModal
2064
- open={openFeed}
2065
- feedBackList={feedBackList}
2066
- setOpen={setOpenFeed}
2067
- handleConfirm={handleFeedDownConfirm}
2068
- />
2069
- <RenameModal
2070
- isModalOpen={isRenameModalOpen}
2071
- handleOk={handleEvent}
2072
- handleCancel={() => handleEvent('close_rename')}
2073
- data={curEditData?.data || {}}
2074
- />
2075
- <DeleteModal
2076
- isModalOpen={isRemoveModalOpen}
2077
- handleOk={handleEvent}
2078
- handleCancel={() => handleEvent('close_remove')}
2079
- data={curEditData?.data || {}}
2080
- />
2081
- </div>
2082
- );
2083
- };
2084
- }
2085
-
2086
- // 重新导出 registerPDFWorker,方便用户从 chat 模块引入
2087
- export { registerPDFWorker } from '@mxmweb/fviewer';