lrf402788946 4 年之前
父節點
當前提交
0cd3af894a

+ 31 - 0
app/controller/dock/.train_chat.js

@@ -0,0 +1,31 @@
+module.exports = {
+  create: {
+    requestBody: ["sender_id", "sender_name", "!content", "send_time", "role", "unit_id"],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: ["sender_id", "sender_name", "content", "send_time", "role", "unit_id"],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: ["sender_id", "sender_name", "content", "send_time", "role", "unit_id"],
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 13 - 0
app/controller/dock/train_chat.js

@@ -0,0 +1,13 @@
+'use strict';
+const meta = require('./.train_chat.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 培训问诊聊天
+class Train_chatController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.dock.trainChat;
+  }
+}
+module.exports = CrudController(Train_chatController, meta);

+ 5 - 0
app/controller/statistics/index.js

@@ -46,5 +46,10 @@ class IndexController extends Controller {
     const data = await this.service.circle(this.ctx.query);
     this.ctx.ok({ data });
   }
+
+  async dockIndex() {
+    const res = await this.service.dockIndex(this.ctx.query);
+    this.ctx.ok({ data: res });
+  }
 }
 module.exports = CrudController(IndexController, {});

+ 1 - 1
app/model/channel.js

@@ -10,7 +10,7 @@ const channel = {
   title: { type: String, required: false, maxLength: 200 }, // 标题
   origin: { type: String, required: false, maxLength: 200 }, // 来源
   type: { type: String, required: false, maxLength: 200 }, // 类别
-  room_id: { type: Number, required: false, maxLength: 200 }, // 房间id,服务生成,从2001开始
+  room_id: { type: String, required: false, maxLength: 200 }, // 房间id,服务生成,从2001开始
   passwd: { type: Secret, required: false, maxLength: 200, select: false }, // 密码,房间号
   desc: { type: String, maxLength: 1000 }, // 简介
   remark: { type: String, maxLength: 200 },

+ 1 - 1
app/model/dock.js

@@ -21,7 +21,7 @@ const vipuser = new Schema({
 vipuser.index({ id: 1 });
 // 展会表
 const dock = {
-  room_id: { type: Number, required: true, maxLength: 10 }, // 房间号
+  room_id: { type: String, required: true, maxLength: 10 }, // 房间号
   password: { type: Secret, select: false }, // 密码
   title: { type: String, required: false, maxLength: 200 }, // 对接会标题
   start_time: { type: String, required: true, maxLength: 200 }, // 开始时间

+ 26 - 0
app/model/train_chat.js

@@ -0,0 +1,26 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const moment = require('moment');
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+// 培训问诊聊天记录表
+const train_chat = {
+  unit_id: { type: String, maxLength: 200 }, // 公共聊天区id
+  sender_id: { type: String, maxLength: 200 }, // 发言人id
+  sender_name: { type: String, required: true, maxLength: 200 }, // 发言人名称
+  content: { type: String, required: true, maxLength: 1000 }, // 发言内容
+  send_time: { type: String, default: moment().format('YYYY-MM-DD HH:mm:ss'), maxLength: 100 }, // 发言时间:年月日时分秒
+  role: { type: String, maxLength: 200 }, // 用户身份
+  remark: { type: String, maxLength: 200 },
+  create_time: { type: String, default: moment().format('YYYY-MM-DD HH:mm:ss') },
+};
+const schema = new Schema(train_chat, { toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.index({ unit_id: 1 });
+schema.index({ sender_id: 1 });
+schema.index({ send_time: 1 });
+schema.index({ 'meta.createdAt': 1 });
+schema.plugin(metaPlugin);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('Train_chat', schema, 'train_chat');
+};

+ 1 - 0
app/router.js

@@ -32,6 +32,7 @@ module.exports = app => {
   require('./router/dock/road_show')(app); // 路演
   require('./router/dock/channel')(app); // 科技频道
   require('./router/dock/channel_video')(app); // 科技频道-视频
+  require('./router/dock/train_chat')(app); // 培训问诊聊天
   require('./router/tecinfo/column')(app); // 栏目
   require('./router/tecinfo/news')(app); // 信息
   require('./router/dock/interview')(app); // 访谈

+ 12 - 0
app/router/dock/train_chat.js

@@ -0,0 +1,12 @@
+'use strict';
+
+
+module.exports = app => {
+  const { router, controller } = app;
+  const profix = '/api/live/';
+  const vision = 'v0';
+  const index = 'dock';
+  const target = 'trainChat';
+  router.resources(target, `${profix}${vision}/${index}/${target}`, controller[index][target]); // index、create、show、destroy
+  router.post(target, `${profix}${vision}/${index}/${target}/update/:id`, controller[index][target].update);
+};

+ 1 - 0
app/router/statistics/index.js

@@ -7,6 +7,7 @@ module.exports = app => {
   const vision = 'v0';
   const index = 'statistics';
   const target = 'index';
+  router.get(target, `${profix}${vision}/${index}/${target}/dockIndex`, controller[index][target].dockIndex);
   router.get(target, `${profix}${vision}/${index}/${target}/index`, controller[index][target].index);
   router.get(target, `${profix}${vision}/${index}/${target}/patent`, controller[index][target].patent);
   router.get(target, `${profix}${vision}/${index}/${target}/product`, controller[index][target].product);

+ 2 - 2
app/service/dock/index.js

@@ -16,8 +16,8 @@ class IndexService extends CrudService {
   }
   async create(body) {
     const last = await this.model.findOne().sort({ room_id: -1 });
-    let room_id = 1001;
-    if (last) room_id = last.room_id + 1;
+    let room_id = '1001';
+    if (last) room_id = parseInt(last.room_id) + 1;
     body.room_id = room_id;
     body.password = { secret: room_id };
     const { vipuser } = body;

+ 35 - 0
app/service/dock/train_chat.js

@@ -0,0 +1,35 @@
+'use strict';
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const _ = require('lodash');
+const moment = require('moment');
+const assert = require('assert');
+
+// 培训问诊聊天
+class Train_chatService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'train_chat');
+    this.model = this.ctx.model.TrainChat;
+  }
+  async create(query, { unit_id, sender_id, sender_name, content, role }) {
+    assert(sender_name, '缺少发言人信息');
+    assert(unit_id, '缺少会场id');
+    assert(content, '缺少发言内容');
+    const send_time = moment().format('YYYY-MM-DD HH:mm:ss');
+    const res = await this.model.create({ sender_id, sender_name, content, send_time, role, unit_id });
+    // TODO MQ
+    const { mq } = this.ctx;
+    if (mq) {
+      const exchange = 'train_live';
+      const parm = {
+        durable: true,
+        headers: {
+          userid: 1,
+        } };
+      await mq.fanout(exchange, unit_id, JSON.stringify(res), parm);
+    }
+    return res;
+  }
+}
+
+module.exports = Train_chatService;

+ 44 - 2
app/service/statistics/index.js

@@ -9,6 +9,7 @@ const assert = require('assert');
 class IndexService extends CrudService {
   constructor(ctx) {
     super(ctx, 'index');
+    this.redis = this.app.redis;
     this.patentModel = this.ctx.model.Patent;
     this.code = this.ctx.model.Code;
     this.productModel = this.ctx.model.Product;
@@ -17,6 +18,7 @@ class IndexService extends CrudService {
     this.personalModel = this.ctx.model.Personal;
     this.organizationModel = this.ctx.model.Organization;
     this.surveyModel = this.ctx.model.Survey;
+    this.dockUser = this.ctx.model.DockUser;
     this.tranModel = this.ctx.model.Transaction;
   }
   /**
@@ -153,7 +155,7 @@ class IndexService extends CrudService {
       value: surveys,
     });
     const trans = await this.tranModel.aggregate([
-      { $match: { status: { $in: [ '0', '1', '2' ] } } },
+      { $match: { status: { $in: [ '0', '1', '3' ] } } },
       {
         $group: {
           _id: '$status',
@@ -171,7 +173,7 @@ class IndexService extends CrudService {
     });
     arr.push({
       name: '对接完成',
-      value: _.get(trans.find(f => f._id === '2'), 'value', 0),
+      value: _.get(trans.find(f => f._id === '3'), 'value', 0),
     });
     return arr;
   }
@@ -207,6 +209,46 @@ class IndexService extends CrudService {
       { name: '东北师范大学' },
     ];
   }
+
+  // 展会首页统计
+  async dockIndex({ dock_id }) {
+    // 同时在线人数(伪)
+    const tszx = await this.redis.get('login_number');
+    // 特邀嘉宾
+    const tyjb = await this.personalModel.count({ is_expert: true });
+    // 洽谈合作 达成意向 交易完成
+    const trans = await this.tranModel.aggregate([
+      { $match: { status: { $in: [ '0', '1', '3' ] } } },
+      {
+        $group: {
+          _id: '$status',
+          value: { $sum: 1 },
+        },
+      },
+    ]);
+    const qthz = _.get(trans.find(f => f._id === '0'), 'value', 0);
+    const dcyx = _.get(trans.find(f => f._id === '1'), 'value', 0);
+    const jywc = _.get(trans.find(f => f._id === '3'), 'value', 0);
+    // 参展项目
+    const res = await this.dockUser.aggregate()
+      .match({ dock_id: ObjectId(dock_id), 'goodsList.type': '1', 'goodsList.dockStatus': '1' })
+      .unwind('$goodsList')
+      .group({
+        _id: '$dock_id',
+        count: { $sum: 1 },
+      });
+    const czxm = _.get(res[0], 'count');
+    const arr = [
+      { name: '同时在线', num: tszx, unit: '人' },
+      { name: '特邀嘉宾', num: tyjb, unit: '人' },
+      { name: '洽谈合作', num: qthz, unit: '项' },
+      { name: '达成意向', num: dcyx, unit: '项' },
+      { name: '交易完成', num: jywc, unit: '项' },
+      { name: '参展项目', num: czxm, unit: '项' },
+    ];
+    return arr;
+
+  }
 }
 
 module.exports = IndexService;

+ 5 - 0
app/service/users/organization.js

@@ -7,6 +7,7 @@ const jwt = require('jsonwebtoken');
 class OrganizationService extends CrudService {
   constructor(ctx) {
     super(ctx, 'organization');
+    this.redis = this.app.redis;
     this.model = this.ctx.model.Organization;
   }
   /**
@@ -47,6 +48,10 @@ class OrganizationService extends CrudService {
     const data = _.omit(JSON.parse(JSON.stringify(object)), [ 'meta', 'password', '__v' ]);
     const { secret: secrets } = this.config.jwt;
     const token = jwt.sign(data, secrets);
+    // 记录登陆
+    let number = await this.redis.get('login_number') || 0;
+    number++;
+    await this.redis.set('login_number', number);
     return token;
   }
 

+ 5 - 0
app/service/users/personal.js

@@ -10,6 +10,7 @@ const assert = require('assert');
 class PersonalService extends CrudService {
   constructor(ctx) {
     super(ctx, 'personal');
+    this.redis = this.app.redis;
     this.model = this.ctx.model.Personal;
   }
   /**
@@ -50,6 +51,10 @@ class PersonalService extends CrudService {
     const data = _.omit(JSON.parse(JSON.stringify(object)), [ 'meta', 'password', '__v' ]);
     const { secret: secrets } = this.config.jwt;
     const token = jwt.sign(data, secrets);
+    // 记录登陆
+    let number = await this.redis.get('login_number') || 0;
+    number++;
+    await this.redis.set('login_number', number);
     return token;
   }
 

+ 21 - 4
app/service/util/util.js

@@ -2,6 +2,7 @@
 const _ = require('lodash');
 const moment = require('moment');
 const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { ObjectId } = require('mongoose').Types;
 const fs = require('fs');
 class UtilService extends CrudService {
   constructor(ctx) {
@@ -9,14 +10,30 @@ class UtilService extends CrudService {
     this.mq = this.ctx.mq;
   }
   async utilMethod(query, body) {
-    const path = 'C:\\Users\\liuruifeng\\Desktop\\temp\\export\\live_news_roadshow.json';
+    const path = 'C:\\Users\\liuruifeng\\Desktop\\temp\\export\\ChannelVideo.json';
     let text = await fs.readFileSync(path, { encoding: 'utf-8' });
     text = JSON.parse(text);
     for (const obj of text) {
-      const { dock_id } = obj;
-      if (dock_id) { obj.dock_id = { $oid: dock_id }; }
+      obj.channel_id = { $oid: obj.channel_id };
     }
-    await fs.writeFileSync('C:\\Users\\liuruifeng\\Desktop\\temp\\export\\live_news_roadshow-rewrite.json', JSON.stringify(text));
+    // const path = 'C:\\Users\\liuruifeng\\Desktop\\temp\\export\\dock.json';
+    // let text = await fs.readFileSync(path, { encoding: 'utf-8' });
+    // text = JSON.parse(text);
+    // const dockArr = [];
+    // const dockUser = [];
+    // for (const obj of text) {
+    //   const dock = _.pick(obj, [ '_id', 'room_id', 'password', 'title', 'start_time', 'end_time', 'province', 'place', 'adminuser', 'phone', 'sponsor', 'organizer', 'videodata', 'vipuser', 'desc', 'status' ]);
+    //   dockArr.push(dock);
+    //   const apply = _.get(obj, 'apply', []);
+    //   const { _id } = obj;
+    //   for (const a of apply) {
+    //     a.dock_id = _id;
+    //     a.user_id = { $oid: a.user_id };
+    //     dockUser.push(a);
+    //   }
+    // }
+    // // await fs.writeFileSync('C:\\Users\\liuruifeng\\Desktop\\temp\\export\\dock_data.json', JSON.stringify(dockArr));
+    await fs.writeFileSync('C:\\Users\\liuruifeng\\Desktop\\temp\\export\\ChannelVideo-rewrite.json', JSON.stringify(text));
     // const eupath = 'C:\\Users\\liuruifeng\\Desktop\\temp\\export\\expert,s_user.json';
     // let eutext = await fs.readFileSync(eupath, { encoding: 'utf-8' });
     // eutext = JSON.parse(eutext);

+ 4 - 4
config/plugin.js

@@ -5,8 +5,8 @@ exports.amqp = {
   enable: true,
   package: 'egg-naf-amqp',
 };
-// exports.redis = {
-//   enable: true,
-//   package: 'egg-redis',
-// };
+exports.redis = {
+  enable: true,
+  package: 'egg-redis',
+};