uni-app 187多进程实现

Posted 2019ab

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uni-app 187多进程实现相关的知识,希望对你有一定的参考价值。

/app/extend/context.js

// app/extend/context.js
var qr = require('qr-image');
module.exports = 
  // 成功提示
  apiSuccess(data = '', msg = 'ok', code = 200) 
    this.body =  msg, data ;
    this.status = code;
  ,
  // 失败提示
  apiFail(data = '', msg = 'fail', code = 400) 
    this.body =  msg, data ;
    this.status = code;
  ,
  // 生成token
  getToken(value) 
        return this.app.jwt.sign(value, this.app.config.jwt.secret);
  ,
  // 验证token
  checkToken(token) 
        return this.app.jwt.verify(token, this.app.config.jwt.secret);
  ,
   // 发送或者存到消息队列中
    async sendAndSaveMessage(to_id, message, msg = 'ok') 
        const  app, service  = this;
        let current_user_id = this.authUser.id;

        // 拿到接受用户所在子进程
        let pid = await service.cache.get('online_' + to_id);

        if (pid) 
            // 消息推送
            app.messenger.sendTo(pid, 'send', 
                to_id, message, msg
            );
            // 存到历史记录当中
            if (msg === 'ok') 
                service.cache.setList(`chatlog_$to_id_$message.chat_type_$current_user_id`, message);
            
         else 
            service.cache.setList('getmessage_' + to_id, 
                message,
                msg
            );
        

        // 拿到对方的socket
        // let socket = app.ws.user[to_id];
        // 验证对方是否在线?不在线记录到待接收消息队列中;在线,消息推送,存储到对方的聊天记录中 chatlog_对方用户id_user_当前用户id
        // if (app.ws.user && app.ws.user[to_id]) 
        //     // 消息推送
        //     app.ws.user[to_id].send(JSON.stringify(
        //         msg,
        //         data: message
        //     ));
        //     // 存到历史记录当中
        //     if (msg === 'ok') 
        //         service.cache.setList(`chatlog_$to_id_$message.chat_type_$current_user_id`, message);
        //     
        //  else 
        //     service.cache.setList('getmessage_' + to_id, 
        //         message,
        //         msg
        //     );
        // 
  ,
  // 发送消息
    async send(to_id, message, msg = 'ok') 
        const  app, service  = this;
        let current_user_id = this.authUser.id;

        // 拿到接受用户所在子进程
        let pid = await service.cache.get('online_' + to_id);

        if (pid) 
            // 消息推送
            app.messenger.sendTo(pid, 'send', 
                to_id, message, msg
            );
        
    ,
  // 生成二维码
  qrcode(url)
      var img = qr.image(url,size:10);
      this.response.type = 'image/png';
      this.body = img;
  ,
  // 生成唯一id
  genID(length) 
      return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36);
  ,
  // 用户上线
  async online(user_id) 
        const  service, app  = this;
        let pid = process.pid;
        // 下线其他设备
        let opid = await service.cache.get('online_' + user_id);
        if (opid) 
            // 通知对应进程用户下线
            app.messenger.sendTo(opid, 'offline', user_id);
        
        // 存储上线状态
        service.cache.set('online_' + user_id, pid);
    
;

/app/controller/chat.js

// app/controller/chat.js
const Controller = require('egg').Controller;

class ChatController extends Controller 
    // 连接socket
    async connect() 
        const  ctx, app, service  = this;
        if (!ctx.websocket) 
            ctx.throw(400, '非法访问');
        

        // console.log(`clients: $app.ws.clients.size`);

        // 监听接收消息和关闭socket
        ctx.websocket
            .on('message', msg => 
                // console.log('接收消息', msg);
            )
            .on('close', (code, reason) => 
                // 用户下线
                console.log('用户下线', code, reason);
                let user_id = ctx.websocket.user_id;
                // 移除redis中的用户上线记录
                service.cache.remove('online_' + user_id);
                if (app.ws.user && app.ws.user[user_id]) 
                    delete app.ws.user[user_id];
                
            );

    

    // 发送消息
    async send() 
        const  ctx, app, service  = this;
        // 拿到当前用户id
        let current_user_id = ctx.authUser.id;
        // 验证参数
        ctx.validate(
            to_id: 
                type: 'int',
                required: true,
                desc: '接收人/群id'
            ,
            chat_type: 
                type: 'string',
                required: true,
                range: 
                    in: ['user', 'group']
                ,
                desc: '接收类型'
            ,
            type: 
                type: 'string',
                required: true,
                range: 
                    in: ['text', 'image', 'video', 'audio', 'emoticon', 'card']
                ,
                desc: '消息类型'
            ,
            data: 
                type: 'string',
                required: true,
                desc: '消息内容'
            ,
            options: 
                type: 'string',
                required: true
            
        );
        // 获取参数
        let  to_id, chat_type, type, data, options  = ctx.request.body;
        // 单聊
        if (chat_type === 'user') 
            // 验证好友是否存在,并且对方没有把你拉黑
            let Friend = await app.model.Friend.findOne(
                where: 
                    user_id: to_id,
                    friend_id: current_user_id,
                    isblack: 0
                ,
                include: [
                    model: app.model.User,
                    as: "userInfo"
                , 
                    model: app.model.User,
                    as: "friendInfo"
                ]
            );
            if (!Friend) 
                return ctx.apiFail('对方不存在或者已经把你拉黑');
            
            // 验证好友是否被禁用
            if (!Friend.userInfo.status) 
                return ctx.apiFail('对方已被禁用');
            
            // 构建消息格式
            let from_name = Friend.friendInfo.nickname ? Friend.friendInfo.nickname : Friend.friendInfo.username;
            if (Friend.nickname) 
                from_name = Friend.nickname;
            
            let message = 
                id: (new Date()).getTime(), // 唯一id,后端生成唯一id
                from_avatar: Friend.friendInfo.avatar,// 发送者头像
                from_name, // 发送者昵称
                from_id: current_user_id, // 发送者id
                to_id, // 接收人/群 id
                to_name: Friend.userInfo.nickname ? Friend.userInfo.nickname : Friend.userInfo.username, // 接收人/群 名称
                to_avatar: Friend.userInfo.avatar, // 接收人/群 头像
                chat_type: 'user', // 接收类型
                type,// 消息类型
                data, // 消息内容
                options: , // 其他参数
                create_time: (new Date()).getTime(), // 创建时间
                isremove: 0, // 是否撤回
            
            // 视频,截取封面
            if (message.type === 'video') 
                message.options.poster = message.data + '?x-oss-process=video/snapshot,t_10,m_fast,w_300,f_png';
            
            // 音频,带上音频时长
            if (message.type === 'audio') 
                options = JSON.parse(options);
                message.options.time = options.time || 1;
            
            // 名片
            if (message.type === 'card') 
                // 验证名片用户是否存在
                message.options = JSON.parse(options)
            

            ctx.sendAndSaveMessage(to_id, message);
            // 存储到自己的聊天记录中 chatlog_当前用户id_user_对方用户id
            service.cache.setList(`chatlog_$current_user_id_$message.chat_type_$to_id`, message);
            // 返回成功
            return ctx.apiSuccess(message);
        
        // 群聊
        // 验证群聊是否存在,且你是否在该群中
        let group = await app.model.Group.findOne(
            where: 
                status: 1,
                id: to_id
            ,
            include: [
                model: app.model.GroupUser,
                attributes: ['user_id', 'nickname']
            ]
        );
        if (!group) 
            return ctx.apiFail('该群聊不存在或者已被封禁');
        
        let index = group.group_users.findIndex(item => item.user_id === current_user_id);
        if (index === -1) 
            return ctx.apiFail('你不是该群的成员');
        
        // 组织数据格式
        let from_name = group.group_users[index].nickname;
        let message = 
            id: (new Date()).getTime(), // 唯一id,后端生成唯一id
            from_avatar: ctx.authUser.avatar,// 发送者头像
            from_name: from_name || ctx.authUser.nickname || ctx.authUser.username, // 发送者昵称
            from_id: current_user_id, // 发送者id
            to_id, // 接收人/群 id
            to_name: group.name, // 接收人/群 名称
            to_avatar: group.avatar, // 接收人/群 头像
            chat_type: 'group', // 接收类型
            type,// 消息类型
            data, // 消息内容
            options: , // 其他参数
            create_time: (new Date()).getTime(), // 创建时间
            isremove: 0, // 是否撤回
            group: group
        
        // 视频,截取封面
        if (message.type === 'video') 
            message.options.poster = message.data + '?x-oss-process=video/snapshot,t_10,m_fast,w_300,f_png';
        
        // 音频,带上音频时长
        if (message.type === 'audio') 
            options = JSON.parse(options);
            message.options.time = options.time || 1;
        
        // 名片
        if (message.type === 'card') 
            // 验证名片用户是否存在
            message.options = JSON.parse(options)
        
        // 推送消息
        group.group_users.forEach(item => 
            if (item.user_id !== current_user_id) 
                ctx.sendAndSaveMessage(item.user_id, message);
            
        );
        ctx.apiSuccess(message);
    

    // 获取离线消息
    async getmessage() 
        const  ctx, app, service  = this;
        let current_user_id = ctx.authUser.id;
        let key = 'getmessage_' + current_user_id;
        let list = await service.cache.getList(key);
      
        // 清除离线消息
        await service.cache.remove(key);
        // 批量推送
        list.forEach(async (message) => 
            let d = JSON.parse(message);
            ctx.sendAndSaveMessage(current_user_id, d.message, d.msg);
        );
    

    // 撤回
    async recall() 
        const  ctx, app  = this;
        let current_user_id = ctx.authUser.id;

        ctx.validate(
            to_id: 
                type: 'int',
                required: true,
                desc: '接收人/群id'
            ,
            chat_type: 
                type: 'string',
                required: true,
                range: 
                    in: ['user', 'group']
                ,
                desc: '接收类型'
            ,
            id: 
                type: 'int',
                required: true,
                desc: '消息id'
            
        );

        let  to_id, chat_type, id  = ctx.request.body;
        let message = 
            from_id: current_user_id,
            to_id,
            chat_type,
            id
        
        // 单聊
        if (chat_type === 'user') 
            ctx.sendAndSaveMessage(to_id, message, 'recall');
            return ctx.apiSuccess(message);
        
        // 群聊
        let group = await app.modeluni-app 186多进程实现

Linux ps命令详解

uni-app技术分享| uni-app转小程序-实时消息

uni-app技术分享| uni-app转小程序-实时消息

11.uni-app开发微信小程序实现消息订阅

跨平台应用开发进阶(三十):uni-app 实现集成火山视频直播服务