Browse Source

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

TonyKang 3 years ago
parent
commit
0476b6cfe2

+ 30 - 0
app/const/map.js

@@ -0,0 +1,30 @@
+'use strict';
+
+/**
+ * 地图默认坐标展示相关
+ *
+ * @author Ellisran
+ * @date
+ * @version
+ */
+
+const level = 15;
+
+const map = [
+    { province: '默认', lng: 116.404, lat: 39.915, office: 15, level: 15 },
+    { province: '甘肃', lng: 103.612, lat: 34.687, office: 3, level: 15 },
+    { province: '内蒙', lng: 110.088, lat: 41.457, office: 9, level: 15 },
+    { province: '四川', lng: 102.6445, lat: 29.386, office: 7, level: 15 },
+    { province: '重庆', lng: 106.863, lat: 29.066, office: 8, level: 15 },
+    { province: '广西', lng: 109.980, lat: 24.484, office: 5, level: 15 },
+    { province: '广东', lng: 113.795, lat: 23.218, office: 4, level: 15 },
+    { province: '江西', lng: 118.366, lat: 27.071, office: 6, level: 15 },
+    { province: '浙江', lng: 120.792, lat: 30.073, office: 10, level: 15 },
+    { province: '山东', lng: 119.059, lat: 36.552, office: 11, level: 15 },
+];
+
+
+module.exports = {
+    map,
+    level,
+};

+ 5 - 8
app/controller/advance_controller.js

@@ -246,18 +246,15 @@ module.exports = app => {
                     throw '参数错误';
                 }
                 // 检查权限等
-                if (advance.uid !== ctx.session.sessionUser.accountId) {
+                if (!ctx.session.sessionUser.is_admin && advance.uid !== ctx.session.sessionUser.accountId) {
                     throw '您无权删除';
                 }
-                if (advance.status !== auditConst.status.uncheck && advance.status !== auditConst.status.checkNo) {
-                    console.log(advance.status !== auditConst.status.uncheck);
-                    console.log(advance.status !== auditConst.status.checkNo);
+                if (!ctx.session.sessionUser.is_admin && advance.status !== auditConst.status.uncheck && advance.status !== auditConst.status.checkNo) {
+                    // console.log(advance.status !== auditConst.status.uncheck);
+                    // console.log(advance.status !== auditConst.status.checkNo);
                     throw '当前不允许删除';
                 }
-                const isDeleted = await ctx.service.advance.deleteAdvance(id);
-                if (!isDeleted) {
-                    throw '删除失败,请重试';
-                }
+                await ctx.service.advance.deleteAdvance(id, ctx.tender.id);
                 ctx.body = { err: 0, msg: '' };
             } catch (error) {
                 this.log(error);

+ 27 - 7
app/controller/change_controller.js

@@ -1138,14 +1138,17 @@ module.exports = app => {
          * @param {Oject} ctx - 全局上下文
          */
         async downloadZip(ctx) {
+            const time = Date.now();
+            const zipPath = `app/public/upload/change/fu_jian_zip${time}.zip`;
+            const responseData = {
+                err: 0,
+                msg: '',
+            };
             try {
-                const fileIds = JSON.parse(ctx.request.query.fileIds);
-                // const { fileIds } = JSON.parse(ctx.request.body.data);
-                // console.log('fileIds', fileIds);
+                // const fileIds = JSON.parse(ctx.request.query.fileIds);
+                const { fileIds = [] } = JSON.parse(ctx.request.body.data);
                 const { name: changeName } = await ctx.service.changeAtt.getChangeName(ctx.params.cid);
                 const zipFilename = `${ctx.tender.data.name}-工程变更-${changeName}-附件.zip`;
-                const time = Date.now();
-                const zipPath = `app/public/upload/change/fu_jian_zip${time}.zip`;
                 const size = await ctx.service.changeAtt.compressedFile(fileIds, zipPath);
 
                 // 解决中文无法下载问题
@@ -1173,8 +1176,25 @@ module.exports = app => {
                         fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
                     }
                 });
-            } catch (error) {
-                this.log(error);
+                // fs的错误不能被try catch捕捉
+                readStream.on('error', err => {
+                    this.log(err);
+                    if (fs.existsSync(path.resolve(this.app.baseDir, zipPath))) {
+                        fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
+                    }
+                    responseData.err = 1;
+                    responseData.msg = err.toString();
+                    ctx.body = responseData;
+                });
+            } catch (err) {
+                this.log(err);
+                if (fs.existsSync(path.resolve(this.app.baseDir, zipPath))) {
+                    fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
+                }
+                this.setMessage(err.toString(), this.messageType.ERROR);
+                responseData.err = 1;
+                responseData.msg = err.toString();
+                ctx.body = responseData;
             }
         }
         /**

+ 40 - 10
app/controller/material_controller.js

@@ -238,7 +238,7 @@ module.exports = app => {
                 searchsql.mid = midList;
             }
             // 取所有工料表
-            return await ctx.service.materialBills.getAllDataByCondition({ where: searchsql });
+            return await ctx.service.materialBills.getAllDataByCondition({ where: searchsql, orders: [['order', 'asc']] });
         }
 
         /**
@@ -259,7 +259,9 @@ module.exports = app => {
                         code: mbd.code,
                         name: mbd.name,
                         unit: mbd.unit,
+                        origin: mbd.origin,
                         mb_id: mbd.id,
+                        order: mbd.order,
                     };
                     for (const m of material_month) {
                         const mb_id = ctx.material.highOrder !== ctx.material.order ? mbd.mb_id : mbd.id;
@@ -571,6 +573,9 @@ module.exports = app => {
                     case 'del':
                         responseData.data.m_tp = await ctx.service.materialBills.del(data.id);
                         break;
+                    case 'changeOrder':
+                        responseData.data = await ctx.service.materialBills.changeOrder(data.id1, data.id2);
+                        break;
                     case 'update':
                         if (data.updateData.code === '' || data.updateData.code === null) {
                             throw '请先输入编号';
@@ -671,12 +676,18 @@ module.exports = app => {
                             m_tp: tp3,
                         };
                         break;
+                    case 'updateOrigin':
+                        await ctx.service.materialBills.saveOrigin(data.updateData);
+                        break;
                     case 'paste':
                         const tp4 = await ctx.service.materialMonth.saveDatas(data.updateData, mbList);
                         responseData.data = {
                             m_tp: tp4,
                         };
                         break;
+                    case 'pasteOrigin':
+                        await ctx.service.materialBills.saveOrigins(data.updateData);
+                        break;
                     default: throw '参数有误';
                 }
                 responseData.data.materialBillsData = await this._getMaterialBillsData(ctx);
@@ -1047,13 +1058,16 @@ module.exports = app => {
          * @param {Object} ctx - 全局上下文
          */
         async downloadZip(ctx) {
+            const zipFilename = `${ctx.tender.data.name}-材料调差-${ctx.params.order}-附件.zip`;
+            const time = Date.now();
+            const zipPath = `app/public/upload/${ctx.tender.id}/tc/fu_jian_zip${time}.zip`;
+            const responseData = {
+                err: 0,
+                msg: '',
+            };
             try {
-                const fileIds = JSON.parse(ctx.request.query.fileIds);
-                // const { fileIds } = JSON.parse(ctx.request.body.data);
-                // console.log('fileIds', fileIds);
-                const zipFilename = `${ctx.tender.data.name}-材料调差-${ctx.params.order}-附件.zip`;
-                const time = Date.now();
-                const zipPath = `app/public/upload/${ctx.tender.id}/tc/fu_jian_zip${time}.zip`;
+                // const fileIds = JSON.parse(ctx.request.query.fileIds);
+                const { fileIds = [] } = JSON.parse(ctx.request.body.data);
                 const size = await ctx.service.materialFile.compressedFile(fileIds, zipPath);
 
                 // 解决中文无法下载问题
@@ -1075,14 +1089,30 @@ module.exports = app => {
                 const readStream = fs.createReadStream(path.join(this.app.baseDir, zipPath));
 
                 ctx.body = readStream;
-                // ctx.body = fs.readFileSync(path.resolve(this.app.baseDir, zipPath));
                 readStream.on('close', () => {
                     if (fs.existsSync(path.resolve(this.app.baseDir, zipPath))) {
                         fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
                     }
                 });
-            } catch (error) {
-                this.log(error);
+                // fs的错误不能被try catch捕捉
+                readStream.on('error', err => {
+                    this.log(err);
+                    if (fs.existsSync(path.resolve(this.app.baseDir, zipPath))) {
+                        fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
+                    }
+                    responseData.err = 1;
+                    responseData.msg = err.toString();
+                    ctx.body = responseData;
+                });
+            } catch (err) {
+                this.log(err);
+                if (fs.existsSync(path.resolve(this.app.baseDir, zipPath))) {
+                    fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
+                }
+                this.setMessage(err.toString(), this.messageType.ERROR);
+                responseData.err = 1;
+                responseData.msg = err.toString();
+                ctx.body = responseData;
             }
         }
     }

+ 97 - 0
app/controller/setting_controller.js

@@ -243,6 +243,7 @@ module.exports = app => {
                     permission,
                     permissionStr: JSON.stringify(permission),
                     pageInfo,
+                    user_total: total,
                     // rule: JSON.stringify(frontRule),
                 };
                 await this.layout('setting/user_permission.ejs', renderData, 'setting/user_permission_modal.ejs');
@@ -847,6 +848,102 @@ module.exports = app => {
                 this.ajaxErrorBody(error, '保存数据失败');
             }
         }
+
+        async dataCollect(ctx) {
+            try {
+                const projectId = ctx.session.sessionProject.id;
+                await this._checkMenu(projectId);
+                const projectData = await ctx.service.project.getDataById(projectId);
+                if (projectData === null) throw '没有对应的项目数据';
+                if (ctx.session.sessionUser.is_admin === 0) throw '没有访问权限';
+                const dataCollectAudits = await ctx.service.datacollectAudit.getList(projectId);
+                // 获取所有项目参与者
+                const accountList = await ctx.service.projectAccount.getAllDataByCondition({
+                    where: { project_id: ctx.session.sessionProject.id, enable: 1 },
+                    columns: ['id', 'name', 'company', 'role', 'enable', 'is_admin', 'account_group', 'mobile'],
+                });
+                const accountGroupList = accountGroup.map((item, idx) => {
+                    const groupList = accountList.filter(item => item.account_group === idx);
+                    return { groupName: item, groupList };
+                });
+                const categoryData = await ctx.service.category.getAllCategory(ctx.session.sessionProject.id);
+                await this.layout('setting/datacollect.ejs', {
+                    projectData,
+                    dataCollectAudits,
+                    accountList,
+                    accountGroup: accountGroupList,
+                    categoryData,
+                }, 'setting/datacollect_modal.ejs');
+            } catch (error) {
+                ctx.helper.log(error);
+                ctx.redirect('/dashboard');
+            }
+        }
+
+        async dataCollectSave(ctx) {
+            try {
+                if (ctx.session.sessionUser.is_admin === 0) throw '没有设置权限';
+                const projectId = ctx.session.sessionProject.id;
+                const responseData = {
+                    err: 0, msg: '', data: null,
+                };
+
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data.type) {
+                    throw '提交数据错误';
+                }
+                switch (data.type) {
+                    case 'show':
+                        responseData.data = await ctx.service.project.update({ data_collect: data.data_collect }, { id: projectId });
+                        ctx.session.sessionProject.dataCollect = data.data_collect;
+                        ctx.session.sessionProject.showDataCollect = data.data_collect ? 1 : 0;
+                        break;
+                    case 'add-audit':
+                        // 判断该用户的组是否已加入到表中,已加入则提示无需添加
+                        const auditInfo = await ctx.service.datacollectAudit.getDataByCondition({ pid: projectId, uid: data.id });
+                        if (auditInfo) {
+                            throw '该用户已存在权限中,无需重复添加';
+                        }
+                        const accountInfo = await ctx.service.projectAccount.getDataById(data.id);
+                        const groupInfo = await ctx.service.datacollectAudit.getGroupInfo(projectId, accountInfo.account_group);
+                        if (groupInfo) {
+                            throw '该用户所在单位已存在权限中,无需单独添加';
+                        }
+                        await ctx.service.datacollectAudit.saveAudit(projectId, accountInfo.account_group, data.id);
+                        responseData.data = await ctx.service.datacollectAudit.getList(projectId);
+                        break;
+                    case 'add-group':
+                        const groupInfo2 = await ctx.service.datacollectAudit.getGroupInfo(projectId, data.id);
+                        if (groupInfo2) {
+                            throw '该单位已存在权限中,无需重复添加';
+                        }
+                        await ctx.service.datacollectAudit.saveGroup(projectId, data.id);
+                        responseData.data = await ctx.service.datacollectAudit.getList(projectId);
+                        break;
+                    case 'del-audit':
+                        const auditInfo2 = await ctx.service.datacollectAudit.getDataById(data.id);
+                        if (!auditInfo2) {
+                            throw '该用户已不存在权限中,移除失败';
+                        }
+                        await ctx.service.datacollectAudit.delAudit(data.id);
+                        responseData.data = await ctx.service.datacollectAudit.getList(projectId);
+                        break;
+                    case 'del-group':
+                        const groupInfo3 = await ctx.service.datacollectAudit.getDataById(data.id);
+                        if (!groupInfo3) {
+                            throw '该单位已不存在权限中,移除失败';
+                        }
+                        await ctx.service.datacollectAudit.delAudit(data.id);
+                        responseData.data = await ctx.service.datacollectAudit.getList(projectId);
+                        break;
+                    default: throw '参数有误';
+                }
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
     }
 
     return SettingController;

+ 28 - 6
app/controller/stage_controller.js

@@ -1574,11 +1574,16 @@ module.exports = app => {
          * @param {Object} ctx - 全局上下文
          */
         async downloadZip(ctx) {
+            const zipFilename = `${ctx.tender.data.name}-计量台账-${ctx.params.order}-附件.zip`;
+            const time = Date.now();
+            const zipPath = `app/public/upload/${ctx.tender.id}/stage/fu_jian_zip${time}.zip`;
+            const responseData = {
+                err: 0,
+                msg: '',
+            };
             try {
-                const fileIds = JSON.parse(ctx.request.query.fileIds);
-                const zipFilename = `${ctx.tender.data.name}-计量台账-${ctx.params.order}-附件.zip`;
-                const time = Date.now();
-                const zipPath = `app/public/upload/${ctx.tender.id}/stage/fu_jian_zip${time}.zip`;
+                const { fileIds = [] } = JSON.parse(ctx.request.body.data);
+                // const fileIds = JSON.parse(ctx.request.query.fileIds);
                 const size = await ctx.service.stageAtt.compressedFile(fileIds, zipPath);
 
                 // 解决中文无法下载问题
@@ -1604,8 +1609,25 @@ module.exports = app => {
                         fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
                     }
                 });
-            } catch (error) {
-                this.log(error);
+                // fs的错误不能被try catch捕捉
+                readStream.on('error', err => {
+                    this.log(err);
+                    if (fs.existsSync(path.resolve(this.app.baseDir, zipPath))) {
+                        fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
+                    }
+                    responseData.err = 1;
+                    responseData.msg = err.toString();
+                    ctx.body = responseData;
+                });
+            } catch (err) {
+                this.log(err);
+                if (fs.existsSync(path.resolve(this.app.baseDir, zipPath))) {
+                    fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
+                }
+                this.setMessage(err.toString(), this.messageType.ERROR);
+                responseData.err = 1;
+                responseData.msg = err.toString();
+                ctx.body = responseData;
             }
 
         }

+ 2 - 0
app/controller/stage_rela_controller.js

@@ -50,6 +50,8 @@ module.exports = app => {
                 if (!tid || !sorder) throw '参数错误';
                 const stage = await this.ctx.service.stage.getDataByCondition({ tid, order: sorder});
                 if (!stage) throw '关联标段/期不存在';
+                const exist = await this.ctx.service.stageRela.getDataByCondition({ sid: this.ctx.stage.id, rela_tid: tid});
+                if (exist) throw '已关联该标段,请勿重复关联';
                 const trid = await this.ctx.service.stageRela.addStageRela(stage);
                 ctx.redirect(ctx.request.header.referer + '/detail/' + trid);
             } catch (err) {

+ 20 - 0
app/controller/tender_controller.js

@@ -23,6 +23,7 @@ const sendToWormhole = require('stream-wormhole');
 const scheduleConst = require('../const/schedule');
 const changeConst = require('../const/change');
 const tenderInfoModel = require('../lib/tender_info');
+const mapConst = require('../const/map');
 
 module.exports = app => {
 
@@ -511,6 +512,24 @@ module.exports = app => {
                 const tenderALLInfo = await ctx.service.tender.getDataById(tender.id);
                 const hadMap = tenderALLInfo.had_map === 1 ? 0 : 1;
                 const tenderMapList = await ctx.service.tenderMap.getAllDataByCondition({ where: { tid: tender.id } });
+                // 默认坐标,否则则取办事处坐标
+                const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
+                let map_json = {
+                    province: mapConst.map[0].province,
+                    lng: mapConst.map[0].lng,
+                    lat: mapConst.map[0].lat,
+                    level: 15,
+                };
+                if (projectData.map_json) {
+                    map_json = JSON.parse(projectData.map_json);
+                } else {
+                    const mapInfo = ctx.helper._.find(mapConst.map, { office: projectData.manager_office });
+                    if (mapInfo) {
+                        map_json.province = mapInfo.province;
+                        map_json.lng = mapInfo.lng;
+                        map_json.lat = mapInfo.lat;
+                    }
+                }
                 const renderData = {
                     tenders,
                     categoryData,
@@ -533,6 +552,7 @@ module.exports = app => {
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.tender.tenderInfo),
                     gclChapter,
                     tenderMapList,
+                    map_json,
                 };
                 if (ctx.session.sessionUser.is_admin) {
                     renderData.tourists = await ctx.service.tenderTourist.getTourists(tender.id);

+ 6 - 4
app/lib/ledger.js

@@ -861,10 +861,12 @@ class checkData {
             if (posRange.length > 0) {
                 for (const p of posRange) {
                     const end_contract_qty = this.ctx.helper.add(p.pre_contract_qty, p.contract_qty);
-                    if (!p.quantity) return !!end_contract_qty;
-                    return p.quantity > 0
-                        ? end_contract_qty > p.quantity
-                        : end_contract_qty < p.quantity || end_contract_qty > 0;
+                    if (!p.quantity && !!end_contract_qty) return true;
+                    if (p.quantity > 0) {
+                        if (end_contract_qty > p.quantity) return true;
+                    } else {
+                        if (end_contract_qty < p.quantity || end_contract_qty > 0) return true;
+                    }
                 }
                 return false;
             }

+ 2 - 0
app/public/js/change_company.js

@@ -46,6 +46,8 @@ $(document).ready(() => {
                 $('#editcompany').modal('hide');
                 toastr.success('变更单位已更新');
                 $('#updatecompany').attr('disabled',false);
+                changeInfo.company = $('#company').val();
+                judgeChange();
             });
         }else{
             toastr.error('变更单位不能同名');

+ 25 - 4
app/public/js/change_detail.js

@@ -171,10 +171,31 @@ $(document).ready(() => {
         })
 
         if (fileIds.length) {
-            const tid = $('#tenderId').val()
-            const cid = $('#changeId').val()
-            $('#downloadZip').attr('href', `/tender/${tid}/change/${cid}/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`);
-            $('#downloadZip')[0].click();
+            if (fileIds.length > 10) {
+              return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`);
+            }
+            const tid = $('#tenderId').val();
+            const cid = $('#changeId').val();
+            
+            toastr.success('正在进行压缩文件...', '', { timeOut: 0, extendedTimeOut: 0});
+            $(this).attr('disabled', "true");
+            const btn = $(this);
+            postCompressFile(`/tender/${tid}/change/${cid}/download/compresse-file`, {fileIds}, function(result) {
+              toastr.clear();
+              toastr.success('压缩文件成功');
+              btn.removeAttr('disabled');
+              const href = window.URL.createObjectURL(result);
+              $('#zipDown').attr('href', href);
+              $('#zipDown').attr('download', `${tenderName}-工程变更-${changeName}-附件.zip`);
+              $("#zipDown")[0].click();
+            }, () => {
+              btn.removeAttr('disabled');
+              toastr.clear();
+              toastr.error('批量下载失败');
+            });
+
+            // $('#downloadZip').attr('href', `/tender/${tid}/change/${cid}/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`);
+            // $('#downloadZip')[0].click();
         }
     });
 

+ 24 - 2
app/public/js/change_information.js

@@ -176,10 +176,32 @@ $(document).ready(() => {
         });
 
         if (fileIds.length) {
+            // const tid = $('#tenderId').val();
+            // const cid = $('#changeId').val();
+            // $('#downloadZip').attr('href', `/tender/${tid}/change/${cid}/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`);
+            // $('#downloadZip')[0].click();
+            if (fileIds.length > 10) {
+              return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`);
+            }
             const tid = $('#tenderId').val();
             const cid = $('#changeId').val();
-            $('#downloadZip').attr('href', `/tender/${tid}/change/${cid}/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`);
-            $('#downloadZip')[0].click();
+            
+            toastr.success('正在进行压缩文件...', '', { timeOut: 0, extendedTimeOut: 0});
+            $(this).attr('disabled', "true");
+            const btn = $(this);
+            postCompressFile(`/tender/${tid}/change/${cid}/download/compresse-file`, {fileIds}, function(result) {
+              toastr.clear();
+              toastr.success('压缩文件成功');
+              btn.removeAttr('disabled');
+              const href = window.URL.createObjectURL(result);
+              $('#zipDown').attr('href', href);
+              $('#zipDown').attr('download', `${tenderName}-工程变更-${changeName}-附件.zip`);
+              $("#zipDown")[0].click();
+            }, () => {
+              btn.removeAttr('disabled');
+              toastr.clear();
+              toastr.error('批量下载失败');
+            });
         }
     });
 

+ 2 - 1
app/public/js/ledger.js

@@ -3415,8 +3415,9 @@ $(document).ready(function() {
         // if (curAuditor && curAuditor.aid !== cur_uid) {
         //     return toastr.error('当前操作没有权限!');
         // }
-        const files = $('#upload-file')[0].files;
         const node = SpreadJsObj.getSelectObject(ledgerSpread.getActiveSheet());
+        if (!node) return
+        const files = $('#upload-file')[0].files;
         // console.log(node);
         const formData = new FormData();
         formData.append('lid', node.id);

+ 147 - 49
app/public/js/material.js

@@ -226,6 +226,8 @@ $(document).ready(() => {
             const select = SpreadJsObj.getSelectObject(sheet);
             // 还需判断是否已被调差清单调用
             setObjEnable($('#del'), !readOnly && select && materialBase.isUsed(select) && rowCount === 1);
+            setObjEnable($('#up-move'), !readOnly && select && materialBillsData.indexOf(select) > 0);
+            setObjEnable($('#down-move'), !readOnly && select && materialBillsData.indexOf(select) < materialBillsData.length - 1);
         },
         add: function () {
             const sheet = materialSpread.getActiveSheet();
@@ -239,7 +241,7 @@ $(document).ready(() => {
                     materialSpreadObj.refreshActn();
                     // 月信息价需要同时添加空白的list
                     if (months.length > 0) {
-                        const one_month ={ mb_id: result.id, code: '', name: null, unit: null, };
+                        const one_month ={ mb_id: result.id, code: '', name: null, origin: null, unit: null, order: result.order };
                         for (const m of months) {
                             one_month[m] = null;
                         }
@@ -271,6 +273,72 @@ $(document).ready(() => {
                 }
             });
         },
+        upMove: function () {
+            const sheet = materialSpread.getActiveSheet();
+            const cur = SpreadJsObj.getSelectObject(sheet);
+            const up = materialBillsData[materialBillsData.indexOf(cur) - 1];
+            const mbIndex = materialBillsData.indexOf(cur);
+            postData(window.location.pathname + '/save', {type: 'changeOrder', id1: cur.id, id2: up.id}, function () {
+                const order = cur.order;
+                cur.order = up.order;
+                up.order = order;
+                materialBillsData.sort(function (a, b) {
+                    return a.order - b.order
+                });
+                SpreadJsObj.reLoadSheetData(sheet);
+                const sel = sheet.getSelections();
+                const index = materialBillsData.indexOf(cur);
+                sheet.setSelection(index, sel.length > 0 ? sel[0].col : 0, 1, 1);
+                materialSpreadObj.refreshActn();
+                if (months.length > 0) {
+                    const monthCur = monthsList[mbIndex];
+                    const monthUp = monthsList[mbIndex - 1];
+                    const monthOrder = monthCur.order;
+                    monthCur.order = monthUp.order;
+                    monthUp.order = monthOrder;
+                    monthsList.sort(function (a, b) {
+                        return a.order - b.order
+                    });
+                    const materialMonthSheet = materialMonthSpread.getActiveSheet();
+                    SpreadJsObj.reLoadSheetData(materialMonthSheet);
+                }
+            });
+        },
+        downMove: function () {
+            const sheet = materialSpread.getActiveSheet();
+            const cur = SpreadJsObj.getSelectObject(sheet);
+            const down = materialBillsData[materialBillsData.indexOf(cur) + 1];
+            const mbIndex = materialBillsData.indexOf(cur);
+            postData(window.location.pathname + '/save', {
+                type: 'changeOrder',
+                id1: cur.id,
+                id2: down.id
+            }, function () {
+                const order = cur.order;
+                cur.order = down.order;
+                down.order = order;
+                materialBillsData.sort(function (a, b) {
+                    return a.order - b.order
+                });
+                SpreadJsObj.reLoadSheetData(sheet);
+                const sel = sheet.getSelections();
+                const index = materialBillsData.indexOf(cur);
+                sheet.setSelection(index, sel.length > 0 ? sel[0].col : 0, 1, 1);
+                materialSpreadObj.refreshActn();
+                if (months.length > 0) {
+                    const monthCur = monthsList[mbIndex];
+                    const monthDown = monthsList[mbIndex + 1];
+                    const monthOrder = monthCur.order;
+                    monthCur.order = monthDown.order;
+                    monthDown.order = monthOrder;
+                    monthsList.sort(function (a, b) {
+                        return a.order - b.order
+                    });
+                    const materialMonthSheet = materialMonthSpread.getActiveSheet();
+                    SpreadJsObj.reLoadSheetData(materialMonthSheet);
+                }
+            });
+        },
         selectionChanged: function (e, info) {
             const sel = info.sheet.getSelections()[0];
             const col = info.sheet.zh_setting.cols[sel.col];
@@ -560,8 +628,9 @@ $(document).ready(() => {
     sheet.resumePaint();
     const static_cols = [
         {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 60, formatter: '@', readOnly: true},
-        {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@', readOnly: true},
+        {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 140, formatter: '@', readOnly: true},
         {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true},
+        {title: '来源地', colSpan: '1', rowSpan: '2', field: 'origin', hAlign: 0, width: 80, formatter: '@', readOnly: 'readOnly.isEdit'},
         {title: '平均单价', colSpan: '1', rowSpan: '2', field: 'average_msg_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true, getValue:'getValue.average_msg_tp'},
     ];
     // 月信息价方法集合
@@ -667,7 +736,7 @@ $(document).ready(() => {
             },
         },
     };
-    materialMonthSpread.getActiveSheet().frozenColumnCount(4);
+    materialMonthSpread.getActiveSheet().frozenColumnCount(5);
     materialMonthSpread.getActiveSheet().options.frozenlineColor = '#f1f1f1';
     SpreadJsObj.initSpreadSettingEvents(materialMonthSpreadSetting, materialMonthCol);
     SpreadJsObj.initSheet(materialMonthSpread.getActiveSheet(), materialMonthSpreadSetting);
@@ -685,31 +754,42 @@ $(document).ready(() => {
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
                     return;
                 }
-                // 判断部分值是否输入的是数字判断和数据计算
-                if (isNaN(validText)) {
-                    toastr.error('不能输入其它非数字类型字符');
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                    return;
-                }
-                const num = parseFloat(validText);
-                if (validText !== null && (num < 0 || !/^\d+(\.\d{1,3})?$/.test(num))) {
-                    toastr.error('请输入大于0并且小于3位小数的浮点数');
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                    return;
-                }
-                select[col.field] = validText;
+                if (col.field === 'origin') {
+                    select[col.field] = validText;
+                    postData(window.location.pathname + '/month/save', { type:'updateOrigin', updateData: { mb_id: select.mb_id, value: validText } }, function (result) {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        materialBillsData = result.materialBillsData;
+                    }, function () {
+                        select[col.field] = orgValue;
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    });
+                } else {
+                    // 判断部分值是否输入的是数字判断和数据计算
+                    if (isNaN(validText)) {
+                        toastr.error('不能输入其它非数字类型字符');
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    const num = parseFloat(validText);
+                    if (validText !== null && (num < 0 || !/^\d+(\.\d{1,3})?$/.test(num))) {
+                        toastr.error('请输入大于0并且小于3位小数的浮点数');
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    select[col.field] = validText;
 
-                // 更新至服务器
-                postData(window.location.pathname + '/month/save', { type:'update', updateData: { mb_id: select.mb_id, yearmonth: col.field, value: validText } }, function (result) {
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                    materialBillsData = result.materialBillsData;
-                    SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
-                    m_tp = result.m_tp;
-                    resetTpTable();
-                }, function () {
-                    select[col.field] = orgValue;
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                });
+                    // 更新至服务器
+                    postData(window.location.pathname + '/month/save', { type:'update', updateData: { mb_id: select.mb_id, yearmonth: col.field, value: validText } }, function (result) {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        materialBillsData = result.materialBillsData;
+                        SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
+                        m_tp = result.m_tp;
+                        resetTpTable();
+                    }, function () {
+                        select[col.field] = orgValue;
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    });
+                }
             }
         },
         deletePress: function (sheet) {
@@ -758,13 +838,14 @@ $(document).ready(() => {
                 SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
                 return;
             }
-            if (sortData.length > 0 && range.col + range.colCount > 4 + months.length) {
+            if (sortData.length > 0 && range.col + range.colCount > 5 + months.length) {
                 toastMessageUniq(hint.cellError);
                 SpreadJsObj.reLoadSheetHeader(materialMonthSpread.getActiveSheet());
                 SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
                 return;
             }
             const data = [];
+            let pasteOrigin = false;
             for (let iRow = 0; iRow < range.rowCount; iRow++) {
                 let bPaste = true;
                 const curRow = range.row + iRow;
@@ -786,16 +867,20 @@ $(document).ready(() => {
                         }
                         continue;
                     }
-                    const num = parseFloat(validText);
-                    if (isNaN(validText)) {
-                        toastMessageUniq(getPasteHint(hint.numberExpr, hintRow));
-                        bPaste = false;
-                        continue;
-                    }
-                    if (validText !== null && (num < 0 || !/^\d+(\.\d{1,3})?$/.test(num))) {
-                        toastMessageUniq(getPasteHint(hint.numberCan, hintRow));
-                        bPaste = false;
-                        continue;
+                    if (colSetting.field === 'origin') {
+                        pasteOrigin = true;
+                    } else {
+                        const num = parseFloat(validText);
+                        if (isNaN(validText)) {
+                            toastMessageUniq(getPasteHint(hint.numberExpr, hintRow));
+                            bPaste = false;
+                            continue;
+                        }
+                        if (validText !== null && (num < 0 || !/^\d+(\.\d{1,3})?$/.test(num))) {
+                            toastMessageUniq(getPasteHint(hint.numberCan, hintRow));
+                            bPaste = false;
+                            continue;
+                        }
                     }
                     materialMonthData[colSetting.field] = validText;
                     sortData[curRow][colSetting.field] = validText;
@@ -810,17 +895,28 @@ $(document).ready(() => {
                 SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
                 return;
             }
-            // 更新至服务器
-            postData(window.location.pathname + '/month/save', { type:'paste', updateData: data }, function (result) {
-                SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
-                materialBillsData = result.materialBillsData;
-                SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
-                m_tp = result.m_tp;
-                resetTpTable();
-            }, function () {
-                SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
-                return;
-            });
+            if (pasteOrigin) {
+                // 更新至服务器
+                postData(window.location.pathname + '/month/save', { type:'pasteOrigin', updateData: data }, function (result) {
+                    SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
+                    materialBillsData = result.materialBillsData;
+                }, function () {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                    return;
+                });
+            } else {
+                // 更新至服务器
+                postData(window.location.pathname + '/month/save', { type:'paste', updateData: data }, function (result) {
+                    SpreadJsObj.reLoadSheetData(materialMonthSpread.getActiveSheet());
+                    materialBillsData = result.materialBillsData;
+                    SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialBillsData);
+                    m_tp = result.m_tp;
+                    resetTpTable();
+                }, function () {
+                    SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
+                    return;
+                });
+            }
         },
     };
 
@@ -830,6 +926,8 @@ $(document).ready(() => {
     if (!readOnly) {
         $('#add').click(materialSpreadObj.add);
         $('#del').click(materialSpreadObj.del);
+        $('#up-move').click(materialSpreadObj.upMove);
+        $('#down-move').click(materialSpreadObj.downMove);
         materialSpread.bind(spreadNS.Events.EditEnded, materialSpreadObj.editEnded);
         materialSpread.bind(spreadNS.Events.ButtonClicked, materialSpreadObj.buttonClicked);
         materialMonthSpread.bind(spreadNS.Events.EditEnded, materialMonthSpreadObj.editEnded);

+ 21 - 2
app/public/js/material_file.js

@@ -255,9 +255,28 @@ $(document).ready(function () {
         // console.log('fileIds', fileIds)
 
         if (fileIds.length) {
+            if (fileIds.length > 10) {
+              return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`)
+            }
+            toastr.success('正在进行压缩文件...', '', { timeOut: 0, extendedTimeOut: 0})
+            $(this).attr('disabled', "true")
+            const btn = $(this)
+            postCompressFile(`/tender/${tid}/measure/material/${order}/file/download/compresse-file`, {fileIds}, function(result) {
+              toastr.clear()
+              toastr.success('压缩文件成功')
+              btn.removeAttr('disabled')
+              const href = window.URL.createObjectURL(result)
+              $('#zipDown').attr('href', href);
+              $('#zipDown').attr('download', `${tender.name}-材料调差-第${order}期-附件.zip`);
+              $("#zipDown")[0].click();
+            }, () => {
+              btn.removeAttr('disabled')
+              toastr.clear()
+              toastr.error('批量下载失败')
+            });
             // postData( `/tender/${tid}/measure/material/${order}/file/download/compresse-file`, { fileIds })
-            $('#downloadZip').attr('href', `/tender/${tid}/measure/material/${order}/file/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`);
-            $('#downloadZip')[0].click();
+            // $('#downloadZip').attr('href', `/tender/${tid}/measure/material/${order}/file/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`);
+            // $('#downloadZip')[0].click();
         }
     });
     function handleFileList(fileList) {

+ 26 - 6
app/public/js/stage.js

@@ -3663,7 +3663,7 @@ $(document).ready(() => {
             }
             if (tab.attr('content') === '#fujian') {
                 const node = SpreadJsObj.getSelectObject(slSpread.getActiveSheet());
-                getNodeList(node.id);
+                node && getNodeList(node.id);
             }
             if (tab.attr('content') === '#zhongjian') {
                 if (!detail) {
@@ -3721,8 +3721,9 @@ $(document).ready(() => {
         // if (curAuditor && curAuditor.aid !== cur_uid) {
         //     return toastr.error('当前操作没有权限!');
         // }
-        const files = $('#upload-file')[0].files;
         const node = SpreadJsObj.getSelectObject(slSpread.getActiveSheet());
+        if (!node) return
+        const files = $('#upload-file')[0].files;
         const formData = new FormData();
         formData.append('lid', node.id);
         for (const file of files) {
@@ -3953,7 +3954,7 @@ $(document).ready(() => {
     // 批量下载
     $('#bach-download').click(function() {
         const fileIds = [];
-        const type = $(this).prop('type');
+        const type = $(this).attr('type');
         let node = ''
         if (type === 'curr') {
             node = '#nodelist-table .check-file:checked'
@@ -3966,9 +3967,28 @@ $(document).ready(() => {
         });
 
         if (fileIds.length) {
-            const url = `/tender/${tender.id}/measure/stage/${stage.order}/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`;
-            $('#zipDown').attr('href', url);
-            $("#zipDown")[0].click();
+            if (fileIds.length > 10) {
+              return toastr.warning(`最大允许10个文件(当前${fileIds.length}个)`)
+            }
+            toastr.success('正在进行压缩文件...', '', { timeOut: 0, extendedTimeOut: 0})
+            $(this).attr('disabled', "true")
+            const btn = $(this)
+            postCompressFile(`/tender/${tender.id}/measure/stage/${stage.order}/download/compresse-file`, {fileIds}, function(result) {
+              toastr.clear()
+              toastr.success('压缩文件成功')
+              btn.removeAttr('disabled')
+              const href = window.URL.createObjectURL(result)
+              $('#zipDown').attr('href', href);
+              $('#zipDown').attr('download', `${tender.name}-计量台账-第${stage.order}期-附件.zip`);
+              $("#zipDown")[0].click();
+            }, () => {
+              btn.removeAttr('disabled')
+              toastr.clear()
+              toastr.error('批量下载失败')
+            });
+            // const url = `/tender/${tender.id}/measure/stage/${stage.order}/download/compresse-file?fileIds=${JSON.stringify(fileIds)}`;
+            // $('#zipDown').attr('href', url);
+            // $("#zipDown")[0].click();
         }
     });
 

+ 3 - 3
app/router.js

@@ -264,7 +264,7 @@ module.exports = app => {
     app.post('/tender/:id/measure/stage/:order/delete/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.deleteFile');
     app.post('/tender/:id/measure/stage/:order/save/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.saveFile');
     app.post('/tender/:id/measure/stage/:order/check/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.checkFile');
-    app.get('/tender/:id/measure/stage/:order/download/compresse-file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.downloadZip');
+    app.post('/tender/:id/measure/stage/:order/download/compresse-file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.downloadZip');
 
     // 中间计量
     app.get('/tender/:id/measure/stage/:order/detail', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.detail');
@@ -386,7 +386,7 @@ module.exports = app => {
     app.get('/change/download/file/:id', sessionAuth, 'changeController.downloadFile');
     app.post('/change/download/file/:id', sessionAuth, 'changeController.checkFile');
     app.post('/tender/:id/change/:cid/info/file/delete', sessionAuth, 'changeController.deleteFile');
-    app.get('/tender/:id/change/:cid/download/compresse-file', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.downloadZip');
+    app.post('/tender/:id/change/:cid/download/compresse-file', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.downloadZip');
     app.post('/tender/:id/change/delete', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.delete');
     app.post('/tender/:id/change/bills', sessionAuth, tenderCheck, uncheckTenderCheck, 'changeController.bills');
 
@@ -438,7 +438,7 @@ module.exports = app => {
     app.get('/tender/:id/measure/material/:order/file/:fid/download', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.downloadFile');
     app.post('/tender/:id/measure/material/:order/file/find', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.getCurMatericalFiles');
     app.post('/tender/:id/measure/material/:order/file/delete', sessionAuth, tenderCheck, uncheckTenderCheck, materialCheck, 'materialController.deleteFile');
-    app.get('/tender/:id/measure/material/:order/file/download/compresse-file', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.downloadZip');
+    app.post('/tender/:id/measure/material/:order/file/download/compresse-file', sessionAuth, tenderCheck, uncheckTenderCheck, 'materialController.downloadZip');
 
     // 个人账号相关
     app.get('/profile/info', sessionAuth, 'profileController.info');

+ 26 - 2
app/service/advance.js

@@ -1,6 +1,8 @@
 'use strict';
 
 const auditConst = require('../const/audit').advance;
+const path = require('path');
+const fs = require('fs');
 
 module.exports = app => {
     class Advance extends app.BaseService {
@@ -205,9 +207,31 @@ module.exports = app => {
         /**
          * 删除预付款记录
          * @param {String} id 预付款id
+         * @param {String} tid 标段id
          */
-        async deleteAdvance(id) {
-            return await this.deleteById(id);
+        async deleteAdvance(id, tid) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                // 删除预付款记录
+                await transaction.delete(this.tableName, { id, tid });
+                // 删除附件
+                const fileInfo = await this.db.select(this.ctx.service.advanceFile.tableName, { where: { vid: id, tid } });
+                await transaction.delete(this.ctx.service.advanceFile.tableName, { vid: id, tid });
+                // 先删除文件
+                for (let i = 0; i < fileInfo.length; i++) {
+                    const file = fileInfo[i];
+                    if (fs.existsSync(path.resolve(this.app.baseDir, './app', file.filepath))) {
+                        fs.unlinkSync(path.resolve(this.app.baseDir, './app', file.filepath));
+                        // fs.unlinkSync(path.resolve(this.app.baseDir, zipPath));
+                    }
+                }
+                // 删除审批记录
+                await transaction.delete(this.ctx.service.advanceAudit.tableName, { vid: id, tid });
+                await transaction.commit();
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
         }
     }
     return Advance;

+ 11 - 0
app/service/advance_file.js

@@ -50,6 +50,17 @@ module.exports = app => {
         async delete(id) {
             return await this.deleteById(id);
         }
+
+        /**
+         * 根据预付款id删除附件
+         * @param {String} vid - 预付款id
+         * @return {void}
+         */
+        async deleteByVid(vid) {
+            await this.db.delete(this.tableName, {
+                vid,
+            });
+        }
     }
     return AdvanceFile;
 };

+ 6 - 6
app/service/change.js

@@ -376,7 +376,7 @@ module.exports = app => {
 
         async getTp(tenderId, status) {
             if (this.ctx.tender.isTourist && status === 0) {
-                const sql5 = 'SELECT SUM(total_price) AS total_price FROM ?? WHERE tid = ?';
+                const sql5 = 'SELECT SUM(cast (total_price as decimal(18,6))) AS total_price FROM ?? WHERE tid = ?';
                 const sqlParam5 = [this.tableName, tenderId];
                 const result5 = await this.db.query(sql5, sqlParam5);
                 return result5[0].total_price ? result5[0].total_price : 0;
@@ -384,7 +384,7 @@ module.exports = app => {
             switch (status) {
                 case 0: // 包含你的所有变更令
                     const sql =
-                        'SELECT SUM(a.total_price) AS total_price FROM ?? AS a WHERE a.tid = ? AND ' +
+                        'SELECT SUM(cast (a.total_price as decimal(18,6))) AS total_price FROM ?? AS a WHERE a.tid = ? AND ' +
                         '(a.uid = ? OR (a.status != ? AND a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? AND a.times = b.times GROUP BY b.cid)) OR a.status = ? )';
                     const sqlParam = [
                         this.tableName,
@@ -398,13 +398,13 @@ module.exports = app => {
                     const result = await this.db.query(sql, sqlParam);
                     return result[0].total_price ? result[0].total_price : 0;
                 case 1: // 待处理(你的)
-                    const sql6 = 'SELECT SUM(a.total_price) AS total_price FROM ?? as a WHERE cid in(SELECT b.cid FROM ?? as b WHERE tid = ? AND uid = ? AND status = ?)';
+                    const sql6 = 'SELECT SUM(cast (a.total_price as decimal(18,6))) AS total_price FROM ?? as a WHERE cid in(SELECT b.cid FROM ?? as b WHERE tid = ? AND uid = ? AND status = ?)';
                     const sqlParam6 = [this.tableName, this.ctx.service.changeAudit.tableName, tenderId, this.ctx.session.sessionUser.accountId, audit.flow.auditStatus.checking];
                     const result6 = await this.db.query(sql6, sqlParam6);
                     return result6[0].total_price ? result6[0].total_price : 0;
                 case 5: // 待上报(所有的)PS:取未上报,退回,修订的变更令
                     const sql2 =
-                        'SELECT SUM(a.total_price) AS total_price FROM ?? AS a WHERE ' +
+                        'SELECT SUM(cast (a.total_price as decimal(18,6))) AS total_price FROM ?? AS a WHERE ' +
                         'a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? AND a.times = b.times GROUP BY b.cid) ' +
                         'AND (a.status = ? OR a.status = ? OR a.status = ?) AND a.tid = ?';
                     const sqlParam2 = [
@@ -421,13 +421,13 @@ module.exports = app => {
                 case 2: // 进行中(所有的)
                 case 4: // 终止(所有的)
                     const sql3 =
-                        'SELECT SUM(a.total_price) AS total_price FROM ?? AS a WHERE ' +
+                        'SELECT SUM(cast (a.total_price as decimal(18,6))) AS total_price FROM ?? AS a WHERE ' +
                         'a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? AND a.times = b.times GROUP BY b.cid) AND a.status = ? AND a.tid = ?';
                     const sqlParam3 = [this.tableName, this.ctx.service.changeAudit.tableName, this.ctx.session.sessionUser.accountId, status, tenderId];
                     const result3 = await this.db.query(sql3, sqlParam3);
                     return result3[0].total_price ? result3[0].total_price : 0;
                 case 3: // 已完成(所有的)
-                    const sql4 = 'SELECT SUM(total_price) AS total_price FROM ?? WHERE status = ? AND tid = ?';
+                    const sql4 = 'SELECT SUM(cast (total_price as decimal(18,6))) AS total_price FROM ?? WHERE status = ? AND tid = ?';
                     const sqlParam4 = [this.tableName, status, tenderId];
                     const result4 = await this.db.query(sql4, sqlParam4);
                     return result4[0].total_price ? result4[0].total_price : 0;

+ 8 - 8
app/service/change_att.js

@@ -93,7 +93,7 @@ module.exports = app => {
                 const ziparchiver = archiver('zip');
                 const outputPath = fs.createWriteStream(path.resolve(this.app.baseDir, zipPath));
                 outputPath.on('error', err => {
-                    reject(err);
+                    return reject(err);
                 });
 
                 ziparchiver.pipe(outputPath);
@@ -103,20 +103,20 @@ module.exports = app => {
 
                 // 存档警告
                 ziparchiver.on('warning', function(err) {
-                    if (err.code === 'ENOENT') {
-                        console.warn('stat故障和其他非阻塞错误');
-                    }
-                    reject(err);
+                    // if (err.code === 'ENOENT') {
+                    //     console.warn('stat故障和其他非阻塞错误');
+                    // }
+                    return reject(err);
                 });
 
                 // 存档出错
                 ziparchiver.on('error', function(err) {
-                    console.log(err);
-                    reject(err);
+                    // console.log(err);
+                    return reject(err);
                 });
                 ziparchiver.finalize();
                 outputPath.on('close', () => {
-                    resolve(ziparchiver.pointer());
+                    return resolve(ziparchiver.pointer());
                 });
             });
         }

+ 2 - 2
app/service/material.js

@@ -189,7 +189,7 @@ module.exports = app => {
                 await transaction.delete(this.ctx.service.materialFile.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialExponent.tableName, { mid: id });
                 await transaction.delete(this.ctx.service.materialExponentHistory.tableName, { mid: id });
-                // 如果存在上一期,把上一期的quantity,expr,msg_tp,msg_times,msg_spread,m_up_risk,m_down_risk,m_spread,m_tp,pre_tp,is_summary添加到bill中
+                // 如果存在上一期,把上一期的quantity,expr,msg_tp,msg_times,msg_spread,m_up_risk,m_down_risk,m_spread,m_tp,pre_tp,orgin,is_summary添加到bill中
                 const materialInfo = await this.getDataById(id);
                 if (materialInfo.order > 1) {
                     const sql = 'UPDATE ' + this.ctx.service.materialBills.tableName + ' as mb, ' +
@@ -199,7 +199,7 @@ module.exports = app => {
                         'mb.`msg_spread` = mbh.`msg_spread`, mb.`m_up_risk` = mbh.`m_up_risk`, ' +
                         'mb.`m_down_risk` = mbh.`m_down_risk`, mb.`m_spread` = mbh.`m_spread`, ' +
                         'mb.`m_tp` = mbh.`m_tp`, mb.`pre_tp` = mbh.`pre_tp`, ' +
-                        'mb.`is_summary` = mbh.`is_summary` ' +
+                        'mb.`origin` = mbh.`origin`, mb.`is_summary` = mbh.`is_summary` ' +
                         'WHERE mbh.`tid` = ? AND mbh.`order` = ? AND mbh.`mb_id` = mb.`id`';
                     const sqlParam = [this.ctx.tender.id, materialInfo.order - 1];
                     await transaction.query(sql, sqlParam);

+ 1 - 0
app/service/material_audit.js

@@ -253,6 +253,7 @@ module.exports = app => {
                         m_spread: mb.m_spread,
                         m_tp: mb.m_tp,
                         pre_tp: mb.pre_tp,
+                        origin: mb.origin,
                         is_summary: mb.is_summary,
                     };
                     mbhList.push(newMbh);

+ 65 - 1
app/service/material_bills.js

@@ -33,11 +33,13 @@ module.exports = app => {
             if (!this.ctx.tender || !this.ctx.material) {
                 throw '数据错误';
             }
+            const order = await this._getMaxOrder(this.ctx.material.id);
             const transaction = await this.db.beginTransaction();
             try {
                 const newBills = {
                     tid: this.ctx.tender.id,
                     mid: this.ctx.material.id,
+                    order: order + 1,
                     in_time: new Date(),
                 };
                 // 新增工料
@@ -67,6 +69,13 @@ module.exports = app => {
             }
         }
 
+        async _getMaxOrder(materialId) {
+            const sql = 'SELECT Max(??) As value FROM ?? Where mid = ' + materialId;
+            const sqlParam = ['order', this.tableName];
+            const queryResult = await this.db.queryOne(sql, sqlParam);
+            return queryResult.value ? queryResult.value : 0;
+        }
+
         /**
          * 删除工料
          * @param {int} id 工料id
@@ -99,6 +108,37 @@ module.exports = app => {
         }
 
         /**
+         * 交换两个工料的顺序
+         * @param {Number} id1 - 工料1的id
+         * @param {Number} id2 - 工料2的id
+         * @returns {Promise<void>}
+         */
+        async changeOrder(id1, id2) {
+            if (!this.ctx.tender || !this.ctx.material) {
+                throw '数据错误';
+            }
+            const bill1 = await this.getDataByCondition({ tid: this.ctx.tender.id, id: id1 });
+            const bill2 = await this.getDataByCondition({ tid: this.ctx.tender.id, id: id2 });
+            if (!bill1 || !bill2) {
+                throw '数据错误';
+            }
+
+            const transaction = await this.db.beginTransaction();
+            try {
+                const order = bill1.order;
+                bill1.order = bill2.order;
+                bill2.order = order;
+                await transaction.update(this.tableName, { id: bill1.id, order: bill1.order });
+                await transaction.update(this.tableName, { id: bill2.id, order: bill2.order });
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        /**
          * 修改工料信息
          * @param {Object} data 工料内容
          * @return {void}
@@ -123,6 +163,28 @@ module.exports = app => {
             }
         }
 
+        async saveOrigin(data) {
+            if (!this.ctx.tender || !this.ctx.material) {
+                throw '数据错误';
+            }
+            return await this.db.update(this.tableName, { id: data.mb_id, origin: data.value });
+        }
+
+        async saveOrigins(datas) {
+            if (!this.ctx.tender || !this.ctx.material) {
+                throw '数据错误';
+            }
+            const updateData = [];
+            for (const data of datas) {
+                updateData.push({
+                    id: data.mb_id,
+                    origin: data.origin,
+                });
+            }
+            if (updateData.length > 0) await this.db.updateRows(this.tableName, updateData);
+            return true;
+        }
+
         /**
          * 修改工料信息
          * @param {Object} data 工料内容
@@ -185,7 +247,7 @@ module.exports = app => {
                 const sqlParam = [mid, mb.id];
                 const mb_quantity = await transaction.queryOne(sql, sqlParam);
                 console.log(mb_quantity);
-                // 取历史期记录获取截止上期调差金额,并清空本期单价和时间,重新计算价差和有效价差
+                // 取历史期记录获取截止上期调差金额,并清空本期单价和时间,来源地,重新计算价差和有效价差
                 const updateData = {
                     id: mb.id,
                     quantity: this.ctx.helper.round(mb_quantity.quantity, 3),
@@ -193,6 +255,7 @@ module.exports = app => {
                     msg_times: null,
                     msg_spread: newmsg_spread,
                     m_spread: newm_spread,
+                    origin: null,
                     m_tp: this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(mb_quantity.quantity, 3), newm_spread), 2),
                     pre_tp: mb.m_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, mb.m_tp), 2) : mb.pre_tp,
                 };
@@ -207,6 +270,7 @@ module.exports = app => {
                     msg_times: null,
                     msg_spread: newmsg_spread,
                     m_spread: newm_spread,
+                    origin: null,
                     m_tp: quantity !== 0 && quantity !== null ? this.ctx.helper.round(this.ctx.helper.mul(this.ctx.helper.round(quantity, 3), newm_spread), 2) : null,
                     pre_tp: mb.m_tp !== null ? this.ctx.helper.round(this.ctx.helper.add(mb.pre_tp, mb.m_tp), 2) : mb.pre_tp,
                 };

+ 8 - 8
app/service/material_file.js

@@ -94,7 +94,7 @@ module.exports = app => {
                 const ziparchiver = archiver('zip');
                 const outputPath = fs.createWriteStream(path.resolve(this.app.baseDir, zipPath));
                 outputPath.on('error', err => {
-                    reject(err);
+                    return reject(err);
                 });
 
                 ziparchiver.pipe(outputPath);
@@ -104,20 +104,20 @@ module.exports = app => {
 
                 // 存档警告
                 ziparchiver.on('warning', function(err) {
-                    if (err.code === 'ENOENT') {
-                        console.warn('stat故障和其他非阻塞错误');
-                    }
-                    reject(err);
+                    // if (err.code === 'ENOENT') {
+                    //     console.warn('stat故障和其他非阻塞错误');
+                    // }
+                    return reject(err);
                 });
 
                 // 存档出错
                 ziparchiver.on('error', function(err) {
-                    console.log(err);
-                    reject(err);
+                    // console.log(err);
+                    return reject(err);
                 });
                 ziparchiver.finalize();
                 outputPath.on('close', () => {
-                    resolve(ziparchiver.pointer());
+                    return resolve(ziparchiver.pointer());
                 });
             });
         }

+ 7 - 9
app/service/stage.js

@@ -224,9 +224,8 @@ module.exports = app => {
                 await this.doCheckStage(stage);
                 if (!stage.readOnly && stage.check_calc) {
                     const tpData = await this.ctx.service.stageBills.getSumTotalPrice(stage);
-                    const srCache = await this.ctx.service.stageRela.getSumCacheTp(stage.id);
-                    stage.contract_tp = this.ctx.helper.add(tpData.contract_tp, srCache.contract_tp);
-                    stage.qc_tp = this.ctx.helper.add(tpData.qc_tp, srCache.qc_tp);
+                    stage.contract_tp = tpData.contract_tp;
+                    stage.qc_tp = tpData.qc_tp;
                     const tp = await this.ctx.service.stagePay.getSpecialTotalPrice(stage);
                     stage.yf_tp = tp.yf;
                     stage.sf_tp = tp.sf;
@@ -447,7 +446,6 @@ module.exports = app => {
             for (const cb of calcBase) {
                 const sum = await this.ctx.service.stageBills.getSumTotalPrice(stage);
                 const bg = await this.ctx.service.stageChange.getQualityTotalPrice(stage);
-                const srCache = await this.ctx.service.stageRela.getSumCacheTp(stage.id);
                 switch (cb.code) {
                     case 'htj':
                         cb.value = param.contractPrice;
@@ -465,7 +463,7 @@ module.exports = app => {
                         cb.value = param.materialAdvance;
                         break;
                     case 'bqwc':
-                        cb.value = this.ctx.helper.sum([sum.contract_tp, sum.qc_tp, srCache.gather_tp]);
+                        cb.value = this.ctx.helper.add(sum.contract_tp, sum.qc_tp);
                         break;
                     case 'bqht':
                         cb.value = sum.contract_tp;
@@ -475,16 +473,16 @@ module.exports = app => {
                         break;
                     case 'ybbqwc':
                         const sumGcl = await this.ctx.service.stageBills.getSumTotalPriceGcl(stage, '^[^0-9]*1[0-9]{2}(-|$)');
-                        cb.value = this.ctx.helper.sum([sumGcl.contract_tp, sumGcl.qc_tp, srCache.gather_tp_100]);
+                        cb.value = this.ctx.helper.add(sumGcl.contract_tp, sumGcl.qc_tp);
                         break;
                     case 'ybbqbg':
-                        cb.value = this.ctx.helper.add(bg.common, srCache.bg_common);
+                        cb.value = bg.common;
                         break;
                     case 'jdbqbg':
-                        cb.value = this.ctx.helper.add(bg.more, srCache.bg_more);
+                        cb.value = bg.more;
                         break;
                     case 'zdbqbg':
-                        cb.value = this.ctx.helper.add(bg.great, srCache.bg_great);
+                        cb.value = bg.great;
                         break;
                     default:
                         cb.value = 0;

+ 4 - 4
app/service/stage_att.js

@@ -124,16 +124,16 @@ module.exports = app => {
 
                 // 存档警告
                 ziparchiver.on('warning', function(err) {
-                    if (err.code === 'ENOENT') {
-                        console.warn('stat故障和其他非阻塞错误');
-                    }
+                    // if (err.code === 'ENOENT') {
+                    //     console.warn('stat故障和其他非阻塞错误');
+                    // }
                     return reject(err);
 
                 });
 
                 // 存档出错
                 ziparchiver.on('error', function(err) {
-                    console.log(err);
+                    // console.log(err);
                     return reject(err);
                 });
 

+ 2 - 2
app/service/stage_rela.js

@@ -79,8 +79,8 @@ class srCache {
             ? this.ctx.service.stageRelaPosFinal.getAllDataByCondition({ where: { sid: this.preRelaStage.sid, rela_tid: this.preRelaStage.rela_tid } })
             : [];
         this.ctx.helper.assignRelaData(pos, [
-            { data: curPosData, fields: ['contract_qty', 'qc_qty', 'postil'], prefix: '', relaId: 'pid' },
-            { data: preStagePos, fields: ['contract_qty', 'qc_qty', 'postil'], prefix: 'pre_', relaId: 'pid' },
+            { data: curPosData, fields: ['contract_qty', 'qc_qty', 'postil', 'pid'], prefix: '', relaId: 'pid' },
+            { data: preStagePos, fields: ['contract_qty', 'qc_qty', 'postil', 'pid'], prefix: 'pre_', relaId: 'pid' },
         ]);
         for (const p of pos) {
             p.gather_qty = this.ctx.helper.add(p.contract_qty, p.qc_qty);

+ 4 - 1
app/view/advance/index.ejs

@@ -62,7 +62,7 @@
                         </tr>
                     </thead>
                     <tbody id="advanceList">
-                        <% advanceList.forEach(item => { %>
+                        <% advanceList.forEach((item, idx) => { %>
                             <tr>
                                 <td><a href="/tender/<%- ctx.tender.id %>/advance/<%- item.id %>/detail" data-id="<%- item.id %>">第<%- item.order %>期</a></td>
                                 <td><%- item.pay_ratio %>%</td>
@@ -88,6 +88,9 @@
                                     <% } else {%>
                                         <span class="<%- auditConst.statusClass[item.status] %>"><%- auditConst.statusString[item.status] %></span>
                                     <% } %>
+                                    <% if (item.status === auditConst.status.checked && !!ctx.session.sessionUser.is_admin && item.order === advanceList.length) { %>
+                                      <a href="del-qi" class="btn btn-outline-danger btn-sm ml-1" data-toggle="modal" data-target="#del-qi" data-id="<%- item.id %>" data-order="<%- item.order %>">删除</a>
+                                    <% } %>
                                 </td>
                             </tr>
                         <% }) %>

+ 5 - 2
app/view/change/information.ejs

@@ -94,12 +94,13 @@
                         </li>
                         <li class="nav-item ml-auto pt-1" id="fujian_btn" style="display:none;">
                             <!--所有附件 翻页-->
-                            <a href="javascript: void(0);" data-toggle="modal" class="btn btn-sm btn-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</a>
+                            <button  data-toggle="modal" class="btn btn-sm btn-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</button>
+                            <!-- <a href="javascript: void(0);" data-toggle="modal" class="btn btn-sm btn-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</a> -->
                             <a href="javascript:void(0);" class="page-select ml-3" content="pre"><i class="fa fa-chevron-left"></i></a> <span id="currentPage">1</span>/<span id="totalPage">10</span> <a href="javascript:void(0);" class="page-select mr-3" content="next"><i class="fa fa-chevron-right"></i></a>
                             <% if (auditStatus !== 8 || (auditStatus === 8 && ctx.tender.touristPermission.file)) { %>
                             <a href="#addfujian" data-toggle="modal" class="btn btn-sm btn-light text-primary" data-placement="bottom" title="" data-original-title="上传附件"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 上传附件</a>
                             <% } %>
-                            <a href="" id="downloadZip" style="display: none;" download></a>
+                            <a href="javascript: void(0);" id="zipDown" download style="display: none;"></a>
                         </li>
                     </ul>
                 </div>
@@ -382,12 +383,14 @@
     </div>
 </div>
 <script>
+    const tenderName = '<%- tender.name %>';
     const totalPriceUnit = '<%- tpUnit %>';
     const unitPriceUnit = '<%- upUnit %>';
     const accountId = parseInt('<%- ctx.session.sessionUser.accountId %>');
     const ledgeStatus = '<%- tender.ledger_status %>';
     const ledgerConsts = JSON.parse('<%- JSON.stringify(ledgerConsts) %>');
     const auditStatus = parseInt('<%- auditStatus %>');
+    const changeName = '<%- change.name %>';
     const touristPermission = parseInt('<%- ctx.tender.touristPermission.file %>');
     const auditList = JSON.parse(unescape('<%- escape(JSON.stringify(auditList)) %>'));
     const precision = JSON.parse('<%- JSON.stringify(precision) %>');

+ 4 - 2
app/view/material/file.ejs

@@ -16,8 +16,9 @@
           <% if (material.filePermission) { %>
           <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>
           <% } %>
-          <a href="javascript: void(0);" data-toggle="modal" class="btn btn-sm btn-light text-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</a>
-          <a href="" id="downloadZip" style="display: none;" download></a>
+          <button data-toggle="modal" class="btn btn-sm btn-light text-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</button>
+          <!-- <a href="javascript: void(0);" data-toggle="modal" class="btn btn-sm btn-light text-primary" id="bach-download"><i class="fa fa-download "></i> 批量下载</a> -->
+          <a href="javascript: void(0);" id="zipDown" download style="display: none;"></a>
         </div>
         <!-- <div class="d-inline-block">
           <span class="d-flex align-items-center" style="margin-left: 5px;">
@@ -121,5 +122,6 @@
   const mid = '<%- ctx.material.id %>';
   const order = '<%- ctx.material.order %>';
   const fileList = JSON.parse(unescape('<%- escape(JSON.stringify(fileList)) %>'));
+  const tender = JSON.parse(unescape('<%- escape(JSON.stringify(tender)) %>'));
   const whiteList = JSON.parse('<%- JSON.stringify(whiteList) %>');
 </script>

+ 2 - 0
app/view/material/info.ejs

@@ -8,6 +8,8 @@
                     <div class="d-inline-block">
                         <a href="javascript: void(0);" id="add" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="新增材料"><i class="fa fa-plus" aria-hidden="true"></i></a>
                         <a href="javascript: void(0);" id="del" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除材料"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                        <a href="javascript: void(0);" id="down-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                        <a href="javascript: void(0);" id="up-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
                     </div>
                 <% } %>
                 <div class="d-inline-block ml-3">

+ 1 - 1
app/view/setting/user.ejs

@@ -3,7 +3,7 @@
     <div class="panel-title">
         <div class="title-main">
             <h2>账号管理
-                <% if (projectData.max_user !== user_total) { %>
+                <% if (projectData.max_user > user_total) { %>
                 <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
                 <% } else { %>
                 <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>

+ 1 - 1
app/view/setting/user_permission.ejs

@@ -3,7 +3,7 @@
     <div class="panel-title">
         <div class="title-main">
             <h2>账号管理
-                <% if (projectData.max_user !== accountData.length) { %>
+                <% if (projectData.max_user > user_total) { %>
                 <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
                 <% } else { %>
                 <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>

+ 2 - 1
app/view/stage/index.ejs

@@ -274,7 +274,8 @@
                                     <a class="nav-link" data-toggle="tab" href="#syfujian" role="tab" fujian-content="syfujian">所有附件</a>
                                 </li>
                                 <li class="nav-item ml-auto pt-1">
-                                    <a href="javascript:void(0);" id="bach-download" class="btn btn-sm btn-primary" type="curr">批量下载</a>
+                                    <!-- <a href="javascript:void(0);" id="bach-download" class="btn btn-sm btn-primary" type="curr">批量下载</a> -->
+                                    <button id="bach-download" class="btn btn-sm btn-primary" type="curr">批量下载</button>
                                     <!--所有附件 翻页-->
                                     <span id="showPage" style="display: none"><a href="javascript:void(0);" class="page-select ml-3" content="pre"><i class="fa fa-chevron-left"></i></a> <span id="currentPage">1</span>/<span id="totalPage">10</span> <a href="javascript:void(0);" class="page-select mr-3" content="next"><i class="fa fa-chevron-right"></i></a></span>
                                     <!-- <% if (!ctx.tender.isTourist && stage.filePermission) { %>

+ 2 - 2
app/view/tender/detail.ejs

@@ -1297,8 +1297,8 @@
             // 创建地图实例
 
             const polyLineList = [];
-            const centerPoint = { lng: 116.404, lat: 39.915 };
-            let level = 15;
+            const centerPoint = { lng: <%- map_json.lng %>, lat: <%- map_json.lat %> };
+            let level = <%- map_json.level %>;
             const pointList = [];
             const centerList = [];
             for (const tm of tenderMapList) {

+ 2 - 0
builder_report_index_define.js

@@ -507,6 +507,8 @@ const stage_pos = {
         { name: '备注1', field: 'ex_memo1', type: dataType.str },
         { name: '备注2', field: 'ex_memo2', type: dataType.str },
         { name: '备注3', field: 'ex_memo3', type: dataType.str },
+
+        { name: '现场实际数量', field: 'real_qty', type: dataType.currency },
     ],
 };
 const stage_pos_compare = {