소스 검색

修复fillMessages引用错误;补充说明文档

Sand 8 년 전
부모
커밋
1fa2434ed4

+ 21 - 10
readme.md

@ -1,6 +1,6 @@
# IM服务器
此项目是医生端即时消息服务器,与患者端不同。患者端的即时消息服务器使用C++编写,并且不具有消息存储功能,医生端与患者端已经连通,参见im.patient项目的说明。以后可能使用node.js框架统一二者。
此项目是家庭医生的消息服务器,含医生端与患者端。医生端使用REST API收发消息,患者端使用Web Socket收发消息。
## 代码管理
@ -8,20 +8,29 @@
## 环境安装
- 开发工具: node.js的代码可以使用文本编辑器开发,如:Sublime, vi, vim等。也可以使用IDE开发,推荐使用WebStorm,包含大量便捷功能,加速开发。
- 开发工具: Node.js的代码可以使用文本编辑器开发,如:Sublime, vi, vim等。也可以使用IDE开发,推荐使用WebStorm,包含大量便捷功能,加速开发。
- 数据库准备: IM服务器使用MySQL数据库,因此需要先安装MySQL数据库。然后执行resources/schema/im_schema.sql与resources/schema/talk_group_schema.sql脚本文件,创建数据模式。第一个创建消息存储所需要的模式,第二个创建业务讨论组数据模式,并包含演示数据。
- 运行环境:node.js使用社区6.X版本或Joyent的0.10.x版本开发,部署环境也需要使用相应的版本。
- ECMA版本:代码需要ECMA 6版本的支持,提供对class, arrow function的支持。
- 运行环境:Node.js使用社区6.X版本或Joyent的0.10.x版本开发,部署环境也需要使用相应的版本。
- ECMA Script版本:代码需要ECMA Script 6版本的支持,提供对class, arrow function的支持。
## 运行
对Windows环境,可以预先安装node.js。对Linux环境,代码包中包含node.js程序,第一次部署需要使用chmod为此增加执行权限。通过以下命令启动消息服务器
对Windows环境,可以预先安装Node.js。对Linux环境,代码包中包含Node.js程序,第一次部署需要使用chmod为此增加执行权限:
    chmod +x node
    
之后通过以下命令启动消息服务器:
    node app.armour.js
启动成功将出现如下日志:
    [INFO] app.js(125,5): Starting IM server, version 1.0.5.20161107, running on port 3000, 2016-11-22 16:00:17
    [INFO] app.js(126,5): Configuration profile: dev
## 测试
测试框架使用mocha。REST客户端使用supertest。should模块提供断言测试。
测试框架使用mocha。REST客户端使用supertest。should模块提供断言测试。测试用例位于test目录,并根据模块划分。
## 部署
@ -29,7 +38,7 @@
    export IM_PROFILE=prod
    
IM_PROFILE值将决定应用加载的配置文件。值为prod, test, dev,仅能使用一个,若配置错误服务将无法运行。若未配置此参数则默认使用dev配置。
IM_PROFILE值将决定应用加载的配置文件,配置文件位于src/resources/config。IM_PROFILE值为prod, test, dev中的一个。若配置错误服务将无法运行。若未配置此参数则默认使用dev配置。
为保证服务正常运行,当服务异常退出时自动重启服务,IM服务器使用app.armour.js脚本,对进程添加保护:进程异常退出时,自动重启。为实现此目标,部署时通过appArmour启动服务即可实现进程的守护功能。
@ -89,11 +98,9 @@ REST API遵循REST最佳实践,规范命名URL中的每个部分。注意POST
        content: "The patient has been followed in the scheduler, please make new follow plan as soon as possible."
    }
2 发送P2P消息
    GET http://192.168.131.115:3000/api/v1/chats/pm
    
参数格式
@ -125,4 +132,8 @@ REST API遵循REST最佳实践,规范命名URL中的每个部分。注意POST
参数:
- user_id: 用户ID
- user_id: 用户ID
### Web Socket
Web Socket提供页面内长连接,并且能够通过Web Socket收发消息。

+ 5 - 7
src/doctor/endpoints/chats.endpoint.js

@ -20,10 +20,8 @@ let Search = require('../models/search');
const APIv1 = require('../include/endpoints').APIv1;
const CONTENT_TYPES = require('../include/commons').CONTENT_TYPE;
const GROUP_TYPE = require('../include/commons').GROUP_TYPE;
const MAX_INT = 9007199254740992;
const DEFAULT_PAGE_SIZE = 100;
const MAX_INT = require('../include/commons').MAX_INT;
const DEFAULT_PAGE_SIZE = require('../include/commons').DEFAULT_PAGE_SIZE;
//--------------------------------------------------------------//
//----------------------------消息发送----------------------------//
@ -219,7 +217,7 @@ router.get(APIv1.Chats.ListWithDoctor, function (req, res) {
 * 参数:
 *  user_id: 用户ID
 *  target_type: 对象类型,1患者,2医生,3讨论组
 *  days: 最近天数
 *  days: 最近天数,默认7天
 */
router.get(APIv1.Chats.Recent, function (req, res) {
    let userId = req.query.user_id;
@ -229,13 +227,13 @@ router.get(APIv1.Chats.Recent, function (req, res) {
    }
    if (days === null) {
        throw {httpStatus: 406, message: 'Missing field: days'};
        days = 7;
    }
    let doctor = new Doctor();
    controllerUtil.regModelEventHandler(doctor, res);
    doctor.getRecentChatList(userId);
    doctor.getRecentChatList(userId, days);
});
/**

+ 13 - 1
src/doctor/include/commons.js

@ -7,7 +7,7 @@
 *
 * @type {string}
 */
var configFile = "config.";
let configFile = "config.";
if (process.env.IM_PROFILE === "prod") {
    configFile += "prod";
@ -63,3 +63,15 @@ exports.MODEL_EVENTS = {
    OK: "ok"                        // 操作结束或有数据返回
};
/**
 * 默认整型最大值。
 * @type {number}
 */
exports.MAX_INT = 9007199254740992;
/**
 * 默认分页大小。
 *
 * @type {number}
 */
exports.DEFAULT_PAGE_SIZE = 100;

+ 4 - 3
src/doctor/models/doctor.js

@ -18,6 +18,7 @@ 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() {
@ -171,7 +172,7 @@ class Doctor extends BaseModel {
    /**
     * 获取最近聊天的用户,组。
     */
    getRecentChatList() {
    getRecentChatList(userId, days) {
        let self = this;
        statsRepo.getRecentChats(userId, days, function (err, rows) {
            if (err) {
@ -446,7 +447,7 @@ class Doctor extends BaseModel {
                return;
            }
            let messages = self.fillMessages(rows);
            let messages = Doctor.fillMessages(rows);
            modelUtil.emitData(self.eventEmitter, messages);
            // 清空统计信息
@ -529,7 +530,7 @@ class Doctor extends BaseModel {
                    return;
                }
                let messages = self.fillMessages(rows);
                let messages = Doctor.fillMessages(rows);
                modelUtil.emitData(self.eventEmitter, messages);
            });
        });

+ 11 - 13
src/doctor/models/group.js

@ -3,9 +3,6 @@
 */
"use strict";
let CONTENT_TYPES = require('../include/commons').CONTENT_TYPE;
let PLATFORMS = require('../include/commons').PLATFORM;
let BaseModel = require('./base.model');
let log = require("../util/log.js");
let modelUtil = require('../util/modelUtil');
@ -14,13 +11,14 @@ let getui = require('getui');
let Patient = new require("../models/patient");
let Doctor = new require('../models/doctor');
let doctorRepo = require('../repository/doctor.repo.js');
let groupRepo = require('../repository/group.repo');
let gmRepo = require('../repository/group.msg.repo');
let nmRepo = require("../repository/notify.msg.repo");
let statsRepo = require("../repository/stats.msg.repo");
let objectUtil = require("../util/objectUtil.js");
const GROUP_TYPE = require('../include/commons').GROUP_TYPE;
const MAX_INT = require('../include/commons').MAX_INT;
class GroupMessage extends BaseModel {
    constructor() {
        super();
@ -58,7 +56,7 @@ class GroupMessage extends BaseModel {
                    }
                    // 关闭网络连接后执行后续操作
                    let feedback = Patient.fillMessages(groupMsg);
                    let feedback = Doctor.fillMessages(groupMsg);
                    modelUtil.emitData(self.eventEmitter, feedback);
                    // 推送通知消息给群组成员
@ -126,7 +124,7 @@ class GroupMessage extends BaseModel {
            }
            // 先给客户端返回数据
            let messages = GroupMessage.fillMessages(rows);
            let messages = Doctor.fillMessages(rows);
            modelUtil.emitData(self.eventEmitter, messages);
            // 清空统计信息
@ -161,7 +159,7 @@ class GroupMessage extends BaseModel {
                        return;
                    }
                    let feedback = Patient.fillMessages(rows);
                    let feedback = Doctor.fillMessages(rows);
                    modelUtil.emitData(feedback);
                });
            }
@ -252,11 +250,11 @@ class GroupMessage extends BaseModel {
                return;
            }
            var lastGroup;
            var lastGroupCode = '';
            for (var i = 0; i < members.length; ++i) {
                var member = members[i];
                var groupCode = member.g_code;
            let lastGroup;
            let lastGroupCode = '';
            for (let i = 0; i < members.length; ++i) {
                let member = members[i];
                let groupCode = member.g_code;
                if (lastGroupCode !== groupCode) {
                    lastGroupCode = groupCode;
                    lastGroup = {groupCode: groupCode, avatars: []};

+ 3 - 1
src/doctor/models/search.js

@ -15,6 +15,8 @@ let searchRepo = require('../repository/search.repo');
let modelUtil = require("../util/modelUtil");
let objectUtil = require('../util/objectUtil');
const GROUP_TYPE = require('../include/commons').GROUP_TYPE;
class Search extends BaseModel{
    constructor() {
        super();
@ -78,7 +80,7 @@ class Search extends BaseModel{
    /**
     * 搜索医生相关的数据,包括医生信息与相关的聊天记录,包括私信与群信。
     */
    searchAboutDoctor() {
    searchAboutDoctor(userId, keyword) {
        let self = this;
        searchRepo.searchDoctors(userId, keyword, function (err, doctors) {

+ 8 - 14
src/doctor/resources/config/config.dev.js

@ -1,7 +1,7 @@
"use strict";
// 三师后台数据库配置
var wlyyDbConfig = {
let wlyyDbConfig = {
    host: '172.19.103.77',
    user: 'root',
    password: '123456',
@ -10,7 +10,7 @@ var wlyyDbConfig = {
};
// IM数据库配置
var imDbConfig = {
let imDbConfig = {
    host: '172.19.103.77',
    user: 'root',
    password: '123456',
@ -19,24 +19,19 @@ var imDbConfig = {
};
// 三师后台
var wlyyServerConfig = {
let wlyyServerConfig = {
    host: '172.19.103.87',
    port: 9092
};
// 加密配置
var crypto = {
    algorithm: ''
};
// 透传服务
var transServerConfig = {
let transServerConfig = {
    host: '172.19.103.76',
    port: 8000
};
// 企业版的推送配置
var geTuiConfig = {
let geTuiConfig = {
    HOST: 'https://api.getui.com/apiex.htm',
    APPID: 'qWmRh2X88l7HuE36z3qBe8',
    APPKEY: 'EzERfV8c849lBkZqHWzQG1',
@ -44,7 +39,7 @@ var geTuiConfig = {
};
// AppStore版的推送App配置
var geTuiAppStoreCfg = {
let geTuiAppStoreCfg = {
    HOST : 'https://api.getui.com/apiex.htm',
    APPID : 'H6FYbDejks6VjMmW3uH7V6',
    APPKEY : '0PFWlKmLBN9YzhCfFWVgYA',
@ -52,7 +47,7 @@ var geTuiAppStoreCfg = {
};
exports.app = 'IM.Server';
exports.version = '1.0.5.20161107';
exports.version = '1.2.5.20161107';
exports.debug = true;
exports.serverPort = 3000;
exports.sessionExpire = 1800;
@ -64,5 +59,4 @@ exports.imDbConfig = imDbConfig;
exports.geTuiConfig = geTuiConfig;
exports.geTuiAppStoreCfg = geTuiAppStoreCfg;
exports.wlyyServerConfig = wlyyServerConfig;
exports.transServerConfig = transServerConfig;
exports.crypto = crypto;
exports.transServerConfig = transServerConfig;

+ 7 - 7
src/doctor/resources/config/config.prod.js

@ -1,6 +1,6 @@
"use strict";
var wlyyDbConfig = {
let wlyyDbConfig = {
    host: '59.61.92.94',
    user: 'wlyy',
    password: 'jkzlehr@123',
@ -8,7 +8,7 @@ var wlyyDbConfig = {
    connectionLimit: '100'
};
var imDbConfig = {
let imDbConfig = {
    host: 'localhost',
    user: 'root',
    password: '19991120',
@ -17,7 +17,7 @@ var imDbConfig = {
};
// 企业版的推送配置
var geTuiConfig = {
let geTuiConfig = {
    HOST: 'https://api.getui.com/apiex.htm',
    APPID: 'qWmRh2X88l7HuE36z3qBe8',
    APPKEY: 'EzERfV8c849lBkZqHWzQG1',
@ -25,7 +25,7 @@ var geTuiConfig = {
};
//AppStore版的推送App配置
var geTuiAppStoreCfg = {
let geTuiAppStoreCfg = {
    HOST : 'https://api.getui.com/apiex.htm',
    APPID : 'H6FYbDejks6VjMmW3uH7V6',
    APPKEY : '0PFWlKmLBN9YzhCfFWVgYA',
@ -33,19 +33,19 @@ var geTuiAppStoreCfg = {
};
// 三师后台
var wlyyServerConfig = {
let wlyyServerConfig = {
    host: '172.19.103.87',
    port: 9090
};
// 透传服务
var transServerConfig = {
let transServerConfig = {
    host: '120.41.253.95',
    port: 3030
};
exports.app = 'im.server';
exports.version = '1.0.2.20160805';
exports.version = '1.2.5.20161107';
exports.debug = true;
exports.serverPort = 3000;
exports.sessionExpire = 1800;

+ 7 - 7
src/doctor/resources/config/config.test.js

@ -1,6 +1,6 @@
"use strict";
var wlyyDbConfig = {
let wlyyDbConfig = {
    host: '120.41.251.85',
    user: 'root',
    password: 't_s_6_7$1',
@ -8,7 +8,7 @@ var wlyyDbConfig = {
    connectionLimit: '100'
};
var imDbConfig = {
let imDbConfig = {
    host: 'localhost',
    user: 'root',
    password: '19991120',
@ -17,7 +17,7 @@ var imDbConfig = {
};
// 企业版的推送配置
var geTuiConfig = {
let geTuiConfig = {
    HOST: 'https://api.getui.com/apiex.htm',
    APPID: 'qWmRh2X88l7HuE36z3qBe8',
    APPKEY: 'EzERfV8c849lBkZqHWzQG1',
@ -25,7 +25,7 @@ var geTuiConfig = {
};
//AppStore版的推送App配置
var geTuiAppStoreCfg = {
let geTuiAppStoreCfg = {
    HOST : 'https://api.getui.com/apiex.htm',
    APPID : 'H6FYbDejks6VjMmW3uH7V6',
    APPKEY : '0PFWlKmLBN9YzhCfFWVgYA',
@ -33,19 +33,19 @@ var geTuiAppStoreCfg = {
};
// 三师后台
var wlyyServerConfig = {
let wlyyServerConfig = {
    host: '172.19.103.87',
    port: 9090
};
// 透传服务
var transServerConfig = {
let transServerConfig = {
    host: '172.19.103.76',
    port: 8000
};
exports.app = 'im.server';
exports.version = '1.0.2.20160805';
exports.version = '1.2.5.20161107';
exports.debug = true;
exports.serverPort = 3000;
exports.sessionExpire = 1800;