/** * 医生模型。 */ "use strict"; let log = require("../../util/log.js"); let getui = require('getui'); let BaseModel = require('./../base.model'); let Schedule = require("./../schedule/schedule.js"); let doctorRepo = require('../../repository/mysql/doctor.repo.js'); let gmRepo = require('../../repository/mysql/group.msg.repo'); let pmRepo = require('../../repository/mysql/private.msg.repo'); let nmRepo = require("../../repository/mysql/notify.msg.repo"); let smRepo = require("../../repository/mysql/system.msg.repo.js"); let statsRepo = require("../../repository/mysql/stats.msg.repo"); let objectUtil = require("../../util/objectUtil.js"); let modelUtil = require('../../util/modelUtil'); const CONTENT_TYPES = require('../../include/commons').CONTENT_TYPE; const PLATFORMS = require('../../include/commons').PLATFORM; const MAX_INT = require('../../include/commons').MAX_INT; class Doctor extends BaseModel { constructor() { super(); this.$id = 'doctor'; } /** * 向医生发送消息。 * * @param message */ sendMessage(message) { let self = this; let tempContent = message.contentType === CONTENT_TYPES.Article ? JSON.stringify(message.content) : message.content; pmRepo.save(message.to, message.from, message.contentType, tempContent, function (err, result) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Save private message failed', err); return; } // 返回新插入的消息数据,并推送 pmRepo.findOneMessage(result.insertId, function (err, msg) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Save private message success, but return last message failed', err); return; } // 先结束网络连接,再推送给客户端 modelUtil.emitData(self.eventEmitter, Doctor.fillMessages(msg)); Doctor.pushMessage(message, 'p2p_msg'); }); // 更新自身的聊天统计信息 statsRepo.updatePrivateChatSummary(message.from, message.to, message.from, message.contentType, message.content, function (err, result) { if (err) log.error(err); }); // 更新对端的聊天统计信息 statsRepo.updatePrivateChatSummary(message.to, message.from, message.from, message.contentType, message.content, function (err, result) { if (err) log.error(err); }); }); } /** * 向医生发送系统消息。 * * @param message */ sendSystemMessage(message) { let self = this; smRepo.save(message.to, message.contentType, message.title, message.summary, message.content, function (err, result) { if (err) { modelUtil.emitDbError(self.eventEmitter, "Save system message failed", err); return; } // 先结束网络连接,再推送给客户端 modelUtil.emitData(self.eventEmitter, {}); Doctor.pushMessage(message, 'system_msg'); }); } /** * 推送消息。 * * @param message * @param channel */ static pushMessage(message, channel){ doctorRepo.getUserStatus(message.to, function (err, result) { if (err) { log.error('Lookup notify message receiver failed: ' + message.to); return; } if (result.length == 0) { log.warn('Notify message receiver is not found: ', message.to); return; } let userStatus = result[0]; let isOnline = result.length > 0 && userStatus.is_online === 1; let delay = null; // 构建通知消息 let notifyMessage = {type: channel, data: message.content}; if (message.from) notifyMessage.from_uid = message.from; if (message.gid) notifyMessage.gid = message.gid; if (message.delay && message.delay !== "null") delay = new Date(Date.parse(message.delay)); let title = '新消息'; let content = message.content; if (message.contentType === CONTENT_TYPES.Image) { content = '[图片]'; } else if (message.contentType === CONTENT_TYPES.Audio) { content = '[语音]'; } else if (message.contentType > 3) { content = '您有一条新消息'; } // 保存通知消息到数据库中,并根据用户在线状态推送此消息 nmRepo.save(message.to, message.contentType, title, content, JSON.stringify(notifyMessage), isOnline, delay, function (err, result) { if (err) { log.error('Save notify message failed, ', err); return; } if (delay) { Schedule.dateSchedule(delay, function (message, client_id, status, token, title, content, notifyMessage, platform) { Doctor.pushToClient(message.to, client_id, status, token, message.contentType, title, content, notifyMessage, platform, function (err, result) { if (err != null) { log.error(err); } else { log.info(result); } }); }.bind(null, message, userStatus.client_id, userStatus.status, userStatus.token, title, content, notifyMessage, userStatus.platform)); } else if (isOnline) { Doctor.pushToClient(message.to, userStatus.client_id, userStatus.status, userStatus.token, message.contentType, title, content, notifyMessage, userStatus.platform, function (err, result) { if (err != null) { log.error(err); } else { log.info(result); } }); } }); }); } /** * 推送消息给医生客户端。 * * @param userId 用户ID * @param clientId 客户端设备ID * @param appStatus 客户端App状态 * @param token * @param contentType * @param title * @param content * @param notifyMessage * @param platform * @param handler */ static pushToClient(userId, clientId, appStatus, token, contentType, title, content, notifyMessage, platform, handler) { if (platform === PLATFORMS.iOS) { getui.pushAPN(userId, token, contentType, title, content, notifyMessage, handler); } else if (platform === PLATFORMS.Android) { getui.pushAndroid(clientId, contentType, title, content, notifyMessage, appStatus, handler); } } /** * 获取最近聊天的用户,组。 */ getRecentChatList(userId, days) { let self = this; statsRepo.getRecentChats(userId, days, function (err, rows) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get recent chat objects failed', err); return; } let data = {patients: [], doctors: [], groups: []}; if (rows.length > 0) { for (let i = 0; i < rows.length; ++i) { let row = rows[i]; if (row.type.indexOf('patient') > -1) { data.patients.push({ code: row.code, name: row.name, birthday: row.birthday === null ? "" : row.birthday, sex: row.sex, avatar: row.photo === null ? "" : row.photo }); } else if (row.type.indexOf('doctor') > -1) { data.doctors.push({ code: row.code, name: row.name, birthday: row.birthday === null ? "" : row.birthday, sex: row.sex, avatar: row.photo === null ? "" : row.photo }); } else if (row.type.indexOf('group') > -1) { data.groups.push({ code: row.code, name: row.name }); } } } modelUtil.emitData(self.eventEmitter, data); }); } /** * 获取参与的聊天列表,包括:点对点,参与的讨论组,系统消息等。 * * @param userId */ getChatList(userId) { let self = this; // 与患者的私信 pmRepo.findAllP2PWithPatient(userId, function (err, patients) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get chat list with patient failed', err); return; } let chats = {patients: [], doctors: [], groups: []}; for (let i = 0; i < patients.length; i++) { let patient = patients[i]; chats.patients.push({ code: patient.code, name: patient.name, birthday: patient.birthday, sex: patient.sex, avatar: patient.photo == null ? "" : patient.photo, newMessageCount: patient.new_msg_count, lastContentType: patient.last_content_type, lastContent: patient.last_content, timestamp: objectUtil.timestampToLong(patient.timestamp) }); } // 含有患者的群 gmRepo.findAllGroupsWithPatient(userId, function (err, groups) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get group list with patient failed', err); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; // 过滤掉医生间的求助团队 if (group.group_type === 2) continue; chats.groups.push({ code: group.code, name: group.name, groupType: group.msg_type, newMessageCount: group.new_msg_count, lastContentType: group.last_content_type, lastContent: group.last_content, timestamp: objectUtil.timestampToLong(group.timestamp) }); } // 医生间的私聊 pmRepo.findAllP2PWithDoctor(userId, function (err, doctors) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get chat list with doctor failed', err); return; } for (let i = 0; i < doctors.length; i++) { let doctor = doctors[i]; chats.doctors.push({ code: doctor.code, name: doctor.name, sex: doctor.sex, avatar: doctor.photo === null ? "" : doctor.photo, newMessageCount: doctor.new_msg_count, lastContentType: doctor.last_content_type, lastContent: doctor.last_content, timestamp: objectUtil.timestampToLong(doctor.timestamp) }); } // 获取医生间的组 gmRepo.findAllGroupsWithDoctor(userId, function (err, groups) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get group list with doctor failed', err); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; chats.groups.push({ code: group.code, name: group.name, groupType: group.group_type, // 行政团队 or 求助 newMessageCount: group.new_msg_count, lastContentType: group.last_content_type, lastContent: group.last_content, timestamp: objectUtil.timestampToLong(group.timestamp) }); } modelUtil.emitData(self.eventEmitter, chats); }); }); }) }); } /** * 获取与患者的聊天列表。 */ getChatsListWithPatient(userId) { let self = this; pmRepo.findAllP2PWithPatient(userId, function (err, patients) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get chat list with patient failed', err); return; } let chats = {patients: [], groups: []}; for (let i = 0; i < patients.length; i++) { let patient = patients[i]; chats.patients.push({ code: patient.code, name: patient.name, birthday: patient.birthday, sex: patient.sex, avatar: patient.photo == null ? "" : patient.photo, newMessageCount: patient.new_msg_count, lastContentType: patient.last_content_type, lastContent: patient.last_content, timestamp: objectUtil.timestampToLong(patient.timestamp) }); } gmRepo.findAllGroupsWithPatient(userId, function (err, groups) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get group list with patient failed', err); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; // 过滤掉医生间的求助团队 if (group.group_type === 2) continue; chats.groups.push({ code: group.code, name: group.name, groupType: group.msg_type, newMessageCount: group.new_msg_count, lastContentType: group.last_content_type, lastContent: group.last_content, timestamp: objectUtil.timestampToLong(group.timestamp) }); } modelUtil.emitData(self.eventEmitter, chats); }) }); } /** * 获取与医生的聊天列表,包括:点对点,参与的讨论组。 * * @param userId */ getChatListWithDoctor(userId) { let self = this; // 先获取医生间的私聊 pmRepo.findAllP2PWithDoctor(userId, function (err, doctors) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get chat list with doctor failed', err); return; } let chats = {doctors: [], groups: []}; for (let i = 0; i < doctors.length; i++) { let doctor = doctors[i]; chats.doctors.push({ code: doctor.code, name: doctor.name, sex: doctor.sex, avatar: doctor.photo === null ? "" : doctor.photo, newMessageCount: doctor.new_msg_count, lastContentType: doctor.last_content_type, lastContent: doctor.last_content, timestamp: objectUtil.timestampToLong(doctor.timestamp) }); } // 再获取医生间的组 gmRepo.findAllGroupsWithDoctor(userId, function (err, groups) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get group list with doctor failed', err); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; chats.groups.push({ code: group.code, name: group.name, groupType: group.group_type, // 行政团队 or 求助 newMessageCount: group.new_msg_count, lastContentType: group.last_content_type, lastContent: group.last_content, timestamp: objectUtil.timestampToLong(group.timestamp) }); } modelUtil.emitData(self.eventEmitter, chats); }); }); } /** * 获取与医生,患者的聊天列表,包括:点对点,参与的讨论组。消息数量 * * @param userId */ getChatListMsgAmount(userId) { let self = this; let chats = {doctor: {}, patient: {}}; // 先获取医生间的私聊 pmRepo.findAllP2PWithDoctor(userId, function (err, doctors) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get chat list with doctor failed', err); return; } var amount = 0; for (let i = 0; i < doctors.length; i++) { let doctor = doctors[i]; //过滤结束的咨询 //if(doctor.last_content_type==7)continue; amount = doctor.new_msg_count+amount; } // 再获取医生间的组 gmRepo.findAllGroupsWithDoctor(userId, function (err, groups) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get group list with doctor failed', err); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; //过滤结束的咨询 //if(group.last_content_type==7)continue; amount = group.new_msg_count+amount; } chats.doctor = amount; var patientAmount =0; //获取患者记录数量 pmRepo.findAllP2PWithPatient(userId, function (err, patients) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get chat list with patient failed', err); return; } for (let i = 0; i < patients.length; i++) { let patient = patients[i]; //过滤结束的咨询 // if(patient.last_content_type==7)continue; patientAmount =patientAmount+ patient.new_msg_count; } //获取患者记录数量 gmRepo.findAllGroupsWithPatient(userId, function (err, groups) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get group list with patient failed', err); return; } for (let i = 0; i < groups.length; i++) { let group = groups[i]; // 过滤掉医生间的求助团队 if (group.group_type === 2) continue; //过滤结束的咨询 //if(group.last_content_type==7)continue; patientAmount = patientAmount+ group.new_msg_count; } chats.patient = patientAmount; modelUtil.emitData(self.eventEmitter, chats); }); }); }); }); } /** * 获取与指定用户的聊天记录。 * * @param userId * @param peerId * @param contentType * @param msgStartId * @param msgEndId * @param count * @param closedInterval */ getPrivateMessages(userId, peerId, contentType, msgStartId, msgEndId, count, closedInterval) { let self = this; pmRepo.findAllMessages(userId, peerId, contentType === undefined ? "0,1,2,3,4,5,6" : contentType, msgStartId, msgEndId, count, closedInterval, function (err, rows) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get private message failed', err); return; } let messages = Doctor.fillMessages(rows); modelUtil.emitData(self.eventEmitter, messages); // 清空统计信息 statsRepo.clearPrivateChatSummary(userId, peerId, function (err, result) { if (err) log.error(err); }); }); } /** * 获取与某人聊天的未读消息数。 * * @param userId * @param peerId */ getUnreadMessageCount(userId, peerId) { let self = this; statsRepo.getPrivateChatAllUnReadCount(userId, function (err, result) { if (err) { modelUtil.emitDbError(self.eventEmitter, "Get unread private message count failed", err); return; } let data = {userId: userId, messageType: 1, newMessageCount: 0}; for (let i = 0; i < result.length; i++) { data.newMessageCount += result[i].new_msg_count; } modelUtil.emitData(self.eventEmitter, data); }); } /** * 获取所有未读的消息数,包括群。 * * @param userId */ getAllUnreadMessageCount(userId) { let self = this; statsRepo.getChatAllUnReadCount(userId, function (err, result) { if (err) { modelUtil.emitDbError(self.eventEmitter, "Get all unread message count failed", err); return; } let data = {userId: userId, messageType: 0, newMessageCount: 0}; for (let index = 0; index < result.length; index++) { data.newMessageCount += result[index].new_msg_count; } modelUtil.emitData(self.eventEmitter, data); }); } /** * 获取与指定用户的未读聊天记录。 * * @param userId * @param peerId */ getUnreadPrivateMessages(userId, peerId) { let self = this; statsRepo.getPrivateChatSummary(userId, peerId, function (err, summary) { if (err) { modelUtil.emitDbError(self.eventEmitter, 'Get unread private messages failed', err); return; } // 没有未读消息,直接返回 if (summary.length == 0 || summary[0].new_msg_count === 0) { modelUtil.emitData(self.eventEmitter, {startId: 0, count: 0, records: []}); return; } pmRepo.findUnread(peerId, userId, MAX_INT, summary[0].new_msg_count, function (err, rows) { if (err) { modelUtil.emitDbError(self.eventEmitter, "Get unread private messages failed", err); return; } let messages = Doctor.fillMessages(rows); modelUtil.emitData(self.eventEmitter, messages); }); }); } /** * 获取聊天统计摘要。 * * @param userId * @param peerId */ getChatSummary(userId, peerId) { let self = this; statsRepo.getPrivateChatSummary(userId, peerId, function (err, result) { if (err) { modelUtil.emitDbError(self.eventEmitter, "Get private messages statistic failed", err); return; } let data = { userId: userId, peerId: peerId, lastCContentType: 1, lastContent: "", newMessageCount: 0, timestamp: 0 }; if (result.length > 0) { let row = result[0]; data.userId = row.uid; data.peerId = row.from_uid; data.lastContentType = row.last_content_type; data.lastContent = row.last_content; data.newMessageCount = row.new_msg_count; data.timestamp = objectUtil.timestampToLong(row.timestamp) } modelUtil.emitData(self.eventEmitter, data); }); } getMessage(messageId, messageType) { let self = this; if (messageType == 1) { // 私信 pmRepo.findOneMessage(messageId, function (err, result) { if (err) { modelUtil.emitDbError(self.eventEmitter, "Get message failed", err); return; } if (result.length == 0) { modelUtil.emitDataNotFound(self.eventEmitter, "Message not found."); return; } modelUtil.emitData(self.eventEmitter, { id: result[0].msg_id, from: result[0].from_uid, to: result[0].to_uid, contentType: result[0].type, content: result[0].content, timestamp: objectUtil.timestampToLong(result[0].timestamp) }); }) } else { // 群信 gmRepo.findOneMessage(messageId, function (err, result) { if (err) { modelUtil.emitDbError(self.eventEmitter, "Get message failed", err); return; } if (result.length == 0) { modelUtil.emitDataNotFound(self.eventEmitter, "Message not found."); return; } modelUtil.emitData(self.eventEmitter, { id: result[0].msg_id, from: result[0].from_uid, at: result[0].at_uid, groupId: result[0].to_gid, contentType: result[0].type, content: result[0].content, timestamp: objectUtil.timestampToLong(result[0].timestamp) }); }); } } /** * 判断与患者的最新咨询会话是否已经结束。 */ isConsultFinished(doctorId, patientId) { let self = this; pmRepo.isCurrentSessionFinished(doctorId, patientId, function (err, result) { if (err) { modelUtil.emitDbError(self.eventEmitter, "Get session finish status failed: ", err); return; } let data = {finished: true, consultId: ''}; if (result.length > 0) { let finishRow = result[0]; data.finished = finishRow.finished === 1; if (!data.finished) { data.consultId = finishRow.consult_id; } } modelUtil.emitData(self.eventEmitter, data); }) } /** * 将消息的返回结果合并成JSON。 * * @param rows * * @returns {startId: 0, count: 0, records: []} */ static fillMessages(rows) { let messages = {startId: rows.length > 0 ? rows[0].msg_id : '', count: rows.length, records: []}; for (let i = 0; i < rows.length; i++) { let row = rows[i]; let record = { id: row.msg_id, from: row.from_uid, contentType: row.type, content: row.content, timestamp: objectUtil.timestampToLong(row.timestamp) }; if (row.to_uid !== undefined) record.to = row.to_uid; if (row.at_uid !== undefined) record.at = row.at_uid; messages.records.push(record); } return messages; } } // Expose class module.exports = Doctor;