ソースを参照

feat: 材料调差-附件 功能已完成

lanjianrong 5 年 前
コミット
094e317288

+ 31 - 0
.github/workflows/nodejs.yml

@@ -0,0 +1,31 @@
+# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
+
+name: Node.js CI
+
+on:
+  push:
+    branches: [ master ]
+  pull_request:
+    branches: [ master ]
+
+jobs:
+  build:
+
+    runs-on: ${{ matrix.os }}
+
+    strategy:
+      matrix:
+        node-version: [6.x, 8.x]
+        os: [ubuntu-latest, windows-latest, macos-latest]
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Use Node.js ${{ matrix.node-version }}
+      uses: actions/setup-node@v1
+      with:
+        node-version: ${{ matrix.node-version }}
+    - run: npm i -g npminstall && npminstall
+    - run: npm run ci
+      env:
+        CI: true

+ 182 - 20
app/controller/material_controller.js

@@ -16,7 +16,11 @@ const measureType = tenderConst.measureType;
 const accountGroup = require('../const/account_group').group;
 const materialConst = require('../const/material');
 const MaterialCalculator = require('../lib/material_calc');
+const sendToWormhole = require('stream-wormhole');
+const fs = require('fs');
+const path = require('path');
 const _ = require('lodash');
+const { typeOf } = require('mathjs');
 
 module.exports = app => {
     class MaterialController extends app.BaseController {
@@ -36,7 +40,7 @@ module.exports = app => {
         /**
          * 期列表(Get)
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async index(ctx) {
             try {
@@ -73,7 +77,7 @@ module.exports = app => {
         /**
          * 期审批流程(Get)
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async materialAuditors(ctx) {
             try {
@@ -107,7 +111,7 @@ module.exports = app => {
         /**
          * 新增期(Post)
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async add(ctx) {
             try {
@@ -132,7 +136,7 @@ module.exports = app => {
         /**
          * 删除期(Post)
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async delete(ctx) {
             try {
@@ -160,7 +164,7 @@ module.exports = app => {
         /**
          * 获取通用的renderData(用于layout, Menu, subMenu部分)
          * @param ctx
-         * @returns {{tender, tenderMenu, auditConst}}
+         * @return {{tender, tenderMenu, auditConst}}
          * @private
          */
         async _getDefaultRenderData(ctx) {
@@ -192,7 +196,7 @@ module.exports = app => {
         /**
          * 获取审批界面所需的 原报、审批人数据等
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          * @private
          */
         async _getMaterialAuditViewData(ctx) {
@@ -214,7 +218,7 @@ module.exports = app => {
         /**
          * 调差工料页面 (Get)
          * @param {Object} ctx - egg全局变量
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async info(ctx) {
             try {
@@ -275,7 +279,7 @@ module.exports = app => {
         /**
          * 调差清单页面 (Get)
          * @param {Object} ctx - egg全局变量
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async list(ctx) {
             try {
@@ -309,9 +313,30 @@ module.exports = app => {
         }
 
         /**
+         * 附件页面 (Get)
+         * @param {Object} ctx - egg全局变量
+         * @return {Promise<void>}
+         */
+        async file(ctx) {
+            try {
+                await this._getMaterialAuditViewData(ctx);
+                const renderData = await this._getDefaultRenderData(ctx);
+                // 获取当前标段所有附件
+                // const searchsql = { tid: ctx.tender.id };
+                renderData.fileList = await ctx.service.materialFile.getAllMaterialFiles(ctx.tender.id, ctx.material.id);
+                renderData.auditors = ctx.material.auditors.map(audit => audit.aid);
+                renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.material.file);
+                await this.layout('material/file.ejs', renderData, 'material/file_modal.ejs');
+            } catch (err) {
+                this.log(err);
+                ctx.redirect('/tender/' + ctx.tender.id + '/measure/material');
+            }
+        }
+
+        /**
          * 调差清单 - 工料操作 (Ajax)
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async saveListsData(ctx) {
             try {
@@ -365,7 +390,7 @@ module.exports = app => {
         /**
          * 调差工料 - 编辑工料项 (Ajax)
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async saveBillsData(ctx) {
             try {
@@ -446,7 +471,7 @@ module.exports = app => {
         /**
          * 添加审批人
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async addAudit(ctx) {
             try {
@@ -465,7 +490,7 @@ module.exports = app => {
 
                 ctx.material.auditorList = await ctx.service.materialAudit.getAuditors(ctx.material.id, ctx.material.times);
                 // 检查审核人是否已存在
-                const exist = this.app._.find(ctx.material.auditorList, {aid: id});
+                const exist = this.app._.find(ctx.material.auditorList, { aid: id });
                 if (exist) {
                     throw '该审核人已存在,请勿重复添加';
                 }
@@ -476,16 +501,16 @@ module.exports = app => {
                 }
 
                 const audit = await ctx.service.materialAudit.getAuditor(ctx.material.id, id, ctx.material.times);
-                ctx.body = {err: 0, msg: '', data: audit};
+                ctx.body = { err: 0, msg: '', data: audit };
             } catch (err) {
                 this.log(err);
-                ctx.body = {err: 1, msg: err.toString(), data: null};
+                ctx.body = { err: 1, msg: err.toString(), data: null };
             }
         }
         /**
          * 移除审批人
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async deleteAudit(ctx) {
             try {
@@ -501,15 +526,15 @@ module.exports = app => {
                 }
 
                 const auditors = await ctx.service.materialAudit.getAuditors(ctx.material.id, ctx.material.times);
-                ctx.body = {err: 0, msg: '', data: auditors};
+                ctx.body = { err: 0, msg: '', data: auditors };
             } catch (err) {
-                ctx.body = {err: 1, msg: err.toString(), data: null};
+                ctx.body = { err: 1, msg: err.toString(), data: null };
             }
         }
         /**
          * 上报和重新上报
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async startAudit(ctx) {
             try {
@@ -536,7 +561,7 @@ module.exports = app => {
         /**
          * 审批
          * @param ctx
-         * @returns {Promise<void>}
+         * @return {Promise<void>}
          */
         async checkAudit(ctx) {
             try {
@@ -563,12 +588,149 @@ module.exports = app => {
 
                 ctx.redirect(ctx.request.header.referer);
             } catch (err) {
-                console.log(err);
                 this.log(err);
                 ctx.session.postError = err.toString();
                 ctx.redirect(ctx.request.header.referer);
             }
         }
+
+        /**
+         * 上传附件
+         * @param {*} ctx 上下文
+         */
+        async upload(ctx) {
+            let stream;
+            try {
+                const parts = this.ctx.multipart({
+                    autoFields: true,
+                });
+                const files = [];
+                const create_time = Date.parse(new Date()) / 1000;
+                while ((stream = await parts()) != null) {
+                    if (!stream.filename) {
+                        // 如果没有传入直接返回
+                        return;
+                    }
+                    const fileInfo = path.parse(stream.filename);
+                    const filepath = path.join('public/upload', this.ctx.tender.id.toString(), 'tc', 'fujian_' + create_time + fileInfo.ext);
+                    await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, 'app', filepath));
+                    files.push({ filepath, name: stream.filename });
+                    // 将上传的文件流消费掉,防止浏览器卡死
+                    stream && (await sendToWormhole(stream));
+                }
+                const upload_time = this.ctx.helper.dateTran(new Date());
+                const payload = files.map(file => {
+                    let idx;
+                    if (Array.isArray(parts.field.name)) {
+                        idx = parts.field.name.findIndex(name => name === file.name);
+                    } else {
+                        idx = 'isString';
+                    }
+                    const newFile = {
+                        tid: ctx.tender.id,
+                        user_id: ctx.session.sessionUser.accountId,
+                        mid: ctx.material.id,
+                        upload_time,
+                        file_path: file.filepath,
+                        file_size: ctx.helper.bytesToSize(idx === 'isString' ? parts.field.size : parts.field.size[idx]),
+                        file_name: file.name,
+                    };
+                    return newFile;
+                });
+                // 执行文件信息写入数据库
+                await ctx.service.materialFile.saveFileMsgToDb(payload);
+                // 将最新的当前标段的所有文件信息返回
+                const data = await ctx.service.materialFile.getAllMaterialFiles(ctx.tender.id, ctx.material.id);
+                ctx.body = { err: 0, msg: '', data };
+            } catch (err) {
+                stream && (await sendToWormhole(stream));
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
+        /**
+         * 查看当前标段以往所有期的附件
+         * @param {Object} ctx 上下文
+         */
+        async getCurMatericalFiles(ctx) {
+            try {
+                const { isCheck } = JSON.parse(ctx.request.body.data);
+                let data;
+                if (isCheck) {
+                    data = await ctx.service.materialFile.getAllMaterialFiles(ctx.tender.id);
+                } else {
+                    data = await ctx.service.materialFile.getAllMaterialFiles(ctx.tender.id, ctx.material.id);
+                }
+                ctx.body = { err: 0, msg: '', data };
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
+
+        /**
+         * 下载附件
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async downloadFile(ctx) {
+            const id = ctx.params.fid;
+            if (id) {
+                try {
+                    const fileInfo = await ctx.service.materialFile.getMaterialFileById(id);
+                    if (fileInfo) {
+                        const fileName = path.join(this.app.baseDir, './app', fileInfo.file_path);
+                        console.log(fileName);
+                        // 解决中文无法下载问题
+                        const userAgent = (ctx.request.header['user-agent'] || '').toLowerCase();
+                        let disposition = '';
+                        if (userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) {
+                            disposition = 'attachment; filename=' + encodeURIComponent(fileInfo.file_name);
+                        } else if (userAgent.indexOf('firefox') >= 0) {
+                            disposition = 'attachment; filename*="utf8\'\'' + encodeURIComponent(fileInfo.file_name) + '"';
+                        } else {
+                            /* safari等其他非主流浏览器只能自求多福了 */
+                            disposition = 'attachment; filename=' + new Buffer(fileInfo.file_name).toString('binary');
+                        }
+                        ctx.response.set({
+                            'Content-Type': 'application/octet-stream',
+                            'Content-Disposition': disposition,
+                            'Content-Length': fileInfo.file_size,
+                        });
+                        ctx.body = await fs.createReadStream(fileName);
+                    } else {
+                        throw '不存在该文件';
+                    }
+                } catch (err) {
+                    this.log(err);
+                    this.setMessage(err.toString(), this.messageType.ERROR);
+                }
+            }
+        }
+
+        /**
+         * 删除附件
+         * @param {Ojbect} ctx 上下文
+         */
+        async deleteFile(ctx) {
+            try {
+                const { data } = ctx.request.body;
+                const { id } = JSON.parse(data);
+                const fileInfo = await ctx.service.materialFile.getMaterialFileById(id);
+                if (fileInfo) {
+                    // 先删除文件
+                    await fs.unlinkSync(path.join(this.app.baseDir, './app', fileInfo.file_path));
+                    // 再删除数据库
+                    await ctx.service.materialFile.delete(id);
+                } else {
+                    throw '不存在该文件';
+                }
+                ctx.body = { err: 0, msg: '请求成功' };
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
     }
 
     return MaterialController;

+ 115 - 0
app/public/js/material_file.js

@@ -0,0 +1,115 @@
+'use strict';
+
+/**
+ * 材料调差 - 附件
+ * @author LanJianRong
+ * @date 2020/06/30
+ * @version
+ */
+
+$(document).ready(function () {
+    $('#upload-file-ok').click(function () {
+        const files = Array.from($('#upload-fujian-file')[0].files)
+        const valiData = files.map(v => {
+            const ext = v.name.substring(v.name.lastIndexOf('.') + 1)
+            return {
+                size: v.size,
+                ext
+            }
+        })
+        if (validateFiles(valiData)) {
+            if (files.length) {
+                const formData = new FormData()
+                files.forEach(file => {
+                    formData.append('file', file)
+                    formData.append('name', file.name)
+                    formData.append('size', file.size)
+                })
+                postDataWithFile(window.location.pathname + '/upload', formData, function (result) {
+                    $('#addfujian').modal('hide');
+                    let html = '';
+                    result.forEach((fileInfo, idx) => {
+                        html += `<tr>
+                        <td>${idx + 1}</td>
+                        <td><a href="/${fileInfo.file_path}">${fileInfo.file_name}</a></td>
+                        <td>${fileInfo.file_size}</td>
+                        <td>${fileInfo.upload_time}</td>`
+                    if (user_id == fileInfo.user_id && !checked) {
+                        html += `<td>
+                        <a class="btn btn-light btn-sm delete-file" data-attid="${fileInfo.id}" title="删除附件">
+                        <span class="fa fa-trash text-danger"></span>
+                        </a>
+                        </td></tr>`
+                    } else {
+                        html += `<td></td></tr>`
+                    }
+                    })
+                    $('#file-list').empty();
+                    $('#file-list').append(html);
+                    console.log(result)
+                });
+            }
+        }
+    })
+    $('#file-checkbox').click(function() {
+        let isCheck = false
+        if($(this).is(':checked')) {
+            isCheck = true
+        }
+        postData(window.location.pathname + '/find', {isCheck}, function(result) {
+            let html = '';
+            result.forEach((fileInfo, idx) => {
+                html += `<tr>
+                <td>${idx + 1 }</td>
+                <td><a href="/${fileInfo.file_path}">${fileInfo.file_name}</a></td>
+                <td>${fileInfo.file_size}</td>
+                <td>${fileInfo.upload_time}</td>`
+                if (user_id == fileInfo.user_id && !checked) {
+                    html += `<td>
+                    <a class="btn btn-light btn-sm delete-file" data-attid="${fileInfo.id}" title="删除附件">
+                    <span class="fa fa-trash text-danger"></span>
+                    </a>
+                    </td></tr>`
+                } else {
+                    html += `<td></td></tr>`
+                }
+            })
+            $('#file-list').empty();
+            $('#file-list').append(html);
+        })
+    })
+    // 删除附件
+    $('body').on('click', '.delete-file', function () {
+        let attid = $(this).data('attid');
+        let self = $(this);
+        const data = {id: attid};
+        postData('/tender/measure/material/file/delete', data, function (result) {
+            self.parents('tr').remove();
+            // 重新排序
+            let newsort = 1;
+            $('#file-list tr').each(function(){
+                $(this).children('td').eq(0).text(newsort);
+                newsort++;
+            });
+        });
+    });
+});
+
+/**
+ * 校验文件大小、格式
+ * @param {Array} files 文件数组
+ */
+function validateFiles(files) {
+    const reg = /(doc|docx|excel|xlsx|xls|txt|zip|jpg|jpeg|png|bmp|BMP|JPG|PNG|JPEG)$/;
+    return files.every(file => {
+        if (file.size > 1024 * 1024 * 10) {
+            toastr.error('文件大小限制为10MB');
+            return false
+        }
+        if (!reg.test(file.ext)) {
+            toastr.error('请上传正确的格式文件');
+            return false
+        }
+        return true
+    })
+}

+ 1 - 0
app/public/js/stage.js

@@ -2545,6 +2545,7 @@ $(document).ready(() => {
                     updateData.imgInfo = itemInfo;
                     updateData.calc_img_remark = img_remark;
                     self.updateImageData = updateData;
+                    console.log(updateData)
                     $('#calc-img').attr('src', updateData.img);
                     $('#view-calc-img').attr('src', updateData.img);
                     $('#show-calc-img').attr('src', updateData.img);

+ 7 - 0
app/router.js

@@ -286,6 +286,13 @@ module.exports = app => {
     app.get('/tender/:id/measure/material/:order/list', sessionAuth, tenderCheck, materialCheck, 'materialController.list');
     app.post('/tender/:id/measure/material/:order/list/save', sessionAuth, tenderCheck, materialCheck, 'materialController.saveListsData');
 
+    // 附件
+    app.get('/tender/:id/measure/material/:order/file', sessionAuth, tenderCheck, materialCheck, 'materialController.file');
+    app.post('/tender/:id/measure/material/:order/file/upload', sessionAuth, tenderCheck, materialCheck, 'materialController.upload');
+    app.post('/tender/:id/measure/material/:order/file/find', sessionAuth, tenderCheck, materialCheck, 'materialController.getCurMatericalFiles');
+    app.get('/tender/measure/material/file/download/:fid', sessionAuth, 'materialController.downloadFile');
+    app.post('/tender/measure/material/file/delete', sessionAuth, 'materialController.deleteFile');
+
     // 个人账号相关
     app.get('/profile/info', sessionAuth, 'profileController.info');
     app.get('/profile/sms', sessionAuth, 'profileController.sms');

+ 67 - 0
app/service/material_file.js

@@ -0,0 +1,67 @@
+'use strict';
+const fs = require('fs');
+const path = require('path');
+
+/**
+ * 附件表 数据模型
+ * @author LanJianRong
+ * @date 2020/6/30
+ * @version
+ */
+
+module.exports = app => {
+    class MaterialFile extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'material_file';
+        }
+
+        /**
+         * 获取当前标段所有上传的附件
+         * @param {Number} tenderId 标段id
+         * @param {Number} mid 期id
+         * @return {Promise<void>} 数据库查询实例
+         */
+        async getAllMaterialFiles(tenderId, mid) {
+            const where = mid ? { tid: tenderId, mid } : { tid: tenderId };
+            return await this.db.select(this.tableName, {
+                where,
+            });
+        }
+
+        /**
+         * 存储上传的文件信息至数据库
+         * @param {Array} payload 载荷
+         * @return {Promise<void>} 数据库插入执行实例
+         */
+        async saveFileMsgToDb(payload) {
+            return await this.db.insert(this.tableName, payload);
+        }
+
+        /**
+         * 获取单个文件信息
+         * @param {Number} id 文件id
+         * @return {Promise<void>} 数据库查询实例
+         */
+        async getMaterialFileById(id) {
+            return await this.getDataByCondition({ id });
+        }
+
+        /**
+         * 删除附件
+         * @param {Number} id - 附件id
+         * @return {void}
+         */
+        async delete(id) {
+            return await this.deleteById(id);
+        }
+    }
+    return MaterialFile;
+};
+

+ 55 - 0
app/view/material/file.ejs

@@ -0,0 +1,55 @@
+<% include ./material_sub_menu.ejs %>
+<div class="panel-content">
+  <div class="panel-title">
+    <div class="title-main d-flex justify-content-between">
+      <div class="d-flex justify-content-start align-items-center">
+        <% if(auditors.includes(ctx.session.sessionUser.accountId)) { %>
+          <a href="#addfujian" data-toggle="modal" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="添加清单"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 上传附件</a>
+        <% } %>
+          <span class="d-flex align-items-center" style="margin-left: 5px;">
+            <input type="checkbox" id="file-checkbox">
+            <span class="text-primary" style="margin-left: 5px;">所有期</span>
+          </span>
+        </div>
+      <div>
+        <a href="#sub-ap" data-toggle="modal" data-target="#sub-ap" class="btn btn-sm btn-primary pull-right">上报审批</a>
+      </div>
+    </div>
+  </div>
+  <div class="content-wrap">
+    <div class="c-body">
+      <div class="sjs-height-0">
+        <table class="table table-bordered">
+          <thead>
+            <tr><th width="50">序号</th><th>名称</th><th width="90">大小</th><th width="100">上传时间</th><th width="100">操作</th></tr>
+          </thead>
+          <tbody id="file-list">
+            <% fileList.forEach(function(file, idx){ %>
+              <tr>
+                <td><%=idx + 1%></td>
+                <td>
+                  <a href="/<%- file.file_path %>" target="_blank"><%=file.file_name%></a>
+                </td><td><%=file.file_size%></td>
+                <td><%=file.upload_time%></td>
+                <td>
+                  <% if(material.status !== auditConst.status.checked &&
+                  ctx.session.sessionUser.accountId === file.user_id) { %>
+                    <a href="javascript: void;" class="btn btn-light btn-sm delete-file" title="删除附件" data-attid="<%- file.id %>">
+                      <span class="fa fa-trash text-danger"></span>
+                    </a>
+                  <% } %>
+                </td>
+              </tr>
+            <% }) %>
+          </tbody>
+        </table>
+      </div>
+    </div>
+  </div>
+</div>
+<script>
+  const curMaterialStatus = <%- material.status %>;
+  // const auditConstCheck =  <%- auditConst.status.checked %>;
+  const fileList = <%- fileList %>;
+  const auditors = <%- auditors %>;
+</script>

+ 54 - 0
app/view/material/file_modal.ejs

@@ -0,0 +1,54 @@
+<!--添加附件-->
+<div class="modal fade" id="addfujian">
+    <div class="modal-dialog" role="document">
+      <div class="modal-content">
+        <div class="modal-header">
+          <h5 class="modal-title" id="myModalLabel">上传附件</h5>
+      <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+        <span aria-hidden="true">&times;</span>
+      </button>
+        </div>
+        <div class="modal-body">
+          <p>大小限制:10MB,支持office等文档格式、图片格式、压缩包格式</p>
+                  <p>
+                      <input id="upload-fujian-file" type="file" multiple="multiple">
+                      <!-- <a href="javascript: void(0);" id="upload-fujian" class="btn btn-primary">选择文件</a> -->
+                    </p>
+        </div>
+    <div class="modal-footer">
+      <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+        <button id="upload-file-ok" type="button" class="btn btn-primary">添加</button>
+    </div>
+      </div>
+    </div>
+  </div>
+<!--提交审批-->
+  <div class="modal fade" id="sub-ap" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+    <div class="modal-dialog" role="document">
+      <div class="modal-content">
+        <div class="modal-header">
+          <h5 class="modal-title" id="myModalLabel">提交审批</h5>
+      <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+        <span aria-hidden="true">&times;</span>
+      </button>
+        </div>
+        <div class="modal-body">
+            <h5>还没添加任何变更清单,无法提交。</h5>
+            <h5>还没设置审批流程,无法提交。</h5>
+            <h5>确认提交审批?</h5>
+        </div>
+        <div class="modal-footer">
+      <!--无法提交-->
+          <button type="button" class="btn btn-secondary" data-dismiss="modal">好的</button>
+      <!--确认提交-->
+          <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+      <button type="button" class="btn btn-primary" data-dismiss="modal">确认提交</button>
+        </div>
+      </div>
+    </div>
+  </div>
+  <% include ./audit_modal.ejs %>
+<script>
+  const user_id = '<%- ctx.session.sessionUser.accountId %>';
+  const checked = '<%- material.status === auditConst.status.checked %>';
+</script>

+ 7 - 0
app/view/material/material_sub_menu.ejs

@@ -24,6 +24,13 @@
                     </li>
                 </ul>
             </div>
+        <div class="nav-box">
+            <ul class="nav-list list-unstyled">
+                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/material/' + ctx.material.order + '/file') { %>active<% } %>">
+                    <a href="/tender/<%- ctx.tender.id %>/measure/material/<%- material.order %>/file"><span class="ml-3">附件</span></a>
+                </li>
+            </ul>
+        </div>
         <% include ./audit_btn.ejs %>
         <div class="side-fold"><a href="javascript: void(0)" data-toggle="tooltip" data-placement="top" data-original-title="折叠侧栏" id="to-mini-menu"><i class="fa fa-sign-out fa-flip-horizontal"></i></a></div>
     </div>

+ 375 - 365
config/web.js

@@ -32,390 +32,390 @@
  * @version
  */
 const JsFiles = {
-    webPath: "/public/js/web/",
+    webPath: '/public/js/web/',
     commonFiles: [
-        "/public/js/jquery/jquery-3.2.1.min.js",
-        "/public/js/jquery/jquery-ui.js",
-        "/public/js/jquery/jquery.validate.js",
-        "/public/js/messages_zh.js",
-        "/public/js/popper/popper.min.js",
-        "/public/js/bootstrap/bootstrap.min.js",
-        "/public/js/vue/vue.js",
-        "/public/js/component/input.js",
-        "/public/js/cookies.js",
-        "/public/js/jquery-contextmenu/jquery.ui.position.min.js",
-        "/public/js/jquery-contextmenu/jquery.contextMenu.min.js",
-        "/public/js/lodash.js",
-        "/public/js/lz-string/lz-string.js",
-        "/public/js/number-precision.js",
-        "/public/js/toastr.min.js",
-        "/public/js/global.js",
+        '/public/js/jquery/jquery-3.2.1.min.js',
+        '/public/js/jquery/jquery-ui.js',
+        '/public/js/jquery/jquery.validate.js',
+        '/public/js/messages_zh.js',
+        '/public/js/popper/popper.min.js',
+        '/public/js/bootstrap/bootstrap.min.js',
+        '/public/js/vue/vue.js',
+        '/public/js/component/input.js',
+        '/public/js/cookies.js',
+        '/public/js/jquery-contextmenu/jquery.ui.position.min.js',
+        '/public/js/jquery-contextmenu/jquery.contextMenu.min.js',
+        '/public/js/lodash.js',
+        '/public/js/lz-string/lz-string.js',
+        '/public/js/number-precision.js',
+        '/public/js/toastr.min.js',
+        '/public/js/global.js',
     ],
     controller: {
         tender: {
             list: {
                 files: [
-                    "/public/js/ztree/jquery.ztree.core.js",
-                    "/public/js/ztree/jquery.ztree.exedit.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/moment/moment.min.js",
+                    '/public/js/ztree/jquery.ztree.core.js',
+                    '/public/js/ztree/jquery.ztree.exedit.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/moment/moment.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/zh_calc.js",
-                    "/public/js/shares/tender_list_order.js",
-                    "/public/js/tender_showhide.js",
-                    "/public/js/tender_list.js"
+                    '/public/js/zh_calc.js',
+                    '/public/js/shares/tender_list_order.js',
+                    '/public/js/tender_showhide.js',
+                    '/public/js/tender_list.js',
                 ],
                 mergeFile: 'tender_list',
             },
             info: {
                 files: [
-                    "/public/js/ztree/jquery.ztree.core.js",
-                    "/public/js/ztree/jquery.ztree.exedit.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/ztree/jquery.ztree.core.js',
+                    '/public/js/ztree/jquery.ztree.exedit.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/zh_calc.js",
-                    "/public/js/shares/tender_list_order.js",
-                    "/public/js/tender_showhide.js",
-                    "/public/js/tender_list_info.js"
+                    '/public/js/zh_calc.js',
+                    '/public/js/shares/tender_list_order.js',
+                    '/public/js/tender_showhide.js',
+                    '/public/js/tender_list_info.js',
                 ],
                 mergeFile: 'tender_list_info',
             },
             progress: {
                 files: [
-                    "/public/js/ztree/jquery.ztree.core.js",
-                    "/public/js/ztree/jquery.ztree.exedit.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/ztree/jquery.ztree.core.js',
+                    '/public/js/ztree/jquery.ztree.exedit.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/zh_calc.js",
-                    "/public/js/shares/tender_list_order.js",
-                    "/public/js/tender_showhide.js",
-                    "/public/js/tender_list_progress.js"
+                    '/public/js/zh_calc.js',
+                    '/public/js/shares/tender_list_order.js',
+                    '/public/js/tender_showhide.js',
+                    '/public/js/tender_list_progress.js',
                 ],
                 mergeFile: 'tender_list_progress',
             },
             manage: {
                 files: [
-                    "/public/js/ztree/jquery.ztree.core.js",
-                    "/public/js/ztree/jquery.ztree.exedit.js",
-                    "/public/js/moment/moment.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/ztree/jquery.ztree.core.js',
+                    '/public/js/ztree/jquery.ztree.exedit.js',
+                    '/public/js/moment/moment.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/zh_calc.js",
-                    "/public/js/shares/tender_list_order.js",
-                    "/public/js/tender_showhide.js",
-                    "/public/js/tender_list_manage.js",
+                    '/public/js/zh_calc.js',
+                    '/public/js/shares/tender_list_order.js',
+                    '/public/js/tender_showhide.js',
+                    '/public/js/tender_list_manage.js',
                 ],
                 mergeFile: 'tender_list_manage',
             },
             tenderInfo: {
                 files: [
-                    "/public/js/echarts/echarts.min.js",
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/echarts/echarts.min.js',
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/zh_calc.js",
-                    //"/public/js/tender.js",
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    // "/public/js/tender.js",
                 ],
                 mergeFile: 'tender',
-            }
+            },
         },
         ledger: {
             explode: {
                 files: [
-                    "/public/js/js-xlsx/xlsx.full.min.js",
-                    "/public/js/js-xlsx/xlsx.utils.js",
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/math.min.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
-                ],
-                mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/shares/merge_peg.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/ledger_tree_col.js",
-                    "/public/js/std_lib.js",
-                    "/public/js/ledger.js",
+                    '/public/js/js-xlsx/xlsx.full.min.js',
+                    '/public/js/js-xlsx/xlsx.utils.js',
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/math.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
+                ],
+                mergeFiles: [
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/shares/merge_peg.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/ledger_tree_col.js',
+                    '/public/js/std_lib.js',
+                    '/public/js/ledger.js',
                 ],
                 mergeFile: 'explode',
             },
             audit: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/ledger_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/ledger_audit.js',
                 ],
                 mergeFile: 'ledger_audit',
             },
             bwtz: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/shares/bills_pos_convert.js",
-                    "/public/js/ledger_bwtz.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/shares/bills_pos_convert.js',
+                    '/public/js/ledger_bwtz.js',
                 ],
                 mergeFile: 'ledger_bwtz',
             },
             gather: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/gcl_gather.js",
-                    "/public/js/ledger_gather.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/gcl_gather.js',
+                    '/public/js/ledger_gather.js',
                 ],
                 mergeFile: 'ledger_gather',
             },
             revise: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/std_lib.js",
-                    "/public/js/revise.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/std_lib.js',
+                    '/public/js/revise.js',
                 ],
                 mergeFile: 'revise',
-            }
+            },
         },
         revise: {
             info: {
                 files: [
-                    "/public/js/js-xlsx/xlsx.full.min.js",
-                    "/public/js/js-xlsx/xlsx.utils.js",
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/math.min.js",
+                    '/public/js/js-xlsx/xlsx.full.min.js',
+                    '/public/js/js-xlsx/xlsx.utils.js',
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/math.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/shares/merge_peg.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/std_lib.js",
-                    "/public/js/revise.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/shares/merge_peg.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/std_lib.js',
+                    '/public/js/revise.js',
                 ],
                 mergeFile: 'revise',
             },
             history: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/revise_history.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/revise_history.js',
                 ],
                 mergeFile: 'revise_history',
-            }
+            },
         },
         stage: {
             // 本期计量台账
             index: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/math.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/math.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/msg_box.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/shares/merge_peg.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/stage_im.js",
-                    "/public/js/stage.js",
-                    "/public/js/stage_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/msg_box.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/shares/merge_peg.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/stage_im.js',
+                    '/public/js/stage.js',
+                    '/public/js/stage_audit.js',
                 ],
                 mergeFile: 'stage',
             },
             detail: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/html2canvas/html2canvas.min.js",
-                    "/public/js/html2canvas/canvas2image.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/html2canvas/html2canvas.min.js',
+                    '/public/js/html2canvas/canvas2image.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/stage_im.js",
-                    "/public/js/stage_detail.js",
-                    "/public/js/stage_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/stage_im.js',
+                    '/public/js/stage_detail.js',
+                    '/public/js/stage_audit.js',
                 ],
                 mergeFile: 'stage_detail',
             },
             pay: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/math.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/math.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/stage_pay.js",
-                    "/public/js/stage_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/stage_pay.js',
+                    '/public/js/stage_audit.js',
                 ],
                 mergeFile: 'stage_pay',
             },
             bwtz: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/shares/bills_pos_convert.js",
-                    "/public/js/stage_bwtz.js",
-                    "/public/js/stage_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/shares/bills_pos_convert.js',
+                    '/public/js/stage_bwtz.js',
+                    '/public/js/stage_audit.js',
                 ],
                 mergeFile: 'stage_bwtz',
             },
             change: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/stage_change.js",
-                    "/public/js/stage_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/stage_change.js',
+                    '/public/js/stage_audit.js',
                 ],
                 mergeFile: 'stage_change',
             },
             gather: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/gcl_gather.js",
-                    "/public/js/stage_gather.js",
-                    "/public/js/stage_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/gcl_gather.js',
+                    '/public/js/stage_gather.js',
+                    '/public/js/stage_audit.js',
                 ],
                 mergeFile: 'stage_gather',
             },
             compare: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/stage_compare.js",
-                    "/public/js/stage_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/stage_compare.js',
+                    '/public/js/stage_audit.js',
                 ],
                 mergeFile: 'stage_compare',
             },
             manager: {
                 files: [
-                    "/public/js/decimal.min.js",
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/shares/cs_tools.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/stage_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/shares/cs_tools.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/stage_audit.js',
                 ],
                 mergeFile: 'stage_manager',
             },
@@ -423,55 +423,55 @@ const JsFiles = {
         stageExtra: {
             jgcl: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/se_jgcl.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/se_jgcl.js',
                 ],
                 mergeFile: 'se_jgcl',
             },
             bonus: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/datepicker/datepicker.min.js",
-                    "/public/js/datepicker/datepicker.zh.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/datepicker/datepicker.min.js',
+                    '/public/js/datepicker/datepicker.zh.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/se_bonus.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/se_bonus.js',
                 ],
                 mergeFile: 'se_bonus',
             },
             other: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/datepicker/datepicker.min.js",
-                    "/public/js/datepicker/datepicker.zh.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/datepicker/datepicker.min.js',
+                    '/public/js/datepicker/datepicker.zh.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/se_other.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/se_other.js',
                 ],
                 mergeFile: 'se_other',
             },
@@ -479,91 +479,101 @@ const JsFiles = {
         measure: {
             compare: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/file-saver/FileSaver.js",
-                    "/public/js/shares/export_excel.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/spreadjs/sheets/v11/interop/gc.spread.excelio.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/file-saver/FileSaver.js',
+                    '/public/js/shares/export_excel.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/measure_compare.js"
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/measure_compare.js',
                 ],
                 mergeFile: 'measure_compare',
-            }
+            },
         },
         material: {
             info: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/toastr.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/toastr.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/material.js",
-                    "/public/js/material_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/material.js',
+                    '/public/js/material_audit.js',
                 ],
                 mergeFile: 'material',
             },
             list: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/toastr.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/toastr.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/gcl_gather.js",
-                    "/public/js/material_list.js",
-                    "/public/js/material_audit.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/gcl_gather.js',
+                    '/public/js/material_list.js',
+                    '/public/js/material_audit.js',
                 ],
                 mergeFile: 'material_list',
             },
+            file: {
+                files: [
+                    '/public/js/toastr.min.js',
+                ],
+                mergeFiles: [
+                    '/public/js/sub_menu.js',
+                    '/public/js/material_file.js',
+                ],
+                mergeFile: 'material_file',
+            },
         },
         compare: {
             tz: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/compare_tz.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/compare_tz.js',
                 ],
                 mergeFile: 'compare_tz',
             },
             stage: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/compare_stage.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/compare_stage.js',
                 ],
                 mergeFile: 'compare_stage',
             },
@@ -571,33 +581,33 @@ const JsFiles = {
         gather: {
             tz: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/gather_tz.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/gather_tz.js',
                 ],
                 mergeFile: 'gather_tz',
             },
             stage: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/gather_stage.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/gather_stage.js',
                 ],
                 mergeFile: 'gather_stage',
             },
@@ -605,39 +615,39 @@ const JsFiles = {
         tools: {
             checkTz: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/sub_menu.js",
-                    "/public/js/div_resizer.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/sjs_setting.js",
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/spss_check_tz.js",
+                    '/public/js/sub_menu.js',
+                    '/public/js/div_resizer.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/sjs_setting.js',
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/spss_check_tz.js',
                 ],
                 mergeFile: 'spss_check_tz',
-            }
+            },
         },
         report: {
             main: {
                 files: [
-                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
-                    "/public/js/decimal.min.js",
-                    "/public/js/moment/moment.min.js",
+                    '/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js',
+                    '/public/js/decimal.min.js',
+                    '/public/js/moment/moment.min.js',
                 ],
                 mergeFiles: [
-                    "/public/js/zh_calc.js",
-                    "/public/js/path_tree.js",
-                    "/public/js/spreadjs_rela/spreadjs_zh.js",
-                    "/public/js/shares/tenders2tree.js",
-                    "/public/report/js/rpt_custom.js",
+                    '/public/js/zh_calc.js',
+                    '/public/js/path_tree.js',
+                    '/public/js/spreadjs_rela/spreadjs_zh.js',
+                    '/public/js/shares/tenders2tree.js',
+                    '/public/report/js/rpt_custom.js',
                 ],
                 mergeFile: 'report_main',
-            }
-        }
-    }
+            },
+        },
+    },
 
 };