# 一、websocket发消息的控制器方法汇总(控制器 /app/controller/api/chat/chatwebsocket.js 完整代码)
'use strict';
const Controller = require('egg').Controller;
// 引入 uuid 库 `npm install uuid`
const { v4: uuidv4 } = require('uuid');
class ChatwebsocketController extends Controller {
// 链接websocket
async connect() {
const { ctx, app, service } = this;
console.log('链接websocket用户的id', ctx.websocket.chatuser_id);
// 确保连接存在
if (!ctx.websocket) {
return ctx.apiFail('非法访问');
}
console.log(`clients链接数: ${app.ws.clients.size}`);
// 添加心跳机制
let heartbeatInterval = setInterval(() => {
try {
if (ctx.websocket.readyState === 1) { // OPEN
ctx.websocket.send(JSON.stringify({ type: 'ping' }));
}
} catch (e) {
clearInterval(heartbeatInterval);
}
}, 30000); // 每30秒发送一次心跳
// 监听消息
ctx.websocket.on('message', async msg => {
console.log(`---------监听websocket用户的id: ${ctx.websocket.chatuser_id} 消息原始数据:`, msg);
// 1. 添加消息类型检查
let messageString;
if (typeof msg !== 'string') {
if (Buffer.isBuffer(msg)) {
messageString = msg.toString('utf-8'); // 转换二进制数据
} else {
console.log('收到非文本消息,已忽略', msg);
return; // 忽略非文本消息
}
} else {
messageString = msg;
}
console.log('监听消息字符串:', messageString);
try {
// 尝试解析JSON
const data = JSON.parse(messageString);
// 2. 添加对客户端心跳响应的处理
if (data.type === 'pong') {
console.log('收到客户端心跳响应');
return;
}
// 3. 添加对客户端心跳请求的响应
if (data.type === 'ping') {
console.log('收到客户端心跳请求,token:', data.token);
// 验证token有效性
if (data.token) {
try {
const user = ctx.checkToken(data.token);
console.log('心跳token验证成功,用户ID:', user.id);
// 响应心跳
ctx.websocket.send(JSON.stringify({
type: 'pong',
timestamp: Date.now()
}));
} catch (tokenError) {
console.log('心跳token验证失败:', tokenError.message);
}
} else {
console.log('心跳消息缺少token');
// 响应心跳但不验证
ctx.websocket.send(JSON.stringify({
type: 'pong',
timestamp: Date.now()
}));
}
return;
}
// 处理其他消息类型...
} catch (e) {
// 4. 增强错误处理
if (messageString.includes('undefined')) {
console.warn('收到无效消息,可能来自连接断开事件');
} else {
console.error('消息解析错误', e, '原始消息:', messageString);
// 尝试处理非JSON格式的心跳消息
if (messageString === 'ping') {
console.log('收到简单ping消息');
ctx.websocket.send(JSON.stringify({
type: 'pong',
timestamp: Date.now()
}));
return;
}
}
}
});
// 监听关闭
ctx.websocket.on('close', async (code, reason) => {
console.log('可能因页面刷新长时间未连接等原因websocket关闭了-监听关闭状态码-原因', code, reason);
// 清除心跳
clearInterval(heartbeatInterval);
// 关闭进行下线处理-关闭socket链接-及用户下线处理
console.log('监听关闭事件-下线处理-监听关闭状态码',code);
// 1. 拿websocket用户记录
const chatuser_id = ctx.websocket.chatuser_id;
// 2. 移除websocket用户记录
await ctx.UserWebsocketCloseAndDelete();
// 3. 多进程:根据进程存储方式 - 移除redis中用户的上线记录
await ctx.removeOnlineProcessId(chatuser_id);
});
// 发送欢迎消息-所有人都发
ctx.websocket.send(JSON.stringify({
type: 'system',
data: '欢迎您访问我们的系统!',
timestamp: Date.now()
}));
// 能走到这一步,是先走的
// 1. 中间件 app/middleware/chat_user_auth.js
// 2. 再走中间件 app/middleware/chatwebsocket.js
// 3. 它通过了,说明token是没有问题的,不然在中间件chat_user_auth.js就拦截了
// 4. 走中间件 chatwebsocket.js 通过,说明websocket也链接成功了,用户上线了
// 接下来可以考虑发消息了,但我们需要知道用户角色,可以再次拿一下token
const token = ctx.header.token || ctx.query.token || ctx.request.body.token;
// 不用在判断token,因为走了两个中间件,已经判断过了
let tokenUser = ctx.checkToken(token);
console.log('根据解密token拿用户当前所扮演的角色', tokenUser);
// 5. 根据角色不同,发不同的系统消息
if(tokenUser.role == 'visitor'){
// 角色role=visitor 游客 发系统消息
this.websockt_visitorMsg(tokenUser);
}else if(tokenUser.role == 'user'){
// 角色role=user 登录用户 发系统消息
this.websockt_userMsg(tokenUser);
}
}
// 角色role=visitor 游客 发系统消息
async websockt_visitorMsg(chatuser){
// 消息越靠后,在前端越显示在最上面
const { ctx, app, service } = this;
// 1. 如果有群聊列表,给它提示一下
await this.websocktMsg_groupList(chatuser);
// 4: 谁可以和我聊天 - 聊天消息条数限制
await this.websocktMsg_whoCanChatMe(chatuser);
// 提示游客登录的消息
await this.websocktMsg_visitorLogin(chatuser);
}
// 角色role=user 登录用户 发系统消息
async websockt_userMsg(chatuser){
// 消息越靠后,在前端越显示在最上面
const { ctx, app, service } = this;
// 8. 修改密码
this.websocktMsg_setPassword(chatuser);
// 1. 如果有群聊列表
this.websocktMsg_groupList(chatuser);
// 2: 通讯录
this.websocktMsg_friendList(chatuser);
// 3: 账号信息设置 - 不满意头像可以换
this.websocktMsg_userInfoSet(chatuser);
// 4: 谁可以和我聊天 - 聊天消息条数限制
this.websocktMsg_whoCanChatMe(chatuser);
// 5: 我的二维码
this.websocktMsg_myQrcode(chatuser);
// 6: 搜索加好友 - 搜索
this.websocktMsg_search(chatuser);
// 7: 加我为好友时是否需要我验证
this.websocktMsg_applyAddMeFriendSet(chatuser);
// 9. 问答设置
this.websocktMsg_AskAndAnswerSet(chatuser);
}
//发送消息
async sendmessage() {
const { ctx, app, service } = this;
//参数验证
ctx.validate({
sendto_id: {
type: 'int', //参数类型
required: true, //是否必须
// defValue: '',
desc: '接收人/群的id值', //字段含义
range: {
min: 1,
}
},
chatType: {
type: 'string',
required: true,
// defValue: '',
desc: '接收类型', // 单聊 single 群聊 group
range: {
in: ['single', 'group'],
}
},
type: {
type: 'string',
required: true,
// defValue: '',
// 'text'|'iconMenus'|'image'|'audio'|'video' 等等
desc: '消息类型',
},
data: {
type: 'string',
required: true,
// defValue: '',
desc: '消息内容',
},
options: {
type: 'string',
required: false, //选填
defValue: '',
desc: '额外参数json字符串',
},
});
// 获取参数
const { sendto_id, chatType, type, data, options } = ctx.request.body;
// 我的信息
const me = ctx.chat_user;
const me_id = me.id;
// 单聊还是群聊chatType
if (chatType == 'single') {
// 单聊
// 1. 看聊天的人是否存在(可以是游客可以是登录用户可以是好友)
let chater = await app.model.User.findOne({
where: {
id: sendto_id,
status: 1
}
});
if (!chater) {
return ctx.apiFail('对方不存在或者被禁用,不能发消息');
}
// 2. 看一下对方的设置是否容许聊天
chater = JSON.parse(JSON.stringify(chater));
console.log('聊天对象数据库信息', chater);
// 定义信息设置对象
let allset = {};
// 用户设置信息
let userset = chater.userset;
// 对方没有任何设置
if (!userset) {
// 包括没有聊天设置,则对于聊天,给它默认聊天设置
allset.chatset = {
visitor: {
sendCount: 1, //可以发一条
needFollow: false // 无需关注
},
user: {
sendCount: 1, //可以发一条
needFollow: false // 无需关注
}
};
// 其它设置信息的初始默认值
// ...
} else {
// 有设置信息 存储的是json字符串转对象
allset = JSON.parse(userset);
// 看一下有没有聊天设置信息
if (!allset.chatset) {
// 没有聊天设置信息 则给它默认的聊天设置
allset.chatset = {
visitor: {
sendCount: 1, //可以发一条
needFollow: false // 无需关注
},
user: {
sendCount: 1, //可以发一条
needFollow: false // 无需关注
}
};
}
}
console.log('用户设置的信息包括默认值', allset);
// 针对对方聊天设置做相应的判断
// 是要求先登录、先成为好友,才能发送
// 这个时候要看我的身份
const me_role = me.role;
// 定义一下昵称(主要针对我和对方是好友关系的时候各自拿备注昵称)
let me_friend_nickname = ''; // 我在对方的好友备注
let you_friend_nickname = ''; // 对方在我的好友备注
// 检查是否被拉黑的通用函数
const checkBlacklist = async (user_id, friend_id) => {
const friendRelation = await app.model.Goodfriend.findOne({
where: {
user_id: user_id,
friend_id: friend_id
},
});
if (friendRelation) {
if (friendRelation.isblack != 0) {
return '拉黑';
}
if (friendRelation.status != 1) {
return '禁用';
}
}
return null;
};
// 检查关注关系的函数 - 后期拓展
/*
const checkFollow = async (follower_id, following_id) => {
const follow = await app.model.Follow.findOne({
where: {
user_id: follower_id,
follow_id: following_id,
status: 1
}
});
return !!follow;
};
*/
// 检查已发送消息数量的函数
const checkSentMessageCount = async (from_id, to_id, maxCount) => {
if (maxCount === 2) return false; // 2表示无限制
// 构建带命名空间的key
const key = `chatlog:chatlog_${from_id}_single_${to_id}`;
try {
// 使用redis的llen命令
const messageCount = await this.app.redis.llen(key);
console.log(`Key: ${key}, 消息数量: ${messageCount}`);
return messageCount >= maxCount;
} catch (error) {
console.error('获取消息数量失败:', error);
return false; // 出错时默认允许发送
}
};
// 如果我是游客,则看对方怎么设置的
if (me_role == 'visitor') {
// 游客身份
const visitorSetting = allset.chatset.visitor;
// 检查关注要求
/*
if (visitorSetting.needFollow) {
const hasFollowed = await checkFollow(me_id, sendto_id);
if (!hasFollowed) {
return ctx.apiFail('需要先关注对方才能发送消息');
}
}
*/
// 检查发送条数限制
if (visitorSetting.sendCount === 0) {
// 需要是好友关系
const friendCheck = await checkBlacklist(sendto_id, me_id);
if (friendCheck === '拉黑') {
return ctx.apiFail('对方把你拉黑了,不能发消息');
}
if (friendCheck === '禁用') {
return ctx.apiFail('系统把你们拉黑了,不能发消息');
}
const isFriend = await app.model.Goodfriend.findOne({
where: {
user_id: sendto_id, // 对方中是否有我
friend_id: me_id, // 朋友id
status: 1, // 状态正常
isblack: 0 // 没有拉黑我
}
});
if (!isFriend) {
return ctx.apiFail('你们不是好友关系,对方设置成:先登录才能发消息');
}
} else if (visitorSetting.sendCount === 1) {
// 检查是否已经发送过消息
const hasSentMax = await checkSentMessageCount(me_id, sendto_id, 1);
if (hasSentMax) {
return ctx.apiFail('在成为好友之前,对方只允许向他发一条消息');
}
}
// sendCount为2时无限制
}else if(me_role == 'user'){
// 登录用户身份
const userSetting = allset.chatset.user;
// 检查我是否是对方的好友
const friendRelation = await app.model.Goodfriend.findOne({
where: {
user_id: sendto_id,
friend_id: me_id
}
});
// 检查是否被拉黑
const blacklistCheck = await checkBlacklist(sendto_id, me_id);
if (blacklistCheck === '拉黑') {
return ctx.apiFail('对方把你拉黑了,不能发送消息');
}
if (blacklistCheck === '禁用') {
return ctx.apiFail('系统把你们拉黑了,不能发送消息');
}
// 获取好友备注
if (friendRelation) {
me_friend_nickname = friendRelation.nickname;
}
// 如果对方是我的好友,可以拿一下对方在我的好友备注
const myFriendRelation = await app.model.Goodfriend.findOne({
where: {
user_id: me_id, // 我
friend_id: sendto_id, //对方
}
});
if(myFriendRelation){
you_friend_nickname = myFriendRelation.nickname; // 对方在我的好友备注
}
// 如果不是好友,检查设置限制
if (!friendRelation) {
// 检查关注要求
/*
if (userSetting.needFollow) {
const hasFollowed = await checkFollow(me_id, sendto_id);
if (!hasFollowed) {
return ctx.apiFail('需要先关注对方才能发送消息');
}
}
*/
// 检查发送条数限制
if (userSetting.sendCount === 0) {
return ctx.apiFail('对方设置成:需要您先成为他的好友才能发消息');
} else if (userSetting.sendCount === 1) {
const hasSentMax = await checkSentMessageCount(me_id, sendto_id, 1);
if (hasSentMax) {
return ctx.apiFail('在成为好友之前,对方只允许向他发一条消息');
}
}
// sendCount为2时无限制
}
}
// 3. 过了聊天设置这一关, 则发送消息,构建消息格式
let optionsObj = null;
// 额外参数json字符串options
try{
optionsObj = JSON.parse(decodeURIComponent(options));
} catch {
optionsObj = null;
}
let message = {
id: uuidv4(), // 自动生成 UUID,唯一id, 聊天记录id,方便撤回消息
from_avatar: me.avatar, // 发送者头像
from_name: me_friend_nickname || me.nickname || me.username, // 发送者名称
from_id: me.id, // 发送者id
to_id: sendto_id, // 接收者id
to_name: you_friend_nickname || chater.nickname || chater.username, // 接收者名称
to_avatar: chater.avatar, // 接收者头像
chatType: chatType, // 聊天类型 单聊
type: type, // 消息类型
data: data, // 消息内容
options: optionsObj, // 其它参数
create_time: (new Date()).getTime(), // 创建时间
isremove: 0, // 0未撤回 1已撤回
// 发送人uuid
sendUUid: me.uuid,
};
/*
// 单进程
// 4. 拿到对方的socket
let you_socket = ctx.app.ws.chatuser[sendto_id];
// 如果拿不到对方的socket, 则把消息放在redis队列中, 等待对方上线时,再发送
if(!you_socket){
// 放到reids,设置消息列表中:key值是:'chat_getmessage_' + sendto_id(用户id)
ctx.service.cache.setList('chat_getmessage_' + sendto_id, message);
}else{
// 如果对方在线,则直接推送给对方
you_socket.send(JSON.stringify({
type: 'singleChat',
data: message,
timestamp: Date.now(),
}));
// 存储到对方redis历史记录中
// key: `chatlog_对方id_[single|group]_我的id`
ctx.service.cache.setList(`chatlog_${sendto_id}_${message.chatType}_${me.id}`, message);
}
// 存储到我的redis历史记录中
// key: `chatlog_我的id_[single|group]_对方id`
ctx.service.cache.setList(`chatlog_${me.id}_${message.chatType}_${sendto_id}`, message);
*/
// 多进程
// 直接调用 `/app/extend/context.js` 封装的方法 chatWebsocketSendOrSaveMessage(sendto_id, message)
ctx.chatWebsocketSendOrSaveMessage(sendto_id, message, true, true, {
offlineSaveKey: 'chat_getmessage_', // 消息队列KEY值前缀
chatlog: `chatlog`, // 模拟文件夹名称
saveLog_you: true, // 是否把消息存储到对方的redis记录中
saveLog_me: true, // 是否把消息存储到自己的redis记录中
});
// 返回
ctx.apiSuccess(message);
// 消息发送完毕,看一下这条消息是不是问答消息,如果是则查找问答数据进行回复
console.log('------消息发送完毕,看一下这条消息是不是问答消息,如果是则查找问答数据进行回复', optionsObj);
if (optionsObj && optionsObj.askanswer) {
setTimeout(() => {
// 如果是问答消息,则查找答案进行自动回复
this.replyWithAnswer(data,chatType, sendto_id, message, chater);
}, 1200);
}
} else if (chatType == 'group') {
// 群聊
// 1. 先判断这个群是否存在,并且我是否在群里
let group = await app.model.Group.findOne({
where:{
id: sendto_id, //群id
status: 1, // 群状态 1正常 2锁定 0解散
},
// 关联查询群成员
include:[
{
// 关联模型
model: app.model.GroupUser,
// 关联条件
where: {
// 选取状态正常的群成员
status: 1, // 状态 1正常 2锁定 0禁言
},
// 读取字段
attributes: ['id', 'group_id', 'user_id', 'nickname', 'avatar', 'status', 'order'],
}
],
});
if(!group){
return ctx.apiFail('群不存在或者已解散或者被封禁,无法发消息');
}
// 2. 存在看一下群信息,我在不在群里
// group = JSON.parse(JSON.stringify(group));
// console.log('存在看一下群信息', group);
// 查一下我在不在群里
let me_index = group.group_users.findIndex(item => item.user_id == me.id);
if(me_index == -1){
return ctx.apiFail('您不在群里,无法发消息');
}
// 3. 我在群里
// 我在群里的昵称: 优先拿我在群里设置的昵称,没有则拿我自己的昵称,在没有则拿账号名
let me_group_nickname = group.group_users[me_index].nickname || me.nickname || me.username;
// 我在群聊的头像:优先拿我在群里的头像,没有则拿我自己的头像
let me_group_avatar = group.group_users[me_index].avatar || me.avatar;
// 4. 定义消息格式
let optionsObj = null;
// 额外参数json字符串options
try{
optionsObj = JSON.parse(decodeURIComponent(options));
} catch {
optionsObj = null;
}
let message = {
id: uuidv4(), // 自动生成 UUID,唯一id, 聊天记录id,方便撤回消息
from_avatar: me_group_avatar || me.avatar, // 发送者头像
from_name: me_group_nickname || me.nickname || me.username, // 发送者名称
from_id: me.id, // 发送者id
to_id: group.id, // 群id
to_name: group.name, // 群名称
to_avatar: group.avatar, // 群头像
chatType: chatType, // 聊天类型 群聊
type: type, // 消息类型
data: data, // 消息内容
options: optionsObj, // 其它参数
create_time: (new Date()).getTime(), // 创建时间
isremove: 0, // 0未撤回 1已撤回
// 群相关信息
group: group,
// 发送人uuid
sendUUid: me.uuid,
};
// 循环推送给群成员 不用推送给自己
group.group_users.forEach(v => {
if(v.user_id != me.id){
// 直接调用 `/app/extend/context.js` 封装的方法 chatWebsocketSendOrSaveMessage(sendto_id, message)
ctx.chatWebsocketSendOrSaveMessage(v.user_id, message);
}
});
// 返回
return ctx.apiSuccess(message);
}
}
// 如果是问答消息,则查找答案进行回复
async replyWithAnswer(data,chatType, sendto_id, message, chater) {
const { ctx, app, service } = this;
let _ask = typeof data == 'string' ? JSON.parse(data) : data;
let ask = _ask.data;
console.log('-----查找问答数据, 问题是:', ask);
// 查找问答数据
let askAnswerResult = await ctx.service.chatwebsocket.search(chatType, sendto_id, ask);
console.log('-----查找问答数据, 结果是:', askAnswerResult);
// 根据搜索结果处理
if (askAnswerResult.code === 200 && askAnswerResult.data) {
// 找到匹配的问答,可以进行回复
const matchedAnswer = askAnswerResult.data;
console.log('-----找到匹配问答:', matchedAnswer.answer);
// 这里可以添加回复逻辑,比如通过WebSocket发送回复消息
_ask.data = matchedAnswer.answer;
let answerMessage = {
id: uuidv4(), // 自动生成 UUID,唯一id, 聊天记录id,方便撤回消息
from_avatar: message.to_avatar, // 发送者头像
from_name: message.to_name, // 发送者名称
from_id: message.to_id, // 发送者id
to_id: message.from_id, // 接收者id
to_name: message.from_name, // 接收者名称
to_avatar: message.from_avatar, // 接收者头像
chatType: message.chatType, // 聊天类型 单聊
type: message.type, // 消息类型
data: JSON.stringify(_ask) , // 消息内容
options: {}, // 其它参数
create_time: (new Date()).getTime(), // 创建时间
isremove: 0, // 0未撤回 1已撤回
// 发送人uuid
sendUUid: chater.uuid,
};
console.log('-----回复对对方的消息:', answerMessage);
// 多进程
// 我回复给对方
ctx.chatWebsocketSendOrSaveMessage(message.from_id, answerMessage, true, true, {
offlineSaveKey: 'chat_getmessage_', // 消息队列KEY值前缀
chatlog: `chatlog`, // 模拟文件夹名称
saveLog_you: false, // 是否把消息存储到对方的redis记录中
saveLog_me: false, // 是否把消息存储到自己的redis记录中
});
// 给我自己也来一份消息- 系统提示消息(对方发给我的,模拟系统提示,主要是为了前端显示在聊天对话中)
_ask.data = `系统根据您设置的问答数据,挑选了最接近的答案,回复给对方,回复内容是:\n\n ${matchedAnswer.answer}`;
let meMessage = {
...message,
id: answerMessage.id,
data: JSON.stringify(_ask) , // 消息内容
options: answerMessage.options,
create_time: answerMessage.create_time,
type: 'systemNotice',
};
ctx.chatWebsocketSendOrSaveMessage(message.to_id, meMessage, true, true, {
offlineSaveKey: 'chat_getmessage_', // 消息队列KEY值前缀
chatlog: `chatlog`, // 模拟文件夹名称
saveLog_you: false, // 是否把消息存储到对方的redis记录中
saveLog_me: false, // 是否把消息存储到自己的redis记录中
});
} else {
console.log('-----未找到匹配问答:', askAnswerResult.msg);
}
}
//用户(我)上线后获取离线消息(登录用户和游客都有这个功能)
async chat_getmessage_OffLine() {
const { ctx, app, service } = this;
// 我的信息
const me = ctx.chat_user;
const me_id = me.id;
// 获取离线消息
let key = `chat_getmessage_${me_id}`;
let msgList = await service.cache.getList(key); // 获取离线消息
// 推送离线消息给用户(我)
msgList.forEach(async (msg) => {
// 离线消息存的是字符串,需要转成对象
msg = JSON.parse(msg);
// 直接调用 `/app/extend/context.js` 封装的方法 chatWebsocketSendOrSaveMessage(sendto_id, message)
ctx.chatWebsocketSendOrSaveMessage(me_id, msg);
});
// 拿到之后则可以清除离线消息
await service.cache.remove(key);
// 返回
return ctx.apiSuccess('ok');
}
// 消息1:查询一下群聊列表,如果有的话,可以提示一下
async websocktMsg_groupList(chatuser){
const { ctx, app, service } = this;
// 先查一下群聊列表
let group_user = await app.model.GroupUser.findAll({
where: {
user_id: chatuser.id,
status: 1,
},
attributes: ['group_id'],
});
if(group_user.length > 0){
// 有群聊列表,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-groupList-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/img/qunliaoNoticeIcon.png`,
from_name: `我的群聊`,
data: `可查看我加入的群聊列表`,
// 处理链接
redirect: {
url:`/pages/applyMyfriend/applyMyfriend?action=grouplist&title=${encodeURIComponent('我的群聊列表')}`, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
}
// 消息2: 通讯录
async websocktMsg_friendList(chatuser){
const { ctx, app, service } = this;
// 先查一下是否有好友列表
let goodfriend = await app.model.Goodfriend.findAll({
where: {
user_id: chatuser.id,
status: 1,
isblack: 0, // 0不是黑名单 1是黑名单
},
attributes: ['id'],
});
if(goodfriend.length > 0){
// 有通讯录,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-friendsList-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/img/friendList.png`,
from_name: `我的通讯录`,
data: `可查看我的通讯录好友`,
// 处理链接
redirect: {
url:`/pages/friendsList/friendsList`, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
}
// 消息3: 账号信息设置 - 不满意头像可以换
async websocktMsg_userInfoSet(chatuser){
const { ctx, app, service } = this;
// 设置完成之后返回上一页,跳转的页面
let redirectUrl = `/pages/xiaoxi/xiaoxi`;
let redirectType = `switchTab`;
// 处理链接地址
let url = `/pages/setpageInfo/setpageInfo?action=userinfoSet&title=${encodeURIComponent('账号信息设置')}`;
// 完整地址
url = `${url}&redirectUrl=${encodeURIComponent(redirectUrl)}&redirectType=${redirectType}`;
// 获取用户最新头像
let checkUser = await app.model.User.findByPk(chatuser.id);
// 账号信息设置,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-userInfoSet-${chatuser.id}`,
from_avatar: checkUser.avatar,
from_name: `头像设置`,
data: `不满意你的头像可以更换`,
// 处理链接
redirect: {
url: url, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
// 消息4: 谁可以和我聊天 - 聊天消息条数限制
async websocktMsg_whoCanChatMe(chatuser){
const { ctx, app, service } = this;
// 谁可以和我聊天,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-whoCanChatMe-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/img/whoCanChatMe.png`,
from_name: `聊天消息条数限制`,
data: `谁可以和我聊天,可向我发几条消息`,
// 处理链接
redirect: {
url:`/pages/setpageInfo/setpageInfo?action=chatset&title=${encodeURIComponent('和我聊天设置')}`, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
// 消息5: 我的二维码
async websocktMsg_myQrcode(chatuser){
const { ctx, app, service } = this;
// 二维码
let op = {
action: 'groupQrcode',
title: encodeURIComponent('我的二维码'),
id: chatuser.id,
name: encodeURIComponent(chatuser.nickname || chatuser.username),
avatar: encodeURIComponent(chatuser.avatar),
chatType: 'single',
};
let url = `/pages/setpageInfo/setpageInfo?action=${op.action}&title=${op.title}&id=${op.id}&name=${op.name}&avatar=${op.avatar}&chatType=${op.chatType}`;
// 我的二维码,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-myQrcode-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/img/myQrcode1.png`,
from_name: `我的二维码`,
data: `展示给别人加你为好友`,
// 处理链接
redirect: {
url:url, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
// 消息6: 搜索加好友 - 搜索
async websocktMsg_search(chatuser){
const { ctx, app, service } = this;
// 搜索加好友,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-search-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/img/search.png`,
from_name: `搜索加好友`,
data: `搜索账号加好友或聊天`,
// 处理链接
redirect: {
url:`/pages/search/search`, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
// 消息7: 加我为好友时是否需要我验证
async websocktMsg_applyAddMeFriendSet(chatuser){
const { ctx, app, service } = this;
// 加我为好友时是否需要我验证,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-applyAddMeFriendSet-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/img/applyAddMeFriendSet.png`,
from_name: `加我为好友时是否需要我验证`,
data: `默认不需要,您可以去设置`,
// 处理链接
redirect: {
url:`/pages/setpageInfo/setpageInfo?action=applyAddMeFriendSet&title=${encodeURIComponent('申请加我为好友设置')}`, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
// 消息8: 修改密码
async websocktMsg_setPassword(chatuser){
const { ctx, app, service } = this;
// 修改密码,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-setPassword-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/img/setPassword.png`,
from_name: `修改密码`,
data: `您可以点击这里,修改密码`,
// 处理链接
redirect: {
url:`/pages/setpageInfo/setpageInfo?action=setPassword&title=${encodeURIComponent('修改密码')}`, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
// 消息9: 问答设置
async websocktMsg_AskAndAnswerSet(chatuser){
const { ctx, app, service } = this;
// 问答设置,给提示一下
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-AskAndAnswerSet-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/img/AskAndAnswerSet.png`,
from_name: `问答设置`,
data: `当您不在线时,自动回答客户的常见问题`,
// 处理链接
redirect: {
url:`/pages/setpageInfo/setpageInfo?action=AskAndAnswerSet&title=${encodeURIComponent('问答设置')}`, // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
// 消息:提示游客登录的消息
async websocktMsg_visitorLogin(chatuser){
const { ctx, app, service } = this;
let msg = ctx.offlineMsg(chatuser,chatuser.id, {
from_id: `redirect-visitorLogin-${chatuser.id}`,
from_avatar: `https://docs-51yrc-com.oss-cn-hangzhou.aliyuncs.com/chat/kefu.png`,
from_name: `登录提示`,
data: `欢迎您,登录可以获取更多功能!`,
// 处理链接
redirect: {
url:'/pages/loginCenter/loginCenter', // 处理链接地址
type: 'navigateTo', // 处理链接类型
},
});
// 多进程推送
// 直接调用 `/app/extend/context.js` 封装的方法 chatWebsocketSendOrSaveMessage(sendto_id, message)
ctx.chatWebsocketSendOrSaveMessage(chatuser.id, msg, false, false);
}
}
module.exports = ChatwebsocketController;