useMsg.ts 9.9 KB

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