lrf 3 lat temu
rodzic
commit
0fb2492b0a

+ 12 - 0
app/controller/.apply.js

@@ -44,4 +44,16 @@ module.exports = {
   compare: {
   compare: {
     requestBody: ['id', 'order'],
     requestBody: ['id', 'order'],
   },
   },
+  export: {
+    parameters: {
+      query: {
+        user_id: 'user_id',
+        user_name: '%user_name%',
+        status: 'status',
+        'apply_date@start': 'meta.createdAt@start',
+        'apply_date@end': 'meta.createdAt@end',
+      },
+    },
+    service: 'export',
+  },
 };
 };

+ 1 - 1
app/model/apply.js

@@ -12,7 +12,7 @@ const apply = {
   examine_name: { type: String }, // 审核人
   examine_name: { type: String }, // 审核人
   examine_desc: { type: String }, // 审核意见
   examine_desc: { type: String }, // 审核意见
   examine_date: { type: String }, // 审核时间
   examine_date: { type: String }, // 审核时间
-  status: { type: String,default:'0' }, // 审核状态
+  status: { type: String, default: '0' }, // 审核状态
   remark: { type: String },
   remark: { type: String },
 };
 };
 const schema = new Schema(apply, { toJSON: { virtuals: true } });
 const schema = new Schema(apply, { toJSON: { virtuals: true } });

+ 135 - 0
app/service/apply.js

@@ -3,12 +3,17 @@ const { CrudService } = require('naf-framework-mongoose-free/lib/service');
 const { BusinessError, ErrorCode } = require('naf-core').Error;
 const { BusinessError, ErrorCode } = require('naf-core').Error;
 const _ = require('lodash');
 const _ = require('lodash');
 const assert = require('assert');
 const assert = require('assert');
+const fs = require('fs');
+const { sep } = require('path');
+const Excel = require('exceljs');
+const moment = require('moment');
 
 
 // 申请表
 // 申请表
 class ApplyService extends CrudService {
 class ApplyService extends CrudService {
   constructor(ctx) {
   constructor(ctx) {
     super(ctx, 'apply');
     super(ctx, 'apply');
     this.model = this.ctx.model.Apply;
     this.model = this.ctx.model.Apply;
+    this.limit = 50;
   }
   }
 
 
   /**
   /**
@@ -33,6 +38,136 @@ class ApplyService extends CrudService {
     }
     }
     return order;
     return order;
   }
   }
+
+  /**
+   * 检查路径,创建路径;返回前端接收路径
+   */
+  async checkPath() {
+    const thisDir = 'apply';
+    const { root_path, export_dir } = this.ctx.app.config.export;
+    const arr = [ root_path, export_dir, thisDir ];
+    let rPath = '';
+    for (const i of arr) {
+      rPath = `${rPath}${i}${sep}`;
+      if (!fs.existsSync(rPath)) {
+        fs.mkdirSync(rPath);
+      }
+    }
+    arr.shift();
+    arr.unshift('files');
+    const path = `/${arr.join('/')}`;
+    return { path, rPath };
+  }
+
+  /**
+   * 导出
+   * @param {Object} query 查询条件
+   * @property {String} rPath 服务器位置(不包含文件名)
+   * @property {String} path 前端接收位置(不包含文件名)
+   */
+  async export(query) {
+    const { path, rPath } = await this.checkPath();
+    const fileName = `导出申请-${new Date().getTime()}.xlsx`;
+    const fullPath = `${path}/${fileName}`;
+    const fullRealPath = `${rPath}${sep}${fileName}`;
+    const total = await this.count(query);
+    const options = {
+      filename: fullRealPath,
+      useStyles: true,
+    };
+    const workbook = new Excel.stream.xlsx.WorkbookWriter(options);
+    const sheet = workbook.addWorksheet('sheet', {
+      pageSetup: {
+        horizontalCentered: true,
+        verticalCentered: true,
+      },
+    });
+    // 添加列头
+    const meta = this.getMeta();
+    const orderMeta = this.getOrderMeta();
+    const orderHead = orderMeta.map(i => i.zh);
+    const head = meta.map(i => i.zh);
+    sheet.addRow(head);
+    sheet.mergeCells(1, 4, 1, 6);
+    sheet.getRow(1).alignment = { vertical: 'middle', horizontal: 'center' };
+    let skip = 0;
+    for (let i = 0; i < total; i += this.limit) {
+      const data = await this.query(query, { skip, limit: this.limit });
+      // 去导出
+      for (let k = 0; k < data.length; k++) {
+        const e = data[k];
+        const arr = [];
+        for (const m of meta) {
+          const { key, format = i => i } = m;
+          const val = format(_.get(e, key));
+          // order额外处理
+          if (key !== 'order') arr.push(val);
+        }
+        arr.push(...orderHead);
+        sheet.addRow(arr).commit();
+        const orders = e.order;
+        for (const order of orders) {
+          // 商品,每行前3个都是空的
+          const orderArr = [];
+          for (let j = 0; j < orderHead.length; j++) orderArr.push('');
+          for (const om of orderMeta) {
+            const { key, format = i => i } = om;
+            const val = format(_.get(order, key));
+            orderArr.push(val);
+          }
+          sheet.addRow(orderArr).commit();
+        }
+
+      }
+
+      skip += this.limit;
+    }
+    sheet.commit();
+    await workbook.commit();
+    return fullPath;
+  }
+  // excel表头配置
+  getMeta() {
+    return [
+      { key: 'user_name', zh: '申请人' },
+      { key: 'status', zh: '状态', format: i => {
+        let val = '';
+        switch (i) {
+          case '0':
+            val = '待审核';
+            break;
+          case '1':
+            val = '通过';
+            break;
+          case '-1':
+            val = '拒绝';
+            break;
+          case '2':
+            val = '有货,可领取';
+            break;
+          case '3':
+            val = '无货,需采买';
+            break;
+          case '4':
+            val = '领取确认完成';
+            break;
+          default:
+            break;
+        }
+        return val;
+      } },
+      { key: 'meta.createdAt', zh: '时间', format: i => moment(i).format('YYYY-MM-DD') },
+      { key: 'order', zh: '商品' },
+    ];
+  }
+  // 商品表头
+  getOrderMeta() {
+    return [
+      { key: 'name', zh: '名称' },
+      { key: 'num', zh: '数量' },
+      { key: 'desc', zh: '特殊说明' },
+    ];
+  }
 }
 }
 
 
 module.exports = ApplyService;
 module.exports = ApplyService;

+ 1 - 0
app/z_router/apply.js

@@ -5,6 +5,7 @@ module.exports = app => {
   const { router, controller } = app;
   const { router, controller } = app;
   const profix = '/api/hc/';
   const profix = '/api/hc/';
   const target = 'apply';
   const target = 'apply';
+  router.post(target, `${profix}${target}/export`, controller[target].export);
   router.post(target, `${profix}${target}/compare`, controller[target].compare);
   router.post(target, `${profix}${target}/compare`, controller[target].compare);
   router.resources(target, `${profix}${target}`, controller[target]); // index、create、show、destroy
   router.resources(target, `${profix}${target}`, controller[target]); // index、create、show、destroy
   router.post(target, `${profix}${target}/update/:id`, controller[target].update);
   router.post(target, `${profix}${target}/update/:id`, controller[target].update);

+ 5 - 0
config/config.default.js

@@ -44,6 +44,11 @@ module.exports = appInfo => {
     },
     },
   };
   };
 
 
+  config.export = {
+    root_path: 'D:\\temp\\hc',
+    export_dir: 'export',
+  };
+
   return {
   return {
     ...config,
     ...config,
     ...userConfig,
     ...userConfig,

+ 5 - 0
config/config.prod.js

@@ -18,5 +18,10 @@ module.exports = () => {
       useCreateIndex: true,
       useCreateIndex: true,
     },
     },
   };
   };
+  config.export = {
+    root_path: '/usr/local/workspace/server/service-file/upload/hc',
+    export_dir: 'export',
+  };
+
   return config;
   return config;
 };
 };

+ 1 - 0
package.json

@@ -9,6 +9,7 @@
   "dependencies": {
   "dependencies": {
     "egg": "^2.15.1",
     "egg": "^2.15.1",
     "egg-scripts": "^2.11.0",
     "egg-scripts": "^2.11.0",
+    "exceljs": "^4.3.0",
     "lodash": "^4.17.21",
     "lodash": "^4.17.21",
     "moment": "^2.29.1",
     "moment": "^2.29.1",
     "naf-framework-mongoose-free": "^0.0.8"
     "naf-framework-mongoose-free": "^0.0.8"