Browse Source

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

zhongzewei 7 years ago
parent
commit
ca145b74e2

+ 1 - 0
.gitignore

@@ -3,5 +3,6 @@ node_modules/
 dist/
 .idea/
 tmp/*.xlsx
+tmp/*.pdf
 test/unit/logs
 *.log

+ 116 - 0
modules/main/controllers/quantity_detail_controller.js

@@ -0,0 +1,116 @@
+/**
+ * Created by zhang on 2017/11/24.
+ */
+
+var quantity_detail_data = require('../facade/quantity_detail_facade');
+let logger = require("../../../logs/log_helper").logger;
+module.exports={
+    save:save,
+    update:update,
+    updateRegex:updateRegex,
+    insertRecode:insertRecode,
+    deleteRecode:deleteRecode,
+    swapRow:swapRow
+}
+
+async function save(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let datas= await quantity_detail_data.saveQuantityDetail(data);
+        result.data=datas;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
+async function update(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let datas= await quantity_detail_data.update(data);
+        result.data=datas;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
+async function updateRegex(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let datas= await quantity_detail_data.updateRegex(data);
+        result.data=datas;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
+async function insertRecode(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let datas= await quantity_detail_data.insertRecode(data);
+        result.data=datas;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
+async function deleteRecode(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let datas= await quantity_detail_data.deleteRecode(data);
+        result.data=datas;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
+async function swapRow(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let datas= await quantity_detail_data.swapRow(data);
+        result.data=datas;
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}

+ 17 - 2
modules/main/facade/decimal_facade.js

@@ -2,10 +2,11 @@
  * Created by zhang on 2017/11/22.
  */
 let projectsModel = require("../../pm/models/project_schema");
-
+let _ = require('lodash');
 
 module.exports ={
-    getProjectDecimal:getProjectDecimal
+    getProjectDecimal:getProjectDecimal,
+    getBillsQuantityDecimal:getBillsQuantityDecimal
 }
 
 async function getProjectDecimal(projectID) {
@@ -15,4 +16,18 @@ async function getProjectDecimal(projectID) {
         decimal = project.property.decimal
     }
     return decimal;
+}
+
+async function getBillsQuantityDecimal(projectID,unit) {
+    let decimal = null;
+    let project =await projectsModel.findOne({ID:projectID});
+    if(project){
+        let billsQuantityDecimal = project.property.billsQuantityDecimal;
+        let el = _.find(billsQuantityDecimal,{'unit':unit});
+        if(!el){
+            el = billsQuantityDecimal[0];
+        }
+        decimal = el.decimal
+    }
+    return decimal;
 }

+ 216 - 297
modules/ration_glj/facade/quantity_detail_facade.js

@@ -15,6 +15,7 @@ const uuidV1 = require('uuid/v1');
 let ration_model = mongoose.model('ration');
 let bill_model=mongoose.model("bills");
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
+let decimal_facade = require('./decimal_facade');
 
 module.exports={
     save:save,
@@ -22,58 +23,143 @@ module.exports={
     deleteByRation:deleteByRation,
     deleteByBill:deleteByBill,
     quantityEditChecking:quantityEditChecking,
+    saveQuantityDetail:saveQuantityDetail,
+    update:update,
+    updateRegex:updateRegex,
+    insertRecode:insertRecode,
+    deleteRecode:deleteRecode,
+    swapRow:swapRow
 };
 
 let operationMap={
-    'ut_create':create_quantity_detail,
     'ut_update':update_quantity_detail,
-    'ut_delete':delete_quantity_detail
 };
 
 let updateFunctionMap = {
-    'normalUpdate':normalUpdate,
-    'updateQuantityRegex':updateQuantityRegex,
     'insertRecode':insertRecode
 }
 
-function create_quantity_detail(user_id,datas) {
-    return function (callback) {
-        let doc = datas.doc;
-        doc.ID = uuidV1();
-        if(doc.hasOwnProperty('regex')){
-            insertRecodeWithReg(doc).then(function (resultObject) {
-                if(resultObject.err){
-                    callback(null,{
-                        moduleName:consts.projectConst.QUANTITY_DETAIL,
-                        err:{
-                            message:result.err.message
-                        }
-                    });
-                } else {
-                    callback(null,resultObject.return_list);
-                }
-            })
-        }else {
-            createNormalRecode(doc,callback)
-        }
+async function saveQuantityDetail(datas) {
+    console.log(datas);
+    let doc = datas;
+    doc.ID = uuidV1();
+    if(doc.refreshQuantity==false){ //如果选择了不替换工程量,则清空
+        await cleanQuantityDetail(doc);
+        return
+    }
+    if(doc.hasOwnProperty('regex')){
+       return await insertRecodeWithReg(doc);
+    }else {
+        return await createNormalRecode(doc);
+    }
+}
 
+async function update(datas) {
+    let doc = datas.doc;
+    if(doc.hasOwnProperty('isSummation')){
+        return await doIsSummationUpdate(datas.query,doc);
+    }else {
+       await quantity_detail_model.update(datas.query,doc);
+       return datas;
     }
 }
 
-function insertRecode(user_id,datas) {
-    return function (callback) {
-        let doc = datas.doc;
-        doc.ID = uuidV1();
-        doInsertRecode(doc).then(function (result) {
-            //console.log(result);
-            if(result.err){
-                callback(result.err,'')
-            }else {
-                callback(null,result.returndata)
-            }
+async function swapRow(datas) {
+    for(let task of datas){
+        await update(task);
+    }
+    return {refreshList:datas};
+}
+
+async function updateRegex(datas) {
+    let resultObjec ={};
 
-        })
+    let detailList = [];
+    let node ={};
+    let decimal =await decimal_facade.getProjectDecimal(datas.query.projectID);
+    if(datas.query.hasOwnProperty('rationID')){
+        detailList = await quantity_detail_model.find({'projectID':datas.query.projectID,'rationID':datas.query.rationID}).sort('seq').exec();
+        node.type = consts.projectConst.RATION;
+        node.ID = datas.query.rationID;
+    }else {
+        detailList = await quantity_detail_model.find({'projectID':datas.query.projectID,'billID':datas.query.billID}).sort('seq').exec();
+        node.type = consts.projectConst.BILLS;
+        node.ID=datas.query.billID;
     }
+    let regex;
+    let result;
+    if(datas.doc.regex==null){
+        result=0;
+        datas.doc.referenceIndexs=[];
+    }else {
+        regex = datas.doc.regex.toUpperCase();
+        let referenceIndexs = datas.doc.referenceIndexs;
+        result = getEvalResult(referenceIndexs,detailList,regex,decimal);
+    }
+    detailList[datas.query.index].result =result;
+    detailList[datas.query.index].regex=datas.doc.regex;
+    detailList[datas.query.index].referenceIndexs =datas.doc.referenceIndexs;
+    let updateTasks =[];
+    datas.doc.result=result;
+    updateTasks.push({
+        query:{
+            ID:datas.query.ID,
+            projectID:datas.query.projectID
+        },
+        doc:datas.doc
+    })
+    updateReferenceRecode(datas.query.index+1,detailList,updateTasks);
+    await quantity_detail_model.bulkWrite(generateUpdateTaks(updateTasks));
+    resultObjec.refreshList=updateTasks;
+    if(datas.query.refreshQuantity==true){
+        let data = {};
+        data.quantity = await summateResults(datas.query,detailList,decimal);
+        data.isFromDetail = 1;
+        node.data = data;
+        resultObjec.node = node;
+    }
+    return resultObjec;
+
+}
+
+
+async function cleanQuantityDetail(doc) {
+    let query = {
+        projectID:doc.projectID
+    }
+    if(doc.hasOwnProperty('rationID')){
+        query.rationID = doc.rationID;
+    }else {
+        query.billID = doc.billID;
+    }
+    await quantity_detail_model.deleteMany(query);
+}
+
+
+async function insertRecode(doc){
+    let query = {
+        projectID:doc.projectID,
+        seq : { $gte: doc.seq }
+    }
+    if(doc.hasOwnProperty('rationID')){
+        query.rationID = doc.rationID;
+    }else {
+        query.billID = doc.billID;
+    }
+    let quantity_detail_List = await getDatailList(doc,{data:{}});
+    let update_task = getUpdateReferenceTask(quantity_detail_List,doc.seq,1);
+    await quantity_detail_model.update(query,{$inc:{seq:1}},{multi: true});
+    if(update_task.length>0){
+        await quantity_detail_model.bulkWrite(generateUpdateTaks(update_task));
+    }
+    doc.ID = uuidV1();
+    let newrecode = await quantity_detail_model.create(doc);
+    let data={
+        doc:newrecode,
+        resort:true,
+        update_task:update_task
+    }
+    return data;
 }
 
 async function doInsertRecode(doc) {
@@ -150,229 +236,78 @@ function getUpdateReferenceTask(quantity_detail_List,seq,re) {
 }
 
 
-function createNormalRecode(doc,callback) {
-    quantity_detail_model.create(doc,(err,result)=>{
-        if(err){
-            callback(err,null);
-        }else {
-            console.log(result);
-            let returndata ={
-                updateTpye:commonConsts.UT_CREATE,
-                moduleName:consts.projectConst.QUANTITY_DETAIL,
-                data:result
-            }
-            callback(null,returndata)
-        }
-    });
+async function createNormalRecode(doc) {
+    let result ={};
+    result.newRecord= await quantity_detail_model.create(doc);
+    return result;
 }
 
 
 async function insertRecodeWithReg (doc) {
-    let returnObjec={
-        err:null,
-        return_list:[]
-    }
+    let returnObjec={}
     try {
-        let returnData={
-            moduleName:'',
-            data:{
-                updateTpye:commonConsts.UT_UPDATE,
-            }
-        }
+        let decimal =await decimal_facade.getProjectDecimal(doc.projectID);
         let regex = doc.regex.toUpperCase();
         let referenceIndexs = doc.referenceIndexs;
-        let detailList = await getDatailList(doc,returnData);
-        doc.result =getEvalResult(referenceIndexs,detailList,regex);
+        let detailList = await getDatailList(doc,returnObjec);
+        doc.result =getEvalResult(referenceIndexs,detailList,regex,decimal);
         let refreshQuantity =false;
         if(doc.refreshQuantity==true){
             refreshQuantity = true;
         }
         delete doc.refreshQuantity;
-        let newRecode = await quantity_detail_model.create(doc) ;
-        detailList.push(newRecode);
+        let newRecord = await quantity_detail_model.create(doc) ;
+        detailList.push(newRecord);
         if(refreshQuantity==true){
-            returnData.data.quantity = await summateResuts(doc,detailList);
-            returnData.data.quantityRefresh = true;
-            returnObjec.return_list.push(returnData);
+            let data = {};
+            data.quantity = await summateResults(doc,detailList,decimal);
+            data.isFromDetail = 1;
+            returnObjec.node.data = data;
         }
-        returnObjec.return_list.push({
-            updateTpye:commonConsts.UT_CREATE,
-            moduleName:consts.projectConst.QUANTITY_DETAIL,
-            data:newRecode
-        });
+        returnObjec.newRecord = newRecord;
         return returnObjec;
     }catch (error){
-        returnObjec.err = new Error('输入的表达式有误,请重新输入!');
-        console.log(error)
-        return returnObjec;
-    }
-
-
-}
-
-
-
-function normalUpdate(user_id,datas) {
-    return function(callback) {
-        if(datas.doc.hasOwnProperty('isSummation')){
-            doIsSummationUpdate(datas.query,datas.doc).then(function (sresult) {
-                let returndata ={
-                    moduleName:consts.projectConst.QUANTITY_DETAIL,
-                    data:{
-                        updateTpye:commonConsts.UT_UPDATE,
-                        query:datas.query,
-                        doc:datas.doc
-                    }
-                }
-                let retrunArr = [];
-                retrunArr.push(returndata);
-                if(sresult){
-                    retrunArr.push(sresult);
-                }
-                callback(null,retrunArr);
-            })
-        }else {
-            updateRecored(datas.query,datas.doc,callback);
-        }
-    }
-}
-function updateQuantityRegex(user_id,datas) {
-    return function(callback){
-        doRegexUpdate(datas).then(function (result) {
-            if(result.err){
-                callback(null,{
-                    moduleName:consts.projectConst.QUANTITY_DETAIL,
-                    err:{
-                        message:result.err.message
-                    }
-                });
-            }else {
-                callback(null,result.rList);
-            }
-
-        })
+        console.log(error);
+        throw new Error('输入的表达式有误,请重新输入!');
     }
 }
 
 async function doIsSummationUpdate(query,doc) {
-    try {
-        let returnData={
-            moduleName:'',
-            data:{
-                updateTpye:commonConsts.UT_UPDATE,
-            }
-        }
-        let  refreshQuantity=false;
-        if(query.refreshQuantity==true){
-            refreshQuantity=true;
-        }
-        delete query.refreshQuantity;
-        let updateDoc = await quantity_detail_model.update(query,doc);
-        let detailList = await getDatailList(query,returnData);
-        if(refreshQuantity==true){
-            let quantity = await summateResuts(query,detailList);
-            returnData.data.quantity = quantity;
-            returnData.data.quantityRefresh = true;
-            return returnData;
-        }else {
-            return null;
-        }
-    }catch (error){
-        console.log(error)
+    let returnObjec={query:query,doc:doc};
+    let decimal =await decimal_facade.getProjectDecimal(query.projectID);
+    let  refreshQuantity=false;
+    if(query.refreshQuantity==true){
+        refreshQuantity=true;
     }
+    delete query.refreshQuantity;
+    await quantity_detail_model.update(query,doc);
+    let detailList = await getDatailList(query,returnObjec);
+    if(refreshQuantity==true){
+        let data = {};
+        data.quantity = await summateResults(query,detailList,decimal);
+        data.isFromDetail = 1;
+        returnObjec.node.data = data;
+    }
+    return returnObjec;
 }
 
 async function getDatailList(query,resultObject) {
     let detailList = [];
+    let node={};
     if(query.hasOwnProperty('rationID')){
         detailList = await quantity_detail_model.find({'projectID':query.projectID,'rationID':query.rationID}).sort('seq').exec();
-        resultObject.moduleName = consts.projectConst.RATION;
-        resultObject.data.rationID=query.rationID;
-
+        node.type = consts.projectConst.RATION;
+        node.ID = query.rationID;
     }else {
         detailList = await quantity_detail_model.find({'projectID':query.projectID,'billID':query.billID}).sort('seq').exec();
-        resultObject.moduleName = consts.projectConst.BILLS;
-        resultObject.data.billID=query.billID;
+        node.type = consts.projectConst.BILLS;
+        node.ID=query.billID;
     }
+    resultObject.node = node;
     return detailList;
 }
 
 
-async function doRegexUpdate(datas) {
-    let resultObjec ={
-        err:null,
-        rList:[]
-    }
-    try {
-        let detailList = [];
-        let quantityResult ={
-            moduleName:'',
-            data:{
-                updateTpye:commonConsts.UT_UPDATE,
-                quantityRefresh:true
-            }
-        }
-        if(datas.query.hasOwnProperty('rationID')){
-            detailList = await quantity_detail_model.find({'projectID':datas.query.projectID,'rationID':datas.query.rationID}).sort('seq').exec();
-            quantityResult.moduleName = consts.projectConst.RATION;
-            quantityResult.data.rationID = datas.query.rationID;
-        }else {
-            detailList = await quantity_detail_model.find({'projectID':datas.query.projectID,'billID':datas.query.billID}).sort('seq').exec();
-            quantityResult.data.billID = datas.query.billID;
-            quantityResult.moduleName = consts.projectConst.BILLS;
-        }
-        let regex;
-        let result;
-        if(datas.doc.regex==null){
-            result=0
-            datas.doc.referenceIndexs=[];
-        }else {
-            regex = datas.doc.regex.toUpperCase();
-            let referenceIndexs = datas.doc.referenceIndexs;
-            result =getEvalResult(referenceIndexs,detailList,regex);
-        }
-        detailList[datas.query.index].result =result;
-        detailList[datas.query.index].regex=datas.doc.regex;
-        detailList[datas.query.index].referenceIndexs =datas.doc.referenceIndexs;
-        let updateTasks =[];
-        datas.doc.result=result;
-        updateTasks.push({
-            query:{
-                ID:datas.query.ID,
-                projectID:datas.query.projectID
-            },
-            doc:datas.doc
-        })
-        updateReferenceRecode(datas.query.index+1,detailList,updateTasks);
-        let updateEdit = await quantity_detail_model.bulkWrite(generateUpdateTaks(updateTasks));
-        resultObjec.rList.push(gernerateResultList(updateTasks));
-        if(datas.query.refreshQuantity==true){
-            quantityResult.data.quantity = await summateResuts(datas.query,detailList);
-            resultObjec.rList.push(quantityResult);
-        }
-        return resultObjec;
-    }catch (error){
-        console.log(error);
-        resultObjec.err=error;
-        return resultObjec
-
-    }
-}
-
-function gernerateResultList(updateTasks) {
-    let returndata ={
-        moduleName:consts.projectConst.QUANTITY_DETAIL,
-        data:{
-            updateTpye:commonConsts.UT_UPDATE,
-            refreshList:updateTasks
-        }
-    }
-    return returndata;
-
-}
-
-
-
 function updateReferenceRecode(index,detailList,updateTasks) {
     for(let d of detailList){
         if(_.includes(d.referenceIndexs,index)){
@@ -394,34 +329,52 @@ function updateReferenceRecode(index,detailList,updateTasks) {
 }
 
 
-async function summateResuts (query,detailList) {
+async function summateResults (query,detailList,decimal) {
     let quantity = 0;
+     decimal = decimal?decimal:await decimal_facade.getProjectDecimal(query.projectID);
     for(let d of detailList){
         if(d.isSummation==1){
-            let result = d.result==null||d.result==undefined?0:d.result
+            let result = d.result==null||d.result==undefined?0:d.result;
             quantity+=result;
         }
     }
-    quantity = quantity.toFixed(4);
     if(query.hasOwnProperty('rationID')){
+        let ration = await  ration_model.findOne({'ID':query.rationID,'projectID':query.projectID,deleteInfo: null});
+        quantity = getQuantityByUnit(quantity,ration.unit);
+        quantity = scMathUtil.roundTo(quantity, -decimal.ration.quantity);
         await ration_model.update({'ID':query.rationID,'projectID':query.projectID,deleteInfo: null},{quantity:quantity,isFromDetail:1});
     }else {
+        let bill = await bill_model.findOne({'ID':query.billID,'projectID':query.projectID,deleteInfo: null});
+        decimal = await decimal_facade.getBillsQuantityDecimal(query.projectID,bill.unit);
+        quantity = getQuantityByUnit(quantity,bill.unit);
+        quantity = scMathUtil.roundTo(quantity, -decimal);
         await bill_model.update({'ID':query.billID,'projectID':query.projectID,deleteInfo: null},{quantity:quantity,isFromDetail:1});
     }
     return quantity
 }
 
+function getQuantityByUnit(quantity,unit) {
+    if(unit){
+        let times = parseInt(unit);
+        if(isNaN(times)){
+            times = 1
+        }
+        quantity = quantity/times;
+    }
+    return quantity;
+}
 
 
-function  getEvalResult(referenceIndexs,detailList,regex) {
+ function  getEvalResult(referenceIndexs,detailList,regex,decimal={}) {
     try {
+        decimal = decimal.quantity_detail?decimal.quantity_detail:4;
         for(let i of referenceIndexs){
             regex = replaceReference(i,detailList,regex)
         }
         console.log('replace all C reference -----'+regex);
         regex =replaceSqr(regex);
         console.log('replace all sqar reference -----'+regex);
-        return scMathUtil.roundTo(eval(regex), -4);
+        return scMathUtil.roundTo(eval(regex), -decimal);
     }catch (error){
         console.log(error);
         throw new Error('输入的表达式有误,请重新输入!');
@@ -492,26 +445,6 @@ function converSqrByArr (sqararr,text) {
     return temp;
 };
 
-
-function updateRecored(query,doc,callback) {
-    quantity_detail_model.update(query,doc,(err,result)=>{
-        if(err){
-            callback(err,'');
-        }else {
-            let returndata ={
-                moduleName:consts.projectConst.QUANTITY_DETAIL,
-                data:{
-                    updateTpye:commonConsts.UT_UPDATE,
-                    query:query,
-                    doc:doc
-                }
-            }
-            callback(null,returndata);
-        }
-    })
-}
-
-
 function update_quantity_detail(user_id,datas) {
     if(datas.updateFunction){
         return updateFunctionMap[datas.updateFunction](user_id,datas);
@@ -520,57 +453,43 @@ function update_quantity_detail(user_id,datas) {
     }
 }
 
-function delete_quantity_detail(user_id,datas) {
-    return function (callback) {
-        doQuantityDelete(datas.doc).then(function (result) {
-            if(result.err){
-                callback(result.err,'')
-            }else {
-                callback(null,result.returndata)
-            }
-        });
-    }
-}
 
-async function doQuantityDelete(doc) {;
-    let result={
-        err:null
+async function deleteRecode(doc) {
+    let resultObject = {};
+    let decimal =await decimal_facade.getProjectDecimal(doc.projectID);
+
+    let query = {
+        projectID:doc.projectID,
+        seq : { $gt: doc.seq }
     }
-    try{
-        let query = {
-            projectID:doc.projectID,
-            seq : { $gt: doc.seq }
-        }
-        if(doc.hasOwnProperty('rationID')){
-            query.rationID = doc.rationID;
-        }else {
-            query.billID = doc.billID;
-        }
-        let quantity_detail_List = await getDatailList(doc,{data:{}});
-        let update_task = getUpdateReferenceTask(quantity_detail_List,doc.seq,-1);
-        await quantity_detail_model.update(query,{$inc:{seq:-1}},{multi: true});
-        if(update_task.length>0){
-            await quantity_detail_model.bulkWrite(generateUpdateTaks(update_task));
-        }
-        await quantity_detail_model.deleteOne({ID:doc.ID,projectID:doc.projectID});
-        let returndata ={
-            moduleName:consts.projectConst.QUANTITY_DETAIL,
-            data:{
-                doc:doc,
-                resort:true,
-                update_task:update_task,
-                updateTpye:commonConsts.UT_DELETE
-            }
-        };
-        result.returndata =returndata
-        return result;
-    }catch (error){
-        console.log(error)
-        result.err;
-        return result
+    if(doc.hasOwnProperty('rationID')){
+        query.rationID = doc.rationID;
+    }else {
+        query.billID = doc.billID;
     }
+    let quantity_detail_List = await getDatailList(doc,resultObject);
+    let update_task = getUpdateReferenceTask(quantity_detail_List,doc.seq,-1);
+    await quantity_detail_model.update(query,{$inc:{seq:-1}},{multi: true});
+    if(update_task.length>0){
+        await quantity_detail_model.bulkWrite(generateUpdateTaks(update_task));
+    }
+    await quantity_detail_model.deleteOne({ID:doc.ID,projectID:doc.projectID});
+    _.remove(quantity_detail_List,{ID:doc.ID,projectID:doc.projectID});
+
+    let n_data = {};//更新节点信息
+    n_data.quantity = await summateResults(query,quantity_detail_List,decimal);
+    n_data.isFromDetail = 1;
+    resultObject.node.data = n_data;
+
+    let r_data ={
+            doc:doc,
+            resort:true,
+            update_task:update_task,
+            updateTpye:commonConsts.UT_DELETE
+        };
+    resultObject.data = r_data;
 
-
+    return resultObject;
 }
 
 

+ 1 - 1
modules/main/models/bills.js

@@ -11,7 +11,7 @@ let counter = require("../../../public/counter/counter.js");
 let consts = require('./project_consts');
 let projectConsts = consts.projectConst;
 let commonConsts = consts.commonConst;
-let quantity_detial = require('../../ration_glj/facade/quantity_detail_facade');
+let quantity_detial = require('../facade/quantity_detail_facade');
 
 
 let billsSchema = new Schema({

+ 1 - 1
modules/main/models/project.js

@@ -7,7 +7,7 @@ var GLJData = require('./glj');
 var ration_glj_data = require('../../ration_glj/facade/ration_glj_facade');
 var ration_coe_data = require('../../ration_glj/facade/ration_coe_facade');
 var ration_ass_data = require('../../ration_glj/facade/ration_ass_facade');
-var quantity_detail_data = require('../../ration_glj/facade/quantity_detail_facade');
+var quantity_detail_data = require('../facade/quantity_detail_facade');
 var fee_rate_data = require('../../fee_rates/facade/fee_rates_facade');
 let projCounter = require('./proj_counter_model');
 let projSetting = require('./proj_setting_model');

+ 1 - 1
modules/main/models/ration.js

@@ -11,7 +11,7 @@ let counter = require("../../../public/counter/counter.js");
 let consts = require('./project_consts');
 let projectConsts = consts.projectConst;
 let commonConsts = consts.commonConst;
-let quantity_detial = require('../../ration_glj/facade/quantity_detail_facade');
+let quantity_detial = require('../facade/quantity_detail_facade');
 
 var rationAssItemSchema = mongoose.Schema({
     name: String,

+ 20 - 0
modules/main/routes/quantity_detail_route.js

@@ -0,0 +1,20 @@
+/**
+ * Created by zhang on 2017/11/24.
+ */
+
+let express = require('express');
+let qdController = require('../controllers/quantity_detail_controller');
+
+module.exports = function (app) {
+
+    var qdRouter = express.Router();
+
+
+    qdRouter.post('/save', qdController.save);
+    qdRouter.post('/update',qdController.update);
+    qdRouter.post('/updateRegex',qdController.updateRegex);
+    qdRouter.post('/insertRecode',qdController.insertRecode);
+    qdRouter.post('/deleteRecode',qdController.deleteRecode);
+    qdRouter.post('/swapRow',qdController.swapRow);
+    app.use('/quantity_detail',qdRouter);
+}

+ 1 - 1
modules/ration_glj/facade/ration_glj_facade.js

@@ -16,7 +16,7 @@ let ration_coe_facade = require('./ration_coe_facade');
 let ration_coe = mongoose.model('ration_coe');
 let std_ration_lib_ration_items = mongoose.model('std_ration_lib_ration_items');
 let glj_calculate_facade = require('./glj_calculate_facade');
-let quantity_detail_facade = require('./quantity_detail_facade');
+let quantity_detail_facade = require('../../main/facade/quantity_detail_facade');
 let logger = require("../../../logs/log_helper").logger;
 import stdgljutil  from "../../../public/cache/std_glj_type_util";
 import EngineeringLibModel from "../../users/models/engineering_lib_model";

+ 24 - 0
modules/reports/controllers/rpt_controller.js

@@ -222,6 +222,30 @@ module.exports = {
             }
         })
     },
+    getPDF:function (req, res) {
+        let prj_id = req.params.prj_id,
+            rpt_id = req.params.rpt_id,
+            pageSize = req.params.size,
+            rptName = req.params.rptName
+        ;
+        let user_id = req.session.sessionUser.ssoId;
+        getAllPagesCommon(user_id, prj_id, rpt_id, pageSize, JV.PAGING_OPTION_NORMAL, function(err, pageRst){
+            rpt_pdf_util.export_pdf_file(pageRst, pageSize, rptName,function (newName) {
+                res.setHeader('Content-Type', 'application/vnd.openxmlformats');
+                res.setHeader("Content-Disposition", "attachment; filename=" + strUtil.getPinYinCamelChars(rptName) + ".pdf");
+
+                let filestream = fs.createReadStream(__dirname.slice(0, __dirname.length - 28) + '/tmp/' + newName + '.pdf');
+                filestream.on('data', function(chunk) {
+                    res.write(chunk);
+                });
+                filestream.on('end', function() {
+                    res.end();
+                });
+            })
+
+        })
+
+    },
     getTestPDF:function (req, res) {
         let rpt_id = req.params.id,
             pageSize = req.params.size,

+ 1 - 1
modules/reports/routes/report_router.js

@@ -26,8 +26,8 @@ module.exports =function (app) {
     //now is the real:
     rptRouter.post('/getReport', reportController.getReportAllPages);
     rptRouter.get('/getExcel/:prj_id/:rpt_id/:size/:rptName/:isOneSheet/:option', reportController.getExcel);
+    rptRouter.get('/getPDF/:prj_id/:rpt_id/:size/:rptName', reportController.getPDF);
     // rptRouter.get('/getExcelInOneBook/:ids/:size/:rptName/:option', reportController.getExcelInOneBook);
-    // rptRouter.get('/getPDF/:id/:size/:rptName', reportController.getPDF);
 
     app.use("/report_api", rptRouter);
 };

+ 20 - 4
modules/reports/util/rpt_excel_util.js

@@ -425,7 +425,12 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
             stylesObj.fonts = [];
             //for (let i = 0; i < sheetData.font_collection)
         }
-        let sheetFont = pageData.font_collection[cell.font];
+        let sheetFont = null;
+        if (typeof cell[JV.PROP_FONT] === "string") {
+            sheetFont = pageData[JV.NODE_FONT_COLLECTION][cell[JV.PROP_FONT]];
+        } else {
+            sheetFont = cell[JV.PROP_FONT];
+        }
         for (let i = 0; i < stylesObj.fonts.length; i++) {
             let font = stylesObj.fonts[i];
             if (sheetFont) {
@@ -582,12 +587,23 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj){
         let rst = 1, hasStyle = false;
         if (!(stylesObj.cellXfs)) stylesObj.cellXfs = [];
         let fontId = private_getFontId(cell);
-        let fontAngle = parseInt(pageData.font_collection[cell.font].FontAngle);
+        let fontAngle = 0;
+        if (typeof cell[JV.PROP_FONT] === "string") {
+            fontAngle = parseInt(pageData[JV.NODE_FONT_COLLECTION][cell[JV.PROP_FONT]].FontAngle);
+        } else {
+            fontAngle = parseInt(cell[JV.PROP_FONT].FontAngle);
+        }
+
         let borderId = private_getBorderId(cell);
-        let cellControl = pageData[JV.NODE_CONTROL_COLLECTION][cell[JV.PROP_CONTROL]];
+        let cellControl = null;
+        if (typeof cell[JV.PROP_CONTROL] === "string") {
+            cellControl = pageData[JV.NODE_CONTROL_COLLECTION][cell[JV.PROP_CONTROL]];
+        } else {
+            cellControl = cell[JV.PROP_CONTROL];
+        }
         for (let i = 0; i < stylesObj.cellXfs.length; i++) {
             let sheetControl = stylesObj.cellXfs[i];
-            if (sheetControl.fontId == fontId && sheetControl.borderId == borderId) {
+            if (sheetControl.fontId === fontId && sheetControl.borderId === borderId) {
                 if (private_checkControl(cellControl, sheetControl)) {
                     rst = i;
                     hasStyle = true;

+ 82 - 46
modules/reports/util/rpt_pdf_util.js

@@ -6,8 +6,8 @@
  */
 
 const prf_cons = require('./pdf_base_files/rpt_pdf_consts');
-var pdf = require('pdfkit');
-var fs = require('fs');
+let pdf = require('pdfkit');
+let fs = require('fs');
 let jpcCmnHelper = require('../rpt_component/helper/jpc_helper_common');
 let DPI = jpcCmnHelper.getScreenDPI()[0];
 //let JV = prf_cons.JV;
@@ -21,7 +21,7 @@ module.exports ={
 function export_pdf_file (pageData, paperSize, fName, callback) {
     let offsetX= 10;
     let offsetY=10;
-    var doc = new pdf({autoFirstPage: false});
+    let doc = new pdf({autoFirstPage: false});
     let newName = '' + (new Date()).valueOf();
     let stream = doc.pipe(fs.createWriteStream(__dirname.slice(0, __dirname.length - 21) + '/tmp/'+newName+'.pdf'));
     let pageObj = pageData;
@@ -29,18 +29,34 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
     let paperSizeIdx = JV.PAGES_SIZE_STR.indexOf(paperSize);
     let size = JV.PAGES_SIZE[paperSizeIdx];
 
+    function private_getIniPageMergeBorder(mergedBand) {
+        let rst = {};
+        rst[JV.PROP_LEFT] = mergedBand[JV.PROP_LEFT];
+        rst[JV.PROP_RIGHT] = mergedBand[JV.PROP_RIGHT];
+        rst[JV.PROP_TOP] = mergedBand[JV.PROP_TOP];
+        rst[JV.PROP_BOTTOM] = mergedBand[JV.PROP_BOTTOM];
+        rst[JV.PROP_STYLE] = mergedBand[JV.PROP_STYLE];
+        return rst;
+    }
+
+    let newPageMergeBand = private_getIniPageMergeBorder(pageObj[JV.BAND_PROP_MERGE_BAND]);
     if (pageObj && pageObj.items.length > 0 ) {
         for(let i=0;i<pageObj.items.length;i++){
             doc.addPage({size:[size[1]*DPI,size[0]*DPI]});
-            var page = pageObj.items[i],
+            let page = pageObj.items[i],
                 fonts = pageObj[JV.NODE_FONT_COLLECTION],
                 styles = pageObj[JV.NODE_STYLE_COLLECTION],
-                controls = pageObj[JV.NODE_CONTROL_COLLECTION],
-                mergedBand = pageObj[JV.BAND_PROP_MERGE_BAND];
+                controls = pageObj[JV.NODE_CONTROL_COLLECTION];
 
-            for (var j = 0; j < page.cells.length; j++) {
-                var cell = page.cells[j];
-                private_drawCell(cell, fonts, styles, controls, mergedBand);
+            if (page[JV.PROP_PAGE_MERGE_BORDER]) {
+                newPageMergeBand[JV.PROP_LEFT] = page[JV.PROP_PAGE_MERGE_BORDER][JV.PROP_LEFT];
+                newPageMergeBand[JV.PROP_RIGHT] = page[JV.PROP_PAGE_MERGE_BORDER][JV.PROP_RIGHT];
+                newPageMergeBand[JV.PROP_TOP] = page[JV.PROP_PAGE_MERGE_BORDER][JV.PROP_TOP];
+                newPageMergeBand[JV.PROP_BOTTOM] = page[JV.PROP_PAGE_MERGE_BORDER][JV.PROP_BOTTOM];
+            }
+            for (let j = 0; j < page.cells.length; j++) {
+                let cell = page.cells[j];
+                private_drawCell(cell, fonts, styles, controls, newPageMergeBand);
             }
         }
     }
@@ -48,34 +64,43 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
     stream.on('finish',function () {
         console.log(newName + ".pdf was written.");
         callback(newName);
-    })
+    });
 
+    function private_chkIfInMergedBand(mergedBand, cell) {
+        let rst = false;
+        if (mergedBand && cell) {
+            rst = mergedBand[JV.PROP_TOP] <= cell[JV.PROP_AREA][JV.PROP_TOP] && mergedBand[JV.PROP_BOTTOM] >= cell[JV.PROP_AREA][JV.PROP_BOTTOM] &&
+                mergedBand[JV.PROP_LEFT] <= cell[JV.PROP_AREA][JV.PROP_LEFT] && mergedBand[JV.PROP_RIGHT] >= cell[JV.PROP_AREA][JV.PROP_RIGHT];
+        }
+        return rst;
+    }
 
     function private_drawCell(cell, fonts, styles, controls, mergedBand) {
         doc.save();
         //doc.translate(0.5,0.5);
-        var style = styles[cell[JV.PROP_STYLE]];
+        let style = styles[cell[JV.PROP_STYLE]];
         if (style) {
-            private_drawLine(cell, doc, style, JV.PROP_TOP, [JV.PROP_LEFT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_TOP], mergedBand, styles);
-            private_drawLine(cell, doc, style, JV.PROP_RIGHT, [JV.PROP_RIGHT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_BOTTOM], mergedBand, styles);
-            private_drawLine(cell, doc, style, JV.PROP_BOTTOM, [JV.PROP_RIGHT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_BOTTOM], mergedBand, styles);
-            private_drawLine(cell, doc, style, JV.PROP_LEFT, [JV.PROP_LEFT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_TOP], mergedBand, styles);
+            let isNeedMergeBand = private_chkIfInMergedBand(mergedBand, cell);
+            private_drawLine(cell, doc, style, JV.PROP_TOP, [JV.PROP_LEFT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_TOP], mergedBand, styles, isNeedMergeBand);
+            private_drawLine(cell, doc, style, JV.PROP_RIGHT, [JV.PROP_RIGHT, JV.PROP_TOP],[JV.PROP_RIGHT, JV.PROP_BOTTOM], mergedBand, styles, isNeedMergeBand);
+            private_drawLine(cell, doc, style, JV.PROP_BOTTOM, [JV.PROP_RIGHT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_BOTTOM], mergedBand, styles, isNeedMergeBand);
+            private_drawLine(cell, doc, style, JV.PROP_LEFT, [JV.PROP_LEFT, JV.PROP_BOTTOM],[JV.PROP_LEFT, JV.PROP_TOP], mergedBand, styles, isNeedMergeBand);
         }
         private_drawCellText(cell, fonts, controls);
         doc.restore();
 
     }
 
-    function private_drawLine(cell, doc, style, styleBorderDest, startP, destP, mergedBand, styles) {
+    function private_drawLine(cell, doc, style, styleBorderDest, startP, destP, mergedBand, styles, isNeedMergeBand) {
         //doc.beginPath();
-        var destStyle = style;
+        let destStyle = style;
         if (mergedBand) {
-            if (mergedBand[styleBorderDest] == cell[JV.PROP_AREA][styleBorderDest]) {
+            if (isNeedMergeBand && parseFloat(mergedBand[styleBorderDest]) === parseFloat(cell[JV.PROP_AREA][styleBorderDest])) {
                 destStyle = styles[mergedBand[JV.PROP_STYLE][JV.PROP_ID]];
             }
         }
         doc.moveTo(cell[JV.PROP_AREA][startP[0]] + offsetX, cell[JV.PROP_AREA][startP[1]] + offsetY);
-        if (destStyle[styleBorderDest] && destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT] != 0) {
+        if (destStyle[styleBorderDest] && parseFloat(destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT]) !== 0) {
             doc.lineWidth(1.0 * destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT]);
             doc.lineTo(cell[JV.PROP_AREA][destP[0]] + offsetX, cell[JV.PROP_AREA][destP[1]] + offsetY);
             doc.strokeColor(destStyle[styleBorderDest][JV.PROP_COLOR]);
@@ -84,12 +109,24 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
     }
     function private_drawCellText(cell, fonts, controls) {
         if (cell[JV.PROP_VALUE]) {
-            var values = ("" + cell[JV.PROP_VALUE]).split('|');
-            var font = fonts[cell[JV.PROP_FONT]];
-            var control = controls[cell[JV.PROP_CONTROL]];
-            var height = cell[JV.PROP_AREA][JV.PROP_BOTTOM] - cell[JV.PROP_AREA][JV.PROP_TOP];
-            var area = [cell[JV.PROP_AREA][JV.PROP_LEFT] + offsetX, cell[JV.PROP_AREA][JV.PROP_TOP] + offsetY, cell[JV.PROP_AREA][JV.PROP_RIGHT] + offsetX, cell[JV.PROP_AREA][JV.PROP_BOTTOM] + offsetY];
-            for (var i = 0; i < values.length; i++) {
+            let values = ("" + cell[JV.PROP_VALUE]).split('|');
+            // let font = fonts[cell[JV.PROP_FONT]];
+            let font = null;
+            if (typeof cell[JV.PROP_FONT] === "string") {
+                font = fonts[cell[JV.PROP_FONT]];
+            } else {
+                font = cell[JV.PROP_FONT];
+            }
+            // let control = controls[cell[JV.PROP_CONTROL]];
+            let control = null;
+            if (typeof cell[JV.PROP_CONTROL] === "string") {
+                control = controls[cell[JV.PROP_CONTROL]];
+            } else {
+                control = cell[JV.PROP_CONTROL];
+            }
+            let height = cell[JV.PROP_AREA][JV.PROP_BOTTOM] - cell[JV.PROP_AREA][JV.PROP_TOP];
+            let area = [cell[JV.PROP_AREA][JV.PROP_LEFT] + offsetX, cell[JV.PROP_AREA][JV.PROP_TOP] + offsetY, cell[JV.PROP_AREA][JV.PROP_RIGHT] + offsetX, cell[JV.PROP_AREA][JV.PROP_BOTTOM] + offsetY];
+            for (let i = 0; i < values.length; i++) {
                 area[JV.IDX_TOP] = cell[JV.PROP_AREA][JV.PROP_TOP] + i * (height / values.length) + offsetY;
                 area[JV.IDX_BOTTOM] = cell[JV.PROP_AREA][JV.PROP_TOP] + (i + 1) * (height / values.length) + offsetY;
                 private_drawText(values[i], area, font, control);
@@ -98,22 +135,22 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
     }
 
     function private_drawText(val, area, font, control) {
-        var dftFontHeight = 12;
-        var output = [];
+        let dftFontHeight = 12;
+        let output = [];
         if (font) {
             dftFontHeight = 1 * font[JV.FONT_PROPS[1]];
-            var dftFontBold = font[JV.FONT_PROPS[3]];
-            var dftFontItalic = font[JV.FONT_PROPS[4]];
-            if (dftFontBold && dftFontBold == 'T') {
+            let dftFontBold = font[JV.FONT_PROPS[3]];
+            let dftFontItalic = font[JV.FONT_PROPS[4]];
+            if (dftFontBold && dftFontBold === 'T') {
                 doc.font(__dirname+'/pdf_base_files/hwxsb.ttf');
-            }else if(dftFontItalic && dftFontItalic == 'T'){
+            }else if(dftFontItalic && dftFontItalic === 'T'){
                 doc.font(__dirname+'/pdf_base_files/Smart-italic.ttf');
             }else {
                 doc.font(__dirname+'/pdf_base_files/Smart.ttf');
             }
             doc.fontSize(dftFontHeight);
         }
-        var options={};
+        let options={};
         if (control) {
             private_setupAreaH(area, control.Horizon, font.FontAngle, dftFontHeight, output,options);
             private_setupAreaV(area, control.Vertical, font.FontAngle, dftFontHeight, output);
@@ -121,8 +158,8 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
             private_setupAreaH(area, "left", font.FontAngle, dftFontHeight, output,options);
             private_setupAreaV(area, "bottom", font.FontAngle, dftFontHeight, output);
         }
-        var w = area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - area[JV.IDX_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
-        if (font.FontAngle != "0") {
+        let w = area[JV.IDX_RIGHT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT] - area[JV.IDX_LEFT] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_RIGHT];
+        if (parseInt(font.FontAngle) !== 0) {
             w = area[JV.IDX_BOTTOM] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] - area[JV.IDX_TOP] - JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
         }
         doc.save();
@@ -142,8 +179,8 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
             }
         }
 
-        var rotateOptions;
-        if (font.FontAngle != "0") {
+        let rotateOptions;
+        if (parseInt(font.FontAngle) !== 0) {
             if (control){
                 rotateOptions=private_setupAreaRotateOption(area,w,control.Vertical,dftFontHeight, output);
             }else {
@@ -156,15 +193,15 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
     }
 
     function private_setupAreaH(area, type, fontAngle, dftFontHeight, outputPoint,options) {
-        var lType = type;
-        if (type != "left" && type != "right" && type != "center") lType = "left";
+        let lType = type;
+        if (type !== "left" && type !== "right" && type !== "center") lType = "left";
         options.align=lType;
         outputPoint[0]=1 * area[JV.IDX_LEFT]+ JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
     }
 
     function private_setupAreaV(area, type, fontAngle, dftFontHeight, outputPoint) {
-        var lType = type;
-        if (type != "top" && type != "bottom" && type != "center") lType = "top";
+        let lType = type;
+        if (type !== "top" && type !== "bottom" && type !== "center") lType = "top";
         switch (lType) {
             case "top":
                 outputPoint[1] = 1 * area[JV.IDX_TOP] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
@@ -179,13 +216,12 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
     }
 
     function private_setupAreaRotateOption(area,w, type="top",dftFontHeight,outputPoint){
-        var x = (area[JV.IDX_RIGHT] - area[JV.IDX_LEFT])/2+area[JV.IDX_LEFT];
-        var y =(area[JV.IDX_BOTTOM] - area[JV.IDX_TOP])/2+ area[JV.IDX_TOP];
-        var rotateOptions = {origin:[x,y]};
-        var h = area[JV.IDX_RIGHT] - area[JV.IDX_LEFT];
+        let x = (area[JV.IDX_RIGHT] - area[JV.IDX_LEFT])/2+area[JV.IDX_LEFT];
+        let y =(area[JV.IDX_BOTTOM] - area[JV.IDX_TOP])/2+ area[JV.IDX_TOP];
+        let rotateOptions = {origin:[x,y]};
+        let h = area[JV.IDX_RIGHT] - area[JV.IDX_LEFT];
         outputPoint[0]=x-w/2+JV.OUTPUT_OFFSET[JV.OFFSET_IDX_LEFT];
-        var lType = type;
-        switch (lType) {
+        switch (type) {
             case "top":
                 outputPoint[1] = y- h/2+ JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP];
                 break;

+ 31 - 24
web/building_saas/glj/js/project_glj.js

@@ -22,6 +22,7 @@ let mixRatioConnectData = [];
 let mixRatioMap={};
 // 单价文件相关
 let usedUnitPriceInfo = {};
+let usedTenderList = [];
 let otherFileData = {};
 let currentTag = '';
 let isChanging = false;
@@ -162,12 +163,15 @@ $(document).ready(function () {
             // 从其他项目中复制
             changeUnitPriceId = $("#other-file").val();
         }
+        $('#change-dj').modal("hide");
+        $.bootstrapLoading.start();
         $.ajax({
             url: '/glj/change-file',
             type: 'post',
             data: {project_id: scUrlUtil.GetQueryString('project'), change_id: changeUnitPriceId, type: type},
             error: function() {
                 isChanging = false;
+                $.bootstrapLoading.end();
             },
             beforeSend: function() {
                 isChanging = true;
@@ -177,20 +181,16 @@ $(document).ready(function () {
                 if (response.err === 1) {
                     let msg = response.msg !== undefined ? response.msg : '未知错误';
                     alert(msg);
+                    $.bootstrapLoading.end();
                     return false;
                 }
                 projectObj.project.projectGLJ.loadData(function () {
                     let projectGLJ = projectObj.project.projectGLJ;
-                    let data = projectGLJ.datas;
                     projectGLJ.loadCacheData();
-                    let usedTenderList = data.usedTenderList !== undefined ? data.usedTenderList : [];
-                    let  usedUnitPriceInfo = data.constData.usedUnitPriceInfo !== undefined ?
-                        data.constData.usedUnitPriceInfo : {};
-
-                    unitPriceFileInit(usedUnitPriceInfo.name, usedTenderList);
-
+                    unitPriceFileInit();
+                    gljOprObj.refreshView();
+                    $.bootstrapLoading.end();
                 });
-                $('#change-dj').modal("hide");
             }
         });
     });
@@ -204,6 +204,14 @@ $(document).ready(function () {
             $("#notify").slideUp('fast');
         });
     });
+
+    $('#pop-dj').popover({
+            placement:"bottom",
+            html:true,
+            trigger:"hover | focus",
+            content: getUsedTenderInfo
+        }
+    );
 });
 
 /**
@@ -226,14 +234,10 @@ function init() {
                 data.constData.ownCompositionTypes : canNotChangeTypeId;
             GLJTypeConst = data.constData.GLJTypeConst !== undefined ? JSON.parse(data.constData.GLJTypeConst) : GLJTypeConst;
 
-            let usedTenderList = data.usedTenderList !== undefined ? data.usedTenderList : [];
-            usedUnitPriceInfo = data.constData.usedUnitPriceInfo !== undefined ?
-                data.constData.usedUnitPriceInfo : {};
-
             // 连接socket服务器
             socketInit();
 
-            unitPriceFileInit(usedUnitPriceInfo.name, usedTenderList);
+            unitPriceFileInit();
 
             setTimeout(spreadInit, 1);
         } else {
@@ -290,17 +294,19 @@ function spreadInit() {
  * @param {Array} data
  * @return {void}
  */
-function unitPriceFileInit(name, data) {
-    $("#used-name").text(name);
-    let usedCount = data.length <= 0 ? 1 : data.length;
+function unitPriceFileInit() {
+    let projectGLJ = projectObj.project.projectGLJ;
+    let data = projectGLJ.datas;
+     usedTenderList = data.usedTenderList !== undefined ? data.usedTenderList : [];
+    usedUnitPriceInfo = data.constData.usedUnitPriceInfo !== undefined ?
+        data.constData.usedUnitPriceInfo : {};
+    $("#used-name").text(usedUnitPriceInfo.name);
+    let usedCount = usedTenderList.length <= 0 ? 1 : usedTenderList.length;
     $("#used-count").text(usedCount);
-    $('#pop-dj').popover({
-            placement:"bottom",
-            html:true,
-            trigger:"hover | focus",
-            content: data.join('<br>')
-        }
-    );
+}
+
+function getUsedTenderInfo() {
+   return usedTenderList.join("<br>");
 }
 
 /**
@@ -371,4 +377,5 @@ function filterProjectGLJ(jsonData) {
         jsonData = tmpData;
     }
     return jsonData;
-}
+}
+

BIN
web/building_saas/img/FirstPageSimple.cur


BIN
web/building_saas/img/LastPageSimple.cur


BIN
web/building_saas/img/NextPageSimple.cur


BIN
web/building_saas/img/PreviousPageSimple.cur


+ 1 - 1
web/building_saas/main/js/calc/calc_fees.js

@@ -70,7 +70,7 @@ let calcFees = {
     getFee: function (data, fullField) {
         let fields = fullField.split('.'), value = data;
         for (let field of fields) {
-            if (value[field]) {
+            if (value[field]!=undefined||value[field]!=null) {
                 value = value[field];
             } else {
                 return 0;

+ 18 - 8
web/building_saas/main/js/models/calc_program.js

@@ -8,7 +8,7 @@
 
 let defaultBillTemplate = {
     ID: 15,
-    name: "清单缺省",
+    name: "清单公式",
     calcItems: [
         {
             ID: 1,
@@ -336,8 +336,10 @@ let executeObj = {
     },
     HJ: function () {
         let me = this;
-        let rst = me.treeNode.data.marketUnitFee ? me.treeNode.data.marketUnitFee : 0;
-        return rst;
+        let p = me.treeNode.data.calcBase ? me.treeNode.data.calcBase : 0;
+        let q = me.treeNode.data.quantity ? me.treeNode.data.quantity : 1;
+        let u = (p / q).toDecimal(me.digit);
+        return u;
     }
 };
 
@@ -622,10 +624,16 @@ class CalcProgram {
                 };
             }
             else if (treeNode.calcType == treeNodeCalcType.ctRationCalcProgram) {
-                let muf = treeNode.data.marketUnitFee ? treeNode.data.marketUnitFee : 0;
-                let q = treeNode.data.quantity ? treeNode.data.quantity : 0;
-                treeNode.data.marketTotalFee = (muf * q).toDecimal(me.digit);
-                treeNode.data.gljList = me.project.ration_glj.getGljArrByRation(treeNode.data.ID);
+                if (treeNode.sourceType === me.project.Ration.getSourceType()){
+                    treeNode.data.gljList = me.project.ration_glj.getGljArrByRation(treeNode.data.ID);
+                }
+                else if (treeNode.sourceType === me.project.VolumePrice.getSourceType()){
+                    delete treeNode.data.gljList;
+                    let muf = treeNode.data.marketUnitFee ? treeNode.data.marketUnitFee : 0;
+                    let q = treeNode.data.quantity ? treeNode.data.quantity : 0;
+                    treeNode.data.marketTotalFee = (muf * q).toDecimal(me.digit);
+                };
+
                 if (treeNode.data.programID == undefined){
                     treeNode.data.programID = projectInfoObj.projectInfo.property.engineering;
                 };
@@ -732,10 +740,12 @@ class CalcProgram {
                     projectID: me.project.ID(),
                     type: node.data.type,
                     quantity: node.data.quantity,
+                    calcBase: node.data.calcBase,
                     programID: node.data.programID,
                     marketUnitFee: node.data.marketUnitFee,
                     marketTotalFee: node.data.marketTotalFee,
-                    fees: node.data.fees
+                    fees: node.data.fees,
+                    isFromDetail:node.data.isFromDetail
                 };
                 let newData = {'updateType': 'ut_update', 'updateData': data};
                 me.project.push(node.sourceType, [newData]);

+ 84 - 62
web/building_saas/main/js/models/quantity_detail.js

@@ -48,13 +48,10 @@ var quantity_detail = {
                 _.forEach(data.update_task,function (item) {
                     me.refreshEachItme(item.query,item.doc);
                 })
-                gljOprObj.detailData.push(data.doc);
                 this.datas.push(data.doc);
             }else {
                 this.datas.push(data);
-                gljOprObj.detailData.push(data);
             }
-            gljOprObj.detailData=_.sortBy(gljOprObj.detailData,'seq');
             this.refreshSheetData();
         };
         quantity_detail.prototype.resortData=function(data,req){
@@ -106,28 +103,13 @@ var quantity_detail = {
                 me.refreshEachItme(item.query,item.doc);
             });
             _.remove(this.datas,{ID:data.doc.ID});
-            _.remove(gljOprObj.detailData,{ID:data.doc.ID});
             this.refreshSheetData();
         };
         quantity_detail.prototype.refreshSheetData=function () {
-            sheetCommonObj.showData(gljOprObj.detailSheet,gljOprObj.detailSetting,gljOprObj.detailData);
-        };
-        quantity_detail.prototype.getUpdateData=function(type,query,doc,callfunction){
-            var updateData = [];
-            var newobj = {
-                'updateType': type,
-                'query': query,
-            }
-            if(doc){
-                newobj['doc']=doc;
-            }
-            if(callfunction){
-                newobj['updateFunction']=callfunction;
-            }
-            updateData.push(newobj);
-            return updateData;
+            gljOprObj.showQuantityDetailData();
         };
         quantity_detail.prototype.saveQuantityDetail=function (args,dataCode) {
+            var me = this;
             var doc={};
             var selected = projectObj.project.mainTree.selected;
             if(selected.sourceType==ModuleNames.ration){
@@ -152,13 +134,25 @@ var quantity_detail = {
                 }
 
             }
-            var updateData
-            if(args.hasOwnProperty("insertRecode")){
-                updateData = this.getUpdateData('ut_update',null,doc,'insertRecode');
+            var url="";
+            $.bootstrapLoading.start();
+            if(args.hasOwnProperty("insertRecode")){//右键插入或者是通过直接编辑保存
+                url = "/quantity_detail/insertRecode";
             }else{
-                updateData = this.getUpdateData('ut_create',null,doc);
+                url = "/quantity_detail/save";
+            }
+            var callback = function (data) {
+                if(doc.refreshQuantity==false){//清空数据
+                    me.cleanQuantityDetail();
+                }else {
+                    data.newRecord?me.refreshAfterSave(data.newRecord):me.refreshAfterSave(data);
+                    data.node?gljOprObj.refreshTreeNode(data.node):"";
+                }
+                $.bootstrapLoading.end();
             }
-            project.pushNow('saveQuantityDetail',[this.getSourceType()],updateData);
+            CommonAjax.post(url,doc,callback,function () {
+                $.bootstrapLoading.end();
+            });
         };
         quantity_detail.prototype.insertQuantityDetail = function (row) {
             var args = {
@@ -169,20 +163,27 @@ var quantity_detail = {
                 args.insertRecode = true;
             }
             this.saveQuantityDetail(args,'isSummation');
-
         };
 
         quantity_detail.prototype.deleteQuantityDetail = function (row) {
+           var me = this;
            var deleteable = this.checkReference(row);
            if(deleteable){
                var recode = gljOprObj.detailData[row];
-               var updateData = this.getUpdateData('ut_delete',null,recode);
-               project.pushNow('deleteQuantityDetail',[this.getSourceType()],updateData);
+               $.bootstrapLoading.start();
+               var callback=function (result) {
+                   me.refreshAfterDelete(result.data);
+                   result.node?gljOprObj.refreshTreeNode(result.node):"";
+                   $.bootstrapLoading.end();
+               }
+               CommonAjax.post("/quantity_detail/deleteRecode",recode,callback,function () {
+                   $.bootstrapLoading.end();
+               });
            }else {
                alert("当前行已被引用,不可删除。");
            }
-
         };
+
         quantity_detail.prototype.checkReference = function (row) {
             var deleteable = true;
            for(var i =0;i<gljOprObj.detailData.length;i++){
@@ -231,13 +232,7 @@ var quantity_detail = {
                     update_task.push({query:{ID:item.ID,projectID:item.projectID},doc:{regex:regex,referenceIndexs:item.referenceIndexs}});
                 }
             })
-
-            var updateData=[];
-            update_task.forEach(function (task) {
-                updateData.push({'updateType': 'ut_update', 'query': task.query,'doc':task.doc});
-            })
-            project.pushNow('updateQuantityDetail',[this.getSourceType()],[updateData]);
-
+            me.commonUpdate("/quantity_detail/swapRow",update_task);
         };
         quantity_detail.prototype.replaceAll=function(FindText, RepText,str) {
             let regExp = new RegExp(FindText, "g");
@@ -281,8 +276,7 @@ var quantity_detail = {
                 }
             }
             if(needupdate){
-                var updateData = this.getUpdateData('ut_update',query,doc,'updateQuantityRegex');
-                project.pushNow('updateQuantityDetail',[this.getSourceType()],updateData);
+                this.commonUpdate("/quantity_detail/updateRegex",{query:query,doc:doc});
             }else {
                 var sheet = subSpread.getActiveSheet();
                 sheet.getCell(args.row,args.col).value(gljOprObj.detailData[args.row].regex);
@@ -312,9 +306,21 @@ var quantity_detail = {
             };
             this.normalUpdate(query,doc);
         };
+        quantity_detail.prototype.commonUpdate = function (url,postData) {
+            var me = this;
+            $.bootstrapLoading.start();
+            var callback = function (data) {
+                me.refreshAfterUpdate(data);
+                data.node?gljOprObj.refreshTreeNode(data.node):"";
+                $.bootstrapLoading.end();
+            }
+            CommonAjax.post(url,postData,callback,function () {
+                $.bootstrapLoading.end();
+            });
+        };
         quantity_detail.prototype.normalUpdate=function(query,doc){
-            var updateData = this.getUpdateData('ut_update',query,doc);
-            project.pushNow('updateQuantityDetail',[this.getSourceType()],updateData);
+            var url = "/quantity_detail/update";
+            this.commonUpdate(url,{query:query,doc:doc});
         };
         quantity_detail.prototype.regexChecking=function(text){
             var regex=/^[0-9Cc\+\-\*\^/\(\)\.]*$/g;
@@ -447,32 +453,48 @@ var quantity_detail = {
                 this.datas = newList;
             }
         };
+        quantity_detail.prototype.cleanQuantityDetail = function (node,needSave) {
+           node =node?node:projectObj.project.mainTree.selected;
+           var query={projectID:node.data.projectID};
+            if(node.sourceType === project.Bills.getSourceType()){
+                query.billID = node.data.ID;
+                this.deleteByBills([{type:'delete',data:node.data}]);
+            }else if(node.sourceType === project.Ration.getSourceType()){
+                this.deleteByRation(node.data);
+                query.rationID = node.data.ID;
+            }
+            if(needSave===true){
+                query.refreshQuantity=false;
+                CommonAjax.post("/quantity_detail/save",query);
+            }
+            gljOprObj.detailData=[];
+            sheetCommonObj.showData(gljOprObj.detailSheet,gljOprObj.detailSetting,[]);
+
+        };
+
         quantity_detail.prototype.quantityEditChecking = function(value,node,fieldName){
             var validate = true;
-            if (value && value != calcFees.getFee(node.data, fieldName)){
-                if(fieldName=='quantity'){
-                   if(node.data.hasOwnProperty('isFromDetail')&&node.data.isFromDetail==1){
-                       var c = confirm('已有工程量明细,是否清空明细表,采用手工输入的表达式?')
-                        if(c){
-                            node.data.isFromDetail=0;
-                            if(node.sourceType === project.Bills.getSourceType()){
-                                this.deleteByBills([{type:'delete',data:node.data}]);
-                            }else if(node.sourceType === project.Ration.getSourceType()){
-                                this.deleteByRation(node.data);
-                            }
-                            gljOprObj.detailData=[];
-                            sheetCommonObj.showData(gljOprObj.detailSheet,gljOprObj.detailSetting,[]);
-
-                            validate = true;
-                        }else {
-                            validate = false;
-                        }
-                   }
-                }
+            if(fieldName=='quantity'){
+               if(node.data.hasOwnProperty('isFromDetail')&&node.data.isFromDetail==1){
+                   var c = confirm('已有工程量明细,是否清空明细表,采用手工输入的表达式?')
+                    if(c){
+                        validate = true;
+                    }else {
+                        validate = false;
+                    }
+               }
             }
             return validate;
-
-        }
+        };
+        quantity_detail.prototype.getDecimal=function (node) {
+            var decimal = 3;
+            if(node.sourceType === project.Bills.getSourceType()){
+                decimal = billsQuanDecimal.decimal(node.data.unit);
+            }else {
+                decimal = decimalObj.ration.quantity
+            }
+            return;
+        };
         return new quantity_detail(project);
     }
 

+ 28 - 0
web/building_saas/main/js/views/glj_view.js

@@ -671,6 +671,7 @@ var gljOprObj = {
     },
     showQuantityDetailData:function (node) {
         var details=[];
+        node =node?node:projectObj.project.mainTree.selected;
         var quantity_detail =projectObj.project.quantity_detail;
         if(node.sourceType==ModuleNames.ration){
             details=_.filter(quantity_detail.datas,{'rationID':node.data.ID});
@@ -996,6 +997,33 @@ var gljOprObj = {
     refreshView:function () {
         this.showRationGLJData();
     },
+    //
+    refreshTreeNode:function (obj) {
+    if(!obj){
+        return;
+    }
+    var objectArray =[];
+    var nodes =[];
+    if(obj instanceof Array){
+        objectArray.concat(obj);
+    }else {
+        objectArray.push(obj);
+    }
+    for(let o of objectArray ){
+        var node = _.find(projectObj.project.mainTree.items,function (n) {
+            return n.sourceType==o.type&&n.data.ID==o.ID;
+        })
+        if(node){
+            for (var k in o.data){
+                node.data[k] = o.data[k];
+            }
+            nodes.push(node);
+        }
+    }
+
+    projectObj.mainController.refreshTreeNode(nodes);
+
+    },
     getTreeNodeCellType:function (data) {
         var ns = GC.Spread.Sheets;
         var rectW = 10;

+ 4 - 1
web/building_saas/main/js/views/main_tree_col.js

@@ -20,6 +20,7 @@ let MainTreeCol = {
             }
         },
 
+        // CSL, 2017-11-28
         calcProgramName: function (node) {
             let programID = node.data.programID;
             if (!programID) return
@@ -30,7 +31,7 @@ let MainTreeCol = {
         type: function (node){
             return node.sourceType !== projectObj.project.VolumePrice.getSourceType();
         },
-
+        // CSL, 2017-11-28
         calcProgramName: function (node) {
             if (
                 node.sourceType === projectObj.project.VolumePrice.getSourceType() ||
@@ -94,6 +95,7 @@ let MainTreeCol = {
             return feeRateObject.getFeeRateEditCellType();
         },
 
+        // CSL, 2017-11-28
         calcProgramName: function (node) {
             if (
                 node.sourceType === projectObj.project.VolumePrice.getSourceType() ||
@@ -106,6 +108,7 @@ let MainTreeCol = {
             }
         },
 
+        // CSL, 2017-11-28
         type: function (node) {
             if (node.sourceType === projectObj.project.VolumePrice.getSourceType()) {
                 let VPType = new GC.Spread.Sheets.CellTypes.ComboBox();

+ 13 - 4
web/building_saas/main/js/views/project_view.js

@@ -108,7 +108,7 @@ var projectObj = {
                 value = null;
             }
         }
-        if (value) {
+        if (value!=undefined||value!=null) {
             if (colSetting.data.decimal) {
                 value = value.toDecimal(colSetting.data.decimal);   
             }
@@ -267,11 +267,20 @@ var projectObj = {
             else if(fieldName ==='feeRate'){
                 project.FeeRate.updateFeeRateFromBills(value,node,fieldName);
             }
-            else if (fieldName === 'quantity' || fieldName === 'marketUnitFee' || fieldName === 'programID' || fieldName === 'type'){
-                if (fieldName === 'quantity' && project.quantity_detail.quantityEditChecking(value,node,fieldName)) {
-                    if (value) {value = value.toDecimal(projectObj.project.Decimal.common.quantity)};
+            else if (fieldName === 'quantity' || fieldName === 'marketUnitFee' || fieldName === 'programID' || fieldName === 'type' || fieldName === 'calcBase'){
+                if (fieldName === 'quantity') {
+                    if (value) {value = value.toDecimal(project.quantity_detail.getDecimal(node))};
+                   if(project.quantity_detail.quantityEditChecking(value,node,fieldName)){
+                       node.data.isFromDetail=0;
+                       project.quantity_detail.cleanQuantityDetail(node,true);
+                   }else {
+                       projectObj.mainController.refreshTreeNode([node]);
+                       return;
+                   }
                 } else if (fieldName === 'marketUnitFee') {
                     if (value) {value = parseFloat(value).toDecimal(projectObj.project.Decimal.common.unitFee)};
+                } else if (fieldName === 'calcBase') {
+                    if (value) {value = parseFloat(value).toDecimal(projectObj.project.Decimal.common.totalFee)};
                 };
 
                 node.changed = true;

+ 45 - 4
web/building_saas/report/html/rpt_main.html

@@ -16,9 +16,11 @@
                 <div class="print-toolsbar">
                     <div class="panel">
                         <div class="panel-body">
-                            <button class="btn btn-secondary btn-sm" type="button" onclick="rptHeaderObj.getExcel();">
-                                <i class="fa fa-print"></i><br>
-                                打印 <span id="checkCount" class="badge badge-primary">5</span>
+                            <button class="btn btn-secondary btn-sm" type="button" onclick="">
+                                <i class="fa fa-print"></i><br>打印
+                            </button>
+                            <button class="btn btn-secondary btn-sm" type="button"  href="#export" data-toggle="modal" data-target="#export">
+                                <i class="fa fa-share-square-o"></i><br>导出
                             </button>
                         </div>
                     </div>
@@ -51,7 +53,7 @@
                         <div class="panel-body">
                             <div class="btn-group" role="group">
                                 <button type="button" class="btn btn-secondary btn-sm">-</button>
-                                <a class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="重置默认大小">1000%</a>
+                                <a class="btn btn-secondary btn-sm" data-toggle="tooltip" data-placement="bottom" title="重置默认大小">100%</a>
                                 <button type="button" class="btn btn-secondary btn-sm">+</button>
                             </div>
                         </div>
@@ -139,6 +141,45 @@
         </div>
     </div>
 </div>
+<!--弹出导出-->
+<div class="modal fade" id="export" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">选择导出格式</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="row">
+                    <div class="col-6">
+                        <a class="btn btn-block btn-outline-secondary" id="PDF_TYPE" onclick="rptControlObj.changeType('PDF')">
+                            <!-- <i class="fa fa-check-square pull-right"></i> -->
+                            <div class="card-body text-center">
+                                <h1 class="display-3"><i class="fa fa-file-pdf-o"></i></h1>
+                                <h1>PDF</h1>
+                            </div>
+                        </a>
+                    </div>
+                    <div class="col-6">
+                        <a class="btn btn-block btn-primary" id="EXCEL_TYPE" onclick="rptControlObj.changeType('Excel')">
+                            <!-- <i class="fa fa-check-square pull-right"></i> -->
+                            <div class="card-body text-center">
+                                <h1 class="display-3"><i class="fa fa-file-excel-o"></i></h1>
+                                <h1>Excel</h1>
+                            </div>
+                        </a>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a onclick="rptControlObj.outputRpt();" class="btn btn-primary">确定</a>
+            </div>
+        </div>
+    </div>
+</div>
 <script>
     const SCREEN_DPI = [];
     function getScreenDPI() {

+ 2 - 2
web/building_saas/report/js/jpc_output.js

@@ -196,12 +196,12 @@ let JpcCanvasOutput = {
             ctx.beginPath();
             let destStyle = style;
             if (mergedBand) {
-                if (isNeedMergeBand && mergedBand[styleBorderDest] == cell[JV.PROP_AREA][styleBorderDest]) {
+                if (isNeedMergeBand && parseFloat(mergedBand[styleBorderDest]) === parseFloat(cell[JV.PROP_AREA][styleBorderDest])) {
                     destStyle = styles[mergedBand[JV.PROP_STYLE][JV.PROP_ID]];
                 }
             }
             ctx.moveTo(cell[JV.PROP_AREA][startP[0]] + me.offsetX, cell[JV.PROP_AREA][startP[1]] + me.offsetY);
-            if (destStyle[styleBorderDest] && destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT] != 0) {
+            if (destStyle[styleBorderDest] && parseFloat(destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT]) !== 0.0) {
                 ctx.lineWidth = 1.0 * destStyle[styleBorderDest][JV.PROP_LINE_WEIGHT];
                 ctx.strokeStyle = destStyle[styleBorderDest][JV.PROP_COLOR];
                 ctx.lineTo(cell[JV.PROP_AREA][destP[0]] + me.offsetX, cell[JV.PROP_AREA][destP[1]] + me.offsetY);

+ 76 - 28
web/building_saas/report/js/rpt_main.js

@@ -3,6 +3,11 @@
  */
 'use strict'
 
+const PRE_PAGE_OFFSET = 150;
+const NEXT_PAGE_OFFSET = 160;
+const FIRST_PAGE_OFFSET = 50;
+const LAST_PAGE_OFFSET = 60;
+
 let rptTplObj = {
     hasInitialized: false,
     iniPage: function() {
@@ -67,7 +72,7 @@ let zTreeOprObj = {
         let canvas = document.getElementById("rptCanvas");
         if (treeNode.nodeType === TPL_TYPE_TEMPLATE && treeNode.refId > 0) {
             let params = {};
-            let pageSize = rptHeaderObj.getCurrentPageSize();
+            let pageSize = rptControlObj.getCurrentPageSize();
             params.user_id = userID;
             params.pageSize = pageSize;
             params.rpt_tpl_id = treeNode.refId;
@@ -106,38 +111,43 @@ let zTreeOprObj = {
 
 let canvasOprObj = {
     canvasOnMouseMove: function (event) {
-        let x = event.offsetX - JpcCanvasOutput.offsetX, canvas = event.originalTarget;
-        if (x < 80) {
-            canvas.style.cursor = "url(/web/building_saas/img/FirstPageSimple.cur), auto";
-        } else if (x < 200) {
-            // canvas.style.cursor = "e-resize";
-            canvas.style.cursor = "url(/web/building_saas/img/PreviousPageSimple.cur), auto";
-        } else if ((canvas.width - x) < 80) {
-            canvas.style.cursor = "url(/web/building_saas/img/LastPageSimple.cur), auto";
-        } else if ((canvas.width - x) < 200) {
-            // canvas.style.cursor = "w-resize";
-            canvas.style.cursor = "url(/web/building_saas/img/NextPageSimple.cur), auto";
-        } else {
-            canvas.style.cursor = "";
+        if (zTreeOprObj.currentNode) {
+            let x = event.offsetX - JpcCanvasOutput.offsetX, canvas = event.originalTarget;
+            if (x < FIRST_PAGE_OFFSET) {
+                canvas.style.cursor = "url(/web/building_saas/img/FirstPageSimple.cur), auto";
+            } else if (x < PRE_PAGE_OFFSET) {
+                // canvas.style.cursor = "e-resize";
+                canvas.style.cursor = "url(/web/building_saas/img/PreviousPageSimple.cur), auto";
+            } else if ((canvas.width - x) < LAST_PAGE_OFFSET) {
+                canvas.style.cursor = "url(/web/building_saas/img/LastPageSimple.cur), auto";
+            } else if ((canvas.width - x) < NEXT_PAGE_OFFSET) {
+                // canvas.style.cursor = "w-resize";
+                canvas.style.cursor = "url(/web/building_saas/img/NextPageSimple.cur), auto";
+            } else {
+                canvas.style.cursor = "";
+            }
         }
     },
     cavansOnClick: function(event){
-        let x = event.offsetX - JpcCanvasOutput.offsetX,
-            //y = event.offsetY - JpcCanvasOutput.offsetY,
-            canvas = event.originalTarget;
-        if (x < 80) {
-            zTreeOprObj.showPage(1, canvas);
-        } else if (x < 200) {
-            zTreeOprObj.showPage(zTreeOprObj.currentPage - 1, canvas);
-        } else if ((canvas.width - x) < 80) {
-            zTreeOprObj.showPage(zTreeOprObj.maxPages, canvas);
-        } else if ((canvas.width - x) < 200) {
-            zTreeOprObj.showPage(zTreeOprObj.currentPage + 1, canvas);
+        if (zTreeOprObj.currentNode) {
+            let x = event.offsetX - JpcCanvasOutput.offsetX,
+                //y = event.offsetY - JpcCanvasOutput.offsetY,
+                canvas = event.originalTarget;
+            if (x < FIRST_PAGE_OFFSET) {
+                zTreeOprObj.showPage(1, canvas);
+            } else if (x < PRE_PAGE_OFFSET) {
+                zTreeOprObj.showPage(zTreeOprObj.currentPage - 1, canvas);
+            } else if ((canvas.width - x) < LAST_PAGE_OFFSET) {
+                zTreeOprObj.showPage(zTreeOprObj.maxPages, canvas);
+            } else if ((canvas.width - x) < NEXT_PAGE_OFFSET) {
+                zTreeOprObj.showPage(zTreeOprObj.currentPage + 1, canvas);
+            }
         }
     }
 };
 
-let rptHeaderObj = {
+let rptControlObj = {
+    currentOutputType: "Excel",
     getCurrentPageSize: function() {
         let rst = "A4";
         //
@@ -151,16 +161,54 @@ let rptHeaderObj = {
     getCurrentReportOption: function() {
         //
     },
+    changeType: function(newType) {
+        let me = rptControlObj;
+        let excelDom = document.getElementById("EXCEL_TYPE");
+        let pdfDom = document.getElementById("PDF_TYPE");
+        if (newType === "Excel") {
+            excelDom.className = "btn btn-block btn-primary";
+            pdfDom.className = "btn btn-block btn-outline-secondary";
+            me.currentOutputType = newType;
+        } else if (newType === "PDF") {
+            excelDom.className = "btn btn-block btn-outline-secondary";
+            pdfDom.className = "btn btn-block btn-primary";
+            me.currentOutputType = newType;
+        } else {
+            //me.currentOutputType = newType;
+        }
+    },
+    outputRpt: function() {
+        let me = rptControlObj;
+        if (me.currentOutputType === "Excel") {
+            me.getExcel();
+        } else if (me.currentOutputType === "PDF") {
+            me.getPDF();
+        } else {
+            //other types if needed.
+        }
+    },
     getExcel: function() {
-        let me = rptHeaderObj;
+        let me = rptControlObj;
         //目前只支持当前打开报表
         //zTreeOprObj.currentRptPageRst
         if (zTreeOprObj.currentNode && zTreeOprObj.currentNode.refId) {
             let orgRptName = zTreeOprObj.currentNode.name;
-            orgRptName = orgRptName.replace('【', '').replace('】','').replace('-','_');
+            orgRptName = orgRptName.replace('【', '').replace('】','').replace('-','_').replace(' ','');
             let url =  "/report_api/getExcel/" + projectInfoObj.projectInfo.ID + "/" + zTreeOprObj.currentNode.refId + "/" +
                 me.getCurrentPageSize() + "/" + orgRptName + "/" + false + "/" + 'normal';
             window.location = url;//这里不能使用get方法跳转,否则下载不成功
         }
+    },
+    getPDF: function() {
+        let me = rptControlObj;
+        //目前只支持当前打开报表
+        //zTreeOprObj.currentRptPageRst
+        if (zTreeOprObj.currentNode && zTreeOprObj.currentNode.refId) {
+            let orgRptName = zTreeOprObj.currentNode.name;
+            orgRptName = orgRptName.replace('【', '').replace('】','').replace('-','_');
+            let url =  "/report_api/getPDF/" + projectInfoObj.projectInfo.ID + "/" + zTreeOprObj.currentNode.refId + "/" +
+                me.getCurrentPageSize() + "/" + orgRptName;
+            window.location = url;//这里不能使用get方法跳转,否则下载不成功
+        }
     }
 };