lrf402788946 3 år sedan
förälder
incheckning
6e0c976b61

+ 2 - 2
app/controller/dining/.arrange.js

@@ -30,8 +30,8 @@ module.exports = {
     service: "query",
     options: {
       query: ["skip", "limit"],
-      sort: ["meta.createdAt"],
-      desc: true,
+      sort: ["date"],
+      asc: true,
       count: true,
     },
   },

+ 2 - 2
app/controller/dining/.menu.js

@@ -6,7 +6,7 @@ module.exports = {
       "order",
       "img",
       "content",
-      "calorie",
+      "reserve",
       "is_use",
     ],
   },
@@ -22,7 +22,7 @@ module.exports = {
       "order",
       "img",
       "content",
-      "calorie",
+      "reserve",
       "is_use",
     ],
   },

+ 7 - 6
app/controller/dining/.order.js

@@ -1,6 +1,6 @@
 module.exports = {
   create: {
-    requestBody: ['user_id','date','breakfast','lunch','dinner'],
+    requestBody: ["user_id", "date", "breakfast", "lunch", "dinner", "openid"],
   },
   destroy: {
     params: ["!id"],
@@ -8,7 +8,7 @@ module.exports = {
   },
   update: {
     params: ["!id"],
-    requestBody: ['user_id','date','breakfast','lunch','dinner'],
+    requestBody: ["user_id", "date", "breakfast", "lunch", "dinner", "openid"],
   },
   show: {
     parameters: {
@@ -19,8 +19,9 @@ module.exports = {
   index: {
     parameters: {
       query: {
-        "create_time@start": "create_time@start",
-        "create_time@end": "create_time@end",
+        openid: "openid",
+        "date@start": "date@start",
+        "date@end": "date@end",
       },
       // options: {
       //   "meta.state": 0 // 默认条件
@@ -34,7 +35,7 @@ module.exports = {
       count: true,
     },
   },
-  useMeal:{
+  useMeal: {
     params: ["!id"],
-  }
+  },
 };

+ 56 - 0
app/controller/system/.news.js

@@ -0,0 +1,56 @@
+module.exports = {
+  create: {
+    requestBody: [
+      "title",
+      "origin",
+      "create_time",
+      "content",
+      "img",
+      "type",
+      "brief",
+    ],
+  },
+  destroy: {
+    params: ["!id"],
+    service: "delete",
+  },
+  update: {
+    params: ["!id"],
+    requestBody: [
+      "title",
+      "origin",
+      "create_time",
+      "content",
+      "img",
+      "type",
+      "brief",
+    ],
+  },
+  show: {
+    parameters: {
+      params: ["!id"],
+    },
+    service: "fetch",
+  },
+  index: {
+    parameters: {
+      query: {
+        title: "title",
+        origin: "origin",
+        type: "type",
+        "create_time@start": "create_time@start",
+        "create_time@end": "create_time@end",
+      },
+      // options: {
+      //   "meta.state": 0 // 默认条件
+      // },
+    },
+    service: "query",
+    options: {
+      query: ["skip", "limit"],
+      sort: ["meta.createdAt"],
+      desc: true,
+      count: true,
+    },
+  },
+};

+ 13 - 0
app/controller/system/news.js

@@ -0,0 +1,13 @@
+'use strict';
+const meta = require('./.news.js');
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 新闻
+class NewsController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.system.news;
+  }
+}
+module.exports = CrudController(NewsController, meta);

+ 17 - 0
app/controller/system/weixin.js

@@ -0,0 +1,17 @@
+'use strict';
+const Controller = require('egg').Controller;
+const { CrudController } = require('naf-framework-mongoose/lib/controller');
+
+// 微信
+class WeixinController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+    this.service = this.ctx.service.system.weixin;
+  }
+
+  async appAuth() {
+    const data = await this.service.appAuth(this.ctx.query, this.ctx.tenant);
+    this.ctx.ok({ data });
+  }
+}
+module.exports = CrudController(WeixinController, {});

+ 35 - 0
app/middleware/order-num.js

@@ -0,0 +1,35 @@
+'use strict';
+const _ = require('lodash');
+const getOrderNum = async (ctx, data) => {
+  const keys = [ 'breakfast', 'lunch', 'dinner' ];
+  for (const key of keys) {
+    if (_.get(data.arrange, key) && _.isArray(_.get(data.arrange, key))) {
+      for (const i of _.get(data.arrange, key)) {
+        const res = await ctx.model.Dining.Menu.findById(i._id);
+        console.log(res.order);
+        if (res) i.order = res.order;
+      }
+    }
+  }
+  return data;
+};
+module.exports = options => {
+  return async function orderNum(ctx, next) {
+    await next();
+    const request = ctx.request;
+    const { method } = request;
+    if (method === 'GET') {
+      let { data } = ctx.body;
+      data = JSON.parse(JSON.stringify(data));
+      // 将所有的菜谱中的点餐数量都换成原id的数量,做成实时数据
+      if (_.isArray(data)) {
+        for (let d of data) {
+          d = await getOrderNum(ctx, d);
+        }
+      } else {
+        data = await getOrderNum(ctx, data);
+      }
+      ctx.body.data = data;
+    }
+  };
+};

+ 1 - 1
app/model/dining/menu.js

@@ -10,7 +10,7 @@ const menu = {
   order: { type: Number, default: 0 }, // 已点数量
   img: { type: Array }, // 图片
   content: { type: String }, // 本品介绍
-  calorie: { type: Number }, // 卡路里,单位:大卡 reserve
+  reserve: { type: Number }, // 卡路里,单位:大卡 reserve
   is_use: { type: Boolean, default: true }, // 可以点餐
   remark: { type: String },
 };

+ 6 - 3
app/model/dining/order.js

@@ -6,20 +6,23 @@ const { ObjectId } = require('mongoose').Types;
 const meal = new Schema({
   list: { type: Array }, // 点餐内容
   reserve: { type: Number, default: 0 }, // 卡路里,热量
-  is_use: { type: Boolean, default: false }, // 是否使用
+  is_use: { type: String, default: '0' }, // 是否使用:0-待使用;1-待评价;2-已完成;3-失效
 });
 // 订餐表
 const order = {
-  user_id: { type: String, required: true }, // 用户openid
+  user_id: { type: String }, // 用户id(预留)
   date: { type: String, required: true }, // 日期
   breakfast: { type: meal }, // 早餐
   lunch: { type: meal }, // 午餐
   dinner: { type: meal }, // 晚餐
+  openid: { type: String }, // openid
   remark: { type: String },
 };
-const schema = new Schema(order, { toJSON: { virtuals: true } });
+const schema = new Schema(order, { 'multi-tenancy': true, toJSON: { virtuals: true } });
 schema.index({ id: 1 });
 schema.index({ date: 1 });
+schema.index({ user_id: 1 });
+schema.index({ openid: 1 });
 schema.index({ 'meta.createdAt': 1 });
 schema.plugin(metaPlugin);
 module.exports = app => {

+ 1 - 1
app/model/system/admin-menu.js

@@ -13,7 +13,7 @@ const adminMenu = {
   sort: { type: Number, default: 0 }, // 排序:降序排列
   remark: { type: String },
 };
-const schema = new Schema(adminMenu, { toJSON: { virtuals: true } });
+const schema = new Schema(adminMenu, { 'multi-tenancy': true, toJSON: { virtuals: true } });
 schema.index({ id: 1 });
 schema.index({ 'meta.createdAt': 1 });
 schema.plugin(metaPlugin);

+ 27 - 0
app/model/system/news.js

@@ -0,0 +1,27 @@
+'use strict';
+const Schema = require('mongoose').Schema;
+const moment = require('moment');
+const metaPlugin = require('naf-framework-mongoose/lib/model/meta-plugin');
+const { ObjectId } = require('mongoose').Types;
+// 新闻表
+const news = {
+  title: { type: String }, // 标题
+  origin: { type: String }, // 来源
+  create_time: { type: String }, // 时间
+  content: { type: String }, // 内容
+  img: { type: Array }, // 图片,1张
+  type: { type: String, default: '0' }, // 类型:0-国内新闻;1-健康咨询
+  brief: { type: String }, // 简介
+  remark: { type: String },
+};
+const schema = new Schema(news, { 'multi-tenancy': true, toJSON: { virtuals: true } });
+schema.index({ id: 1 });
+schema.index({ title: 1 });
+schema.index({ type: 1 });
+schema.index({ create_time: 1 });
+schema.index({ 'meta.createdAt': 1 });
+schema.plugin(metaPlugin);
+module.exports = app => {
+  const { mongoose } = app;
+  return mongoose.model('News', schema, 'news');
+};

+ 1 - 1
app/model/system/opera.js

@@ -12,7 +12,7 @@ const opera = {
   remark: { type: String },
   // 操作时间转过来
 };
-const schema = new Schema(opera, { toJSON: { virtuals: true } });
+const schema = new Schema(opera, { 'multi-tenancy': true, toJSON: { virtuals: true } });
 schema.index({ id: 1 });
 schema.index({ user_id: 1 });
 schema.index({ target: 1 });

+ 3 - 0
app/router.js

@@ -7,7 +7,10 @@ module.exports = app => {
   const { router, controller } = app;
   router.get('/', controller.home.index);
   require('./router/system/admin')(app); // 管理员
+  require('./router/system/weixin')(app); // 微信相关
   require('./router/system/tenant')(app); // 站点管理
+  require('./router/system/news')(app); // 新闻管理
   require('./router/dining/menu')(app); // 菜单管理
   require('./router/dining/arrange')(app); // 安排管理
+  require('./router/dining/order')(app); // 订单管理
 };

+ 3 - 2
app/router/dining/arrange.js

@@ -6,7 +6,8 @@ module.exports = app => {
   const profix = `/api${config.appName ? `/${config.appName}` : ''}`;
   const index = 'dining';
   const target = 'arrange';
-  router.get(target, `${profix}/${index}/${target}/getByDate`, controller[index][target].getByDate);
-  router.resources(target, `${profix}/${index}/${target}`, controller[index][target]); // index、create、show、destroy
+  const on = app.middleware.orderNum();
+  router.get(target, `${profix}/${index}/${target}/getByDate`, on, controller[index][target].getByDate);
+  router.resources(target, `${profix}/${index}/${target}`, on, controller[index][target]); // index、create、show、destroy
   router.post(target, `${profix}/${index}/${target}/update/:id`, controller[index][target].update);
 };

+ 11 - 0
app/router/system/news.js

@@ -0,0 +1,11 @@
+'use strict';
+
+
+module.exports = app => {
+  const { router, controller, config } = app;
+  const profix = `/api${config.appName ? `/${config.appName}` : ''}`;
+  const index = 'system';
+  const target = 'news';
+  router.resources(target, `${profix}/${index}/${target}`, controller[index][target]); // index、create、show、destroy
+  router.post(target, `${profix}/${index}/${target}/update/:id`, controller[index][target].update);
+};

+ 10 - 0
app/router/system/weixin.js

@@ -0,0 +1,10 @@
+'use strict';
+
+
+module.exports = app => {
+  const { router, controller, config } = app;
+  const profix = `/api${config.appName ? `/${config.appName}` : ''}`;
+  const index = 'system';
+  const target = 'weixin';
+  router.get(target, `${profix}/${index}/${target}/appAuth`, controller[index][target].appAuth);
+};

+ 11 - 0
app/schedule/check-ticket.js

@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = {
+  schedule: {
+    interval: '10s', // 间隔
+    type: 'all', // 指定所有的 worker 都需要执行
+  },
+  async task(ctx) {
+    await ctx.service.dining.order.checkTimeOut();
+  },
+};

+ 9 - 0
app/service/dining/arrange.js

@@ -11,6 +11,15 @@ class ArrangeService extends CrudService {
     this.model = this.ctx.model.Dining.Arrange;
   }
 
+  async create(body) {
+    const { date } = body;
+    const _tenant = this.ctx.tenant;
+    let res = await this.model.findOne({ date, _tenant });
+    if (!res) res = await this.model.create(body);
+    else res = await this.model.updateOne({ _id: res._id }, body);
+    return res;
+  }
+
   /**
    * 获取某天的安排
    * @param {Object} query 参数

+ 27 - 0
app/service/dining/menu.js

@@ -10,6 +10,33 @@ class MenuService extends CrudService {
     super(ctx, 'menu');
     this.model = this.ctx.model.Dining.Menu;
   }
+
+  /**
+   * 添加数量
+   * @param {Object} order 每单点的所有菜
+   */
+  async addOrder(order) {
+    const { breakfast, lunch, dinner } = order;
+    let list = [];
+    const b = _.flattenDeep(breakfast.list);
+    const l = _.flattenDeep(lunch.list);
+    const d = _.flattenDeep(dinner.list);
+    list = [ ...b, ...l, ...d ];
+    list = _.groupBy(list, '_id');
+    const ids = Object.keys(list);
+    list = ids.map(i => {
+      return { _id: i, num: list[i].length };
+    });
+    for (const i of list) {
+      const { _id, num } = i;
+      const data = await this.model.findById(_id);
+      if (data) {
+        data.order = data.order + num;
+        await data.save();
+      }
+    }
+
+  }
 }
 
 module.exports = MenuService;

+ 33 - 2
app/service/dining/order.js

@@ -3,14 +3,19 @@ const { CrudService } = require('naf-framework-mongoose/lib/service');
 const { BusinessError, ErrorCode } = require('naf-core').Error;
 const _ = require('lodash');
 const assert = require('assert');
-
+const moment = require('moment');
 // 点餐
 class OrderService extends CrudService {
   constructor(ctx) {
     super(ctx, 'order');
     this.model = this.ctx.model.Dining.Order;
   }
-
+  async create(data) {
+    const res = await this.model.create(data);
+    // 所有菜品,都需要去加点单量
+    this.ctx.service.dining.menu.addOrder(data);
+    return res;
+  }
   /**
    * 扫码领餐
    * @param {Object} query 参数
@@ -19,6 +24,32 @@ class OrderService extends CrudService {
   async useMeal({ id }) {
     console.log(id);
   }
+
+  /**
+   * 检查所有的票是否过期
+   */
+  async checkTimeOut() {
+    const tenantList = await this.ctx.model.System.Tenant.find();
+    for (const site of tenantList) {
+      const { _tenant } = site;
+      // 赋值全局的分站识别变量,然service,model都变成该分站=切换分站
+      this.ctx.tenant = _tenant;
+      // 查出所有订餐记录
+      const list = await this.ctx.model.Dining.Order.find();
+      for (const order of list) {
+        const { date } = order;
+        // TODO 这三个时间点,应该是设置出来的,目前我写死了
+        const breakfast_time = `${date} 10:00`;
+        const lunch_time = `${date} 13:00`;
+        const dinner_time = `${date} 19:00`;
+        if (order.breakfast.list.length > 0 && moment().isSameOrAfter(breakfast_time)) order.breakfast.is_use = '3';
+        if (order.lunch.list.length > 0 && moment().isSameOrAfter(lunch_time)) order.lunch.is_use = '3';
+        if (order.dinner.list.length > 0 && moment().isSameOrAfter(dinner_time)) order.dinner.is_use = '3';
+        await order.save();
+      }
+    }
+
+  }
 }
 
 module.exports = OrderService;

+ 15 - 0
app/service/system/news.js

@@ -0,0 +1,15 @@
+'use strict';
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const _ = require('lodash');
+const assert = require('assert');
+
+// 新闻
+class NewsService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'news');
+    this.model = this.ctx.model.System.News;
+  }
+}
+
+module.exports = NewsService;

+ 33 - 0
app/service/system/weixin.js

@@ -0,0 +1,33 @@
+'use strict';
+const { CrudService } = require('naf-framework-mongoose/lib/service');
+const { BusinessError, ErrorCode } = require('naf-core').Error;
+const _ = require('lodash');
+const assert = require('assert');
+
+// 微信相关
+class WeixinService extends CrudService {
+  constructor(ctx) {
+    super(ctx, 'weixin');
+  }
+
+  async appAuth({ js_code }, tenant) {
+    if (!tenant) throw new BusinessError(ErrorCode.ACCESS_DENIED, '未找到分站');
+    const { wxApp } = this.app.config;
+    if (!wxApp) throw new BusinessError(ErrorCode.SERVICE_FAULT, '系统未启动小程序登录!');
+    if (!wxApp[tenant]) throw new BusinessError(ErrorCode.SERVICE_FAULT, '未设置该小程序相关信息!');
+    const { appid, secret } = wxApp[tenant];
+    const url = `https://api.weixin.qq.com/sns/jscode2session?appid=${appid}&secret=${secret}&js_code=${js_code}&grant_type=authorization_code`;
+    const res = await this.ctx.curl(url, {
+      method: 'get',
+      headers: {
+        'content-type': 'application/json',
+      },
+      dataType: 'json',
+    });
+    const { openid } = res.data;
+    if (!openid) throw new BusinessError(ErrorCode.BUSINESS, '未获取到openid', '未获取到openid');
+    return res.data;
+  }
+}
+
+module.exports = WeixinService;

+ 6 - 1
config/config.default.js

@@ -46,7 +46,12 @@ module.exports = appInfo => {
       // useCreateIndex: true,
     },
   };
-  config.wx = {};
+  config.wxApp = {
+    test: {
+      appid: 'wxe8b4c4d5e87a7d31',
+      secret: '60cffc9d8766e8b169db970d2422a647',
+    },
+  };
 
   return {
     ...config,