From 768eb63fc69d413055821c7963168f2e2677412c Mon Sep 17 00:00:00 2001 From: QYF-GitLab1 <1940665526@qq.com> Date: 星期五, 11 四月 2025 15:01:49 +0800 Subject: [PATCH] 1 --- src/views/Start.vue | 557 +++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 413 insertions(+), 144 deletions(-) diff --git a/src/views/Start.vue b/src/views/Start.vue index 33ba4d7..ec86788 100644 --- a/src/views/Start.vue +++ b/src/views/Start.vue @@ -1,6 +1,6 @@ <template> <div class="chat-box"> - <div class="chat-box-content"> + <div class="chat-box-content" ref="messagesContainer"> <div class="chat-date">03/15 13:10:00</div> <div class="chat-back-info"> <div class="back-avator"> @@ -46,37 +46,63 @@ <span>鎹竴鎹�</span> </div> </div> - <div class="chat-footer"> - <div class="icon-list"> - <img src="../assets/images/liebiao1.png" alt="" /> - <img src="../assets/images/tianjia2.png" alt="" /> + <div + v-for="(item, index) in message" + :key="index" + :class="['message', item.type === 'user' ? 'user-message' : 'assistant-message']" + > + <el-avatar + style="min-width: 40px" + :size="screenWidth > 375 ? 60 : 40" + v-if="item.type != 'user'" + :src="assistantAvatar" + /> + <div :class="['message-content', item.type === 'user' ? 'user-message-content' : '']"> + <div class="message-text" v-html="item.content"></div> + <div class="message-footer" v-if="item.type != 'user'"> + <span class="message-time">{{ item.time }}</span> + </div> </div> - <div class="chat-text"> - <el-input - type="textarea" - :autosize="{ minRows: 2, maxRows: 10 }" - placeholder="璇疯緭鍏ユ偍鐨勯棶棰�" - v-model="inputValue" - /> - </div> - <div class="select"> - <div class="select-left"> - <div class="select-item"> - <img src="../assets/images/sikao.png" alt="" /> - <span>娣卞害鎬濊�冿紙R1)</span> - </div> - <div class="select-item"> - <img src="../assets/images/lianwang.png" alt="" /> - <span>鑱旂綉鎼滅储</span> + <div v-if="loading" class="message assistant-message loading-message"> + <el-avatar :size="40" :src="assistantAvatar" /> + <div :class="['message-content', item.type === 'user' ? 'user-message-content' : '']"> + <div class="message-text"> + <span class="dot-loading">鎬濊�冧腑</span> </div> </div> - <div class="select-right"> - <div class="select-item"> - <img src="../assets/images/fujian1.png" alt="" /> - </div> - <div class="select-item"> - <img src="../assets/images/shangchuan2.png" alt="" /> - </div> + </div> + </div> + </div> + <div class="chat-footer"> + <div class="icon-list"> + <img src="../assets/images/liebiao1.png" alt="" /> + <img src="../assets/images/tianjia2.png" alt="" /> + </div> + <div class="chat-text"> + <el-input + type="textarea" + :autosize="{ minRows: 2, maxRows: 10 }" + placeholder="璇疯緭鍏ユ偍鐨勯棶棰�" + v-model="inputValue" + /> + </div> + <div class="select"> + <div class="select-left"> + <div class="select-item"> + <img src="../assets/images/sikao.png" alt="" /> + <span>娣卞害鎬濊�冿紙R1)</span> + </div> + <div class="select-item"> + <img src="../assets/images/lianwang.png" alt="" /> + <span>鑱旂綉鎼滅储</span> + </div> + </div> + <div class="select-right"> + <div class="select-item"> + <img src="../assets/images/fujian1.png" alt="" /> + </div> + <div class="select-item"> + <img @click="sendMsg()" src="../assets/images/shangchuan2.png" alt="" /> </div> </div> </div> @@ -84,21 +110,97 @@ </div> </template> <script lang="ts" setup> -import { ref } from 'vue' +import { nextTick, onMounted, ref, watch } from 'vue' +import defaultImg from '../assets/images/image2.png' const inputValue = ref('') +const message = ref<any>([]) +const loading = ref(false) +const autoScroll = ref(true) +const messagesContainer = ref<HTMLElement | null>(null) +const assistantAvatar = defaultImg +const screenWidth = ref(window.innerWidth) + +const scrollToBottom = async () => { + if (!autoScroll.value) return + await nextTick() + if (messagesContainer.value) { + messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight + } +} +const formatMessage = (content: string) => { + return content.replace(/\n/g, '<br>') +} + +interface ChatMessage { + content: string + type: 'user' | 'assistant' + time: string +} +const sendMsg = async () => { + if (!inputValue.value.trim() || loading.value) return + + const userMessage: ChatMessage = { + content: inputValue.value, + type: 'user', + time: new Date().toLocaleTimeString(), + } + message.value.push(userMessage) + + const messageToSend = inputValue.value + inputValue.value = '' + loading.value = true + + try { + setTimeout(() => { + const assistantMessage: ChatMessage = { + content: + '浣犲ソ,鍗佸ぇ鏉�涓ぇ鍌荤摐澶у帵鎻愰珮鍏氬憳婀垮湴鍏洯澶у垰鍒氭拻鍙嶅鍝堟寕鍙疯垂鍝�浼ょ殑姝岃繑鍥炵粰娉曟拻鏃︾瓑鍝堢殑鍦版柟鍙戠敓鑿插ぇ浣块鐨勬拻', + type: 'assistant', + time: new Date().toLocaleTimeString(), + } + message.value.push(assistantMessage) + loading.value = false + console.log(message, 'dasdas') + }, 1000) + // 淇濆瓨娑堟伅鍒版湰鍦板瓨鍌� + localStorage.setItem('chatMessages', JSON.stringify(message.value)) + } catch (error) { + console.error('鍙戦�佹秷鎭け璐�', error) + } finally { + loading.value = false + } +} + +// 鐩戝惉娑堟伅鍙樺寲锛岃嚜鍔ㄦ粴鍔� +watch(message.value, () => { + scrollToBottom() +}) + +// 浠庢湰鍦板瓨鍌ㄥ姞杞芥秷鎭� +onMounted(() => { + const savedMessages = localStorage.getItem('chatMessages') + if (savedMessages) { + message.value = JSON.parse(savedMessages) + } + scrollToBottom() + screenWidth.value = window.innerWidth +}) </script> <style lang="less" scoped> @media screen and (max-width: 750px) { .chat-box { width: 100%; - height: auto; + height: 100%; background-image: url('@/assets/images/beijing2.png'); background-position: center; background-size: cover; + .chat-box-content { width: 100%; + height: calc(100vh - 170px); display: flex; flex-direction: column; + overflow: auto; justify-content: flex-start; align-items: flex-start; @@ -139,20 +241,22 @@ } .base-book-box { - width: 300px; - padding: 20px; + width: 80%; + padding: 15px; box-sizing: border-box; background-color: #fff; border-radius: 20px; + font-size: 14px; } } .back-item { - width: 300px; + max-width: 80%; background: #ffffff; border-radius: 20px; margin-left: 50px; margin-bottom: 20px; + font-size: 14px; .back-item-title { width: 80%; @@ -170,6 +274,7 @@ ul { padding: 0 25px; + li { list-style: none; margin: 10px 0 10px 0; @@ -191,85 +296,143 @@ } } } + } + .chat-footer { + width: 90%; + margin: auto; + background-color: #fff; + border-radius: 20px; + padding: 10px; + box-sizing: border-box; + margin-bottom: 20px; - .chat-footer { - width: 300px; - background-color: #fff; - border-radius: 20px; - padding: 20px; - box-sizing: border-box; - margin-left: 50px; - margin-bottom: 20px; + .icon-list img { + margin-right: 10px; + cursor: pointer; + } - .icon-list img { - margin-right: 10px; - cursor: pointer; + ::v-deep(.chat-text) { + margin-bottom: 10px; + + .el-textarea__inner { + border: none !important; + outline: none !important; + box-shadow: none !important; + background-color: transparent !important; + resize: none !important; } + } - ::v-deep(.chat-text) { - margin-bottom: 10px; - .el-textarea__inner { - border: none !important; - outline: none !important; - box-shadow: none !important; - background-color: transparent !important; - resize: none !important; - } - } + .select { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; - .select { - width: 100%; + .select-left, + .select-right { display: flex; align-items: center; - justify-content: space-between; + justify-content: flex-start; - .select-left, - .select-right { + .select-item { display: flex; align-items: center; - justify-content: flex-start; + box-sizing: border-box; + border: 1px solid #e9d8bf; + border-radius: 15px; + font-size: 12px; + font-family: + Microsoft YaHei, + Microsoft YaHei-Regular; + font-weight: 400; + color: #e1c49a; - .select-item { - display: flex; - align-items: center; - box-sizing: border-box; - border: 1px solid #e9d8bf; - border-radius: 15px; - font-size: 12px; - font-family: - Microsoft YaHei, - Microsoft YaHei-Regular; - font-weight: 400; - color: #e1c49a; - - img { - margin-right: 5px; - cursor: pointer; - } + img { + margin-right: 5px; + cursor: pointer; } } + } - .select-left { - .select-item { - min-width: 70px; - padding: 5px 8px; - } + .select-left { + .select-item { + min-width: 70px; + padding: 5px 8px; + margin-left: 2px; } + } - .select-right { - display: flex; - align-items: center; - justify-content: flex-end; + .select-right { + display: flex; + align-items: center; + justify-content: flex-end; - .select-item { - border: 0; - } + .select-item { + border: 0; + margin-left: 2px; } } } } + .message { + display: flex; + margin-bottom: 24px; + align-items: flex-start; + animation: slideIn 0.3s ease; + animation-fill-mode: forwards; + max-width: 85%; + border-radius: 12px; + // box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + padding: 16px; + padding-left: 3px; + } + + .message-content { + background: #fff; + margin-left: 10px; + border-radius: 20px; + min-width: 200px; + padding: 5px; + } + + .message-text { + padding: 12px 16px; + border-radius: 12px; + word-wrap: break-word; + line-height: 1.6; + font-size: 0.95rem; + transition: all 0.3s ease; + white-space: pre-wrap; + color: #333; + } + + .user-message { + flex-direction: row-reverse; + margin-left: auto; + } + + .user-message .message-text { + color: #8b6e47; + } + + .message-footer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 8px; + padding: 0 4px; + color: #999; + } + + .message-time { + font-size: 0.85rem; + color: #999; + margin-left: 10px; + } } } + @media screen and (min-width: 750px) { .chat-box { width: 100%; @@ -279,14 +442,48 @@ background-position: center; background-repeat: no-repeat; display: flex; - justify-content: center; + flex-direction: column; + justify-content: flex-start; align-items: center; + padding-bottom: 10px; + .chat-box-content { width: 1200px; + height: calc(100vh - 180px); display: flex; flex-direction: column; justify-content: flex-start; + overflow: auto; align-items: flex-start; + + .chat-send { + width: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: flex-end; + margin-bottom: 20px; + + .chat-send-info { + width: 263px; + height: 40px; + background: #af8b56; + border-radius: 20px; + line-height: 40px; + padding: 0 20px; + color: #fff; + } + + .chat-message { + width: 263px; + height: 40px; + background: #fff; + border-radius: 20px; + line-height: 40px; + padding: 0 20px; + color: #000; + } + } .chat-date { width: 100%; @@ -375,79 +572,151 @@ } } } + } - .chat-footer { - width: 800px; - height: 170px; - background-color: #fff; - border-radius: 20px; - padding: 20px; - box-sizing: border-box; - margin-left: 103px; + .chat-box-content::-webkit-scrollbar { + width: 1px; + } - .icon-list img { - margin-right: 10px; - cursor: pointer; + /* 闅愯棌姘村钩婊氬姩鏉� */ + .chat-box-content::-webkit-scrollbar { + height: 0; + } + + .chat-footer { + width: 1200px; + height: 170px; + background-color: #fff; + border-radius: 20px; + padding: 20px; + box-sizing: border-box; + + .icon-list img { + margin-right: 10px; + cursor: pointer; + } + + ::v-deep(.chat-text) { + margin-bottom: 10px; + + .el-textarea__inner { + border: none !important; + outline: none !important; + box-shadow: none !important; + background-color: transparent !important; + resize: none !important; } + } - ::v-deep(.chat-text) { - margin-bottom: 10px; - .el-textarea__inner { - border: none !important; - outline: none !important; - box-shadow: none !important; - background-color: transparent !important; - resize: none !important; - } - } + .select { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; - .select { - width: 100%; + .select-left, + .select-right { + flex: 1; display: flex; align-items: center; - justify-content: space-between; + justify-content: flex-start; - .select-left, - .select-right { - flex: 1; + .select-item { display: flex; align-items: center; - justify-content: flex-start; + padding: 2px 10px; + box-sizing: border-box; + border: 1px solid #e9d8bf; + border-radius: 15px; + margin-right: 10px; + font-size: 14px; + font-family: + Microsoft YaHei, + Microsoft YaHei-Regular; + font-weight: 400; + color: #e1c49a; - .select-item { - display: flex; - align-items: center; - padding: 2px 10px; - box-sizing: border-box; - border: 1px solid #e9d8bf; - border-radius: 15px; + img { margin-right: 10px; - font-size: 14px; - font-family: - Microsoft YaHei, - Microsoft YaHei-Regular; - font-weight: 400; - color: #e1c49a; - - img { - margin-right: 10px; - cursor: pointer; - } + cursor: pointer; } } + } - .select-right { - display: flex; - align-items: center; - justify-content: flex-end; + .select-right { + display: flex; + align-items: center; + justify-content: flex-end; - .select-item { - border: 0; - } + .select-item { + border: 0; } } } } + + .message { + display: flex; + margin-bottom: 24px; + align-items: flex-start; + animation: slideIn 0.3s ease; + animation-fill-mode: forwards; + max-width: 95%; + border-radius: 12px; + // box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + padding: 16px; + } + + .message-content { + background: #fff; + margin-left: 20px; + border-radius: 20px; + min-width: 200px; + padding: 5px; + } + + .message-text { + padding: 12px 16px; + border-radius: 12px; + word-wrap: break-word; + line-height: 1.6; + font-size: 0.95rem; + transition: all 0.3s ease; + white-space: pre-wrap; + color: #333; + } + + .user-message { + flex-direction: row-reverse; + margin-left: auto; + } + + .user-message .message-text { + color: #8b6e47; + } + + .message-footer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 8px; + padding: 0 4px; + color: #999; + } + + .message-time { + font-size: 0.85rem; + color: #999; + margin-left: 10px; + } + } +} + +.user-message-content { + background: #af8b56 !important; + .message-text { + color: #fff !important; + padding: 5px 10px; } } </style> -- Gitblit v1.9.1