ConversationChatContainer.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <template>
  2. <div class="conversation-chat-container">
  3. <div class="conversation-chat-left">
  4. <DialogAsideLeft />
  5. </div>
  6. <div class="conversation-chat-main" ref="chat_main">
  7. <DialogHeader class="conversation-chat-header" :style="{ height: header_height + 'px' }" />
  8. <div class="conversation-chat-content">
  9. <DialogList
  10. class="conversation-chat-list"
  11. :height="list_height"
  12. :agent_id="agent_id"
  13. :list="chat_log_list"
  14. :suggestion="chat_suggestion"
  15. :show_welcome="show_welcome"
  16. @share="handleChatShare"
  17. @submit="handleSuggestSubmit"
  18. />
  19. <DialogInput
  20. class="conversation-chat-input"
  21. :style="{ height: input_height + 'px' }"
  22. :disabled="input_disabled"
  23. @inputTextChange="handleTextChange"
  24. @inputFileChange="handleFileChange"
  25. @submit="handleInputSubmit"
  26. />
  27. </div>
  28. <DialogFooter class="conversation-chat-footer" :style="{ height: footer_height + 'px' }" />
  29. </div>
  30. <div class="conversation-chat-right">
  31. <DialogAsideRight />
  32. </div>
  33. </div>
  34. </template>
  35. <script setup>
  36. import { ref, getCurrentInstance, onMounted, onUnmounted, computed } from 'vue';
  37. import DialogAsideLeft from '../../modules/conversation-chat/DialogAsideLeft.vue';
  38. import DialogHeader from '../../modules/conversation-chat/DialogHeader.vue';
  39. import DialogList from '../../modules/conversation-chat/DialogList.vue';
  40. import DialogInput from '../../modules/conversation-chat/DialogInput.vue';
  41. import DialogFooter from '../../modules/conversation-chat/DialogFooter.vue';
  42. import DialogAsideRight from '../../modules/conversation-chat/DialogAsideRight.vue';
  43. import useEleSize from '../../utils/use-ele-size';
  44. import useWebSocketChat from '../../modules/conversation-chat/use-websocket-chat';
  45. import { jsonParse, jsonStringify } from '../../utils/utils';
  46. /**
  47. * 1. 历史会话进入此页面,展示历史会话内容
  48. * 2. 点击智能体,新建会话
  49. */
  50. const props = defineProps({
  51. /**
  52. * 智能体的ID
  53. * 此参数必须传递
  54. */
  55. agent_id: String,
  56. /**
  57. * 会话ID
  58. * 如果有此参数,则意味着获取该对话的记录内容
  59. */
  60. session_id: String,
  61. chat_type: String
  62. });
  63. const header_height = 30;
  64. const footer_height = 30;
  65. const input_height = 100;
  66. const { width: chat_width, height: chat_height } = useEleSize('chat_main');
  67. /**
  68. * 对话列表区域的高度
  69. */
  70. const list_height = computed(() => {
  71. return chat_height.value - header_height - footer_height - input_height;
  72. });
  73. // ------------------------------------------------------------------
  74. // ------------------------------------------------------------------
  75. // ------------------------------------------------------------------
  76. /**
  77. * 对话数据列表
  78. */
  79. const chat_log_list = ref([]);
  80. const chat_suggestion = ref({});
  81. /**
  82. * 是否显示欢迎页
  83. * 当用户进入对话页面,还未正式开始对话时
  84. * 对话区域会显示欢迎内容
  85. * 当用户开始对话时,欢迎内容消失,对话列表开始展示
  86. */
  87. const show_welcome = ref(false);
  88. /**
  89. * 分享
  90. * @param chat_id
  91. */
  92. const handleChatShare = (chat_id) => {};
  93. /**
  94. * 在聊天界面点击推荐项
  95. * 继续对话
  96. */
  97. const handleSuggestSubmit = (suggest) => {};
  98. // ---------------------------------------------
  99. /**
  100. * 输入区域数据控制
  101. */
  102. const input_text = ref('');
  103. const input_files = ref([]);
  104. /**
  105. * 是否禁用输入组件
  106. */
  107. const input_disabled = ref(false);
  108. /**
  109. * 输入文本发生了变化
  110. * @param value
  111. */
  112. const handleTextChange = (value) => {};
  113. /**
  114. * 输入的文件发生了变化
  115. * @param files
  116. */
  117. const handleFileChange = (files) => {};
  118. /**
  119. * 输入已经确认要提交了
  120. * 1. 文件上传
  121. * 2. 创建会话
  122. * get-chat-id
  123. * 连接socket
  124. * 3. socket 发送文本与文件数据内容
  125. * 4. 接收 socket 返回的数据项
  126. */
  127. const handleInputSubmit = () => {
  128. /**
  129. * 创建会话 get chat id
  130. */
  131. /**
  132. * 上传文件,获取文件参数
  133. */
  134. /**
  135. * 组装socket参数
  136. * 发送websocket消息
  137. */
  138. const msg = jsonStringify({
  139. message: '消息内容'
  140. });
  141. handleWSSend(msg);
  142. };
  143. /**
  144. * ------------------------------------------------------------
  145. * websocket定义以及初始化
  146. */
  147. const wsTrigger = {
  148. /**
  149. * 当websocket消息回来后
  150. * @param e
  151. */
  152. onMessage: handleWSMessage,
  153. /**
  154. * 当websocket消息出错时
  155. * @param e
  156. */
  157. onError: handleWSError,
  158. /**
  159. * 当websocket消息关闭时
  160. * @param e
  161. */
  162. onClose: handleWSClose
  163. };
  164. /**
  165. * 初始化websocket相关的一些方法
  166. */
  167. const { initWSConnection, sendWSMessage, getWSInstance, closeWSConnect } = useWebSocketChat(wsTrigger);
  168. /**
  169. * 发送websocket消息
  170. * @param chat_id - 对话记录的ID
  171. * @param value
  172. */
  173. function handleWSSend(chat_id, value) {
  174. // 初始化websocket连接
  175. initWSConnection(props.agent_id, chat_id, props.chat_type);
  176. sendWSMessage(value);
  177. }
  178. /**
  179. * 接收websocket消息
  180. * @param e
  181. */
  182. function handleWSMessage(e) {
  183. const res_data = e.data;
  184. const res_content = jsonParse(res_data);
  185. /**
  186. * 类别:
  187. * close
  188. * error
  189. * message
  190. * stream
  191. */
  192. const res_type = res_content.type;
  193. const res_message = res_content.message; // 消息内容
  194. }
  195. /**
  196. * 处理websocket错误
  197. * @param e
  198. */
  199. function handleWSError(e) {}
  200. /**
  201. * 处理websocket关闭事件
  202. * @param e
  203. */
  204. function handleWSClose(e) {}
  205. onMounted(() => {
  206. // 组件挂载
  207. if (props.session_id) {
  208. // 有历史记录:获取历史记录内容进行展示
  209. } else {
  210. // 无历史记录:等待创建会话内容,列表区域显示欢迎界面
  211. }
  212. });
  213. // ---------------------------------------------------------
  214. onUnmounted(() => {
  215. // 组件卸载,关闭组件内的websocket连接
  216. closeWSConnect();
  217. });
  218. </script>
  219. <style lang="css" scoped>
  220. .conversation-chat-container {
  221. display: flex;
  222. justify-content: center;
  223. margin-left: auto;
  224. margin-right: auto;
  225. height: 100%;
  226. }
  227. .conversation-chat-left {
  228. width: 25%;
  229. flex-shrink: 0;
  230. }
  231. .conversation-chat-right {
  232. width: 25%;
  233. flex-shrink: 0;
  234. }
  235. .conversation-chat-main {
  236. flex-grow: 1;
  237. height: 100%;
  238. margin-left: auto;
  239. margin-right: auto;
  240. display: flex;
  241. flex-direction: column;
  242. background-color: #aaa;
  243. }
  244. .conversation-chat-content {
  245. flex-grow: 1;
  246. display: flex;
  247. flex-direction: column;
  248. overflow: hidden;
  249. }
  250. .conversation-chat-list {
  251. flex-grow: 1;
  252. overflow: auto;
  253. }
  254. .conversation-chat-input {
  255. height: 100px;
  256. background-color: #a67777;
  257. flex-shrink: 0;
  258. }
  259. </style>