Browse Source

Merge branch 'master' into olym

olym 7 years ago
parent
commit
a05adc124c

+ 14 - 0
Dockerfile_pp

@@ -0,0 +1,14 @@
+FROM operationbase:latest
+
+WORKDIR /ConstructionOperation
+
+RUN git pull http://192.168.1.12:3000/SmartCost/ConstructionOperation master
+
+
+RUN cnpm install
+
+EXPOSE 6080
+
+ENV NODE_ENV=pp
+
+ENTRYPOINT babel-node operation.js

+ 1 - 0
config/config.js

@@ -2,6 +2,7 @@ module.exports = {
     current: {server: "192.168.1.184", port: "60666"},
     local: {server: "localhost", port: "27017"},
     qa: {server: "192.168.1.184", port: "60666"},
+    pp:{server: "172.18.111.228", port: "27017"},
     prod: {server: "", port: ""},
     setupDb:function (env="local") {
         let me = this;

+ 84 - 0
modules/ration_repository/models/ration_item.js

@@ -488,6 +488,79 @@ rationItemDAO.prototype.updateAnnotation = function (lastOpr, repId, updateArr,
     });
 };
 
+//计算导入数据的价格
+rationItemDAO.prototype.calcForRation = function (stdGljList, ration) {
+    //根据工料机类型划分价格
+    const labour = [1],  material = [201, 202, 203, 204, 205, 206], machine = [301, 302, 303];
+    let labourPrc = [], materialPrc = [], machinePrc = [], singlePrc, updatePrc = {labourPrice: 0, materialPrice: 0, machinePrice: 0, basePrice: 0};
+    let rationGljList = ration.rationGljList;
+    for(let rationGlj of rationGljList){
+        let glj = stdGljList[rationGlj.gljId];
+        let prcType = isDef(glj) ? getParentType(glj.gljType) : null;
+        if(isDef(prcType)){
+            singlePrc = scMathUtil.roundTo(parseFloat(glj.basePrice) * parseFloat(rationGlj.consumeAmt), -3);
+            if(prcType === 'labour'){
+                labourPrc.push(singlePrc);
+            }
+            else if(prcType === 'material'){
+                materialPrc.push(singlePrc);
+            }
+            else if(prcType === 'machine'){
+                machinePrc.push(singlePrc);
+            }
+        }
+    }
+    //计算人工费
+    if(labourPrc.length > 0){
+        let sumLaP = 0;
+        for(let i = 0, len  = labourPrc.length; i < len; i++){
+            sumLaP += labourPrc[i];
+        }
+        updatePrc.labourPrice = scMathUtil.roundTo(sumLaP, -2);
+    }
+    //材料费
+    if(materialPrc.length > 0){
+        let sumLaP = 0;
+        for(let i = 0, len  = materialPrc.length; i < len; i++){
+            sumLaP += materialPrc[i];
+        }
+        updatePrc.materialPrice = scMathUtil.roundTo(sumLaP, -2);
+    }
+    //机械费
+    if(machinePrc.length > 0){
+        let sumLaP = 0;
+        for(let i = 0, len  = machinePrc.length; i < len; i++){
+            sumLaP += machinePrc[i];
+        }
+        updatePrc.machinePrice = scMathUtil.roundTo(sumLaP, -2);
+    }
+    //基价
+    updatePrc.basePrice = scMathUtil.roundTo(updatePrc.labourPrice + updatePrc.materialPrice + updatePrc.machinePrice, -2);
+    //更新定额数据
+    ration.labourPrice = updatePrc.labourPrice.toString();
+    ration.materialPrice = updatePrc.materialPrice.toString();
+    ration.machinePrice = updatePrc.machinePrice.toString();
+    ration.basePrice = updatePrc.basePrice.toString();
+
+    function isDef(v){
+        return v !== undefined && v !== null;
+    }
+    //是否属于人工、材料、机械类型
+    function getParentType(type){
+        if(labour.indexOf(type) !== -1){
+            return 'labour';
+        }
+        if(material.indexOf(type) !== -1){
+            return 'material';
+        }
+        if(machine.indexOf(type) !== -1){
+            return 'machine';
+        }
+        return null;
+    }
+
+};
+
 /**
  * 根据条件获取定额数据
  *
@@ -533,8 +606,10 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
     const stdGLJData = await stdBillsLibListsModel.getGljItemsByRep(rationRepository[0].gljLib);
     // 整理标准工料机库数据
     let stdGLJList = {};
+    let stdGLJListByID = {};
     for (const tmp of stdGLJData) {
         stdGLJList[tmp.code.toString()] = tmp.ID;
+        stdGLJListByID[tmp.ID] = tmp;
     }
     let lastData = {};
     const rationData = [];
@@ -579,6 +654,10 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
             caption: tmp[2],
             rationRepId: rationRepId,
             sectionId: 0,
+            labourPrice: '0',
+            materialPrice: '0',
+            machinePrice: '0',
+            basePrice: '0',
             rationGljList: []
         };
         // 防止重复加入
@@ -607,6 +686,11 @@ rationItemDAO.prototype.batchAddFromExcel = async function(rationRepId, data) {
     if (insertData.length <= 0) {
         return true;
     }
+    //计算价格
+    for(let ration of insertData){
+        this.calcForRation(stdGLJListByID, ration);
+    }
+
     // 组织id
     const counterInfo = await counter.counterDAO.getIDAfterCount(counter.moduleName.rations, insertData.length);
     let maxId = counterInfo.value.sequence_value;

+ 1 - 0
modules/reports/models/tpl_tree_node.js

@@ -23,6 +23,7 @@ let TplNodeSchema = new Schema({
     ID: Number,         //template节点ID,只有在nodeType是模板节点有效
     refId: Number,      //引用报表模板id (引用 collection: rpt_templates)
     name: String,       //显示名称
+    released: Boolean,  //是否已发布
     items: []           //子节点
 });
 

+ 88 - 13
modules/reports/util/rpt_construct_data_util.js

@@ -143,6 +143,36 @@ class Rpt_Data_Extractor {
         pri_setup_filter(JV.NODE_DETAIL_FIELDS);
         pri_setup_filter(JV.NODE_MASTER_FIELDS_EX);
         pri_setup_filter(JV.NODE_DETAIL_FIELDS_EX);
+        if (tpl[JV.NODE_MAP_DATA_HANDLE_INFO] && tpl[JV.NODE_MAP_DATA_HANDLE_INFO].length > 0) {
+            for (let preHandle of tpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
+                if (rst.indexOf(preHandle[JV.PROP_DATA_KEY]) < 0) {
+                    rst.push(preHandle[JV.PROP_DATA_KEY]);
+                }
+                if (preHandle[JV.PROP_HANDLE_TYPE] === JV.PROP_HANDLE_TYPE_FILTER) {
+                    if (preHandle[JV.PROP_FILTER_KEYS]) {
+                        for (let filter of preHandle[JV.PROP_FILTER_KEYS]) {
+                            if (filter[JV.PROP_FILTER_COMPARE_OBJ] && rst.indexOf(filter[JV.PROP_FILTER_COMPARE_OBJ]) < 0) {
+                                rst.push(filter[JV.PROP_FILTER_COMPARE_OBJ]);
+                            }
+                        }
+                    }
+                } else if (preHandle[JV.PROP_HANDLE_TYPE] === JV.PROP_HANDLE_TYPE_SUM) {
+                    if (preHandle[JV.PROP_SUM_GROUP_KEYS]) {
+                        for (let grpKey of preHandle[JV.PROP_SUM_GROUP_KEYS]) {
+                            if (grpKey.seeking_parent && rst.indexOf(grpKey.seeking_parent) < 0) {
+                                rst.push(grpKey.seeking_parent);
+                            }
+                        }
+                    }
+                } else if (preHandle[JV.PROP_PARENT_CHILD_SORT_KEY] && preHandle[JV.PROP_PARENT_CHILD_SORT_KEY].length > 0) {
+                    for (let item of preHandle[JV.PROP_PARENT_CHILD_SORT_KEY]) {
+                        if (rst.indexOf(item[JV.PROP_PARENT_DATA_KEY]) < 0) {
+                            rst.push(item[JV.PROP_PARENT_DATA_KEY]);
+                        }
+                    }
+                }
+            }
+        }
         if (rst.length === 0) {
             rst.push(projectConst.RATION_ASS);
         }
@@ -279,42 +309,70 @@ function filterData(sourceData, handleCfg, prjData) {
             tempRstArr.push(item);
         }
     }
-    let private_chkVal = function (src, dest, compStr) {
+    let private_chkVal = function (src, compVal, compStr) {
         let rst = true;
         switch (compStr) {
             case "==" :
-                rst = (src == dest);
+                rst = (src == compVal);
                 break;
             case "===" :
-                rst = (src === dest);
+                rst = (src === compVal);
                 break;
             case ">" :
-                rst = (src > dest);
+                rst = (src > compVal);
                 break;
             case ">=" :
-                rst = (src >= dest);
+                rst = (src >= compVal);
                 break;
             case "<" :
-                rst = (src < dest);
+                rst = (src < compVal);
                 break;
             case "<=" :
-                rst = (src <= dest);
+                rst = (src <= compVal);
                 break;
             case "!=" :
-                rst = (src != dest);
+                rst = (src != compVal);
                 break;
             case "!==" :
-                rst = (src !== dest);
+                rst = (src !== compVal);
+                break;
+            case "in" :
+                if (compVal instanceof Array) {
+                    rst = compVal.indexOf(src) >= 0;
+                } else {
+                    //string,需要转类型
+                    let newCv = JSON.parse(compVal);
+                    if (newCv instanceof Array) {
+                        rst = newCv.indexOf(src) >= 0;
+                    } else {
+                        rst = false;
+                    }
+                }
+                break;
+            case "not in":
+                if (compVal instanceof Array) {
+                    rst = compVal.indexOf(src) < 0;
+                } else {
+                    //string,需要转类型
+                    let newCv = JSON.parse(compVal);
+                    if (newCv instanceof Array) {
+                        rst = newCv.indexOf(src) < 0;
+                    } else {
+                        rst = true;
+                    }
+                }
                 break;
             default:
                 rst = true;
         }
         return rst;
     };
+    let compareObj = {};
     for (let item of tempRstArr) {
         let compRst = true;
         let curComparePrjData = null;
-        for (let cfg of handleCfg[JV.PROP_FILTER_KEY]) {
+        let startIdx = 0;
+        for (let cfg of handleCfg[JV.PROP_FILTER_KEYS]) {
             if (cfg[JV.PROP_FILTER_COMPARE_VAL]) {
                 //比较key值
                 compRst = private_chkVal(item[cfg.key], cfg[JV.PROP_FILTER_COMPARE_VAL], cfg[JV.PROP_FILTER_CONDITION]);
@@ -323,11 +381,28 @@ function filterData(sourceData, handleCfg, prjData) {
                 if (!curComparePrjData) {
                     curComparePrjData = getModuleDataByKey(prjData, cfg[JV.PROP_FILTER_COMPARE_OBJ]);
                 }
-                for (let data of curComparePrjData.data) {
-                    compRst = private_chkVal(item[cfg.key], data[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]], cfg[JV.PROP_FILTER_CONDITION]);
-                    if (compRst) break;
+                if (cfg[JV.PROP_FILTER_CONDITION] === "in" || cfg[JV.PROP_FILTER_CONDITION] === "not in") {
+                    let compareArr = null;
+                    if (!compareObj.hasOwnProperty(cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY] + startIdx.toString())) {
+                        compareObj[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY] + startIdx.toString()] = [];
+                        compareArr = compareObj[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY] + startIdx.toString()];
+                        for (let data of curComparePrjData.data) {
+                            if (compareArr.indexOf(data[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]]) < 0) {
+                                compareArr.push(data[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]]);
+                            }
+                        }
+                    } else {
+                        compareArr = compareObj[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY] + startIdx.toString()];
+                    }
+                    compRst = private_chkVal(item[cfg.key], compareArr, cfg[JV.PROP_FILTER_CONDITION]);
+                } else {
+                    for (let data of curComparePrjData.data) {
+                        compRst = private_chkVal(item[cfg.key], data[cfg[JV.PROP_FILTER_COMPARE_OBJ_KEY]], cfg[JV.PROP_FILTER_CONDITION]);
+                        if (compRst) break;
+                    }
                 }
             }
+            startIdx++;
         }
         if (compRst) {
             rstArr.push(item);

+ 1 - 1
public/web/rpt_value_define.js

@@ -53,7 +53,7 @@ const JV = {
     PROP_CHILD_SORT_KEYS: "子排序键值集",
     PROP_OTHER_SUB_SORT: "其他子排序",
     PROP_HANDLE_TYPE: "预处理类型",
-    PROP_FILTER_KEY: "过滤键值集",
+    PROP_FILTER_KEYS: "过滤键值集",
     PROP_FILTER_COMPARE_OBJ: "compareObjKey",
     PROP_FILTER_COMPARE_OBJ_KEY: "compareObjIdKey",
     PROP_FILTER_COMPARE_VAL: "compareValue",

+ 174 - 10
web/maintain/ration_repository/js/ration_coe.js

@@ -31,7 +31,126 @@ var rationCoeOprObj = {
         me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
         me.sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStarting);
         me.sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
-       // me.sheet.bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
+        //右键
+        me.onContextmenuOpr();
+    },
+
+    isDef: function (v) {
+        return v !== undefined && v !== null;
+    },
+
+    onContextmenuOpr: function () {
+        let me = rationCoeOprObj;
+        $.contextMenu({
+            selector: '#rdSpread',
+            build: function($triggerElement, e){
+                //控制允许右键菜单在哪个位置出现
+                let sheet = me.sheet;
+                let offset = $("#rdSpread").offset(),
+                    x = e.pageX - offset.left,
+                    y = e.pageY - offset.top;
+                let target = sheet.hitTest(x, y);
+                if(sheet.getParent().getActiveSheetIndex() === 2 && target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){//在表格内
+                    let currentCache = me.isDef(me.cache["_Coe_" + me.curRation.ID])  ? me.cache["_Coe_" + me.curRation.ID] : [];
+                    sheet.setActiveCell(target.row, target.col);
+                    //控制按钮是否可用
+                    let upDis = false,
+                        downDis = false,
+                        refDis = false;
+                    if(target.row >= currentCache.length){
+                        upDis = true;
+                        downDis = true;
+                        refDis = true;
+                    }
+                    else {
+                        if(!me.isDef(currentCache[target.row - 1])){
+                            upDis = true;
+                        }
+                        if(!me.isDef(currentCache[target.row + 1])){
+                            downDis = true;
+                        }
+                    }
+                    return {
+                        callback: function(){},
+                        items: {
+                            "upMove": {name: "上移", disabled: upDis, icon: "fa-arrow-up", callback: function (key, opt) {
+                                me.upMove(currentCache[target.row], currentCache[target.row - 1], {row: target.row - 1, col: target.col});
+                            }},
+                            "downMove": {name: "下移", disabled: downDis, icon: "fa-arrow-down", callback: function (key, opt) {
+                                me.downMove(currentCache[target.row], currentCache[target.row + 1], {row: target.row + 1, col: target.col});
+                            }},
+                            "ref": {name: "添加到本节其他定额", disabled: refDis, icon: "fa-arrow-left", callback: function (key, opt) {
+                                me.updateSectionRation(rationOprObj.currentRations["_SEC_ID_" + rationOprObj.currentSectionId], currentCache[target.row], function (updateArr) {
+                                    for(let i = 0, len = updateArr.length; i < len; i++){
+                                        let ration = updateArr[i];
+                                        let rationCoeList = updateArr[i].rationCoeList;
+                                        let newNo = 1;
+                                        for(let j = 0, jLen = rationCoeList.length; j < jLen; j++){
+                                            if(rationCoeList[j].no >= newNo){
+                                                newNo = rationCoeList[j].no + 1;
+                                            }
+                                        }
+                                        let theCache = me.cache["_Coe_" + ration.ID];
+                                        if(theCache !== undefined && theCache !== null){
+                                            let newCoe = {};
+                                            for(let attr in currentCache[target.row]){
+                                                newCoe[attr] = currentCache[target.row][attr];
+                                            }
+                                            newCoe.no = newNo;
+                                            theCache.push(newCoe);
+                                        }
+                                    }
+                                });
+                            }}
+                        }
+                    };
+                }
+                else{
+                    return false;
+                }
+            }
+        });
+    },
+
+    upMove: function (thisObj, preObj, cell) {
+        let me = this;
+        let tempNo = thisObj.no;
+        thisObj.no = preObj.no;
+        preObj.no = tempNo;
+        //ajax
+        me.updateCurRation(function () {
+            me.showCoeItems(me.curRation.ID);
+            me.sheet.setActiveCell(cell.row, cell.col);
+        });
+    },
+
+    downMove: function (thisObj, nextObj, cell) {
+        let me = this;
+        let tempNo = thisObj.no;
+        thisObj.no = nextObj.no;
+        nextObj.no = tempNo;
+        me.updateCurRation(function () {
+            me.showCoeItems(me.curRation.ID);
+            me.sheet.setActiveCell(cell.row, cell.col);
+        });
+    },
+
+    //本节所有使用此条件
+    useAll: function (coe) {
+
+    },
+
+    sortByNo: function (cache) {
+        cache.sort(function (a, b) {
+            let rst = 0;
+            if(a.no > b.no){
+                rst = 1;
+            }
+            else if(a.no < b.no){
+                rst = -1;
+            }
+            return rst;
+        });
     },
 
     onClipboardPasting: function(sender, args) {
@@ -221,7 +340,11 @@ var rationCoeOprObj = {
                 success:function(result){
                     if (result) {
                         var rstArr = [];
-                        for (let obj of result.data){rstArr.push(obj)};
+                        let newNo = curCache && curCache.length > 0 ? curCache[curCache.length - 1].no + 1 : 1;
+                        for (let obj of result.data){
+                            obj.no = newNo++;
+                            rstArr.push(obj)
+                        }
                         if (curCache) {
                             curCache = curCache.concat(rstArr);
                         }else{
@@ -254,12 +377,16 @@ var rationCoeOprObj = {
             ration.rationCoeList.length == 0){return;};*/
 
         var coeList = ration.rationCoeList;
+        let coeIDs = [];
+        for(let i = 0, len = coeList.length; i < len; i++){
+            coeIDs.push(coeList[i].ID);
+        }
         var curCache = me.cache["_Coe_" + ration.ID];
         if (curCache) {
             me.showCoeItems(ration.ID);
             //sheetCommonObj.lockCells(me.sheet, me.setting);
         } else if(!curCache && typeof coeList !== 'undefined' && coeList.length > 0) {
-            var data = {"libID": me.libID, "coeIDs": coeList};
+            var data = {"libID": me.libID, "coeIDs": coeIDs};
             $.ajax({
                 type:"POST",
                 url:"api/getCoeItemsByIDs",
@@ -272,9 +399,16 @@ var rationCoeOprObj = {
                     if (result.data) {
                         var tempResult = [];
                         for (let obj of result.data) {
-                            tempResult.push(obj);
+                            for(let i = 0, len = coeList.length; i < len; i++){
+                                if(obj.ID === coeList[i].ID){
+                                    obj.no = coeList[i].no;
+                                    tempResult.push(obj);
+                                    break;
+                                }
+                            }
                         };
 
+
                         me.cache["_Coe_" + ration.ID] = tempResult;
 
                         me.showCoeItems(ration.ID);
@@ -295,8 +429,8 @@ var rationCoeOprObj = {
         if (curCache) {
             curCache.sort(function(a, b) {
                 var rst = 0;
-                if (a.serialNo > b.serialNo) rst = 1
-                else if (a.serialNo < b.serialNo) rst = -1;
+                if (a.no > b.no) rst = 1
+                else if (a.no < b.no) rst = -1;
                 return rst;
             });
             sheetsOprObj.showData(me.sheet, me.setting, curCache);
@@ -310,15 +444,45 @@ var rationCoeOprObj = {
             var curCache = me.cache["_Coe_" + me.curRation.ID];
             if (curCache) {
                 for (let obj of curCache) {
-                    rst.push(obj.ID);
-                };
+                    rst.push({ID: obj.ID, no: obj.no});
+                }
                 me.curRation.rationCoeList = rst;
                 updateArr.push(me.curRation);
                 rationOprObj.mixUpdateRequest(updateArr, [], [], function () {
                     if(callback) callback();
                 });
-            };
-        };
+            }
+        }
+    },
+
+    //更新本节所有定额
+    updateSectionRation: function (rations, coe, callback) {
+        let me = this;
+        let updateArr = [];
+        for(let i = 0, len = rations.length; i < len; i++){
+            if(rations[i].ID !== me.curRation.ID){
+                let rationCoeList = rations[i].rationCoeList;
+                let isExist = false;
+                let newNo = 1;
+                for(let j = 0, jLen = rationCoeList.length; j < jLen; j++){
+                    if(rationCoeList[j].no >= newNo){
+                        newNo = rationCoeList[j].no + 1;
+                    }
+                    if(rationCoeList[j].ID === coe.ID){
+                        isExist = true;
+                    }
+                }
+                if(!isExist){
+                    rationCoeList.push({ID: coe.ID, no: newNo});
+                    updateArr.push(rations[i]);
+                }
+            }
+        }
+        if(updateArr.length > 0){
+            rationOprObj.mixUpdateRequest(updateArr, [], [], function () {
+                if(callback) callback(updateArr);
+            });
+        }
     }
 }
 

+ 33 - 0
web/maintain/report/js/cfg_const.js

@@ -514,6 +514,39 @@ let sortingKeysSetting = {
     }
 };
 
+let filterKeysSetting = {
+    view: {
+        addDiyDom: preHandleFilterObj.addDiyDom
+    },
+    edit: {
+        enable: false,
+        editNameSelectAll: false,
+        showRemoveBtn: false,
+        showRenameBtn: false
+    },
+    check: {
+        enable: true
+    },
+    data: {
+        keep: {
+            parent:true,
+            leaf:true
+        },
+        key: {
+            children: 'items',
+            name: "Name",
+            title: "Title",
+        },
+        simpleData: {
+            enable: true
+        }
+    },
+    callback:{
+        onCheck: preHandleFilterObj.onCheck,
+        beforeDrag: function(){return false;}
+    }
+};
+
 const engineering = {
     // 建筑工程
     ARCHITECTURE: 1,

+ 3 - 1
web/maintain/report/js/rpt_tpl_helper.js

@@ -107,7 +107,9 @@ let tplHelper = {
             dataInfoMapTreeOprObj.extractTabFields(rptTpl);
             dataInfoMapTreeOprObj.extractDiscreteFieldParam(rptTpl);
             discreteFieldParamTreeOprObj.extractFieldMaps(rptTpl);
-            //5. 计算式
+            //5. 指标预处理
+            preHandleObj.extractTabFields(rptTpl);
+            //6. 计算式
             calculationTreeOprObj.extractCalculation(rptTpl);
         } else {
             rst = false;

+ 15 - 0
web/maintain/report/js/rpt_tpl_main.js

@@ -111,10 +111,17 @@ let zTreeOprObj = {
     buildSubRootNodeDoc: function(subNode) {
         let me = this, rst = null;
         if (subNode) {
+            let isReleased = false;
+            if (subNode.nodeType == RT.NodeType.TEMPLATE) {
+                if (subNode.hasOwnProperty("released")) {
+                    isReleased = subNode.released;
+                }
+            }
             rst = {
                 nodeType: subNode.nodeType,
                 refId: subNode.refId,
                 ID: subNode.ID,
+                released: isReleased,
                 items: me.private_build_items(subNode.items, null),
                 name: subNode.name
             };
@@ -128,11 +135,18 @@ let zTreeOprObj = {
             itemRst = [];
             for (let item of items) {
                 if (item !== excludeNode) {
+                    let isReleased = false;
+                    if (item.nodeType == RT.NodeType.TEMPLATE) {
+                        if (item.hasOwnProperty("released")) {
+                            isReleased = item.released;
+                        }
+                    }
                     let ir = {};
                     ir.nodeType = item.nodeType;
                     ir.refId = item.refId;
                     ir.name = item.name;
                     ir.ID = item.ID;
+                    ir.released = isReleased;
                     ir.items = me.private_build_items(item.items);
                     itemRst.push(ir);
                 }
@@ -253,6 +267,7 @@ let zTreeOprObj = {
                 rawNode.nodeType = RT.NodeType.TEMPLATE;
                 rawNode.name = "新增报表模板";
                 rawNode.ID = newNodeID;
+                rawNode.released = false;
                 let newNodes = [], isSilent = false;
                 newNodes.push(rawNode);
                 me.treeObj.addNodes(me.currentNode, -1, newNodes, isSilent);

+ 313 - 45
web/maintain/report/js/rpt_tpl_pre_handle.js

@@ -3,6 +3,7 @@
  */
 
 const sort_types = ["normal", "tree", "accord_to_parent", "self_define"];
+const condition_types = ["==", "===", ">", ">=", "<", "<=", "!=", "in", "not in"];
 const pre_handle_data_objects = ["bills", "ration", "ration_glj"];
 const pre_handle_data_objects_name = ["清单", "定额", "定额工料机"];
 const exposed_bills_properties = [
@@ -97,23 +98,82 @@ let preHandleObj = {
         types.push({Name: JV.PROP_HANDLE_TYPE_ADD_DUMMY, Title: ""});
         // types.push({Name: "纯手工填写", Title: ""});
         me.typeTreeObj = $.fn.zTree.init($("#pre_handle_type_reversed"), preHandleTypeSetting, types);
-        me.setDisabledBandSelect(true);
+        me.setDisabledBandSelect([0,1,2,3,4]);
         me.build_handle_data_selection();
     },
-    setDisabledBandSelect: function(disabled) {
+    setDisabledBandSelect: function(disabledIdxArr) {
         let me = this;
         if (me.typeTreeObj) {
             let nodes = me.typeTreeObj.getNodes();
-            for (let node of nodes) {
-                me.typeTreeObj.setChkDisabled(node, disabled, true, true);
+            for (let idx = 0; idx < nodes.length; idx++) {
+                if (disabledIdxArr.indexOf(idx) >= 0) {
+                    me.typeTreeObj.setChkDisabled(nodes[idx], true, true, true);
+                } else {
+                    me.typeTreeObj.setChkDisabled(nodes[idx], false, true, true);
+                }
             }
         }
     },
-    addNewNode: function() {
-        let me = this, item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": "排序", "排序方式": "normal", "排序键值集":[], Operations: []};
+    addNewNode: function(nodeType) {
+        let me = this, item = null, preHandleType = nodeType;
+        if (!nodeType) {
+            preHandleType = JV.PROP_HANDLE_TYPE_SORT;
+        }
+        switch (nodeType) {
+            case JV.PROP_HANDLE_TYPE_SORT:
+                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "排序方式": "normal", "排序键值集":[]};
+                break;
+            case JV.PROP_HANDLE_TYPE_FILTER:
+                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "过滤键值集": []};
+                break;
+            case JV.PROP_HANDLE_TYPE_SUM:
+                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "分组键值集": [], "统计键值集":[]};
+                break;
+            case JV.PROP_HANDLE_TYPE_ADJUST:
+                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "数据调整集":[]};
+                break;
+            case JV.PROP_HANDLE_TYPE_ADD_DUMMY:
+                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "Dummy数据集":[]};
+                break;
+            default:
+                item = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": "排序", "排序方式": "normal", "排序键值集":[]};
+                break;
+        }
         me.private_set_title(item);
         me.treeObj.addNodes(null, -1, [item], true);
     },
+    private_change_node_by_type: function(handleType, item) {
+        let preHandleType = handleType;
+        if (!handleType) {
+            preHandleType = JV.PROP_HANDLE_TYPE_SORT;
+        }
+        item[JV.PROP_HANDLE_TYPE] = preHandleType;
+        switch (handleType) {
+            case JV.PROP_HANDLE_TYPE_SORT:
+                item[JV.PROP_SORT_TYPE] = "normal";
+                item[JV.PROP_SORT_KEYS] = [];
+                break;
+            case JV.PROP_HANDLE_TYPE_FILTER:
+                item[JV.PROP_FILTER_KEYS] = [];
+                break;
+            case JV.PROP_HANDLE_TYPE_SUM:
+                item[JV.PROP_SUM_GROUP_KEYS] = [];
+                item[JV.PROP_SUM_SUM_KEYS] = [];
+                break;
+            case JV.PROP_HANDLE_TYPE_ADJUST:
+                item[JV.PROP_ADJUST_COLLECTION] = [];
+                break;
+            case JV.PROP_HANDLE_TYPE_ADD_DUMMY:
+                item[JV.PROP_DUMMY_COLLECTION] = [];
+                break;
+            default:
+                item[JV.PROP_HANDLE_TYPE] = JV.PROP_HANDLE_TYPE_SORT;
+                item[JV.PROP_SORT_TYPE] = "normal";
+                item[JV.PROP_SORT_KEYS] = [];
+                break;
+        }
+        // return rst;
+    },
     private_copy_node: function(src, dest) {
         let me = this;
         dest[JV.PROP_DATA_KEY] = src[JV.PROP_DATA_KEY];
@@ -190,14 +250,16 @@ let preHandleObj = {
         //点击预处理环节 节点
         let me = preHandleObj;
         me.currentNode = treeNode;
-        me.setDisabledBandSelect(false);
+        me.setDisabledBandSelect([2,3,4]);
+        // me.setDisabledBandSelect([]);
         me.refreshByNode(treeNode);
     },
     onTypeClick: function(event,treeId,treeNode) {
         //选择预处理类型(排序、过滤。。。)
         let me = preHandleObj;
         if (me.currentNode) {
-            me.currentNode[JV.PROP_HANDLE_TYPE] = treeNode[JV.PROP_NAME];
+            // me.currentNode[JV.PROP_HANDLE_TYPE] = treeNode[JV.PROP_NAME];
+            me.private_change_node_by_type(treeNode[JV.PROP_NAME], me.currentNode);
             me.private_set_title(me.currentNode);
             me.treeObj.updateNode(me.currentNode, false);
             me.refreshByNode(me.currentNode);
@@ -207,28 +269,13 @@ let preHandleObj = {
         //更改(或选择)预处理环节中的 数据依据(就是说报表想预处理什么数据)
         let me = preHandleObj;
         if (oprType === "top") {
-            me.childTreeObj = $.fn.zTree.init($("#child_sorting_keys"), sortingKeysSetting, exposed_properties_arr[dom.selectedIndex]);
-            me.treeObj = $.fn.zTree.init($("#pre_handle_sort_keys_reversed"), sortingKeysSetting, exposed_properties_arr[dom.selectedIndex]);
+            preHandleSortObj.childTreeObj = $.fn.zTree.init($("#child_sorting_keys"), sortingKeysSetting, exposed_properties_arr[dom.selectedIndex]);
+            preHandleSortObj.treeObj = $.fn.zTree.init($("#pre_handle_sort_keys_reversed"), sortingKeysSetting, exposed_properties_arr[dom.selectedIndex]);
+            preHandleFilterObj.treeObj = $.fn.zTree.init($("#pre_handle_filter_keys_reversed"), filterKeysSetting, exposed_properties_arr[dom.selectedIndex]);
         } else if (oprType === "accord_to_parent") {
-            me.parentTreeObj = $.fn.zTree.init($("#parent_sorting_keys"), sortingKeysSetting, exposed_properties_arr[dom.selectedIndex]);
+            preHandleSortObj.parentTreeObj = $.fn.zTree.init($("#parent_sorting_keys"), sortingKeysSetting, exposed_properties_arr[dom.selectedIndex]);
         }
     },
-    onSortTypeChange: function(dom) {
-        //排序类型的选择/更改
-        let me = preHandleObj;
-        me.hide_all_dom();
-        $("#div_pre_handle_data")[0].style.display = "";
-        $("#div_sort_type")[0].style.display = "";
-        if (dom.selectedIndex === 2) {
-            $("#div_sort_type_according_to_parent")[0].style.display = "";
-            $("#div_sort_type_parent_data")[0].style.display = "";
-            me.parentTreeObj = $.fn.zTree.init($("#parent_sorting_keys"), sortingKeysSetting, exposed_properties_arr[dom.selectedIndex]);
-            me.childTreeObj = $.fn.zTree.init($("#child_sorting_keys"), sortingKeysSetting, exposed_properties_arr[dom.selectedIndex]);
-        } else if (dom.selectedIndex === 0) {
-            $("#div_sort_type_normal")[0].style.display = "";
-        }
-
-    },
     onBeforeDrop: function(treeId, treeNodes, targetNode, moveType){
         //
     },
@@ -242,29 +289,32 @@ let preHandleObj = {
         return rst;
     },
     extractTabFields: function (rptTpl) {
-        if (rptTpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
-            for (let handleObj of rptTpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
+        let me = this, nodes = me.treeObj.getNodes();
+        let rst = [];
+        if (nodes && nodes.length > 0) {
+            for (let handleObj of nodes) {
                 switch (handleObj[JV.PROP_HANDLE_TYPE]) {
                     case JV.PROP_HANDLE_TYPE_SORT:
-                        preHandleSortObj.extractTabFields(handleObj);
+                        rst.push(preHandleSortObj.extractTabFields(handleObj));
                         break;
                     case JV.PROP_HANDLE_TYPE_FILTER:
-                        preHandleFilterObj.extractTabFields(handleObj);
+                        rst.push(preHandleFilterObj.extractTabFields(handleObj));
                         break;
                     case JV.PROP_HANDLE_TYPE_SUM:
-                        preHandleSummaryObj.extractTabFields(handleObj);
+                        rst.push(preHandleSummaryObj.extractTabFields(handleObj));
                         break;
                     case JV.PROP_HANDLE_TYPE_ADJUST:
-                        preHandleAdjustObj.extractTabFields(handleObj);
+                        rst.push(preHandleAdjustObj.extractTabFields(handleObj));
                         break;
                     case JV.PROP_HANDLE_TYPE_ADD_DUMMY:
-                        preHandleAddDummyObj.extractTabFields(handleObj);
+                        rst.push(preHandleAddDummyObj.extractTabFields(handleObj));
                         break;
                     default:
                         break;
                 }
             }
         }
+        rptTpl[JV.NODE_MAP_DATA_HANDLE_INFO] = rst;
     }
 };
 
@@ -280,6 +330,12 @@ let preHandleSortObj = {
                 break;
             case 0 :
                 //normal
+                let keys = [];
+                for (let sortKeyItem of src[JV.PROP_SORT_KEYS]) {
+                    let item = {key: sortKeyItem.key, order: sortKeyItem.order};
+                    keys.push(item);
+                }
+                dest[JV.PROP_SORT_KEYS] = keys;
                 break;
             case 1 :
                 //tree
@@ -334,12 +390,12 @@ let preHandleSortObj = {
                     //normal
                     $("#div_sort_type_normal")[0].style.display = "";
                     idx = pre_handle_data_objects.indexOf(preHandleObj.currentNode[JV.PROP_DATA_KEY]);
-                    me.treeObj = $.fn.zTree.init($("#pre_handle_sort_keys_reversed"), sortingKeysSetting, exposed_properties_arr[idx]);
-                    let nodes = me.treeObj.getNodes();
+                    me.normalTreeObj = $.fn.zTree.init($("#pre_handle_sort_keys_reversed"), sortingKeysSetting, exposed_properties_arr[idx]);
+                    let nodes = me.normalTreeObj.getNodes();
                     for (let sortItem of preHandleObj.currentNode[JV.PROP_SORT_KEYS]) {
                         for (let keyNode of nodes) {
                             if (sortItem.key === keyNode.Key) {
-                                me.treeObj.checkNode(keyNode, true, false, false);
+                                me.normalTreeObj.checkNode(keyNode, true, false, false);
                                 break;
                             }
                         }
@@ -392,13 +448,12 @@ let preHandleSortObj = {
         }
     },
     resetNormalSort: function() {
-        let nodes = me.treeObj.getNodes();
+        let me = preHandleSortObj;
+        let nodes = me.normalTreeObj.getCheckedNodes();
         let normalSortKeys = [];
         for (let node of nodes) {
-            if (node.checked) {
-                let keyObj = {key: node.Key, order: node.Order};
-                normalSortKeys.push(keyObj);
-            }
+            let keyObj = {key: node.Key, order: node.Order};
+            normalSortKeys.push(keyObj);
         }
         preHandleObj.currentNode[JV.PROP_SORT_KEYS] = normalSortKeys;
     },
@@ -410,25 +465,232 @@ let preHandleSortObj = {
         if (sel) {
             sel.bind("change", function(){
                 treeNode.Order = sel[0].value;
+                preHandleSortObj.resetNormalSort();
             });
         }
     },
+    onSortTypeChange: function(dom) {
+        //排序类型的选择/更改
+        let me = preHandleObj;
+        me.hide_all_dom();
+        $("#div_pre_handle_data")[0].style.display = "";
+        $("#div_sort_type")[0].style.display = "";
+        let data_dom = $("#select_mapping_data")[0];
+        if (dom.selectedIndex === 2) {
+            $("#div_sort_type_according_to_parent")[0].style.display = "";
+            $("#div_sort_type_parent_data")[0].style.display = "";
+            preHandleSortObj.parentTreeObj = $.fn.zTree.init($("#parent_sorting_keys"), sortingKeysSetting, exposed_properties_arr[0]);
+            preHandleSortObj.childTreeObj = $.fn.zTree.init($("#child_sorting_keys"), sortingKeysSetting, exposed_properties_arr[data_dom.selectedIndex]);
+            me.currentNode[JV.PROP_PARENT_CHILD_SORT_KEY] = {};
+            me.currentNode[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_DATA_KEY] = pre_handle_data_objects[0];
+            me.currentNode[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_SORT_KEYS] = [];
+            me.currentNode[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_CHILD_SORT_KEYS] = [];
+        } else if (dom.selectedIndex === 0) {
+            $("#div_sort_type_normal")[0].style.display = "";
+            preHandleSortObj.normalTreeObj = $.fn.zTree.init($("#pre_handle_sort_keys_reversed"), sortingKeysSetting, exposed_properties_arr[data_dom.selectedIndex]);
+            me.currentNode[JV.PROP_SORT_KEYS] = [];
+        }
+        me.currentNode[JV.PROP_SORT_TYPE] = dom.value;
+    },
     extractTabFields: function (handleObj) {
-        //
+        let me = this, rst = {};
+        rst[JV.PROP_HANDLE_TYPE] = handleObj[JV.PROP_HANDLE_TYPE];
+        rst[JV.PROP_DATA_KEY] = handleObj[JV.PROP_DATA_KEY];
+        rst[JV.PROP_SORT_TYPE] = handleObj[JV.PROP_SORT_TYPE];
+        switch (sort_types.indexOf(handleObj[JV.PROP_SORT_TYPE])) {
+            case -1:
+                //unknown!
+                break;
+            case 0 :
+                //normal
+                rst[JV.PROP_SORT_KEYS] = handleObj[JV.PROP_SORT_KEYS];
+                break;
+            case 1 :
+                //tree
+                break;
+            case 2 :
+                //according to parent
+                break;
+            case 3 :
+                //self define
+                break;
+            default:
+                break;
+        }
+        return rst;
     }
 };
 
 let preHandleFilterObj = {
+    treeObj: null,
     copyNode: function (src, dest) {
-        //
+        let keys = [];
+        for (let filterItem of src[JV.PROP_FILTER_KEYS]) {
+            let item = {key: filterItem.key};
+            item[JV.PROP_FILTER_CONDITION] = filterItem[JV.PROP_FILTER_CONDITION];
+            item[JV.PROP_FILTER_COMPARE_VAL] = filterItem[JV.PROP_FILTER_COMPARE_VAL];
+            if (filterItem[JV.PROP_FILTER_COMPARE_OBJ]) {
+                item[JV.PROP_FILTER_COMPARE_OBJ] = filterItem[JV.PROP_FILTER_COMPARE_OBJ];
+                item[JV.PROP_FILTER_COMPARE_OBJ_KEY] = filterItem[JV.PROP_FILTER_COMPARE_OBJ_KEY];
+            }
+            keys.push(item);
+        }
+        dest[JV.PROP_FILTER_KEYS] = keys;
     },
     refresh_node: function () {
+        let me = this;
         $("#div_filter_type")[0].style.display = "";
         if (preHandleObj.currentNode) {
+            let idx = pre_handle_data_objects.indexOf(preHandleObj.currentNode[JV.PROP_DATA_KEY]);
+            me.treeObj = $.fn.zTree.init($("#pre_handle_filter_keys_reversed"), filterKeysSetting, exposed_properties_arr[idx]);
+            let nodes = me.treeObj.getNodes();
+            for (let filterItem of preHandleObj.currentNode[JV.PROP_FILTER_KEYS]) {
+                for (let keyNode of nodes) {
+                    if (filterItem.key === keyNode.Key) {
+                        me.treeObj.checkNode(keyNode, true, false, false);
+                        //and then others...
+                        //过滤条件
+                        keyNode[JV.PROP_FILTER_CONDITION] = filterItem[JV.PROP_FILTER_CONDITION];
+                        $("#diySelect_" + keyNode.tId)[0].selectedIndex = condition_types.indexOf(filterItem[JV.PROP_FILTER_CONDITION]);
+                        //条件值
+                        keyNode[JV.PROP_FILTER_COMPARE_VAL] = filterItem[JV.PROP_FILTER_COMPARE_VAL];
+                        $("#diyInput_" + keyNode.tId)[0].selectedIndex = filterItem[JV.PROP_FILTER_COMPARE_VAL];
+                        //其他关联业务数据对象
+                        if (filterItem[JV.PROP_FILTER_COMPARE_OBJ]) {
+                            let cmpObjDom = $("#diyDataSelect_" + keyNode.tId)[0];
+                            keyNode[JV.PROP_FILTER_COMPARE_OBJ] = filterItem[JV.PROP_FILTER_COMPARE_OBJ];
+                            let idx = pre_handle_data_objects.indexOf(filterItem[JV.PROP_FILTER_COMPARE_OBJ]);
+                            cmpObjDom.selectedIndex = idx + 1;
+                            me.private_setup_compare_obj(cmpObjDom);
+                            let cmpObjIdDom = $("#diyDataDetailSelect_" + keyNode.tId)[0];
+                            for (let i = 0; i < cmpObjIdDom.children.length; i++) {
+                                let option = cmpObjIdDom.children[i];
+                                if (option.value === filterItem[JV.PROP_FILTER_COMPARE_OBJ_KEY]) {
+                                    keyNode[JV.PROP_FILTER_COMPARE_OBJ_KEY] = filterItem[JV.PROP_FILTER_COMPARE_OBJ_KEY]
+                                    cmpObjIdDom.selectedIndex = i;
+                                    break;
+                                }
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+    },
+    onCheck: function(event,treeId,treeNode) {
+        let me = preHandleFilterObj;
+        me.resetFilter();
+    },
+    resetFilter: function() {
+        let me = this;
+        let nodes = me.treeObj.getCheckedNodes();
+        let normalSortKeys = [];
+        for (let node of nodes) {
+            let keyObj = {key: node.Key};
+            if (!node[JV.PROP_FILTER_CONDITION]) {
+                node[JV.PROP_FILTER_CONDITION] = "==";
+            }
+            keyObj[JV.PROP_FILTER_CONDITION] = node[JV.PROP_FILTER_CONDITION];
+            keyObj[JV.PROP_FILTER_COMPARE_VAL] = node[JV.PROP_FILTER_COMPARE_VAL];
+            if (node[JV.PROP_FILTER_COMPARE_OBJ]) {
+                keyObj[JV.PROP_FILTER_COMPARE_OBJ] = node[JV.PROP_FILTER_COMPARE_OBJ];
+                keyObj[JV.PROP_FILTER_COMPARE_OBJ_KEY] = node[JV.PROP_FILTER_COMPARE_OBJ_KEY];
+            }
+            normalSortKeys.push(keyObj);
+        }
+        preHandleObj.currentNode[JV.PROP_FILTER_KEYS] = normalSortKeys;
+    },
+    build_filter_handle_data_selection_str: function(treeId,treeNode) {
+        let rst = [];
+        rst.push("<select class='selDemo' id='diyDataSelect_" + treeNode.tId + "'>");
+        rst.push("<option value='empty'>无</option>");
+        for (let i = 0; i < pre_handle_data_objects.length; i++) {
+            rst.push("<option value='" + pre_handle_data_objects[i] + "'>" + pre_handle_data_objects_name[i] + "</option>");
+        }
+        rst.push("</select>");
+        return rst.join("");
+    },
+    build_filter_handle_data_detail_selection_str: function(treeId,treeNode) {
+        let rst = [];
+        rst.push("<select class='selDemo' id='diyDataDetailSelect_" + treeNode.tId + "'>");
+        rst.push("</select>");
+        return rst.join("");
+    },
+    addDiyDom: function(treeId,treeNode) {
+        let me = preHandleFilterObj;
+        let aObj = $("#" + treeNode.tId + IDMark_A);
+        let dataDtlSelStr = me.build_filter_handle_data_detail_selection_str(treeId,treeNode);
+        aObj.after(dataDtlSelStr);
+        let dataSelStr = me.build_filter_handle_data_selection_str(treeId,treeNode);
+        aObj.after(dataSelStr);
+        let editStr = "<input type='text' id='diyInput_" + treeNode.tId + "' width='10'/>";
+        aObj.after(editStr);
+        let selStr = "<select class='selDemo' id='diySelect_" + treeNode.tId + "'><option value='=='>等于</option><option value='==='>全等于</option><option value='>'>大于</option><option value='>='>大于等于</option><option value='<'>小于</option><option value='<='>小于等于</option><option value='!='>不等于</option><option value='in'>在</option><option value='not in'>不在</option></select>";
+        aObj.after(selStr);
+        let sel = $("#diySelect_" + treeNode.tId);
+        if (sel) {
+            sel.bind("change", me.filterConditionChange);
+        }
+        sel = $("#diyDataSelect_" + treeNode.tId);
+        if (sel) {
+            sel.bind("change", me.filterCompareObjChange);
+        }
+        sel = $("#diyDataDetailSelect_" + treeNode.tId);
+        if (sel) {
+            sel.bind("change", me.filterCompareObjKeyChange);
+        }
+    },
+    filterConditionChange: function(event) {
+        let me = preHandleFilterObj, sel = event.currentTarget, tId = sel.id.slice(10);
+        let node = me.treeObj.getNodeByTId(tId);
+        node[JV.PROP_FILTER_CONDITION] = sel.value;
+        me.resetFilter();
+    },
+    private_setup_compare_obj: function(dom) {
+        let me = this, sel = dom, tId = sel.id.slice(14);
+        let node = me.treeObj.getNodeByTId(tId);
+        node[JV.PROP_FILTER_COMPARE_OBJ] = sel.value;
+        let idx = pre_handle_data_objects.indexOf(sel.value);
+        let dtlKey = "diyDataDetailSelect_" + tId;
+        let dtlSel = document.getElementById(dtlKey);
+        dtlSel.length = 0;
+        if (idx >= 0) {
+            let jdtlSel = $("#" + dtlKey);
+            for (let item of exposed_properties_arr[idx]) {
+                jdtlSel.append("<option value='" + item.Key + "'>" + item.Name + "</option>");
+            }
+        } else {
+            //清除所有key选项
+            node[JV.PROP_FILTER_COMPARE_OBJ_KEY] = null;
         }
     },
+    filterCompareObjChange: function(event) {
+        let me = preHandleFilterObj, sel = event.currentTarget;
+        me.private_setup_compare_obj(sel);
+        me.resetFilter();
+    },
+    filterCompareObjKeyChange: function(event) {
+        let me = preHandleFilterObj, sel = event.currentTarget, tId = sel.id.slice(20);
+        let node = me.treeObj.getNodeByTId(tId);
+        node[JV.PROP_FILTER_COMPARE_OBJ_KEY] = sel.value;
+        me.resetFilter();
+    },
     extractTabFields: function (handleObj) {
-        //
+        let me = this, rst = {};
+        rst[JV.PROP_HANDLE_TYPE] = handleObj[JV.PROP_HANDLE_TYPE];
+        rst[JV.PROP_DATA_KEY] = handleObj[JV.PROP_DATA_KEY];
+        rst[JV.PROP_FILTER_KEYS] = [];
+        for (let item of handleObj[JV.PROP_FILTER_KEYS]) {
+            let dtl = {};
+            dtl.key = item.key;
+            dtl[JV.PROP_FILTER_CONDITION] = item[JV.PROP_FILTER_CONDITION];
+            dtl[JV.PROP_FILTER_COMPARE_VAL] = item[JV.PROP_FILTER_COMPARE_VAL]?item[JV.PROP_FILTER_COMPARE_VAL]:null;
+            dtl[JV.PROP_FILTER_COMPARE_OBJ] = item[JV.PROP_FILTER_COMPARE_OBJ]?item[JV.PROP_FILTER_COMPARE_OBJ]:null;
+            dtl[JV.PROP_FILTER_COMPARE_OBJ_KEY] = item[JV.PROP_FILTER_COMPARE_OBJ_KEY]?item[JV.PROP_FILTER_COMPARE_OBJ_KEY]:null;
+            rst[JV.PROP_FILTER_KEYS].push(dtl);
+        }
+        return rst;
     }
 };
 
@@ -442,7 +704,9 @@ let preHandleSummaryObj = {
         }
     },
     extractTabFields: function (handleObj) {
+        let rst = {};
         //
+        return rst;
     }
 };
 
@@ -456,7 +720,9 @@ let preHandleAdjustObj = {
         }
     },
     extractTabFields: function (handleObj) {
+        let rst = {};
         //
+        return rst;
     }
 };
 
@@ -470,6 +736,8 @@ let preHandleAddDummyObj = {
         }
     },
     extractTabFields: function (handleObj) {
+        let rst = {};
         //
+        return rst;
     }
 };

+ 1 - 1
web/maintain/report/rpt_tpl_detail_mapping_fields.html

@@ -1,7 +1,7 @@
 <div class="tab-pane" id="rpttplfieldmap" role="tabpanel">
     <div class="main-data">
         <div class="p-3">
-            <label>报表映射指标</label>
+            <label>报表映射指标(勾选表示:主从关系的ID关联指标)</label>
             <div class="tab-content">
                 <ul id="field_map_tree_reversed" class="ztree"></ul>
             </div>

+ 1 - 1
web/maintain/report/rpt_tpl_detail_pre_handle.html

@@ -2,7 +2,7 @@
     <div class="main-data">
         <div class="p-3">
             <div class="tab-bar">
-                <a onclick="preHandleObj.addNewNode()" class="btn btn-secondary btn-sm fa fa-plus-square">预处理环节</a>
+                <a onclick="preHandleObj.addNewNode('排序')" class="btn btn-secondary btn-sm fa fa-plus-square">预处理环节</a>
             </div>
             <div class="form-group row">
                 <div class="form-group col-md-7">

+ 6 - 0
web/maintain/report/rpt_tpl_detail_pre_handle_filter.html

@@ -1,2 +1,8 @@
 <div class="form-group row" id="div_filter_type">
+    <div class="form-group col-md-12">
+        <label>过滤键值集</label>
+        <div class="ztree-warp">
+            <ul id="pre_handle_filter_keys_reversed" class="ztree"></ul>
+        </div>
+    </div>
 </div>

+ 3 - 2
web/maintain/report/rpt_tpl_detail_pre_handle_sort.html

@@ -1,7 +1,7 @@
 <div class="form-group row" id="div_sort_type">
     <div class="input-group col-5">
-        <div class="input-group-addon">排序类型</div>
-        <select class="form-control input-sm" id="select_sort_types" onchange="preHandleObj.onSortTypeChange(this)">
+        <div class="input-group-addon">排序方式</div>
+        <select class="form-control input-sm" id="select_sort_types" onchange="preHandleSortObj.onSortTypeChange(this)">
             <option value="normal">普通</option>
             <option value="tree">树结构</option>
             <option value="accord_to_parent">依据上级</option>
@@ -16,6 +16,7 @@
 </div>
 <div class="form-group row" id="div_sort_type_normal">
     <div class="form-group col-md-7">
+        <label>排序键值集</label>
         <div class="ztree-warp">
             <ul id="pre_handle_sort_keys_reversed" class="ztree"></ul>
         </div>

+ 3 - 0
web/users/js/main_tree_col.js

@@ -21,6 +21,9 @@ let MainTreeCol = {
             }else {
                 return node.data["quantity"];
             }
+        },
+        code: function (node) {
+
         }
     },
     readOnly: {