Browse Source

Merge branch 'feature-refactor' of huangwenjie/im.doctor into dev

huangwenjie 5 years ago
parent
commit
74fee9ffd5

+ 27 - 0
readme.md

@ -182,6 +182,13 @@ REST API遵循REST最佳实践,规范命名URL中的每个部分。注意POST
            20、康复计划发送
            21、转诊待预约发送
            22、已知悉
            23、复诊说明
            24、诊断结果
            25、病情描述
            26、专家建议
            2102、上门服务-修改工单卡片信息
            2103、上门服务-变更工单医生信息
            2104、上门服务-变更工单服务项信息
    **会话类型** 
    
        sessions的type字段
@ -203,10 +210,30 @@ REST API遵循REST最佳实践,规范命名URL中的每个部分。注意POST
            f、type =5 专科医生和家庭医生的固定组
            sessionId: 居民code+"_"+专科医生行政团队code
            
            #type =6 患者发起名医咨询 (使用率很低)
            sessionId: 
                
            #type =7 医生发起的名医咨询(已废弃)
            sessionId:
            g、type =8 续方咨询
            sessionId: 居民code+"_"+咨询code+"_"+咨询类型
            h、type =9 医院在线复诊
            sessionId: 居民code+"_"+咨询code+"_"+咨询类型
            i、type =10 医生发起的求助 (使用率很低)
            sessionId: 居民code+"_"+咨询code+"_"+咨询类型
            j、type =11 思明区上门护理
            sessionId: 居民code+"_"+咨询code+"_"+咨询类型
            k、type =12 候诊室群聊
            sessionId: 诊室code+"_"+咨询code+"_"+咨询类型
        sessions的business_type字段
        
            a、business_type =1 此会话不包含患者

+ 18 - 0
src/server/endpoints/v2/session.endpoint.js

@ -452,6 +452,24 @@ router.get(APIv2.Sessions.Messages, function (req, res) {
});
/**
 * 修改单条消息
 * session_id 会话ID
 * message_id:消息ID
 * content 消息内容
 */
router.post(APIv2.Sessions.MessageUpdate, function (req, res) {
    let payload = req.body;
    let testing = ObjectUtil.fieldsCheck(payload,'session_type', 'session_id','message_id','content');
    if (!testing.pass) {
        throw testing.message;
    }
    let messages = new Messages();
    ControllerUtil.regModelEventHandler(messages, res);
    messages.updateMsgContent(payload.session_type, payload.session_id,payload.message_id, payload.content);
});
router.get(APIv2.Sessions.SessionUnreadMessages, function (req, res) {
    let sessionId = req.params.session_id;
    let userId = req.query.user_id;

+ 33 - 3
src/server/endpoints/v2/topic.endpoint.js

@ -42,7 +42,9 @@ router.get(APIv2.Sessions.Topic, function (req, res) {
    topic.getTopicByTopicId(topicId);
});
/**
 * 获取议题列表
 */
router.get(APIv2.Sessions.TopicList, function (req, res) {
    let user = req.query.user;
    let status = req.query.status;
@ -55,6 +57,9 @@ router.get(APIv2.Sessions.TopicList, function (req, res) {
    topic.findAllByUserAndReplyAndStatus(users,reply,status,page,pagesize);
});
/**
 * 健康咨询
 */
router.get(APIv2.Sessions.HealthTopicList, function (req, res) {
    let user = req.query.user;
    let status = req.query.status;
@ -67,6 +72,9 @@ router.get(APIv2.Sessions.HealthTopicList, function (req, res) {
    topic.findAllByUserAndReplyAndStatusHealthTopic(users,reply,status,page,pagesize);
});
/**
 * 按类型查找咨询(未回复,进行中,已回复)
 */
router.get(APIv2.Sessions.TopicListByType,function (req,res) {
    let user = req.query.user;
    let status = req.query.status;
@ -84,6 +92,9 @@ router.get(APIv2.Sessions.TopicListByType,function (req,res) {
});
/**
 * 按类型查找咨询(未回复,进行中,已回复)的数量
 */
router.get(APIv2.Sessions.TopicListCountByType,function (req,res) {
    let user = req.query.user;
    let status = req.query.status;
@ -99,6 +110,9 @@ router.get(APIv2.Sessions.TopicListCountByType,function (req,res) {
});
/**
 * 健康咨询(区分团队)
 */
router.get(APIv2.Sessions.HealthTeamTopicList, function (req, res) {
    let user = req.query.user;
    let status = req.query.status;
@ -112,6 +126,9 @@ router.get(APIv2.Sessions.HealthTeamTopicList, function (req, res) {
    topic.findAllByUserAndReplyAndStatusHealthTeamTopic(users,reply,status,adminTeamCode,page,pagesize);
});
/**
 * 议题回复数统计
 */
router.get(APIv2.Sessions.TopicReplyCount, function (req, res) {
    let user = req.query.user;
    let status = req.query.status;
@ -124,7 +141,9 @@ router.get(APIv2.Sessions.TopicReplyCount, function (req, res) {
});
/**
 * 创建议题
 */
router.post(APIv2.Sessions.Topics, function (req, res) {
    let payload = req.body;
    let testing = ObjectUtil.fieldsCheck(payload, "topic_id", "topic_name", "participants", "messages", "session_type");
@ -136,6 +155,9 @@ router.post(APIv2.Sessions.Topics, function (req, res) {
    topic.createTopic(payload.topic_name, payload.topic_id, payload.session_id, JSON.parse(payload.participants), JSON.parse(payload.messages),payload.session_type);
});
/**
 * 修改议题
 */
router.put(APIv2.Sessions.Topics, function (req, res) {
    let payload = req.body;
    let topicId = payload.topic_id;
@ -147,6 +169,9 @@ router.put(APIv2.Sessions.Topics, function (req, res) {
    topic.updateTopic(topicId, JSON.parse(jsonValue));
});
/**
 * 议题是否已结束,若top_id为current,则检查最后一个议题的状态
 */
router.get(APIv2.Sessions.TopicEnded, function (req, res) {
    let sessionId = req.params.session_id;
    let topicId = req.params.topic_id;
@ -157,6 +182,9 @@ router.get(APIv2.Sessions.TopicEnded, function (req, res) {
    topic.isTopicEnded(sessionId, topicId, null);
});
/**
 *结束议题
 */
router.post(APIv2.Sessions.TopicEnded, function (req, res) {
    let payload = req.body;
    let endUser = payload.end_user;
@ -169,7 +197,9 @@ router.post(APIv2.Sessions.TopicEnded, function (req, res) {
    ControllerUtil.regModelEventHandler(topic, res);
    topic.endTopic(topicId, endUser, endUserName,agent);
});
/**
 * 进入议题
 */
router.post(APIv2.Sessions.TopicInto, function (req, res) {
    let payload = req.body;
    let intoUser = payload.into_user;

+ 36 - 0
src/server/handlers/rtcSocketHandler.js

@ -0,0 +1,36 @@
module.exports = function(io, streams) {
  io.on('connection', function(socket) {
    console.log('-- ' + socket.id + ' joined --');
      socket.emit('id', socket.id);
      socket.on('message', function (details) {
      var othersocket = io.sockets.connected[details.to];
      if (!othersocket) {
        return;
      }
        delete details.to;
        details.from = socket.id;
        othersocket.emit('message', details);
    });
      socket.on('readyToStream', function(options) {
      console.log('-- ' + socket.id + ' is ready to stream --');
      
      streams.addStream(socket.id, options.name); 
    });
      socket.on('update', function(options) {
      streams.update(socket.id, options.name);
    });
    function leave() {
      console.log('-- ' + socket.id + ' left --');
      streams.removeStream(socket.id);
    }
      socket.on('disconnect', leave);
      socket.on('leave', leave);
  });
};

+ 143 - 8
src/server/handlers/socket.handler.js

@ -10,9 +10,14 @@ let clientCache = require('../models/socket.io/client.cache').clientCache();
let PatientClient = require('./../models/socket.io/patient.client');
let PcDoctorClient  = require('./../models/socket.io/pcDoctor.client');
let DoctorClient  = require('./../models/socket.io/doctor.client');
let RtcClient  = require('../models/socket.io/rtc.client.js');
let Sessions = require('../models/sessions/sessions');
let Users = require('../models/user/users');
let ModelUtil = require('../util/model.util.js');
let pusher = require('../models/push/pusher.js');
let AppClient = require('../models/client/app.client.js');
let sessions = new Sessions();
let users = new Users();
@ -21,6 +26,9 @@ class SocketHandler {
        this._socketServer = socketServer;
    }
    sleep (time) {
        return new Promise((resolve) => setTimeout(resolve, time));
    }
    /**
     * 启用事件监听。
     */
@ -75,18 +83,145 @@ class SocketHandler {
                }
            });
            // 返回userid的socketid
            socket.on('getSid',function(data){
                var clientJson = null;
                if(!(data instanceof Object)){
                    clientJson = JSON.parse(data);
                }else{
                    clientJson = data;
                }
                var userId = clientJson.userId;
                var rtcClient = clientCache.findById(userId);
                if(rtcClient === undefined){
                    socketServer.sockets.emit('error', {message: 'this socket client has not ever connect '});
                    return;
                }
                var result = {'userId':userId,'sid':rtcClient._socket.id};
                log.info('request getSid,userid :'+userId);
                socket.emit('getSid',result);
            });
            // 设置userid的socketid
            socket.on('setSid',function(data){
                var clientJson = null;
                if(!(data instanceof Object)){
                    clientJson = JSON.parse(data);
                }else{
                    clientJson = data;
                }
                var userId = clientJson.userId;
                let rtcClient = new RtcClient(socket,socketServer);
                rtcClient.userId = userId;
                clientCache.addClient(rtcClient);
                var result = {'userId':userId,'sid':rtcClient._socket.id};
                log.info('request setSid,userid :'+userId);
                socket.emit('setSid',result);
            });
            // 接收客户端消息
            /**
             * 视频消息格式:
             * var payload = {
                                userId: userId,
                                sid:sid, socket.io 的id
                                targetId: targetUid,
                                type: "offer/answer/hang-up/time-out/canidate",  发起视频/接受视频/(拒绝视频|挂断视频)/超时
                                sdp: myPeerConnection.localDescription
                            };
             */
            socket.on('message', function (data) {
                log.info('Got message from ' + clientCache.findBySocket(socket).userId);
                var payload = null;
                if(!(data instanceof Object)){
                    payload = JSON.parse(data);
                }else{
                    payload = data;
                }
                // 视频聊天消息
                if(payload !== undefined && payload.type){
                    if(payload.fromSid === undefined || payload.fromSid === ''){
                        socket.emit('error', {error: 'Missing fields(s): sid.',"payload":payload});
                        return;
                    }
                    switch (payload.type) {
                        case 'video-offer':
                            let title = 'videoCall';
                            /* var getui = {
                              from:from_userId,
                              fromSid:from_sid,
                              to:to_userId,
                              msgType: "videoCall",
                          };*/
                            AppClient.getAppStatus(payload.targetId, function (err, userStatus) {
                                if (err) {
                                    ModelUtil.logError("Get user app status failed", err);
                                    socket.emit('error', {error: 'cannot get ClietnId for targetId:' + payload.targetId,"payload":payload});
                                    return;
                                }
                                pusher.pushToSingleViaAndroid(title, title, payload, userStatus.client_id, userStatus.app_in_bg, function (err, res) {
                                    if (err) {
                                        ModelUtil.logError("Send notification via Android failed", err);
                                        socket.emit('error', {error: 'Send notification via Android failed for targetId:' + payload.targetId,"payload":payload});
                                    } else {
                                        log.info("offer Send notification via Android succeed: ", JSON.stringify(res));
                                    }
                                });
                            });
                            break;
                        case 'video-answer':
                            var rtcClientSocket = clientCache.findById(payload.targetId);
                            if(rtcClientSocket === undefined){
                                socket.emit('error',{error: 'cannot find this socket client for userid:'+ payload.targetId + ' when video-answer',"payload":payload});
                                return
                            }
                            rtcClientSocket._socket.send(payload,function(client){
                            });
                            break;
                        case 'candidate':
                            var rtcClientSocket = clientCache.findById(payload.targetId);
                            if(rtcClientSocket === undefined){
                                socket.emit('error',{error: 'cannot find this socket client for userid:'+ payload.targetId + ' when candidate',"payload":payload});
                                return
                            }
                            rtcClientSocket._socket.send(payload,function(client){
                            });
                            break;
                        case 'hang-up':
                            var rtcClientSocket = clientCache.findById(payload.targetId);
                            if(rtcClientSocket === undefined){
                                socket.emit('error',{error: 'cannot find this socket client for userid:'+ payload.targetId + ' when hang-up',"payload":payload});
                                return
                            }
                            rtcClientSocket._socket.send(payload,function(client){
                            });
                        case 'time-out':
                            var rtcClientSocket = clientCache.findById(payload.targetId);
                            if(rtcClientSocket === undefined){
                                socket.emit('error',{error: 'cannot find this socket client for userid:'+ payload.targetId + ' when time-out',"payload":payload});
                                return
                            }
                            rtcClientSocket._socket.send(payload,function(client){
                            });
                            break;
                    }
                }else{
                    // 其他类型的消息
                    log.info('Got message from ' + clientCache.findBySocket(socket).userId);
                let sessionId = data.session_id;
                let message = data.message;
                message.timestamp = new Date();
                    let sessionId = data.session_id;
                    let message = data.message;
                    message.timestamp = new Date();
                /*sessions.createSession(sessionId, "Let's talk!", 1, ['504a0bcddb1e4e37a0306b39c51900b5', 'cd92414c-5b06-11e6-8344-fa163e8aee56'], function (err, res) {
                    /*sessions.createSession(sessionId, "Let's talk!", 1, ['504a0bcddb1e4e37a0306b39c51900b5', 'cd92414c-5b06-11e6-8344-fa163e8aee56'], function (err, res) {
                        sessions.saveMessageBySession(sessionId, message);
                    });*/
                    sessions.saveMessageBySession(sessionId, message);
                });*/
                sessions.saveMessageBySession(sessionId, message);
                }
            });
            socket.on('error',function(errMsg){
                log.info(JSON.stringify(errMsg));
                socket.emit(errMsg);
            });
            // 客户端退出
@ -99,7 +234,7 @@ class SocketHandler {
            });
            // 客户端断开
            socket.on('disconnect', function () {
            socket.on('disconnect', function (soc) {
                let patientClient = clientCache.findBySocket(socket);
                if (patientClient) {
                    log.info("User disconnect: ", patientClient.userId);

+ 13 - 3
src/server/include/commons.js

@ -33,7 +33,8 @@ const SESSION_TYPES = {
    GROUP: 3,           // 固定组
    DISCUSSION: 4,       // 临时讨论组
    SPECIALISTGROUP: 5,       // 专科医生和家庭医生的固定组
    PRESCRIPTION_HOSPITAL:9,//医院在线复诊
    PRESCRIPTION: 8,   // 续方
    PRESCRIPTION_HOSPITAL:9, //医院在线复诊
    ONDOOR_NURSING:11   //上门护理
};
@ -78,7 +79,7 @@ exports.PARTICIPANT_ROLES = PARTICIPANT_ROLES;
 *  消息内容类型。
 */
const CONTENT_TYPES = {
    PlainText: 1,   // 信息
    PlainText: 1,   // 文本信息
    Image: 2,       // 图片信息
    Audio: 3,       // 语音信息
    Article: 4,     // 文章信息
@ -94,6 +95,9 @@ const CONTENT_TYPES = {
    PrescriptionBloodStatus:16,//续方咨询血糖血压咨询消息
    PrescriptionFollowupContent:17,//续方咨询随访问卷消息
    Rehabilitation: 20, //康复计划发送
    ChangeDoorCardInfo: 2102,//上门服务-修改工单卡片信息
    ChangeDoorDoctor: 2103,//上门服务-变更工单医生信息
    ChangeDoorPackageItems:2104, //上门服务-变更工单服务项信息
    typeToDescription: function (type, defaultDescription) {
        if (CONTENT_TYPES.Image == type) {
            return '[图片]';
@ -237,6 +241,10 @@ const DB_TABLES = {
            return DB_TABLES.MucMessages;
        else if (sessionType == SESSION_TYPES.SPECIALISTGROUP)
            return DB_TABLES.GroupMessages;
        else if (sessionType == SESSION_TYPES.PRESCRIPTION_HOSPITAL)
            return DB_TABLES.MucMessages;
        else if (sessionType == SESSION_TYPES.ONDOOR_NURSING)
            return DB_TABLES.MucMessages;
        else throw {message: "Unknown session type"};
    }
};
@ -248,7 +256,9 @@ const MESSAGE_BUSSINESS_TYPE = {
    D_CT_02: "D_CT_02",//指定咨询, 您有新的消息
    D_CT_03: "D_CT_03",//名医咨询, 您有新的名医咨询
    D_CT_04: "D_CT_04",//名医咨询, 您有新的名医咨询
    D_CT_05: "D_CT_05"//续方咨询, 您有新的续方咨询
    D_CT_05: "D_CT_05",//续方咨询, 您有新的续方咨询
    D_CT_06: "D_CT_06",//在线复诊咨询, 您有新的复诊咨询
    D_CT_07: "D_CT_07"//上门服务咨询, 您有新的上门服务咨询回复
};
exports.MESSAGE_BUSSINESS_TYPE = MESSAGE_BUSSINESS_TYPE;

+ 2 - 1
src/server/include/endpoints.js

@ -32,7 +32,7 @@ const APIv2 = {
        UserConsultTime:'/:user_id/consult/time'                        //用户咨询时间
    },
    Sessions: {
        Base: '/api/v2/sessions',
        Base: '/api/v2/sessions',                                       //创建会话
        Session: '/:session_id/session',                                // 获取会话
        SessionListByType: '/sessionListByType',                        // 按会话类型获取会话
@ -57,6 +57,7 @@ const APIv2 = {
        Messages: '/:session_id/messages',                              // 会话消息
        MessagesByTopic: '/:session_id/topics/:topic_id/messages',      // 议题消息
        Message: '/:session_id/messages/:message_id',                   // 单条消息
        MessageUpdate: '/:session_id/messages/:message_id/update',      // 更新消息内容(消息里有i健康业务状态时)
        SessionsUnreadMessageCount: '/unread_message_count',            // 所有会话的未读消息数
        SessionUnreadMessageCount: '/:session_id/unread_message_count', // 指定会话的未读消息数

+ 6 - 1
src/server/models/client/app.client.js

@ -178,10 +178,15 @@ class AppClient extends RedisModel {
                    session_type==SESSION_TYPES.DISCUSSION||
                    session_type==SESSION_TYPES.SPECIALISTGROUP||
                    session_type==SESSION_TYPES.PRESCRIPTION||
                    session_type==SESSION_TYPES.PRESCRIPTION_HOSPITAL||
                    session_type==SESSION_TYPES.ONDOOR_NURSING||
                    message.business_type == MESSAGE_BUSSINESS_TYPE.D_CT_01||
                    message.business_type == MESSAGE_BUSSINESS_TYPE.D_CT_02||
                    message.business_type == MESSAGE_BUSSINESS_TYPE.D_CT_03||
                    message.business_type == MESSAGE_BUSSINESS_TYPE.D_CT_04){
                    message.business_type == MESSAGE_BUSSINESS_TYPE.D_CT_04||
                    message.business_type == MESSAGE_BUSSINESS_TYPE.D_CT_05||
                    message.business_type == MESSAGE_BUSSINESS_TYPE.D_CT_06||
                    message.business_type == MESSAGE_BUSSINESS_TYPE.D_CT_07){
                    //是否发送消息
                    MessageNoticeSettingRepo.findOne(targetId,'1',function (err,res) {
                        if(res&&res.length>0){

+ 22 - 4
src/server/models/client/wechat.client.js

@ -62,7 +62,10 @@ class WechatClient extends RedisModel {
            message.content_type == CONTENT_TYPES.Image ||
            message.content_type == CONTENT_TYPES.Audio||
            message.content_type == CONTENT_TYPES.PrescriptionBloodStatus ||
            message.content_type == CONTENT_TYPES.PrescriptionFollowupContent)) {
            message.content_type == CONTENT_TYPES.PrescriptionFollowupContent ||
            message.content_type == CONTENT_TYPES.ChangeDoorCardInfo ||
            message.content_type == CONTENT_TYPES.ChangeDoorDoctor ||
            message.content_type == CONTENT_TYPES.ChangeDoorPackageItems)) {
            let patientClient = clientCache.findById(targetUserId);
            let doctorClient = clientCache.findByIdAndType(message.sender_id,SOCKET_TYPES.DOCTOR);
            let pc_doctorClient = clientCache.findByIdAndType("pc_"+message.sender_id,SOCKET_TYPES.PC_DOCTOR);
@ -327,6 +330,7 @@ class WechatClient extends RedisModel {
    }
    /**
     *
     * 发送微信模板消息给居民
     *
     * @param targetUserId
@ -400,9 +404,23 @@ class WechatClient extends RedisModel {
                    var patient = map.get("openid");
                    map.delete("openid");
                    let agent = topic.agent;
                    let consultTitle = topic.type==8?"续方":"健康";
                    let description = topic.type==8?"续方咨询":topic.description;
                    let url = config.wechatConfig.baseUrl + (topic.type==8?"/wx/html/yszx/html/prescription-consulting.html":"/wx/html/yszx/html/consulting-doctor.html");
                    let consultTitle = null;
                    let description = null;
                    let url = config.wechatConfig.baseUrl;
                    switch (topic.type) {
                        case 8:
                            consultTitle = "续方";
                            description  = "续方咨询";
                            url = url + "/wx/html/yszx/html/prescription-consulting.html";
                        case 11:
                            consultTitle = "上门服务";
                            description  = "上门服务咨询";
                            url = url + "wx/html/appoint_service/html/appoint-serviceDetail.html";
                        default:
                            consultTitle = "健康";
                            description  = topic.description;
                            url = url + "/wx/html/yszx/html/consulting-doctor.html";
                    }
                    if(agent){//代理人发起的议题
                        var agentOpenid = "";
                        if(map.size>0){

+ 48 - 1
src/server/models/messages/messages.js

@ -20,6 +20,7 @@ let configFile = require('../../include/commons').CONFIG_FILE;
let config = require('../../resources/config/' + configFile);
let logger = require('../../util/log');
let pubSub = require("../redis/pubSub.js");
let async = require("async");
const REDIS_KEYS = require('../../include/commons').REDIS_KEYS;
@ -98,7 +99,10 @@ class Messages extends RedisModel {
        let sessionKey = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
        let messageKey = RedisModel.makeRedisKey(REDIS_KEYS.Messages, sessionId);
        let messageTimestampKey = RedisModel.makeRedisKey(REDIS_KEYS.MessagesByTimestamp, sessionId);
        log.info("  message.timestamp = " + message.timestamp);
        log.info("  message.sender_id = " + message.sender_id);
        log.info("  message.sender_name= " + message.sender_name);
        log.info("  message.timestamp.getTime() = " + message.timestamp.getTime());
        let msgJson = {
            id: message.id,
            sender_id: message.sender_id,
@ -207,6 +211,49 @@ class Messages extends RedisModel {
        MessageRepo.save(message, sessionType, messageId, sessionId, handler);
    }
    /**
     * 保存Message 到mysql
     * @param message 消息对象
     * @param sessionType
     * @param messageId
     * @param sessionId
     * @param handler
     * @type type 会话类型,1表示MUC会话,2表示P2P,3表示群会话,4表示临时讨论组
     */
    updateMsgContent(sessionType,sessionId, messageId, content,handler) {
        let self = this;
        async.waterfall( [
            function (callback) {
                MessageRepo.selectOneMessage(sessionType, messageId, function (err, res) {
                    if (err) {
                        ModelUtil.emitError(self.eventEmitter, {message: "this message not exist,id: " + messageId});
                    } else {
                        res[0].content = content;
                        log.info("res[0].timestamp="+res[0].timestamp.getTime());
                        callback(null,res[0]);
                    }
                })
            },
            function (messageObj) {
                log.info("  11messages.timestamp="+messageObj.timestamp.getTime());
                let messages = new Messages();
                messages.saveMessageToRedis(sessionId, sessionType, messageId, messageObj);
                MessageRepo.updateMsgContent(sessionType,sessionId, messageId, content, function (err, res) {
                    if (err) {
                        ModelUtil.emitError(self.eventEmitter, {message: "update message content failed: " + err});
                    } else {
                        ModelUtil.emitOK(self.eventEmitter, {status: 200,data: content});
                    }
                })
            }
        ], function (err, res) {
            if (err) {
                ModelUtil.emitError(self.eventEmitter, "update message content failed:" + err);
            }
        });
    }
    /**
     * 更新会话最后一条消息
     *

+ 1 - 1
src/server/models/redis/redisPubClient.js

@ -62,7 +62,7 @@ function uncaughtExceptionHandler(err){
    if(err && err.code == 'ECONNREFUSED'){
        //do someting
    }else{
        log.error(err+"exit in pub Redis");
        log.error(err+" exit in pub Redis");
    }
}
process.on('uncaughtException', uncaughtExceptionHandler);

+ 1 - 1
src/server/models/redis/redisSubClient.js

@ -62,7 +62,7 @@ function uncaughtExceptionHandler(err){
    if(err && err.code == 'ECONNREFUSED'){
        //do someting
    }else{
        log.error(err+"exit in sub Redis");
        log.error(err+" exit in sub Redis");
    }
}
process.on('uncaughtException', uncaughtExceptionHandler);

+ 1 - 1
src/server/models/sessions/participants.js

@ -269,7 +269,7 @@ class Participants extends RedisModel {
                if(oldUserId){
                    redis.hgetAsync(participantsRoleKey,oldUserId).then(function(role){
                        if(!role)role = 0;
                        self.addUser(session.id,userId,role,function(err,addResult){
                        self.deleteUserFromMysql(session.id,userId,function(err,addResult){
                            if(err){
                                ModelUtil.emitOK(self.eventEmitter, {status:-1,message: "会话成员添加失败!"});
                                return;

+ 19 - 5
src/server/models/sessions/sessions.js

@ -393,6 +393,7 @@ class Sessions extends RedisModel {
     */
    getUserSessions(userId, page, size, businessType) {
        let userSessionKey = RedisModel.makeRedisKey(REDIS_KEYS.UserSessions, userId);
        logger.info(userId);
        let self = this;
        if (page > 0) {
            if (page == 1) {
@ -430,6 +431,7 @@ class Sessions extends RedisModel {
                let sessionList = [];
                let functionList = [];
                for (let j = 0; j < sessionIds.length; j++) {
                    log.info("遍历会话 :" + sessionIds);
                    let fun = function (index, callback) {
                        if (!callback) {
                            callback = index, index = 0
@ -822,6 +824,7 @@ class Sessions extends RedisModel {
     */
    getUserStatusSessions(userId,status,businessType,page, size) {
        let userSessionKey = RedisModel.makeRedisKey(REDIS_KEYS.UserSessions, userId);
        log.info(userId);
        let self = this;
        async.waterfall([
            // 获取会话ID列表
@ -977,6 +980,7 @@ class Sessions extends RedisModel {
        if (!start_msg_id && !end_msg_id) {
            redis.zrevrangeAsync(message_timestamp_key, 0, 0).then(function (res) {
                logger.info("redis return res-----"+res);
                log.info("session.js--830---getMessages  res.length: " + res.length);
                if (res.length == 0) {
                    //修复应redis没有缓冲聊天记录导致会话列表加载不出来
                    // cache messages
@ -1144,7 +1148,10 @@ class Sessions extends RedisModel {
        }
        participants.existsParticipant(sessionId, userId, function (err, res) {
            if (!res) {
            log.info("1151-userId=" + userId);
            log.info(" res[0].exist=" + res[0].exist);
            log.info(!res[0].exist && userId != "system");
            if (! res[0].exist && userId != "system") {
                handler(Error("User not found in session " + sessionId), null);
            } else {
                //将消息ID转换成分值
@ -1432,8 +1439,9 @@ class Sessions extends RedisModel {
                ModelUtil.emitError(self.eventEmitter, "Check session participant failed: ", err);
                return;
            }
            if (res) {
            logger.info("session.js--1443--res[0].exist" + res[0].exist);
            log.info("message.sender_id=" + message.sender_id);
            if ( res[0].exist || message.sender_id == "system") {
                redis.hmgetAsync(sessionKey, ["type", "name"]).then(function (res) {
                    sessionType = res[0];
                    let sessionName = res[1];
@ -1588,7 +1596,9 @@ class Sessions extends RedisModel {
        }
        // 发送成员必须处于会话中
        participants.existsParticipant(sessionId, message.sender_id, function (err, res) {
            if (res) {
            log.info("1599-message.sender_id=" + message.sender_id);
            log.info("res[0].exist=" + res[0].exist);
            if ( res[0].exist || message.sender_id == "system") {
                redis.hmgetAsync(session_key, ["type", "name"]).then(function (res) {
                    sessionType = res[0];
                    sessionName = res[1];
@ -1652,6 +1662,7 @@ class Sessions extends RedisModel {
     * @param handler
     */
    saveIntoMessageByTopic(message, sessionId, handler) {
        log.info("2--保存代理人进入的消息:");
        let messages = new Messages();
        let participants = new Participants();
        let session_key = RedisModel.makeRedisKey(REDIS_KEYS.Session, sessionId);
@ -1666,7 +1677,9 @@ class Sessions extends RedisModel {
        }
        // 发送成员必须处于会话中
        participants.existsParticipant(sessionId, message.sender_id, function (err, res) {
            if (res) {
            log.info("session.js--1477--res[0].exist" + res[0].exist);
            log.info("message.sender_id=" + message.sender_id);
            if (res[0].exist || message.sender_id == "system") {
                redis.hmgetAsync(session_key, ["type", "name"]).then(function (res) {
                    sessionType = res[0];
                    sessionName = res[1];
@ -1721,6 +1734,7 @@ class Sessions extends RedisModel {
                    return;
                })
            } else {
                log.info("4--用户不在此会话当中!");
                if (handler){ handler("用户不在此会话当中!", messageId);return;}
            }
        });

+ 3 - 0
src/server/models/sessions/topics.js

@ -289,6 +289,7 @@ class Topics extends RedisModel {
                }else{
                    self.saveTopicToRedis(topicName, topicId, sessionId, messages, datetime, function (err, startMsgId) {
                        if (err) {
                            log.error(err);
                            ModelUtil.emitOK(self.eventEmitter, {status: -1, message: "议题创建失败!"});
                            return;
                        }
@ -483,6 +484,7 @@ class Topics extends RedisModel {
     * @param intoUserName
     */
    intoTopic(topicId,intoUser,intoUserName,senderId,content){
        log.info("1--进入议题:" + senderId);
        let intoDate = new Date();
        let self = this;
        let topic_key = RedisModel.makeRedisKey(REDIS_KEYS.Topic, topicId);
@ -513,6 +515,7 @@ class Topics extends RedisModel {
            let sessions = new Sessions();
            sessions.saveIntoMessageByTopic(msg, sessionId, function (err, msgId) {
                log.info("3--sessions.saveIntoMessageByTopic: sessionId:" + sessionId);
                if (err) {
                    ModelUtil.emitOK(self.eventEmitter, {status: -1, "message": err});
                } else {

+ 1 - 1
src/server/models/socket.io/doctor.client.js

@ -1,5 +1,5 @@
/**
 * 患者端socket.
 * 医生端socket.
 *
 * author: Sand
 * since: 2016/11/18

+ 17 - 0
src/server/models/socket.io/rtc.client.js

@ -0,0 +1,17 @@
/**
 * 视频聊天 socket.
 *
 * author: lith
 * since: 2018/08/16
 */
"use strict";
var Client = require('./client');
class RtcClient extends Client{
    constructor(socket, socketServer){
        super(socket, socketServer);
    }
}
module.exports = RtcClient;

+ 46 - 1
src/server/repository/mysql/message.repo.js

@ -9,6 +9,7 @@ let log = require('../../util/log.js');
let SessionRepo = require('../../repository/mysql/session.repo');
let ImDb = require('../mysql/db/im.db');
const DB_TABLES = require('../../include/commons').DB_TABLES;
class MessageRepo {
@ -100,6 +101,49 @@ class MessageRepo {
        }
    }
    /**
     * 修改消息内容
     *
     * @param message 消息对象
     * @param sessionType 会话类型,参见 SESSIONS_TYPES
     * @param messageId
     * @param sessionId
     * @param handler
     */
    static updateMsgContent(sessionType, sessionId,messageId, content,handler) {
        let sql = "UPDATE " + DB_TABLES.sessionTypeToTableName(sessionType)  + " set content =  ? , timestamp = ? where id = ? and session_id = ?";
        log.info(sql);
        ImDb.execQuery({
            "sql": sql,
            "args": [content.toString(),new Date(), messageId,sessionId],
            "handler": handler || function (err, res) {
                if (err) log.error(err);
            }
        });
    }
    /**
     * 修改消息内容
     *
     * @param message 消息对象
     * @param sessionType 会话类型,参见 SESSIONS_TYPES
     * @param messageId
     * @param sessionId
     * @param handler
     */
    static selectOneMessage(sessionType,messageId,handler) {
        let sql = "SELECT * from " + DB_TABLES.sessionTypeToTableName(sessionType)  + "  where id = ?";
        log.info(sql);
        ImDb.execQuery({
            "sql": sql,
            "args": [messageId],
            "handler": handler || function (err, res) {
                if (err) log.error(err);
            }
        });
    }
    /**
     * 获取会话医生的id
     * @param sessionId
@ -109,7 +153,8 @@ class MessageRepo {
        let sql =
            "SELECT s.content_type, s.content,s.agent FROM " + DB_TABLES.sessionTypeToTableName(sessionType) + " s " +
            "WHERE s.session_id = ? order by s.timestamp desc limit 1 ";
        log.info("获取会话医生的id sql : " + sql);
        log.info("获取会话医生的id args : " + [sessionId]);
        ImDb.execQuery({
            "sql": sql,
            "args": [sessionId],

+ 6 - 1
src/server/repository/mysql/participant.repo.js

@ -245,6 +245,8 @@ class ParticipantRepo {
     */
    static existsParticipant(sessionId, userId, handler) {
        let sql = "SELECT case when count(*) > 0 then true else false end exist FROM participants w WHERE w.session_id =? AND w.participant_id = ? ";
        log.info("用户是否在指定Session中:sql:" + sql);
        log.info("用户是否在指定Session中:args:" + [sessionId, userId]);
        ImDb.execQuery({
            "sql": sql,
            "args": [sessionId, userId],
@ -262,7 +264,9 @@ class ParticipantRepo {
    static saveParticipantsToMysql(sessionId, users, handler) {
        let sql = "INSERT INTO " + DB_TABLES.Participants + " (session_id,participant_id,participant_role,last_fetch_time) VALUES ";
        let args = [];
        let nowDate = null;
        let nowDate = new Date();
        log.info("saveParticipantsToMysql:[sql] = " + sql);
        log.info("saveParticipantsToMysql:[users.length] = " + users.length);
        for (let j in users) {
            let tokens = users[j].split(":");
            sql += "(?,?,?,?)";
@ -271,6 +275,7 @@ class ParticipantRepo {
            args.push(tokens.length > 1 ? tokens[1] : '0');
            args.push(nowDate);
            if (j != users.length - 1) sql += ", ";
            log.info("saveParticipantsToMysql:[args] = " + args);
        }
        sql += " ON DUPLICATE KEY UPDATE participant_role = VALUES(participant_role)";
        ImDb.execQuery({

+ 6 - 0
src/server/repository/mysql/session.repo.js

@ -102,6 +102,8 @@ class SessionRepo {
        let sql = "select session_id from " + DB_TABLES.Participants + " w where w.participant_id = ? and type=? group by w.session_id";
        let sessionSQL = "select id, name, type, create_date, last_sender_id, last_sender_name, last_content_type, last_content, last_message_time from "
            + DB_TABLES.Sessions + " s where s.id in(" + sql + ") ";
        log.info("获取用户全部会话: sql :" + sql);
        log.info("获取用户全部会话: args :" + args);
        ImDb.execQuery({
            "sql": sessionSQL,
            "args": [userId, type],
@ -190,6 +192,8 @@ class SessionRepo {
                let sql1 = ("select session_id from " + DB_TABLES.Participants + " w where w.participant_id = ? and participant_role ="+PARTICIPANT_ROLES.REGULAR+" group by w.session_id")
                sessionSQL =  "select * from "
                    + DB_TABLES.Sessions + " s where (s.id in(" + sql + ") and s.business_type = ? and s.status = 1) or (s.id in(" + sql1 + ") and s.business_type = ? and s.status = 0) limit "+page+","+pagesize;
                log.info("findAllByTypeAndStatus: sql " + sessionSQL);
                log.info("findAllByTypeAndStatus: args " + [userId, businessType,userId,businessType]);
                ImDb.execQuery({
                    "sql": sessionSQL,
                    "args": [userId, businessType,userId,businessType],
@ -204,6 +208,8 @@ class SessionRepo {
            sql = "select session_id from " + DB_TABLES.Participants + " w where w.participant_id = ? and participant_role ="+PARTICIPANT_ROLES.HOST+" group by w.session_id";
            sessionSQL =  "select * from "
                + DB_TABLES.Sessions + " s where s.id in(" + sql + ") and s.business_type = ? and s.status = ? limit "+page+","+pagesize;
            log.info("findAllByTypeAndStatus: sql : "+sessionSQL);
            log.info("findAllByTypeAndStatus: args : "+[userId, businessType,status]);
            ImDb.execQuery({
                "sql": sessionSQL,
                "args": [userId, businessType,status],

+ 1 - 1
src/server/repository/redis/redis.client.js

@ -66,7 +66,7 @@ function uncaughtExceptionHandler(err){
    if(err && err.code == 'ECONNREFUSED'){
        //do someting
    }else{
        log.error(err+"exit in redis");
        log.error(err+" exit in redis");
    }
}
process.on('uncaughtException', uncaughtExceptionHandler);

+ 13 - 13
src/server/resources/config/config.test.js

@ -1,9 +1,9 @@
"use strict";
let imDbConfig = {
    host: '172.19.103.85',
    user: 'linzhou',
    password: 'linzhou',
    host: '172.26.0.104',
    user: 'ssgg',
    password: 'ssgg@jkzl2019',
    database: 'im_new',
    connectionLimit: '50',
    charset: 'utf8mb4'
@ -11,7 +11,7 @@ let imDbConfig = {
// Redis
let redisConfig = {
    host: '192.168.131.172',
    host: '172.26.0.253',
    port: 6379,
    db: 1
};
@ -22,21 +22,21 @@ let redisConfig = {
// };
// 内网Redis
let innerRedisConfig = {
    host: '192.168.131.172',
    host: '172.26.0.253',
    port: 6379,
    db: 1
};
// 三师后台
let wlyyServerConfig = {
    host: '192.168.131.172',
    port: 9092,
    host: '172.26.0.104',
    port: 8080,
    model:"/wlyy"
};
//医生助手配置
let wlyyDAServerConfig = {
    host: '192.168.131.172',
    port: 9092,
    host: '172.26.0.104',
    port: 8080,
    model:"/wlyy"
};
@ -50,13 +50,13 @@ let getTuiConfig = {
// 微信配置
let wechatConfig = {
    appId: 'wxddece6347fe7fe87',
    appSecret: '41ade403de3d0e2e450f54a324ec013a',
    appId: 'wx1f129f7b51701428',
    appSecret: '988f005d8309ed1795939e0f042431fb',
    token: '27eb3bb24f149a7760cf1bb154b08040',
    accId: 'gh_710bf0b315a1',
    accId: 'gh_ffd64560fb21',
    baseUrl: 'ehr.yihu.com/wlyy',
    template: {
        consultTemplate: 'oGFfTWPEYvwwfmcIK1hquZ4-cVXdNomV3bCMLfj97Jc'  // 咨询回复模板
        consultTemplate: '-dr4QNyFoRvVsf8uWxXMC1dRyjwnbUuJwJ21vBLhf18'  // 咨询回复模板
    }
};