Browse Source

变更令附件功能

laiguoran 6 years ago
parent
commit
13dfd9ee99

+ 1 - 1
app/base/base_service.js

@@ -79,7 +79,7 @@ class BaseService extends Service {
     }
 
     /**
-     * 根据条件查找单条数据
+     * 根据条件查找列表数据
      *
      * @param {Object} condition - 筛选条件
      * @return {Array} - 返回数据

+ 128 - 1
app/controller/change_controller.js

@@ -9,10 +9,12 @@
  */
 
 const moment = require('moment');
+const fs = require('fs');
+const path = require('path');
 const audit = require('../const/audit');
 const codeRuleConst = require('../const/code_rule');
 const changeConst = require('../const/change');
-const tenderMenu = require('../../config/menu').tenderMenu;
+// const tenderMenu = require('../../config/menu').tenderMenu;
 
 module.exports = app => {
     class ChangeController extends app.BaseController {
@@ -109,6 +111,7 @@ module.exports = app => {
          */
         async index(ctx) {
             try {
+                console.log(ctx);
                 await this._filterChanges(ctx);
             } catch (err) {
                 this.log(err);
@@ -213,6 +216,7 @@ module.exports = app => {
          */
         async info(ctx) {
             try {
+                const whiteList = this.ctx.app.config.multipart.whitelist;
                 const tid = ctx.session.sessionUser.tenderId !== undefined ? ctx.session.sessionUser.tenderId : ctx.params.id;
                 const tender = await this.service.tender.getDataById(tid);
                 const change = await ctx.service.change.getDataByCondition({cid: ctx.params.cid});
@@ -223,6 +227,9 @@ module.exports = app => {
                 // 获取公司列表
                 const companyList = await ctx.service.changeCompany.getAllDataByCondition({ tid: tid });
 
+                // 获取附件列表
+                const attList = await ctx.service.changeAtt.getAllDataByCondition({ cid: ctx.params.cid });
+
                 const renderData = {
                     uid: ctx.session.sessionUser.accountId,
                     tender,
@@ -231,6 +238,8 @@ module.exports = app => {
                     auditStatus,
                     auditConst: audit.flow,
                     companyList,
+                    attList,
+                    whiteList,
                 };
                 await this.layout('change/info.ejs', renderData, 'change/info_modal.ejs');
             } catch (err) {
@@ -314,6 +323,124 @@ module.exports = app => {
 
             ctx.body = responseData;
         }
+
+        /**
+         * 上传附件
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async uploadFile(ctx) {
+            const responseData = {
+                err: 0,
+                msg: '',
+                data: [],
+            };
+            let stream;
+            try {
+                stream = await ctx.getFileStream();
+                const create_time = Date.parse(new Date()) / 1000;
+                const fileInfo = path.parse(stream.filename);
+                const dirName = 'app/public/upload/changes/' + moment().format('YYYYMMDD');
+                const fileName = 'changes' + create_time + fileInfo.ext;
+
+                // 判断文件夹是否存在,不存在则直接创建文件夹
+                if (!fs.existsSync(path.join(this.app.baseDir, dirName))) {
+                    await fs.mkdirSync(path.join(this.app.baseDir, dirName));
+                }
+                // 保存文件
+                await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, dirName, fileName));
+                // 保存数据到att表
+                let fileData = {
+                    in_time : create_time,
+                    filename: fileInfo.name,
+                    fileext: fileInfo.ext,
+                    filesize: stream.fields.size,
+                    filepath: path.join(dirName, fileName),
+                };
+                const result = await ctx.service.changeAtt.save(stream.fields, fileData, ctx.session.sessionUser.accountId);
+                if (!(result.effectRows = 1)) {
+                    throw '导入数据库保存失败';
+                }
+                fileData.in_time = moment(create_time * 1000).format('YYYY-MM-DD');
+                fileData.filesize = await ctx.helper.bytesToSize(stream.fields.size);
+                fileData.id = result.insertId;
+                responseData.data = fileData;
+            } catch (err) {
+                this.log(err);
+                // 失败需要消耗掉stream 以防卡死
+                if (stream) {
+                    await sendToWormhole(stream);
+                }
+                this.setMessage(err.toString(), this.messageType.ERROR);
+            }
+            ctx.body = responseData;
+        }
+
+        /**
+         * 下载附件
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async downloadFile(ctx) {
+            const id = ctx.params.id;
+            if (id) {
+                try {
+                    const fileInfo = await ctx.service.changeAtt.getDataById(id);
+                    if (fileInfo !== undefined && fileInfo !== '') {
+                        const fileName = path.join(this.app.baseDir, fileInfo.filepath);
+                        ctx.response.set({
+                            'Content-Type': 'application/octet-stream',
+                            'Content-Disposition': `attachment; filename=` + fileInfo.filename + fileInfo.fileext,
+                            'Content-Length': fileInfo.filesize
+                        });
+                        ctx.body = await fs.createReadStream(fileName);
+                    } else {
+                        throw '不存在该文件';
+                    }
+                } catch (err) {
+                    this.log(err);
+                    this.setMessage(err.toString(), this.messageType.ERROR);
+                }
+            }
+        }
+
+        /**
+         * 删除附件
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async deleteFile(ctx) {
+            const responseData = {
+                err: 0,
+                msg: '',
+                data: '',
+            };
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                console.log(data.id);
+                const fileInfo = await ctx.service.changeAtt.getDataById(data.id);
+                if (fileInfo !== undefined && fileInfo !== '') {
+                    // 先删除文件
+                    await fs.unlinkSync(path.join(this.app.baseDir, fileInfo.filepath));
+                    // 再删除数据库
+                    await ctx.service.changeAtt.deleteById(data.id);
+                    responseData.data = '';
+                } else {
+                    throw '不存在该文件';
+                }
+
+                // if (data.tid === undefined || data.uci === undefined || data.uc === undefined || data.ac === undefined) {
+                //     throw '参数有误';
+                // }
+                // const [addCompany, selectCompany] = await ctx.service.changeCompany.setCompanyList(data);
+                // responseData.data = { add: addCompany, select: selectCompany };
+            } catch (err) {
+                responseData.err = 1;
+                responseData.msg = err;
+            }
+
+            ctx.body = responseData;
+        }
     }
 
     return ChangeController;

+ 5 - 0
app/public/css/main.css

@@ -544,3 +544,8 @@ body {
   width:inherit;
   height: inherit;
 }
+
+#tablist .active {
+  background: #e4e7ea;
+  font-weight: 600;
+}

+ 58 - 0
app/public/js/change_detail.js

@@ -14,5 +14,63 @@ $(document).ready(() => {
         const tab = $(this).attr('aria-controls');
         $('.show_title').hide();
         $('#'+ tab +'_title').show();
+    });
+
+    // 上传附件
+    $('#upload-file-btn').click(function () {
+        const file = $('#upload-file')[0];
+        if (file.files[0] === undefined) {
+            toastr.error('未选择上传文件!');
+            return false;
+        }
+        const filesize = file.files[0].size;
+        if (filesize > 30 * 1024 * 1024) {
+            toastr.error('文件大小过大!');
+            return false;
+        }
+        const fileext = '.' + file.files[0].name.toLowerCase().split('.').splice(-1)[0];
+        if (whiteList.indexOf(fileext) === -1) {
+            toastr.error('只能上传指定格式的附件!');
+            return false;
+        }
+        const formData = new FormData();
+        formData.append('cid', $('#changeId').val());
+        formData.append('tid', $('#tenderId').val());
+        formData.append('size', filesize);
+        formData.append('file', file.files[0]);
+        postDataWithFile('/change/upload/file', formData, function (data) {
+            $('#addfujian').modal('hide');
+            console.log(data);
+            const fileInfo = data;
+            let index = $('#attList tr').length;
+            let html = '<tr> ' +
+                '<td>' + (index+1) + '</td> ' +
+                '<td><a href="/change/download/file/' + fileInfo.id + '">' + fileInfo.filename + fileInfo.fileext + '</a></td> ' +
+                '<td>' + fileInfo.filesize + '</td> ' +
+                '<td>' + fileInfo.in_time + '</td> ' +
+                '<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>';
+            $('#attList').append(html);
+        }, function () {
+
+        });
+        $('#upload-file').val('');
+
+    });
+
+    $('body').on('click', '.delete-file', function () {
+        let attid = $(this).data('attid');
+        console.log(attid);
+        let self = $(this);
+        const data = {id: attid};
+        postData('/change/delete/file', data, function (result) {
+            self.parents('tr').remove();
+            // 重新排序
+            let newsort = 1;
+            $('#attList tr').each(function(){
+                $(this).children('td').eq(0).text(newsort);
+                newsort++;
+            });
+        });
     })
 });

+ 42 - 0
app/public/js/change_set.js

@@ -0,0 +1,42 @@
+'use strict';
+
+/**
+ * 变更令详细页js
+ *
+ * @author EllisRan.
+ * @date 2018/11/22
+ * @version
+ */
+
+$(document).ready(() => {
+    // 上报时按钮点击
+    $('a[data-target="#sub-ap"]').on('click', function () {
+        let category = $(this).data('category');
+        if (category === 'save_change') {
+            // 保存修改modal
+            $('.up-change').hide();
+            $('.save-change').show();
+        } else {
+            // 上报审批modal
+            $('.up-change').show();
+            $('.save-change').hide();
+            // 判断清单列表和变更信息是否填写完整
+        }
+    })
+
+    // 提交表单
+    // 上报时按钮点击
+    $('button[data-sumbit^="_change"]').on('click', function () {
+        let category = $(this).data('category');
+        if (category === 'save_change') {
+            // 保存修改modal
+            $('.up-change').hide();
+            $('.save-change').show();
+        } else {
+            // 上报审批modal
+            $('.up-change').show();
+            $('.save-change').hide();
+            // 判断清单列表和变更信息是否填写完整
+        }
+    })
+});

+ 4 - 3
app/router.js

@@ -63,7 +63,7 @@ module.exports = app => {
     app.post('/list/update', sessionAuth, 'tenderController.updateTender');
     app.post('/list/del', sessionAuth, 'tenderController.deleteTender');
     // 标段概况
-    app.get('/tender/:id', sessionAuth, tenderCheck, 'tenderController.tenderInfo');
+    app.get('/tender/:id/info', sessionAuth, tenderCheck, 'tenderController.tenderInfo');
     app.get('/tender/:id/type', sessionAuth, 'tenderController.tenderType');
     app.post('/tender/:id/save', sessionAuth, tenderCheck, 'tenderController.saveTenderInfo');
     app.post('/tender/rule', sessionAuth, 'tenderController.rule');
@@ -130,8 +130,9 @@ module.exports = app => {
     app.post('/tender/:id/change/newCode', sessionAuth, tenderCheck, 'changeController.newCode');
     app.post('/tender/:id/change/add', sessionAuth, tenderCheck, 'changeController.add');
     app.get('/tender/:id/change/:cid/info', sessionAuth, tenderCheck, 'changeController.info');
-    app.get('/tender/:id/change/:cid/bills', sessionAuth, tenderCheck, 'changeController.bills');
-    app.get('/tender/:id/change/:cid/file', sessionAuth, tenderCheck, 'changeController.file');
+    app.post('/change/upload/file', sessionAuth, 'changeController.uploadFile');
+    app.get('/change/download/file/:id', sessionAuth, 'changeController.downloadFile');
+    app.post('/change/delete/file', sessionAuth, 'changeController.deleteFile');
 
     // 变更单位管理
     app.post('/change/update/company', sessionAuth, 'changeController.updateCompany');

+ 42 - 0
app/service/change_att.js

@@ -0,0 +1,42 @@
+'use strict';
+
+/**
+ *
+ *  附件
+ * @author Ellisran
+ * @date 2019/1/11
+ * @version
+ */
+
+module.exports = app => {
+    class ChangeAtt extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'change_attachment';
+        }
+
+        /**
+         * 添加附件
+         * @param data
+         * @param fileData
+         */
+        async save(postData, fileData, uid) {
+            const data = {
+                tid: postData.tid,
+                cid: postData.cid,
+                uid: uid,
+            };
+            Object.assign(data, fileData);
+            const result = await this.db.insert(this.tableName, data);
+            return result;
+        }
+    }
+
+    return ChangeAtt;
+};

+ 49 - 22
app/view/change/info.ejs

@@ -24,17 +24,24 @@
         <div class="title-main d-flex justify-content-between">
             <h2 id="info_title" class="show_title">变更信息</h2>
             <div id="bills_title" class="show_title" style="display: none">
+                <% if (auditStatus === 1 || auditStatus === 2) { %>
                 <a href="#addlist" data-toggle="modal" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="添加清单"><i class="fa fa-plus" aria-hidden="true"></i> 添加清单</a>
+                <% } %>
             </div>
             <div id="files_title" class="show_title" style="display: none">
-                <a href="#addfujian" data-toggle="modal" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="添加清单"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 上传附件</a>
+                <% if (auditStatus === 1 || auditStatus === 2 || auditStatus === 6) { %>
+                <a href="#addfujian" data-toggle="modal" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="添加清单">
+                    <i class="fa fa-cloud-upload" aria-hidden="true"></i> 上传附件
+                </a>
+                <% } %>
             </div>
             <input id="tenderId" value="<%= tender.id %>" type="hidden">
+            <input id="changeId" value="<%= change.cid %>" type="hidden">
             <!--info状态区分-->
             <% if (auditStatus === 1) { %>
             <div>
-                <a href="#sub-ap" data-toggle="modal" class="btn btn-sm btn-success pull-right">保存修改</a>
-                <a href="#sub-sp" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm pull-right">上报审批</a>
+                <a href="#sub-ap" data-category="save_change" data-toggle="modal" data-target="#sub-ap" class="btn btn-sm btn-success pull-right">保存修改</a>
+                <a href="#sub-ap" data-category="up_change" data-toggle="modal" data-target="#sub-ap" class="btn btn-primary btn-sm pull-right">上报审批</a>
                 <a href="#" class="btn btn-outline-danger btn-sm pull-right text-truncate" style="max-width: 100px;" title="删除 <%- change.code %>">删除 <%- change.code %></a>
             </div>
             <% } else if (auditStatus === 2) { %>
@@ -72,9 +79,9 @@
         <div class="c-body tab-pane active" role="tabpanel" id="info">
             <!--变更信息-->
             <% if (auditStatus === 1 || auditStatus === 2) { %>
-            <div class="row">
-                <div class="col-md-4">
-                    <form>
+            <form action="/change/save" method="post" id="change_form">
+                <div class="row">
+                    <div class="col-md-4">
                         <div class="form-group">
                             <label><b class="text-danger">*&nbsp;</b>申请编号</label>
                             <a href="#" class="pull-right" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="自动编号"><i class="fa fa-repeat"></i></a>
@@ -104,10 +111,8 @@
                             <label>变更图号</label>
                             <input class="form-control" placeholder="" type="text" value="<%- change.new_code %>">
                         </div>
-                    </form>
-                </div>
-                <div class="col-md-4" style="z-index:999">
-                    <form>
+                    </div>
+                    <div class="col-md-4" style="z-index:999">
                         <div class="form-group">
                             <label><b class="text-danger">*&nbsp;</b>工程变更理由及内容</label>
                             <textarea class="form-control" rows="6"><%- change.content %></textarea>
@@ -120,10 +125,8 @@
                             <label>备注</label>
                             <textarea class="form-control" rows="3"><%- change.memo %></textarea>
                         </div>
-                    </form>
-                </div>
-                <div class="col-md-4">
-                    <form>
+                    </div>
+                    <div class="col-md-4">
                         <div class="form-group">
                             <label>变更类型</label>
                             <div class="checkbox">
@@ -177,9 +180,17 @@
                             <label><b class="text-danger">*&nbsp;</b>批复文号</label>
                             <input class="form-control" placeholder="" type="text" value="<%- change.w_code %>" readonly>
                         </div>
-                    </form>
+
+                        <!--清单、附件、审批人上传数据-->
+                        <input type="hidden" name="changelist" id="changelist" value="{{changelist}}">
+                        <input type="hidden" name="changewhitelist" id="changewhitelist" value="{{changewhitelist}}">
+                        <input type="hidden" name="changeaudit" id="changeaudit" value="{{changeaudit}}">
+                        <input type="hidden" name="changedecimalnum" id="changedecimalnum" value="{{changeArray.decimalnum}}">
+
+                        <input type="hidden" name="changestatus" id="changeStatus">
+                    </div>
                 </div>
-            </div>
+            </form>
             <% } else { %>
             <div class="row">
                 <div class="col-md-4">
@@ -320,16 +331,27 @@
                 <thead>
                 <tr><th width="50">序号</th><th>名称</th><th width="90">大小</th><th width="100">上传时间</th><th width="100">操作</th></tr>
                 </thead>
-                <tbody>
-                <tr><td>1</td><td><a href="">合同段工程变更现场办公会议纪要的通知.rar</a></td><td>682.64 KB</td><td>2017-01-01 13:22</td><td><a href="#" class="btn btn-light btn-sm" title="删除附件"><span class="fa fa-trash text-danger"></span></a></td></tr>
-                <tr><td>2</td><td><a href="">管理处关于发送LZTJ-1合同段YT-24号设计更改的通知.rar</a></td><td>1.52 MB</td><td>2017-01-01 14:22</td><td><a href="#" class="btn btn-light btn-sm" title="删除附件"><span class="fa fa-trash text-danger"></span></a></td></tr>
-                <tr><td>3</td><td><a href="">原设计施工图.pdf</a></td><td>396.73 KB</td><td>2017-01-01 12:22</td><td></td></tr>
+                <tbody id="attList">
+                <% if (attList !== undefined && attList !== '') { %>
+                <% for (const [index,att] of attList.entries()) { %>
+                <tr>
+                    <td><%- index+1 %></td>
+                    <td><a href="/change/download/file/<%- att.id %>"><%- att.filename %><%- att.fileext %></a></td>
+                    <td><%- ctx.helper.bytesToSize(att.filesize) %></td>
+                    <td><%- moment(att.in_time * 1000).format('YYYY-MM-DD') %></td>
+                    <td>
+                        <% if (att.uid === uid && (auditStatus === 1 || auditStatus === 2 || auditStatus === 6)) { %>
+                        <a class="btn btn-light btn-sm delete-file" data-attid="<%- att.id %>" title="删除附件"><span class="fa fa-trash text-danger"></span></a>
+                        <% } %>
+                    </td>
+                </tr>
+                <% } %>
+                <% } %>
                 </tbody>
             </table>
         </div>
     </div>
 </div>
-<script src="/public/js/change_detail.js"></script>
 <link href="/public/css/toastr.css" rel="stylesheet">
 <script src="/public/js/toastr.min.js"></script>
 <script>
@@ -352,4 +374,9 @@
             "hideMethod": "fadeOut"
         };
     })
-</script>
+    const whiteList = JSON.parse('<%- JSON.stringify(whiteList) %>');
+</script>
+<script src="/public/js/change_detail.js"></script>
+<% if (auditStatus === 1 || auditStatus === 2) { %>
+<script src="/public/js/change_set.js"></script>
+<% } %>

+ 57 - 3
app/view/change/info_modal.ejs

@@ -30,6 +30,60 @@
         </div>
     </div>
 </div>
+
+<!--上报审批-->
+<div class="modal fade" id="sub-ap" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title up-change">上报审批</h5>
+                <h5 class="modal-title save-change">保存修改</h5>
+            </div>
+            <form method="post" action="/tender/<%- tender.id %>/change/<%- change.cid %>/save">
+                <div class="modal-body">
+                    <!--如未创建清单-->
+                    <h5>还没添加任何变更清单,无法提交。</h5>
+                    <!--可以提交审批 但需要设置审批流程-->
+                    <div class="form-group">
+                        <label>搜索审批人</label>
+                        <div class="input-group">
+                            <input class="form-control" placeholder="请输入姓名进行检索" type="text">
+                            <div class="input-group-append">
+                                <button class="btn btn-outline-secondary" type="button"><i class="fa fa-search"></i></button>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="card border-primary">
+                        <div class="card-body">
+                            <h5 class="card-title">
+                                <a href="#" class="btn btn-primary btn-sm pull-right">添加</a>张三
+                            </h5>
+                            <h6 class="card-subtitle mb-2 text-muted">监理</h6>
+                            <p class="card-text">XXXXX公司</p>
+                        </div>
+                    </div>
+                    <div class="card mt-3">
+                        <div class="card-header">
+                            审批流程
+                        </div>
+                        <ul class="list-group list-group-flush">
+                            <li class="list-group-item"><i class="fa fa fa-play-circle fa-rotate-90"></i> 布尔  <small class="text-muted">施工</small></li>
+                            <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a><i class="fa fa-chevron-circle-down"></i> 张三  <small class="text-muted">监理</small></li>
+                            <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a><i class="fa fa-chevron-circle-down"></i> 王五 <small class="text-muted">监理</small></li>
+                            <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a><i class="fa fa fa-stop-circle"></i> 李四 <small class="text-muted">监理</small></li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" data-sumbit="up_change" class="btn btn-primary up-change">确认上报</button>
+                    <button type="button" data-sumbit="save_change" class="btn btn-success save-change">保存修改</button>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
+
 <script src="/public/js/change_company.js"></script>
 <% } %>
 
@@ -230,12 +284,12 @@
                 </button>
             </div>
             <div class="modal-body">
-                <p>上传文件大小最大:10MB</p>
-                <p><a href="" class="btn btn-primary">选择文件</a></p>
+                <p>上传文件大小最大:30MB</p>
+                <p><input class="btn btn-primary" value="选择文件" type="file" id="upload-file" /></p>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-primary">添加</button>
+                <button type="button" class="btn btn-primary" id="upload-file-btn">添加</button>
             </div>
         </div>
     </div>