소스 검색

feat: 合并input代码

sunxiao 4 주 전
부모
커밋
effcf14b72

+ 1 - 1
src/assets/styles/github-markdown-light.scss

@@ -547,7 +547,7 @@
   margin-top: 16px;
 }
 .markdown-body p, .markdown-body li {
-  font-size: 14px;
+  font-size: 16px;
 }
 
 .markdown-body li+li {

+ 11 - 0
src/assets/svgs/chat/icon-arrow-down.svg

@@ -0,0 +1,11 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
+                        <g clip-path="url(#clip0_5397_2138)">
+                        <path d="M8.00004 14.6668C9.84097 14.6668 11.5076 13.9206 12.7141 12.7142C13.9205 11.5078 14.6667 9.8411 14.6667 8.00016C14.6667 6.15923 13.9205 4.49256 12.7141 3.28612C11.5076 2.07969 9.84097 1.3335 8.00004 1.3335C6.15911 1.3335 4.49244 2.07969 3.28599 3.28612C2.07957 4.49256 1.33337 6.15923 1.33337 8.00016C1.33337 9.8411 2.07957 11.5078 3.28599 12.7142C4.49244 13.9206 6.15911 14.6668 8.00004 14.6668Z" fill="#1A2029" stroke="#1A2029" stroke-width="1.33333" stroke-linejoin="round"/>
+                        <path d="M5.33337 8L7.33337 10L11.3334 6" stroke="white" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
+                        </g>
+                        <defs>
+                        <clipPath id="clip0_5397_2138">
+                        <rect width="16" height="16" fill="white"/>
+                        </clipPath>
+                        </defs>
+                      </svg>

+ 3 - 0
src/assets/svgs/chat/icon-deep.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
+  <path d="M6.82151 2.10744C6.50895 2.42 6.33336 2.84393 6.33336 3.28595C6.33336 3.72798 6.50895 4.15191 6.82151 4.46447L11.5356 9.17851C11.8481 9.49107 12.272 9.66667 12.7141 9.66667C13.1561 9.66667 13.58 9.49107 13.8926 9.17851C14.2051 8.86595 14.3807 8.44203 14.3807 8C14.3807 7.55797 14.2051 7.13405 13.8926 6.82149C13.58 6.50893 13.1561 6.33333 12.7141 6.33333C12.272 6.33333 11.8481 6.50893 11.5356 6.82149L6.82151 11.5355C6.50895 11.8481 6.33336 12.272 6.33336 12.714C6.33336 13.1561 6.50895 13.58 6.82151 13.8926C7.13407 14.2051 7.558 14.3807 8.00002 14.3807C8.44205 14.3807 8.86597 14.2051 9.17853 13.8926C9.4911 13.58 9.66669 13.1561 9.66669 12.714C9.66669 12.272 9.4911 11.8481 9.17853 11.5355L4.46449 6.82149C4.15193 6.50893 3.72801 6.33333 3.28598 6.33333C2.84395 6.33333 2.42003 6.50893 2.10747 6.82149C1.79491 7.13405 1.61931 7.55797 1.61931 8C1.61931 8.44203 1.79491 8.86595 2.10747 9.17851C2.42003 9.49107 2.84395 9.66667 3.28598 9.66667C3.72801 9.66667 4.15193 9.49107 4.46449 9.17851L9.17853 4.46447C9.4911 4.15191 9.66669 3.72798 9.66669 3.28595C9.66669 2.84393 9.4911 2.42 9.17853 2.10744C8.86597 1.79488 8.44205 1.61929 8.00002 1.61929C7.558 1.61929 7.13407 1.79488 6.82151 2.10744Z" stroke="#2E5CFF" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

+ 14 - 0
src/assets/svgs/chat/icon-internet-active.svg

@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
+<g clip-path="url(#clip0_5450_2335)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00004 14.6668C11.6819 14.6668 14.6667 11.6821 14.6667 8.00016C14.6667 4.31826 11.6819 1.3335 8.00004 1.3335C4.31814 1.3335 1.33337 4.31826 1.33337 8.00016C1.33337 11.6821 4.31814 14.6668 8.00004 14.6668Z" stroke="#2E5CFF" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M1.33337 8H14.6667" stroke="#2E5CFF" stroke-linecap="round" stroke-linejoin="round"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00004 14.6668C9.47281 14.6668 10.6667 11.6821 10.6667 8.00016C10.6667 4.31826 9.47281 1.3335 8.00004 1.3335C6.52727 1.3335 5.33337 4.31826 5.33337 8.00016C5.33337 11.6821 6.52727 14.6668 8.00004 14.6668Z" stroke="#2E5CFF" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M3.28601 3.38037C4.49244 4.5868 6.15911 5.333 8.00004 5.333C9.84101 5.333 11.5077 4.5868 12.7141 3.38037" stroke="#2E5CFF" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M12.7141 12.6191C11.5077 11.4127 9.84101 10.6665 8.00004 10.6665C6.15911 10.6665 4.49244 11.4127 3.28601 12.6191" stroke="#2E5CFF" stroke-linecap="round" stroke-linejoin="round"/>
+</g>
+<defs>
+<clipPath id="clip0_5450_2335">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>

+ 14 - 0
src/assets/svgs/chat/icon-internet.svg

@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
+  <g clip-path="url(#clip0_5397_2123)">
+    <path fill-rule="evenodd" clip-rule="evenodd" d="M8.00004 14.6668C11.6819 14.6668 14.6667 11.6821 14.6667 8.00016C14.6667 4.31826 11.6819 1.3335 8.00004 1.3335C4.31814 1.3335 1.33337 4.31826 1.33337 8.00016C1.33337 11.6821 4.31814 14.6668 8.00004 14.6668Z" stroke="#1A2029" stroke-linecap="round" stroke-linejoin="round"/>
+    <path d="M1.33337 8H14.6667" stroke="#1A2029" stroke-linecap="round" stroke-linejoin="round"/>
+    <path fill-rule="evenodd" clip-rule="evenodd" d="M8.00004 14.6668C9.47281 14.6668 10.6667 11.6821 10.6667 8.00016C10.6667 4.31826 9.47281 1.3335 8.00004 1.3335C6.52727 1.3335 5.33337 4.31826 5.33337 8.00016C5.33337 11.6821 6.52727 14.6668 8.00004 14.6668Z" stroke="#1A2029" stroke-linecap="round" stroke-linejoin="round"/>
+    <path d="M3.28601 3.38037C4.49244 4.5868 6.15911 5.333 8.00004 5.333C9.84101 5.333 11.5077 4.5868 12.7141 3.38037" stroke="#1A2029" stroke-linecap="round" stroke-linejoin="round"/>
+    <path d="M12.7141 12.6191C11.5077 11.4127 9.84101 10.6665 8.00004 10.6665C6.15911 10.6665 4.49244 11.4127 3.28601 12.6191" stroke="#1A2029" stroke-linecap="round" stroke-linejoin="round"/>
+  </g>
+  <defs>
+    <clipPath id="clip0_5397_2123">
+      <rect width="16" height="16" fill="white"/>
+    </clipPath>
+  </defs>
+</svg>

+ 210 - 28
src/components/Chat/ChatAgentInput.vue

@@ -1,6 +1,6 @@
 <script setup>
 import { ref, unref, onMounted, onUnmounted, computed, watch } from 'vue';
-import { useMessage, NInput, NSwitch, NPopover, NScrollbar, NUpload, NTooltip, NProgress } from 'naive-ui';
+import { useMessage, NInput, NPopover, NScrollbar, NUpload, NTooltip, NProgress, NButton } from 'naive-ui';
 import { useUserStore } from '@/stores/modules/userStore';
 import { baseURL } from '@/utils/request';
 import { getFormatYesterDay } from '@/utils/format';
@@ -24,8 +24,14 @@ const MAX_NUM = 5;
 const useStore = useUserStore();
 
 const modelLoading = defineModel('loading');
+const modelOnline = defineModel('online');
 const switchStatus = defineModel('switch');
 
+const selectOptions = [
+  { title: 'LibraAl', subTitle: '水务行业专家', value: 0 },
+  { title: 'Deepseek', subTitle: '适合深度思考', value: 1 },
+]
+
 const message = useMessage();
 
 const inpVal = ref('');
@@ -65,7 +71,15 @@ watch(inpVal, (curVal) => {
 })
 
 watch(() => props.activeItem, (curVal) => {
-  selectedOption.value = curVal?.tools ? curVal :  null;
+  // console.log(curVal);
+  selectedOption.value = curVal?.tools ? curVal : null;
+  // TODO: 这里后续大概率要删除
+  if ( curVal?.tools ) {
+    // 选中智能体,没有联网搜索
+    modelOnline.value = false;
+    // 选中智能体,需要使用默认的libraAi
+    switchStatus.value = 0;
+  }
 })
 
 const handleInpFocus = () => {
@@ -197,6 +211,10 @@ const selectOption = (index) => {
   highlightedIndex.value = index;
   isOpen.value = false;
   inpVal.value = selectedOption.value.content;
+  // 选中智能体,没有联网搜索
+  modelOnline.value = false;
+  // 选中智能体,需要使用默认的libraAi
+  switchStatus.value = 0;
 }
 
 const beforeUpload = ({ file }) => {
@@ -262,6 +280,12 @@ const clearFileList = () => {
   uploadFileList.value = [];
 }
 
+// 切换智能体
+const onChangeAgent = ({ value }) => {
+  switchStatus.value = value;
+  modelOnline.value = false;
+}
+
 onMounted(async () => {
   const { data } = await helperApi.getHelperList();
   
@@ -299,7 +323,7 @@ defineExpose({
         <div class="chat-inp-outer border-[1px]" :class="[{ 'border-[#2454FF]': isFocusState }]">
           <ul class="chat-tools-inner py-[10px] px-[10px] bg-[#fcfcfc]" v-show="selectedOption">
             <li class="tools-tips space-x-[10px]">
-              <span>与</span>            
+              <span>与</span>       
               <p class="agent-name space-x-[5px]" @click="isOpen = true">
                 <img src="https://static.fuxicarbon.com/userupload/db77ffe0cef843278a23b0d2db9505fa.png" alt="">
                 <span>{{ selectedOption?.title }}</span>
@@ -358,34 +382,91 @@ defineExpose({
                   </NTooltip>
                 </NUpload>
               </div>
-              <NInput 
-                class="flex-1"
-                ref="inpRef" 
-                type="textarea" 
-                size="medium"
-                placeholder="输入@,召唤智能体"
-                v-model:value="inpVal" 
-                :autosize="{ minRows: 1, maxRows: 5 }"
-                @focus="focusInput"
-                @blur="blurInput"
-                @keypress="handleInpEnter"
-              />
+              <div class="w-full ml-[15px]">
+                <NInput 
+                  class="flex-1"
+                  ref="inpRef" 
+                  type="textarea" 
+                  size="medium"
+                  placeholder="输入@,召唤智能体"
+                  v-model:value="inpVal" 
+                  :autosize="{ minRows: 1, maxRows: 4 }"
+                  @focus="focusInput"
+                  @blur="blurInput"
+                  @keypress="handleInpEnter"
+                />
+              </div>
             </div>
-            <div class="submit-btn">
-              <button class="btn bg-[#1A2029] hover:bg-[#3C4148]" @click="handleBtnClick">
-                <SvgIcon name="tool-send-plane" size="22" v-show="!modelLoading"></SvgIcon>
-                <div style="color: #fff" class="la-ball-running-dots la-sm" v-show="modelLoading">
-                  <div v-for="item in 5" :key="item"></div>
+
+            <div class="option-wrapper">
+              <div class="option-list space-x-[10px]">
+                <n-popover 
+                  trigger="focus" 
+                  to=".option-wrapper" 
+                  raw 
+                  :show-arrow="false"
+                  placement="top-start"
+                  :width="150"
+                  content-class="content-class"
+                  content-style="padding: 0;"
+                  isOpen
+                  :disabled="selectedOption"
+                >
+                  <template #trigger>
+                    <n-button text>
+                      <div class="switch-agent option">
+                        <span>{{ selectOptions[switchStatus]?.title }}</span>
+                        <i class="n-base-icon n-base-suffix__arrow"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.14645 5.64645C3.34171 5.45118 3.65829 5.45118 3.85355 5.64645L8 9.79289L12.1464 5.64645C12.3417 5.45118 12.6583 5.45118 12.8536 5.64645C13.0488 5.84171 13.0488 6.15829 12.8536 6.35355L8.35355 10.8536C8.15829 11.0488 7.84171 11.0488 7.64645 10.8536L3.14645 6.35355C2.95118 6.15829 2.95118 5.84171 3.14645 5.64645Z" fill="currentColor"></path></svg></i>
+                      </div>
+                    </n-button>
+                  </template>
+                  <ul class="select-agent-options space-y-[8px]">
+                    <li class="agent-option-item" v-for="item in selectOptions" :key="item.value" @click="onChangeAgent(item)">
+                      <p class="">
+                        <span class="agent-title">{{ item.title }}</span>
+                        <span class="agent-sub-title">{{ item.subTitle }}</span>
+                      </p>
+                      <SvgIcon name="chat-icon-arrow-down" v-show="switchStatus == item.value"></SvgIcon>
+                    </li>
+                  </ul>
+                </n-popover>
+
+                <div 
+                  class="internet-agent option space-x-[4px]"
+                  :class="{'agent-active': modelOnline}"
+                  @click="modelOnline = !modelOnline"
+                  v-show="switchStatus == 1"
+                >
+                  <span class="icon"></span>
+                  <span>联网搜索</span>
+                  <span class="circle"></span>
                 </div>
-              </button>
+
+                <!-- <div class="internet-agent  option space-x-[4px]">
+                  <SvgIcon name="chat-icon-deep"></SvgIcon>
+                  <span>深度思考(T1)</span>
+                  <span class="circle"></span>
+                </div> -->
+              </div>
+
+              <div class="submit-btn">
+                <button class="btn bg-[#1A2029] hover:bg-[#3C4148]" @click="handleBtnClick">
+                  <SvgIcon name="tool-send-plane" size="22" v-show="!modelLoading"></SvgIcon>
+                  <div style="color: #fff" class="la-ball-running-dots la-sm" v-show="modelLoading">
+                    <div v-for="item in 5" :key="item"></div>
+                  </div>
+                </button>
+              </div>
             </div>
+
           </div>
         </div>
-        <div class="switch-inner pt-[8px] flex justify-between items-center">
-          <div class="space-x-[6px]">
+
+        <div class="switch-inner pt-[8px] flex justify-center items-center">
+          <!-- <div class="space-x-[6px]">
             <NSwitch size="small" v-model:value="switchStatus"></NSwitch>
             <span class="text-[12px] text-[#9E9E9E]">使用deepseek R1</span>
-          </div>
+          </div> -->
           <div>
             <TheArchival></TheArchival>
           </div>
@@ -419,10 +500,12 @@ defineExpose({
 <style scoped lang="scss">
 .chat-inp-outer {
   border-radius: 8px;
-  overflow: hidden;
   box-shadow: 0px 3px 12px 0px #97D3FF40;
 
   .chat-tools-inner {
+    border-top-left-radius: 8px;
+    border-top-right-radius: 8px;
+    margin-bottom: -3px;
     @include flex(x, center, between);
 
     .tools-tips {
@@ -446,12 +529,13 @@ defineExpose({
 
   .chat-inp-inner {
     position: relative;
-    @include flex(x, center, between);
+    border-radius: 8px;
+    padding: 18px 16px 14px 16px;
     background: #fff;
 
     .inp-wrapper {
       @include flex(x, start, center);
-      padding: 17px 0px 17px 17px;
+      margin-bottom: 14px;
 
       .upload-inner {
         width: 30px;
@@ -471,9 +555,69 @@ defineExpose({
       }
     }
 
+    .option-wrapper {
+      @include flex(x, center, between);
+
+      .option-list {
+        @include flex(x, center, between);
+        .option {
+          @include flex(x, center, between);
+          height: 32px;
+          padding: 0 8px;
+          border: 1px solid #f5f5f5;
+          border-radius: 8px;
+          font-size: 14px;
+          font-weight: bold;
+          color: #1A2029;
+          cursor: pointer;
+          .icon {
+            display: block;
+            width: 16px;
+            height: 16px;
+          }
+          .circle {
+            width: 6px;
+            height: 6px;
+            border-radius: 100%;
+            background: #BDBDBD;
+          }
+        }
+        .switch-agent {
+          width: 110px;
+          background: #f5f5f5;
+        }
+
+        .internet-agent {
+          transition: all 0.3s ease;
+          .icon {
+            background: url("@/assets/svgs/chat/icon-internet.svg");
+          }
+          &:hover {
+            color: #2E5CFF;
+            .circle {
+              background: #2E5CFF;
+            }
+            .icon {
+              background: url("@/assets/svgs/chat/icon-internet-active.svg");
+            }
+          }
+        }
+
+        .agent-active {
+          background: #eaeff8;
+          color: #2E5CFF;
+          .circle {
+            background: #2E5CFF;
+          }
+          .icon {
+            background: url("@/assets/svgs/chat/icon-internet-active.svg");
+          }
+        }
+      }
+    }
+
     .submit-btn {
       @include flex(x, center, center);
-      width: 84px;
 
       .btn {
         @include flex(x, center, center);
@@ -615,6 +759,44 @@ defineExpose({
   height: 30px;
   background: linear-gradient(180deg, rgba(232, 241, 250, 0) 0%, #E7F0FA 95%);
 }
+</style>
+
+<style lang="scss">
+.chat-inp-outer {
+  .n-input-wrapper {
+    padding: 0;
+  }
+}
 
+.option-wrapper {
+  .n-popover {
+    border-radius: 8px !important;
+    box-shadow: none;
+  }
+}
 
+.select-agent-options {
+  width: 150px;
+  padding: 12px 19px;
+  border: 1px solid #ddd;
+  border-radius: 8px;
+  background: #fff;
+
+  .agent-option-item {
+    @include flex(x, center, between);
+    cursor: pointer;
+    .agent-title, .agent-sub-title {
+      display: block;
+    }
+    .agent-title {
+      font-size: 14px;
+      font-weight: bold;
+      color: #1A2029;
+    }
+    .agent-sub-title {
+      font-size: 12px;
+      color: #666;
+    }
+  }
+}
 </style>

+ 139 - 24
src/components/Chat/ChatText.vue

@@ -1,5 +1,6 @@
 <script setup lang="jsx">
 import { computed, ref, inject, watchEffect } from 'vue';
+import { NCollapse, NCollapseItem } from 'naive-ui';
 import MarkdownIt from 'markdown-it';
 import hljs from 'highlight.js';
 import mila from 'markdown-it-link-attributes';
@@ -11,7 +12,8 @@ import markdownItSup from 'markdown-it-sup';
 import anchor from 'markdown-it-anchor';
 import toc from 'markdown-it-toc-done-right';
 
-const updateCatalog = inject('updateCatalog');
+const updateCatalog = inject('updateCatalog', null);
+const thinkStr = ref('');
 
 const props = defineProps({
   content: {
@@ -29,6 +31,32 @@ const highlightBlock = (str, lang) => {
   `
 }
 
+let buffer = '';
+
+const handleThinkContent = (content) => {
+  thinkStr.value = content
+  console.log('Extracted think content:', content);
+};
+
+const processStreamData = (chunk) => {
+  // 将新接收到的数据追加到缓冲区
+  buffer += chunk;
+
+  // 使用非贪婪匹配尽可能快地找到<think>...</think>的内容
+  const regex = /<think>(.*?)<\/think>/gs;
+
+  let match;
+  while ((match = regex.exec(buffer)) !== null) {
+    const thinkContent = match[1];
+    // 假设你想对<think>内的内容做特殊处理
+    handleThinkContent(thinkContent);
+
+    // 移除已处理的部分
+    buffer = buffer.slice(match.index + match[0].length);
+  }
+
+
+}
 const mdi = new MarkdownIt({
   html: true,
   linkify: true,
@@ -72,9 +100,9 @@ mdi.use(toc, {
   callback: (_, ast) => {
     setTimeout(_ => {
       const domExists = document.querySelector('.table-of-contents');
-      if ( updateCatalog ) {
-        if ( domExists ) {
-          const { c:content } = ast;
+      if (updateCatalog) {
+        if (domExists) {
+          const { c: content } = ast;
           updateCatalog(content);
         } else {
           updateCatalog([]);
@@ -90,24 +118,7 @@ const transformText = (text) => {
   });
 }
 
-mdi.renderer.rules.echart_block = (tokens, idx, options, env, self) => {
-  const token = tokens[idx];
-  const optionsString = token.content.trim();
-  try {
-    const optionsObj = JSON.parse(optionsString);
-
-    echartOptions[`chart-${idx}`] = { id: idx, code: optionsString, option: optionsObj, isExecute: false }
-
-    return `<div id="chart-${idx}"></div>`;
-  } catch (e) {
-    console.error('Invalid ECharts options:', optionsString);
-    return '';
-  }
-};
-
-mdi.block.ruler.after('fence', 'echart_block', function (state, startLine, endLine, silent) {
-  const startStr = '@@@echarts_b';
-  const endStr = '@@@echarts_e';
+const extractRuler = (startStr, endStr, state, startLine, endLine) => {
 
   if (startLine + 1 < state.lineMax && state.src.slice(state.bMarks[startLine] + state.tShift[startLine], state.eMarks[startLine]) === startStr) {
 
@@ -135,8 +146,52 @@ mdi.block.ruler.after('fence', 'echart_block', function (state, startLine, endLi
   }
 
   return false;
+}
+
+// echart
+mdi.renderer.rules.echart_block = (tokens, idx, options, env, self) => {
+  const token = tokens[idx];
+  const optionsString = token.content.trim();
+  try {
+    const optionsObj = JSON.parse(optionsString);
+
+    echartOptions[`chart-${idx}`] = { id: idx, code: optionsString, option: optionsObj, isExecute: false }
+
+    return `<div id="chart-${idx}"></div>`;
+  } catch (e) {
+    console.error('Invalid ECharts options:', optionsString);
+    return '';
+  }
+};
+
+mdi.block.ruler.after('fence', 'echart_block', function (state, startLine, endLine) {
+  const startStr = '@@@echarts_b';
+  const endStr = '@@@echarts_e';
+  return extractRuler(startStr, endStr, state, startLine, endLine);
 });
 
+// think tag
+// mdi.renderer.rules.think_tag = (tokens, idx, options, env, self) => {
+//   const token = tokens[idx];
+//   const optionsString = token.content.trim();
+//   try {
+//     // const optionsObj = JSON.parse(optionsString);
+//     // echartOptions[`chart-${idx}`] = { id: idx, code: optionsString, option: optionsObj, isExecute: false }
+//     thinkStr.value = optionsString;
+
+//     return `<div class="testAA">${optionsString}</div>`;
+//   } catch (e) {
+//     console.error('Invalid:', e);
+//     return '';
+//   }
+// };
+
+// mdi.block.ruler.after('fence', 'think_tag', function (state, startLine, endLine) {
+//   const startStr = '<think>';
+//   const endStr = '</think>';
+//   return extractRuler(startStr, endStr, state, startLine, endLine);
+// });
+
 const updateCharts = () => {
   Object.keys(echartOptions).forEach((key) => {
     if (echartInstance[key]) return;
@@ -171,8 +226,40 @@ function splitStringByChartDiv(str) {
   return result;
 }
 
+const processedValue = (value) => {
+	return value.replace(/<think>([\s\S]*?)<\/think>/g, (_, content) => {
+	    const lines = content.trim().split('\n');
+	    const quotedLines = lines.map((line) => `> ${line}`).join('\n');
+	    return quotedLines;
+	  });
+};
+
+const thinkParser = (content) => {
+  const regex = /<think>(.*?)<\/think>/gs;
+  const thinkTagRegex = /<think>/;
+  const match = regex.exec(content);
+  if ( match !== null ) {
+    return match[1]
+  }
+  if (thinkTagRegex.test(content)) {
+    return content.slice(7);
+  }
+}
+
+
 watchEffect(() => {
-  const value = mdi.render(props.content);
+  const { content } = props;
+  const thinkValue = thinkParser(content);
+  // const tempStr = !thinkValue ? content : content.replace(thinkValue, '')
+
+  const tempStr = !thinkValue ? content : content.replace(thinkValue, '')
+  
+  // processStreamData(content);
+
+  thinkStr.value = thinkValue && mdi.render(thinkValue || '');
+
+  const value = mdi.render(tempStr);
+  // const value = mdi.render(processedValue(content));
 
   const result = splitStringByChartDiv(value)
 
@@ -181,6 +268,8 @@ watchEffect(() => {
   updateCharts();
 })
 
+
+
 // 原本的逻辑,暂时不用
 const text = computed(() => {
   let value = props.content ?? ""
@@ -190,11 +279,15 @@ const text = computed(() => {
     return mdi.render(value)
   return value
 })
-
 </script>
 
 <template>
   <div class="markdown-body text-[15px] break-all" v-if="content">
+    <n-collapse arrow-placement="right" display-directive="show" class="collapse-wrapper" :default-expanded-names="['thinkTag']" v-if="thinkStr">
+      <n-collapse-item title="已深度思考" name="thinkTag">
+        <div class="think-container" v-html="thinkStr"></div>
+      </n-collapse-item>
+    </n-collapse>
     <div v-for="item, index in markdownText" :key="index" v-html="item"></div>
   </div>
 </template>
@@ -207,6 +300,28 @@ const text = computed(() => {
 .markdown-body {
   word-break: break-word;
 
+  .collapse-wrapper {
+    margin-bottom: 20px;
+
+    .n-collapse-item__header-main {
+      font-size: 14px;
+      color: rgba(0, 0, 0, 0.6) !important;
+    }
+  }
+
+  .think-container {
+    border-left: 2px solid rgba(0, 0, 0, 0.08);
+    padding: 4px 0px 4px 12px;
+    margin-bottom: 8px;
+    font-size: 14px;
+    line-height: 26px;
+    color: rgba(0, 0, 0, 0.6);
+    p, li, span {
+      font-size: 14px;
+    }
+  }
+
+
   .custom-table-wrapper {
     width: 760px;
     padding: 10px 10px 4px 10px;

+ 6 - 4
src/components/Layout/TheArchival.vue

@@ -1,11 +1,9 @@
 <script setup>
 import { NPopover } from 'naive-ui';
-
-
 </script>
 
-<template >
-  <div class="flex space-x-[20px] text-[12px] text-[#1a2029e5]">
+<template>
+  <div class="flex space-x-[10px] text-[12px] text-[#B0B7C0]">
     <div>
       以上内容均由LibraAI生成,仅供参考 
     </div>
@@ -35,6 +33,7 @@ import { NPopover } from 'naive-ui';
 
 <style lang="scss" scoped>
   .archival {
+    transition: all 0.3s;
     cursor: pointer;
     &::after {
       content: " ";
@@ -46,5 +45,8 @@ import { NPopover } from 'naive-ui';
       border-left:4px solid transparent;
       border-bottom:4px solid #b0b7c0;
     }
+    &:hover {
+      color: #666;
+    }
   }
 </style>

+ 2 - 5
src/components/Layout/TheChatView.vue

@@ -48,7 +48,7 @@ defineExpose({ targetScrollDom });
     <div class="catalog-wrapper" v-if="catalogData.length">
       <slot name="catalog"></slot>
     </div>
-    <div class="chat-wrapper w-full h-full flex flex-col rounded-[20px]">
+    <div class="chat-wrapper w-full h-full flex flex-col rounded-[10px]">
       <div class="chat-header flex items-center justify-between py-[24px] px-[18px] ">
         <div class="left_inner" @click="handleClickBack">
           <span v-if="isBackBtn" class="back-btn"></span>
@@ -68,7 +68,7 @@ defineExpose({ targetScrollDom });
       <main class="control-main" v-if="!isChatSlot">
         <slot name="control"></slot>
       </main>
-      <footer class="chat-footer relative w-[900px] m-auto pb-[30px]" v-if="isFooter">
+      <footer class="chat-footer relative w-[900px] m-auto pb-[10px]" v-if="isFooter">
         <slot name="footer" />
       </footer>
     </div>
@@ -80,9 +80,6 @@ defineExpose({ targetScrollDom });
   position: relative;
   padding: 20px 20px 20px 0;
   overflow: hidden;
-  
-  .catalog-wrapper {
-  }
 
   .chat-header {
     .left_inner {

+ 1 - 1
src/components/Layout/TheControlView.vue

@@ -62,7 +62,7 @@ defineExpose({ targetScrollDom });
       <main class="control-main" v-if="!isChatSlot">
         <slot name="control"></slot>
       </main>
-      <footer class="chat-footer relative w-[900px] m-auto pb-[30px]" v-if="isFooter">
+      <footer class="chat-footer relative w-[900px] m-auto pb-[10px]" v-if="isFooter">
         <slot name="footer" />
       </footer>
     </div>

+ 5 - 2
src/views/answer/AnswerView.vue

@@ -21,7 +21,8 @@ const { recommendList } = useRecommend({ type: 0 });
 
 const message = useMessage();
 
-const switchActive = ref(false);
+const onlineSearch = ref(false);
+const switchActive = ref(0);
 const activeItem = ref({});
 
 const isLoading = ref(false);
@@ -107,7 +108,6 @@ const onRegenerate = async ({ showVal, question, realQuestion, tools, uploadFile
     const [ fileItem ] = uploadFileList;
     fileQuestionStr = `file:${fileItem.name + fileItem.originSuffix}||${fileItem.url}||${question}`
   }
-
   const params = {
     data: {
       sessionId,
@@ -117,6 +117,8 @@ const onRegenerate = async ({ showVal, question, realQuestion, tools, uploadFile
       modelType: Number(unref(switchActive)),
       isStrong: Number(unref(switchActive)),
       tools: tools ? tools : unref(switchActive) ? 'DEEPSEEK' : null,
+      onlineSearch: Boolean(unref(onlineSearch)),
+      // tools,
       prompt: null
       // TODO: 后续大概率需要删除
       // topP: 0.9,
@@ -281,6 +283,7 @@ onUnmounted(() => {
           ref="inputRef"
           v-model:loading="isLoading"
           v-model:switch="switchActive"
+          v-model:online="onlineSearch"
           @on-click="handleSubmit"
           @on-enter="handleSubmit"
         ></ChatAgentInput>

+ 6 - 3
src/views/work/WorkView.vue

@@ -20,7 +20,8 @@ const { chatDataSource, addChat, updateChat, clearChat, updateById } = useChat()
 const helperList = ref([]);
 const message = useMessage();
 
-const switchActive = ref(false);
+const switchActive = ref(0);
+const onlineSearch = ref(false);
 
 const isLoading = ref(false);
 const inputRef = ref(null);
@@ -111,11 +112,12 @@ const onRegenerate = async ({ showVal, question, tools, uploadFileList }) => {
   const params = {
     data: {
       sessionId,
-      showVal,                        // 展示问题
+      showVal,                                  // 展示问题
       question: fileQuestionStr || question,    // 给大模型的问题
       module: 2,
       tools: activeItem.value.tools || tools,
-      isStrong: Number(unref(switchActive))
+      isStrong: Number(unref(switchActive)),
+      onlineSearch: Boolean(unref(onlineSearch)),
     },
     signal: controller.signal,
     onDownloadProgress: ({ event }) => {
@@ -287,6 +289,7 @@ onUnmounted(() => {
           ref="inputRef"
           v-model:loading="isLoading"
           v-model:switch="switchActive"
+          v-model:online="onlineSearch"
           @on-click="handleSubmit"
           @on-enter="handleSubmit"
         ></ChatAgentInput>