Browse Source

feat:内容逐字显示、内容加载效果

xianna.liang 9 months ago
parent
commit
9f3bd8efb4
5 changed files with 219 additions and 37 deletions
  1. 60 0
      components/loadingPoints.vue
  2. 57 17
      pages/index15/index15.vue
  3. 88 19
      pages/index32/index32.vue
  4. 7 0
      theme/chat15.css
  5. 7 1
      theme/chat32.css

+ 60 - 0
components/loadingPoints.vue

@@ -0,0 +1,60 @@
+<template>
+    <view class="">
+        <view class="spinner">
+          <view class="bounce1"></view>
+          <view class="bounce2"></view>
+          <view class="bounce3"></view>
+		  <slot> </slot>
+        </view>
+    </view>
+</template>
+
+<script>
+</script>
+
+<style>
+    .spinner {
+      right: 200px;
+      width: 100%;
+      text-align: end;
+    }
+     
+    .spinner > view {
+      width: 12px;
+      height: 12px;
+      background-color: #1E90FF;
+     
+      border-radius: 100%;
+      display: inline-block;
+      -webkit-animation: bouncedelay 1.4s infinite ease-in-out;
+      animation: bouncedelay 1.4s infinite ease-in-out;
+      /* Prevent first frame from flickering when animation starts */
+      -webkit-animation-fill-mode: both;
+      animation-fill-mode: both;
+    }
+     
+    .spinner .bounce1 {
+      -webkit-animation-delay: -0.32s;
+      animation-delay: -0.32s;
+    }
+     
+    .spinner .bounce2 {
+      -webkit-animation-delay: -0.16s;
+      animation-delay: -0.16s;
+    }
+     
+    @-webkit-keyframes bouncedelay {
+      0%, 80%, 100% { -webkit-transform: scale(0.0) }
+      40% { -webkit-transform: scale(1.0) }
+    }
+     
+    @keyframes bouncedelay {
+      0%, 80%, 100% {
+        transform: scale(0.0);
+        -webkit-transform: scale(0.0);
+      } 40% {
+        transform: scale(1.0);
+        -webkit-transform: scale(1.0);
+      }
+    }
+</style>

+ 57 - 17
pages/index15/index15.vue

@@ -17,8 +17,14 @@
 									<view class="content right" disabled>{{ item.userContent }}</view>
 								</view>
 								<!-- ai方-聊天内容 -->
-								<view class="item other" v-if="item.otherContent != ''">
-									<view class="content left">{{ item.otherContent }}</view>
+								<view class="item other">
+									<view class="">
+										<view class="loadingPoint" v-if='msgList.isloading[index]'>
+											<loadingPointsVue></loadingPointsVue>
+										</view>
+										<view class="content left" v-if='!msgList.isloading[index]'>
+											{{ msgList.otherChatList[index] }}</view>
+									</view>
 									<image class="avtar" src="../../static/Ai-avatar.png" mode="aspectFit"></image>
 								</view>
 							</view>
@@ -33,7 +39,7 @@
 								confirm-type="send" @confirm="handleSend" maxlength="300" />
 						</view>
 						<view class="uni-button">
-							<button class="send-btn" @click="handleSend" type="primary">发送</button>
+							<button class="send-btn" @click="handleSend" type="primary" :disabled="msgList.isClick">发送</button>
 						</view>
 					</view>
 				</view>
@@ -51,36 +57,46 @@
 		reactive,
 		watch
 	} from 'vue';
-	import {
-		onShow
-	} from '@dcloudio/uni-app'
 
 	import {
 		getDataList
 	} from '../../api/ChatApp.js'
 
 	import axios from 'axios';
-	// import display from '../../theme/display';
+	import loadingPointsVue from '../../components/loadingPoints.vue';
 
 	const msgList = reactive({
+		// 输入框
 		chatMsg: '',
+		// 聊天数据列表
 		chatList: [],
 		// 滚动距离
 		scrollTop: 0,
-		boxWord: '选择无处不在,面朝大海春暖花开是海子的选择,人不是生来被打败的是海明威的选择,人固有一死,或重于泰山,或轻于鸿毛,是司马迁的选择,选择是一次又一次自我重塑的过程,让我们不断地成长,不断地完善,如果说人生是一次不断选择的旅程,那么当千帆阅尽最终留下的就是一片属于自己的独一无二的风景   ——董卿《朗读者》',
+		// setTimeout的返回值,唯一确定结束对应的setTimeout
 		timer: null,
+		// 
 		textCount: 0,
-		otherContent: ''
+		otherContent: '',
+		// 处理后的ai数据返回值
+		otherChatList: [],
+		// 发送/返回的次数
+		len: 0,
+		// 加载符号是否显示
+		isloading: [],
+		isClick:false
 	})
 
 	// 发送消息
 	const handleSend = async () => {
+		msgList.isClick = !msgList.isClick
 		const data = {
 			AppId: '0c8ff06b-91d9-43f7-b61e-ca5da1db15d4',
 			AId: 'TK1234',
 			content: ''
 		}
 		if (msgList.chatMsg != '') {
+			msgList.isloading[msgList.len] = true
+			msgList.len++
 			let obj = {
 				otherContent: '',
 				userContent: '',
@@ -88,11 +104,13 @@
 			}
 			data.content = msgList.chatMsg
 			obj.userContent = msgList.chatMsg
-			obj.otherContent = await GetNewsList(data)
 			msgList.chatList.push(obj)
-		}
 
-		msgList.otherContent = ''
+			obj.otherContent = await GetNewsList(data)
+			await sleep(16000);
+			getChatContent(obj.otherContent, msgList.len)
+		}
+		
 	}
 
 
@@ -113,20 +131,42 @@
 		})
 	})
 	//滚动至聊天底部
-	watch(msgList.chatList, (newVal) => {
-		scrollToBottom()
+	watch([msgList.otherChatList,msgList.chatList], (newVal) => {
+		msgList.scrollTop = scrollToBottom()
 	})
 
-
-
 	// 调用数据接口
 	const GetNewsList = async (data) => {
-		console.log(111)
 		msgList.chatMsg = ''
 		var res = await getDataList(data)
 		console.log(res)
 		return res
 	}
+
+	// ------- 聊天逐字输出 -----------
+	// 延时函数
+	const sleep = ((delaytime = 10000) => {
+		return new Promise(resolve => setTimeout(resolve, delaytime));
+	})
+
+	// 逐字显示内容
+	const getChatContent = ((text, index) => {
+		msgList.timer = setInterval(() => {
+			msgList.textCount++;
+			if (msgList.textCount == text.length + 1) {
+				msgList.otherChatList[index - 1] = text;
+				clearInterval(msgList.timer);
+			} else {
+				// 取字符串子串
+				let nowStr = text.substring(0, msgList.textCount);
+				msgList.otherChatList[index - 1] = nowStr;
+			}
+
+		}, 200);
+		msgList.textCount = 0
+		msgList.isloading[index - 1] = false
+		msgList.isClick = !msgList.isClick
+	})
 </script>
 
 <style>

+ 88 - 19
pages/index32/index32.vue

@@ -1,6 +1,6 @@
 <template>
 	<view id='app'>
-		<view class="zhanwei"></view>
+		<view class="placeholder"></view>
 		<view class="pageView">
 			<view class="sidebar-left"></view>
 			<view class="body">
@@ -11,15 +11,21 @@
 					<scroll-view id="content-box" scroll-y="true" class="scrollview" :scroll-top="msgList.scrollTop">
 						<!-- 聊天主体 -->
 						<view id="content-overflow">
-							<view class="scrollview-item" v-for="(item,index) in msgList.myList" :key='index'>
+							<view class="scrollview-item" v-for="(item,index) in msgList.chatList" :key='index'>
 								<!-- user方-聊天内容 -->
 								<view class="item self" v-if="item.userContent != ''">
 									<image class="avtar" src="../../static/user-avatar.png" mode="aspectFit"></image>
 									<view class="content right" disabled>{{ item.userContent }}</view>
 								</view>
 								<!-- ai方-聊天内容 -->
-								<view class="item other" v-if="item.otherContent != ''">
-									<view class="content left">{{ item.otherContent }}</view>
+								<view class="item other">
+									<view class="">
+										<view class="loadingPoint" v-if='msgList.isloading[index]'>
+											<loadingPointsVue></loadingPointsVue>
+										</view>
+										<view class="content left" v-if='!msgList.isloading[index]'>
+											{{ msgList.otherChatList[index] }}</view>
+									</view>
 									<image class="avtar" src="../../static/Ai-avatar.png" mode="aspectFit"></image>
 								</view>
 							</view>
@@ -52,34 +58,61 @@
 		reactive,
 		watch
 	} from 'vue';
+
 	import {
-		onShow
-	} from '@dcloudio/uni-app'
+		getDataList
+	} from '../../api/ChatApp.js'
+
+	import axios from 'axios';
+	import loadingPointsVue from '../../components/loadingPoints.vue';
 
 	const msgList = reactive({
+		// 输入框
 		chatMsg: '',
-		myList: [{
-			userContent: '',
-			otherContent: '',
-			image: ''
-		}, ],
+		// 聊天数据列表
+		chatList: [],
 		// 滚动距离
 		scrollTop: 0,
-		boxWord: '选择无处不在,面朝大海春暖花开是海子的选择,人不是生来被打败的是海明威的选择,人固有一死,或重于泰山,或轻于鸿毛,是司马迁的选择,选择是一次又一次自我重塑的过程,让我们不断地成长,不断地完善,如果说人生是一次不断选择的旅程,那么当千帆阅尽最终留下的就是一片属于自己的独一无二的风景   ——董卿《朗读者》'
+		// 
+		timer: null,
+		textCount: 0,
+		otherContent: '',
+		otherChatList: [],
+		len: 0,
+		isloading: [],
+		isClick:false
 	})
 
 	// 发送消息
-	const handleSend = (() => {
+	const handleSend = async () => {
+		msgList.isClick = !msgList.isClick
+		const data = {
+			AppId: '0c8ff06b-91d9-43f7-b61e-ca5da1db15d4',
+			AId: 'TK1234',
+			content: ''
+		}
 		if (msgList.chatMsg != '') {
+			msgList.isloading[msgList.len] = true
+			msgList.len++
 			let obj = {
-				otherContent: msgList.boxWord,
-				userContent: msgList.chatMsg,
+				otherContent: '',
+				userContent: '',
 				image: ""
 			}
-			msgList.myList.push(obj)
+			data.content = msgList.chatMsg
+			obj.userContent = msgList.chatMsg
+			msgList.chatList.push(obj)
+
+			obj.otherContent = await GetNewsList(data)
+
+			await sleep(16000);
+			getChatContent(obj.otherContent, msgList.len)
+
+
 		}
-		msgList.chatMsg = ''
-	})
+
+		msgList.otherContent = ''
+	}
 
 	// 滚动条回到最底部
 	const scrollToBottom = (() => {
@@ -97,10 +130,46 @@
 			})
 		})
 	})
+	
 	//滚动至聊天底部
-	watch(msgList.myList, (newVal) => {
+	watch([msgList.otherChatList,msgList.chatList], (newVal) => {
 		scrollToBottom()
 	})
+	
+	// 调用数据接口
+	const GetNewsList = async (data) => {
+		msgList.chatMsg = ''
+		var res = await getDataList(data)
+		console.log(res)
+		return res
+	}
+	
+	// ------- 聊天逐字输出 -----------
+	// 延时函数
+	const sleep = ((delaytime = 10000) => {
+		return new Promise(resolve => setTimeout(resolve, delaytime));
+	})
+	
+	// 逐字显示内容
+	const getChatContent = ((text, index) => {
+		console.log(index)
+		msgList.timer = setInterval(() => {
+			msgList.textCount++;
+			if (msgList.textCount == text.length + 1) {
+				msgList.otherChatList[index - 1] = text;
+				clearInterval(msgList.timer);
+			} else {
+				// 取字符串子串
+				let nowStr = text.substring(0, msgList.textCount);
+				msgList.otherChatList[index - 1] = nowStr;
+			}
+	
+		}, 200);
+		console.log(msgList.timer)
+		msgList.textCount = 0
+		msgList.isloading[index - 1] = false
+		msgList.isClick = !msgList.isClick
+	})
 </script>
 
 <style>

+ 7 - 0
theme/chat15.css

@@ -91,6 +91,7 @@
 	font-weight: 500;
 	color: #fff;
 	line-height: 320rpx;
+	z-index: 1;
 }
 
 .chat-bottom .send-msg .uni-textarea textarea {
@@ -125,4 +126,10 @@
 /* 去除导航条 */
 .scrollview ::-webkit-scrollbar {
 	display: none;
+}
+
+
+/* 聊天框数据加载 图标距离头像的间距 */
+.loadingPoint{
+	margin-right: 30px;
 }

+ 7 - 1
theme/chat32.css

@@ -1,7 +1,7 @@
 /* 32寸 大屏样式 */
 
 
-.zhanwei {
+.placeholder {
 	height: 40vh;
 
 }
@@ -98,6 +98,7 @@
 	font-weight: 500;
 	color: #fff;
 	line-height: 320rpx;
+	z-index: 1;
 }
 
 .chat-bottom .send-msg .uni-textarea textarea {
@@ -135,4 +136,9 @@
 /* 去除导航条 */
 .scrollview ::-webkit-scrollbar {
 	display: none;
+}
+
+/* 聊天框数据加载 图标距离头像的间距 */
+.loadingPoint{
+	margin-right: 30px;
 }