From 7e465ce011a27b730d529fd912eae5f9552520b4 Mon Sep 17 00:00:00 2001
From: zhaowei <zhaowei>
Date: 星期三, 07 八月 2024 17:48:35 +0800
Subject: [PATCH] 基本实现语言大模型页面布局及功能(未与模型对话接口调试)

---
 src/views/ai/LanguageModel.vue |  615 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 532 insertions(+), 83 deletions(-)

diff --git a/src/views/ai/LanguageModel.vue b/src/views/ai/LanguageModel.vue
index 3a17391..e2d3666 100644
--- a/src/views/ai/LanguageModel.vue
+++ b/src/views/ai/LanguageModel.vue
@@ -2,37 +2,102 @@
   <div class="page-container">
     <div class="outer-container">
       <div class="left-container">
-        <div><img src="@/assets/page/languageModel/logo.png" style="width: 100%"></div>
-        <a-button style="margin: 20px 0 10px" @click="createNewConversation">鏂板浼氳瘽</a-button>
+        <div class="logo-container"><img src="@/assets/page/languageModel/logo.png"></div>
+        <div class="manage-history-container">
+          <div @click="createNewConversation"
+               :class="[isAtNewConversation?'create-history-container-active':'',isDeletingBatch?'fold-create-history-container':'expand-create-history-container']"
+               class="create-new-conversation">
+            <a-icon type="plus"></a-icon>
+            <span v-if="!isDeletingBatch">鏂板浼氳瘽</span>
+          </div>
+          <div @click="expandDeleteBatchContainer"
+               :class="[isDeletingBatch?'expand-delete-batch-container':'fold-delete-batch-container',chatHistoryList.length===0?'disable-expand':'']"
+               class="delete-batch-container">
+            <a-icon type="delete" v-if="!isDeletingBatch"/>
+            <template v-else>
+              <div class="expand-delete-batch-inner">
+                <div class="select-all-button">
+                  <label class="checkbox-custom">
+                    <input type="checkbox" @change="allHistoryCheckedChange"
+                           id="select-all-checkbox"></input>
+                    <span class="check-mark"></span>
+                    <div>鍏ㄩ��</div>
+                  </label>
+                </div>
+                <div class="split-line"></div>
+                <a-popover placement="top" :visible="deleteBatchPopVisible" trigger="click"
+                           :getPopupContainer="node=>node.parentNode" overlayClassName="delete-batch-popover">
+                  <template slot="content">
+                    <div class="popover-content">
+                      <div>鍒犻櫎鍚庢棤娉曟仮澶嶏紝鏄惁缁х画鍒犻櫎锛�</div>
+                      <div>
+                        <button class="cancel-delete-button" @click="deleteBatchPopVisible=false">鍙栨秷</button>
+                        <button id="confirm-delete-batch-button" @click="confirmDeleteBatchConversation">鍒犻櫎
+                        </button>
+                      </div>
+                    </div>
+                  </template>
+                  <div @click="deleteBatchConversation" id="delete-batch-button"
+                       :class="[checkedConversationIdList.length?'able-delete-button':'disable-delete-button']">
+                    <a-icon type="delete"/>
+                    <div>鍒犻櫎</div>
+                  </div>
+                </a-popover>
+                <div class="split-line"></div>
+                <div @click.stop="cancelDeleteBatchConversation">
+                  <a-icon type="close"/>
+                  <div>閫�鍑�</div>
+                </div>
+              </div>
+            </template>
+          </div>
+        </div>
         <div class="chat-history-container">
-
-          <div v-for="(item,index) in chatHistoryList" :key="index"
-               :class="[item.id===activeHistoryIndex?'single-history-active':'']"
-               @click="switchToCurrentConversation(item,index)" @mouseenter="item.iconVisible=true"
+          <div v-for="(item,index) in chatHistoryList" :key="item.id"
+               :class="[item.id===activeHistoryIndex?'single-history-active':'',item.inputVisible?'input-visible-class':'']"
+               @click="switchToCurrentConversation(item,$event)"
+               @mouseenter="item.iconVisible=true"
                @mouseleave="item.iconVisible=false">
-            <a-popconfirm ok-text="鍒犻櫎" cancel-text="鍙栨秷" @confirm="confirmDeleteConversation(item,index)"
-                          @cancel="cancelDeleteConversation(item)"
-                          :visible="item.deletePopVisible" :arrowPointAtCenter="true">
-              <template slot="title">
-                鍒犻櫎鍚庢棤娉曟仮澶嶏紝鏄惁缁х画鍒犻櫎锛�
+            <!--input鏀剧疆鍦╬opover涓棤娉曚娇鐢ㄥ姛鑳�-->
+            <label v-if="isDeletingBatch" class="checkbox-custom">
+              <input type="checkbox" v-model="checkedConversationIdList" :value="item.id"
+                     @change="singleHistoryCheckedChange"/>
+              <span class="check-mark"></span>
+            </label>
+
+
+            <a-popover placement="top" :visible="item.deletePopVisible" trigger="click"
+                       :getPopupContainer="node=>node.parentNode">
+              <template slot="content">
+                <div class="popover-content">
+                  <div>鍒犻櫎鍚庢棤娉曟仮澶嶏紝鏄惁缁х画鍒犻櫎锛�</div>
+                  <div>
+                    <button class="cancel-delete-button" @click="cancelDeleteConversation(item,$event)">鍙栨秷</button>
+                    <button @click="confirmDeleteConversation(item,index)" id="delete-conversation-button">鍒犻櫎</button>
+                  </div>
+                </div>
               </template>
               <template v-if="!item.inputVisible">
                 <div class="conversation-title">{{item.title}}</div>
-                <div class="icon-container" v-show="item.iconVisible">
-                  <a-icon type="edit" @click.stop="editConversationTitle(item,index)"/>
-                  <a-icon type="delete" @click.stop="deleteConversation(item,index)"/>
+                <div class="icon-container hover-icon-container" v-show="!isDeletingBatch">
+                  <a-icon type="edit" @click.stop="editConversationTitle(item)"/>
+                  <a-icon type="delete" @click.stop="deleteConversation(item)"
+                          @blur="cancelDeleteConversation(item,$event)"/>
                 </div>
               </template>
 
               <template v-else>
                 <input id="edit-input" v-model="editedConversationTitle"
-                       @keydown.enter="confirmEditConversationTitle(item)" maxlength="15"></input>
+                       @keydown.enter="confirmEditConversationTitle(item,$event)"
+                       @blur="cancelEditConversationTitle(item,$event)"
+                       maxlength="15">
+                </input>
                 <div class="icon-container">
-                  <a-icon type="check" @click.stop="confirmEditConversationTitle(item)"/>
-                  <a-icon type="close" @click.stop="cancelEditConversationTitle(item)"/>
+                  <a-icon type="check" @click.stop="confirmEditConversationTitle(item,$event)"/>
+                  <a-icon type="close"/>
                 </div>
               </template>
-            </a-popconfirm>
+            </a-popover>
           </div>
         </div>
       </div>
@@ -55,7 +120,7 @@
           </div>
         </div>
         <div class="input-container" :class="[textareaFocused?'input-container-active':'']">
-          <textarea v-model="inputQuestion" placeholder="Enter鍙戦�侊紝Shift+Enter鎹㈣"
+          <textarea v-model="inputQuestion" :placeholder="textareaPlaceholder"
                     @keydown.enter="sendQuestion($event)" @focus="textareaFocused=true"
                     @blur="textareaFocused=false"></textarea>
           <img src="@/assets/page/languageModel/send-message.png" @click="sendQuestion($event)" v-if="!isResponding">
@@ -73,7 +138,8 @@
   import { randomUUID } from '@/utils/util'
 
   message.config({
-    maxCount: 1
+    maxCount: 1,
+    duration: 2
   })
 
   export default {
@@ -82,9 +148,11 @@
     data() {
       return {
         chatHistoryList: [],
+        checkedConversationIdList: [],
+        deleteBatchPopVisible: false,
         currentConversation: {
-          'id': '683a65fd-8feb-4446-ad32-714c4785f667',
-          'messages': [
+          id: '683a65fd-8feb-4446-ad32-714c4785f667',
+          messages: [
             {
               'role': 'user',
               'content': '浣犳槸璋侊紵浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋佷綘鏄皝浣犳槸璋�'
@@ -118,12 +186,15 @@
               'content': '鎴戣兘绔欏湪鏈潵瑙嗚甯姪鍚屽浠仛濂界敓娑鍒掓寚瀵笺��'
             }
           ],
-          'stream': false,
-          'max_tokens': 500,
+          stream: false,
+          max_tokens: 500,
           iconVisible: false,
           inputVisible: false,
           deletePopVisible: false
         },
+        // currentConversation: {},
+        isAtNewConversation: false,
+        isDeletingBatch: false,
         activeHistoryIndex: null,
         editingHistoryIndex: null,
         deletingHistoryIndex: null,
@@ -133,15 +204,25 @@
         deletePopVisible: false,
         conversationContainer: null,
         inputQuestion: '',
+        textareaPlaceholder: 'Enter鍙戦�侊紝Shift+Enter鎹㈣',
         textareaFocused: false,
         isResponding: false
       }
     },
-    created() {
-      this.getConversationByApi()
 
+    watch: {
+      deleteBatchPopVisible: {
+        handler(val) {
+          if (val) {
+            document.addEventListener('click', this.handleDocumentClick)
+          } else {
+            document.removeEventListener('click', this.handleDocumentClick)
+          }
+        }
+      }
     },
     mounted() {
+      this.getConversationByApi()
       this.conversationContainer = document.querySelector('.conversation-container')
     },
     methods: {
@@ -152,13 +233,16 @@
         this.currentConversation.title = this.currentConversation.messages[0].content.slice(0, 15)
         this.chatHistoryList.push(this.currentConversation)
         this.activeHistoryIndex = this.chatHistoryList[0].id
+        if (!this.chatHistoryList.length) this.textareaPlaceholder = '璇峰皾璇曢棶鎴戯細浣犳槸璋侊紵'
       },
 
       /* 鍒涘缓涓�涓柊浼氳瘽 */
       createNewConversation() {
+        if (this.isAtNewConversation) this.$message.info('褰撳墠宸叉槸鏈�鏂板璇�')
+        this.isAtNewConversation = true
         this.currentConversation = {
           id: randomUUID(),
-          title: '鏈懡鍚嶅璇�',
+          title: '',
           messages: [],
           stream: true,
           max_tokens: 500,
@@ -166,66 +250,138 @@
           inputVisible: false,
           deletePopVisible: false
         }
-        // 閫�鍑哄叾浠栧姛鑳�
-        if (this.editingHistoryIndex !== null) this.cancelEditConversationTitle(this.chatHistoryList.find(item => item.id === this.editingHistoryIndex))
-        if (this.deletingHistoryIndex !== null) this.cancelDeleteConversation(this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex))
-
-        this.chatHistoryList.unshift(this.currentConversation)
-        this.activeHistoryIndex = this.chatHistoryList[0].id
-        console.log(this.chatHistoryList)
+        // 鏂板缓浼氳瘽鏃跺彇娑堝師鍏堣閫変腑鐨勫巻鍙插璇濓紝鏇存竻鏅板憡璇夌敤鎴风幇鍦ㄧ晫闈㈠浜庢柊寤哄璇濅腑
+        if (this.activeHistoryIndex !== null) this.activeHistoryIndex = null
+        this.textareaPlaceholder = '璇峰皾璇曢棶鎴戯細浣犳槸璋侊紵'
       },
 
-      /* 鍒囨崲鑷冲綋鍓嶇偣鍑讳細璇� */
-      switchToCurrentConversation(record, index) {
-        if (record.inputVisible) return // 褰撴潯浼氳瘽姝e湪琚慨鏀规椂鍐嶆鐐瑰嚮鏈潯浼氳瘽鏃犲弽棣�
-        this.activeHistoryIndex = record.id
-        this.currentConversation = this.chatHistoryList[index]
+      /* 鐐瑰嚮鍏ㄩ�夋寜閽悗鏀瑰彉鍕鹃�夊悗瑙﹀彂 */
+      allHistoryCheckedChange(event) {
+        // event.target.indeterminate = true
+        if (event.target.checked) {
+          this.checkedConversationIdList = this.chatHistoryList.map(item => item.id)
+        } else {
+          this.checkedConversationIdList = []
+        }
+        console.log('瑙﹀彂鍏ㄩ��', event.target.checked)
+      },
 
-        if (this.editingHistoryIndex !== null) {
-          this.chatHistoryList.find(item => item.id === this.editingHistoryIndex).inputVisible = false
-          this.editingHistoryIndex = null
+      /* 鐐瑰嚮鍘嗗彶璁板綍涓閫夋鏀瑰彉鍕鹃�夊悗瑙﹀彂 */
+      singleHistoryCheckedChange() {
+        // 浠呭湪鎵归噺鍒犻櫎灞曞紑鏃惰幏鍙栧埌
+        const selectAllCheckbox = document.getElementById('select-all-checkbox')
+
+        if (this.checkedConversationIdList.length > 0) {
+          if (this.checkedConversationIdList.length !== this.chatHistoryList.length) {
+            console.log('瑙﹀彂鏈叏閫変腑', selectAllCheckbox.indeterminate)
+            this.$nextTick(() => selectAllCheckbox.indeterminate = true)
+          } else {
+            console.log('瑙﹀彂鍏ㄨ閫変腑', selectAllCheckbox)
+            // document.getElementById('select-all-checkbox').indeterminate = false
+            this.$nextTick(() => {
+              selectAllCheckbox.indeterminate = false
+              selectAllCheckbox.checked = true
+            })
+          }
+        } else {
+          selectAllCheckbox.indeterminate = false
+          selectAllCheckbox.checked = false
         }
       },
 
-      editConversationTitle(record, index) {
-        // 浠呭紑鍚渶鍚庝竴娆$偣鍑荤紪杈戞寜閽悗鐨勮緭鍏ユ
-        if (this.editingHistoryIndex !== null && this.editingHistoryIndex !== record.id) this.chatHistoryList.find(item => item.id === this.editingHistoryIndex).inputVisible = false
-        // 杩涘叆缂栬緫鍚庡叧闂墍鏈夌‘璁ゅ垹闄ゅ脊绐�
-        if (this.deletingHistoryIndex !== null) this.cancelDeleteConversation(this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex))
-        console.log('杩涘叆淇敼', record)
-        this.editingHistoryIndex = record.id
-        record.inputVisible = true
-        this.editedConversationTitle = record.title
-        this.$nextTick(() => {
-          document.getElementById('edit-input').focus()
+      /* 鐐瑰嚮鎵归噺鍒犻櫎浼氳瘽鍥炬爣鏃跺睍寮�鎵归噺绠$悊鍖哄煙 */
+      expandDeleteBatchContainer() {
+        if (this.chatHistoryList.length === 0) return
+        this.isDeletingBatch = true
+      },
+
+      /* 鐐瑰嚮绾㈣壊鍥炬爣鎵归噺鍒犻櫎鎸夐挳鍚庤Е鍙� */
+      deleteBatchConversation() {
+        if (!this.checkedConversationIdList.length) return
+        this.deleteBatchPopVisible = !this.deleteBatchPopVisible
+      },
+
+      /* 鐐瑰嚮鏂囨。绌虹櫧鍏抽棴鎵归噺鍒犻櫎popover */
+      handleDocumentClick(e) {
+        const popover = document.querySelector('.delete-batch-popover')
+        const button = document.getElementById('delete-batch-button')
+        if (popover && !popover.contains(e.target) && !button.contains(e.target)) this.deleteBatchPopVisible = false
+      },
+
+      /* 纭鎵归噺鍒犻櫎瀵硅瘽 */
+      confirmDeleteBatchConversation() {
+        if (this.checkedConversationIdList.includes(this.activeHistoryIndex)) this.createNewConversation()
+        this.chatHistoryList = this.chatHistoryList.filter(item => !this.checkedConversationIdList.includes(item.id))
+        this.$message.success('鍒犻櫎鎴愬姛')
+        const timer = setTimeout(() => {
+          this.cancelDeleteBatchConversation()
+          clearTimeout(timer)
         })
       },
 
-      deleteConversation(record, index) {
+      /* 鍙栨秷鎵归噺鍒犻櫎浼氳瘽鍔熻兘 */
+      cancelDeleteBatchConversation() {
+        this.deleteBatchPopVisible = false
+        this.isDeletingBatch = false
+        this.checkedConversationIdList = []
+      },
+
+      /* 鍒囨崲鑷冲綋鍓嶇偣鍑讳細璇� */
+      switchToCurrentConversation(record, event = {}) {
+        if (event.target && event.target.type === 'checkbox') return //鐐瑰嚮澶氶�夋寜閽伩鍏嶄紶閫掔粰姝や簨浠�
+        if (record.inputVisible) return // 褰撴潯浼氳瘽姝e湪琚慨鏀规椂鍐嶆鐐瑰嚮鏈潯浼氳瘽鏃犲弽棣�
+        // 鍏抽棴鐐瑰嚮缂栬緫鎸夐挳鍚庣殑杈撳叆妗�
+        if (this.editingHistoryIndex !== null && this.editingHistoryIndex !== record.id) this.cancelEditConversationTitle(this.chatHistoryList.find(item => item.id === this.editingHistoryIndex))
+        // 鍏抽棴鎵�鏈夌‘璁ゅ垹闄ゅ脊绐�
+        if (this.deletingHistoryIndex !== null) this.cancelDeleteConversation(this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex))
+
+        this.activeHistoryIndex = record.id
+        this.currentConversation = this.chatHistoryList.find(item => item.id === record.id)
+        this.isAtNewConversation = false
+
+        // 鍒囨崲瀵硅瘽鏃舵洿鏀规彁闂緭鍏ユ鎻愮ず鏂囧瓧
+        if (record.messages.length > 0) this.textareaPlaceholder = 'Enter鍙戦�侊紝Shift+Enter鎹㈣'
+      },
+
+      /* 鐐瑰嚮缂栬緫浼氳瘽鏍囬鎸夐挳鏃惰Е鍙� */
+      editConversationTitle(record) {
+        // 浠呭紑鍚渶鍚庝竴娆$偣鍑荤紪杈戞寜閽悗鐨勮緭鍏ユ
+        if (this.editingHistoryIndex !== null && this.editingHistoryIndex !== record.id) this.cancelEditConversationTitle(this.chatHistoryList.find(item => item.id === this.editingHistoryIndex))
+        // 杩涘叆缂栬緫鍚庡叧闂墍鏈夌‘璁ゅ垹闄ゅ脊绐�
+        if (this.deletingHistoryIndex !== null) this.cancelDeleteConversation(this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex))
+
+        this.editingHistoryIndex = record.id
+        record.inputVisible = true
+        this.editedConversationTitle = record.title
+        this.$nextTick(() => document.getElementById('edit-input').focus())
+      },
+
+      /* 鐐瑰嚮鍗曚釜鍒犻櫎浼氳瘽鎸夐挳鏃惰Е鍙� */
+      deleteConversation(record) {
         // 鐐瑰嚮鍒犻櫎鎸夐挳鏃跺叧闂墍鏈夋鍦ㄧ紪杈戠殑杈撳叆妗�
         if (this.editingHistoryIndex !== null) {
           this.cancelEditConversationTitle(this.chatHistoryList.find(item => item.id === this.editingHistoryIndex))
           return
         }
         // 浠呭彲浣跨敤鏈�鍚庝竴娆$偣鍑诲垹闄ゆ寜閽殑鍔熻兘
-        if (this.deletingHistoryIndex !== null && this.deletingHistoryIndex !== record.id) this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex).deletePopVisible = false
-        record.deletePopVisible = true
+        if (this.deletingHistoryIndex !== null && this.deletingHistoryIndex !== record.id) this.cancelDeleteConversation(this.chatHistoryList.find(item => item.id === this.deletingHistoryIndex))
+
+        record.deletePopVisible = !record.deletePopVisible
         this.deletingHistoryIndex = record.id
       },
 
-      confirmEditConversationTitle(record) {
+      /* 纭缂栬緫浼氳瘽鏍囬 */
+      confirmEditConversationTitle(record, event) {
         record.title = this.editedConversationTitle
-        record.inputVisible = false
-        this.editingHistoryIndex = null
-        this.editedConversationTitle = ''
+        this.cancelEditConversationTitle(record, event)
       },
 
+      /* 纭鍒犻櫎浼氳瘽鏃惰Е鍙� */
       confirmDeleteConversation(record, index) {
         this.chatHistoryList = this.chatHistoryList.filter(item => item.id !== this.deletingHistoryIndex)
 
         if (this.chatHistoryList.length > 0) {
           // 鍒ゆ柇褰撳墠浼氳瘽鏄笉鏄鍒犻櫎鐨勪細璇�
-          // TODO 鐢变簬鐩墠娌℃湁鍞竴鏍囪瘑ID锛屾殏鏃朵娇鐢ㄥ巻鍙茶褰曢泦鍚堥暱搴︿綔涓篒D浣跨敤锛屽悗鏈熷繀椤昏皟鏁�
           if (this.activeHistoryIndex === record.id) {
             if (this.chatHistoryList[index]) {
               console.log('鍒犻櫎闈炴渶鍚庝竴鏉�')
@@ -239,19 +395,26 @@
           }
         } else {
           console.log('鍒犻櫎鍓嶅彧鏈変竴鏉�')
-          this.currentConversation = {}
           this.activeHistoryIndex = null
+          this.createNewConversation()
         }
+        record.deletePopVisible = false
         this.deletingHistoryIndex = null
         this.$message.success('鍒犻櫎鎴愬姛锛�')
       },
 
-      cancelEditConversationTitle(record) {
+      /* 鍙栨秷缂栬緫浼氳瘽鏍囬鏃惰Е鍙� */
+      cancelEditConversationTitle(record, event) {
+        // 澶卞幓鐒︾偣浜嬩欢鏃惰嫢鐐瑰嚮鐨勫厓绱犳槸纭缂栬緫鎸夐挳鍒欎笉杩涜澶卞幓鐒︾偣浜嬩欢锛岀洿鎺ヨ繘鍏ョ‘璁ょ紪杈戜簨浠�
+        if (event.relatedTarget && event.relatedTarget.className === 'anticon anticon-check') return
         record.inputVisible = false
         this.editingHistoryIndex = null
       },
 
-      cancelDeleteConversation(record) {
+      /* 鍙栨秷鍒犻櫎浼氳瘽鏃惰Е鍙� */
+      cancelDeleteConversation(record, event) {
+        // 澶卞幓鐒︾偣浜嬩欢鏃惰嫢鐐瑰嚮鐨勫厓绱犳槸纭鍒犻櫎鎸夐挳鍒欎笉杩涜澶卞幓鐒︾偣浜嬩欢锛岀洿鎺ヨ繘鍏ョ‘璁ゅ垹闄や簨浠�
+        if (event.relatedTarget && event.relatedTarget.id === 'delete-conversation-button') return
         record.deletePopVisible = false
         this.deletingHistoryIndex = null
       },
@@ -270,7 +433,6 @@
             this.$message.error('璇风瓑寰呮満鍣ㄤ汉鍥炲鍚庡啀鍙戦�佸摝~')
             return
           }
-
           if (!this.inputQuestion) {
             this.$message.error('浣犳病鏈夎緭鍏ュ唴瀹瑰摝')
             return
@@ -281,6 +443,14 @@
             content: this.inputQuestion
           }
           this.currentConversation.messages.push(newQuestion)
+
+          // 褰撴柊寤哄璇濇椂闇�鍏堟彁闂啀璁插璇濆姞鍏ュ埌鍘嗗彶璁板綍涓�
+          if (this.currentConversation.messages.length === 1) {
+            this.currentConversation.title = newQuestion.content.slice(0, 15)
+            this.chatHistoryList.unshift(this.currentConversation)
+            if (this.isDeletingBatch) this.singleHistoryCheckedChange()
+            this.switchToCurrentConversation(this.currentConversation)
+          }
 
           this.isResponding = true
           const response = {
@@ -302,14 +472,17 @@
 </script>
 
 <style scoped lang="less">
-  @background: rgba(255, 255, 255, .8);
+  @main-container-background: rgba(255, 255, 255, .8);
   @container-border-radius: 12px;
   @container-padding: 10px;
-  @single-history-border: 3px solid #ABC0CC;
-  @single-conversation-border: 1px solid #7295AB;
+  @single-history-edit-border: 3px solid #ABC0CC;
+  @single-history-hover-background: #f1f1f1;
+  @single-history-active-background: #e5ebed;
   @input-container-border: 3px solid #B8CAD5;
-  @conversation-content-container-box-shadow: 2px 2px 10px 0px #eeeeee;
-  @input-container-box-shadow: 2px 2px 10px 0px #7295AB;
+  @user-question-background: #e5ebed;
+  @assistant-answer-background: #F0F5F5;
+  @conversation-content-container-box-shadow: 2px 2px 10px 0px #ddd;
+  @input-container-box-shadow: 2px 2px 10px 0px #ABC0CC;
 
   .page-container {
     display: flex;
@@ -317,6 +490,7 @@
     align-items: center;
     font-size: 18px;
     height: 100%;
+    font-family: ali_r_main;
 
     .outer-container {
       width: 100%;
@@ -328,7 +502,7 @@
       .left-container {
         width: 20%;
         height: 100%;
-        background-color: @background;
+        background-color: @main-container-background;
         border-radius: @container-border-radius;
         padding: @container-padding;
         margin-right: 25px;
@@ -336,8 +510,127 @@
         flex-direction: column;
         justify-content: space-between;
 
+        .logo-container {
+          height: 80px;
+          img {
+            width: 100%;
+            height: 100%;
+          }
+        }
+
+        .manage-history-container {
+          margin: 20px 0 15px;
+          display: flex;
+
+          & > div {
+            border: 1px solid #d9d9d9;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            cursor: pointer;
+            color: #585258;
+            transition: box-shadow .2s ease-in-out;
+
+            &:hover {
+              box-shadow: @conversation-content-container-box-shadow;
+            }
+          }
+
+          .create-new-conversation {
+            margin-right: 10px;
+
+            &.create-history-container-active {
+              border: 1px solid transparent;
+              background-color: @single-history-active-background;
+
+              &:hover {
+                box-shadow: none;
+              }
+            }
+
+            &.fold-create-history-container {
+              flex: none;
+              width: 40px;
+              height: 40px;
+              border-radius: 50%;
+            }
+
+            &.expand-create-history-container {
+              flex: 1;
+              height: 100%;
+              border-radius: 20px;
+
+              .anticon {
+                margin-right: 10px;
+              }
+            }
+          }
+
+          .delete-batch-container {
+            &.expand-delete-batch-container {
+              flex: 1;
+              border-radius: 20px;
+              cursor: default;
+              box-shadow: none;
+
+              .expand-delete-batch-inner {
+                display: flex;
+                justify-content: space-evenly;
+                align-items: center;
+                height: 100%;
+                width: 100%;
+
+                & > div {
+                  display: flex;
+                  align-items: center;
+
+                  &.select-all-button {
+                    height: 100%;
+                  }
+
+                  &.able-delete-button {
+                    color: #D9737A;
+                  }
+
+                  &.disable-delete-button {
+                    color: #bbb;
+                    cursor: not-allowed !important;
+                  }
+
+                  &:not(.split-line) {
+                    cursor: pointer;
+                  }
+
+                  .anticon {
+                    margin-right: 10px;
+                  }
+
+                  &.split-line {
+                    width: 1px;
+                    background-color: #000;
+                    height: 50%;
+                  }
+                }
+              }
+            }
+
+            &.fold-delete-batch-container {
+              width: 40px;
+              height: 40px;
+              border-radius: 50%;
+            }
+
+            &.disable-expand {
+              cursor: not-allowed;
+              &:hover {
+                box-shadow: none;
+              }
+            }
+          }
+        }
+
         .chat-history-container {
-          height: 582px;
+          flex: 1;
           overflow: auto;
 
           & > div {
@@ -345,16 +638,26 @@
             border-radius: 10px;
             padding: 10px 20px;
             cursor: pointer;
+            display: flex;
+            align-items: center;
 
             & > span {
               display: flex;
               justify-content: space-between;
+              position: relative;
+              flex: 1;
 
               .conversation-title {
                 flex: 1;
-                white-space: nowrap;
-                text-overflow: ellipsis;
                 overflow: hidden;
+                white-space: nowrap;
+              }
+
+              .hover-icon-container {
+                // display锛歯one鐨勬秷澶辨柟寮忎細璁╃偣鍑诲垹闄ゅ脊鍑虹殑popover鍗$墖鏃犳硶鐐瑰嚮绌虹櫧澶勬秷澶�
+                opacity: 0;
+                position: absolute;
+                right: 0;
               }
 
               .icon-container {
@@ -365,12 +668,12 @@
                   margin-left: 5px;
 
                   &:hover {
-                    background-color: rgba(0, 0, 0, .2);
+                    background-color: rgba(0, 0, 0, .1);
                   }
                 }
               }
 
-              input {
+              #edit-input {
                 flex: 1;
                 height: 100%;
                 border: none;
@@ -386,12 +689,153 @@
             }
 
             &:hover {
-              background-color: #eee;
+              background-color: @single-history-hover-background;
+              .icon-container {
+                opacity: 1;
+                background-color: @single-history-hover-background;
+              }
             }
 
             &.single-history-active {
-              // border: @single-history-border;
-              background-color: #e5ebed;
+              background-color: @single-history-active-background;
+              &:hover {
+                .icon-container {
+                  background-color: @single-history-active-background;
+                }
+              }
+            }
+
+            &.input-visible-class {
+              background-color: @main-container-background;
+              border: @single-history-edit-border;
+              &:hover {
+                .icon-container {
+                  background-color: transparent;
+                }
+              }
+
+            }
+          }
+        }
+
+        /deep/ .ant-popover {
+          padding-bottom: 10px;
+
+          .ant-popover-arrow {
+            display: none;
+          }
+
+          .ant-popover-inner {
+            border-radius: @container-border-radius;
+            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+
+            .ant-popover-inner-content {
+              padding: 12px 16px;
+
+              .popover-content {
+                font-size: 16px;
+                font-weight: bold;
+                display: flex;
+                flex-direction: column;
+                align-items: center;
+                font-family: ali_r_main;
+
+                & > div {
+                  width: 100%;
+                  display: flex;
+                  justify-content: space-evenly;
+                  margin-top: 10px;
+
+                  button {
+                    border: none;
+                    padding: 5px 30px;
+                    border-radius: 20px;
+                    font-weight: bold;
+                    cursor: pointer;
+                    outline: none;
+                  }
+
+                  .cancel-delete-button {
+                    background-color: #D9D9D9;
+                  }
+
+                  #delete-conversation-button, #confirm-delete-batch-button {
+                    background-color: #7295AB;
+                    color: #fff;
+                    font-weight: normal;
+                  }
+                }
+              }
+            }
+          }
+        }
+
+        .checkbox-custom {
+          height: 100%;
+          position: relative;
+          display: flex;
+          justify-content: flex-end;
+          align-items: center;
+          cursor: pointer;
+          -webkit-user-select: none;
+          -moz-user-select: none;
+          -ms-user-select: none;
+          user-select: none;
+
+          input {
+            position: absolute;
+            opacity: 0;
+            cursor: pointer;
+            height: 0;
+            width: 0;
+
+            &:checked ~ .check-mark {
+              background-color: #7295AB;
+              border: none;
+
+              &:after {
+                display: block;
+              }
+            }
+
+            &:indeterminate ~ .check-mark {
+              background-color: #fff;
+              border: 1px solid #818181;
+
+              &:after {
+                display: block;
+                width: 10px;
+                height: 3px;
+                background: #818181;
+                border-radius: 12px;
+              }
+            }
+          }
+
+          .check-mark {
+            position: relative;
+            height: 16px;
+            width: 16px;
+            background-color: transparent;
+            border: 1px solid #818181;
+            border-radius: 50%;
+            margin-right: 10px;
+
+            &:after {
+              content: "";
+              position: absolute;
+              display: none;
+              top: 50%;
+              left: 50%;
+              width: 8px;
+              height: 8px;
+              border-radius: 50%;
+              background: #fff;
+              transform: translate(-50%, -50%);
+            }
+
+            &:hover {
+              border: 3px solid #7295AB;
             }
           }
         }
@@ -407,7 +851,7 @@
 
         .conversation-container {
           height: 570px;
-          background-color: @background;
+          background-color: @main-container-background;
           padding: @container-padding*2;
           border-radius: @container-border-radius;
           margin-bottom: 25px;
@@ -422,10 +866,17 @@
 
               &.user-question {
                 align-items: flex-end;
+                .content {
+                  background-color: @user-question-background;
+                }
               }
 
               &.assistant-answer {
                 align-items: flex-start;
+
+                .content {
+                  background-color: @assistant-answer-background;
+                }
               }
 
               .avatar {
@@ -443,7 +894,6 @@
                 box-shadow: @conversation-content-container-box-shadow;
                 border-radius: @container-border-radius;
                 padding: @container-padding;
-                background-color: #e5ebed;
               }
             }
 
@@ -455,7 +905,7 @@
 
         .input-container {
           flex: 1;
-          background-color: @background;
+          background-color: @main-container-background;
           border-radius: @container-border-radius;
           padding: @container-padding*2;
           border: 3px solid transparent;
@@ -495,6 +945,5 @@
         }
       }
     }
-
   }
 </style>
\ No newline at end of file

--
Gitblit v1.9.3