From 9860e221460a0a4ac1903dad2c97160d0eed0e63 Mon Sep 17 00:00:00 2001 From: long <515897141@qq.com> Date: 星期五, 03 三月 2023 10:59:42 +0800 Subject: [PATCH] 初始化 --- src/components/ChatList/chat_list.vue | 315 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 315 insertions(+), 0 deletions(-) diff --git a/src/components/ChatList/chat_list.vue b/src/components/ChatList/chat_list.vue new file mode 100644 index 0000000..c00d120 --- /dev/null +++ b/src/components/ChatList/chat_list.vue @@ -0,0 +1,315 @@ +<template> + <div> + <ul ref="chatList" class="chat-list" :style="`height:${height};`"> + + <li v-for="(item, index) in list" :key="index"> + <!-- 鏃堕棿 --> + <div v-if="item.time_tx" class="flex"><div class="chat-time">{{ item.time_tx }}</div></div> + + <!-- 鑱婂ぉ涓讳綋 鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌 --> + <!-- 閫氬父涓讳綋 鏈夌敤鎴蜂俊鎭� --> + <div class="chat-item" :class="{'me-item': getDirection(item.fromUser)=='right'}"> + <img :src="item.avatar" alt="" class="avatar" fit="cover"> + <div class="info"> + <!-- ({{ item.msgtype }}) --> + <div class="name">{{ item.name }}</div> + + <!-- 娑堟伅鍐呭 鈫撯啌鈫撯啌鈫撯啌鈫撯啌鈫撯啌 --> + <!-- 鏂囨湰 --> + <textPop v-if="item.msgtype === 'text'" :data="item.content" :direction="getDirection(item.fromUser)" /> + <!-- 鍥剧墖 --> + <imagePop v-if="item.msgtype === 'image'" :data="item" :direction="getDirection(item.fromUser)" /> + <!-- 娑堟伅鍐呭 鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈 --> + </div> + </div> + <!-- 鑱婂ぉ涓讳綋 鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈鈫戔啈 --> + </li> + + <div v-if="loading" class="text-center"> + <div class="ball-rotate"><div /></div> + </div> + </ul> + + <div class="handle-wrap flex flex-ver"> + <input v-model="myTalk" type="text" class="input flex-1" maxlength="100" @keyup.enter="handleSend"> + <div class="send-btn" @click="handleSend">鍙戦��</div> + </div> + + <!-- audioFileUrl --> + <audio ref="refAudio" src=""> + 鎮ㄧ殑娴忚鍣ㄤ笉鏀寔 audio 鏍囩銆� + </audio> + </div> +</template> + +<script> +// const listMockData = require('./chat_list_mockData') +const chatFn = require('@/utils/chat/chat.js') +import imagePop from './msg/imagePop.vue' +import textPop from './msg/textPop.vue' +import config from '../../config/index' +export default { + name: 'ChatList', + components: { textPop, imagePop }, + mixins: [], + props: { + // 楂樺害 + height: { + type: String, + default: '100vh' + } + }, + data() { + return { + userId: '', + myTalk: '', + + // 鍒楄〃鏁版嵁 + loading: false, + list: [] + } + }, + mounted() { + this.init() + }, + methods: { + init() { + this.userId = this.getQueryString('userId') + console.log('this.userId', this.userId) + if (!this.userId) window.appToast('缂哄皯userID锛岃閲嶆柊杩涘叆') + }, + + // 鍒ゆ柇浣嶇疆 return 'left' 'right' + getDirection(itemUserId) { + return itemUserId === 'mySelf' ? 'right' : 'left' + }, + + // 鐐瑰嚮鍙戦�� + handleSend() { + if (this.loading) return window.appToast('鎿嶄綔杩囧揩锛岃绋嶅悗') + if (!this.userId) return window.appToast('缂哄皯userID锛岃閲嶆柊杩涘叆') + + const myTalk = JSON.parse(JSON.stringify(this.myTalk)) + const list = JSON.parse(JSON.stringify(this.list)) + + if (!myTalk) return window.appToast('璇疯緭鍏ュ唴瀹�') + this.myTalk = '' + + list.push({ + content: { 'content': myTalk }, + name: '鎴�', + msgtime: this.$moment().format('yyyy-MM-DD HH:mm:ss'), + action: 'send', + id: this.$moment().format('yyyyMMDDHHmmss'), + avatar: require('@/assets/imgs/mySelf.png'), + msgtype: 'text', + fromUser: 'mySelf' + }) + + // 澶勭悊鑱婂ぉ鏄剧ず鐨勬棩鏈� + list && list.forEach((item, index) => { + if (index !== 0) item.time_tx = chatFn.chatTime(item.msgtime, list[index - 1] && list[index - 1].msgtime) + }) + this.list = list + + this.$nextTick(() => { this.scrollBottom() }) + + this.getData(myTalk) + }, + + // 鑾峰彇ai杩斿洖鍐呭 + getData(keyWord) { + console.log('getChatList') + var { loading, userId } = this + const list = JSON.parse(JSON.stringify(this.list)) + if (loading) return + + this.loading = true + + const url = config.is_use_test_server ? 'crm-user/chatGpt/chat' : 'chat/msg' + + this.Req.http.post({ + url: url, + data: { + msg: keyWord, + userId: userId + }, + udData: { noLoading: true, nokey: true }, + mockData: { + code: 100, + msg: '', + data: { + text: '鏈哄櫒浜哄洖澶�' + } + } + }).then(res => { + this.loading = false + + if (res.data) { + const content = res.data.replace(/\n/g, '</br>') + list.push({ + content: { 'content': content }, + name: 'AI', + msgtime: this.$moment().format('yyyy-MM-DD HH:mm:ss'), + action: 'send', + id: this.$moment().format('yyyyMMDDHHmmss'), + avatar: require('@/assets/imgs/AI.png'), + msgtype: 'text', + fromUser: 'robot' + }) + } + + // 澶勭悊鑱婂ぉ鏄剧ず鐨勬棩鏈� + list && list.forEach((item, index) => { + if (index !== 0) item.time_tx = chatFn.chatTime(item.msgtime, list[index - 1] && list[index - 1].msgtime) + }) + + this.list = list + + this.$nextTick(() => { this.scrollBottom() }) + }).catch(res => { + this.loading = false + const warnText = res.msg || ('璇风◢鍚庡啀璇�...') + window.appToast(warnText) + }) + }, + + scrollBottom() { + this.$nextTick(() => { + this.$refs.chatList.scrollTop = this.$refs.chatList.scrollHeight + }) + } + } +} +</script> + +<style scoped> +.loading-tx{ + font-size: 22px; + color: #999; +} + +.chat-list{ + overflow-y: auto; + background-color: #fff; + padding-top: 40px; + box-sizing: border-box; + padding-bottom: 140px; +} + +.chat-time{ + background-color: #DADADA; + color: #fff; + font-size: 24px; + line-height: 1.2; + padding: 4px 0; + border-radius: 6px; + text-align: center; + margin: 6px auto 10px; + padding: 4px 10px; +} + +.chat-item{ + margin-bottom: 20px; + padding: 0 20px ; +} +.chat-item .avatar{ + height: 60px; + width: 60px; + display: block; + margin-right: 10px; + border-radius: 4px; + float: left; +} +.chat-item .info{ + /* padding-top: 4px; */ + display: inline-block; + text-align: left; +} +.chat-item .info .name{ + line-height: 1.2; + height: 1.2em; + margin-bottom: 4px; + font-size: 22px; +} +.chat-item.me-item{ + text-align: right; +} +.chat-item.me-item .avatar{ + float: right; + margin-right: 0; + margin-left: 10px; +} +.chat-item.me-item .name{ + text-align: right; +} + +.handle-wrap{ + background-color: #F7F7F7; + position: fixed; + bottom: 0; + left: 0; + width: 100%; + padding: 20px 30px 60px 30px; + box-sizing: border-box; +} +.handle-wrap .input{ + height: 60px; + line-height: 30px; + font-size: 26px; + border: none; + background-color: #fff; + border-radius: 6px; + outline: none; +} +.handle-wrap .input:focus{ + border: none; +} +.handle-wrap .send-btn{ + background-color: #45B1D7; + height: 60px; + line-height: 60px; + color: #fff; + padding: 0 20px; + border-radius: 6px; + letter-spacing: 4px; + margin-left: 20px; + font-size: 28px; +} + +@keyframes ball-rotate { + 0% {transform: rotate(0deg) scale(1); } + + 50% {transform: rotate(180deg) scale(0.6);} + + 100% {transform: rotate(360deg) scale(1);} +} +.ball-rotate{position: relative;width: 100px;height: 70px;margin: 0 auto 20px;} +.ball-rotate > div { + background-color: #000; + width: 30px; + height: 30px; + border-radius: 100%; + margin: 4px; + animation-fill-mode: both; + position: absolute; + top: 50%; + left: 50%; + margin: -16px 0 0 -16px; +} +.ball-rotate > div:first-child { + animation: ball-rotate 1s 0s cubic-bezier(.7, -.13, .22, .86) infinite; +} +.ball-rotate > div:before, .ball-rotate > div:after { + background-color: #000; + width: 30px; + height: 30px; + border-radius: 100%; + margin: 4px; + content: ""!important; + position: absolute; + opacity: .8; +} +.ball-rotate > div:before {top: 0px;left: -56px} +.ball-rotate > div:after {top: 0px;left: 50px} +</style> -- Gitblit v1.8.0