<!-- 聊天记录模式+虚拟列表演示(vue)，加载更多聊天记录无闪动&支持渲染大量数据 -->
<!-- 注意：虚拟列表缓存高度默认仅在cell初始化时获取一次，若您的聊天列表中带有图片，强烈建议给图片一个固定的高度，如果高度根据内容动态撑高，可能导致虚拟列表抖动 -->
<!-- 如果必须实现高度根据内容动态撑高+虚拟列表功能，可监听图片加载完毕事件，并在其中调用z-paging的didUpdateVirtualListCell刷新缓存高度 -->
<template>
	<view class="content">
		<!-- use-chat-record-mode：开启聊天记录模式 -->
		<!-- use-virtual-list：开启虚拟列表模式 -->
		<!-- cell-height-mode：设置虚拟列表模式高度不固定 -->
		<!-- safe-area-inset-bottom：开启底部安全区域适配 -->
		<!-- bottom-bg-color：设置slot="bottom"容器的背景色，这里设置为和chat-input-bar的背景色一致 -->
		<z-paging ref="paging" v-model="dataList" :paging-style="{ paddingTop: paddingTop + 'px' }" default-page-size="20" :innerListStyle="innerListStyle" use-chat-record-mode use-virtual-list cell-height-mode="dynamic" :auto-clean-list-when-reload="false" safe-area-inset-bottom bottom-bg-color="#fafafa"
		
		@query="queryList" :back-to-top-style="backToTopStyle" :auto-show-back-to-top="showNewMessageTip" @scrolltoupper="onScrollToUpper" @backToTopClick="onBackToTopClick" @keyboardHeightChange="keyboardHeightChange" @hidedKeyboard="hidedKeyboard">
			<!-- 顶部提示文字 -->
			<template #top>
				<navigation-Bar :isReconnecting="isReconnecting" :user="user" @initNav="initNav" @more="navMore">
					<template #card-swiper>
						<card-swiper v-if="navSwiper"></card-swiper>
					</template>
					<template #card-notice>
						<card-notice v-if="navNotice"></card-notice>
					</template>
				</navigation-Bar>
			</template>
			
			<!-- style="transform: scaleY(-1)"必须写，否则会导致列表倒置！！！ -->
			<!-- 注意不要直接在chat-item组件标签上设置style，因为在微信小程序中是无效的，请包一层view -->
			<template #cell="{item,index}">
				<view style="transform: scaleY(-1)">
					<view-item @playAudio="playAudio" :playId="playId" :messageList="dataList" :messageIndex="index" :item="item"></view-item>
				</view>
			</template>
			
			<!-- 底部聊天输入框 -->
			<template #bottom>
				<slot name="chat-bar" :user="user" :keyboardHeight="keyboardHeight"></slot>
			</template>
			
			<!-- 查看最新消息 -->
			<template #backToTop>
			  <text>有新消息</text>
			</template>
			
		</z-paging>
	</view>
</template>
 
<script>
	import dayjs from 'dayjs';
	import relativeTime from "dayjs/plugin/relativeTime";
	dayjs.extend(relativeTime);
	import NavigationBar from '@/pages/im/components/navigationBar.vue';
	import cardSwiper from '@/pages/im/components/cardSwiper.vue';
	import cardNotice from '@/pages/im/components/cardNotice.vue';
	import ViewItem from '@/pages/im/components/viewItem.vue';
	import ImMessageApi from '@/sheep/api/im/memberMessage';
	import UserApi from '@/sheep/api/member/user';
	export default {
		components: {
			NavigationBar,
			cardSwiper,
			cardNotice,
			ViewItem,
		},
		props: {
			groupId: 0,
			userId: 0,
			isReconnecting: false,
		},
		data() {
			return {
				dataList: [],
				keyboardHeight: -1,
				paddingTop: 0,
				navSwiper: false,
				navSwiperH: 80,
				navNotice: false,
				navNoticeH: 90,
				height: 0,
				
				queryParams: {
					pageNo: 1,
					pageSize: 10,
					groupId: 0,
				},
				
				showNewMessageTip: false,
				backToTopStyle: {
					'width': '100px',
					'background-color': '#fff',
					'border-radius': '30px',
					'box-shadow': '0 2px 4px rgba(0, 0, 0, 0.1)',
					'display': 'flex',
					'justifyContent': 'center',
					'alignItems': 'center',
				},
 				 
				innerListStyle: {
					borderBottom: '20px solid #fafafa',
				},
				
				audioList: [],
				voiceIndex: -1,
				playId: null,
				
				user: {},
			}
		},
		created() {
			this.getUserInfo();
		},
		methods: {
			getUserInfo() {
				UserApi.getUserInfoById(this.userId).then(res => {
					this.user = res.data;
					this.user.time = this.showDayTime(this.user.updateTime);
				});
			},
			showDayTime(datetime) {
			  if (!datetime) return "";
			  return dayjs(datetime).fromNow();
			},
			initNav(e) {
				this.height = e.height;
				this.paddingTop = this.height;
				
				if(this.navSwiper){
					this.paddingTop = this.paddingTop + this.navSwiperH;
				}
				
				if(this.navNotice){
					this.paddingTop = this.paddingTop + this.navNoticeH;
				}
			},
			navMore() {
				this.navNotice = !this.navNotice;
				
				if(this.navNotice){
					this.paddingTop = this.paddingTop + this.navNoticeH;
				}else{
					this.paddingTop = this.paddingTop - this.navNoticeH;
				}
			},
			queryList(pageNo, pageSize) {
				// 组件加载时会自动触发此方法，因此默认页面加载时会自动触发，无需手动调用
				// 这里的pageNo和pageSize会自动计算好，直接传给服务器即可
				// 模拟请求服务器获取分页数据，请替换成自己的网络请求
				this.queryParams.pageNo = pageNo;
				this.queryParams.pageSize = pageSize;
				this.queryParams.groupId = this.groupId;  
				
				/* this.$refs.paging.complete([
					{
						dd:'2',
						msgType: 'message',
						message: {
							time: false,
							src: 'https://rbtnet.oss-cn-hangzhou.aliyuncs.com/laohu.png',
							position: 'left',
							isRead: true,
							src: '',
							sec: '30',
							msgType: 'voice',
						},
					},
					{
						dd:'2',
						msgType: 'info',
						message: {
							title: '温馨提示',
							content: '请礼貌用语友好沟通，如遇骚扰等不文明行为，可以将对方屏蔽并投诉。',
							msgType: 'card',
						},
					},
					{
						dd:'2',
						msgType: 'message',
						message: {
							time: true,
							timeDesc: '14:52',
							src: 'https://rbtnet.oss-cn-hangzhou.aliyuncs.com/laohu.png',
							position: 'right',
							isRead: true,
							msgType: 'emoji',
						},
					},
					{
						dd:'2',
						msgType: 'message',
						message: {
							time: true,
							timeDesc: '14:52',
							src: 'http://rbtnet.oss-cn-hangzhou.aliyuncs.com/test/20240726/98a24075202b429d9c9722df541621c6.jpg',
							position: 'right',
							isRead: true,
							msgType: 'img',
						},
					},
					{
						dd:'2',
						msgType: 'message',
						message: {
							time: false,
							src: 'https://rbtnet.oss-cn-hangzhou.aliyuncs.com/laohu.png',
							position: 'right',
							isRead: true,
							src: '',
							sec: '130',
							msgType: 'voice',
						},
					},
					{
						dd:'2',
						msgType: 'message',
						message: {
							time: false,
							position: 'right',
							content: '地址：广东省广州市番禺区祈福新村129号',
							msgType: 'map',
						},
					},
					{
						dd:'2',
						msgType: 'message',
						message: {
							time: false,
							position: 'right',
							content: '吃饭了吗',
							msgType: 'text',
						},
					},
					{
						dd:'2',
						msgType: 'info',
						message: {
							content: '长按图片、文字或视频，支持撤回消息哦~',
							msgType: 'text',
						},
					},
					{
						dd:'2',
						msgType: 'message',
						message: {
							time: true,
							timeDesc: '14:52',
							src: 'https://rbtnet.oss-cn-hangzhou.aliyuncs.com/laohu.png',
							position: 'left',
							isRead: true,
							msgType: 'emoji',
						},
					},
					]);
					 */
					
				ImMessageApi.getMemberMessagePage(this.queryParams).then(res => {
					// 将请求的结果数组传递给z-paging
					this.$refs.paging.complete(res.data.list);
				}).catch(res => {
					// 如果请求失败写this.$refs.paging.complete(false);
					// 注意，每次都需要在catch中写这句话很麻烦，z-paging提供了方案可以全局统一处理
					// 在底层的网络请求抛出异常时，写uni.$emit('z-paging-error-emit');即可
					this.$refs.paging.complete(false);
				})	
			},
			/** 监听滚动到底部事件（因为 scroll 翻转了顶就是底） */
			onScrollToUpper() {
			  // 若已是第一页则不做处理
			  if (this.queryParams.pageNo === 1) {
			    return;
			  }
			  this.showNewMessageTip = false;
			  // 到底重置消息列表
			  this.reload();
			},
			// 监听键盘高度改变，请不要直接通过uni.onKeyboardHeightChange监听，否则可能导致z-paging内置的键盘高度改变监听失效（如果不需要切换表情面板则不用写）
			keyboardHeightChange(res) {
				this.keyboardHeight = res.height;
			}, 
			// 用户尝试隐藏键盘，此时如果表情面板在展示中，应当通知chatInputBar隐藏表情面板（如果不需要切换表情面板则不用写）
			hidedKeyboard() {
				this.$emit('hidedKeyboard');
			},
			reload(message) {
				if(message){
					if(this.queryParams.pageNo > 1){
						this.showNewMessageTip = true;
					}
					if(message.readStatus){
						this.updateReadStatus(message);
					}else{
						this.$refs.paging.addChatRecordData([message]);
					}
				}else{
					this.$refs.paging.reload();
				}
			},
			updateReadStatus(message) {
				this.dataList.forEach(item => {
				    if (item.id == message.id) {
				      item.readStatus = true;
				    }
				});
			},
			/** 滚动到最新消息 */
			onBackToTopClick(event) {
				event(false); // 禁用默认操作
				this.$refs.paging.scrollToBottom();
			},
			playAudio(e) {
				this.playId = e.id;
				this.clearAllAudio();
				var audio = uni.createInnerAudioContext();
				this.audioList.push(audio);
				//语音自然播放结束
				audio.onEnded((res) => {
					this.playId = null;
				});
				
				audio.src = e.content;
				audio.play();
			},
			clearAllAudio() {
				this.audioList.forEach(function(e){
					e.destroy();
				})
			},
		}
	}
</script>

<style scoped>
	.content {
		background-color: #fafafa;
		height: calc(100vh);
	}
</style>
