From fd0e3fd03817d6610c52b09fe27cccf0d3f96438 Mon Sep 17 00:00:00 2001 From: yaowanxin <3588231647@qq.com> Date: 星期二, 12 八月 2025 16:26:11 +0800 Subject: [PATCH] Merge branch 'dev_ai' of http://114.132.189.42:9002/r/product-inventory-management 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..5b06e76 --- /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() + loading.value = false + // 濡傛灉鏈夋煡璇㈠叧閿瓧锛屽垯妯℃嫙娴佸紡杈撳嚭 + 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