浏览代码

feat(sidepanel): 优化聊天功能和界面

- 新增消息列表滚动控制和底部返回按钮
- 改进总结功能,支持多文件综合分析
- 优化消息存储逻辑,使用 cloneDeep 复制消息对象
- 添加 SVG 图标组件和相关配置- 调整聊天界面样式,提升用户体验
wzg 5 月之前
父节点
当前提交
1a6d168507

+ 2 - 0
package.json

@@ -20,11 +20,13 @@
     "axios": "^1.7.9",
     "element-plus": "^2.9.1",
     "highlight.js": "^11.11.1",
+    "lodash": "^4.17.21",
     "moment": "^2.30.1",
     "openai": "^4.85.4",
     "pinia": "^3.0.1",
     "sass": "^1.85.1",
     "vant": "^4.9.17",
+    "vite-plugin-svg-icons": "^2.0.1",
     "vue": "^3.5.12",
     "xlsx": "^0.18.5"
   },

+ 1 - 0
src/assets/svg/send.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1741937191391" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3653" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M843.8784 214.391467c33.1776-7.543467 60.996267 24.746667 49.6128 56.029866l-1.024 2.542934-201.6768 465.4592a42.666667 42.666667 0 0 1-59.0336 20.7872l-2.474667-1.416534-201.710933-124.125866a42.666667 42.666667 0 0 1-19.8144-42.8032l0.477867-2.6112-1.672534 0.887466a42.666667 42.666667 0 0 1-39.0144-0.853333l-2.730666-1.604267-217.224534-139.639466c-30.976-19.9168-23.688533-66.56 10.752-76.7488l2.8672-0.750934 682.666667-155.136z m-63.163733 101.853866l-501.469867 113.9712 109.7216 70.536534 163.601067-95.419734a42.666667 42.666667 0 0 1 56.797866 12.868267l1.536 2.474667a42.666667 42.666667 0 0 1-12.868266 56.797866l-2.474667 1.570134-132.9664 77.550933 1.928533 0.631467a42.666667 42.666667 0 0 1 5.239467 2.321066l2.542933 1.450667 159.744 98.304 148.667734-343.057067z" fill="#ffffff" p-id="3654"></path><path d="M464.776533 599.825067a42.666667 42.666667 0 0 1 65.365334 54.749866l-1.9456 2.338134-139.639467 155.136c-25.5488 28.398933-72.1408 11.400533-74.2912-25.838934l-0.085333-2.696533v-139.639467a42.666667 42.666667 0 0 1 85.248-2.798933l0.085333 2.798933v28.433067l65.262933-72.482133z" fill="#ffffff" p-id="3655"></path><path d="M302.353067 495.803733a42.666667 42.666667 0 0 1 56.439466-14.318933l2.525867 1.501867 49.629867 31.914666a42.666667 42.666667 0 0 1-43.639467 73.2672l-2.5088-1.4848-49.629867-31.914666a42.666667 42.666667 0 0 1-12.817066-58.965334z" fill="#ffffff" p-id="3656"></path></svg>

+ 1 - 0
src/assets/svg/stop.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1741938563101" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6206" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><path d="M661.247 857.615H362.753c-108.002 0-196.368-88.366-196.368-196.368V362.753c0-108.002 88.366-196.368 196.368-196.368h298.494c108.002 0 196.368 88.366 196.368 196.368v298.494c0 108.002-88.366 196.368-196.368 196.368z" fill="#FF0000" p-id="6207"></path></svg>

src/assets/vue.svg → src/assets/svg/vue.svg


+ 107 - 58
src/entrypoints/sidepanel/Chat.vue

@@ -5,37 +5,40 @@
       <pageMask />
     </div>
     <!-- 消息列表 -->
-    <el-scrollbar v-else class="message-list" ref="scrollbar">
-      <div class="messages">
-        <div v-for="(message, index) in messages" :key="index"
-             :class="['message-item', message.isSelf ? 'self' : 'other']">
-          <el-avatar :size="32" :src="message.avatar" />
-          <div class="message-content">
-            <div class="content" v-if="!message.isSelf" :class="{ 'loading-content': message.content === '' }">
-              <span v-html="message.content"></span>
-              <span class="loading-indicator" v-if="sendLoading && index === messages.length - 1">
+    <div class="message-list" v-else>
+      <el-scrollbar ref="scrollbar" @scroll="handleScroll">
+        <div class="messages">
+          <div v-for="(message, index) in messages" :key="index"
+               :class="['message-item', message.isSelf ? 'self' : 'other']">
+            <el-avatar :size="32" :src="message.avatar" />
+            <div class="message-content">
+              <div class="content" v-if="!message.isSelf" :class="{ 'loading-content': message.content === '' }">
+                <span v-html="message.content"></span>
+                <span class="loading-indicator" v-if="sendLoading && index === messages.length - 1">
                 <span class="dot"></span>
                 <span class="dot"></span>
                 <span class="dot"></span>
               </span>
-            </div>
-            <document v-else-if="message.type === 'document' && message.isSelf" :content="message.content"
-                      :rawContent="message.rawContent" />
-            <div v-else class="content">
-              <span v-if="message.type === ''">{{ message.content }}</span>
-              <span class="loading-indicator" v-if="sendLoading && index === messages.length - 1">
+              </div>
+              <document v-else-if="message.type === 'document' && message.isSelf" :content="message.content"
+                        :rawContent="message.rawContent" />
+              <div v-else class="content">
+                <span v-if="message.type === ''">{{ message.content }}</span>
+                <span class="loading-indicator" v-if="sendLoading && index === messages.length - 1">
                 <span class="dot"></span>
                 <span class="dot"></span>
                 <span class="dot"></span>
               </span>
-            </div>
-            <div class="timestamp ">{{ moment(message.timestamp).format('MM-DD HH:mm') }}
-              <span v-if="message.add" style="cursor: pointer;" @click="handleInput">填充</span>
+              </div>
+              <div class="timestamp ">{{ moment(message.timestamp).format('MM-DD HH:mm') }}
+                <span v-if="message.add" style="cursor: pointer;" @click="handleInput">填充</span>
+              </div>
             </div>
           </div>
         </div>
-      </div>
-    </el-scrollbar>
+      </el-scrollbar>
+      <ScrollToBottom :target="scrollbar" ref="scrollToBottomRef" />
+    </div>
 
     <Tools @read-click="readClick"
            @upload-file="handleUpload"
@@ -63,27 +66,27 @@
             </div>
           </div>
 
-          <div class="card-btn">
+          <div v-show="type !== FunctionList.Intelligent_Form_filling" class="card-btn">
             <el-tooltip content="总结当前页面" placement="top">
-              <el-button round @click="handleSummary" :disabled="!taklToHtml">总结</el-button>
+              <el-button round @click="handleSummary">总结</el-button>
             </el-tooltip>
-
-            <!--            <el-tooltip content="选择后,在输入框描述填表流程" placement="top">-->
-            <!--              <el-button :class="type === '2' ? 'buttom-clicked' : ''" round @click="handelIntelligentFillingClick"-->
-            <!--                         :disabled="!taklToHtml">智能填表-->
-            <!--              </el-button>-->
-            <!--            </el-tooltip>-->
           </div>
         </div>
 
         <el-input ref="textareaRef" v-model="inputMessage" type="textarea" :rows="3" placeholder="输入消息..."
                   @keyup.enter="handleAsk" />
         <div class="chat_area_op">
-          <el-button type="primary" link @click="handleAsk" :disabled="!inputMessage.trim() || sendLoading">
-            <el-icon size="18" :color="inputMessage.trim() ? 'black' : 'gray'">
-              <Promotion />
-            </el-icon>
+          <el-button
+            :style="`background-color:${inputMessage.trim() ? '#4d6bfe' : '#d6dee8'};border-color:${inputMessage.trim() ? '#4d6bfe' : '#d6dee8'}`"
+            v-if="inputMessage.trim() || !sendLoading" type="primary" circle @click="handleAsk"
+            :disabled="!inputMessage.trim() || sendLoading">
+            <svg-icon icon-class="send" color="#000000" />
           </el-button>
+          <el-button style="background-color:#ffffff;border:2px solid rgb(134 143 153);" v-else circle
+                     @click="handleStopAsk">
+            <svg-icon icon-class="stop" color="red" />
+          </el-button>
+
         </div>
       </div>
 
@@ -99,13 +102,15 @@
 import { ref, onMounted, nextTick, inject, useTemplateRef, reactive } from 'vue'
 import { ElScrollbar, ElAvatar, ElInput, ElButton } from 'element-plus'
 import moment from 'moment'
+import { cloneDeep } from 'lodash'
 import fileLogo from '@/assets/svg/file.svg'
 import {
   buildExcelUnderstandingPrompt,
   getSummaryPrompt,
   getFileContent,
   buildObjPrompt,
-  modelFileUpload
+  modelFileUpload,
+  controllerList
 } from '@/entrypoints/sidepanel/utils/ai-service.js'
 import { storeToRefs } from 'pinia'
 import { ElMessage } from 'element-plus'
@@ -114,6 +119,7 @@ import Tools from '@/entrypoints/sidepanel/component/tools.vue'
 import historyComponent from '@/entrypoints/sidepanel/component/historyComponent.vue'
 import document from '@/entrypoints/sidepanel/component/document.vue'
 import pageMask from '@/entrypoints/sidepanel/component/pageMask.vue'
+import ScrollToBottom from '@/entrypoints/sidepanel/component/ScrollToBottom.vue'
 import { mockData, startMsg, mockData2, options, FunctionList } from '@/entrypoints/sidepanel/mock'
 import { useAutoResizeTextarea } from '@/entrypoints/sidepanel/hook/useAutoResizeTextarea.ts'
 import { getPageInfo, getXlsxValue, handleInput } from './utils/index.js'
@@ -121,6 +127,7 @@ import { useMsgStore } from '@/store/modules/msg.ts'
 
 // 滚动条引用
 const scrollbar = ref(null)
+const scrollToBottomRef = ref(null)
 const xlsxData = ref({})
 const isShowPage = ref(false)
 const tareRef = useTemplateRef('textareaRef')
@@ -143,12 +150,41 @@ const {
 const inputMessage = ref('')
 const pageInfo = ref('')
 
+
+function handleStopAsk() {
+  if (type.value === FunctionList.Intelligent_Form_filling) {
+    inputMessage.value = ''
+    pageInfoList.value = []
+    isShowPage.value = false
+    taklToHtml.value = false
+    type.value = FunctionList.File_Operation
+  }
+  controllerList.value[0].abort()
+  controllerList.value = []
+  sendLoading.value = false
+}
+
+function handleScroll({ scrollTop }) {
+  // scrollTop 滚动条的位置
+  const { wrapRef } = scrollbar.value
+  const { scrollHeight, clientHeight } = wrapRef
+  scrollToBottomRef.value.showButton = scrollHeight - scrollTop - clientHeight >= 350
+}
+
 /**
  * @param {string} msg
  * @param {string} raw
  * @param {string} type 发送的类型 document 、text
  * **/
-const addMessage = (msg, raw, type) => {
+async function addMessage(msg, raw, type) {
+  // 添加indexDB Store配置
+  if (msgUuid.value === '') {
+    msgUuid.value = 'D' + Date.now().toString()
+    await registerStore({
+      name: msgUuid.value,
+      keyPath: 'id'
+    })
+  }
   const newMessage = reactive({
     id: messages.value.length + 1,
     type: type || '',
@@ -161,14 +197,14 @@ const addMessage = (msg, raw, type) => {
     addToHistory: !taklToHtml.value
   })
   if (type === 'document') {
-    newMessage.content = JSON.stringify(msg)
+    newMessage.content = msg
     newMessage.rawContent = raw
   }
   if (!msg) return
 
   messages.value.push(newMessage)
-  useStore(msgUuid.value).add({ ...newMessage })
-  nextTick(() => {
+  useStore(msgUuid.value).add(cloneDeep(newMessage))
+  await nextTick(() => {
     scrollbar.value?.setScrollTop(99999)
   })
   return newMessage
@@ -182,11 +218,11 @@ const handleSummary = async () => {
     })
     params.push({
       role: 'user', content: `
-    请根据这几个文件综合分析总结
+    请根据这几个文件的文本内容综合分析总结
     要求:
-    1.抽取文件的内容
-    2.每个文件的内容进行总结
-    3.所有文件进行综合的总结`
+    1.抽取文件的文本内容
+    2.每个文件文本内容进行分别总结
+    3.对步骤二总结的内容进行综合总结`
     })
   } else {
     let tempStr = ''
@@ -206,12 +242,12 @@ const handleSummary = async () => {
       6. 对这几段内容进行综合分析及联想`
     }]
   }
-  addMessage(pageInfoList.value, '总结', 'document')
+  await addMessage(pageInfoList.value, '总结', 'document')
   if (requestFlowFn) {
-    await requestFlowFn(params)
-    taklToHtml.value = true
-    isShowPage.value = true
+    isShowPage.value = false
+    taklToHtml.value = false
     pageInfoList.value = []
+    const res = await requestFlowFn(params)
   }
 }
 
@@ -220,7 +256,7 @@ async function handelIntelligentFillingClick() {
   taklToHtml.value = true
   const tempPageInfo = await getPageInfo()
   pageInfo.value = tempPageInfo
-  pageInfoList.value.unshift(tempPageInfo)
+  pageInfoList.value = [tempPageInfo]
   inputMessage.value = '/智能填表 '
   type.value = FunctionList.Intelligent_Form_filling
 }
@@ -233,6 +269,11 @@ function handleCurrentChange(e) {
       }
     })
   })
+  if (AIModel.value.file === true) {
+    isShowPage.value = false
+    taklToHtml.value = false
+    pageInfoList.value = []
+  }
 }
 
 function handleCurrentData(e) {
@@ -252,7 +293,10 @@ function handleCurrentData(e) {
 }
 
 async function readClick() {
-  type.value = FunctionList.File_Operation
+  if (type.value === FunctionList.Intelligent_Form_filling) {
+    pageInfoList.value = []
+    type.value = FunctionList.File_Operation
+  }
   isShowPage.value = true
   taklToHtml.value = true
   if (pageInfoList.value.length >= Number(import.meta.env.VITE_MAX_FILE_NUMBER)) {
@@ -273,6 +317,7 @@ function deletePageInfo(i) {
   if (pageInfoList.value.length === 0) {
     isShowPage.value = false
     taklToHtml.value = false
+    type.value = FunctionList.File_Operation
   }
 }
 
@@ -281,20 +326,15 @@ function addNewDialogue() {
     ElMessage.warning('已经是新对话')
     return
   }
+  isShowPage.value = false
+  taklToHtml.value = false
   messages.value = []
+  pageInfoList.value = []
   msgUuid.value = ''
 }
 
 async function handleAsk() {
   if (sendLoading.value) return
-  // 添加indexDB Store配置
-  if (msgUuid.value === '') {
-    msgUuid.value = 'D' + Date.now().toString()
-    await registerStore({
-      name: msgUuid.value,
-      keyPath: 'id'
-    })
-  }
   addMessage(inputMessage.value.trim())
   if (type.value === FunctionList.Intelligent_Form_filling) {
     const res = await fetchRes(inputMessage.value.trim())
@@ -355,11 +395,20 @@ const handleUpload = async (file) => {
     return
   }
   if (type.value === FunctionList.File_Operation) {
-    const fileVaue = await getFileValue(file)
-    // streamRes()
+    let formData = new FormData()
+    formData.append('file', file)
+    const res = await getFileContent(formData)
+    pageInfoList.value.unshift({
+      title: file.name,
+      url: 'File',
+      favIconUrl: fileLogo,
+      content: {
+        mainContent: res.data
+      }
+    })
+    isShowPage.value = true
   }
 }
-let str = ''
 
 async function getFileValue(file) {
   const msg = addMessage(`文件上传中`)

+ 33 - 0
src/entrypoints/sidepanel/component/ScrollToBottom.vue

@@ -0,0 +1,33 @@
+<script setup lang="ts">
+import { ref, onMounted, onUnmounted } from 'vue'
+import { CaretBottom } from '@element-plus/icons-vue'
+
+const showButton = ref(false)
+
+const props = defineProps({
+  target: {
+    required: true
+  }
+})
+
+
+defineExpose({
+  showButton
+})
+
+</script>
+
+<template>
+  <el-button v-show="showButton" :icon="CaretBottom" circle
+             @click="props.target.setScrollTop(99999)"
+             class="back_bottom" />
+</template>
+
+<style scoped lang="scss">
+.back_bottom {
+  position: absolute;
+  bottom: 12px;
+  right: 12px;
+  font-size: 20px
+}
+</style>

+ 4 - 4
src/entrypoints/sidepanel/component/document.vue

@@ -3,16 +3,16 @@ import { onMounted, computed } from 'vue'
 
 const props = defineProps({
   content: {
-    type: String,
+    type: [String, Object],
     default: ''
   },
   rawContent: {
-    type: String,
+    type: [String, Object],
     default: ''
   }
 })
 const docZil = computed(() => {
-  return JSON.parse(props.content)
+  return props.content
 })
 </script>
 
@@ -71,6 +71,6 @@ const docZil = computed(() => {
   max-width: 240px;
   padding: 10px 12px;
   border-radius: 6px;
-  background-color: rgba(255, 255, 255, 0.8);
+  background-color: rgba(114, 118, 139, .06);
 }
 </style>

+ 1 - 1
src/entrypoints/sidepanel/component/pageMask.vue

@@ -4,7 +4,7 @@
 
 <template>
   <div class="w-full h-full pt-20">
-    <div class="max-w-96 text-left m-auto">
+    <div class="max-w-96 text-left m-auto p-5">
       <p class="font-black text-4xl mb-4 text-black">你好,</p>
       <p class="font-black text-3xl mb-4 text-black">我是PVS智能助手,</p>
       <p class="font-black text-2xl mb-4 text-black">我今天能帮你什么?</p>

+ 1 - 1
src/entrypoints/sidepanel/component/tools.vue

@@ -37,7 +37,7 @@ watchEffect(() => {
       <el-tooltip effect="dark" content="截屏" placement="top">
         <el-button class="tools_btn" link :icon="Scissor" @click="emit('handleCapture')" />
       </el-tooltip>
-      <el-tooltip effect="dark" content="智能填表" placement="top">
+      <el-tooltip effect="dark" content="智能填表:选择后,在输入框描述填表流程" placement="top">
         <el-button class="tools_btn" link :icon="Edit" @click="emit('handelIntelligentFillingClick')" />
       </el-tooltip>
 

+ 46 - 0
src/entrypoints/sidepanel/components/SvgIcon/index.vue

@@ -0,0 +1,46 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+
+const props = defineProps({
+  iconClass: {
+    type: String,
+    required: true
+  },
+  className: {
+    type: String,
+    default: 'svg_icon_default_style'
+  },
+  color: {
+    type: String,
+    default: ''
+  }
+})
+
+const iconName = computed(() => {
+  return `#icon-${props.iconClass}`
+})
+const svgClass = computed(() => {
+  if (props.className) {
+    return `svg-icon ${props.className}`
+  }
+  return 'svg-icon'
+})
+</script>
+
+<template>
+  <svg :class="svgClass" aria-hidden="true">
+    <use :xlink:href="iconName" :fill="color" />
+  </svg>
+</template>
+
+<style scoped lang="scss">
+.svg-icon {
+  width: 100%;
+  height: auto;
+}
+
+.svg_icon_default_style {
+  width: 16px;
+  height: 16px;
+}
+</style>

+ 4 - 2
src/entrypoints/sidepanel/css/chat.scss

@@ -16,11 +16,12 @@
 
 .message-list {
   flex: 1;
-  padding: 16px;
-  overflow: auto;
+  overflow: hidden;
+  position: relative;
 }
 
 .messages {
+  padding: 12px 12px 0;
   min-height: 100%;
   display: flex;
   flex-direction: column;
@@ -318,6 +319,7 @@
   border-color: #409eff;
   box-shadow: none;
 }
+
 .buttom-clicked {
   color: #409eff;
   border-color: rgb(197.7, 225.9, 255);

+ 14 - 3
src/entrypoints/sidepanel/hook/useMsg.ts

@@ -3,6 +3,7 @@ import { ref, reactive, nextTick, inject } from 'vue'
 import { storeToRefs } from 'pinia'
 import avator from '@/public/icon/32.png'
 import moment from 'moment'
+import { cloneDeep } from 'lodash'
 import {
   getFormKey,
   buildObjPrompt,
@@ -306,7 +307,7 @@ export function useMsg(scrollbar?: any) {
     console.log(obj.rawContent)
 
     //添加到存储历史
-    useStore(msgUuid.value).add({ ...obj })
+    useStore(msgUuid.value).add(cloneDeep(obj))
     // 处理最终内容
     sendLoading.value = false
     nextTick(() => {
@@ -330,6 +331,12 @@ export function useMsg(scrollbar?: any) {
     return obj.rawContent
   }
 
+  /**
+   * @param data 输入数据
+   * @returns true 成功
+   * @returns false 失败
+   * **/
+
   async function requestFlowFn(data: any[]) {
     sendLoading.value = true
     const obj = reactive<any>({
@@ -345,9 +352,12 @@ export function useMsg(scrollbar?: any) {
     messages.value.push(obj)
     scrollbar.value?.setScrollTop(99999)
     const iterator = await sendMessage(data)
+    console.log(iterator)
     if (iterator.error) {
       // 实时格式化显示内容
       obj.content = iterator.error
+      sendLoading.value = false
+      return false
     } else {
       for await (const chunk of iterator) {
         if (chunk) {
@@ -363,12 +373,13 @@ export function useMsg(scrollbar?: any) {
       }
     }
     //添加到存储历史
-    useStore(msgUuid.value).add({ ...obj })
+    useStore(msgUuid.value).add(cloneDeep(obj))
     // 处理最终内容
     sendLoading.value = false
-    nextTick(() => {
+    await nextTick(() => {
       scrollbar.value?.setScrollTop(99999)
     })
+    return true
   }
 
   return {

+ 3 - 1
src/entrypoints/sidepanel/main.ts

@@ -7,6 +7,8 @@ import 'element-plus/dist/index.css'
 import locale from 'element-plus/es/locale/lang/zh-cn' // 中文语言
 import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 import store from '@/store/index'
+import 'virtual:svg-icons-register'
+import SvgIcon from '@/entrypoints/sidepanel/components/SvgIcon/index.vue'
 
 const app = createApp(App)
 app.use(ElementPlus, { locale: locale, size: 'small' })
@@ -14,5 +16,5 @@ app.use(store)
 for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
   app.component(key, component)
 }
-
+app.component('svg-icon', SvgIcon)
 app.mount('#app')

+ 13 - 6
src/entrypoints/sidepanel/utils/ai-service.js

@@ -3,6 +3,11 @@ import hljs from 'highlight.js'
 import 'highlight.js/styles/atom-one-dark.css' // 导入一个暗色主题样式
 import { getActivePinia } from 'pinia'
 import { useMsgStore } from '@/store/modules/msg.ts'
+import { ref } from 'vue'
+
+
+// 创建新的 AbortController
+export const controllerList = ref([])
 
 export async function sendMessage(message) {
   const pinia = getActivePinia()
@@ -12,15 +17,14 @@ export async function sendMessage(message) {
   const store = useMsgStore(pinia)
   const { openai, AIModel } = store
   try {
-    // 创建新的 AbortController
     const controller = new AbortController()
-    const a = +new Date()
+    controllerList.value.push(controller)
     return await openai.chat.completions.create({
       //模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
       model: AIModel.value,
       messages: message,
       stream: true
-    })
+    }, { signal: controller.signal })
   } catch (error) {
     return { error: error }
   } finally {
@@ -34,7 +38,8 @@ export async function getFileContent(data) {
       body: data
     }).then((res) => res.json())
     return res
-  } catch (error) {}
+  } catch (error) {
+  }
 }
 
 export async function getFormKey(data) {
@@ -44,7 +49,8 @@ export async function getFormKey(data) {
       body: JSON.stringify(data)
     }).then((res) => res.json())
     return res
-  } catch (error) {}
+  } catch (error) {
+  }
 }
 
 export async function hepl(data) {
@@ -54,7 +60,8 @@ export async function hepl(data) {
       body: JSON.stringify(data)
     }).then((res) => res.json())
     return res
-  } catch (error) {}
+  } catch (error) {
+  }
 }
 
 function formatMessages(currentMessage, Summary, html) {

+ 0 - 15
src/store/modules/msg.ts

@@ -1,5 +1,4 @@
 import { defineStore } from 'pinia'
-import { useIndexedDBStore } from './indexedDB'
 import OpenAI from 'openai'
 
 export const useMsgStore = defineStore('msg', {
@@ -20,20 +19,6 @@ export const useMsgStore = defineStore('msg', {
         // timeout: 5000,
         dangerouslyAllowBrowser: true
       })
-    },
-    addMsg(msg: any) {
-      const { useStore } = useIndexedDBStore()
-      useStore(this.msgUuid).add(msg)
-      this.messages.push(msg)
-    },
-
-    addMsg1(msg: any) {
-      this.messages.push(msg)
-    },
-
-    msgToDB(msg: any) {
-      const { useStore } = useIndexedDBStore()
-      useStore(this.msgUuid).add(msg)
     }
   }
 })

+ 3 - 3
src/utils/page-analyzer.js

@@ -64,9 +64,9 @@ export default class PageAnalyzer {
         content.textContent = form.outerHTML
       }
     } else {
-      // const content = document.body.cloneNode(true)
-      // return cleanPage(content)
-      return document.documentElement.outerHTML
+      const content = document.body.cloneNode(true)
+      return cleanPage(content)
+      // return document.documentElement.outerHTML
       // .trim().replace(/\s+/g, " ")
       // content
       //     .querySelectorAll("script, style, iframe, nav, header, footer,svg")

+ 14 - 1
wxt.config.ts

@@ -1,7 +1,20 @@
 import { defineConfig } from 'wxt'
+import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
+import path from 'path'
 
 // See https://wxt.dev/api/config.html
 export default defineConfig({
+  vite: ({ command }) => {
+    return {
+      plugins: [
+        createSvgIconsPlugin({
+          iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
+          symbolId: 'icon-[dir]-[name]',
+          svgoOptions: command === 'build'
+        })
+      ]
+    }
+  },
   extensionApi: 'chrome',
   srcDir: 'src',
   manifest: {
@@ -17,7 +30,7 @@ export default defineConfig({
       'sidePanel'
     ],
     content_security_policy: {
-      extension_pages: "script-src 'self'; object-src 'self';"
+      extension_pages: 'script-src \'self\'; object-src \'self\';'
     },
     action: {
       default_title: '派维斯智能体助手'