uniapp框架基于websocket组件实现消息数量实时更新功能

标消息开发页msgindex.vue

 一、来消息的数量自加

1.消息数量实时更新的部分有四个:协同消息数量、应用消息数量、公告消息数量、消息总数。

2.问题研究:每当后台发送一条消息过来,消息页对应部分显示数字徽标。涉及到实时更新的问题,因为uniapp框架的页面不可能周期的调用后端接口实现实时更新。那么使用Websocket组件被动的使数量的实时更新。(你喜欢被动吗?)消息页面的不涉及到触发条件的更新,需要使用websocket,当然后端不可能把数量的变量直接推给咱们,顶多把表单分三类通过websocket发给咱们。咱们要进一步的对数量的加加减减进行处理。

逻辑实现

 

3.圈1、圈2、圈3,都是正常现象,websocket发过来的值直接用在<view>里就可以。如下:

 4.但是圈4-tabBar,这个傻逼东西做的就很狗,它他妈的用 

if(this.$store.state.wsAllnum>0){
    uni.setTabBarBadge({
		index: 0,
		text:this.$store.state.wsAllnum.toString(),
	})	
}
else if(this.$store.state.wsAllnum==0){
	uni.removeTabBarBadge({
		index: 0,
    })
};

这个来写,这个需要触发条件,但是消息数量实时更新在.vue界面是不会有触发条件的,来了就能显示。还好这个东西可以全局使用,我把它放在了websocket组件的.js文件里的来消息函数进行触发。如上图逻辑实现的圈4。注:在使用uni.setTabBarBadge的时候,注意textd的数据类型是字符串,要将数字转换成字符串的格式。(太傻逼了)

5.同时为了防止前端数据丢失以及接下来两个页面的数据交换打基础,使用了uniapp的数据缓存函数。

 uni.setStorage({
	key: 'msgSynergykey',
	data: state.wsSynergynum,
	success: function () {
	}
});
console.log("皆",state.wsSynergyDate);
uni.getStorage({
	key:'msgSynergykey',
	success:(res)=>{
	    if(res.data){
		    state.wsSynergynum = res.data //定义全局变量供页面使用
	    }
	}
})

 方便全局数据拿去。

二、点击某一消息类型,该类型的数量全部消失,对应的总数也相应减少。

1.由第一节可知,总数量写在了.js文件里,并通过来消息函数触发,在.vue界面点击部分消息窗口时整体的消息数量会改变并放在缓存里,但是这时无法触发来消息函数 ,进而无法触发总数的变化。

2.解决办法:回想一下,消息总数一开始为什么放在了websocket所在的.js文件里?因为最开始是来消息时总数自动更新,并且不需要页面内的任何条件出发,所以写在了那里。但是这次有触发条件了,就是点击时间。那么在点击事件下边在写一遍tabbar数量的函数就实现了。

.js代码

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import user from '@/store/modules/user'
//import websocket from '@/store/modules/websocket';
import getters from './getters'

const store = new Vuex.Store({
	 state: {
	         socketTask: null,
	         websocketData: {}, // 存放从后端接收到的websocket数据
				wsSynergyDate:{},//cunchu
				wsAppliedDate:{},
				wsAnnouncedDate:{},
				wsSynergynum:0,
				wsAppliednum:0,
				wsAnnouncednum:0,
				wsAllnum:0,
				wsUrl:"",
	     },
		  
	     mutations: {
	         setWebsocketData (state, data) {
	             state.websocketData = data
					 if(state.websocketData.msgCategory==1){
						 state.wsSynergyDate=state.websocketData;
						 state.wsSynergynum+=1;
						 uni.setStorage({
						 	key: 'msgSynergykey',
						 	data: state.wsSynergynum,
						 	success: function () {
						 	}
						 });
						 console.log("皆",state.wsSynergyDate);
						 uni.getStorage({
						 	key:'msgSynergykey',
						 	success:(res)=>{
						 		if(res.data){
						 			state.wsSynergynum = res.data //定义全局变量供页面使用
						 		}
						 	}
						 })
					 };
					
					 
					 if(state.websocketData.msgCategory==2){
					 	state.wsAppliedDate=state.websocketData;
						state.wsAppliednum+=1;
						uni.setStorage({
							key: 'msgAppliedkey',
							data: state.wsAppliednum,
							success: function () {
							}
						});
						console.log("阵",state.wsAppliedDate);
						uni.getStorage({
							key:'msgAppliedkey',
							success:(res)=>{
								if(res.data){
									state.wsAppliednum = res.data //定义全局变量供页面使用
								}
							}
						})
					 };
					 
					 
					 if(state.websocketData.msgCategory==3){
					 	state.wsAnnouncedDate=state.websocketData;
						state.wsAnnouncednum+=1;
						uni.setStorage({
							key: 'msgAnnouncedkey',
							data: state.wsAnnouncednum,
							success: function () {
							}
						});
						console.log("列",state.wsAnnouncedDate);
						uni.getStorage({
							key:'msgAnnouncedkey',
							success:(res)=>{
								if(res.data){
									state.wsAnnouncednum = res.data //定义全局变量供页面使用
								}
							}
						})
					 };
					state.wsAllnum=state.wsSynergynum+state.wsAppliednum+state.wsAnnouncednum;
					 uni.setStorage({
					 	key: 'msgAllkey',
					 	data: state.wsAllnum,
					 	success: function () {
					 	}
					 });
					 uni.getStorage({
					 	key:'msgAllkey',
					 	success:(res)=>{
					 		if(res.data){
					 			state.wsAllnum = res.data //定义全局变量供页面使用
					 		}
					 	}
					 });
					 if(state.wsAllnum>0){
						 uni.setTabBarBadge({
							index: 0,
							text:state.wsAllnum.toString(),
						})	
					 }else if(state.wsAllnum==0){
						 uni.removeTabBarBadge({
							 index: 0,
						 })
					 };
					 
	         }
	     }, 
		  
		   actions: {
				 websocketInit ({ state, dispatch }, url) {
					  state.socketTast = uni.connectSocket({
							url, // url是websocket连接ip
							success: () => {
								 console.log('websocket连接成功!')
							},
							fail: e => {
								 console.log('连接失败' + e)
							}
					  })
					  state.socketTast.onOpen(() => dispatch('websocketOnOpen'))
					  state.socketTast.onMessage(res => dispatch('websocketOnMessage', res))
					  state.socketTast.onClose(e => dispatch('websocketOnClose'))
					  state.socketTast.onError(e => dispatch('websocketOnError'))
				 },
				 websocketOnOpen ({ commit }) {
					  console.log('WebSocket连接正常打开中...!')
				 },
				  // 收到数据
					websocketOnMessage ({ commit }, res) {
						 console.log('收到服务器内容啦!!!:' + res.data)
						 if (res.data !== 'success') {
							  commit('setWebsocketData', (res && JSON.parse(res.data) || null))
							  
						 }
					},
					websocketOnClose ({ commit, dispatch }) {
						 console.log('WebSocket连接关闭')
					},
					websocketOnError ({ commit, dispatch }) {
						 console.log('WebSocket连接错误')
					},
					websocketClose ({ state }) {
						 if (!state.socketTast) return
						 state.socketTast.close({
							  success (res) {
									console.log('关闭成功', res)
							  },
							  fail (err) {
									console.log('关闭失败', err)
							  }
						 })
					},
				  // 发送数据
				  websocketSend ({ state }, data) {
						uni.sendSocketMessage({
							 data,
							 success: res => {
								  console.log('发送成功', res)
							 },
							 fail: e => {
								  console.log('发送失败', e)
							 }
						})
				  }
			 },

  modules: {
    user,
	 //websocket,
	},
  getters
})

export default store

.vue代码

 

<template>
	
	<view class="pagecolor" >
		<view class="navbar">
			<uni-nav-bar>
				<block slot="left">
					<view class="bartext">
						<h2>消息</h2>
					</view>
				</block>
			</uni-nav-bar>
		</view>
		<!-- 协同消息通知 -->
		<view>
			<view v-if="this.$store.state.wsSynergyDate.msgCategory!=1">
				<uni-card class="todo_first"
					@click="handlemesSynergy">
					<view  style="border-bottom: 0.5px solid #d0d0d0;padding: 5rpx 10rpx;">
						<uni-badge size="small" :text="this.$store.state.wsSynergynum" absolute="rightTop" >
							<uni-icons type="staff-filled" size="30" color="#2c5a42" style="margin-left: -1%;"></uni-icons>
						</uni-badge>
						<text style="font-size:33rpx;color: #3d3d3d;margin-left: 2%;">新协同消息</text>
						<text style="font-size: 24rpx;color: #838383;float: right;margin-top: 15rpx;">{{this.firstsynergy.createTime|MerchantsNumber}}</text>
					</view>
					 <view style="margin-top: 4%;">
						<h5 class="todo_0">
							<view > <text>{{this.firstsynergy.creatorName}}</text> </view>
							<view class="flex"> 
								<text>{{this.firstsynergy.msgTitle}}:</text>
								<text>{{this.firstsynergy.msgContent}}</text> 
							</view>
						</h5>
					</view>
				</uni-card>
			</view>
			<view v-else>
				<uni-card class="todo_first"
					@click="handlemesSynergy">
					<view  style="border-bottom: 0.5px solid #d0d0d0;padding: 5rpx 10rpx;">
						<uni-badge size="small" :text="this.$store.state.wsSynergynum" absolute="rightTop" >
							<uni-icons type="staff-filled" size="30" color="#2c5a42" style="margin-left: -1%;"></uni-icons>
						</uni-badge>
						<text style="font-size:33rpx;color: #3d3d3d;margin-left: 2%;">新协同消息</text>
						<text style="font-size: 24rpx;color: #838383;float: right;margin-top: 15rpx;">{{this.$store.state.wsSynergyDate.createTime|MerchantsNumber}}</text>
					</view>
					 <view style="margin-top: 4%;">
						<h5 class="todo_0">
							<view > <text>{{this.$store.state.wsSynergyDate.creatorName}}</text> </view>
							<view class="flex"> 
								<text>{{this.$store.state.wsSynergyDate.msgTitle}}:</text>
								<text>{{this.$store.state.wsSynergyDate.msgContent}}</text> 
							</view>
						</h5>
					</view>
				</uni-card>
			</view>
		</view>
		<!-- 应用消息通知 -->
		<view>
			<view v-if="this.$store.state.wsAppliedDate.msgCategory!=2">
				<uni-card class="todo_first"
					@click="handlemesApplied">
					<view  style="border-bottom: 0.5px solid #d0d0d0;padding: 5rpx 10rpx;">
						<uni-badge size="small" :text="this.$store.state.wsAppliednum" absolute="rightTop" >
							<uni-icons type="shop-filled" size="30" color="#32669a" style="margin-left: -1%;"></uni-icons>
						</uni-badge>
						<text style="font-size:33rpx;color: #3d3d3d;margin-left: 2%;">新应用消息</text>
						<text style="font-size: 24rpx;color: #838383;float: right;margin-top: 15rpx;">{{this.firstapplied.createTime|MerchantsNumber}}</text>
					</view>
					<view style="margin-top: 4%;">
						<h5 class="todo_0">
							<view><text>{{this.firstapplied.creatorName}}</text></view>
							<view class="flex">
								<text>{{this.firstapplied.msgTitle}}:</text>
								<text>{{this.firstapplied.msgContent}}</text>
							</view>
						</h5>
					</view>
				</uni-card>
			</view>
			<view v-else>
				<uni-card class="todo_first"
					@click="handlemesApplied">
					<view  style="border-bottom: 0.5px solid #d0d0d0;padding: 5rpx 10rpx;">
						<uni-badge size="small" :text="this.$store.state.wsAppliednum" absolute="rightTop" >
							<uni-icons type="shop-filled" size="30" color="#32669a" style="margin-left: -1%;"></uni-icons>
						</uni-badge>
						<text style="font-size:33rpx;color: #3d3d3d;margin-left: 2%;">新应用消息</text>
						<text style="font-size: 24rpx;color: #838383;float: right;margin-top: 15rpx;">{{this.$store.state.wsAppliedDate.createTime|MerchantsNumber}}</text>
					</view>
					<view style="margin-top: 4%;">
						<h5 class="todo_0">
							<view><text>{{this.$store.state.wsAppliedDate.creatorName}}</text></view>
							<view class="flex">
								<text>{{this.$store.state.wsAppliedDate.msgTitle}}:</text>
								<text>{{this.$store.state.wsAppliedDate.msgContent}}</text>
							</view>
						</h5>
					</view>
				</uni-card>
			</view>
		</view>
		<!-- 公告消息通知 -->
		<view>
			<view v-if="this.$store.state.wsAnnouncedDate.msgCategory!=3">
				<uni-card class="todo_first"
					@click="handlemesAnnounce">
					 <view  style="border-bottom: 0.5px solid #d0d0d0;padding: 5rpx 10rpx;">
					 	<uni-badge size="small" :text="this.$store.state.wsAnnouncednum" absolute="rightTop" >
							<uni-icons type="sound-filled" size="30" color="#ecec00" style="margin-left: -1%;"></uni-icons>
					 	</uni-badge>
						<text style="font-size:33rpx;color: #3d3d3d;margin-left: 2%;">新公告消息</text>
					 	<text style="font-size: 24rpx;color: #838383;float: right;margin-top: 15rpx;">{{this.firstannounce.createTime|MerchantsNumber}}</text>
					 </view>
					 <view style="margin-top: 4%;">
						<h5 class="todo_0">
							<view><text>{{this.firstannounce.creatorName}}</text></view>
							<view class="flex">
								<text>{{this.firstannounce.msgTitle}}:</text>
								<text>{{this.firstannounce.msgContent}}</text>
							</view>
						</h5>
					</view>
				</uni-card>
			</view>
			<view v-else>
				<uni-card class="todo_first"
					@click="handlemesAnnounce">
					 <view  style="border-bottom: 0.5px solid #d0d0d0;padding: 5rpx 10rpx;">
					 	<uni-badge size="small" :text="this.$store.state.wsAnnouncednum" absolute="rightTop" >
							<uni-icons type="sound-filled" size="30" color="#ecec00" style="margin-left: -1%;"></uni-icons>
					 	</uni-badge>
						<text style="font-size:33rpx;color: #3d3d3d;margin-left: 2%;">新公告消息</text>
					 	<text style="font-size: 24rpx;color: #838383;float: right;margin-top: 15rpx;">{{this.$store.state.wsAnnouncedDate.createTime|MerchantsNumber}}</text>
					 </view>
					 <view style="margin-top: 4%;">
						<h5 class="todo_0">
							<view><text>{{this.$store.state.wsAnnouncedDate.creatorName}}</text></view>
							<view class="flex">
								<text>{{this.$store.state.wsAnnouncedDate.msgTitle}}:</text>
								<text>{{this.$store.state.wsAnnouncedDate.msgContent}}</text>
							</view>
						</h5>
					</view>
				</uni-card>
			</view>
		</view>
		
		
	</view>
</template>

<script>
	import {listtop,read}from "@/api/system/message";
	import index from "@/store/index";
import { created } from "../uview-ui/libs/mixin/mixin";
	export default{
		data() {
			return {
				flag:1,
				synergylist:[],
				appliedlist:[],
				announcelist:[],
				firstsynergy:[],
				firstapplied:[],
				firstannounce:[],
				queryParams:{
					pageNum: 1,
					pageSize:this.mestodototal,
				},
			}
		},
		created() {
			this.getlistone();
			this.getlistwo();
			this.getlistthree();
		},

		onLoad: function (options) {
			
			uni.startPullDownRefresh();
		},
		onPullDownRefresh() {
			this.getlistone();
			this.getlistwo();
			this.getlistthree();
			setTimeout(function () {
				
				uni.stopPullDownRefresh();
			}, 500);
		},
		//过滤器显示时间
		filters: {
		   MerchantsNumber(value) {
				if(value!=null){
					let start = value.slice(0,16);
					return `${start}`;
				}
		   }
		},
		
		methods: {
			getlistone(){
				listtop(this.queryParams).then(Response=>{
					for(let i=0;i<Response.total;i++){
						if(Response.rows[i].msgCategory==1){
							this.synergylist.push(Response.rows[i])	
						};
					}
					this.firstsynergy=this.synergylist[0];
				})
			},
			
			getlistwo(){
				listtop(this.queryParams).then(Response=>{
					for(let i=0;i<Response.total;i++){
						if(Response.rows[i].msgCategory==2){
							this.appliedlist.push(Response.rows[i])	
						};
					}
					this.firstapplied=this.appliedlist[0];
				})
			},
			getlistthree(){
				listtop(this.queryParams).then(Response=>{
					for(let i=0;i<Response.total;i++){
						if(Response.rows[i].msgCategory==3){
							this.announcelist.push(Response.rows[i])	
						};
					}
					this.firstannounce=this.announcelist[0];
				})
			},
			
			handlemesApplied(){
				this.$tab.navigateTo('/pages/message/mesApplied/mesApplied');
				this.$store.state.wsAppliednum=0
				uni.setStorage({
					key: 'msgAppliedkey',
					data: 0,
					success: function (res) {
					}
				});
				 this.$store.state.wsAllnum=this.$store.state.wsSynergynum+this.$store.state.wsAnnouncednum;
				 uni.setStorage({
				 	key: 'msgAllkey',
				 	data: this.$store.state.wsAllnum,
				 	success: function (res) {
				 	}
				 });
				if(this.$store.state.wsAllnum>0){
					uni.setTabBarBadge({
						index: 0,
						text:this.$store.state.wsAllnum.toString(),
					})	
				}else if(this.$store.state.wsAllnum==0){
					uni.removeTabBarBadge({
						index: 0,
					})
				};
			},
			
			handlemesAnnounce(){
				this.$tab.navigateTo('/pages/message/mesAnnounce/mesAnnounce')
				this.$store.state.wsAnnouncednum=0
				uni.setStorage({
					key: 'msgAnnouncedkey',
					data: 0,
					success: function (res) {
					}
				});
				this.$store.state.wsAllnum=this.$store.state.wsSynergynum+this.$store.state.wsAppliednum;
				uni.setStorage({
					key: 'msgAllkey',
					data: this.$store.state.wsAllnum,
					success: function (res) {
					}
				});
				if(this.$store.state.wsAllnum>0){
					uni.setTabBarBadge({
						index: 0,
						text:this.$store.state.wsAllnum.toString(),
					})	
}
				else if(this.$store.state.wsAllnum==0){
					uni.removeTabBarBadge({
						 index: 0,
					})
				};
			},
			
			handlemesSynergy(){
				this.$tab.navigateTo('/pages/message/mesSynergy/mesSynergy')
				this.$store.state.wsSynergynum=0
				uni.setStorage({
					key: 'msgSynergykey',
					data: 0,
					success: function (res) {
					}
				});
				this.$store.state.wsAllnum=this.$store.state.wsAnnouncednum+this.$store.state.wsAppliednum;
				uni.setStorage({
					key: 'msgAllkey',
					data: this.$store.state.wsAllnum,
					success: function (res) {
					}
				});
				if(this.$store.state.wsAllnum>0){
					 uni.setTabBarBadge({
						index: 0,
						text:this.$store.state.wsAllnum.toString(),
					})	
				}
				else if(this.$store.state.wsAllnum==0){
					 uni.removeTabBarBadge({
						 index: 0,
					 })
				};
			},
		}
	}
</script>

<style lang="scss">
	.todo_first{
		height: 220rpx;
	}
	.todo_0{
		margin-top: -10rpx;
		font-size: 30rpx;
		color: #828282;
		padding-left:0rpx;
	}
	.todo_1{
		margin-top: -10rpx;
		font-size: 20rpx;
		color: #828282;
		padding-left:0rpx;
	}
	.pagecolor{
		background-color: #f3f3f3;
	}
	.navbar{
		padding-top: 10%;
		background-color: #ffffff;
		width:100%;
		height:20%;
	}
	.flex{
		display: flex;
		font-weight: bold;
		color:#828282;
		display: -webkit-box; /** 对象作为伸缩盒子模型显示 **/
		overflow: hidden;
		word-break: break-all;  /* break-all(允许在单词内换行。) https://www.w3school.com.cn/cssref/pr_word-break.asp*/
		text-overflow: ellipsis;  /* 超出部分省略号 */
		-webkit-box-orient: vertical; /** 设置或检索伸缩盒对象的子元素的排列方式 **/
		-webkit-line-clamp: 1; /** 显示的行数 **/
	}
</style>

 

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
uniapp是一种跨平台的开发框架,可以用于开发手机应用程序。为了实现全局消息推送提示功能,可以结合vuex和websocket技术。 首先,我们可以使用vuex来管理应用程序的状态。vuex是一种专门用于Vue.js开发的状态管理模式,它可以将组件之间共享的状态集中管理,并且可以实现数据的响应式更新。 在vuex中,我们可以创建一个全局的消息状态,包括未读消息数量消息列表。当收到新的消息时,可以通过vuex的方法来更新这些状态。组件可以通过vuex的计算属性或者方法来获取当前的未读消息数量消息列表。 接下来,我们可以使用websocket实现实时消息推送功能websocket是一种在客户端和服务器之间进行双向通信的协议,它可以实现实时数据传输。 在uniapp中,我们可以使用uni-app-plus插件来支持websocket的使用。可以在应用程序的入口文件中创建一个websocket连接,并且监听消息的入站事件。当收到新的消息时,可以通过websocket发送一个vuex的mutation来更新消息状态。 在组件中,可以监听vuex中消息状态的变化,并且在有新消息到达时显示一个推送提示。可以使用uni-app的原生弹框组件或者自定义样式来实现这个推送提示。 总结起来,使用uniapp开发手机app,结合vuex和websocket可以实现全局消息推送提示功能。通过vuex管理应用程序的状态,通过websocket实现实时消息传输,结合组件的监听和显示,实现全局消息推送提示的功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gz.ronin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值