From a0dd2bd1be4e97a93443a48b86c719930d0a268a Mon Sep 17 00:00:00 2001
From: yaowanxin <3588231647@qq.com>
Date: 星期二, 12 八月 2025 16:13:44 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_ai' into ywx
---
src/views/chatHome/chatHomeIndex/MobileChat.vue | 461 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 461 insertions(+), 0 deletions(-)
diff --git a/src/views/chatHome/chatHomeIndex/MobileChat.vue b/src/views/chatHome/chatHomeIndex/MobileChat.vue
new file mode 100644
index 0000000..f8bc625
--- /dev/null
+++ b/src/views/chatHome/chatHomeIndex/MobileChat.vue
@@ -0,0 +1,461 @@
+<template>
+ <div class="mobile-chat-wrapper" style="height: 91vh;">
+ <div class="chat-history">
+ <div class="chat-content" ref="chatContent">
+ <div class="chat-wrapper" v-for="(item, index) in chatList" :key="index">
+ <div class="chat-friend" v-if="item.uid !== '1001'">
+ <div class="info-time">
+ <img :src="item.headImg" alt="" />
+ <span>{{ item.name }}</span>
+ <span>{{ item.time }}</span>
+ </div>
+ <div class="chat-text" v-if="item.chatType == 0">
+ <template v-if="isSend && index === chatList.length - 1">
+ <span class="flash_cursor"></span>
+ </template>
+ <template v-else>
+ <pre>{{ item.msg }}</pre>
+ </template>
+ </div>
+ <div class="chat-img" v-if="item.chatType == 1">
+ <img :src="item.msg" alt="琛ㄦ儏" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" />
+ <el-image :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image>
+ </div>
+ <div class="chat-img" v-if="item.chatType == 2">
+ <div class="word-file">
+ <FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard>
+ </div>
+ </div>
+ </div>
+ <div class="chat-me" v-else>
+ <div class="info-time">
+ <span>{{ item.name }}</span>
+ <span>{{ item.time }}</span>
+ <img :src="item.headImg" alt="" />
+ </div>
+ <div class="chat-text" v-if="item.chatType == 0">
+ {{ item.msg }}
+ </div>
+ <div class="chat-img" v-if="item.chatType == 1">
+ <img :src="item.msg" alt="琛ㄦ儏" v-if="item.extend.imgType == 1" style="width: 100px; height: 100px" />
+ <el-image style="max-width: 300px; border-radius: 10px" :src="item.msg" :preview-src-list="srcImgList" v-else> </el-image>
+ </div>
+ <div class="chat-img" v-if="item.chatType == 2">
+ <div class="word-file">
+ <FileCard :fileType="item.extend.fileType" :file="item.msg"></FileCard>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="chat-input-wrapper">
+ <div style="display: flex; align-items: center">
+ <input v-model="inputMsg" @change="sendText" :disabled="loading" class="input-text" autofocus placeholder="缁欏皬鏅哄彂閫佹秷鎭�" />
+ <img class="send-icon" src="@/assets/img/emoji/rocket.png" alt="" @click="sendText" />
+
+ </div>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, nextTick,onActivated } from 'vue'
+import { useRoute } from 'vue-router'
+import { animation } from '@/utils/util'
+import chatGPTHeadImg from '@/assets/img/head_portrait1.png'
+import headPortrait from '@/assets/img/head_portrait.jpg'
+import FileCard from '@/components/FileCard.vue'
+import { ElMessage } from "element-plus"
+import {checking} from './ai-wd.js'
+
+// 瀹氫箟鍝嶅簲寮忔暟鎹�
+const route = useRoute()
+const chatContent = ref(null)
+const ws = ref(null)
+const chatList = ref([
+ {
+ headImg: chatGPTHeadImg,
+ name: '灏忔櫤',
+ time: new Date().toLocaleTimeString(),
+ msg: ' 灏忔櫤涓烘偍鏈嶅姟',
+ chatType: 0,
+ uid: '1002'
+ }
+])
+const inputMsg = ref('')
+const isSend = ref(false)
+const fileList = ref([])
+const isProcessing = ref(false)
+const loading = ref(true)
+const srcImgList = ref([])
+
+// 鍒犻櫎鍥剧墖
+const deleteImg = (index) => {
+ if (index >= 0 && index < fileList.value.length) {
+ fileList.value.splice(index, 1)
+ }
+}
+
+// WebSocket娑堟伅鎺ユ敹
+const websocketonmessage = (e) => {
+ const redata = JSON.parse(e.data)
+ //鏁版嵁鎺ユ敹
+ let chatGPT = {
+ headImg: headPortrait,
+ name: 'DeepSeek',
+ time: new Date().toLocaleTimeString(),
+ msg: redata[0].text,
+ chatType: 0, //淇℃伅绫诲瀷锛�0鏂囧瓧锛�1鍥剧墖
+ uid: '1002' //uid
+ }
+ sendMsg(chatGPT)
+ isSend.value = false
+}
+
+// WebSocket鍙戦�佹秷鎭�
+const websocketsend = (Data) => {
+ console.log("鍗冲皢鍙戦�佹秷鎭�", Data)
+ if (ws.value && ws.value.readyState === WebSocket.OPEN) {
+ console.log("鍙戦�佹秷鎭�", ws.value)
+ console.log("鍙戦�佹秷鎭�", Data)
+ let fileUrls = fileList.value.map(item => item.file.fileUrl)
+ //鏁版嵁鍙戦��
+ ws.value.send(Data + ":" + fileUrls.join(","))
+ fileList.value = []
+ inputMsg.value = ''
+ }
+}
+
+// 鍙戦�佹枃鏈秷鎭�
+const sendText = () => {
+ if (inputMsg.value) {
+ let chatMsg = {
+ headImg: headPortrait,
+ name: '鍗ч緳',
+ time: new Date().toLocaleTimeString(),
+ msg: inputMsg.value,
+ chatType: 0, //淇℃伅绫诲瀷锛�0鏂囧瓧锛�1鍥剧墖
+ uid: '1001' //uid
+ }
+ chatList.value.push(chatMsg)
+ let chatGPT = {
+ headImg: headPortrait,
+ name: '灏忔櫤',
+ time: new Date().toLocaleTimeString(),
+ msg: "",
+ chatType: 0, //淇℃伅绫诲瀷锛�0鏂囧瓧锛�1鍥剧墖
+ uid: '1002' //uid
+ }
+ chatList.value.push(chatGPT) // 灏嗘帴鏀跺埌鐨勬秷鎭瓨鍌ㄥ埌 messages 鏁扮粍
+ simulateStreamingOutput(chatGPT, inputMsg.value)
+ inputMsg.value = ''
+
+ } else {
+ ElMessage({
+ message: '娑堟伅涓嶈兘涓虹┖鍝',
+ type: 'warning'
+ })
+ }
+}
+
+// 鍙戦�佷俊鎭�
+const sendMsg = (msgList) => {
+ chatList.value.push(msgList)
+ scrollBottom()
+}
+
+// 鑾峰彇绐楀彛楂樺害骞舵粴鍔ㄨ嚦鏈�搴曞眰
+const scrollBottom = () => {
+ nextTick(() => {
+ const scrollDom = chatContent.value
+ animation(scrollDom, scrollDom.scrollHeight - scrollDom.offsetHeight)
+ })
+}
+
+// 缁勪欢鎸傝浇鏃舵墽琛�
+onActivated(() => {
+ chatList.value = []
+ chatList.value.push({
+ headImg: chatGPTHeadImg,
+ name: '灏忔櫤',
+ time: new Date().toLocaleTimeString(),
+ msg: '灏忔櫤涓烘偍鏈嶅姟',
+ chatType: 0,
+ uid: '1002'
+ })
+ chatList.value.push({
+ headImg: chatGPTHeadImg,
+ name: '鍗ч緳',
+ time: new Date().toLocaleTimeString(),
+ msg: route.query.keyWord,
+ chatType: 0,
+ uid: '1001'
+ })
+ // 娣诲姞涓�涓┖鐨勫洖澶嶆秷鎭崰浣�
+ const replyMsg = {
+ headImg: chatGPTHeadImg,
+ name: '灏忔櫤',
+ time: new Date().toLocaleTimeString(),
+ msg: '',
+ chatType: 0,
+ uid: '1002'
+ }
+ chatList.value.push(replyMsg)
+ scrollBottom()
+
+ // 濡傛灉鏈夋煡璇㈠叧閿瓧锛屽垯妯℃嫙娴佸紡杈撳嚭
+ if (route.query.keyWord) {
+ simulateStreamingOutput(replyMsg, route.query.keyWord)
+ }
+})
+// 妯℃嫙娴佸紡杈撳嚭
+const simulateStreamingOutput = async (msgObj, keyWord) => {
+ loading.value = true
+ // 鐢熸垚0.8-1.3绉掍箣闂寸殑闅忔満寤惰繜
+ const delay = Math.random() * 500 + 800
+
+ // 妯℃嫙鍥炲鍐呭锛堝疄闄呭簲鐢ㄤ腑搴斾粠API鑾峰彇锛�
+ const responseText = `鍏充簬"${keyWord}"鐨勯棶棰橈紝鎴戞潵涓烘偍瑙g瓟锛歕n` + checking(keyWord)
+
+ isSend.value = true
+
+ let index = 0
+ setTimeout(() => {
+ const interval = setInterval(() => {
+ isSend.value = true
+ if (index < responseText.length) {
+ msgObj.msg += responseText.charAt(index)
+ index++
+ isSend.value = false
+ scrollBottom()
+ } else {
+ clearInterval(interval)
+ isSend.value = false
+ loading.value = false
+ }
+ }, 50) // 姣�50ms杈撳嚭涓�涓瓧绗︼紝妯℃嫙娴佸紡鏁堟灉
+ }, delay)
+
+}
+</script>
+
+<style lang="scss" scoped>
+.mobile-chat-wrapper {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ height: 91vh;
+ position: relative;
+ background-color: white;
+
+ .chat-history {
+ flex: 1 1 0;
+ overflow-y: auto;
+ }
+
+ .chat-input-wrapper {
+ padding: 8px 16px 8px 8px;
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ .file-tt{
+ flex-direction: column;
+ width: 200px;
+ display: flex;
+ padding: 5px;
+ border-radius: 5px;
+ margin-right: 5px;
+ background: #cacaca;
+ .file-item{
+ width: 200px;
+ overflow:hidden;
+ word-wrap: break-word;
+ text-overflow:ellipsis;
+ display:-webkit-box;
+ -webkit-box-orient:vertical;
+ -webkit-line-clamp:2;
+ }
+ }
+
+ .send-icon {
+ height: 40px;
+ margin-left: 16px;
+ }
+ .input-text{
+ font-size: 18px;
+ width: 100%;
+ border-radius: 20px;
+ height: 80px;
+ padding-left: 10px;
+ //padding-top: 10px;
+ border: none;
+ color: black; /* 淇敼鏂囨湰棰滆壊涓虹櫧鑹� */
+ background-color: #f5f4f4; /* 淇敼鑳屾櫙棰滆壊涓烘繁鐏拌壊 */
+ }
+ }
+
+ .chat-content {
+ width: 100%;
+ height: 80%;
+ overflow-y: scroll;
+ padding: 20px;
+ box-sizing: border-box;
+
+ &::-webkit-scrollbar {
+ width: 0;
+ /* Safari,Chrome 闅愯棌婊氬姩鏉� */
+ height: 0;
+ /* Safari,Chrome 闅愯棌婊氬姩鏉� */
+ display: none;
+ /* 绉诲姩绔�乸ad 涓奡afari锛孋hrome锛岄殣钘忔粴鍔ㄦ潯 */
+ }
+
+ .chat-wrapper {
+ position: relative;
+ word-break: break-all;
+
+ .chat-friend {
+ width: 100%;
+ float: left;
+ margin-bottom: 20px;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+
+ .chat-text {
+ max-width: 90%;
+ padding: 20px;
+ border-radius: 20px 20px 20px 5px;
+ background-color: rgb(245, 248, 248);
+ color: black;
+
+ &:hover {
+ background-color: rgb(232, 232, 232);
+ }
+
+ pre {
+ white-space: break-spaces;
+ }
+ }
+
+ .chat-img {
+ img {
+ width: 100px;
+ height: 100px;
+ }
+ }
+
+ .info-time {
+ margin: 10px 0;
+ color: black;
+ font-size: 14px;
+
+ img {
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ vertical-align: middle;
+ margin-right: 10px;
+ }
+
+ span:last-child {
+ color: rgb(101, 104, 115);
+ margin-left: 10px;
+ vertical-align: middle;
+ }
+ }
+ }
+
+ .chat-me {
+ width: 100%;
+ float: right;
+ margin-bottom: 20px;
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+ align-items: flex-end;
+
+ .chat-text {
+ float: right;
+ max-width: 90%;
+ padding: 20px;
+ border-radius: 20px 20px 5px 20px;
+ background-color: rgb(29, 144, 245);
+ color: #fff;
+
+ &:hover {
+ background-color: rgb(26, 129, 219);
+ }
+ }
+
+ .chat-img {
+ img {
+ max-width: 300px;
+ max-height: 200px;
+ border-radius: 10px;
+ }
+ }
+
+ .info-time {
+ margin: 10px 0;
+ color: black;
+ font-size: 14px;
+ display: flex;
+ justify-content: flex-end;
+
+ img {
+ width: 30px;
+ height: 30px;
+ border-radius: 50%;
+ vertical-align: middle;
+ margin-left: 10px;
+ }
+
+ span {
+ line-height: 30px;
+ }
+
+ span:first-child {
+ color: rgb(101, 104, 115);
+ margin-right: 10px;
+ vertical-align: middle;
+ }
+ }
+ }
+ }
+ }
+ .flash_cursor {
+ width: 20px;
+ height: 30px;
+ display: inline-block;
+ background: #d6e3f5;
+ opacity: 1;
+ animation: glow 800ms ease-out infinite alternate;
+ }
+ @keyframes glow {
+ 0% {
+ opacity: 1;
+ }
+
+ 25% {
+ opacity: 0.5;
+ }
+
+ 50% {
+ opacity: 0;
+ }
+
+ 75% {
+ opacity: 0.5;
+ }
+
+ 100% {
+ opacity: 1;
+ }
+ }
+}
+</style>
--
Gitblit v1.9.3