useMsg.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. // 消息数组
  2. import { ref, reactive, nextTick, inject } from 'vue'
  3. import { storeToRefs } from 'pinia'
  4. import avator from '@/public/icon/32.png'
  5. import moment from 'moment'
  6. import {
  7. getFormKey,
  8. hepl,
  9. formatMessage,
  10. sendMessage
  11. } from '../utils/ai-service.js'
  12. import { ElMessage } from 'element-plus'
  13. import { getPageInfo, getFileValue } from '../utils/index.js'
  14. import { mockData, mockData2 } from '../mock'
  15. import { useMsgStore } from '@/store/modules/msg'
  16. import { FunctionList } from '../mock'
  17. import { putChat } from '@/api/index.js'
  18. import { useUserStore } from '@/store/modules/user'
  19. export function useMsg(scrollbar?: any) {
  20. const { messages, msgUuid } = storeToRefs(useMsgStore())
  21. const userStore = useUserStore()
  22. const indexTemp = ref(0)
  23. const taklToHtml = ref<any>(false)
  24. const sendLoading = ref(false)
  25. const pageInfo = ref<any>({})
  26. const type = ref(FunctionList.File_Operation)
  27. const formMap = ref([])
  28. // 获取父组件提供的 Hook 实例
  29. const getFormKeyAndValue = async (file: any, form?: any) => {
  30. // const obj = reactive({
  31. // id: moment(),
  32. // username: '用户1',
  33. // rawContent: '',
  34. // content: '解析文件中',
  35. // timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
  36. // isSelf: false,
  37. // avatar: avator,
  38. // addToHistory: !taklToHtml.value
  39. // })
  40. try {
  41. sendLoading.value = true
  42. // messages.value.push(obj)
  43. const response = await getFormKey({
  44. body: form,
  45. input_data: file
  46. })
  47. return response
  48. } catch (error) {
  49. // obj.content = '解析出错'
  50. } finally {
  51. sendLoading.value = false
  52. }
  53. }
  54. // 发送消息
  55. // const handleSend = async (msg: any) => {
  56. // if ( msg?.startsWith('/')) {
  57. // if (!taklToHtml.value)
  58. // return messages.value.push({
  59. // id: messages.value.length + 1,
  60. // username: '用户1',
  61. // content: '请打开与页面对话!',
  62. // rawContent: '请打开与页面对话!',
  63. // timestamp: moment().format('YYYY-MM-DD HH:mm:ss'),
  64. // isSelf: false,
  65. // avatar: avator,
  66. // addToHistory: false
  67. // })
  68. // indexTemp.value = 0
  69. // fetchRes(msg)
  70. // }
  71. // }
  72. async function awaitFindForm(obj: any) {
  73. return await new Promise((res, rej) => {
  74. chrome.runtime.sendMessage(
  75. {
  76. type: 'FROM_SIDE_PANEL_TO_GET_PAGE_FORM'
  77. },
  78. ({ status, data }) => {
  79. if (status === 'error') {
  80. obj.content = '当前页面未找到表单'
  81. res({ status })
  82. }
  83. if (status === 'ok') {
  84. obj.content = '请上传数据'
  85. res({ status, data })
  86. }
  87. if (status === 'select') {
  88. obj.content = '检测到左侧页面中有多个表单,请选择要填写的表单。'
  89. function handle(message, sender, sendResponse) {
  90. if (message.type === 'TO_SIDE_PANEL_FORM_INFO') {
  91. console.log('收到一次性消息:', message.data)
  92. res({ status: 'ok', data: message.data })
  93. obj.content = '请上传数据'
  94. console.log(565656)
  95. // 销毁监听器(确保只触发一次)
  96. chrome.runtime.onMessage.removeListener(handle)
  97. }
  98. }
  99. chrome.runtime.onMessage.addListener(handle)
  100. }
  101. }
  102. )
  103. })
  104. }
  105. const fetchRes = async (msg: any) => {
  106. indexTemp.value = 0
  107. sendLoading.value = true
  108. const obj: any = reactive({
  109. type: type || '',
  110. rawContent: '',
  111. senderId: -1,
  112. receiverId: userStore.userInfo.id, //大模型
  113. content: '',
  114. sortKey: moment().valueOf(),
  115. role: 'system',
  116. conversationId:msgUuid.value,
  117. addToHistory: `${!taklToHtml.value}`
  118. })
  119. messages.value.push(obj)
  120. msg = msg.split('/智能填表')[1]
  121. nextTick(() => {
  122. if (scrollbar.value && scrollbar.value.wrapRef) {
  123. scrollbar.value.setScrollTop(scrollbar.value.wrapRef.scrollHeight)
  124. }
  125. })
  126. if (!msg) {
  127. sendLoading.value = false
  128. const res = await awaitFindForm(obj)
  129. return res
  130. }
  131. try {
  132. const res = await fetchDataAndProcess(msg, obj)
  133. sendLoading.value = false
  134. if (res.status === 'ok') {
  135. await new Promise((res: any) =>
  136. setTimeout(() => {
  137. res()
  138. }, 2000)
  139. )
  140. const res = await awaitFindForm(obj)
  141. console.log(res, 34444)
  142. return res
  143. }
  144. } catch (error) {
  145. obj.content = '流程链执行出错'
  146. return { status: 'error' }
  147. } finally {
  148. sendLoading.value = false
  149. console.log(messages.value);
  150. putChat({
  151. ...msg,
  152. content:'',
  153. })
  154. }
  155. }
  156. let str = ''
  157. async function fetchDataAndProcess(input: any, obj: any) {
  158. str = input
  159. console.log(str)
  160. const pageInfo = await getPageInfo()
  161. await new Promise((res: any) =>
  162. setTimeout(() => {
  163. res()
  164. }, 2000)
  165. )
  166. // const res = await hepl({
  167. // input_data: input,
  168. // body: pageInfo.content.mainContent
  169. // })
  170. const res: any = await new Promise((resolve, reject) => {
  171. setTimeout(() => {
  172. resolve({
  173. data:
  174. pageInfo.title === '智能招采'
  175. ? mockData[indexTemp.value]
  176. : mockData2[indexTemp.value]
  177. })
  178. }, 1000)
  179. })
  180. if (!res.data.tag || res.data.tag === 'undefined') {
  181. ElMessage({
  182. message: '未找到标签,请重试',
  183. type: 'error',
  184. duration: 4 * 1000,
  185. grouping: true
  186. })
  187. obj.content = '未找到标签,请重试'
  188. return { status: 'error' }
  189. }
  190. await new Promise((resolve) => setTimeout(resolve, 2000))
  191. obj.content = `点击${res.data.tag}元素`
  192. const res2 = await new Promise((resolve, rej) => {
  193. chrome.runtime.sendMessage(
  194. {
  195. type: 'FROM_SIDE_PANEL_TO_ACTION',
  196. data: res.data
  197. },
  198. async ({ data, status }) => {
  199. if (chrome.runtime.lastError) {
  200. console.error('消息发送错误:', chrome.runtime.lastError)
  201. } else {
  202. if (status === 'error') {
  203. obj.content = data
  204. resolve({ data, status })
  205. console.log(222)
  206. }
  207. if (res.data.next === '是') {
  208. const arr = str.split(',')
  209. arr.shift()
  210. str = arr.join(',')
  211. indexTemp.value++
  212. const res = await fetchDataAndProcess(str, obj)
  213. resolve(res)
  214. } else resolve({ status: 'ok' })
  215. }
  216. }
  217. )
  218. })
  219. return res2
  220. }
  221. /**
  222. *
  223. * @param addHtml 是否添加页面信息
  224. */
  225. const streamRes = async (addHtml: any = false) => {
  226. pageInfo.value = await getPageInfo()
  227. sendLoading.value = true
  228. const obj = reactive<any>({
  229. id: +new Date(),
  230. type: type || '',
  231. rawContent: '',
  232. senderId: -1,
  233. receiverId: userStore.userInfo.id,
  234. content: '',
  235. sortKey: moment().valueOf(),
  236. role: 'system',
  237. conversationId: msgUuid.value,
  238. addToHistory: `${!taklToHtml.value}`
  239. })
  240. let history = []
  241. if (taklToHtml.value) {
  242. if (addHtml) {
  243. history.push({
  244. role: 'user',
  245. content: `页面主要内容${pageInfo.value.content.mainContent}`
  246. })
  247. }
  248. history.push({
  249. role: 'user',
  250. content: messages.value[messages.value.length - 1].rawContent
  251. })
  252. } else {
  253. history = messages.value
  254. .filter((item: any) => item.addToHistory === 'true')
  255. .slice(-20)
  256. .map((item: any) => ({
  257. role: item.role,
  258. content: item.rawContent
  259. }))
  260. }
  261. messages.value.push(obj)
  262. nextTick(() => {
  263. scrollbar.value?.setScrollTop(99999)
  264. })
  265. try {
  266. console.log(history,565666);
  267. const iterator = await sendMessage(history)
  268. console.log(iterator);
  269. for await (const chunk of iterator) {
  270. if (chunk) {
  271. const decodedChunk = chunk.choices[0].delta.content
  272. if (decodedChunk) {
  273. // 保存原始内容
  274. obj.rawContent += decodedChunk
  275. // 实时格式化显示内容
  276. obj.content = formatMessage(obj.rawContent)
  277. }
  278. }
  279. scrollbar.value?.setScrollTop(99999)
  280. }
  281. if (type.value === FunctionList.Intelligent_Form_filling) {
  282. obj.type = 'form' //
  283. }
  284. return { rawContent: obj.rawContent, status: 'ok' }
  285. } catch (error) {
  286. console.log(error);
  287. obj.content = '网络出错'
  288. return { rawContent: obj.rawContent, status: 'error' }
  289. } finally {
  290. console.log(messages.value);
  291. putChat({
  292. ...obj,
  293. content: '',
  294. })
  295. // 处理最终内容
  296. sendLoading.value = false
  297. nextTick(() => {
  298. scrollbar.value?.setScrollTop(99999)
  299. })
  300. }
  301. }
  302. /**
  303. * @param data 输入数据
  304. * @returns true 成功
  305. * @returns false 失败
  306. * **/
  307. async function requestFlowFn(data: any[]) {
  308. sendLoading.value = true
  309. const obj = reactive<any>({
  310. id: +new Date(),
  311. type: type || '',
  312. rawContent: '',
  313. senderId: -1,
  314. receiverId: userStore.userInfo.id, //大模型
  315. content: '',
  316. sortKey: moment().valueOf(),
  317. role: 'system',
  318. conversationId: msgUuid.value,
  319. addToHistory: `${!taklToHtml.value}`
  320. })
  321. messages.value.push(obj)
  322. scrollbar.value?.setScrollTop(99999)
  323. const iterator = await sendMessage(data)
  324. if (iterator.error) {
  325. // 实时格式化显示内容
  326. obj.content = iterator.error
  327. sendLoading.value = false
  328. return false
  329. } else {
  330. for await (const chunk of iterator) {
  331. if (chunk) {
  332. const decodedChunk = chunk.choices[0].delta.content
  333. if (decodedChunk) {
  334. // 保存原始内容
  335. obj.rawContent += decodedChunk
  336. // 实时格式化显示内容
  337. obj.content = formatMessage(obj.rawContent)
  338. }
  339. }
  340. scrollbar.value?.setScrollTop(99999)
  341. }
  342. }
  343. console.log(messages.value);
  344. putChat({
  345. ...obj,
  346. content: '',
  347. })
  348. // 处理最终内容
  349. sendLoading.value = false
  350. await nextTick(() => {
  351. scrollbar.value?.setScrollTop(99999)
  352. })
  353. return true
  354. }
  355. return {
  356. indexTemp,
  357. taklToHtml,
  358. sendLoading,
  359. type,
  360. fetchRes,
  361. streamRes,
  362. getFormKeyAndValue,
  363. requestFlowFn
  364. }
  365. }