Преглед изворни кода

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/YangHuOperation

vian пре 1 година
родитељ
комит
de0829dd31

+ 37 - 0
modules/all_models/bill_code.js

@@ -0,0 +1,37 @@
+//单体模板库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const billCodeLib = new Schema({
+        ID:{type:String,index:true},
+        creator: String,
+        createDate: Number,
+        recentOpr: [oprSchema],
+        name: String,
+        compilationID: String
+    },
+    {versionKey: false}
+);
+
+mongoose.model("std_bill_code_lib", billCodeLib,"std_bill_code_lib");
+
+
+
+const billCodeItem = new Schema({
+    ID:{type:String,index:true},
+    libID: {type:String,index:true},
+    code: {type:String},
+    name: String,
+    formatName: String,
+    formatName2: String,
+    unit: String,
+    subArea: Boolean,
+    startValue: Number,
+    stepValue: Number,
+    startCode: Number,
+},
+{versionKey: false}
+);
+
+billCodeItem.index({ libID: 1, code: 1 });
+mongoose.model("std_bill_code_item", billCodeItem,"std_bill_code_item");

+ 4 - 1
modules/all_models/compilation.js

@@ -76,6 +76,8 @@ let modelSchema = {
     overWriteUrl:String,
     //例题建设项目ID
     example: Array,
+    // 版本号
+    edition: String,
     // 发布时间
     release_time: {
         type: Number,
@@ -96,6 +98,7 @@ let modelSchema = {
         type: Number,
         default: 12 // 总部id
     },
-    defaultLocation:String//默认工程所在地
+    defaultLocation:String,//默认工程所在地
+    freeUse:Boolean
 };
 mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 5 - 0
modules/all_models/engineering_lib.js

@@ -74,6 +74,11 @@ let modelSchema = {
         type: Schema.Types.Mixed,
         default: []
     },
+    //车船税文件
+    billCode_lib: {
+        type: Schema.Types.Mixed,
+        default: []
+    },
     //设置人材机显示列
     glj_col:{
         showAdjustPrice:Boolean//是否显示调整价列

+ 118 - 0
modules/bill_code_lib/controllers/bill_code_controller.js

@@ -0,0 +1,118 @@
+/**
+ * Created by zhang on 2018/9/3.
+ */
+import BaseController from "../../common/base/base_controller";
+import billCodeFacade from "../facade/bill_code_facade";
+let config = require("../../../config/config.js");
+let logger = require('../../../logs/log_helper').logger;
+import CompilationModel from '../../users/models/compilation_model';
+
+class BillCodeController extends BaseController{
+    async main(request, response) {
+     
+        let compilationModel = new CompilationModel();
+        let compilationList = await compilationModel.getCompilationList({_id: 1, name: 1});
+        compilationList.unshift({_id: 'all', name: '所有'});
+        let activeCompilation = compilationList.find(compilation => compilation._id.toString() === request.query.filter);
+        if (activeCompilation) {
+            activeCompilation.active = 'active';
+        } else {
+            compilationList[0].active = 'active'
+        }
+        let filter = request.query.filter ? {compilationID: request.query.filter} : {};
+        let templateLibs = await billCodeFacade.findByCondition(filter,{feature:0},false);
+        let renderData = {
+            title:'递延清单',
+            userAccount: request.session.managerData.username,
+            userID: request.session.managerData.userID,
+            templateLibs:templateLibs,
+            compilationList: compilationList,
+            layout: 'maintain/common/html/layout'
+        };
+        response.render("maintain/bill_code_lib/html/main", renderData);
+    }
+    async addLib(request, response){
+        try {
+            await billCodeFacade.addLib(request.body);
+        }catch (error) {
+            console.log(error);
+        }
+        response.redirect(request.headers.referer);
+    }
+    async findLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let conditions={'ID' : data.ID};
+            let resultData = await billCodeFacade.findByCondition(conditions);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async saveLib(request, response){
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            console.log(data.data);
+            let resultData= await billCodeFacade.saveLib(data);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async deleteLibByID(request,response){
+        logger.info(`delete projectFeatureLib ${request.ip}`);
+        let result={
+            error:0
+        };
+        try {
+            let data = request.body.data;
+            data = JSON.parse(data);
+            let resultData= await billCodeFacade.deleteLibByID(data.ID);
+            result.data=resultData;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        response.json(result);
+    }
+    async edit(request,response){
+        //先取出替换库信息:
+        let libID = request.params.libID;
+       
+        let billCodeSegment = await billCodeFacade.findByCondition({'ID':libID});
+        let items = await billCodeFacade.findItemsByCondition({'libID':libID},"-_id -libID -ID");
+        console.log(items);
+        if(billCodeSegment){
+            let randerData = {
+                title:'递延清单',
+                mainURL:'/billCode/main',
+                libName:billCodeSegment.name,
+                userAccount: request.session.managerData.username,
+                userID: request.session.managerData.userID,
+                templateLibs:JSON.stringify({data:items}),
+                libID:libID,
+                LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
+                layout: 'maintain/common/html/edit_layout'
+            };
+            response.render("maintain/bill_code_lib/html/edit", randerData);
+        }else {
+            response.redirect(request.headers.referer);
+        }
+    }
+}
+export default BillCodeController;

+ 58 - 0
modules/bill_code_lib/facade/bill_code_facade.js

@@ -0,0 +1,58 @@
+/**
+ * Created by zhang on 2018/9/3.
+ */
+import mongoose from "mongoose";
+const uuidV1 = require('uuid/v1');
+let moment = require("moment");
+let billCodeLibModel = mongoose.model('std_bill_code_lib');
+let billCodeItemModel = mongoose.model('std_bill_code_item');
+let compilationModel = mongoose.model('compilation');
+
+
+let billCodeLib = {
+    findByCondition:async function(conditions,options,single=true){
+        if(single == true){
+            return await billCodeLibModel.findOne(conditions,options);
+        }else {
+            return await billCodeLibModel.find(conditions,options);
+        }
+    },
+    findItemsByCondition:async function(conditions,options){
+        return await  billCodeItemModel.find(conditions,options).lean();
+    },
+    addLib : async function (data){
+        let now = new Date().getTime();
+        let dateStr = moment(now).format('YYYY-MM-DD HH:mm:ss');
+        //取编办信息
+        let compilation = await compilationModel.findOne({_id:data.compilationId});
+        if(compilation){
+            let newLib = {
+                creator: data.userAccount,
+                createDate: now,
+                recentOpr: [{operator: data.userAccount, operateDate: dateStr}],
+                name: data.name,
+                compilationID: data.compilationId,
+                compilationName: compilation.name,
+            };
+            newLib.ID = uuidV1();
+            return await billCodeLibModel.create(newLib);
+        }else {
+            throw  new Error("没有找到该编办!");
+        }
+    },
+    saveLib:async function(param) {
+        await billCodeItemModel.deleteMany({libID:param.query.ID});
+        const items = param.data.data.map((item) => {
+            item.libID = param.query.ID;
+            item.ID = uuidV1();
+            return item;
+        });
+        return await billCodeItemModel.insertMany(items);
+    },
+    deleteLibByID:async function(ID){
+        await billCodeItemModel.deleteMany({libID:ID});
+        return await billCodeLibModel.deleteOne({ID:ID});
+    },
+};
+
+export default billCodeLib

+ 21 - 0
modules/bill_code_lib/routes/bill_code_routes.js

@@ -0,0 +1,21 @@
+/**
+ * Created by zhang on 2018/9/3.
+ */
+
+let express = require("express");
+let billCodeRouter =express.Router();
+import  BillCodeController from "../controllers/bill_code_controller";
+let billCodeController = new BillCodeController();
+
+module.exports =function (app){
+
+    billCodeRouter.get("/main", billCodeController.auth, billCodeController.init, billCodeController.main);
+    billCodeRouter.post("/addLib", billCodeController.auth, billCodeController.init, billCodeController.addLib);
+    billCodeRouter.post("/findLib", billCodeController.auth, billCodeController.init, billCodeController.findLib);
+    billCodeRouter.post("/saveLib", billCodeController.auth, billCodeController.init, billCodeController.saveLib);
+    billCodeRouter.post("/deleteLibByID", billCodeController.auth, billCodeController.init, billCodeController.deleteLibByID);
+    billCodeRouter.get("/edit/:libID", billCodeController.auth, billCodeController.init, billCodeController.edit);
+    app.use("/billCode", billCodeRouter);
+};
+
+

+ 30 - 0
modules/common/std/std_glj_lib_map_model.js

@@ -51,6 +51,36 @@ class STDGLJLibMapModel extends BaseModel {
         return result;
     }
 
+      /**
+     * 获取对应的工料机库
+     *
+     * @param {String} compilationId
+     * @return {Promise}
+     */
+       async getAllGLJLibList() {
+        let result = [];
+        let gliLib = await this.findDataByCondition({deleted: false}, null, false);
+
+        if (gliLib.length <= 0) {
+            return result;
+        }
+
+        // 整理数据
+        let gljList = [];
+        for(let tmp of gliLib) {
+            let tmpRation = {id: tmp.ID, name: tmp.dispName};
+            if (gljList.length <= 0) {
+                gljList = [tmpRation];
+            } else {
+                gljList.push(tmpRation);
+            }
+        }
+
+        result = gljList;
+        return result;
+    }
+
+
 }
 
 export default STDGLJLibMapModel;

+ 46 - 4
modules/users/controllers/compilation_controller.js

@@ -25,6 +25,7 @@ import projectFeatureFacade from "../../project_feature_lib/facade/project_featu
 import basicInfoFacade from "../../basic_info_lib/facade/basic_info_facade";
 import progressiveFacade from "../../progressive_interval_lib/facade/progressive_facade";
 import vvTaxFacade from "../../vehicleVessel_lib/facade/vvTax_facade";
+import billCodeFacade from "../../bill_code_lib/facade/bill_code_facade";
 import {default as category, List as categoryList} from "../../common/const/category_const.js";
 import locationList from  "../../common/const/locationList";
 
@@ -198,7 +199,8 @@ class CompilationController extends BaseController {
             billsTemplateData = [],
             featureList = [],
             progressiveList = [],
-            vvTaxList = [];
+            vvTaxList = [],
+            billCodeList = [];
         let valuationData = {}, valuationList = {}, artificialCoefficientList = [], calculationList = [], billsGuidanceList = [], mainTreeColList = [];
         let billTemplateList = [];
         try {
@@ -216,7 +218,7 @@ class CompilationController extends BaseController {
 
             // 获取工料机库
             let stdGLJLibMapModel = new STDGLJLibMapModel();
-            gljList = await stdGLJLibMapModel.getGLJLibList(selectedCompilation._id);
+            gljList = await stdGLJLibMapModel.getAllGLJLibList();
 
             // 获取费率标准库
             let stdFeeRateLibsModel = new STDFeeRateLibsModel();
@@ -265,6 +267,9 @@ class CompilationController extends BaseController {
             //获取车船税库
             vvTaxList = await vvTaxFacade.findByCondition({}, false, false);
 
+             //获取递延清单库
+             billCodeList = await billCodeFacade.findByCondition({}, false, false);
+
         } catch (error) {
             console.log(error);
         }
@@ -293,6 +298,7 @@ class CompilationController extends BaseController {
             infoList: JSON.stringify(infoList),
             progressiveList:JSON.stringify(progressiveList),
             vvTaxList: JSON.stringify(vvTaxList),
+            billCodeList: JSON.stringify(billCodeList),
             title : config[process.env.NODE_ENV].title?config[process.env.NODE_ENV].title:'养护云版',
             layout: 'users/views/layout/layout',
             LicenseKey:config.getLicenseKey(process.env.NODE_ENV)
@@ -763,11 +769,35 @@ class CompilationController extends BaseController {
      * @return {Promise.<void>}
      */
     async changeLocation(request, response) {
-        let valuationId = request.body.id;
+        let compilationId = request.body.id;
         let location = request.body.location;
         try {
             let compilationModel = new CompilationModel();
-            let result = await compilationModel.updateLocation(valuationId, location);
+            let result = await compilationModel.updateLocation(compilationId, location);
+            if (result) {
+                response.json({error: 0, message: '', data: null});
+            } else {
+                response.json({error: 1, message: '更新数据错误', data: null});
+            }
+        } catch(error) {
+            response.json({error: 1, message: '更新数据错误', data: null});
+        }
+    }
+
+
+     /**
+     * 更改编办默认工程所在工
+     *
+     * @param request
+     * @param response
+     * @return {Promise.<void>}
+     */
+      async changeFreeUse(request, response) {
+        let compilationId = request.body.id;
+        let freeUse = request.body.freeUse;
+        try {
+            let compilationModel = new CompilationModel();
+            let result = await compilationModel.updateFreeUse(compilationId, freeUse);
             if (result) {
                 response.json({error: 0, message: '', data: null});
             } else {
@@ -778,6 +808,18 @@ class CompilationController extends BaseController {
         }
     }
 
+    async setEdition(request, response){
+        let compilationId = request.body.id;
+        let edition = request.body.edition;
+        try{
+            let compilationModel = new CompilationModel();
+            await compilationModel.setEdition(compilationId, edition);
+            response.json({err: 0, msg: '', data: null});
+        }
+        catch (err){
+            response.json({err: 1, msg: err, data: null});
+        }
+    }
 }
 
 export default CompilationController;

+ 23 - 1
modules/users/models/compilation_model.js

@@ -36,7 +36,7 @@ class CompilationModel extends BaseModel {
      */
     async getCompilationList(fields = null) {
         // 筛选字段
-        let field = fields == null ? {_id: 1, name: 1, is_release: 1,release_time:1, defaultLocation:1,categoryID: 1, description: 1,overWriteUrl: 1,example: 1,
+        let field = fields == null ? {_id: 1, name: 1, is_release: 1,release_time:1, defaultLocation:1,categoryID: 1, description: 1,overWriteUrl: 1,example: 1,edition: 1,freeUse:1,
             "ration_valuation.id": 1, "ration_valuation.name": 1, "ration_valuation.enable": 1,
             "suggestion_valuation.id": 1, "suggestion_valuation.name": 1, "suggestion_valuation.enable": 1,
             "feasibility_valuation.id": 1, "feasibility_valuation.name": 1, "feasibility_valuation.enable": 1,
@@ -470,6 +470,28 @@ class CompilationModel extends BaseModel {
         return await this.updateById(compilationId, {defaultLocation: location});
     }
 
+     /*
+     * 设置是否提供免费版
+     *
+     * @param {String} compilationId
+     * @param {int} location
+     * @return {Promise}
+     * */
+     async updateFreeUse(compilationId, freeUse) {
+        return await this.updateById(compilationId, {freeUse: freeUse});
+    }
+
+  /*
+    * 设置版本号
+    *
+    * @param {String} compilationId
+    * @param {String} edition
+    * @return {Promise}
+    * */
+  async setEdition(compilationId, edition){
+    return await this.updateById(compilationId, {edition: edition});
+   }
+
 }
 
 export default CompilationModel;

+ 3 - 0
modules/users/models/engineering_lib_model.js

@@ -190,6 +190,9 @@ class EngineeringLibModel extends BaseModel {
         //判断车船税
         data.vvTax_lib = this._validLib(data.vvTax_lib);
 
+        //判断递延清单库
+        data.billCode_lib = this._validLib(data.billCode_lib);
+
         //计税方式组合
         data.tax_group = this._validLib(data.tax_group);
 

+ 2 - 0
modules/users/routes/compilation_route.js

@@ -36,5 +36,7 @@ module.exports = function (app) {
 
     router.post('/changeCategory', compilationController.auth, compilationController.init, compilationController.changeCategory);
     router.post('/changeLocation', compilationController.auth, compilationController.init, compilationController.changeLocation);
+    router.post('/changeFreeUse', compilationController.auth, compilationController.init, compilationController.changeFreeUse);
+    router.post('/setEdition', compilationController.auth, compilationController.init, compilationController.setEdition);
     app.use("/compilation", router);
 };

+ 0 - 1
operation.js

@@ -1,7 +1,6 @@
 let express = require('express');
 // import schedule from 'node-schedule';
 let schedule = require("node-schedule");
-
 let config = require("./config/config.js");
 config.setupDb(process.env.NODE_ENV);
 let dbm = require("./config/db/db_manager");

+ 2 - 1
package.json

@@ -41,6 +41,7 @@
     "start": "C:\\Users\\mai\\AppData\\Roaming\\npm\\babel-node.cmd operation.js",
     "dev_server": "SET NODE_ENV=qa&& babel-node operation.js",
     "dev_server_sc": "SET NODE_ENV=qa_sc&& babel-node operation.js",
+    "dev_server_hw": "SET NODE_ENV=qa_hw&& babel-node operation.js",
     "qa_server": "SET NODE_ENV=qa&& D:\\GitHome\\ConstructionOperation\\node_modules\\.bin\\babel-node operation.js",
     "qa_sc_server": "SET NODE_ENV=qa_sc&& D:/GitHome/ConstructionOperation/node_modules/.bin/babel-node operation.js",
     "uat_server": "SET NODE_ENV=uat&& D:/GitHome/ConstructionOperation/node_modules/.bin/babel-node operation.js",
@@ -49,4 +50,4 @@
     "prod_sc_server": "SET NODE_ENV=prod_sc&& babel-node operation.js",
     "local2prod_hw_server": "SET NODE_ENV=local2prod_hw&& babel-node operation.js"
   }
-}
+}

+ 32 - 0
web/maintain/bill_code_lib/html/edit.html

@@ -0,0 +1,32 @@
+<nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0 second_header">
+    <ul class="nav nav-tabs" role="tablist">
+        <li class="nav-item">
+            <a class="nav-link active px-3" href="javascript: void(0);">递延清单库</a>
+        </li>
+    </ul>
+</nav>
+
+<div class="main">
+    <div class="content" >
+        <div class="container-fluid" >
+        <div class=" col-lg-12 p-0">
+            <nav class="navbar sticky-top navbar-toggleable-md navbar-light bg-faded tools-bar">
+                <div class="collapse navbar-collapse" id="navbarNav">
+                    <div class="tools-btn btn-group align-top">
+                        <a href="javascript:void(0)" class="btn btn-sm lock-btn-control" id="createNormal"><i class="fa fa-list-alt" aria-hidden="true"></i> 生成默认</a>
+                        <a href="javascript:void(0)" class="btn btn-sm lock-btn-control" id="format"><i class="fa fa-list-alt" aria-hidden="true"></i> 校验格式</a>
+                        <a href="javascript:void(0)" class="btn btn-sm lock-btn-control" id="save"><i class="fa fa-floppy-o" aria-hidden="true"></i> 保存</a>
+                    </div>
+                </div>
+            </nav>
+            <textarea class="form-control lock-text-control" id="templateLibs" rows="38"></textarea>
+        </div>
+        </div>
+        <input type="hidden" id="libID" value="<%= libID %>">
+        <input type="hidden" id="originalFeature" value="<%= templateLibs %>">
+    </div>
+</div>
+
+<script type="text/javascript" src="/lib/json/json2.js"></script>
+<script src="/public/web/lock_util.js"></script>
+<script type="text/javascript" src="/web/maintain/bill_code_lib/js/bill_code_edit.js"></script>

+ 147 - 0
web/maintain/bill_code_lib/html/main.html

@@ -0,0 +1,147 @@
+<div class="main">
+    <div class="content">
+        <div class="container-fluid">
+            <div class="row">
+                <div class="col-md-2">
+                    <div class="list-group mt-3">
+                        <% for (let compilation of compilationList) { %>
+                        <% if (compilation._id === 'all') { %>
+                        <a href="/billCode/main" class="list-group-item list-group-item-action <%= compilation.active %>">
+                            所有
+                        </a>
+                        <% } else { %>
+                        <a id="<%= compilation._id %>" href="/billCode/main/?filter=<%= compilation._id %>" class="list-group-item list-group-item-action <%= compilation.active %>">
+                            <%= compilation.name %>
+                        </a>
+                        <% }} %>
+                    </div>
+                </div>
+                <div class="col-md-10">
+                    <div class="warp-p2 mt-3">
+                        <table class="table table-hover table-bordered">
+                            <thead>
+                                <tr>
+                                    <th>递延清单库名称</th>
+                                    <th width="160">编办</th>
+                                    <th width="160">添加时间</th>
+                                    <th width="70">操作</th>
+                                </tr>
+                            </thead>
+                            <tbody id="showArea">
+                                <% for(let lib of templateLibs){ %>
+                                <tr class="libTr">
+                                    <td id="<%= lib.ID%>"><a href="/billCode/edit/<%= lib.ID%>?locked=true"><%= lib.name%></a></td>
+                                    <td><%= lib.compilationName%></td>
+                                    <td><%= moment(lib.createDate).format('YYYY-MM-DD')%></td>
+                                    <td>
+                                        <a class="lock-btn-control disabled" href="javascript:void(0);"
+                                            style="color: #0275d8" onclick='getFeatureLib("<%= lib.ID%>")' title="编辑"><i
+                                                class="fa fa-pencil-square-o"></i></a>
+                                        <a class="text-danger lock-btn-control disabled" href="javascript:void(0);"
+                                            onclick='showDeleteModal("<%= lib.ID%>")' title="删除"><i
+                                                class="fa fa-remove"></i></a>
+                                        <a class="lock" data-locked="true" href="javascript:void(0);" title="解锁"><i
+                                                class="fa fa-unlock-alt"></i></a>
+                                    </td>
+                                </tr>
+                                <% } %>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!--弹出添加-->
+<div class="modal fade" id="add" data-backdrop="static" style="display: none;" aria-hidden="true">
+    <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">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form id="addLibForm" method="post" action="/billCode/addLib"
+                    enctype="application/x-www-form-urlencoded21">
+                    <div class="form-group">
+                        <label>递延清单库名称</label>
+                        <input id="name" name="name" class="form-control" placeholder="输入递延清单库名称" type="text">
+                        <small class="form-text text-danger" id="nameError" style="display: none">请输入递延清单库名称。</small>
+                    </div>
+                    <div class="form-group">
+                        <label>编办名称</label>
+                        <select class="form-control" name="compilationId">
+                            <% for (let compilation of compilationList) { %>
+                            <% if (compilation.name !== '所有') { %>
+                            <option value="<%= compilation._id %>"><%= compilation.name %></option>
+                            <% }} %>
+                        </select>
+                    </div>
+                    <input type="hidden" name="userAccount" value="<%= userAccount%>">
+                </form>
+            </div>
+            <div class="modal-footer">
+                <button id="addLibs" class="btn btn-primary">新建</button>
+                <button type="button" id="cancelBtn" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!--弹出编辑-->
+<div class="modal fade" id="edit" data-backdrop="static" style="display: none;" aria-hidden="true">
+    <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">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form>
+                    <div class="form-group">
+                        <label>递延清单库名称</label>
+                        <input id="renameText" class="form-control" placeholder="输入名称" type="text" value="">
+                        <small class="form-text text-danger" id="renameError" style="display: none">请输入名称。</small>
+                        <input id="libID" type="hidden">
+                    </div>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <a id="rename" href="javascript: void(0);" class="btn btn-primary">确定</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!--弹出删除-->
+<div class="modal fade" id="del" data-backdrop="static" style="display: none;" aria-hidden="true">
+    <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">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <h5 class="text-danger">删除后无法恢复,确认是否删除?</h5>
+                <input type="hidden" id="libID_del">
+                <input type="hidden" id="delCount">
+            </div>
+            <div class="modal-footer">
+                <a id="delete" href="javascript:void(0);" class="btn btn-danger">确认</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<script src="/public/web/lock_util.js"></script>
+<script type="text/javascript" src="/web/maintain/bill_code_lib/js/bill_code.js"></script>

+ 81 - 0
web/maintain/bill_code_lib/js/bill_code.js

@@ -0,0 +1,81 @@
+/**
+ * Created by zhang on 2018/9/3.
+ */
+$(document).ready(function() {
+    // 保存按钮
+    $("#addLibs").click(async function() {
+        let name = $('#name').val();
+        if(name==''){
+            $("#nameError").show();
+            return;
+        }else {
+            $("#addLibs").attr("disabled",true);//防止重复提交
+            $("#addLibForm").submit();
+        }
+    });
+
+    $("#rename").click(async function() {
+        let libID = $("#libID").val();
+        let name = $('#renameText').val();
+        if(libID!=''){
+            if(name ==''){
+                $("#renameError").show();
+                return;
+            }else {
+                try {
+                    await ajaxPost("/billCode/saveLib",{query:{ID:libID},data:{name:name}});
+                    $("#"+libID).children("a").text(name);
+                    $("#edit").modal('hide');
+                }catch(err) {
+                    console.log(err);
+                }
+            }
+        }
+    });
+
+    $("#delete").click(async function() {
+        let libID = $("#libID_del").val();
+        let delCount = parseInt($("#delCount").val());
+        delCount = delCount+1;
+        $("#delCount").val(delCount);
+        if(delCount == 3){
+            if(libID!=""){
+                try {
+                    let result = await ajaxPost("/billCode/deleteLibByID",{ID:libID});
+                    if(result.ok){
+                        $("#"+libID).parent(".libTr").remove();
+                    }
+                    $("#del").modal('hide');
+                }catch (err){
+                    console.log(err);
+                }
+            }
+        }
+    });
+
+    // 锁定、解锁
+    $('.lock').click(function () {
+        lockUtil.handleLockClick($(this));
+    });
+});
+
+async function getFeatureLib (ID) {
+    try {
+        const lib = await ajaxPost("/billCode/findLib",{ID});
+        if(lib){
+            $("#renameText").val(lib.name);
+            $("#libID").val(ID);
+            $("#edit").modal({show:true});
+        }else {
+            alert("没有找到该结构分部");
+        }
+    }catch (err){
+        console.log(err);
+    }
+}
+
+function showDeleteModal(ID){
+    $("#libID_del").val(ID);
+    $("#delCount").val(0);
+    $("#del").modal({show:true});
+}

+ 71 - 0
web/maintain/bill_code_lib/js/bill_code_edit.js

@@ -0,0 +1,71 @@
+/**
+ * Created by zhang on 2018/9/3.
+ */
+
+$(document).ready(function () {
+    const locked = lockUtil.getLocked();
+    lockUtil.lockTools($(document.body), locked);
+    try {
+        let tem = sortJson(JSON.parse($("#originalFeature").val()));
+        $("#templateLibs").val(JSON.stringify(tem.data,null,4));
+    }catch (err){
+        console.log(err);
+    }
+
+   $("#format").click( function() {
+       try {
+           let jsonText =  $("#templateLibs").val();
+           $("#templateLibs").val(JSON.stringify(JSON.parse(jsonText),null,4));
+       }catch (err){
+           console.log(err);
+           alert("输入的JSON格式有误,请重新输入!");
+       }
+   });
+    $("#save").click(async function() {
+        try {
+            let libID = $("#libID").val();
+            let jsonText =  $("#templateLibs").val();
+            if(jsonText.indexOf("'")!=-1){
+                alert("输入的格式不能包含 ' 位于:"+jsonText.substr(jsonText.indexOf("'")-15,18));
+                return;
+            }
+            let newFeature = await ajaxPost("/billCode/saveLib",{query:{ID:libID},data:{data:JSON.parse(jsonText)}});
+        }catch (err){
+            console.log(err);
+            alert("保存失败,请查看输入数据");
+        }
+    });
+
+    $("#createNormal").click( function() {
+        let explorer = [ 
+            {
+                "code" : "202-2-1",
+                "name" : "路面厚",
+                "formatName" : "挖除%smm以内厚水泥混凝土路面",
+                "formatName2" : "挖除%smm厚水泥混凝土路面",
+                "unit":"m2",
+                "subArea":false,
+                "startValue":50,
+                "stepValue":50,
+                "startCode":2
+            },
+            {
+                "code" : "202-2-2",
+                "name" : "路面厚",
+                "formatName" : "挖除%smm以内厚沥青混凝土路面",
+                "formatName2" : "挖除%smm厚沥青混凝土路面",
+                "unit":"m2",
+                "subArea":true,
+                "startValue":20,
+                "stepValue":10,
+                "startCode":2
+            }
+        ];
+        try {
+            let jsonText =  JSON.stringify(explorer);
+            $("#templateLibs").val(JSON.stringify(JSON.parse(jsonText),null,4));
+        }catch (err){
+            console.log(err);
+        }
+    })
+});

+ 275 - 191
web/maintain/report/css/main.css

@@ -1,296 +1,380 @@
 /*building SAAS 0.1*/
 /*bootstrap 初始化*/
 body {
-    font-size: 0.9rem
+  font-size: 0.9rem;
 }
 .dropdown-menu {
-    font-size: 0.9rem
+  font-size: 0.9rem;
 }
 /*自定义css*/
 .header {
-    background: #e1e1e1
+  background: #e1e1e1;
 }
 .header .header-logo {
-    background: #ff6501;
-    color: #fff;
-    float: left;
-    padding-top: .25rem;
-    padding-bottom: .25rem;
-    margin-right: 1rem;
-    font-size: 1.25rem;
-    line-height: inherit
-}
-.top-msg{
+  background: #ff6501;
+  color: #fff;
+  float: left;
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  margin-right: 1rem;
+  font-size: 1.25rem;
+  line-height: inherit;
+}
+.top-msg {
   position: fixed;
-  top:0;
-  width:100%;
-  z-index: 999
-}
-.in-1{padding-left:0rem!important}
-.in-2{padding-left:1rem!important}
-.in-3{padding-left:1.5rem!important}
-.in-4{padding-left:2rem!important}
-.in-5{padding-left:2.5rem!important}
-.in-6{padding-left:3rem!important}
+  top: 0;
+  width: 100%;
+  z-index: 999;
+}
+.in-1 {
+  padding-left: 0rem !important;
+}
+.in-2 {
+  padding-left: 1rem !important;
+}
+.in-3 {
+  padding-left: 1.5rem !important;
+}
+.in-4 {
+  padding-left: 2rem !important;
+}
+.in-5 {
+  padding-left: 2.5rem !important;
+}
+.in-6 {
+  padding-left: 3rem !important;
+}
 .main {
-    position: relative;
-    background: #f7f7f9;
+  position: relative;
+  background: #f7f7f9;
 }
 .main-nav {
-    position: absolute;
-    text-align: center;
-    z-index: 999;
-    padding: 2px 0 0 2px
+  position: absolute;
+  text-align: center;
+  z-index: 999;
+  padding: 2px 0 0 2px;
 }
 .main-nav .nav a {
-    display: block;
-    width: 28px;
-    text-align: center;
-    line-height: 18px;
-    color: #999;
-    padding: 10px 0;
-    border-right: 1px solid #ccc;
+  display: block;
+  width: 28px;
+  text-align: center;
+  line-height: 18px;
+  color: #999;
+  padding: 10px 0;
+  border-right: 1px solid #ccc;
 }
 .main-nav .nav a:hover {
-    background: #fff;
-    color: #333;
-    text-decoration: none;
+  background: #fff;
+  color: #333;
+  text-decoration: none;
 }
 .main-nav .nav a.active {
-    border: 1px solid #ccc;
-    border-right: 1px solid #fff;
-    background: #fff;
-    color: #333
+  border: 1px solid #ccc;
+  border-right: 1px solid #fff;
+  background: #fff;
+  color: #333;
 }
 .content {
-    background: #fff
+  background: #fff;
 }
 .tools-btn {
-    height: 30px;
-    line-height: 30px;
+  height: 30px;
+  line-height: 30px;
 }
 .toolsbar .tools-btn.btn:hover {
-    background: #f7f7f9;
+  background: #f7f7f9;
 }
 .main-side {
-    border-right: 1px solid #ccc;
-    overflow-y: auto;
+  border-right: 1px solid #ccc;
+  overflow-y: auto;
 }
 .main-side .tab-bar {
-    padding:5px 10px;
-    height:38px;
-    position:fixed;
+  padding: 5px 10px;
+  height: 38px;
+  position: fixed;
 }
 .main-side .tab-content {
-    margin-top: 38px
+  margin-top: 38px;
 }
-.top-content, .fluid-content {
-    overflow: hidden;
-    border-bottom: 1px solid #ccc;
+.top-content,
+.fluid-content {
+  overflow: hidden;
+  border-bottom: 1px solid #ccc;
 }
 .warp-p2 {
-    padding: 2px
+  padding: 2px;
 }
-.bottom-content .nav,.top-content .nav {
-    background: #f7f7f9;
-    padding:0 0 0 2px
+.bottom-content .nav,
+.top-content .nav {
+  background: #f7f7f9;
+  padding: 0 0 0 2px;
 }
-.bottom-content .nav-tabs .nav-link, .side-tabs .nav-tabs .nav-link,.top-content .nav-tabs .nav-link {
-    border-radius: 0;
-    padding: 0.2em 0.5em
+.bottom-content .nav-tabs .nav-link,
+.side-tabs .nav-tabs .nav-link,
+.top-content .nav-tabs .nav-link {
+  border-radius: 0;
+  padding: 0.2em 0.5em;
 }
 .side-tabs .nav-tabs .nav-item {
-  z-index: 999
+  z-index: 999;
 }
 .side-tabs .nav-tabs {
-    border-bottom: none;
-    margin-bottom: -1px
+  border-bottom: none;
+  margin-bottom: -1px;
 }
 .side-tabs .nav-tabs .nav-link {
-    border-radius: 0;
-    padding: 0em 0.5em;
-    line-height: 30px;
-    z-index: 999
+  border-radius: 0;
+  padding: 0em 0.5em;
+  line-height: 30px;
+  z-index: 999;
 }
 .bottom-content .nav-tabs .nav-link.active {
-    border-top: 1px solid #f7f7f9
+  border-top: 1px solid #f7f7f9;
 }
 .side-tabs .nav-tabs .nav-link.active {
-    border-top: none;
-    border-bottom:1px solid #fff
+  border-top: none;
+  border-bottom: 1px solid #fff;
 }
-.side-tabs a.active, .sub-nav a.active {
-    background: #ccc
+.side-tabs a.active,
+.sub-nav a.active {
+  background: #ccc;
 }
 .poj-manage {
-    background: #fff
+  background: #fff;
 }
 .slide-sidebar {
-    border-left: 1px solid #E1E1E1;
-    box-shadow: 0px 15px 15px rgba(0, 0, 0, 0.1);
-    background: none repeat scroll 0% 0% #ffffff;
-    overflow: hidden;
-    position: absolute;
-    right: 0px;
-    top: 0;
-    z-index: 999;
-    width: 0px;
+  border-left: 1px solid #e1e1e1;
+  box-shadow: 0px 15px 15px rgba(0, 0, 0, 0.1);
+  background: none repeat scroll 0% 0% #ffffff;
+  overflow: hidden;
+  position: absolute;
+  right: 0px;
+  top: 0;
+  z-index: 999;
+  width: 0px;
 }
 .new-msg {
-    -webkit-animation: tada 1s infinite .2s ease both;
-    -moz-animation: tada 1s infinite .2s ease both;
+  -webkit-animation: tada 1s infinite 0.2s ease both;
+  -moz-animation: tada 1s infinite 0.2s ease both;
 }
 @-webkit-keyframes tada {
-    0% {
-        -webkit-transform: scale(1)
-    }
-    10%, 20% {
-        -webkit-transform: scale(0.9) rotate(-3deg)
-    }
-    30%, 50%, 70%, 90% {
-        -webkit-transform: scale(1.1) rotate(3deg)
-    }
-    40%, 60%, 80% {
-        -webkit-transform: scale(1.1) rotate(-3deg)
-    }
-    100% {
-        -webkit-transform: scale(1) rotate(0)
-    }
+  0% {
+    -webkit-transform: scale(1);
+  }
+  10%,
+  20% {
+    -webkit-transform: scale(0.9) rotate(-3deg);
+  }
+  30%,
+  50%,
+  70%,
+  90% {
+    -webkit-transform: scale(1.1) rotate(3deg);
+  }
+  40%,
+  60%,
+  80% {
+    -webkit-transform: scale(1.1) rotate(-3deg);
+  }
+  100% {
+    -webkit-transform: scale(1) rotate(0);
+  }
 }
 @-moz-keyframes tada {
-    0% {
-        -moz-transform: scale(1)
-    }
-    10%, 20% {
-        -moz-transform: scale(0.9) rotate(-3deg)
-    }
-    30%, 50%, 70%, 90% {
-        -moz-transform: scale(1.1) rotate(3deg)
-    }
-    40%, 60%, 80% {
-        -moz-transform: scale(1.1) rotate(-3deg)
-    }
-    100% {
-        -moz-transform: scale(1) rotate(0)
-    }
+  0% {
+    -moz-transform: scale(1);
+  }
+  10%,
+  20% {
+    -moz-transform: scale(0.9) rotate(-3deg);
+  }
+  30%,
+  50%,
+  70%,
+  90% {
+    -moz-transform: scale(1.1) rotate(3deg);
+  }
+  40%,
+  60%,
+  80% {
+    -moz-transform: scale(1.1) rotate(-3deg);
+  }
+  100% {
+    -moz-transform: scale(1) rotate(0);
+  }
 }
 .has-danger {
-    -webkit-animation: shake 1s .2s ease both;
-    -moz-animation: shake 1s .2s ease both;
-    animation: shake 1s .2s ease both;
+  -webkit-animation: shake 1s 0.2s ease both;
+  -moz-animation: shake 1s 0.2s ease both;
+  animation: shake 1s 0.2s ease both;
 }
 @-webkit-keyframes shake {
-    0%, 100% {
-        -webkit-transform: translateX(0);
-    }
-    10%, 30%, 50%, 70%, 90% {
-        -webkit-transform: translateX(-10px);
-    }
-    20%, 40%, 60%, 80% {
-        -webkit-transform: translateX(10px);
-    }
+  0%,
+  100% {
+    -webkit-transform: translateX(0);
+  }
+  10%,
+  30%,
+  50%,
+  70%,
+  90% {
+    -webkit-transform: translateX(-10px);
+  }
+  20%,
+  40%,
+  60%,
+  80% {
+    -webkit-transform: translateX(10px);
+  }
 }
 @-moz-keyframes shake {
-    0%, 100% {
-        -moz-transform: translateX(0);
-    }
-    10%, 30%, 50%, 70%, 90% {
-        -moz-transform: translateX(-10px);
-    }
-    20%, 40%, 60%, 80% {
-        -moz-transform: translateX(10px);
-    }
+  0%,
+  100% {
+    -moz-transform: translateX(0);
+  }
+  10%,
+  30%,
+  50%,
+  70%,
+  90% {
+    -moz-transform: translateX(-10px);
+  }
+  20%,
+  40%,
+  60%,
+  80% {
+    -moz-transform: translateX(10px);
+  }
 }
 @keyframes shake {
-    0%, 100% {
-        transform: translateX(0);
-    }
-    10%, 30%, 50%, 70%, 90% {
-        transform: translateX(-10px);
-    }
-    20%, 40%, 60%, 80% {
-        transform: translateX(10px);
-    }
+  0%,
+  100% {
+    transform: translateX(0);
+  }
+  10%,
+  30%,
+  50%,
+  70%,
+  90% {
+    transform: translateX(-10px);
+  }
+  20%,
+  40%,
+  60%,
+  80% {
+    transform: translateX(10px);
+  }
 }
 .bottom-content {
-    height: 370px;
-    overflow: hidden;
+  height: 370px;
+  overflow: hidden;
 }
-.bottom-content .tab-content .main-data-bottom{
-    height: 340px;
-    overflow: auto;
+.bottom-content .tab-content .main-data-bottom {
+  height: 340px;
+  overflow: auto;
 }
 .form-signin {
-    max-width: 500px;
-    margin: 150px auto;
+  max-width: 500px;
+  margin: 150px auto;
 }
-.poj-list, .side-content {
-    overflow: auto;
+.poj-list,
+.side-content {
+  overflow: auto;
 }
 .poj-list span.poj-icon {
-  padding-right:10px;
-  color:#ccc
+  padding-right: 10px;
+  color: #ccc;
 }
-.print-toolsbar{
-  padding:5px
+.print-toolsbar {
+  padding: 5px;
 }
 .print-toolsbar .panel {
-  display:inline-block;
-  vertical-align:top;
-  background:#f7f7f9
+  display: inline-block;
+  vertical-align: top;
+  background: #f7f7f9;
 }
-.print-toolsbar .panel .panel-foot{
+.print-toolsbar .panel .panel-foot {
   text-align: center;
-  font-size: 12px
+  font-size: 12px;
 }
 .print-list {
-  border-right:1px solid #ccc
+  border-right: 1px solid #ccc;
 }
 .print-list .form-list {
-  overflow: auto
+  overflow: auto;
 }
-.print-list .list-tools{
-  height:50px;
-  padding:10px 0;
-  border-bottom:1px solid #f2f2f2
+.print-list .list-tools {
+  height: 50px;
+  padding: 10px 0;
+  border-bottom: 1px solid #f2f2f2;
 }
 .pageContainer {
   background: #ededed;
-  text-align: center
+  text-align: center;
 }
-.pageContainer .page{
-  border:9px solid transparent;
+.pageContainer .page {
+  border: 9px solid transparent;
   display: inline-block;
 }
-.pageContainer .page img{
-  width:inherit;
+.pageContainer .page img {
+  width: inherit;
   height: inherit;
 }
-.codeList{
-    max-height: 200px;
-    overflow:auto;
+.codeList {
+  max-height: 200px;
+  overflow: auto;
 }
-.main-data-top,.main-data-bottom,.main-data,.main-data-h{
+.main-data-top,
+.main-data-bottom,
+.main-data,
+.main-data-h {
   overflow: auto;
 }
 .modal-fixed-height {
-    height:400px;
-    overflow-y:auto;
+  height: 400px;
+  overflow-y: auto;
 }
 .form-view {
-    border-left:1px solid #ccc;
+  border-left: 1px solid #ccc;
 }
 .ztree {
-  border-style:solid; 
-  border-width:1px; 
-  border-color:#000;
+  border-style: solid;
+  border-width: 1px;
+  border-color: #000;
 }
 .ztree-warp {
-  height:200px;
+  height: 200px;
   overflow: auto;
 }
-.sub-button{
-  position:sticky;
-  bottom:0;
-  left:0
+.sub-button {
+  position: sticky;
+  bottom: 0;
+  left: 0;
+}
+
+.valuationSelector {
+  cursor: pointer;
+  position: absolute;
+  left: 105px;
+  top: 38px;
+  border: 1px solid #d9d9d9;
+  display: none;
+}
+.mutiSelector {
+  width: 130px;
+  margin: 0;
+  padding: 0 10px;
+}
+.mutiSelector li {
+  list-style: none;
+  font-size: 16px;
+}
+.mutiSelector .checked {
+  background-color: #0275d8;
+  color: #fff;
+}
+.mutiSelector li:hover {
+  background-color: #0275d8;
+  color: #fff;
+  cursor: pointer;
 }

+ 29 - 2
web/maintain/report/html/rpt_tpl_dtl_info.html

@@ -58,9 +58,24 @@
                     <div class="input-group-addon">额外标记</div>
                     <select class="form-control input-sm" id="element_flags_select" onchange="zTreeOprObj.onChangeFlag('taxType', this)"><option value ="NA">N/A</option><option value ="1">一般计税</option><option value ="2">简易计税</option></select>
                 </div>
-                <div class="input-group col-2">
+                <div class="input-group col-4">
                     <div class="input-group-addon">工程类型</div>
-                    <select class="form-control input-sm" id="element_prjFlags_select" onchange="zTreeOprObj.onChangeFlag('valuationType', this)"><option value ="NA">N/A</option><option value ="suggestion">建议估算</option><option value ="feasibility">可行性估算</option><option value ="rough">概算</option><option value ="bill">预算</option><option value ="ration">工程量清单</option></select>
+                    <input class="form-control input-sm" id="element_prjFlags_select"
+                        onchange="zTreeOprObj.onChangeFlag('valuationType', this)" style="display: none;">
+                    <input class="form-control input-sm" id="element_prjFlags_selectStr" readonly>
+                    <div id="valuationSelector" class="valuationSelector">
+                        <ul class="mutiSelector">
+                            <li id="valuationSelector_suggestion" value="suggestion">建议估算</li>
+                            <li id="valuationSelector_feasibility" value="feasibility">可行性估算</li>
+                            <li id="valuationSelector_rough" value="rough">概算</li>
+                            <li id="valuationSelector_bill" value="bill">预算</li>
+                            <li id="valuationSelector_three_bill_budget" value="three_bill_budget">三级清单预算</li>
+                            <li id="valuationSelector_ration" value="ration">清单预算</li>
+                            <li id="valuationSelector_changeBudget" value="changeBudget">变更预算</li>
+                            <li id="valuationSelector_settlement" value="settlement">结算</li>
+                        </ul>
+                    
+                    </div>
                 </div>
                 <div class="input-group col-3">
                     <div class="input-group-addon">报表汇总类型</div>
@@ -71,6 +86,18 @@
                     <select class="form-control input-sm" id="element_sumLv_flags" onchange="zTreeOprObj.onChangeFlag('sumLevelType', this)"><option value ="NA">N/A</option><option value ="construct">建设项目级别</option><option value ="Single">单项工程级别</option><option value ="custom">用户自选工程</option></select>
                 </div>
             </div>
+               
+        </div>
+        <div>
+            <div class="input-group col-3">
+                <div class="input-group-addon">审核对比数据级别</div>
+                <select id="element_contrastType_select" class="form-control" onchange="zTreeOprObj.onChangeFlag('contrastType', this)">
+                    <option value="NA">N/A</option>
+                    <option value="chapter">项目节</option>
+                    <option value="bill">清单</option>
+                    <option value="quantities">工程量明细</option>
+                </select>
+            </div>
         </div>
     </div>
 </div>

+ 239 - 145
web/maintain/report/js/rpt_tpl_main.js

@@ -15,8 +15,23 @@ const
     NODE_LEVEL_COMPILATION_NEW = 1,
     NODE_LEVEL_USER = 0;
 
+
+// 工程类型枚举值
+const valuationSelectorMap = {
+    valuationSelector_NA: 'N/A',
+    valuationSelector_suggestion: '建议估算',
+    valuationSelector_feasibility: '可行性估算',
+    valuationSelector_rough: '概算',
+    valuationSelector_bill: '预算',
+    valuationSelector_three_bill_budget: '三级清单预算',
+    valuationSelector_ration: '清单预算',
+    valuationSelector_changeBudget: '变更预算',
+    valuationSelector_settlement: '结算'
+}
+
+
 let rptTplObj = {
-    iniPage: function() {
+    iniPage: function () {
         zTreeOprObj.getCompilationList();
         rpt_tpl_cfg_helper.getReportTplCfg();
         selectableFiledTreeOprObj.iniTree();
@@ -33,23 +48,23 @@ let zTreeOprObj = {
     moveSrcTopNode: null,
     dupTplIds: null,
     hasRefreshedDupRefIds: false,
-    getCompilationList: function(){
+    getCompilationList: function () {
         let me = zTreeOprObj, params = {};
-        CommonAjax.postEx("report_tpl_api/getCompilationList", params, 20000, true, function(result){
-                //console.log(result);
-                for (let item of result) {
-                    // if (item.is_release) {
-                        $("#compilations").append("<option value='" + item._id + "'>" + item.name + "</option>");
-                    // }
-                }
-                // me.getReportTemplateTree($("#compilations").get(0));
-                me.getReportTemplateTreeEx($("#compilations").get(0));
-            }, null, null
+        CommonAjax.postEx("report_tpl_api/getCompilationList", params, 20000, true, function (result) {
+            //console.log(result);
+            for (let item of result) {
+                // if (item.is_release) {
+                $("#compilations").append("<option value='" + item._id + "'>" + item.name + "</option>");
+                // }
+            }
+            // me.getReportTemplateTree($("#compilations").get(0));
+            me.getReportTemplateTreeEx($("#compilations").get(0));
+        }, null, null
         );
     },
-    refreshNodes: function() {
+    refreshNodes: function () {
         let me = this;
-        let private_setupIsParent = function(node){
+        let private_setupIsParent = function (node) {
             // if (node.nodeType === RT.NodeType.NODE || node.level === 0) {
             if (node.nodeType === RT.NodeType.NODE || node.level <= NODE_LEVEL_COMPILATION_NEW) {
                 node.isParent = true;
@@ -68,7 +83,7 @@ let zTreeOprObj = {
         }
         me.treeObj.refresh();
     },
-    removeTreeRootNode: function(rawNode, isAsync, callback, failCallback) {
+    removeTreeRootNode: function (rawNode, isAsync, callback, failCallback) {
         let params = {};
         params.compilationId = rawNode.compilationId;
         params.engineerId = rawNode.engineerId;
@@ -76,13 +91,13 @@ let zTreeOprObj = {
         params.isPhysically = true;
         CommonAjax.postEx("report_tpl_api/removeTreeRootNode", params, 5000, isAsync, callback, failCallback, null);
     },
-    copyReportTemplate: function(orgID, newID, isAsync, callback, failCallback) {
+    copyReportTemplate: function (orgID, newID, isAsync, callback, failCallback) {
         let params = {};
         params.orgRptTplId = orgID;
         params.newRptTplId = newID;
         CommonAjax.postEx("report_tpl_api/copyRptTpl", params, 5000, isAsync, callback, failCallback, null);
     },
-    updateTreeRootNode: function(rawNode, isAsync, callback, failCallback) {
+    updateTreeRootNode: function (rawNode, isAsync, callback, failCallback) {
         let params = {};
         params.doc = rawNode;
         CommonAjax.postEx("report_tpl_api/updateTreeRootNode", params, 5000, isAsync, callback, failCallback, null);
@@ -103,7 +118,7 @@ let zTreeOprObj = {
         params.subNode = subNode;
         CommonAjax.postEx("report_tpl_api/updateSubLevelOneNode", params, 5000, isAsync, callback, failCallback, null);
     },
-    createIniNode: function() {
+    createIniNode: function () {
         return {
             nodeType: RT.NodeType.TEMPLATE,
             refId: -1,
@@ -112,7 +127,7 @@ let zTreeOprObj = {
             items: null
         };
     },
-    buildRootNodeDoc: function(topNode, excludeNode) {
+    buildRootNodeDoc: function (topNode, excludeNode) {
         let me = this, rst = null;
         if (topNode) {
             rst = {
@@ -128,7 +143,7 @@ let zTreeOprObj = {
         }
         return rst;
     },
-    buildSubRootNodeDoc: function(subNode) {
+    buildSubRootNodeDoc: function (subNode) {
         let me = this, rst = null;
         if (subNode) {
             let isReleased = false;
@@ -177,18 +192,18 @@ let zTreeOprObj = {
         return itemRst;
     },
 
-    addHoverDom: function(treeId, treeNode) {
+    addHoverDom: function (treeId, treeNode) {
         let me = zTreeOprObj, sObj = $("#" + treeNode.tId + "_span");
-        if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length > 0 || treeNode.nodeType === RT.NodeType.TEMPLATE) return;
+        if (treeNode.editNameFlag || $("#addBtn_" + treeNode.tId).length > 0 || treeNode.nodeType === RT.NodeType.TEMPLATE) return;
         if (treeNode.level === 0) {
             let addStr = "<span class='button star' id='addBtn_" + treeNode.tId + "' title='新增编办类型' onfocus='this.blur();'></span>";
             sObj.after(addStr);
-            let btn = $("#addBtn_"+treeNode.tId);
-            if (btn) btn.bind("click", function(){
+            let btn = $("#addBtn_" + treeNode.tId);
+            if (btn) btn.bind("click", function () {
                 let rawNode = me.createIniComilationNode();
                 if (!me.chkIfDupCompilationNode(rawNode, treeNode)) {
                     rawNode.userId = treeNode.userId;
-                    me.addNewNodeEx(rawNode, function(rst){
+                    me.addNewNodeEx(rawNode, function (rst) {
                         if (rst) {
                             let newNodes = [], isSilent = false;
                             rawNode.isParent = true;
@@ -218,8 +233,8 @@ let zTreeOprObj = {
         } else {
             let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增子目录' onfocus='this.blur();'></span>";
             sObj.after(addStr);
-            let btn = $("#addBtn_"+treeNode.tId);
-            if (btn) btn.bind("click", function(){
+            let btn = $("#addBtn_" + treeNode.tId);
+            if (btn) btn.bind("click", function () {
                 me.getNewNodeID(1, function (newNodeID) {
                     let rawNode = me.createIniNode();
                     rawNode.nodeType = RT.NodeType.NODE;
@@ -242,7 +257,7 @@ let zTreeOprObj = {
                         me.treeObj.addNodes(treeNode, insertIdx, newNodes, isSilent);
                         let tn = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
                         let newTopNode = me.buildRootNodeDoc(tn);
-                        me.updateTreeRootNode(newTopNode, true, function(rst){
+                        me.updateTreeRootNode(newTopNode, true, function (rst) {
                             if (!(rst)) {
                                 alert("新增节点失败!");
                             }
@@ -253,8 +268,8 @@ let zTreeOprObj = {
             });
             addStr = "<span class='button blue_core' id='addBtn2_" + treeNode.tId + "' title='新增报表模板' onfocus='this.blur();'></span>";
             sObj.after(addStr);
-            btn = $("#addBtn2_"+treeNode.tId + "");
-            if (btn) btn.bind("click", function(){
+            btn = $("#addBtn2_" + treeNode.tId + "");
+            if (btn) btn.bind("click", function () {
                 // let me = zTreeOprObj;
                 if (treeNode.nodeType === RT.NodeType.NODE || treeNode.level === NODE_LEVEL_COMPILATION_NEW) {
                     me.getNewNodeID(1, function (newNodeID) {
@@ -268,7 +283,7 @@ let zTreeOprObj = {
                         me.treeObj.addNodes(treeNode, -1, newNodes, isSilent);
                         let tn = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
                         let topNode = me.buildRootNodeDoc(tn);
-                        me.updateTreeRootNode(topNode, true, function(rst){
+                        me.updateTreeRootNode(topNode, true, function (rst) {
                             if (!(rst)) {
                                 alert("新增空白模板失败!");
                             }
@@ -279,11 +294,11 @@ let zTreeOprObj = {
             });
         }
     },
-    removeHoverDom: function(treeId, treeNode) {
-        $("#addBtn_"+treeNode.tId).unbind().remove();
-        $("#addBtn2_"+treeNode.tId).unbind().remove();
+    removeHoverDom: function (treeId, treeNode) {
+        $("#addBtn_" + treeNode.tId).unbind().remove();
+        $("#addBtn2_" + treeNode.tId).unbind().remove();
     },
-    addNewNodeEx: function(rawNode, callback, failCallback) {
+    addNewNodeEx: function (rawNode, callback, failCallback) {
         let params = {};
         params.doc = rawNode;
         CommonAjax.postEx("report_tpl_api/createTreeRootNode", params, 5000, true, callback, failCallback, null);
@@ -292,7 +307,7 @@ let zTreeOprObj = {
         let me = zTreeOprObj;
         let topPNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
         let newTopNode = me.buildRootNodeDoc(topPNode);
-        me.updateTreeRootNode(newTopNode, true, function(rst){
+        me.updateTreeRootNode(newTopNode, true, function (rst) {
             if (!(rst)) {
                 alert("修改发布状态失败!");
             }
@@ -363,7 +378,7 @@ let zTreeOprObj = {
                 treeNodes[0].ID = newNodeID;
                 if (confirm("是否引用相同的报表模板?")) {
                     newTopNode = me.buildRootNodeDoc(targetTopNode);
-                    me.updateTreeRootNode(newTopNode, false, function(goodRst){
+                    me.updateTreeRootNode(newTopNode, false, function (goodRst) {
                         canContinue = true;
                         if (treeNodes[0].rptTpl) {
                             treeNodes[0].rptTpl.ID = newNodeID;
@@ -372,7 +387,7 @@ let zTreeOprObj = {
                         me.chkAndSetDupRefTplIds(me.treeObj.getNodes(), null);
                         me.treeObj.refresh();
                         me.chkAndRreshRefTpl();
-                    }, function(badRst){
+                    }, function (badRst) {
                         displayMessage("更新模板节点失败!", "red", 2000);
                         // console.log(badRst.toString());
                         console.log(badRst);
@@ -381,8 +396,8 @@ let zTreeOprObj = {
                     treeNodes[0].refId = newNodeID;
                     // targetNode.refId = newNodeID; //targetNode可以是父节点也可以是兄弟节点,没必要引用相同的tplID
                     newTopNode = me.buildRootNodeDoc(targetTopNode);
-                    me.copyReportTemplate(orgID, newNodeID, true, function(goodResult){
-                        me.updateTreeRootNode(newTopNode, true, function(goodRst){
+                    me.copyReportTemplate(orgID, newNodeID, true, function (goodResult) {
+                        me.updateTreeRootNode(newTopNode, true, function (goodRst) {
                             canContinue = true;
                             // treeObj.updateNode(nodes[0]);
                             zTreeOprObj.treeObj.updateNode(treeNodes[0]);
@@ -393,12 +408,12 @@ let zTreeOprObj = {
                             me.chkAndSetDupRefTplIds(me.treeObj.getNodes(), null);
                             me.treeObj.refresh();
                             me.chkAndRreshRefTpl();
-                        }, function(badRst){
+                        }, function (badRst) {
                             displayMessage("更新模板节点失败!", "red", 2000);
                             // console.log(badRst.toString());
                             console.log(badRst);
                         });
-                    }, function(badResult){
+                    }, function (badResult) {
                         displayMessage("Copy请求失败!", "red", 2000);
                         // console.log(badResult.toString());
                         console.log(badResult);
@@ -410,19 +425,19 @@ let zTreeOprObj = {
             // }
         } else {
             newTopNode = me.buildRootNodeDoc(targetTopNode);
-            me.updateTreeRootNode(newTopNode, false, function(rst){
+            me.updateTreeRootNode(newTopNode, false, function (rst) {
                 canContinue = true;
                 me.currentNode = treeNodes[0];
-            }, function(badResult){
+            }, function (badResult) {
                 displayMessage("移动请求失败!", "red", 2000);
                 console.log(badResult.toString());
                 canContinue = false;
             });
             if (canContinue && !isCopy && me.moveSrcTopNode) {
                 let newSrcTopNode = me.buildRootNodeDoc(me.moveSrcTopNode);
-                me.updateTreeRootNode(newSrcTopNode, true, function(rst){
+                me.updateTreeRootNode(newSrcTopNode, true, function (rst) {
                     // canContinue = true;
-                }, function(badResult){
+                }, function (badResult) {
                     displayMessage("移动请求失败!", "red", 2000);
                     canContinue = true;
                 });
@@ -430,7 +445,7 @@ let zTreeOprObj = {
             me.moveSrcTopNode = null;
         }
     },
-    addReportTemplate: function(newUsers) {
+    addReportTemplate: function (newUsers) {
         let me = zTreeOprObj, params = {};
         params.compilationId = $("#compilations").get(0).value;
         params.userId = [];
@@ -444,11 +459,11 @@ let zTreeOprObj = {
             allEngIds.push(item.value);
         }
         params.engineerId = allEngIds;
-        CommonAjax.postEx("report_tpl_api/getRptTplTree", params, 20000, true, function(result){
-            result.sort(function(item1, item2){
+        CommonAjax.postEx("report_tpl_api/getRptTplTree", params, 20000, true, function (result) {
+            result.sort(function (item1, item2) {
                 let rst = 0;
                 if (item1.userId === item2.userId) {
-                    rst = (item1.engineerId > item2.engineerId)?1:((item1.engineerId < item2.engineerId)?-1:0);
+                    rst = (item1.engineerId > item2.engineerId) ? 1 : ((item1.engineerId < item2.engineerId) ? -1 : 0);
                 } else {
                     if (item1.userId === "-100") {
                         rst = 1
@@ -462,7 +477,7 @@ let zTreeOprObj = {
                             if (idx1 >= 0 && idx2 >= 0) {
                                 break;
                             }
-                            rst = (idx1 > idx2)?1:((idx1 < idx2)?-1:0);
+                            rst = (idx1 > idx2) ? 1 : ((idx1 < idx2) ? -1 : 0);
                         }
                     }
                 }
@@ -472,7 +487,7 @@ let zTreeOprObj = {
             let allTopTplNodes = [];
             for (let user of newUsers) {
                 allTopUserIdNodes.push(user.userId);
-                allTopTplNodes.push({userId: user.userId, name: user.real_name, items: [], isParent: true});
+                allTopTplNodes.push({ userId: user.userId, name: user.real_name, items: [], isParent: true });
             }
             for (let item of result) {
                 let uidx = allTopUserIdNodes.indexOf(item.userId);
@@ -568,8 +583,8 @@ let zTreeOprObj = {
     getReportTemplateTreeEx: function (compilationSelect) {
         let me = zTreeOprObj, params = {};
         params.compilationId = compilationSelect.value;
-        CommonAjax.postEx("report_tpl_api/getTplTreeByCompilation", params, 20000, true, function(result){
-            result.sort(function(item1, item2){
+        CommonAjax.postEx("report_tpl_api/getTplTreeByCompilation", params, 20000, true, function (result) {
+            result.sort(function (item1, item2) {
                 let rst = 0;
                 if (item1.userId === "-100") {
                     rst = -1;
@@ -580,7 +595,7 @@ let zTreeOprObj = {
             });
             // me.chkAndSetDupRefTplIds(result);
             // console.log(dupRefIds);
-            let allTopTplNodes = [{userId: "-100", name: "公共模板", items:[], isParent: true, refId: ""}];
+            let allTopTplNodes = [{ userId: "-100", name: "公共模板", items: [], isParent: true, refId: "" }];
             if (result.length > 0) {
                 if (!result[0].hasOwnProperty("refId")) {
                     result[0].refId = "";
@@ -600,7 +615,7 @@ let zTreeOprObj = {
                     for (let itemIdx = 1; itemIdx < result.length; itemIdx++) {
                         let item = result[itemIdx];
                         if (item.userId === user._id) {
-                            allTopTplNodes.push({userId: user.userId, name: user.real_name, items: [], isParent: true, refId: ""});
+                            allTopTplNodes.push({ userId: user.userId, name: user.real_name, items: [], isParent: true, refId: "" });
                             allTopTplNodes[allTopTplNodes.length - 1].items.push(result[itemIdx]);
                             break;
                         }
@@ -653,11 +668,11 @@ let zTreeOprObj = {
         }
         return rst;
     },
-    createIniComilationNode: function() {
+    createIniComilationNode: function () {
         //在新的需求下,无需工程id
         let rst = {
             compilationId: $("#compilations").get(0).selectedOptions[0].value,
-            userId: (userAccount ===  'admin')?("-100"):userID,
+            userId: (userAccount === 'admin') ? ("-100") : userID,
             properties: [],
             released: true,
             isDeleted: false,
@@ -666,7 +681,7 @@ let zTreeOprObj = {
         };
         return rst;
     },
-    onBeforeRemove: function(treeId, treeNode){
+    onBeforeRemove: function (treeId, treeNode) {
         let canRemove = false;
         if (treeNode.level > NODE_LEVEL_USER) {
             if (!(treeNode.items) || treeNode.items.length < 1) {
@@ -679,19 +694,19 @@ let zTreeOprObj = {
         }
         return canRemove;
     },
-    onRemove: function(e, treeId, treeNode){
+    onRemove: function (e, treeId, treeNode) {
         if (treeNode.level > NODE_LEVEL_USER) {
             let me = zTreeOprObj,
                 topPNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW);
             let rawNode = me.buildRootNodeDoc(topPNode, treeNode);
             if (treeNode.level === NODE_LEVEL_COMPILATION_NEW) {
-                me.removeTreeRootNode(rawNode, true, function(rst){
+                me.removeTreeRootNode(rawNode, true, function (rst) {
                     if (!(rst)) {
                         alert("删除请求失败!");
                     }
                 });
             } else {
-                me.updateTreeRootNode(rawNode, true, function(rst){
+                me.updateTreeRootNode(rawNode, true, function (rst) {
                     if (!(rst)) {
                         alert("删除请求失败!");
                     }
@@ -702,12 +717,12 @@ let zTreeOprObj = {
     },
     beforeEditName: function (treeId, treeNode) {
         if (treeNode.level > NODE_LEVEL_COMPILATION_NEW) {
-            setTimeout(function(){
+            setTimeout(function () {
                 let ip = $("#" + treeNode.tId + IDMark_Input);
                 if (ip.length > 0) {
                     ip[0].className = "individualRename";
                 } else {
-                    setTimeout(function(){
+                    setTimeout(function () {
                         let ip = $("#" + treeNode.tId + IDMark_Input);
                         if (ip.length > 0) {
                             ip[0].className = "individualRename";
@@ -722,13 +737,13 @@ let zTreeOprObj = {
             return false;
         }
     },
-    beforeRename: function(treeId, treeNode, newName, isCancel) {
+    beforeRename: function (treeId, treeNode, newName, isCancel) {
         if (newName.length === 0) {
             return false;
         }
         return true;
     },
-    onRename : function(e, treeId, treeNode, isCancel) {
+    onRename: function (e, treeId, treeNode, isCancel) {
         if (!isCancel) {
             let me = zTreeOprObj;
             if (treeNode.level === 0) {
@@ -737,7 +752,7 @@ let zTreeOprObj = {
                 let subTopNode = me.getParentNodeByNodeLevel(treeNode, NODE_LEVEL_COMPILATION_NEW + 1);
                 let topPNode = subTopNode.getParentNode();
                 let rawNode = me.buildSubRootNodeDoc(subTopNode);
-                me.updateSubNode(topPNode, rawNode, true, function(rst){
+                me.updateSubNode(topPNode, rawNode, true, function (rst) {
                     if (!(rst)) {
                         alert('修改名称请求失败!');
                     }
@@ -745,17 +760,17 @@ let zTreeOprObj = {
             }
         }
     },
-    onChangeFlag: function(flagProp, flagDom){
+    onChangeFlag: function (flagProp, flagDom) {
         let me = zTreeOprObj;
         if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE) {
             if (!me.currentNode.hasOwnProperty("flags")) {
                 me.currentNode.flags = {};
             }
-            me.currentNode.flags[flagProp] = (flagDom.selectedOptions[0].value === 'NA')?null:flagDom.selectedOptions[0].value;
+            me.currentNode.flags[flagProp] = (flagDom.selectedOptions[0].value === 'NA') ? null : flagDom.selectedOptions[0].value;
             let subTopNode = me.getParentNodeByNodeLevel(me.currentNode, NODE_LEVEL_COMPILATION_NEW + 1);
             let topPNode = subTopNode.getParentNode();
             let rawNode = me.buildSubRootNodeDoc(subTopNode);
-            me.updateSubNode(topPNode, rawNode, true, function(rst){
+            me.updateSubNode(topPNode, rawNode, true, function (rst) {
                 if (!(rst)) {
                     alert('修改标记:[' + flagProp + '] 失败!');
                 }
@@ -763,6 +778,23 @@ let zTreeOprObj = {
         }
     },
 
+    onMutiChangeFlag: function (flagProp, flagDom) {
+        let me = zTreeOprObj;
+        if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE) {
+            if (!me.currentNode.hasOwnProperty("flags")) {
+                me.currentNode.flags = {};
+            }
+            me.currentNode.flags[flagProp] = flagDom[0].value.split(',');
+            let subTopNode = me.getParentNodeByNodeLevel(me.currentNode, NODE_LEVEL_COMPILATION_NEW + 1);
+            let topPNode = subTopNode.getParentNode();
+            let rawNode = me.buildSubRootNodeDoc(subTopNode);
+            me.updateSubNode(topPNode, rawNode, true, function (rst) {
+                if (!(rst)) {
+                    alert('修改标记:[' + flagProp + '] 失败!');
+                }
+            });
+        }
+    },
     createNewTpl: function () {
         let me = zTreeOprObj, params = {};
         if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE) {
@@ -781,14 +813,14 @@ let zTreeOprObj = {
             params.engineerId = topPNode.engineerId;
             params.userId = topPNode.userId;
             params.subNode = rawNode;
-            CommonAjax.postEx("report_tpl_api/createDftRptTpl", params, 10000, true, function(result){
-                    if (result) {
-                        me.currentNode.rptTpl = result;
-                        me.chkAndRreshRefTpl();
-                    } else {
-                        alert('update error!');
-                    }
-                }, null, null
+            CommonAjax.postEx("report_tpl_api/createDftRptTpl", params, 10000, true, function (result) {
+                if (result) {
+                    me.currentNode.rptTpl = result;
+                    me.chkAndRreshRefTpl();
+                } else {
+                    alert('update error!');
+                }
+            }, null, null
             );
         }
     },
@@ -805,7 +837,7 @@ let zTreeOprObj = {
         }
         return true;
     },
-    onClick: function(event,treeId,treeNode) {
+    onClick: function (event, treeId, treeNode) {
         let me = zTreeOprObj;
         me.currentNode = treeNode;
         bandTreeOprObj.currentNode = null;
@@ -859,77 +891,106 @@ let zTreeOprObj = {
         }
         return rst;
     },
-    chkAndRreshRefTpl: function(forceRefresh) {
+    chkAndRreshRefTpl: function (forceRefresh) {
         let me = zTreeOprObj, params = {};
-        const valuationTypes = ['suggestion', 'feasibility', 'rough', 'bill', 'ration'];
+        const valuationTypes = ['suggestion', 'feasibility', 'rough', 'bill', 'three_bill_budget', 'ration', 'changeBudget', 'settlement'];
         if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE && me.currentNode.refId > 0) {
             if (forceRefresh || !(me.currentNode.rptTpl)) {
                 params.rptTplId = me.currentNode.refId;
-                CommonAjax.postEx("report_tpl_api/getRefRptTpl", params, 20000, true, function(result){
-                        me.currentNode.rptTpl = result;
-                        me.currentNode.rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = me.currentNode.name;
-                        if (me.currentNode.rptTpl["GROUP_KEY"]) {
-                            let grp_keys = me.currentNode.rptTpl["GROUP_KEY"].split('_');
-                            if (grp_keys.length > 0) {
-                                grp_keys[1] = me.currentNode.name;
-                            }
-                            me.currentNode.rptTpl["GROUP_KEY"] = grp_keys.join("_");
+                CommonAjax.postEx("report_tpl_api/getRefRptTpl", params, 20000, true, function (result) {
+                    me.currentNode.rptTpl = result;
+                    me.currentNode.rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = me.currentNode.name;
+                    if (me.currentNode.rptTpl["GROUP_KEY"]) {
+                        let grp_keys = me.currentNode.rptTpl["GROUP_KEY"].split('_');
+                        if (grp_keys.length > 0) {
+                            grp_keys[1] = me.currentNode.name;
                         }
-                        tplHelper.refreshTplView(me.currentNode.rptTpl);
-                        if (me.currentNode.hasOwnProperty('flags')) {
-                            if (me.currentNode.flags.hasOwnProperty('taxType')) {
-                                let val = parseInt(me.currentNode.flags['taxType']);
-                                $("#element_flags_select")[0].selectedIndex = val;
-                            } else {
-                                $("#element_flags_select")[0].selectedIndex = 0;
-                            }
-                            if (me.currentNode.flags.hasOwnProperty('valuationType')) {
-                                let vType = me.currentNode.flags['valuationType'];
-                                let vtIdx = valuationTypes.indexOf(vType);
-                                $("#element_prjFlags_select")[0].selectedIndex = vtIdx + 1;
-                            } else {
-                                $("#element_prjFlags_select")[0].selectedIndex = 0;
-                            }
-                            if (me.currentNode.flags.hasOwnProperty('reportType')) {
-                                let rType = me.currentNode.flags['reportType'];
-                                if (rType === 'billSummary') $("#element_rptFlags_select")[0].selectedIndex = 1
-                                else if (rType === 'gljSummary') $("#element_rptFlags_select")[0].selectedIndex = 2
-                                else $("#element_rptFlags_select")[0].selectedIndex = 0;
-                            } else {
-                                $("#element_rptFlags_select")[0].selectedIndex = 0;
-                            }
-
-                            if (me.currentNode.flags.hasOwnProperty('sumLevelType')) {
-                                let sumLvType = me.currentNode.flags['sumLevelType'];
-                                if (sumLvType === 'construct') $("#element_sumLv_flags")[0].selectedIndex = 1
-                                else if (sumLvType === 'Single') $("#element_sumLv_flags")[0].selectedIndex = 2
-                                else if (sumLvType === 'custom') $("#element_sumLv_flags")[0].selectedIndex = 3
-                                else $("#element_sumLv_flags")[0].selectedIndex = 0;
-                            } else {
-                                $("#element_sumLv_flags")[0].selectedIndex = 0;
-                            }
-
+                        me.currentNode.rptTpl["GROUP_KEY"] = grp_keys.join("_");
+                    }
+                    tplHelper.refreshTplView(me.currentNode.rptTpl);
+                    if (me.currentNode.hasOwnProperty('flags')) {
+                        if (me.currentNode.flags.hasOwnProperty('taxType')) {
+                            let val = parseInt(me.currentNode.flags['taxType']);
+                            $("#element_flags_select")[0].selectedIndex = val;
                         } else {
                             $("#element_flags_select")[0].selectedIndex = 0;
-                            $("#element_prjFlags_select")[0].selectedIndex = 0;
+                        }
+                        $("#valuationSelector").hide();
+                        if (me.currentNode.flags.hasOwnProperty('valuationType')) {
+                            $(".mutiSelector").find('li').removeClass('checked');
+                            let valuationTypeStr = '';
+                            let valuationTypeStrList = [];
+                            let vType = me.currentNode.flags['valuationType'];
+                            // let vtIdx = valuationTypes.indexOf(vType);
+                            // $("#element_prjFlags_select")[0].selectedIndex = vtIdx + 1;
+                            if (vType instanceof Array) {
+                                for (let i = 0; i < vType.length; i++) {
+                                    $("#valuationSelector_" + vType[i]).addClass('checked');
+                                    valuationTypeStrList.push(valuationSelectorMap["valuationSelector_" + vType[i]]);
+                                }
+                                valuationTypeStr = valuationTypeStrList.join(',');
+                            } else if (vType) {
+                                $("#valuationSelector_" + vType).addClass('checked');
+                                valuationTypeStr = valuationSelectorMap["valuationSelector_" + vType];
+                            }
+                            $("#element_prjFlags_select")[0].value = vType;
+                            $("#element_prjFlags_selectStr")[0].value = valuationTypeStr;
+                        } else {
+                            $("#element_prjFlags_select")[0].value = '';
+                            $("#element_prjFlags_selectStr")[0].value = '';
+                            $('#valuationSelector .mutiSelector li').removeClass('checked');
+                        }
+                        if (me.currentNode.flags.hasOwnProperty('reportType')) {
+                            let rType = me.currentNode.flags['reportType'];
+                            if (rType === 'billSummary') $("#element_rptFlags_select")[0].selectedIndex = 1
+                            else if (rType === 'gljSummary') $("#element_rptFlags_select")[0].selectedIndex = 2
+                            else $("#element_rptFlags_select")[0].selectedIndex = 0;
+                        } else {
+                            $("#element_rptFlags_select")[0].selectedIndex = 0;
+                        }
+                        if (me.currentNode.flags.hasOwnProperty('sumLevelType')) {
+                            let sumLvType = me.currentNode.flags['sumLevelType'];
+                            if (sumLvType === 'construct') $("#element_sumLv_flags")[0].selectedIndex = 1
+                            else if (sumLvType === 'Single') $("#element_sumLv_flags")[0].selectedIndex = 2
+                            else if (sumLvType === 'custom') $("#element_sumLv_flags")[0].selectedIndex = 3
+                            else $("#element_sumLv_flags")[0].selectedIndex = 0;
+                        } else {
                             $("#element_sumLv_flags")[0].selectedIndex = 0;
                         }
 
-                        if ($("#rpt_tpl_visual_tab")[0].className === "nav-link p-1 active") {
-                            setTimeout(function(){visualJumbo.iniSpreadJs(); visualJumbo.setupTpl()}, 50)
+                        if (me.currentNode.flags.hasOwnProperty('contrastType')) {
+                            let contrastType = me.currentNode.flags['contrastType'];
+                            if (contrastType === 'chapter') $("#element_contrastType_select")[0].selectedIndex = 1
+                            else if (contrastType === 'bill') $("#element_contrastType_select")[0].selectedIndex = 2
+                            else if (contrastType === 'quantities') $("#element_contrastType_select")[0].selectedIndex = 3
+                            else $("#element_contrastType_select")[0].selectedIndex = 0;
                         }
-                    }, null, null
+                    } else {
+                        $("#element_flags_select")[0].selectedIndex = 0;
+                        $("#element_prjFlags_select")[0].selectedIndex = 0;
+                        $("#element_sumLv_flags")[0].selectedIndex = 0;
+                        // 清空工程类型
+                        $("#valuationSelector").hide();
+                        $("#element_prjFlags_select")[0].value = '';
+                        $("#element_prjFlags_selectStr")[0].value = '';
+                        $('#valuationSelector .mutiSelector li').removeClass('checked');
+                    }
+
+                    if ($("#rpt_tpl_visual_tab")[0].className === "nav-link p-1 active") {
+                        setTimeout(function () { visualJumbo.iniSpreadJs(); visualJumbo.setupTpl() }, 50)
+                    }
+                }, null, null
                 );
             } else {
                 me.currentNode.rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MAIN_INFO_RPT_NAME] = me.currentNode.name;
                 tplHelper.refreshTplView(me.currentNode.rptTpl);
                 if ($("#rpt_tpl_visual_tab")[0].className === "nav-link p-1 active") {
-                    setTimeout(function(){visualJumbo.iniSpreadJs(); visualJumbo.setupTpl()}, 50)
+                    setTimeout(function () { visualJumbo.iniSpreadJs(); visualJumbo.setupTpl() }, 50)
                 }
             }
         }
     },
-    getRefTpl: function() {
+    getRefTpl: function () {
         let me = zTreeOprObj, rst = null;
         if (me.currentNode && me.currentNode.nodeType === RT.NodeType.TEMPLATE && me.currentNode.refId > 0) {
             rst = me.currentNode.rptTpl
@@ -978,11 +1039,11 @@ let zTreeOprObj = {
 let userListObj = {
     foundedUserList: [],
     UserIdList: [],
-    pushUser: function(user, newUsers) {
+    pushUser: function (user, newUsers) {
         let me = userListObj;
         if (me.UserIdList.indexOf(user._id) < 0) {
             me.UserIdList.push(user._id);
-            let newUser = {userId: user._id, real_name: user.real_name, username: user.username, mobile: user.mobile};
+            let newUser = { userId: user._id, real_name: user.real_name, username: user.username, mobile: user.mobile };
             me.foundedUserList.push(newUser);
             if (newUsers) {
                 newUsers.push(newUser);
@@ -993,11 +1054,11 @@ let userListObj = {
         let key = $("#rpt_user_input1").get(0).value;
         let newUsers = [];
         $.ajax({
-            type:"GET",
+            type: "GET",
             url: "user/search?keyword=" + key,
             cache: false,
             timeout: 5000,
-            success: function(result){
+            success: function (result) {
                 if (result.data && result.data.length > 0) {
                     for (let user of result.data) {
                         userListObj.pushUser(user, newUsers);
@@ -1007,21 +1068,21 @@ let userListObj = {
                     }
                 }
             },
-            error: function(jqXHR, textStatus, errorThrown){
+            error: function (jqXHR, textStatus, errorThrown) {
             }
         });
     },
     findUsersByIds: function (userIds, cb) {
         let params = {};
         params.userIds = userIds;
-        CommonAjax.postEx("user/getUserList", params, 20000, true, function(result){
-                for (let user of result) {
-                    userListObj.pushUser(user, null);
-                }
-                if (cb) {
-                    cb(result);
-                }
-            }, null, null
+        CommonAjax.postEx("user/getUserList", params, 20000, true, function (result) {
+            for (let user of result) {
+                userListObj.pushUser(user, null);
+            }
+            if (cb) {
+                cb(result);
+            }
+        }, null, null
         );
     }
 };
@@ -1031,7 +1092,40 @@ function displayMessage(message, color, disappearTime, id) {
     if (!domId) domId = "id_after_saved_lbl";
     $("#" + domId)[0].style.color = color;
     $("#" + domId)[0].innerHTML = message;
-    setTimeout(function(){
+    setTimeout(function () {
         $("#" + domId)[0].innerHTML = "";
     }, disappearTime);
-}
+}
+
+$("#element_prjFlags_selectStr").on('click', function () {
+    if ($('#valuationSelector').visible) {
+        $('#valuationSelector').hide();
+    } else {
+        $('#valuationSelector').show();
+    }
+    return false;
+})
+
+$('#rpttplinfo').on('click', function () {
+    $('#valuationSelector').hide();
+})
+
+$('.mutiSelector').find('li').on('click', function (e) {
+    const hasChecked = $(this).hasClass('checked');
+    if (hasChecked) {
+        $(this).removeClass('checked');
+    } else {
+        $(this).addClass('checked');
+    }
+    const resultIDList = [];
+    const resultList = [];
+    $('.mutiSelector .checked').each(function (index, value) {
+        resultList.push(valuationSelectorMap[$(value).attr('id')]);
+        resultIDList.push($(value).attr('value'));
+    })
+    const result = resultList.join(',');
+    $('#element_prjFlags_selectStr').val(result);
+    $('#element_prjFlags_select').val(resultIDList);
+    zTreeOprObj.onMutiChangeFlag('valuationType', $('#element_prjFlags_select'));
+    return false;
+})

+ 218 - 217
web/maintain/report/js/rpt_tpl_pre_handle.js

@@ -8,23 +8,23 @@ const pre_handle_data_objects = ["bills", "ration", "ration_glj", "projectGLJ"];
 const pre_handle_data_objects_name = ["清单", "定额", "定额人材机", "项目人材机"];
 //供货方式
 const fixed_supply_types = [
-    {Name: "自行采购(0)", Title: "", Value: 0},
-    {Name: "部分甲供(1)", Title: "", Value: 1},
-    {Name: "完全甲供(2)", Title: "", Value: 2},
-    {Name: "甲定乙供(3)", Title: "", Value: 3}
+    { Name: "自行采购(0)", Title: "", Value: 0 },
+    { Name: "部分甲供(1)", Title: "", Value: 1 },
+    { Name: "完全甲供(2)", Title: "", Value: 2 },
+    { Name: "甲定乙供(3)", Title: "", Value: 3 }
 ];
 //三材类别
 const fixed_material_types = [
-    {Name: "钢材(1)", Title: "", Value: 1},
-    {Name: "钢筋(2)", Title: "", Value: 2},
-    {Name: "木材(3)", Title: "", Value: 3},
-    {Name: "水泥(4)", Title: "", Value: 4},
-    {Name: "标准砖(5)", Title: "", Value: 5}
+    { Name: "钢材(1)", Title: "", Value: 1 },
+    { Name: "钢筋(2)", Title: "", Value: 2 },
+    { Name: "木材(3)", Title: "", Value: 3 },
+    { Name: "水泥(4)", Title: "", Value: 4 },
+    { Name: "标准砖(5)", Title: "", Value: 5 }
 ];
 //工料机来源
 const fixed_glj_from_types = [
-    {Name: "标准(std)", Title: "", Value: 'std'},
-    {Name: "补充(cpt)", Title: "", Value: 'cpt'},
+    { Name: "标准(std)", Title: "", Value: 'std' },
+    { Name: "补充(cpt)", Title: "", Value: 'cpt' },
 ];
 // const fixed_glj_types = [
 //     {Name: "人工(1)", Title: "", Value: 1},
@@ -54,31 +54,31 @@ const fixed_glj_from_types = [
 //     {Name: "一般风险费(8)", Title: "", Value: 8}
 // ];
 const fixed_glj_types = [
-    {Name: "人工(1)", Title: "", Value: 1},
-    {Name: "普通材料(201)", Title: "", Value: 201},
-    {Name: "混凝土(202)", Title: "", Value: 202},
-    {Name: "砂浆(203)", Title: "", Value: 203},
-    {Name: "配合比(204)", Title: "", Value: 204},
-    {Name: "商品混凝土(205)", Title: "", Value: 205},
-    {Name: "商品砂浆(206)", Title: "", Value: 206},
-    {Name: "其他材料(207)", Title: "", Value: 207},
-    {Name: "机械台班(301)", Title: "", Value: 301},
-    {Name: "机械组成物(302)", Title: "", Value: 302},
-    {Name: "机上人工(303)", Value: 303},
-    {Name: "仪器仪表(304)", Value: 304},
-    {Name: "燃料动力费(305)", Value: 305},
-    {Name: "折旧费(306)", Value: 306},
-    {Name: "检修费(307)", Value: 307},
-    {Name: "维护费(308)", Value: 308},
-    {Name: "安拆费及场外运费(309)", Value: 309},
-    {Name: "校验费(310)", Value: 310},
-    {Name: "其他费用(311)", Value: 311},
-    {Name: "其他施工机具使用费(312)", Value: 312},
-    {Name: "主材(4)", Title: "", Value: 4},
-    {Name: "设备(5)", Title: "", Value: 5},
-    {Name: "企业管理费(6)", Title: "", Value: 6},
-    {Name: "利润(7)", Title: "", Value: 7},
-    {Name: "一般风险费(8)", Title: "", Value: 8}
+    { Name: "人工(1)", Title: "", Value: 1 },
+    { Name: "普通材料(201)", Title: "", Value: 201 },
+    { Name: "混凝土(202)", Title: "", Value: 202 },
+    { Name: "砂浆(203)", Title: "", Value: 203 },
+    { Name: "配合比(204)", Title: "", Value: 204 },
+    { Name: "商品混凝土(205)", Title: "", Value: 205 },
+    { Name: "商品砂浆(206)", Title: "", Value: 206 },
+    { Name: "其他材料(207)", Title: "", Value: 207 },
+    { Name: "机械台班(301)", Title: "", Value: 301 },
+    { Name: "机械组成物(302)", Title: "", Value: 302 },
+    { Name: "机上人工(303)", Value: 303 },
+    { Name: "仪器仪表(304)", Value: 304 },
+    { Name: "燃料动力费(305)", Value: 305 },
+    { Name: "折旧费(306)", Value: 306 },
+    { Name: "检修费(307)", Value: 307 },
+    { Name: "维护费(308)", Value: 308 },
+    { Name: "安拆费及场外运费(309)", Value: 309 },
+    { Name: "校验费(310)", Value: 310 },
+    { Name: "其他费用(311)", Value: 311 },
+    { Name: "其他施工机具使用费(312)", Value: 312 },
+    { Name: "主材(4)", Title: "", Value: 4 },
+    { Name: "设备(5)", Title: "", Value: 5 },
+    { Name: "企业管理费(6)", Title: "", Value: 6 },
+    { Name: "利润(7)", Title: "", Value: 7 },
+    { Name: "一般风险费(8)", Title: "", Value: 8 }
 ];
 // const fixed_top_bills_nodes = [
 //     {Name: "分部分项工程(1)", Title: "", Value: 1}
@@ -89,14 +89,14 @@ const fixed_glj_types = [
 //     ,{Name: "工程造价(19)", Title: "", Value: 19}
 // ];
 const fixed_top_bills_nodes = [
-    {Name: "建筑安装工程费(1)", Title: "", Value: 1}
-    ,{Name: "土地使用及拆迁补偿费(2)", Title: "", Value: 2}
-    ,{Name: "养护工程其他费用(3)", Title: "", Value: 3}
-    ,{Name: "预备费(4)", Title: "", Value: 4}
-    ,{Name: "一二三四部分合计(7)", Title: "", Value: 7}
-    ,{Name: "贷款利息(8)", Title: "", Value: 8}
-    ,{Name: "总造价(9)", Title: "", Value: 9}
-    ,{Name: "第100章至700章清单(19)", Title: "", Value: 19}
+    { Name: "建筑安装工程费(1)", Title: "", Value: 1 }
+    , { Name: "土地使用及拆迁补偿费(2)", Title: "", Value: 2 }
+    , { Name: "养护工程其他费用(3)", Title: "", Value: 3 }
+    , { Name: "预备费(4)", Title: "", Value: 4 }
+    , { Name: "一二三四部分合计(7)", Title: "", Value: 7 }
+    , { Name: "贷款利息(8)", Title: "", Value: 8 }
+    , { Name: "总造价(9)", Title: "", Value: 9 }
+    , { Name: "第100章至700章清单(19)", Title: "", Value: 19 }
 ];
 
 // const fixed_other_bills_types = [
@@ -116,27 +116,27 @@ const fixed_top_bills_nodes = [
 //     ,{Name: "增值税(20)", Title: "", Value: 20}
 // ];
 const fixed_other_bills_types = [
-    {Name: "基本预备费(5)", Title: "", Value: 5}
-    ,{Name: "价差预备费(6)", Title: "", Value: 6}
-    ,{Name: "设备购置费(10)", Title: "", Value: 10}
-    ,{Name: "专项费用(11)", Title: "", Value: 11}
-    ,{Name: "施工场地建设费(12)", Title: "", Value: 12}
-    ,{Name: "养护单位(业主)管理费(13)", Title: "", Value: 13}
-    ,{Name: "信息化费", Title: "", Value: 14}
-    ,{Name: "工程监理费(15)", Title: "", Value: 15}
-    ,{Name: "设计文件审查费(16)", Title: "", Value: 16}
-    ,{Name: "勘察设计费(17)", Title: "", Value: 17}
-    ,{Name: "招标代理及标底编制费(18)", Title: "", Value: 18}
-    ,{Name: "第100章至700章清单(19)", Title: "", Value: 19}
-    ,{Name: "专项暂定合计(20)", Title: "", Value: 20}
-    ,{Name: "清单合计扣除专项暂定合计(21)", Title: "", Value: 21}
-    ,{Name: "计日工(22)", Title: "", Value: 22}
-    ,{Name: "劳务(23)", Title: "", Value: 23}
-    ,{Name: "材料(24)", Title: "", Value: 24}
-    ,{Name: "施工机械(25)", Title: "", Value: 25}
-    ,{Name: "暂列金额(26)", Title: "", Value: 26}
-    ,{Name: "安全生产费(27)", Title: "", Value: 27}
-    ,{Name: "100章清单(28)", Title: "", Value: 28}
+    { Name: "基本预备费(5)", Title: "", Value: 5 }
+    , { Name: "价差预备费(6)", Title: "", Value: 6 }
+    , { Name: "设备购置费(10)", Title: "", Value: 10 }
+    , { Name: "专项费用(11)", Title: "", Value: 11 }
+    , { Name: "施工场地建设费(12)", Title: "", Value: 12 }
+    , { Name: "养护单位(业主)管理费(13)", Title: "", Value: 13 }
+    , { Name: "信息化费", Title: "", Value: 14 }
+    , { Name: "工程监理费(15)", Title: "", Value: 15 }
+    , { Name: "设计文件审查费(16)", Title: "", Value: 16 }
+    , { Name: "勘察设计费(17)", Title: "", Value: 17 }
+    , { Name: "招标代理及标底编制费(18)", Title: "", Value: 18 }
+    , { Name: "第100章至700章清单(19)", Title: "", Value: 19 }
+    , { Name: "专项暂定合计(20)", Title: "", Value: 20 }
+    , { Name: "清单合计扣除专项暂定合计(21)", Title: "", Value: 21 }
+    , { Name: "计日工(22)", Title: "", Value: 22 }
+    , { Name: "劳务(23)", Title: "", Value: 23 }
+    , { Name: "材料(24)", Title: "", Value: 24 }
+    , { Name: "施工机械(25)", Title: "", Value: 25 }
+    , { Name: "暂列金额(26)", Title: "", Value: 26 }
+    , { Name: "安全生产费(27)", Title: "", Value: 27 }
+    , { Name: "100章清单(28)", Title: "", Value: 28 }
 ];
 // const fixed_bills_flags = [
 //     {Name: "分部分项工程(1)", Title: "", Value: 1},
@@ -161,90 +161,91 @@ const fixed_other_bills_types = [
 //     {Name: "增值税(20)", Title: "", Value: 20}
 // ];
 const fixed_bills_flags = [
-    {Name: "建筑安装工程费(1)", Title: "", Value: 1}
-    ,{Name: "土地使用及拆迁补偿费(2)", Title: "", Value: 2}
-    ,{Name: "养护工程其他费用(3)", Title: "", Value: 3}
-    ,{Name: "预备费(4)", Title: "", Value: 4}
-    ,{Name: "基本预备费(5)", Title: "", Value: 5}
-    ,{Name: "价差预备费(6)", Title: "", Value: 6}
-    ,{Name: "一二三四部分合计(7)", Title: "", Value: 7}
-    ,{Name: "贷款利息(8)", Title: "", Value: 8}
-    ,{Name: "总造价(9)", Title: "", Value: 9}
-    ,{Name: "设备购置费(10)", Title: "", Value: 10}
-    ,{Name: "专项费用(11)", Title: "", Value: 11}
-    ,{Name: "施工场地建设费(12)", Title: "", Value: 12}
-    ,{Name: "养护单位(业主)管理费(13)", Title: "", Value: 13}
-    ,{Name: "信息化费", Title: "", Value: 14}
-    ,{Name: "工程监理费(15)", Title: "", Value: 15}
-    ,{Name: "设计文件审查费(16)", Title: "", Value: 16}
-    ,{Name: "勘察设计费(17)", Title: "", Value: 17}
-    ,{Name: "招标代理及标底编制费(18)", Title: "", Value: 18}
-    ,{Name: "第100章至700章清单(19)", Title: "", Value: 19}
-    ,{Name: "专项暂定合计(20)", Title: "", Value: 20}
-    ,{Name: "清单合计扣除专项暂定合计(21)", Title: "", Value: 21}
-    ,{Name: "计日工(22)", Title: "", Value: 22}
-    ,{Name: "劳务(23)", Title: "", Value: 23}
-    ,{Name: "材料(24)", Title: "", Value: 24}
-    ,{Name: "施工机械(25)", Title: "", Value: 25}
-    ,{Name: "暂列金额(26)", Title: "", Value: 26}
-    ,{Name: "安全生产费(27)", Title: "", Value: 27}
-    ,{Name: "100章清单(28)", Title: "", Value: 28}
+    { Name: "建筑安装工程费(1)", Title: "", Value: 1 }
+    , { Name: "土地使用及拆迁补偿费(2)", Title: "", Value: 2 }
+    , { Name: "养护工程其他费用(3)", Title: "", Value: 3 }
+    , { Name: "预备费(4)", Title: "", Value: 4 }
+    , { Name: "基本预备费(5)", Title: "", Value: 5 }
+    , { Name: "价差预备费(6)", Title: "", Value: 6 }
+    , { Name: "一二三四部分合计(7)", Title: "", Value: 7 }
+    , { Name: "贷款利息(8)", Title: "", Value: 8 }
+    , { Name: "总造价(9)", Title: "", Value: 9 }
+    , { Name: "设备购置费(10)", Title: "", Value: 10 }
+    , { Name: "专项费用(11)", Title: "", Value: 11 }
+    , { Name: "施工场地建设费(12)", Title: "", Value: 12 }
+    , { Name: "养护单位(业主)管理费(13)", Title: "", Value: 13 }
+    , { Name: "信息化费", Title: "", Value: 14 }
+    , { Name: "工程监理费(15)", Title: "", Value: 15 }
+    , { Name: "设计文件审查费(16)", Title: "", Value: 16 }
+    , { Name: "勘察设计费(17)", Title: "", Value: 17 }
+    , { Name: "招标代理及标底编制费(18)", Title: "", Value: 18 }
+    , { Name: "第100章至700章清单(19)", Title: "", Value: 19 }
+    , { Name: "专项暂定合计(20)", Title: "", Value: 20 }
+    , { Name: "清单合计扣除专项暂定合计(21)", Title: "", Value: 21 }
+    , { Name: "计日工(22)", Title: "", Value: 22 }
+    , { Name: "劳务(23)", Title: "", Value: 23 }
+    , { Name: "材料(24)", Title: "", Value: 24 }
+    , { Name: "施工机械(25)", Title: "", Value: 25 }
+    , { Name: "暂列金额(26)", Title: "", Value: 26 }
+    , { Name: "安全生产费(27)", Title: "", Value: 27 }
+    , { Name: "100章清单(28)", Title: "", Value: 28 }
 ];
 const fixed_bills_types = [
-    {Name: "大项费用(1)", Title: "", Value: 1},
-    {Name: "分部(2)", Title: "", Value: 2},
-    {Name: "分项(3)", Title: "", Value: 3},
-    {Name: "清单(4)", Title: "", Value: 4},
-    {Name: "补项(5)", Title: "", Value: 5}
+    { Name: "大项费用(1)", Title: "", Value: 1 },
+    { Name: "分部(2)", Title: "", Value: 2 },
+    { Name: "分项(3)", Title: "", Value: 3 },
+    { Name: "清单(4)", Title: "", Value: 4 },
+    { Name: "补项(5)", Title: "", Value: 5 }
 ];
 const fixed_bills_special_provisional_types = [
-    {Name: "材料", Title: "", Value: "材料"},
-    {Name: "工程设备", Title: "", Value: "工程设备"},
-    {Name: "专业工程", Title: "", Value: "专业工程"}
+    { Name: "材料", Title: "", Value: "材料" },
+    { Name: "工程设备", Title: "", Value: "工程设备" },
+    { Name: "专业工程", Title: "", Value: "专业工程" }
 ];
 const exposed_bills_properties = [
-    {Name: "清单_所属项目ID", Title: "", Key: "projectID", Order: "ascend"}
-    ,{Name: "清单_ID", Title: "", Key: "ID", Order: "ascend"}
-    ,{Name: "顶层父清单_标记", Title: "", Key: "topBillID", Order: "ascend", individualType: fixed_top_bills_nodes}
-    ,{Name: "清单_层次", Title: "", Key: "treeLevel", Order: "ascend"}
-    ,{Name: "清单_类别", Title: "", Key: "type", Order: "ascend", individualType: fixed_bills_types}
-    ,{Name: "清单_标记", Title: "", Key: "flags.flag", Order: "ascend", individualType: fixed_bills_flags}
-    ,{Name: "清单_顺序号", Title: "", Key: "treeFlatSerialOrder", Order: "ascend"}
-    ,{Name: "清单_专项类型", Title: "", Key: "specialProvisional", Order: "ascend", individualType: fixed_bills_special_provisional_types}
+    { Name: "清单_所属项目ID", Title: "", Key: "projectID", Order: "ascend" }
+    , { Name: "清单_ID", Title: "", Key: "ID", Order: "ascend" }
+    , { Name: "顶层父清单_标记", Title: "", Key: "topBillID", Order: "ascend", individualType: fixed_top_bills_nodes }
+    , { Name: "清单_层次", Title: "", Key: "treeLevel", Order: "ascend" }
+    , { Name: "清单_类别", Title: "", Key: "type", Order: "ascend", individualType: fixed_bills_types }
+    , { Name: "清单_标记", Title: "", Key: "flags.flag", Order: "ascend", individualType: fixed_bills_flags }
+    , { Name: "清单_顺序号", Title: "", Key: "treeFlatSerialOrder", Order: "ascend" }
+    , { Name: "清单_专项类型", Title: "", Key: "specialProvisional", Order: "ascend", individualType: fixed_bills_special_provisional_types }
 ];
 const exposed_ration_properties = [
-    {Name: "定额_工程内部ID", Title: "", Key: "ID", Order: "ascend"}
-    ,{Name: "定额_所属项目ID", Title: "", Key: "projectID", Order: "ascend"}
-    ,{Name: "定额_所属清单ID", Title: "", Key: "billsItemID", Order: "ascend"}
-    ,{Name: "定额_清单内顺序", Title: "", Key: "serialNo", Order: "ascend"}
-    ,{Name: "定额_类型", Title: "", Key: "type", Order: "ascend"}
+    { Name: "定额_工程内部ID", Title: "", Key: "ID", Order: "ascend" }
+    , { Name: "定额_所属项目ID", Title: "", Key: "projectID", Order: "ascend" }
+    , { Name: "定额_所属清单ID", Title: "", Key: "billsItemID", Order: "ascend" }
+    , { Name: "定额_清单内顺序", Title: "", Key: "serialNo", Order: "ascend" }
+    , { Name: "定额_类型", Title: "", Key: "type", Order: "ascend" }
+    , { Name: "定额_工程量", Title: "", Key: "quantity", Order: "ascend" }
 ];
 const exposed_ration_glj_properties = [
-    {Name: "定额人材机_ID", Title: "", Key: "ID"}
-    ,{Name: "定额人材机_项目人材机映射ID", Title: "", Key: "projectGLJID", Order: "ascend"}
-    ,{Name: "定额人材机_所属定额ID", Title: "", Key: "rationID", Order: "ascend"}
-    ,{Name: "定额人材机_所属清单ID", Title: "", Key: "billsItemID", Order: "ascend"}
-    ,{Name: "定额人材机_所属工程ID", Title: "", Key: "projectID", Order: "ascend"}
-    ,{Name: "定额人材机_代码", Title: "", Key: "code", Order: "ascend"}
-    ,{Name: "定额人材机_类型", Title: "", Key: "type", Order: "ascend", individualType: fixed_glj_types}
-    ,{Name: "定额人材机_数量", Title: "", Key: "quantity", Order: "ascend"}
-    ,{Name: "定额人材机_是否暂估", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).is_evaluate", Order: "ascend", isBoolean: true, booleanOptions: [1,0]}
-    ,{Name: "定额人材机_是否主要材料", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).is_main_material", Order: "ascend", isBoolean: true, booleanOptions: [1,0]}
-    ,{Name: "定额人材机_供货方式", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).supply", Order: "ascend", individualType: fixed_supply_types}
-    ,{Name: "定额人材机_三材类别", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).materialType", Order: "ascend", individualType: fixed_material_types}
+    { Name: "定额人材机_ID", Title: "", Key: "ID" }
+    , { Name: "定额人材机_项目人材机映射ID", Title: "", Key: "projectGLJID", Order: "ascend" }
+    , { Name: "定额人材机_所属定额ID", Title: "", Key: "rationID", Order: "ascend" }
+    , { Name: "定额人材机_所属清单ID", Title: "", Key: "billsItemID", Order: "ascend" }
+    , { Name: "定额人材机_所属工程ID", Title: "", Key: "projectID", Order: "ascend" }
+    , { Name: "定额人材机_代码", Title: "", Key: "code", Order: "ascend" }
+    , { Name: "定额人材机_类型", Title: "", Key: "type", Order: "ascend", individualType: fixed_glj_types }
+    , { Name: "定额人材机_数量", Title: "", Key: "quantity", Order: "ascend" }
+    , { Name: "定额人材机_是否暂估", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).is_evaluate", Order: "ascend", isBoolean: true, booleanOptions: [1, 0] }
+    , { Name: "定额人材机_是否主要材料", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).is_main_material", Order: "ascend", isBoolean: true, booleanOptions: [1, 0] }
+    , { Name: "定额人材机_供货方式", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).supply", Order: "ascend", individualType: fixed_supply_types }
+    , { Name: "定额人材机_三材类别", Title: "", Key: "ref_join(projectGLJID,projectGLJ,id).materialType", Order: "ascend", individualType: fixed_material_types }
 ];
 const exposed_prj_glj_properties = [
-    {Name: "项目人材机_ID", Title: "", Key: "id"}
-    ,{Name: "项目人材机_所属工程ID", Title: "", Key: "projectID", Order: "ascend"}
-    ,{Name: "项目人材机_代码", Title: "", Key: "code", Order: "ascend"}
-    ,{Name: "项目人材机_类型", Title: "", Key: "type", Order: "ascend", individualType: fixed_glj_types}
-    ,{Name: "项目人材机_数量", Title: "", Key: "quantity", Order: "ascend"}
-    ,{Name: "项目人材机_是否暂估", Title: "", Key: "is_evaluate", Order: "ascend", isBoolean: true, booleanOptions: [1,0]}
-    ,{Name: "项目人材机_是否主要材料", Title: "", Key: "is_main_material", Order: "ascend", isBoolean: true, booleanOptions: [1,0]}
-    ,{Name: "项目人材机_是否材料计算", Title: "", Key: "unit_price.calcMaterial", Order: "ascend", isBoolean: true, booleanOptions: [1,0]}
-    ,{Name: "项目人材机_供货方式", Title: "", Key: "supply", Order: "ascend", individualType: fixed_supply_types}
-    ,{Name: "项目人材机_三材类别", Title: "", Key: "materialType", Order: "ascend", individualType: fixed_material_types}
-    ,{Name: "项目人材机_来源", Title: "", Key: "from", Order: "ascend", individualType: fixed_glj_from_types}
+    { Name: "项目人材机_ID", Title: "", Key: "id" }
+    , { Name: "项目人材机_所属工程ID", Title: "", Key: "projectID", Order: "ascend" }
+    , { Name: "项目人材机_代码", Title: "", Key: "code", Order: "ascend" }
+    , { Name: "项目人材机_类型", Title: "", Key: "type", Order: "ascend", individualType: fixed_glj_types }
+    , { Name: "项目人材机_数量", Title: "", Key: "quantity", Order: "ascend" }
+    , { Name: "项目人材机_是否暂估", Title: "", Key: "is_evaluate", Order: "ascend", isBoolean: true, booleanOptions: [1, 0] }
+    , { Name: "项目人材机_是否主要材料", Title: "", Key: "is_main_material", Order: "ascend", isBoolean: true, booleanOptions: [1, 0] }
+    , { Name: "项目人材机_是否材料计算", Title: "", Key: "unit_price.calcMaterial", Order: "ascend", isBoolean: true, booleanOptions: [1, 0] }
+    , { Name: "项目人材机_供货方式", Title: "", Key: "supply", Order: "ascend", individualType: fixed_supply_types }
+    , { Name: "项目人材机_三材类别", Title: "", Key: "materialType", Order: "ascend", individualType: fixed_material_types }
+    , { Name: "项目人材机_来源", Title: "", Key: "from", Order: "ascend", individualType: fixed_glj_from_types }
 ];
 const exposed_properties_arr = [exposed_bills_properties, exposed_ration_properties, exposed_ration_glj_properties, exposed_prj_glj_properties];
 
@@ -252,15 +253,15 @@ let preHandleObj = {
     treeObj: null,
     typeTreeObj: null,
     currentNode: null,
-    iniTree: function(rptTpl) {
+    iniTree: function (rptTpl) {
         let me = this;
         me.buildData(rptTpl);
     },
-    buildData: function(rptTpl) {
+    buildData: function (rptTpl) {
         let me = this, handles = [];
         if (rptTpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
             for (let item of rptTpl[JV.NODE_MAP_DATA_HANDLE_INFO]) {
-                let hd = {Name: "预处理环节"};
+                let hd = { Name: "预处理环节" };
                 me.private_copy_node(item, hd);
                 me.private_set_title(hd);
                 hd.Operations = []; //考虑到用户可能会换来换去,这样会有冗余的属性出现
@@ -269,7 +270,7 @@ let preHandleObj = {
         }
         me.treeObj = $.fn.zTree.init($("#pre_handle_data_info_reversed"), preHandleSetting, handles);
     },
-    build_handle_data_selection: function() {
+    build_handle_data_selection: function () {
         let sel = $("#select_mapping_data"), sel2 = $("#select_mapping_data_for_sort_type");
         for (let i = 0; i < pre_handle_data_objects.length; i++) {
             sel2.append("<option value='" + pre_handle_data_objects[i] + "'>" + pre_handle_data_objects_name[i] + "</option>");
@@ -278,19 +279,19 @@ let preHandleObj = {
     },
     buildTypeData: function () {
         let me = this, types = [];
-        types.push({Name: JV.PROP_HANDLE_TYPE_SORT, Title: ""});
-        types.push({Name: JV.PROP_HANDLE_TYPE_FILTER, Title: ""});
-        types.push({Name: JV.PROP_HANDLE_TYPE_BILLS_DATA_MOVE, Title: ""});
-        types.push({Name: JV.PROP_HANDLE_TYPE_COMPONENT_MOVE, Title: ""});
-        types.push({Name: JV.PROP_HANDLE_TYPE_SUM, Title: ""});
-        types.push({Name: JV.PROP_HANDLE_TYPE_ADJUST, Title: ""});
-        types.push({Name: JV.PROP_HANDLE_TYPE_ADD_DUMMY, Title: ""});
+        types.push({ Name: JV.PROP_HANDLE_TYPE_SORT, Title: "" });
+        types.push({ Name: JV.PROP_HANDLE_TYPE_FILTER, Title: "" });
+        types.push({ Name: JV.PROP_HANDLE_TYPE_BILLS_DATA_MOVE, Title: "" });
+        types.push({ Name: JV.PROP_HANDLE_TYPE_COMPONENT_MOVE, Title: "" });
+        types.push({ Name: JV.PROP_HANDLE_TYPE_SUM, Title: "" });
+        types.push({ Name: JV.PROP_HANDLE_TYPE_ADJUST, Title: "" });
+        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([0,1,2,3,4,5,6]);
+        me.setDisabledBandSelect([0, 1, 2, 3, 4, 5, 6]);
         me.build_handle_data_selection();
     },
-    setDisabledBandSelect: function(disabledIdxArr) {
+    setDisabledBandSelect: function (disabledIdxArr) {
         let me = this;
         if (me.typeTreeObj) {
             let nodes = me.typeTreeObj.getNodes();
@@ -310,38 +311,38 @@ let preHandleObj = {
         }
         switch (nodeType) {
             case JV.PROP_HANDLE_TYPE_SORT:
-                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "排序方式": "normal", "排序键值集":[]};
+                rst = { Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "排序方式": "normal", "排序键值集": [] };
                 break;
             case JV.PROP_HANDLE_TYPE_FILTER:
-                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "过滤键值集": []};
+                rst = { Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "过滤键值集": [] };
                 break;
             case JV.PROP_HANDLE_TYPE_BILLS_DATA_MOVE:
-                rst = {Name: "预处理环节", Title: "", "映射数据对象": "ration", "预处理类型": preHandleType};
+                rst = { Name: "预处理环节", Title: "", "映射数据对象": "ration", "预处理类型": preHandleType };
                 break;
             case JV.PROP_HANDLE_TYPE_COMPONENT_MOVE:
-                rst = {Name: "预处理环节", Title: "", "映射数据对象": "ration", "预处理类型": preHandleType};
+                rst = { Name: "预处理环节", Title: "", "映射数据对象": "ration", "预处理类型": preHandleType };
                 break;
             case JV.PROP_HANDLE_TYPE_SUM:
-                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "分组键值集": [], "统计键值集":[]};
+                rst = { Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "分组键值集": [], "统计键值集": [] };
                 break;
             case JV.PROP_HANDLE_TYPE_ADJUST:
-                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "数据调整集":[]};
+                rst = { Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "数据调整集": [] };
                 break;
             case JV.PROP_HANDLE_TYPE_ADD_DUMMY:
-                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "Dummy数据集":[]};
+                rst = { Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": preHandleType, "Dummy数据集": [] };
                 break;
             default:
-                rst = {Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": "排序", "排序方式": "normal", "排序键值集":[]};
+                rst = { Name: "预处理环节", Title: "", "映射数据对象": "bills", "预处理类型": "排序", "排序方式": "normal", "排序键值集": [] };
                 break;
         }
         return rst;
     },
-    addNewNode: function(nodeType) {
+    addNewNode: function (nodeType) {
         let me = this, item = me.createNewNode(nodeType);
         me.private_set_title(item);
         me.treeObj.addNodes(null, -1, [item], true);
     },
-    private_change_node_by_type: function(handleType, item) {
+    private_change_node_by_type: function (handleType, item) {
         let preHandleType = handleType;
         if (!handleType) {
             preHandleType = JV.PROP_HANDLE_TYPE_SORT;
@@ -377,7 +378,7 @@ let preHandleObj = {
         }
         // return rst;
     },
-    private_copy_node: function(src, dest) {
+    private_copy_node: function (src, dest) {
         let me = this;
         dest[JV.PROP_DATA_KEY] = src[JV.PROP_DATA_KEY];
         dest[JV.PROP_HANDLE_TYPE] = src[JV.PROP_HANDLE_TYPE];
@@ -394,7 +395,7 @@ let preHandleObj = {
             preHandleAddDummyObj.copyNode(src, dest);
         }
     },
-    private_set_title: function(node) {
+    private_set_title: function (node) {
         let nameStr = node[JV.PROP_NAME], idx = nameStr.indexOf("(");
         if (idx >= 0) {
             nameStr = nameStr.slice(0, idx);
@@ -402,7 +403,7 @@ let preHandleObj = {
         node[JV.PROP_NAME] = nameStr + "(" + node[JV.PROP_HANDLE_TYPE] + ")";
         node.Title = "映射数据对象:" + node[JV.PROP_DATA_KEY] + " | " + node[JV.PROP_HANDLE_TYPE];
     },
-    refreshByNode: function(treeNode) {
+    refreshByNode: function (treeNode) {
         let me = preHandleObj;
         if (me.typeTreeObj) {
             let nodes = me.typeTreeObj.getNodes();
@@ -438,7 +439,7 @@ let preHandleObj = {
             }
         }
     },
-    hide_all_dom: function() {
+    hide_all_dom: function () {
         $("#div_pre_handle_data")[0].style.display = "none";
         $("#div_sort_type")[0].style.display = "none";
         $("#div_sort_type_normal")[0].style.display = "none";
@@ -451,15 +452,15 @@ let preHandleObj = {
         $("#div_sort_tree")[0].style.display = "none";
         $("#div_sort_self_define")[0].style.display = "none";
     },
-    onPreHandleClick: function(event,treeId,treeNode) {
+    onPreHandleClick: function (event, treeId, treeNode) {
         //点击预处理环节 节点
         let me = preHandleObj;
         me.currentNode = treeNode;
-        me.setDisabledBandSelect([4,5,6]);
+        me.setDisabledBandSelect([4, 5, 6]);
         // me.setDisabledBandSelect([]);
         me.refreshByNode(treeNode);
     },
-    onTypeClick: function(event,treeId,treeNode) {
+    onTypeClick: function (event, treeId, treeNode) {
         //选择预处理类型(排序、过滤。。。)
         let me = preHandleObj;
         if (me.currentNode) {
@@ -470,7 +471,7 @@ let preHandleObj = {
             me.refreshByNode(me.currentNode);
         }
     },
-    onChangeDataMappingObj: function(dom, oprType) {
+    onChangeDataMappingObj: function (dom, oprType) {
         //更改(或选择)预处理环节中的 数据依据(就是说报表想预处理什么数据)
         let me = preHandleObj;
         if (oprType === "top") {
@@ -493,14 +494,14 @@ let preHandleObj = {
         }
         return rst;
     },
-    onBeforeDrop: function(treeId, treeNodes, targetNode, moveType){
+    onBeforeDrop: function (treeId, treeNodes, targetNode, moveType) {
         let rst = false;
         if (targetNode.level === 0 && moveType !== "inner") {
             rst = true;
         }
         return rst;
     },
-    onBeforeRemove: function(treeId, treeNode){
+    onBeforeRemove: function (treeId, treeNode) {
         let rst = true;
         if (treeNode.isParent) {
             rst = false;
@@ -509,14 +510,14 @@ let preHandleObj = {
         }
         return rst;
     },
-    addHoverDom: function(treeId, treeNode) {
+    addHoverDom: function (treeId, treeNode) {
         let me = preHandleObj, sObj = $("#" + treeNode.tId + "_span");
-        if ((treeNode.level > 0 && treeNode[JV.PROP_HANDLE_TYPE] !== JV.PROP_HANDLE_TYPE_FILTER) || ($("#addBtn_"+treeNode.tId).length > 0) ) return;
+        if ((treeNode.level > 0 && treeNode[JV.PROP_HANDLE_TYPE] !== JV.PROP_HANDLE_TYPE_FILTER) || ($("#addBtn_" + treeNode.tId).length > 0)) return;
         if (treeNode[JV.PROP_HANDLE_TYPE] === JV.PROP_HANDLE_TYPE_SORT && treeNode[JV.PROP_SORT_TYPE] === "accord_to_parent") {
             let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增子排序' onfocus='this.blur();'></span>";
             sObj.after(addStr);
-            let btn = $("#addBtn_"+treeNode.tId);
-            if (btn) btn.bind("click", function(){
+            let btn = $("#addBtn_" + treeNode.tId);
+            if (btn) btn.bind("click", function () {
                 let newSubNodes = [];
                 let newNode = me.createNewNode(treeNode[JV.PROP_HANDLE_TYPE]);
                 newNode.Name = "子排序";
@@ -530,8 +531,8 @@ let preHandleObj = {
         } else if (treeNode[JV.PROP_HANDLE_TYPE] === JV.PROP_HANDLE_TYPE_FILTER) {
             let addStr = "<span class='button add' id='addBtn_" + treeNode.tId + "' title='新增子过滤' onfocus='this.blur();'></span>";
             sObj.after(addStr);
-            let btn = $("#addBtn_"+treeNode.tId);
-            if (btn) btn.bind("click", function(){
+            let btn = $("#addBtn_" + treeNode.tId);
+            if (btn) btn.bind("click", function () {
                 let newSubNodes = [];
                 let newNode = me.createNewNode(treeNode[JV.PROP_HANDLE_TYPE]);
                 newNode.Name = "子过滤";
@@ -547,7 +548,7 @@ let preHandleObj = {
         }
     },
     removeHoverDom: function (treeId, treeNode) {
-        $("#addBtn_"+treeNode.tId).unbind().remove();
+        $("#addBtn_" + treeNode.tId).unbind().remove();
     },
     extractTabFields: function (rptTpl) {
         let me = this, nodes = me.treeObj.getNodes();
@@ -598,16 +599,16 @@ let preHandleSortObj = {
             case -1:
                 //unknown!
                 break;
-            case 0 :
+            case 0:
                 //normal
                 let keys = [];
                 for (let sortKeyItem of src[JV.PROP_SORT_KEYS]) {
-                    let item = {key: sortKeyItem.key, order: sortKeyItem.order};
+                    let item = { key: sortKeyItem.key, order: sortKeyItem.order };
                     keys.push(item);
                 }
                 dest[JV.PROP_SORT_KEYS] = keys;
                 break;
-            case 1 :
+            case 1:
                 //tree
                 let billKeys = [];
                 if (src[JV.PROP_FILTER_TOP_BILLS_NODES] && src[JV.PROP_FILTER_TOP_BILLS_NODES].length > 0) {
@@ -620,7 +621,7 @@ let preHandleSortObj = {
                 }
                 dest[JV.PROP_FILTER_OTHER_BILLS_NODES] = otherBillKeys;
                 break;
-            case 2 :
+            case 2:
                 //according to parent
                 dest[JV.PROP_PARENT_CHILD_SORT_KEY] = {};
                 dest[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_DATA_KEY] = src[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_PARENT_DATA_KEY];
@@ -636,14 +637,14 @@ let preHandleSortObj = {
                 if (src[JV.PROP_OTHER_SUB_SORT] !== null && src[JV.PROP_OTHER_SUB_SORT] !== undefined) {
                     dest.items = [];
                     for (let subSort of src[JV.PROP_OTHER_SUB_SORT]) {
-                        let destSubSort = {Name: "子排序"};
+                        let destSubSort = { Name: "子排序" };
                         me.copyNode(subSort, destSubSort);
                         destSubSort[JV.PROP_DATA_KEY] = src[JV.PROP_DATA_KEY];
                         dest.items.push(destSubSort);
                     }
                 }
                 break;
-            case 3 :
+            case 3:
                 //self define
                 dest[JV.PROP_SORT_TYPE_SELF_DEFINE_LOGIC] = src[JV.PROP_SORT_TYPE_SELF_DEFINE_LOGIC];
                 break;
@@ -663,7 +664,7 @@ let preHandleSortObj = {
                 case -1:
                     //unknown!
                     break;
-                case 0 :
+                case 0:
                     //normal
                     $("#div_sort_type_normal")[0].style.display = "";
                     idx = pre_handle_data_objects.indexOf(preHandleObj.currentNode[JV.PROP_DATA_KEY]);
@@ -678,7 +679,7 @@ let preHandleSortObj = {
                         }
                     }
                     break;
-                case 1 :
+                case 1:
                     //tree
                     //tree排序是我们特有的数据结构方式,与数据结构有关,非common用
                     $("#div_sort_tree")[0].style.display = "";
@@ -711,7 +712,7 @@ let preHandleSortObj = {
                         preHandleObj.currentNode[JV.PROP_FILTER_OTHER_BILLS_NODES] = [];
                     }
                     break;
-                case 2 :
+                case 2:
                     //according to parent
                     $("#div_sort_type_according_to_parent")[0].style.display = "";
                     $("#div_sort_type_parent_data")[0].style.display = "";
@@ -724,7 +725,7 @@ let preHandleSortObj = {
                     me.childTreeObj = $.fn.zTree.init($("#child_sorting_keys"), sortingKeysSetting, exposed_properties_arr[idx]);
                     me.checkupNode(preHandleObj.currentNode[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_CHILD_SORT_KEYS], me.childTreeObj);
                     break;
-                case 3 :
+                case 3:
                     //self define
                     $("#div_sort_self_define")[0].style.display = "";
                     $("#selfDefineSort")[0].value = preHandleObj.currentNode[JV.PROP_SORT_TYPE_SELF_DEFINE_LOGIC];
@@ -734,7 +735,7 @@ let preHandleSortObj = {
             }
         }
     },
-    checkupNode: function(keysArr, treeObj) {
+    checkupNode: function (keysArr, treeObj) {
         let nodes = treeObj.getNodes();
         for (let key of keysArr) {
             for (let node of nodes) {
@@ -745,7 +746,7 @@ let preHandleSortObj = {
             }
         }
     },
-    onCheck: function(event,treeId,treeNode) {
+    onCheck: function (event, treeId, treeNode) {
         let me = preHandleSortObj;
         if (treeId.indexOf("parent_sorting_keys") >= 0) {
             me.resetParentSort();
@@ -755,7 +756,7 @@ let preHandleSortObj = {
             me.resetNormalSort();
         }
     },
-    onTopBillsNodeCheck: function (event,treeId,treeNode) {
+    onTopBillsNodeCheck: function (event, treeId, treeNode) {
         let me = preHandleSortObj;
         if (treeNode.checked) {
             if (preHandleObj.currentNode[JV.PROP_FILTER_TOP_BILLS_NODES].indexOf(treeNode.Value) < 0) {
@@ -768,7 +769,7 @@ let preHandleSortObj = {
             }
         }
     },
-    onOtherBillsNodeCheck: function (event,treeId,treeNode) {
+    onOtherBillsNodeCheck: function (event, treeId, treeNode) {
         let me = preHandleSortObj;
         if (treeNode.checked) {
             if (preHandleObj.currentNode[JV.PROP_FILTER_OTHER_BILLS_NODES].indexOf(treeNode.Value) < 0) {
@@ -799,29 +800,29 @@ let preHandleSortObj = {
         }
         preHandleObj.currentNode[JV.PROP_PARENT_CHILD_SORT_KEY][JV.PROP_CHILD_SORT_KEYS] = sortKeys;
     },
-    resetNormalSort: function() {
+    resetNormalSort: function () {
         let me = preHandleSortObj;
         let nodes = me.normalTreeObj.getCheckedNodes();
         let normalSortKeys = [];
         for (let node of nodes) {
-            let keyObj = {key: node.Key, order: node.Order};
+            let keyObj = { key: node.Key, order: node.Order };
             normalSortKeys.push(keyObj);
         }
         preHandleObj.currentNode[JV.PROP_SORT_KEYS] = normalSortKeys;
     },
-    addDiyDom: function(treeId,treeNode) {
+    addDiyDom: function (treeId, treeNode) {
         let aObj = $("#" + treeNode.tId + IDMark_A);
-        let editStr = "<select class='selDemo' id='diySelect_" +treeNode.tId+ "'><option value='ascend'>升序 </option><option value='descend'>降序 </option></select>";
+        let editStr = "<select class='selDemo' id='diySelect_" + treeNode.tId + "'><option value='ascend'>升序 </option><option value='descend'>降序 </option></select>";
         aObj.after(editStr);
         let sel = $("#diySelect_" + treeNode.tId);
         if (sel) {
-            sel.bind("change", function(){
+            sel.bind("change", function () {
                 treeNode.Order = sel[0].value;
                 preHandleSortObj.resetNormalSort();
             });
         }
     },
-    onSortTypeChange: function(dom) {
+    onSortTypeChange: function (dom) {
         //排序类型的选择/更改
         let me = preHandleObj;
         me.hide_all_dom();
@@ -868,16 +869,16 @@ let preHandleSortObj = {
             case -1:
                 //unknown!
                 break;
-            case 0 :
+            case 0:
                 //normal
                 rst[JV.PROP_SORT_KEYS] = handleObj[JV.PROP_SORT_KEYS];
                 break;
-            case 1 :
+            case 1:
                 //tree
                 rst[JV.PROP_FILTER_TOP_BILLS_NODES] = handleObj[JV.PROP_FILTER_TOP_BILLS_NODES];
                 rst[JV.PROP_FILTER_OTHER_BILLS_NODES] = handleObj[JV.PROP_FILTER_OTHER_BILLS_NODES];
                 break;
-            case 2 :
+            case 2:
                 //according to parent
                 rst[JV.PROP_PARENT_CHILD_SORT_KEY] = handleObj[JV.PROP_PARENT_CHILD_SORT_KEY];
                 rst[JV.PROP_OTHER_SUB_SORT] = [];
@@ -892,7 +893,7 @@ let preHandleSortObj = {
                     }
                 }
                 break;
-            case 3 :
+            case 3:
                 //self define
                 rst[JV.PROP_SORT_TYPE_SELF_DEFINE_LOGIC] = handleObj[JV.PROP_SORT_TYPE_SELF_DEFINE_LOGIC];
                 break;
@@ -908,7 +909,7 @@ let preHandleFilterObj = {
     copyNode: function (src, dest) {
         let me = preHandleFilterObj, keys = [];
         for (let filterItem of src[JV.PROP_FILTER_KEYS]) {
-            let item = {key: filterItem.key};
+            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]) {
@@ -924,7 +925,7 @@ let preHandleFilterObj = {
         if (src[JV.PROP_OTHER_SUB_FILTER] && src[JV.PROP_OTHER_SUB_FILTER].length > 0) {
             dest.items = [];
             for (let subFilter of src[JV.PROP_OTHER_SUB_FILTER]) {
-                let dtlRst = {Name: "子过滤", Title: ""};
+                let dtlRst = { Name: "子过滤", Title: "" };
                 subFilter[JV.PROP_DATA_KEY] = src[JV.PROP_DATA_KEY];
                 me.copyNode(subFilter, dtlRst);
                 dtlRst[JV.PROP_HANDLE_TYPE] = src[JV.PROP_HANDLE_TYPE];
@@ -991,16 +992,16 @@ let preHandleFilterObj = {
             }
         }
     },
-    onCheck: function(event,treeId,treeNode) {
+    onCheck: function (event, treeId, treeNode) {
         let me = preHandleFilterObj;
         me.resetFilter();
     },
-    resetFilter: function() {
+    resetFilter: function () {
         let me = this;
         let nodes = me.treeObj.getCheckedNodes();
         let normalSortKeys = [];
         for (let node of nodes) {
-            let keyObj = {key: node.Key};
+            let keyObj = { key: node.Key };
             if (!node[JV.PROP_FILTER_CONDITION]) {
                 node[JV.PROP_FILTER_CONDITION] = "==";
             }
@@ -1014,7 +1015,7 @@ let preHandleFilterObj = {
         }
         preHandleObj.currentNode[JV.PROP_FILTER_KEYS] = normalSortKeys;
     },
-    build_filter_handle_data_selection_str: function(treeId,treeNode) {
+    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>");
@@ -1024,13 +1025,13 @@ let preHandleFilterObj = {
         rst.push("</select>");
         return rst.join("");
     },
-    build_filter_handle_data_detail_selection_str: function(treeId,treeNode) {
+    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("");
     },
-    build_individual_filter_selection_str: function (individualTypes,treeNode) {
+    build_individual_filter_selection_str: function (individualTypes, treeNode) {
         let rst = [];
         rst.push("<select class='selDemo' id='diyDataDetailSelect_" + treeNode.tId + "'>");
         for (let i = 0; i < individualTypes.length; i++) {
@@ -1039,7 +1040,7 @@ let preHandleFilterObj = {
         rst.push("</select>");
         return rst.join("");
     },
-    addDiyDom: function(treeId,treeNode) {
+    addDiyDom: function (treeId, treeNode) {
         let me = preHandleFilterObj;
         let aObj = $("#" + treeNode.tId + IDMark_A);
         if (treeNode.hasOwnProperty("isBoolean")) {
@@ -1070,9 +1071,9 @@ let preHandleFilterObj = {
             }
         } else {
             //注意:这是后面的DOM先生成
-            let dataDtlSelStr = me.build_filter_handle_data_detail_selection_str(treeId,treeNode);
+            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);
+            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);
@@ -1114,13 +1115,13 @@ let preHandleFilterObj = {
         //注:这里虽然是boolean选项,但实际有可能是0,1的选择(非true,false),所以需要设置node节点的booleanOptions
         me.resetFilter();
     },
-    filterConditionChange: function(event) {
+    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) {
+    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;
@@ -1139,12 +1140,12 @@ let preHandleFilterObj = {
             node[JV.PROP_FILTER_COMPARE_OBJ_KEY] = null;
         }
     },
-    filterCompareObjChange: function(event) {
+    filterCompareObjChange: function (event) {
         let me = preHandleFilterObj, sel = event.currentTarget;
         me.private_setup_compare_obj(sel);
         me.resetFilter();
     },
-    filterIndividualCompareObjKeyChange: function(event) {
+    filterIndividualCompareObjKeyChange: function (event) {
         let me = preHandleFilterObj, sel = event.currentTarget, tId = sel.id.slice(20);
         let inTxt = $("#diyInput_" + tId);
         if (inTxt) {
@@ -1154,7 +1155,7 @@ let preHandleFilterObj = {
         node[JV.PROP_FILTER_COMPARE_VAL] = sel.value;
         me.resetFilter();
     },
-    filterCompareObjKeyChange: function(event) {
+    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;

+ 33 - 33
web/maintain/structural_segment_lib/js/structural_segment_edit.js

@@ -35,39 +35,39 @@ $(document).ready(function () {
             alert("保存失败,请查看输入数据");
         }
     });
-    $("#createNormal").click(()=>{
-        $("#createNormal").click(async function() {
-            let explorer = [ 
-                {
-                    "valuationName" : "粤建市[2019]6号",
-                    "monomerType" : "building",
-                    "items" : [ 
-                        {
-                            "type" : "单项工程",
-                            "key" : "basicEngineering",
-                            "dispName" : "基础工程",
-                            "subItems" : [ 
-                                {
-                                    "type" : "单位工程",
-                                    "key" : "foundationTreatment",
-                                    "feeType" : "建筑工程",
-                                    "engineering" : "房屋建筑与装饰工程",
-                                    "dispName" : "基础处理与基坑支护工程",
-                                    "calcProgram" : "计算程序2018一般/简易计税(标准)-粤建市[2019]6号",
-                                    "IndicatorSegment" : "基础工程"
-                                }
-                            ],
-                            
-                        }
-                    ]
-                }
-            ];
-            try {
-                let jsonText =  JSON.stringify(explorer);
-                $("#templateLibs").val(JSON.stringify(JSON.parse(jsonText),null,4));
-            }catch (err){
-                console.log(err);
+
+    $("#createNormal").click( function() {
+        let explorer = [ 
+            {
+                "valuationName" : "粤建市[2019]6号",
+                "monomerType" : "building",
+                "items" : [ 
+                    {
+                        "type" : "单项工程",
+                        "key" : "basicEngineering",
+                        "dispName" : "基础工程",
+                        "subItems" : [ 
+                            {
+                                "type" : "单位工程",
+                                "key" : "foundationTreatment",
+                                "feeType" : "建筑工程",
+                                "engineering" : "房屋建筑与装饰工程",
+                                "dispName" : "基础处理与基坑支护工程",
+                                "calcProgram" : "计算程序2018一般/简易计税(标准)-粤建市[2019]6号",
+                                "IndicatorSegment" : "基础工程"
+                            }
+                        ],
+                        
+                    }
+                ]
             }
-        })
+        ];
+        try {
+            let jsonText =  JSON.stringify(explorer);
+            $("#templateLibs").val(JSON.stringify(JSON.parse(jsonText),null,4));
+        }catch (err){
+            console.log(err);
+        }
     })
+    
 });

+ 57 - 1
web/users/js/compilation.js

@@ -334,7 +334,12 @@ $(document).ready(function() {
                 $("#vvTax-area").show();
                 $("#add-compilation-title").text('添加车船税');
                 break;
+            case 'billCode':
+                $("#billCode-area").show();
+                $("#add-compilation-title").text('添加递延清单库');
+                break;    
         }
+
         $("#addcompilation").modal('show');
     });
 
@@ -350,7 +355,7 @@ $(document).ready(function() {
     });
 
     // 移除操作
-    $(".bill-list, .ration-list, .glj-list, .fee-list, .artificial-list, .program-list, .billsGuidance-list,.feature-list,.info-list,.progressive-list,.vvTax-list").on("click", ".remove-lib", function() {
+    $(".bill-list, .ration-list, .glj-list, .fee-list, .artificial-list, .program-list, .billsGuidance-list,.feature-list,.info-list,.progressive-list,.vvTax-list,.billCode-list").on("click", ".remove-lib", function() {
         $(this).parent().remove();
     });
 
@@ -588,6 +593,37 @@ $(document).ready(function() {
             }
         });
     })
+
+    // 修改是否提供免费版
+    $('#freeUse').change(function (val) {
+        $.ajax({
+            url: '/compilation/changeFreeUse',
+            type: 'post',
+            data: {id: id, freeUse: $(this).prop('checked')},
+            dataType: "json",
+            success: function(response) {
+                if (response.error !== 0) {
+                    alert('更改失败');
+                }
+            }
+        });
+    })
+
+    //更改版本号
+    $('#edition').change(function () {
+        let edition = $(this).val();
+        $.ajax({
+            url: '/compilation/setEdition',
+            type: 'post',
+            dataType: "json",
+            data: { id: id, edition: edition },
+            success: function (response) {
+                if (response.err !== 0) {
+                    alert('更改失败');
+                }
+            }
+        });
+    });
 });
 
 /**
@@ -609,6 +645,7 @@ function initCompilation() {
     let infoData = infoList == undefined ? [] : JSON.parse(infoList);
     let progressiveData = progressiveList == undefined?[]: JSON.parse(progressiveList);
     let vvTaxData = vvTaxList == undefined?[]: JSON.parse(vvTaxList);
+    let billCodeData = billCodeList == undefined?[]: JSON.parse(billCodeList);
     /*mainTreeCol = mainTreeCol !== '' ? mainTreeCol.replace(/\n/g, '\\n') : mainTreeCol;
     billsTemplateData = billsTemplateData.replace(/\n/g, '\\n');
 
@@ -730,6 +767,14 @@ function initCompilation() {
         html += tmpHtml;
     }
     $("select[name='vvTax_lib']").children("option").first().after(html);
+
+     //递延清单库文件
+     html = '';
+     for(let tmp of billCodeData){
+         let tmpHtml = '<option value="' + tmp.ID + '">' + tmp.name + '</option>';
+         html += tmpHtml;
+     }
+     $("select[name='billCode_lib']").children("option").first().after(html);
 }
 
 /**
@@ -751,6 +796,7 @@ function getAndValidData(model) {
     let infoLib = $("select[name='info_lib']").children("option:selected").val();
     let progressiveLib = $("select[name='progressive_lib']").children("option:selected").val();
     let vvTaxLib = $("select[name='vvTax_lib']").children("option:selected").val();
+    let billCodeLib = $("select[name='billCode_lib']").children("option:selected").val();
 
 
     if (name === '' && model === 'all') {
@@ -773,6 +819,10 @@ function getAndValidData(model) {
     if (model === 'vvTax' && (vvTaxLib === '' || vvTaxLib === undefined)) {
         throw '请选择车船税文件';
     }
+    if (model === 'billCode' && (billCodeLib === '' || billCodeLib === undefined)) {
+        throw '请选择递延清单库文件';
+    }
+
 
     if (model === 'glj' && (gljLib === '' || gljLib === undefined)) {
         throw '请选择人材机库';
@@ -801,6 +851,7 @@ function getAndValidData(model) {
     let infoString = $("select[name='info_lib']").children("option:selected").text();
     let progressiveString = $("select[name='progressive_lib']").children("option:selected").text();
     let vvTaxString = $("select[name='vvTax_lib']").children("option:selected").text();
+    let billCodeLibString = $("select[name='billCode_lib']").children("option:selected").text();
 
 
     let result = {
@@ -848,7 +899,12 @@ function getAndValidData(model) {
         vvTax: {
             id: vvTaxLib,
             name: vvTaxString
+        },
+        billCode: {
+            id: billCodeLib,
+            name: billCodeLibString
         }
+
     };
     return result;
 }

+ 21 - 0
web/users/views/compilation/engineering.html

@@ -159,6 +159,26 @@
                             </div>
                     </div>
 
+                    <div class="row">
+                        <div class="form-group col-md-3">
+                            <label>递延清单库</label>
+                            <div class="billCode-list">
+                                <% if (Object.keys(libData).length > 0 && libData.billCode_lib && libData.billCode_lib.length > 0) { %>
+                                <% libData.billCode_lib.forEach(function (billCode, index){ %>
+                                <p class="form-control-static">
+                                    <a class="pull-right text-danger remove-lib" data-model="billCode" title="移除" data-id="<%= billCode.id %>">
+                                        <span class="glyphicon glyphicon-remove"></span>
+                                    </a>
+                                    <input type="hidden" name="billCode_lib" data-id="<%= billCode.id %>" value="<%= JSON.stringify({id: billCode.id, name: billCode.name}) %>">
+                                    <% if (index === 0) {%><i class="glyphicon glyphicon-flag"></i>&nbsp;<% } %><%= billCode.name %>
+                                </p>
+                                <% }) %>
+                                <% } %>
+                            </div>
+                            <a href="#" class="btn btn-link btn-sm add-compilation" data-model="billCode">添加</a>
+                        </div>
+                    </div>
+
                     <div class="col-md-12">
                         <a data-toggle="modal" data-target="#other_setting" class="btn btn-primary btn-sm " style="margin-right:5px">显示设置</a>
                     </div>
@@ -288,6 +308,7 @@
     let infoList = '<%- infoList %>';
     let progressiveList = '<%- progressiveList %>';
     let vvTaxList = '<%- vvTaxList %>';
+    let billCodeList = '<%- billCodeList %>';
     let colSpread = null;
     let colEditSpread = null;
 </script>

+ 6 - 0
web/users/views/compilation/index.html

@@ -300,6 +300,12 @@
                             <% }) %>
                     </select>
                 </td></tr>
+                <tr>
+                    <td>
+                        <p><span> 提供免费版:</span> <input type="checkbox" id="freeUse"  <% if (selectedCompilation.freeUse) { %> checked <% } %>></p>       
+                    </td>
+                </tr>
+                <tr><td><span>版本号:</span><input class="form-control" type="text" id="edition" value="<%= selectedCompilation.edition%>"></td></tr>
             </table>
         </div>
         <input type="hidden" name="id" value="<%= selectedCompilation._id %>" id="compilation-id">

+ 10 - 0
web/users/views/compilation/modal.html

@@ -81,6 +81,16 @@
                         </div>
                     </div>
                 </div>
+                <div class="form-group" id="billCode-area">
+                    <label>递延清单库</label>
+                    <div class="row">
+                        <div class="col-xs-12">
+                            <select class="form-control" name="billCode_lib">
+                                <option value="">请选择递延清单库</option>
+                            </select>
+                        </div>
+                    </div>
+                </div>
                 <div class="form-group" id="artificial-area">
                     <label>人工系数</label>
                     <div class="row">