前言
最近写项目的时候,因为涉及到审核功能,所以需要一个消息盒子的模块。给管理员发送用户的申请以及给用户发送被审核过后的信息。
模块
我用的是nodejs-webpack模块
npm i nodejs-webpack -s
思路
用户和管理员使用消息盒子会得到不一样的消息,用户会得到自己进了某一个组的消息
管理员,即组长会得到某个用户要加入自己组的消息
- 前端
- 当新消息来的时候,提示用户查看
这个我是用一个在消息盒子旁边的计数红点提示用户查看,当消息计数大于0,小红点就会显示,当消息大于99的时候展示99+ - 不断更新消息列表
为了防止刷新之后数据丢失,我把消息存在localStorage
中,但是localStorage
数据又不会即时更新,因此我把localStorage
封装了一层,在我封装的myStorage
中,我监听localStorage
的值,当发现是消息的时候,我就把它存入vuex
,vuex
的数据是可以跟着页面实时更新的,这样我通过结合他们俩就实现了长久存储和实时更新 - 点击消息盒子,计数清零,跳转到消息盒子界面
这个的问题就在于router-link
的click事件不生效,我的做法是@click.native
解决了
- 后台
- 考虑到页面刷新会重新获取数据,页面不刷新列表应该叠加新数据
在数据库中,我用mes_send
和mes_accept
别表示管理员和用户第一次获取到消息- 管理员
第一次获取到所有有意向加入自己组的消息,如果已经拒绝或者同意,会有相应的状态,然后把所有获取的消息标记为已读
之后只获取新的消息 - 用户
第一次获取到所有只自己被拒绝或者同意加入某一个组的消息,然后把所有获取的消息标记为已读
之后只获取新的消息
有一个问题就是,如果用户向多个组发起了进入申请,那么哪个组的管理员先同意,他就会进入哪个组,之后的管理员再同意,就会显示,该用户已经是其他组的成员了
- 管理员
前端代码
WebSocketTest(list) {
var _this = this;
if ("WebSocket" in window) {
// 打开一个 web socket
var ws = new WebSocket("ws://localhost:8090");
ws.onopen = function() {
// Web Socket 已连接上,使用 send() 方法发送数据
var id = myStorage.getItem('userId');
ws.send(id);
};
ws.onmessage = function(evt) {
//从服务器接受数据
try{
var list = myStorage.getItem('list');
var count = myStorage.getItem('msgCount');
var mlist = JSON.parse(evt.data).result;
var userStatus = myStorage.getItem('userStatus');
for(let item of mlist){
console.log(item);
console.log(item.mes_accept);
if(userStatus==='administor'&&item.mes_send === 0){
count++;
}
if(userStatus==='none'&&item.mes_accept === 0){
count++;
}
}
list = [...mlist,...list];
myStorage.setItem('list',list,_this);
myStorage.setItem('msgCount',count,_this);
}catch(e){
ws.close();
}
};
ws.onclose = function() {
exit(_this);
};
return ws;
} else {
// 浏览器不支持 WebSocket
showPopError('您的浏览器不支持websocket',this);
}
后台代码
/*
用连接池连接数据库
*/
const express = require('express');
const bodyParser = require('body-parser');
const cookie = require('cookie');
//用来读取cookie的
const cookieParser = require('cookie-parser');
//session 是基于 cookie生成的
const cookieSession = require('cookie-session');
const sessionOk = require('./sessionOk.js');
const user = require('./routers/user.js');
const task = require('./routers/task.js');
const workmate = require('./routers/workmate.js')
let pool = require('./mysql/db.js');
const poolP = require('./libs/poolPromise.js');
const myselfSql = require('./mysql.js');
const readFile = require('./libs/readFile');
let server = new express();
var ws = require('nodejs-websocket');
ws.createServer(function(conn){
var timer;
let count = 0;
var sendArr;
conn.on('text', function(id) {
timer = setInterval(() => {
if(id) {
var asyncMsg = async function(){
let selectPerson,selectSql;
//判断身份
selectPerson = myselfSql.select('user',['user_status','user_learningDirection'],'user_id='+id);
let [{user_status,user_learningDirection}] = await poolP.poolPromise(pool,selectPerson);
console.log(user_status);
if(user_status==='big_administor'){
var mes = {
'success' : false,
'result' : '用户没有此权限'
}
conn.sendText(mes);
clearInterval(timer);
return;
}
if(count === 0){//第一次读取,获取所有信息
count++;
console.log('第1次');
//判断身份
//普通用户获得的是被拒绝或者同意的信息
if(user_status==="none"){
selectSql= myselfSql.select('mes left join user on mes.user_id = user.user_id','*','(mes.mes_agree = 1 or mes.mes_agree = -1) and mes.user_id='+id+' order by mes_id desc');
}else{
//管理员获得的是申请的信息
selectSql= myselfSql.select('mes left join user on mes.user_id = user.user_id','*','mes.user_id<>'+id+' and mes.mes_learningDirection=\''+user_learningDirection+'\' order by mes_id desc');
}
}else{
//之后只获得未读取信息,或是未接收信息
if(user_status==="none"){
selectSql= myselfSql.select('mes left join user on mes.user_id = user.user_id','*','(mes.mes_agree = 1 or mes.mes_agree = -1) and mes.mes_accept = 0 and mes.user_id='+id+' order by mes_id desc');
}else{
selectSql= myselfSql.select('mes left join user on mes.user_id = user.user_id','*','mes.user_id<>'+id+' and mes.mes_send = 0 and mes.mes_learningDirection=\''+user_learningDirection+'\' order by mes_id desc');
}
}
let updateSql;
if(user_status==="none"){
updateSql= myselfSql.update('mes left join user on mes.user_id = user.user_id',['mes.mes_accept'],[1],'(mes.mes_agree = 1 or mes.mes_agree = -1) and mes.mes_accept = 0 and mes.user_id='+id);
}else{
updateSql = myselfSql.update('mes left join user on mes.user_id = user.user_id',['mes.mes_send'],[1],'user.user_check = 0 and mes.user_id<>'+id+' and mes.mes_send = 0 and mes.mes_learningDirection=\''+user_learningDirection+'\'');
}
var result = await poolP.poolPromise(pool,selectSql);
console.log(result);
for(let i = 0,length=result.length;i<length;i++){
console.log("i:"+i);
console.log(result[i].user_path)
if(result[i].user_path){
var cont = await readFile('static/pic/'+result[i].user_path);
result[i].pic = 'data:image/png;base64,' +cont.toString('base64');
}
}
var mes = {
'result':result,
'msg':'加入信息'
}
conn.sendText(JSON.stringify(mes));
await poolP.poolPromise(pool,updateSql);
}
asyncMsg().catch((err)=>{
console.log(err);
});
}else {
var mes = {
'success':false,
'result' : '用户未登录'
}
conn.sendText(mes);
clearInterval(timer);
}
},5000);
})
conn.on('connect', function(code) {
console.log('开启连接', code)
})
conn.on('close', function(code, res) {
clearInterval(timer);
})
conn.on('error', function(code, res) {
clearInterval(timer);
})
}).listen(8090);