lrf 3 سال پیش
والد
کامیت
af10ece4dc
2فایلهای تغییر یافته به همراه142 افزوده شده و 51 حذف شده
  1. 4 4
      app/extend/application.js
  2. 138 47
      lib/service/crud-service.js

+ 4 - 4
app/extend/application.js

@@ -1,13 +1,13 @@
 'use strict';
-let colors = require('colors');
+const colors = require('colors');
 module.exports = {
   log(word) {
-    console.log(colors.brightBlue.italic.underline(word));
+    if (process.env.NODE_ENV === 'development') console.log(colors.brightBlue.italic.underline(word));
   },
   logSuccess(word) {
-    console.log(colors.brightGreen.italic.underline(word));
+    if (process.env.NODE_ENV === 'development') console.log(colors.brightGreen.italic.underline(word));
   },
   logError(word) {
-    console.log(colors.brightRed.italic.underline(word));
+    if (process.env.NODE_ENV === 'development') console.log(colors.brightRed.italic.underline(word));
   },
 };

+ 138 - 47
lib/service/crud-service.js

@@ -1,6 +1,6 @@
 'use strict';
 
-const { isString, isArray, cloneDeep, head: getHead, get } = require('lodash');
+const { isString, isArray, cloneDeep, head: getHead, get, omit } = require('lodash');
 const { isNullOrUndefined, trimData } = require('naf-core').Util;
 const assert = require('assert');
 const { ObjectId } = require('mongoose').Types;
@@ -8,16 +8,57 @@ const { BusinessError, ErrorCode } = require('naf-core').Error;
 const { NafService } = require('./naf-service');
 
 class CrudService extends NafService {
+  /**
+   * 创建前处理函数
+   * @param {Object} data 数据
+   */
+  beforeCreate(data) {
+    return data;
+  }
+  /**
+   * 创建后处理函数
+   * @param {Object} data  数据
+   */
+  afterCreate(data) {
+    return data;
+  }
+
   async create(data) {
     assert(data);
     // TODO:保存数据
-    const res = await this.model.create(data);
+    data = await this.beforeCreate(data);
+    let res = await this.model.create(data);
+    res = await this.afterCreate(res);
     return res;
   }
 
+  /**
+   * 修改前处理函数;需要将 查询条件和数据返回 (提供重写用,免去中间件)
+   * @param {Object} filter 查询条件
+   * @param {Object} update 数据
+   * @return {Object} 返回查询条件和数据
+   */
+  berforeUpdate(filter, update) {
+    return { filter, update };
+  }
+
+  /**
+   * 修改后处理函数;需要将 数据返回 (提供重写用,免去中间件)
+   * @param {Object} filter 查询条件
+   * @param {Object} data 数据
+   * @return {Object} 返回修改后的数据
+   */
+
+  afterUpdate(filter, data) {
+    return data;
+  }
+
   async update(filter, update, { projection } = {}) {
     assert(filter);
     assert(update);
+    const berforeUpdateResult = await this.berforeUpdate(filter, update);
+    filter = berforeUpdateResult.filter;
+    update = berforeUpdateResult.update;
     const { _id, id } = filter;
     if (_id || id) filter = { _id: ObjectId(_id || id) };
     // TODO:检查数据是否存在
@@ -27,22 +68,57 @@ class CrudService extends NafService {
     // TODO: 修改数据
     entity.set(trimData(update));
     await entity.save();
-    return await this.model.findOne(filter, projection).exec();
+    let reSearchData = await this.model.findOne(filter, projection).exec();
+    reSearchData = await this.afterUpdate(reSearchData);
+    return reSearchData;
   }
+  /**
+   * 删除前处理函数
+   * @param {Object} filter 查询条件
+   * @return {Object} 查询条件
+   */
+  beforeDelete(filter) {
+    return filter;
+  }
+  /**
+   * 删除后处理函数
+   * @param {Object} filter 查询条件
+   */
+  afterDelete(filter) {}
 
   async delete(filter) {
     assert(filter);
+    filter = await this.beforeDelete(filter);
     const { _id, id } = filter;
     if (_id || id) {
       await this.model.findByIdAndDelete(_id || id).exec();
     } else {
       await this.model.deleteMany(filter).exec();
     }
+    await this.afterDelete(filter);
     return 'deleted';
   }
+  /**
+   * 查询前处理函数
+   * @param {Object} filter 查询条件
+   * @return {Object} 查询条件
+   */
+  beforeFetch(filter) {
+    return filter;
+  }
+  /**
+   * 查询后处理函数
+   * @param {Object} filter 查询条件
+   * @param {Object} data 数据
+   * @return {Object} 查询条件
+   */
+  afterFetch(filter, data) {
+    return data;
+  }
 
   async fetch(filter, { sort, desc, projection } = {}) {
     assert(filter);
+    filter = await this.beforeFetch(filter);
     const { _id, id } = filter;
     if (_id || id) filter = { _id: ObjectId(_id || id) };
 
@@ -52,8 +128,16 @@ class CrudService extends NafService {
     } else if (sort && isArray(sort)) {
       sort = sort.map(f => ({ [f]: desc ? -1 : 1 })).reduce((p, c) => ({ ...p, ...c }), {});
     }
+    let res = await this.model.findOne(filter, projection).exec();
+    res = await this.afterFetch(filter, res);
+    return res;
+  }
 
-    return await this.model.findOne(filter, projection).exec();
+  beforeQuery(filter) {
+    return filter;
+  }
+  afterQuery(filter, data) {
+    return data;
   }
 
   async query(filter, { skip = 0, limit, sort, desc, projection } = {}) {
@@ -64,58 +148,65 @@ class CrudService extends NafService {
       sort = sort.map(f => ({ [f]: desc ? -1 : 1 })).reduce((p, c) => ({ ...p, ...c }), {});
     }
     let condition = cloneDeep(filter);
-    // 分站模式确认
+    condition = await this.beforeQuery(condition);
     condition = this.dealFilter(condition);
-    const isOpenMultiTenancy = get(this.app, 'plugins.multiTenancy');
-    if (isOpenMultiTenancy) {
-      const _tenant = this.isMultiTenancy();
-      if (_tenant) condition._tenant = _tenant;
-    }
-    const pipeline = [{ $match: condition }];
-    // 先排序
-    if (sort) pipeline.push({ $sort: sort });
-    // 再进行分页
-    if (limit) {
-      pipeline.push({ $skip: parseInt(skip) });
-      pipeline.push({ $limit: parseInt(limit) });
-    }
-    // 再将数据过滤
-    if (projection) pipeline.push({ $project: projection });
-    else {
-      const defaultProject = await this.getSelectFalse();
-      if (defaultProject)pipeline.push({ $project: defaultProject });
-    }
-    const rs = await this.model.aggregate(pipeline);
-    // const rs = await this.model.find(trimData(condition), projection, { skip, limit, sort }).exec();
+    // const pipeline = [{ $match: condition }];
+    // // 先排序
+    // if (sort) pipeline.push({ $sort: sort });
+    // // 再进行分页
+    // if (limit) {
+    //   pipeline.push({ $skip: parseInt(skip) });
+    //   pipeline.push({ $limit: parseInt(limit) });
+    // }
+    // // 再将数据过滤
+    // if (projection) pipeline.push({ $project: projection });
+    // else {
+    //   const defaultProject = await this.getSelectFalse();
+    //   if (defaultProject) pipeline.push({ $project: defaultProject });
+    // }
+    // let rs = await this.model.aggregate(pipeline);
+
+    // 过滤出ref字段
+    const refMods = await this.getRefMods();
+    const populate = refMods.map(i => i.col);
+    // 带ref查询
+    let rs = await this.model.find(trimData(condition), projection, { skip, limit, sort }).populate(populate).exec();
+    rs = JSON.parse(JSON.stringify(rs));
+    // 整理ref数据
+    rs = rs.map(i => {
+      for (const obj of refMods) {
+        const { col, prop } = obj;
+        if (!prop) continue;
+        i = { ...omit(i, [ col ]), [`${col}_${prop}`]: get(i, `${col}.${prop}`), [col]: get(i, `${col}._id`) };
+      }
+      return i;
+    });
+    rs = await this.afterQuery(filter, rs);
     return rs;
   }
 
+  async getRefMods() {
+    const mod = await this.getModel();
+    const refMods = [];
+    for (const key in mod) {
+      if (!mod[key].ref) continue;
+      refMods.push({ col: key, prop: mod[key].getProp });
+    }
+    return refMods;
+  }
+
   async count(filter) {
     let condition = cloneDeep(filter);
+    condition = await this.beforeQuery(condition);
     condition = this.dealFilter(condition);
-    // 分站模式确认
-    const isOpenMultiTenancy = get(this.app, 'plugins.multiTenancy');
-    if (isOpenMultiTenancy) {
-      const _tenant = this.isMultiTenancy();
-      if (_tenant) condition._tenant = _tenant;
-    }
-    let count = 0;
-    const res = await this.model.aggregate([{ $match: condition }, { $count: 'id' }]);
-    if (res && isArray(res)) {
-      const head = getHead(res);
-      count = get(head, 'id', 0);
-    }
+    const count = await this.model.count(condition);
+    // const res = await this.model.aggregate([{ $match: condition }, { $count: 'id' }]);
+    // if (res && isArray(res)) {
+    //   const head = getHead(res);
+    //   count = get(head, 'id', 0);
+    // }
     return count;
   }
-  /**
-   * 判断默认model是否是分站模式
-   * 是分站模式且不是master,就返回分站标识
-   */
-  isMultiTenancy() {
-    const is_multi = this.model.prototype.schema.options['multi-tenancy'];
-    const tenant = this.model.prototype.schema.options['x-tenant'];
-    if (is_multi && tenant !== 'master') return tenant;
-  }
 
   async queryAndCount(filter, options) {
     filter = this.dealFilter(filter);