Bläddra i källkod

feat: 完善对话模块

zhupei@smartai.com 1 år sedan
förälder
incheckning
a0faeb0b93

+ 23 - 0
src/base/store/use-all-agents.js

@@ -49,6 +49,29 @@ export const useAllAgentStore = defineStore('all_agents', {
 
       return this.agents;
     },
+    /**
+     * 根据agent id获取到相关的记录
+     * @param {string} agent_id
+     */
+    getInfo(agent_id) {
+      if (!agent_id) {
+        return null;
+      }
+
+      const list = this.getList();
+      console.log(list, '所有的agent');
+
+      const total = list.length;
+      for (let i = 0; i < total; i++) {
+        const item = list[i];
+
+        if (item.id === agent_id) {
+          return item;
+        }
+      }
+
+      return null;
+    },
     setList(arr) {
       const list = jsonParse(jsonStringify(arr));
 

+ 2 - 2
src/modules/conversation-board/api-conversation-board.js

@@ -65,7 +65,7 @@ const res_list_example = {
  * 获取所有对话可用的智能体
  * @see https://app.apifox.com/link/project/5404857/apis/api-233232945
  */
-export const conversationBoardAgentList = (params) => {
+export const conversationBoardAgentListBackup = (params) => {
   return new Promise((resolve, reject) => {
     setTimeout(() => {
       resolve(res_list_example);
@@ -78,7 +78,7 @@ export const conversationBoardAgentList = (params) => {
  * 正式环境需要使用的会话列表
  * @see https://app.apifox.com/link/project/5404857/apis/api-233232945
  */
-export const conversationBoardAgentListBackup = (params) => {
+export const conversationBoardAgentList = (params) => {
   const request_url = `/api/dialog/list`;
 
   const send_data = {

+ 49 - 0
src/modules/conversation-board/get-agent-client-config.js

@@ -0,0 +1,49 @@
+/**
+ * 此文件是针对对话agent进行个性化配置
+ * 如有新增配置项,请写清楚注释
+ *
+ * 配置项的 key 为 /api/dialog/list?status=1&current=1&pageSize=50 接口返回的 data中的每一项的ID值
+ */
+
+const client_agent_config = {
+  /**
+   * 小数绘图
+   * 文生图、图生文
+   */
+  '9d75142a-66eb-4e23-b7d4-03efe4584915': {
+    // 文本限制的长度
+    text_limit: 250,
+
+    // 是否支持文件上传
+    file_upload: true,
+
+    // 以下与文件上传配置有关的项目,必须在 file_upload = true 情况下才生效
+    // 可以接收的文件类型
+    file_accept: '.jpg,.png',
+    // 允许多少个文件上传
+    file_limit: 1,
+    // 文件上传组件的提示信息
+    file_message: '支持上传 .png, .jpg,大小不超过10M'
+  }
+};
+
+/**
+ * 客户端对agent的个性化配置
+ * 配置项大致如下:
+ * 1. 文件上传配置
+ *    是否支持文件上传
+ *    支持多少个文件上传
+ *    支持什么类型的文件上传
+ * @param {string} agent_id
+ */
+export default function getAgentClientConfig(agent_id) {
+  if (!agent_id) {
+    return null;
+  }
+
+  if (agent_id in client_agent_config) {
+    return client_agent_config[agent_id];
+  }
+
+  return null;
+}

+ 6 - 2
src/modules/conversation-chat/DialogHeader.vue

@@ -1,10 +1,14 @@
 <template>
   <div class="dialog-header">
-    <div>修改名称</div>
+    <div>{{ agent_info.agent.name }}</div>
   </div>
 </template>
 
-<script setup></script>
+<script setup>
+const props = defineProps({
+  agent_info: Object
+});
+</script>
 
 <style lang="css" scoped>
 .dialog-header {

+ 29 - 6
src/modules/conversation-chat/DialogInput.vue

@@ -35,7 +35,7 @@
 </template>
 
 <script setup>
-import { ref } from 'vue';
+import { ref, onMounted, onUnmounted } from 'vue';
 import InputActions from './dialog-input/InputActions.vue';
 
 import FileUploadPreview from '../file-upload/FileUploadPreview.vue';
@@ -55,6 +55,15 @@ const props = defineProps({
     default: false,
     required: false
   },
+  // 智能体的基本信息
+  agent_info: {
+    type: Object
+  },
+  // 智能体的配置项
+  agent_config: {
+    type: Object
+  },
+
   /**
    * 是否开启文件上传功能
    * 默认 true,即默认开启
@@ -142,7 +151,7 @@ const props = defineProps({
 const input_text_value = ref('');
 const input_file_list = ref([]);
 
-const emit = defineEmits(['inputTextChange', 'inputFileChange', 'submit']);
+const emit = defineEmits(['submit']);
 
 // const fileSelect = useFileSelect('file_upload_input');
 const { select, remove } = useFileSelectedV2();
@@ -153,11 +162,20 @@ const handleSubmit = () => {
     return;
   }
 
-  emit('submit');
+  const real_file_list = [];
+  input_file_list.value.forEach((item) => {
+    real_file_list.push(item.file);
+  });
+
+  emit('submit', {
+    text: input_text_value.value,
+    files: real_file_list
+  });
 };
 
 const clear = () => {
   input_text_value.value = '';
+  input_file_list.value = [];
 };
 
 /**
@@ -199,7 +217,7 @@ const handleFileUpload = () => {
       }
     }
 
-    console.log(files, '文件列表', id, input_file_list.value);
+    // console.log(files, '文件列表', id, input_file_list.value);
   });
 };
 /**
@@ -230,7 +248,7 @@ const handleTextInput = (value, event) => {
 
   input_text_value.value = value;
 
-  emit('inputTextChange', input_text_value.value);
+  // emit('inputTextChange', input_text_value.value);
 };
 
 /**
@@ -253,11 +271,16 @@ const handleTextKeyUp = (e) => {
       removeBreakLineFlag();
 
       // 提交
-      emit('submit');
+      // emit('submit');
+      handleSubmit();
     }
   }
 };
 
+onUnmounted(() => {
+  remove();
+});
+
 defineExpose({
   clear: clear
 });

+ 6 - 4
src/modules/conversation-chat/dialog-item/DialogActions.vue

@@ -2,12 +2,14 @@
   <div class="dialog-actions-container">
     <div class="dialog-action-part dialog-action-left">
       <div class="action-btn-item" @click="handleCopy">复制</div>
-      <div class="action-btn-item" @click="handleRetry">再试一次</div>
-      <div class="action-btn-item" @click="handleShare">分享</div>
+      <!-- <div class="action-btn-item" @click="handleRetry">再试一次</div>
+      <div class="action-btn-item" @click="handleShare">分享</div> -->
     </div>
 
     <div class="dialog-action-part dialog-action-right">
-      <div class="action-btn-item" @click="handleLike">
+      <div class="action-btn-item"></div>
+
+      <!-- <div class="action-btn-item" @click="handleLike">
         <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
           <use xlink:href="#mshd-vote-up"></use>
         </svg>
@@ -16,7 +18,7 @@
         <svg width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
           <use xlink:href="#mshd-vote-down"></use>
         </svg>
-      </div>
+      </div> -->
     </div>
   </div>
 </template>

+ 7 - 1
src/modules/conversation-chat/use-file-select-v2.js

@@ -1,17 +1,23 @@
 export default function useFileSelectedV2(options) {
   const input_list = [];
 
+  let ele_index = 0;
+
   return {
     select(fn) {
       /**
        * https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file
        */
+      const cur = Date.now();
       const input = document.createElement('input');
       input.type = 'file';
-      input.id = Date.now();
+      input.id = `9d75142a66eb4e23b7d403efe4584915-${cur}-${ele_index}`;
       input.setAttribute('multiple', true);
+      input.setAttribute('style', 'display: none;');
       document.body.appendChild(input);
 
+      ele_index = ele_index + 1;
+
       input.click();
       input.onchange = (e) => {
         if (typeof fn === 'function') {

+ 45 - 20
src/modules/conversation-dialog/api-dialog.js

@@ -16,30 +16,55 @@ import { kuky_Authorization } from '../../base/storage';
  * http://192.168.20.119:9301/api/agent/get-chat-id/42e4fcdc9bea11efac300242ac160006
  */
 
+// /**
+//  * 上传文档
+//  * @param {string} id - agentId
+//  * @param {files} files - files
+//  * @returns {Promise<Object>}
+//  */
+// const uploadFiles = (id, file) => {
+//   return ajax.post(`/api/files/upload/${id}`, file, {
+//     headers: {
+//       'Content-Type': 'multipart/form-data'
+//     }
+//   });
+// };
+
+// const uploadExcels = (file) => {
+//   return ajax.post('/api/document/excel/upload', file, {
+//     headers: {
+//       'Content-Type': 'multipart/form-data'
+//     }
+//   });
+// };
+
 /**
- * 上传文档
- * @param {string} id - agentId
- * @param {files} files - files
- * @returns {Promise<Object>}
+ * 上传文件
+ * @param {string} agent_id
+ * @param {string} chat_id
+ * @param {FormData} file
+ * @returns
  */
-const uploadFiles = (id, file) => {
-  return ajax.post(`/api/files/upload/${id}`, file, {
-    headers: {
-      'Content-Type': 'multipart/form-data'
+export const uploadFiles = (agent_id, chat_id, file) => {
+  /**
+   * 响应数据示例
+   * 单文件
+   */
+  const res_example1 = {
+    code: 200,
+    msg: '',
+    data: {
+      id: 'faf0d7f5-ba4d-4dcc-81bd-be826accfeb9',
+      name: 'juejin.pdf',
+      size: 1432958,
+      extension: 'pdf',
+      mime_type: 'application/pdf',
+      created_by: '714172d6-5be3-4891-b413-2eb5a5047d02',
+      created_at: 1734487728
     }
-  });
-};
-
-const uploadExcels = (file) => {
-  return ajax.post('/api/document/excel/upload', file, {
-    headers: {
-      'Content-Type': 'multipart/form-data'
-    }
-  });
-};
+  };
 
-const uploadFile = (id, chatId, file) => {
-  return ajax.post(`/api/files/upload/${id}?chat_id=${chatId}`, file, {
+  return ajax.post(`/api/files/upload/${agent_id}?chat_id=${chat_id}`, file, {
     headers: {
       'Content-Type': 'multipart/form-data'
     }

+ 4 - 0
src/modules/conversation-dialog/format-dialog-answer-from-websocket_receive_message.js

@@ -239,6 +239,10 @@ export default function formatDialogAnswerFromWebsocketReceiveMessage(message_st
   if (resType === 'error') {
     // 错误消息
     chat_status = 3;
+    currentMsg.client_custom_chat_status = 2; // 次轮会话已结束
+    currentMsg.client_custom_chat_type = 1; // 修改消息类型: 改为 结束
+
+    currentMsg.answer = resMessage;
   }
 
   /**

+ 7 - 0
src/modules/conversation-dialog/format-dialog-send-options.js

@@ -3,6 +3,13 @@ import { jsonParse, jsonStringify } from '../../utils/utils';
 /**
  * 格式化websocket发送消息的参数
  */
+
+/**
+ * 组装发送websocket消息时的参数
+ * @param {string} text - 纯文本数据
+ * @param {object[]} file_list - 文件上传后,接口返回的数据信息,某些场景需要携带文件数据
+ * @returns
+ */
 export default function formatDialogSendOptions(text, file_list) {
   /**
    * 组装socket参数

+ 18 - 2
src/modules/file-upload/FileItemDocPreview.vue

@@ -1,5 +1,5 @@
 <template>
-  <div>
+  <div class="file-item-doc-preview">
     <div>{{ file.name }}</div>
   </div>
 </template>
@@ -10,6 +10,22 @@ import { ref, computed } from 'vue';
 const props = defineProps({
   file: Object
 });
+
+console.log(props.file, '文档内容');
+
+/**
+ * lastModified: 1733385125049
+ * lastModifiedDate: Date,
+ * name: 'juejin.pdf',
+ * size: 143258,
+ * type: 'application/pdf',
+ * webkitRelativePath: ''
+ */
 </script>
 
-<style lang="css" scoped></style>
+<style lang="css" scoped>
+.file-item-doc-preview {
+  background-color: #fff;
+  padding: 5px;
+}
+</style>

+ 3 - 9
src/modules/file-upload/FileUploadPreview.vue

@@ -14,6 +14,7 @@
 import { ref, computed } from 'vue';
 import FileItemDocPreview from './FileItemDocPreview.vue';
 import FileItemImagePreview from './FileItemImagePreview.vue';
+import isImageByFileName from './is-image-by-filename';
 
 const props = defineProps({
   file_list: Array
@@ -35,10 +36,8 @@ const file_images_list = computed(() => {
 
   props.file_list.forEach((item, index) => {
     const file_name = item.file.name;
-    const name_info_arr = file_name.split('.');
-    const end_fix = name_info_arr[name_info_arr.length - 1];
 
-    const is_image = isImageEndfix(end_fix);
+    const is_image = isImageByFileName(file_name);
 
     if (is_image) {
       arr.push(item);
@@ -56,10 +55,8 @@ const file_doc_list = computed(() => {
 
   props.file_list.forEach((item, index) => {
     const file_name = item.file.name;
-    const name_info_arr = file_name.split('.');
-    const end_fix = name_info_arr[name_info_arr.length - 1];
 
-    const is_image = isImageEndfix(end_fix);
+    const is_image = isImageByFileName(file_name);
 
     if (!is_image) {
       arr.push(item);
@@ -72,9 +69,6 @@ const file_doc_list = computed(() => {
 
 <style lang="css" scoped>
 .file-upload-preview-area {
-  /* display: flex;
-  justify-content: space-between;
-  align-items: center; */
 }
 
 .file-doc-preview-container {

+ 14 - 0
src/modules/file-upload/files-2-formdata.js

@@ -0,0 +1,14 @@
+/**
+ * 将 File 转换为文件上传用到的 formdata 数据
+ * @param {File[]} f_list
+ * @returns
+ */
+export default function files2Formdata(f_list) {
+  const formData = new FormData();
+
+  f_list.forEach((item) => {
+    formData.append('file', item);
+  });
+
+  return formData;
+}

+ 20 - 0
src/modules/file-upload/is-image-by-filename.js

@@ -0,0 +1,20 @@
+/**
+ * 判断一个文件的后缀名是否是图片
+ * @param endfix
+ */
+const isImageEndfix = (endfix) => {
+  return endfix === 'jpg' || endfix === 'png' || endfix === 'jpeg' || endfix === 'gif';
+};
+
+/**
+ * 根据文件名检查一个文件是否是图片类型
+ * @param {string} file_name
+ */
+export default function isImageByFileName(file_name) {
+  const name_info_arr = file_name.split('.');
+  const end_fix = name_info_arr[name_info_arr.length - 1];
+
+  const is_image = isImageEndfix(end_fix);
+
+  return is_image;
+}

+ 26 - 21
src/views/ConversationQA.vue

@@ -105,34 +105,39 @@ onMounted(async () => {
 
   if (!agent_id) {
     // 不存在参数
-    query_value_status.value = 3;
-    query_value_message.value = '非法操作:参数异常';
 
-    // TODO: 使用默认的通用agent创建对话
+    // 使用默认的通用agent创建对话
+    /**
+     * 如果没有agent参数,则使用默认的agent
+     * 默认的agent,和赵秦刚沟通,为知识问答(2024-12-18)
+     * 下列为知识问答的ID
+     */
+    const default_agent_id = '42e4fcdc-9bea-11ef-ac30-0242ac160006';
+    chat_agent.value = default_agent_id;
+
+    query_value_status.value = 2;
+    query_value_message.value = 'success';
+  } else {
+    // 有agent参数
+    // 判断已经缓存的agent列表是否存在
 
-    return;
-  }
+    const is_valid = await isValidAgent(agent_id);
 
-  // 有agent参数
-  // 判断已经缓存的agent列表是否存在
+    if (!is_valid) {
+      // 不存在参数
+      query_value_status.value = 3;
+      query_value_message.value = '非法操作:参数异常';
 
-  const is_valid = await isValidAgent(agent_id);
+      return;
+    }
 
-  if (!is_valid) {
-    // 不存在参数
-    query_value_status.value = 3;
-    query_value_message.value = '非法操作:参数异常';
+    chat_agent.value = agent_id;
+    chat_session.value = session_id;
+    // 如果存在history_id则获取历史会话内容
 
-    return;
+    query_value_status.value = 2;
+    query_value_message.value = 'success';
   }
-
-  query_value_status.value = 2;
-  query_value_message.value = 'success';
-
-  chat_agent.value = agent_id;
-  chat_session.value = session_id;
-
-  // 如果存在history_id则获取历史会话内容
 });
 
 /**

+ 1 - 1
src/views/Xiaoshu.vue

@@ -79,7 +79,7 @@ onMounted(() => {
       height: 40px;
       line-height: 40px;
       text-align: center;
-      background-color: red;
+      background-color: #165dff;
       color: #fff;
       display: inline-block;
       cursor: pointer;

+ 1 - 0
src/views/conversation/ChatAsideMenu.vue

@@ -43,6 +43,7 @@ import { computed } from 'vue';
 import { useRouter } from 'vue-router';
 import { useThemeStore } from '../../base/store/use-theme';
 import { useRecentAgentStore } from '../../base/store/use-recent-agents';
+import { useAllAgentStore } from '../../base/store/use-all-agents';
 
 import ChatAsideBtn from './ChatAsideBtn.vue';
 

+ 11 - 0
src/views/conversation/ConversationBoardContainer.vue

@@ -46,13 +46,24 @@ import BoardAgentList from '../../modules/conversation-board/BoardAgentList.vue'
 
 import useAgentList4Board from '../../modules/conversation-board/use-agent-list-4-board';
 
+import { useRecentAgentStore } from '../../base/store/use-recent-agents';
+import { useAllAgentStore } from '../../base/store/use-all-agents';
+
 const emit = defineEmits(['agentActive']);
 
 const selected_id = ref('');
 
 const { api_status, api_message, list_agents, getAgentList } = useAgentList4Board();
 
+const recentAgents = useRecentAgentStore();
+const allAgents = useAllAgentStore();
+
 const handleItemActive = (target_id) => {
+  const target_info = allAgents.getInfo(target_id);
+
+  // 添加记录
+  recentAgents.addItem(target_id, 'name', 'icon');
+
   emit('agentActive', target_id);
 };
 

+ 115 - 48
src/views/conversation/ConversationChatContainer.vue

@@ -5,7 +5,11 @@
     </div>
 
     <div class="conversation-chat-main" ref="chat_main">
-      <DialogHeader class="conversation-chat-header" :style="{ height: header_height + 'px' }" />
+      <DialogHeader
+        class="conversation-chat-header"
+        :agent_info="CHAT_AGENT_INFOMATION"
+        :style="{ height: header_height + 'px' }"
+      />
 
       <div class="conversation-chat-content">
         <DialogWelcome v-if="show_welcome" class="conversation-chat-area" />
@@ -25,9 +29,9 @@
           ref="dialog_input"
           class="conversation-chat-input"
           :style="{ height: input_height + 'px' }"
+          :agent_info="CHAT_AGENT_INFOMATION.agent"
+          :agent_config="CHAT_AGENT_INFOMATION.config"
           :disabled="input_disabled"
-          @inputTextChange="handleTextChange"
-          @inputFileChange="handleFileChange"
           @submit="handleInputSubmit"
         />
       </div>
@@ -52,8 +56,12 @@ import DialogInput from '../../modules/conversation-chat/DialogInput.vue';
 import DialogFooter from '../../modules/conversation-chat/DialogFooter.vue';
 import DialogAsideRight from '../../modules/conversation-chat/DialogAsideRight.vue';
 
+import { useAllAgentStore } from '../../base/store/use-all-agents';
+import getAgentClientConfig from '../../modules/conversation-board/get-agent-client-config';
+
 import useWebSocketChat from '../../modules/conversation-dialog/use-websocket-chat';
-import { getHistoryLogs, getDialogChatId } from '../../modules/conversation-dialog/api-dialog';
+import { getHistoryLogs, getDialogChatId, uploadFiles } from '../../modules/conversation-dialog/api-dialog';
+import files2Formdata from '../../modules/file-upload/files-2-formdata';
 
 import formatDialogSendOptions from '../../modules/conversation-dialog/format-dialog-send-options';
 
@@ -87,6 +95,19 @@ const props = defineProps({
   chat_type: String
 });
 
+const allAgents = useAllAgentStore();
+
+/**
+ * 对话使用到的agent信息
+ * agent属性是由接口返回的数据
+ * config属性是客户端自定义的数据,针对特定的agent的一些个性化配置,可由此进行配置
+ * 二者结合,形成对话组件所需要的一些参数
+ */
+const CHAT_AGENT_INFOMATION = ref({
+  agent: {},
+  config: {}
+});
+
 const header_height = 30;
 const footer_height = 30;
 const input_height = 100;
@@ -168,31 +189,11 @@ const handleSuggestSubmit = (suggest) => {};
 
 // ---------------------------------------------
 
-/**
- * 输入区域数据控制
- */
-const input_text = ref('');
-const input_files = ref([]);
-
 /**
  * 是否禁用输入组件
  */
 const input_disabled = ref(false);
 
-/**
- * 输入文本发生了变化
- * @param value
- */
-const handleTextChange = (value) => {
-  input_text.value = value;
-};
-/**
- * 输入的文件发生了变化
- * @param files
- */
-const handleFileChange = (files) => {
-  input_files.value = files;
-};
 /**
  * 输入已经确认要提交了
  *
@@ -201,7 +202,12 @@ const handleFileChange = (files) => {
  * 3. 连接socket,socket 发送文本与文件数据内容
  * 4. 接收 socket 返回的数据项
  */
-const handleInputSubmit = async () => {
+const handleInputSubmit = async (options) => {
+  const ask_text = options.text; // 文本
+  const ask_files = options.files; // 文件列表
+
+  const agent_id = props.agent_id;
+
   /**
    * 创建会话 get chat id
    * 判断对话是否已经创建
@@ -211,7 +217,7 @@ const handleInputSubmit = async () => {
   if (chat_new_id.value === null) {
     // 未创建chat,开始创建
     try {
-      const chatResult = await getDialogChatId(props.agent_id);
+      const chatResult = await getDialogChatId(agent_id);
 
       if (chatResult.code / 1 === 200) {
         // 成功
@@ -234,24 +240,52 @@ const handleInputSubmit = async () => {
     console.log(chat_new_id.value, '已创建');
   }
 
+  // 文件上传后的信息
+  let files_response = null;
   /**
    * 如果存在文件数据,则进行文件上传
    */
-  if (input_files.value.length !== 0) {
+  if (ask_files.length !== 0) {
     // 进行文件上传,获取文件信息
+    const file_params = files2Formdata(ask_files);
+    const chat_id = chat_new_id.value;
+
+    try {
+      const uploadResult = await uploadFiles(agent_id, chat_id, file_params);
+
+      if (uploadResult.code / 1 === 200) {
+        // 文件上传成功
+        const file_uploaded = uploadResult.data;
+
+        if (Array.isArray(file_uploaded)) {
+          files_response = file_uploaded;
+        } else {
+          files_response = [file_uploaded];
+        }
+      } else {
+        // 文件上传异常
+        // TODO: 处理错误
+        return;
+      }
+    } catch (err) {
+      console.log(err);
+      // 文件上传失败
+      // TODO: 处理错误
+      return;
+    }
   }
 
   /**
    * 获取文件参数
    * 组装socket参数
    */
-  const msg = formatDialogSendOptions(input_text.value, input_files.value);
+  const msg = formatDialogSendOptions(ask_text, files_response);
 
   /**
    * 整理客户端提问的数据
    * 组装Question数据
    */
-  const client_question = formatDialogQuestionByClient(input_text.value, input_files.value);
+  const client_question = formatDialogQuestionByClient(ask_text, ask_files);
   // 保存用户的提问信息
   // 当消息正式发出后,将提问数据放入列表中
   chat_new_question.value = client_question;
@@ -333,8 +367,6 @@ function handleWSSend(chat_id, value) {
    */
   show_welcome.value = false;
   // 清空文本数据和文件数据,避免下一次会话冲突
-  input_text.value = '';
-  input_files.value = [];
   // 清空表单里的数据
   inputClear();
   // 清空可能存在的推荐项目
@@ -364,40 +396,51 @@ function handleWSMessage(e) {
   const currentChat = formatDialogAnswerFromWebsocketReceiveMessage(res_data, last_msg);
   const chat_status = currentChat.status;
   const chat_message = currentChat.message;
-  const chat_data = currentChat.data;
-
-  if (chat_status === 0) {
-    // 未开始: 此状态不存在,无需处理
-  }
 
-  if (chat_status === 1) {
-    // 此轮对话仍然在进行中
+  // 处理对话数据
+  const handleChatData = () => {
+    const chat_data = currentChat.data; // 对话相关的数据项
 
     // 原来的最后一项弹出
     chat_new_list.value.pop();
     // 添加新的最后一项
     chat_new_list.value.push(chat_data);
+
     // 滚动到底部
     scroll2ListBottom();
+  };
+
+  if (chat_status === 0) {
+    // 未开始: 此状态不存在,无需处理
+  }
+
+  if (chat_status === 1) {
+    // 此轮对话仍然在进行中
+    handleChatData();
   }
 
   if (chat_status === 2) {
     // 此轮对话已结束
+    handleChatData();
 
-    // 原来的最后一项弹出
-    chat_new_list.value.pop();
-    // 添加新的最后一项
-    chat_new_list.value.push(chat_data);
-    // 滚动到底部
-    scroll2ListBottom();
+    // 对话已结束:检查是否存在推荐数据
+    const chat_suggest = currentChat.suggest; // 对话相关的推荐数据
+    if (chat_suggest) {
+      chat_suggestion.value = chat_suggest;
+    }
 
-    // 文件上传、文本输入区域放开使用
+    // 对话已结束:文件上传、文本输入区域放开使用
     input_disabled.value = false;
   }
 
   if (chat_status === 3) {
     // 此轮对话出错了
     // TODO: 错误处理
+
+    // 此轮对话已结束
+    handleChatData();
+    // 对话已结束:文件上传、文本输入区域放开使用
+    input_disabled.value = false;
   }
 }
 
@@ -414,10 +457,13 @@ function handleWSError(e) {}
 function handleWSClose(e) {}
 
 onMounted(() => {
+  const agent_id = props.agent_id;
+  const session_id = props.session_id;
+
   // 组件挂载
-  if (props.session_id) {
+  if (session_id) {
     // 有历史记录:获取历史记录内容进行展示
-    getHistoryLogs(props.agent_id, props.session_id)
+    getHistoryLogs(agent_id, session_id)
       .then((res) => {
         if (res.code / 1 === 200) {
           // 成功
@@ -447,6 +493,27 @@ onMounted(() => {
   } else {
     // 无历史记录:等待创建会话内容(用户开始输入、提交完成),列表区域显示欢迎界面
   }
+
+  /**
+   * 根据agent_id 查询到agent的基本信息
+   * 从而确定agent的相关功能支持,例如:是否需要上传文件,支持上传什么类型的文件、支持上传多少个文件?
+   * 例如:主题、背景、等等
+   */
+  const agentInfo = allAgents.getInfo(agent_id);
+  if (agentInfo) {
+    const client_config = getAgentClientConfig(agent_id);
+    if (client_config) {
+      CHAT_AGENT_INFOMATION.value = {
+        config: client_config,
+        agent: agentInfo
+      };
+    } else {
+      CHAT_AGENT_INFOMATION.value = {
+        config: {},
+        agent: agentInfo
+      };
+    }
+  }
 });
 
 // ---------------------------------------------------------
@@ -484,7 +551,7 @@ onUnmounted(() => {
   display: flex;
   flex-direction: column;
 
-  background-color: #aaa;
+  /* background-color: #aaa; */
 }
 .conversation-chat-content {
   flex-grow: 1;