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

Merge branch '1.0.0_online' of http://192.168.1.12:3000/SmartCost/ConstructionOperation

laiguoran пре 7 година
родитељ
комит
3862759a44
66 измењених фајлова са 2376 додато и 612 уклоњено
  1. 12 1
      config/config.js
  2. BIN
      lib/ztree/css/img/diy/10.png
  3. 2 0
      modules/all_models/compilation.js
  4. 5 0
      modules/all_models/manager.js
  5. 26 0
      modules/all_models/ration_template.js
  6. 1 0
      modules/all_models/stdBills_bills.js
  7. 2 0
      modules/all_models/stdRation_coe.js
  8. 4 0
      modules/all_models/stdRation_ration.js
  9. 11 10
      modules/all_models/tpl_tree_node.js
  10. 52 1
      modules/bills_lib/controllers/bills_permissionController.js
  11. 198 1
      modules/bills_lib/models/bills_lib_interfaces.js
  12. 2 0
      modules/bills_lib/routes/bills_lib_routes.js
  13. 2 0
      modules/material_replace_lib/controllers/material_replace_controller.js
  14. 4 0
      modules/material_replace_lib/facade/material_replace_facade.js
  15. 9 0
      modules/ration_repository/controllers/ration_controller.js
  16. 4 0
      modules/ration_repository/controllers/ration_repository_controller.js
  17. 92 4
      modules/ration_repository/models/ration_item.js
  18. 1 0
      modules/ration_repository/routes/ration_rep_routes.js
  19. 16 0
      modules/reports/rpt_component/helper/jpc_helper_field.js
  20. 6 6
      modules/reports/rpt_component/jpc_ex.js
  21. 83 62
      modules/reports/rpt_component/jpc_flow_tab.js
  22. 2 2
      modules/reports/util/rpt_construct_data_util.js
  23. 6 2
      modules/reports/util/rpt_excel_util.js
  24. 1 1
      modules/reports/util/rpt_pdf_util.js
  25. 1 1
      modules/std_billsGuidance_lib/facade/facades.js
  26. 1 1
      modules/std_billsGuidance_lib/routes/routes.js
  27. 1 0
      modules/std_glj_lib/controllers/gljController.js
  28. 5 0
      modules/sys_tools/models/sys_model.js
  29. 20 2
      modules/users/controllers/compilation_controller.js
  30. 17 1
      modules/users/models/compilation_model.js
  31. 11 6
      modules/users/models/manager_model.js
  32. 1 0
      modules/users/routes/compilation_route.js
  33. 4 0
      public/web/id_tree.js
  34. 5 0
      public/web/rpt_value_define.js
  35. 11 4
      test/demo/stringTest.js
  36. 173 160
      web/common/js/slideResize.js
  37. 2 2
      web/maintain/billsGuidance_lib/css/main.css
  38. 56 43
      web/maintain/billsGuidance_lib/html/zhiyin.html
  39. 177 230
      web/maintain/billsGuidance_lib/js/billsGuidance.js
  40. 7 2
      web/maintain/billsGuidance_lib/js/global.js
  41. 96 2
      web/maintain/bills_lib/html/main.html
  42. 6 2
      web/maintain/bills_lib/scripts/bills_lib_ajax.js
  43. 1 1
      web/maintain/main_col_lib/js/main_col_edit.js
  44. 10 0
      web/maintain/main_col_lib/js/main_tree_col.js
  45. 77 0
      web/maintain/material_replace_lib/html/edit_新编辑版本.html
  46. 478 0
      web/maintain/material_replace_lib/js/material_replace_edit_新编辑版本.js
  47. 13 0
      web/maintain/ration_repository/css/main.css
  48. 29 15
      web/maintain/ration_repository/dinge.html
  49. 165 31
      web/maintain/ration_repository/js/coe.js
  50. 6 0
      web/maintain/ration_repository/js/gljSelect.js
  51. 2 0
      web/maintain/ration_repository/js/global.js
  52. 64 3
      web/maintain/ration_repository/js/ration.js
  53. 1 1
      web/maintain/ration_repository/js/ration_assist.js
  54. 6 0
      web/maintain/ration_repository/js/ration_glj.js
  55. 197 0
      web/maintain/ration_repository/js/ration_template.js
  56. 6 1
      web/maintain/ration_repository/js/section_tree.js
  57. 6 0
      web/maintain/report/html/rpt_tpl_dtl_info.html
  58. 48 4
      web/maintain/report/js/rpt_tpl_main.js
  59. 10 5
      web/maintain/std_glj_lib/html/gongliao.html
  60. 38 1
      web/maintain/std_glj_lib/js/glj.js
  61. 39 1
      web/maintain/std_glj_lib/js/global.js
  62. 40 0
      web/users/js/compilation.js
  63. 1 0
      web/users/js/login.js
  64. 1 0
      web/users/views/compilation/index.html
  65. 2 2
      web/users/views/login/index.html
  66. 1 1
      web/users/views/manager/index.html

Разлика између датотеке није приказан због своје велике величине
+ 12 - 1
config/config.js


BIN
lib/ztree/css/img/diy/10.png


+ 2 - 0
modules/all_models/compilation.js

@@ -53,6 +53,8 @@ let modelSchema = {
     description: String,
     //代码覆盖路径
     overWriteUrl:String,
+    //例题建设项目ID
+    example: Array,
     // 发布时间
     release_time: {
         type: Number,

+ 5 - 0
modules/all_models/manager.js

@@ -55,6 +55,11 @@ let modelSchema = {
         type: Number,
         default: 0
     },
+    //职称
+    position: {
+        type: String,
+        default: ''
+    },
     // 超级管理员 1为超级管理员
     super_admin: {
         type: Number,

+ 26 - 0
modules/all_models/ration_template.js

@@ -0,0 +1,26 @@
+/**
+ * Created by zhang on 2018/11/26.
+ */
+
+var mongoose = require('mongoose'),
+    Schema = mongoose.Schema;
+
+let ration_template =  new Schema({
+    ID:String,
+    projectID: Number,
+    rationID:String,
+    createLocation:Number,//提取位置
+    templateList:[new Schema({
+        code:String,
+        name:String,
+        type:String,
+        billsLocation:String,//这个是清单编号
+        fxID:String,//这个是分项对应的ID
+        unit:String,
+        quantity:String,
+        coe:String,
+        billID:String//记取位置对应的清单ID
+    },{ _id: false })]
+},{versionKey:false});
+
+mongoose.model('ration_template', ration_template,"ration_template");

+ 1 - 0
modules/all_models/stdBills_bills.js

@@ -14,6 +14,7 @@ const stdBills_bills = new Schema({
             ruleText: String,
             engineering: Number, //工程专业,填计算程序工程专业ID
             Expression: String,
+            comment: String, //备注,清单精灵处输入
             jobs: [],
             items: [],
             recharge:String,

+ 2 - 0
modules/all_models/stdRation_coe.js

@@ -12,6 +12,8 @@ const coeSchema = new Schema({
     amount: String,                 // 调整的量
     gljCode: String,
     gljName: String,
+    replaceCode:String,
+    replaceName:String,
     _id: false
 });
 

+ 4 - 0
modules/all_models/stdRation_ration.js

@@ -47,6 +47,10 @@ const rationItemSchema = new Schema({
     rationCoeList: Array,
     rationAssList: [rationAssItemSchema],
     rationInstList: [rationInstSchema],
+    rationTemplateList: {
+        type: Array,
+        default: []
+    },
     isDeleted: {type: Boolean, default: false}
 });
 

+ 11 - 10
modules/all_models/tpl_tree_node.js

@@ -28,14 +28,15 @@ let TplNodeSchema = new Schema({
 });
 
 let RptTplTreeSchema = new Schema({
-    compilationId: String,  //编办的ObjectId
-    // engineerId: Number,     //工程专业Id(参考 /modules/common/const/engineering.js)
-    userId: String,        //用户名的object_id串
-    properties: [],         //这是一个预留的属性,假定未来还会有不同的划分细节(如:招标/投标/清单 ... etc)
-    name: String,           //显示名称
-    released: Boolean,      //是否已发布
-    isDeleted: Boolean,     //删除标记
-    items: []               //TplNodeSchema entity
+    compilationId: String,      //编办的ObjectId
+    // engineerId: Number,         //工程专业Id(参考 /modules/common/const/engineering.js)
+    userId: String,             //用户名的object_id串
+    properties: [],             //这是一个预留的属性,假定未来还会有不同的划分细节(如:招标/投标/清单 ... etc)
+    name: String,               //显示名称
+    released: Boolean,          //是否已发布
+    isDeleted: Boolean,         //删除标记
+    flags: Schema.Types.Mixed,  //额外标记集合(这些标记可能会影响到前端显示,如‘计税方式’等)
+    items: []                   //TplNodeSchema entity
 });
 RptTplTreeSchema.statics.findAndModify = function (query, sort, doc, options, callback) {
     return this.collection.findAndModify(query, sort, doc, options, callback);
@@ -43,8 +44,8 @@ RptTplTreeSchema.statics.findAndModify = function (query, sort, doc, options, ca
 
 mongoose.model("rpt_tpl_tree", RptTplTreeSchema, "rpt_tpl_tree");
 /*
-let TreeNodeModel = mongoose.model("rpt_tpl_tree", TreeNodeSchema, "rpt_tpl_tree");
-/*/
+ let TreeNodeModel = mongoose.model("rpt_tpl_tree", TreeNodeSchema, "rpt_tpl_tree");
+ /*/
 // let TreeNodeModel = mongoose.model("rpt_tpl_tree", RptTplTreeSchema, "rpt_tpl_tree");
 //*/
 

+ 52 - 1
modules/bills_lib/controllers/bills_permissionController.js

@@ -2,10 +2,12 @@
  * Created by Zhong on 2017/8/2.
  */
 let billsController = require("./bills_lib_controllers");
+let billsLibDao = require("./../models/bills_lib_interfaces");
 import baseController from "../../common/base/base_controller";
 import fs from 'fs';
 import path from 'path';
 import multiparty from 'multiparty';
+const excel = require("node-xlsx");
 const uuidV1 = require('uuid/v1');
 
 const shareDir = 'public/share/images';
@@ -68,6 +70,56 @@ class billsPermContr extends baseController{
         billsController.isUsed(req, res);
     }
     /*
+     * 导入标准清单(确定节点结构:深度数组)
+     * */
+    importBills(req, res){
+        let form = new multiparty.Form({uploadDir: './public'});
+        const allowHeader = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
+        let uploadFullName;
+        form.parse(req, async function (err, fields, files) {
+            try {
+                const file = typeof files.file !== 'undefined' ? files.file[0] : null;
+                if (err || !file) {
+                    throw '上传失败。';
+                }
+                if (file.headers['content-type'] === undefined || allowHeader.indexOf(file.headers['content-type']) < 0) {
+                    throw '不支持该类型';
+                }
+                const billsLibId = typeof fields.billsLibId !== 'undefined' && fields.billsLibId.length > 0 ? fields.billsLibId[0] : null;
+                if (!billsLibId) {
+                    throw '请选择一个清单库。';
+                }
+                let hasData = await billsLibDao.hasData(billsLibId);
+                if (hasData) {
+                    throw '请新建一个新的清单库,或删除库中的清单后再导入。';
+                }
+                // 重命名文件名
+                uploadFullName = './public/' + file.originalFilename;
+                fs.renameSync(file.path, uploadFullName);
+                const sheet = excel.parse(uploadFullName);
+                if (sheet[0] === undefined || sheet[0].data === undefined || sheet[0].data.length <= 0) {
+                    throw 'excel没有对应数据';
+                }
+                //插入清单
+                await billsLibDao.importBills(billsLibId, sheet[0].data);
+                // 删除文件
+                if(uploadFullName && fs.existsSync(uploadFullName)){
+                    fs.unlinkSync(uploadFullName);
+                }
+                res.json({error: 0, data: null, msg: ''});
+
+            } catch (err) {
+                console.log(err);
+                // 删除文件
+                if(uploadFullName && fs.existsSync(uploadFullName)){
+                    fs.unlinkSync(uploadFullName);
+                }
+                res.json({error: 1, data: null, msg: err});
+            }
+        });
+    }
+
+    /*
     *上传图片
     * */
     uploadImg(req, res){
@@ -172,7 +224,6 @@ class billsPermContr extends baseController{
             res.json({error: 1, data: {pageCount: 1, currentImgsUrl: []}, message: err});
         }
     }
-
 }
 
 export default billsPermContr;

+ 198 - 1
modules/bills_lib/models/bills_lib_interfaces.js

@@ -11,6 +11,7 @@ let ItemCharacter = mongoose.model('std_bills_lib_itemCharacter');
 let moment = require("moment");
 let billsGuidanceLib = mongoose.model('std_billsGuidance_lib');
 const engLibModel = mongoose.model('engineering_lib');
+let uuid = require('uuid');
 let billsLibDao = function(){};
 
 
@@ -3091,7 +3092,203 @@ billsLibDao.prototype.edUpdateItem = function(data, callback){
         }
     });
 };
-//
+
+billsLibDao.prototype.hasData = async function (billsLibId) {
+    let bills = await Bills.findOne({billsLibId: billsLibId});
+    if (bills) {
+        return true;
+    }
+    return false;
+};
+
+billsLibDao.prototype.importBills = async function (billsLibId, sheetData) {
+    //实际节点深度数组,下标等于深度,元素为该为上一个该深度清单数据, 数组长度-1等于最大深度
+    let depthArr = [];
+    const deepest = 10000;
+    //深度的值,并不是真正的深度,只是三种类型节点(顶节点、中间节点、底节点)的深度值,节点根据深度值与深度数组最大深度的比较,对深度数组进行更新,
+    //并且确定父子上下关系
+    function getDepthValue(code){
+        let midReg = /\.{1,}/g;
+        //root
+        if (code.length === 1) {
+            return 0;
+        }
+        if (midReg.test(code)) {
+            return code.match(midReg).length;
+        }
+        return deepest;
+    }
+    let billsDatas = [],
+        jobMapping = {},
+        itemMapping = {};
+    function getDivideData(data){
+        let rst = [];
+        let divideReg = /[\n,\r]/g,
+            prefixReg = /\d+\.{1}/g; //前缀 1. 2.
+        let divideArr = data.split(divideReg);
+        for (let dData of divideArr) {
+            if (dData !== '') {
+                rst.push(dData.replace(prefixReg, ''));
+            }
+        }
+        return rst;
+    }
+    //设置总工作内容/项目特征映射
+    function setBillsSubMapping(subData, mapping){
+        for (let data of subData) {
+            if (!mapping[data]) {
+                let code = Object.keys(mapping).length + 1;
+                mapping[data] = {billsLibId: billsLibId, code: code, content: data, deleted: false};
+            }
+        }
+    }
+    let row = -1;
+    //从表格中获取清单数据
+    for (let rowData of sheetData) {
+        row++;
+        if (row === 0) {
+            continue;
+        }
+        let bills = {
+            deleted: false,
+            billsLibId: billsLibId,
+            parent: null,
+            ID: uuid.v1(),
+            ParentID: -1,
+            NextSiblingID: -1,
+            code: typeof rowData[0] !== 'undefined' ? rowData[0] : '',
+            name: typeof rowData[1] !== 'undefined' ? rowData[1] : '',
+            unit: typeof rowData[2] !== 'undefined' ? rowData[2] : '',
+            ruleText: typeof rowData[3] !== 'undefined' ? rowData[3] : '',
+            recharge: '',
+        };
+        let jobData = typeof rowData[4] !== 'undefined' ? getDivideData(rowData[4]) : [],
+            itemData = typeof rowData[5] !== 'undefined' ? getDivideData(rowData[5]) :[];
+        bills.jobData = jobData;
+        bills.itemData = itemData;
+        setBillsSubMapping(jobData, jobMapping);
+        setBillsSubMapping(itemData, itemMapping);
+        billsDatas.push(bills);
+    }
+    //设置工作内容、项目特征id
+    async function setSubId(moduleName, subMapping) {
+        let idx = 0,
+            subCount = Object.keys(subMapping).length;
+        let subCounter = await counter.counterDAO.getIDAfterCount(moduleName, subCount);
+        for (let mapping in subMapping) {
+            let id = subCounter.sequence_value - (subCount - 1) + idx;
+            let sub = subMapping[mapping];
+            sub.id = id;
+            idx++;
+        }
+    }
+    await setSubId(counter.moduleName.billsLib_jobs, jobMapping);
+    await setSubId(counter.moduleName.billsLib_items, itemMapping);
+    //获得清单、工作内容/项目特征关联数组
+    //subDatas为清单工作内容/项目特征的字符串数组 eg: ['场内运输', '开挖'];
+    //mapping为总工作内容/项目特征字符串映射 eg: {'场内运输': {content: '场内运输', id: 1, code: 1, deleted: false}}
+    function getBillsSubRef(subDatas, mapping) {
+        let rst = [];
+        for (let i = 0; i < subDatas.length; i++) {
+            let data = subDatas[i];
+            if (mapping[data]) {
+                rst.push({id: mapping[data].id, serialNo: i + 1});
+            }
+        }
+        return rst;
+    }
+    //设置完整的清单数据(树结构、工作内容/项目特征)
+    for (let i = 0; i < billsDatas.length; i++) {
+        let bills = billsDatas[i],
+            preBills = billsDatas[i - 1];
+        //树结构相关设置
+        let maxDepth = depthArr.length - 1;
+        let depthV = getDepthValue(bills.code);
+        //前节点为最底层节点,且这个节点为最底层节点,则深度相同
+        let preIsDeepest = preBills && getDepthValue(preBills.code) === deepest ? true : false;
+        if (preIsDeepest && depthV === deepest) {
+            depthV = maxDepth;
+        }
+        if (depthV > maxDepth) {
+            let parent = depthArr[depthArr.length - 1];
+            if (parent) {
+                bills.ParentID = parent.ID;
+                bills.parent = parent;
+            }
+            depthArr.push(bills);
+        } else {
+            let parent = depthArr[depthV -1];
+            if (parent) {
+                bills.ParentID = parent.ID;
+                bills.parent = parent;
+            }
+            depthArr[depthV].NextSiblingID = bills.ID;
+            depthArr.splice(depthV, 1);
+            if (depthV < maxDepth) { //切割
+                depthArr = depthArr.slice(0, depthV);
+            }
+            depthArr.push(bills);
+        }
+        //工作内容项目特征
+        bills.jobs = getBillsSubRef(bills.jobData, jobMapping);
+        bills.items = getBillsSubRef(bills.itemData, itemMapping);
+    }
+    function getSectionInfo(bills){
+        let parentIDs = [];
+        let sectionInfo = {first: null, second: null, third: null};
+        getParent(bills);
+        if(parentIDs[parentIDs.length - 1]){
+            sectionInfo.first = parentIDs[parentIDs.length - 1];
+        }
+        if(parentIDs[parentIDs.length - 2]){
+            sectionInfo.second = parentIDs[parentIDs.length - 2];
+        }
+        if(parentIDs[parentIDs.length - 3]){
+            sectionInfo.third = parentIDs[parentIDs.length - 3];
+        }
+        return sectionInfo;
+        function getParent(bills){
+            if(bills.parent){
+                parentIDs.push(bills.parent.ID);
+                getParent(bills.parent);
+            }
+        }
+    }
+    //设置sectionInfo
+    for (let bills of billsDatas) {
+        bills.sectionInfo = getSectionInfo(bills);
+    }
+    //插入清单
+    let bulks = [];
+    for (let bills of billsDatas) {
+        delete bills.parent;
+        bulks.push({insertOne: {document: bills}});
+    }
+    if (bulks.length > 0) {
+        await Bills.bulkWrite(bulks);
+    }
+    //清除工作内容、项目特征
+    await JobContent.remove({billsLibId: billsLibId});
+    await ItemCharacter.remove({billsLibId: billsLibId});
+    function getSubBulks(subMapping) {
+        let rst = [];
+        for (let mapping in subMapping) {
+            let sub = subMapping[mapping];
+            rst.push({insertOne: {document: sub}});
+        }
+        return rst;
+    }
+    //插入工作内容
+    let jobBulks = getSubBulks(jobMapping);
+    if (jobBulks.length > 0) {
+        await JobContent.bulkWrite(jobBulks);
+    }
+    //插入项目特征
+    let itemBulks = getSubBulks(itemMapping);
+    if (itemBulks.length > 0) {
+        await ItemCharacter.bulkWrite(itemBulks);
+    }
+};
 
 
 module.exports = new billsLibDao();

+ 2 - 0
modules/bills_lib/routes/bills_lib_routes.js

@@ -29,6 +29,8 @@ module.exports =function (app) {
     billsRouter.post("/deleteStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.deleteStdBillsLib);
     billsRouter.post("/renameStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.renameStdBillsLib);
     billsRouter.post("/getStdBillsLibName", billsLibContr.auth, billsLibContr.init, billsLibContr.getStdBillsLibName);
+    //导入清单
+    billsRouter.post('/importBills', billsContr.importBills);
     //上传图片
     billsRouter.post('/uploadImg', billsContr.uploadImg);
     //删除图片

+ 2 - 0
modules/material_replace_lib/controllers/material_replace_controller.js

@@ -34,6 +34,7 @@ class ReplaceController extends BaseController{
             let gljLib = await  materialFacade.findGLJLibByComID(compilationId);
             let billsList = await materialFacade.findBillsByLibID(libID);
             //let templateDatas = await materialFacade.getTemplateDatasByLibID(libID);
+            //let stdBills = await  materialFacade.getStdBillsByLib(billsLibId);
 
             let randerData = {
                 title:'材料替换库',
@@ -45,6 +46,7 @@ class ReplaceController extends BaseController{
                 billsLibId:billsLibId,
                 gljLibID:gljLib.ID,
                 libID:libID,
+                //stdBills:JSON.stringify(stdBills),
                 LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
                 layout: 'maintain/common/html/edit_layout'
             };

+ 4 - 0
modules/material_replace_lib/facade/material_replace_facade.js

@@ -76,6 +76,10 @@ let materialReplaceLib = {
     },
     getMaterialByBillsID : async function(billsID){
        return  await replaceMaterialModel.find({billsItemID:billsID});
+    },
+    getStdBillsByLib:async function(libID){
+        let bills = await stdBillsModel.find({billsLibId: libID},['ID','code','name','items']);
+        return bills;
     }
 };
 function prepareDatas(data) {//整理数据

+ 9 - 0
modules/ration_repository/controllers/ration_controller.js

@@ -108,6 +108,15 @@ class RationController extends BaseController{
             callback(req, res, err, '', null);
         });
     }
+    async updateRationTemplate(req, res){
+        let data = JSON.parse(req.body.data);
+        try {
+            let newTemplate = await rationItem.updateRationTemplate(data.rationRepId, data.rationID, data.templateData);
+            callback(req, res, 0, 'success', newTemplate);
+        } catch (err) {
+            callback(req, res, 1, err, null);
+        }
+    }
 }
 
 export default RationController;

+ 4 - 0
modules/ration_repository/controllers/ration_repository_controller.js

@@ -197,6 +197,7 @@ class RationRepositoryController extends baseController {
                     await rationItem.batchUpdateSectionIdFromExcel(sheet[0].data);
                 if (rationItem.failGLJList && rationItem.failGLJList.length > 0) {
                     responseData.msg = rationItem.failGLJList.join("\r\n");
+                    rationItem.failGLJList = [];
                 }
                 // 删除文件
                 if(uploadFullName && fs.existsSync(uploadFullName)){
@@ -265,6 +266,9 @@ class RationRepositoryController extends baseController {
             let stdGLJList = {};
             let stdGLJListByID = {};
             for (const tmp of stdGLJData) {
+                if (tmp.priceProperty && tmp.priceProperty.price1) {
+                    tmp.basePrice = tmp.priceProperty.price1;
+                }
                 stdGLJList[tmp.code.toString()] = tmp.ID;
                 stdGLJListByID[tmp.ID] = tmp;
             }

+ 92 - 4
modules/ration_repository/models/ration_item.js

@@ -101,15 +101,49 @@ rationItemDAO.prototype.sortToNumber = function (datas) {
     }
 };
 
-rationItemDAO.prototype.getRationItemsBySection = function(rationRepId, sectionId,callback){
+rationItemDAO.prototype.getRationItemsBySection = async function(rationRepId, sectionId,callback){
     let me = this;
-    rationItemModel.find({"rationRepId": rationRepId, "sectionId": sectionId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
+    try {
+        let rations = await rationItemModel.find({rationRepId: rationRepId, sectionId: sectionId});
+        me.sortToNumber(rations);
+        let matchRationIDs = [],
+            matchRations = [];
+        for (let ration of rations) {
+            if (ration.rationTemplateList) {
+                for (let rt of ration.rationTemplateList) {
+                    if (rt.rationID) {
+                        matchRationIDs.push(rt.rationID);
+                    }
+                }
+            }
+        }
+        if (matchRationIDs.length > 0) {
+            matchRations = await rationItemModel.find({ID: {$in: matchRationIDs}}, '-_id ID code name');
+        }
+        for (let mr of matchRations) {
+            for (let ration of rations) {
+                if (ration.rationTemplateList) {
+                    for (let rt of ration.rationTemplateList) {
+                        if (rt.rationID && rt.rationID === mr.ID) {
+                            rt.code = mr.code ? mr.code : '';
+                            rt.name = mr.name ? mr.name : '';
+                        }
+                    }
+                }
+            }
+        }
+        callback(false,"Get items successfully", rations);
+    } catch (err) {
+        console.log(err);
+        callback(true, "Fail to get items", "");
+    }
+  /*  rationItemModel.find({"rationRepId": rationRepId, "sectionId": sectionId, "$or": [{"isDeleted": null}, {"isDeleted": false} ]},function(err,data){
         if(err) callback(true, "Fail to get items", "");
         else {
             me.sortToNumber(data);
             callback(false,"Get items successfully", data);
         }
-    })
+    })*/
 };
 rationItemDAO.prototype.mixUpdateRationItems = function(rationLibId, lastOpr, sectionId, updateItems, addItems, rIds, callback){
     var me = this;
@@ -144,7 +178,16 @@ rationItemDAO.prototype.removeRationItems = function(rationLibId, lastOpr, rIds,
             } else {
                 rationRepositoryDao.updateOprArr({ID: rationLibId}, lastOpr, moment(Date.now()).format('YYYY-MM-DD HH:mm:ss'), function (err) {
                     if(!err){
-                        callback(false, "Remove successfully", docs);
+                        rationItemModel.update({rationRepId: rationLibId}, {$pull: {rationTemplateList: {rationID: {$in: rIds}}}}, function (theErr) {
+                            if (!theErr) {
+                                callback(false, "Remove successfully", docs);
+                            } else {
+                                callback(true, "Fail to remove", false);
+                            }
+
+                        });
+                    } else {
+                        callback(true, "Fail to remove", false);
                     }
                 })
             }
@@ -228,6 +271,7 @@ rationItemDAO.prototype.addRationItems = function(rationLibId, lastOpr, sectionI
 };
 
 rationItemDAO.prototype.updateRationItems = function(rationLibId, lastOpr, sectionId, items,callback){
+    console.log('enter============');
     var functions = [];
     for (var i=0; i < items.length; i++) {
         functions.push((function(doc) {
@@ -632,6 +676,50 @@ rationItemDAO.prototype.updateAnnotation = function (lastOpr, repId, updateArr,
     });
 };
 
+//更新定额下模板关联
+rationItemDAO.prototype.updateRationTemplate = async function (rationRepId, rationID, templateData) {
+    //自动匹配定额
+    let matachCodes = [],
+        matchRations = [];
+    //要保存的数据
+    let saveData = [];
+    for (let data of templateData) {
+        if (data.code) {
+            matachCodes.push(data.code);
+        }
+    }
+    matachCodes = Array.from(new Set(matachCodes));
+    if (matachCodes.length > 0) {
+        matchRations = await rationItemModel.find({rationRepId: rationRepId, code: {$in: matachCodes}}, '-_id ID code name');
+    }
+    let validData = [];
+    //设置展示数据
+    for (let data of templateData) {
+        let match = false;
+        for (let ration of matchRations) {
+            if (data.code && data.code === ration.code) {
+                match = true;
+                data.name = ration.name;
+                data.rationID = ration.ID;
+                break;
+            }
+        }
+        if (!match) {
+            data.code = '';
+            data.name = '';
+        }
+        if (data.type || data.code || data.name || data.billsLocation) {
+            validData.push(data);
+        }
+    }
+    for (let data of validData) {
+        saveData.push({rationID: data.rationID ? data.rationID : null, type: data.type, billsLocation: data.billsLocation});
+    }
+    //更新
+    await rationItemModel.update({ID: rationID}, {$set: {rationTemplateList: saveData}});
+    return validData;
+};
+
 //计算导入数据的价格
 rationItemDAO.prototype.calcForRation = function (stdGljList, ration) {
     const processDecimal = -6;

+ 1 - 0
modules/ration_repository/routes/ration_rep_routes.js

@@ -59,6 +59,7 @@ module.exports =  function (app) {
     apiRouter.post("/getRationsCodes",rationController.auth, rationController.init, rationController.getRationsCodes);
     apiRouter.post("/updateJobContent",rationController.auth, rationController.init, rationController.updateJobContent);
     apiRouter.post("/updateAnnotation",rationController.auth, rationController.init, rationController.updateAnnotation);
+    apiRouter.post("/updateRationTemplate",rationController.auth, rationController.init, rationController.updateRationTemplate);
 
     apiRouter.post("/createNewGljTypeNode",repositoryGljController.auth, gljController.init, gljController.createNewGljTypeNode);
     apiRouter.post("/updateGljNodes",repositoryGljController.auth, gljController.init, gljController.updateGljNodes);

+ 16 - 0
modules/reports/rpt_component/helper/jpc_helper_field.js

@@ -123,6 +123,22 @@ let JpcFieldHelper = {
                     }
                 }
             }
+            if (!isEx) {
+                let dis_detail_fields = rptTpl[JV.NODE_NO_MAPPING_FIELDS];
+                for (let i = 0; i < tab_fields.length; i++) {
+                    if (tab_fields[i][JV.PROP_IS_AUTO_HEIGHT]) {
+                        for (let j = 0; j < dis_detail_fields.length; j++) {
+                            if (tab_fields[i]["FieldID"] === dis_detail_fields[j]["ID"]) {
+                                let item = [];
+                                item[0] = JV.BLANK_FIELD_INDEX;
+                                item[1] = tab_fields[i];
+                                rstFieldsIdx.push(item);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
         }
     }
 };

+ 6 - 6
modules/reports/rpt_component/jpc_ex.js

@@ -164,7 +164,7 @@ JpcExSrv.prototype.createNew = function(){
         me.formulas = JpcFunc.createNew(rptTpl);
     };
 
-    JpcResult.analyzeData = function(rptTpl, dataObj, defProperties, option) {
+    JpcResult.analyzeData = function(rptTpl, dataObj, defProperties, option, outputType) {
         let me = this, dftPagingOption = option||JV.PAGING_OPTION_NORMAL;
         //1. data object
         let dataHelper = JpcData.createNew();
@@ -189,20 +189,20 @@ JpcExSrv.prototype.createNew = function(){
         //3. formulas
         me.executeFormulas(JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me);
         //4. paging
-        me.paging(rptTpl, dataObj, defProperties, dftPagingOption);
+        me.paging(rptTpl, dataObj, defProperties, dftPagingOption, outputType);
         //alert('analyzeData was completed!');
         //for garbage collection:
         dataHelper = null;
     };
-    JpcResult.paging = function(rptTpl, dataObj, defProperties, option) {
+    JpcResult.paging = function(rptTpl, dataObj, defProperties, option, outputType) {
         let me = this, dftPagingOption = option||JV.PAGING_OPTION_NORMAL;
         if (me.flowTab) {
             if (me.isFollowMode) {
-                me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, me.flowTabEx);
+                me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, me.flowTabEx, outputType);
             } else {
-                me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null);
+                me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null, outputType);
                 if (me.flowTabEx) {
-                    me.exTotalPages = me.flowTabEx.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null);
+                    me.exTotalPages = me.flowTabEx.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null, outputType);
                     //console.log('ad-hoc flow pages: ' + me.exTotalPages);
                 }
                 me.totalPages += me.exTotalPages;

+ 83 - 62
modules/reports/rpt_component/jpc_flow_tab.js

@@ -20,11 +20,12 @@ JpcFlowTabSrv.prototype.createNew = function(){
     //grpPageInfo :{"segGrpRecStartIdx": 0, "insertedGrpRecAmt": 0, "preAddPageGrpInfo": null}; //纯属解释参数grpPageInfo结构
     //valueIdx: [isFollowMode, type(normal, auto-height, group), valueIndex, sub-value-index(自动行高特有), total-value-amount(自动行高特有)] //解释 dispValueIdxLst 数据构造
     function private_addPageValue(ValuedIdxLst, sortedSequence, grpSequenceInfo, startRecIdx, maxRecPerPage,page_seg_map, segIdx, pageIdx, grpPageInfo, isFollow, segAutoHeightInfo, prePageLeftAutoHeightRecAmt) {
-        let vIdx = [], preAmt = 0, insertedGrpAmt = 0, grp_lines = 0, followMode = (isFollow)?JV.TYPE_FOLLOW_MODE:-1, nextPageAutoHeightRecAmt = 0;
+        let vIdx = [], vFirstIdx = [], preAmt = 0, insertedGrpAmt = 0, grp_lines = 0, followMode = (isFollow)?JV.TYPE_FOLLOW_MODE:-1, nextPageAutoHeightRecAmt = 0;
         if (grpSequenceInfo && grpPageInfo) {
             if (grpPageInfo[JV.PROP_PRE_ADD_GRP_REC_INFO].length > 0) {
                 for (let grpLineIdx of grpPageInfo[JV.PROP_PRE_ADD_GRP_REC_INFO]) {
-                    vIdx.push([followMode, JV.DISPLAY_VAL_TYPE_GROUP, grpPageInfo[JV.PROP_SEG_GRP_IDX], grpLineIdx]);
+                    //vIdx.push([followMode, JV.DISPLAY_VAL_TYPE_GROUP, grpPageInfo[JV.PROP_SEG_GRP_IDX], grpLineIdx]);
+                    vFirstIdx.push([followMode, JV.DISPLAY_VAL_TYPE_GROUP, grpPageInfo[JV.PROP_SEG_GRP_IDX], grpLineIdx]);
                 }
                 grpPageInfo[JV.PROP_SEG_GRP_IDX]++;
             }
@@ -127,6 +128,10 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 if (private_normal_add_rec(vi)) break;
             }
         }
+        if (vFirstIdx.length > 0) {
+            vIdx = vIdx.concat(vFirstIdx);
+            //备注: 在一开始就加grp的情况下,这些数据应该放在后面才对
+        }
         page_seg_map.push([pageIdx, segIdx]);
         ValuedIdxLst.push(vIdx);
         return nextPageAutoHeightRecAmt;
@@ -148,7 +153,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
 
         me.auto_height_fields_idx = [];//那些被标记为判断自动行高的指标集合
         me.auto_height_info = [];
-        me.group_fields = [];
+        me.group_check_fields = [];
         me.group_sum_fields = [];
         me.group_sum_values = null;
         me.group_node_info = null; //记录在哪个seg及到哪条记录后有group sum信息
@@ -167,8 +172,17 @@ JpcFlowTabSrv.prototype.createNew = function(){
         if (rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_SEG_SUM]) JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_SEG_SUM][JV.PROP_SUM_FIELDS], me.seg_sum_tab_fields, me.seg_sum_fields_idx, me.isEx);
         if (rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_PAGE_SUM]) JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_PAGE_SUM][JV.PROP_SUM_FIELDS], me.page_sum_tab_fields, me.page_sum_fields_idx, me.isEx);
         if (rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP]) {
-            JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_FIELDS], me.group_fields, null, me.isEx);
-            JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_SUM_FIELDS], me.group_sum_fields, null, me.isEx);
+            JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_FIELDS], me.group_check_fields, null, me.isEx);
+            if (rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES]) {
+                for (let grpLine of rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES]) {
+                    if (grpLine[JV.PROP_GROUP_SUM_KEYS] && grpLine[JV.PROP_GROUP_SUM_KEYS].length > 0) {
+                        JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, grpLine[JV.PROP_GROUP_SUM_KEYS], me.group_sum_fields, null, me.isEx);
+                    }
+                }
+            }
+            for (let grp_sum_f of me.group_sum_fields) {
+                grp_sum_f[JV.PROP_SUM_KEY] = `grp_sum_key_` + grp_sum_f[JV.PROP_FIELD_ID];
+            }
         }
         JpcFieldHelper.findAutoHeightFieldIdx(rptTpl, rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_CONTENT][JV.PROP_FLOW_FIELDS], me.auto_height_fields_idx, me.isEx);
         for (let si = 0; si < dataSeq.length; si++) {
@@ -182,7 +196,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         let data_details = me.isEx?dataObj[JV.DATA_DETAIL_DATA_EX]:dataObj[JV.DATA_DETAIL_DATA],
             data_fields = [];
         for (let i = 0; i < me.seg_sum_fields_idx.length; i++) {
-            if (typeof(me.seg_sum_fields_idx[i])=="object") {
+            if (typeof(me.seg_sum_fields_idx[i]) === "object") {
                 let exField = JE.F(me.seg_sum_fields_idx[i][JV.PROP_ID], $CURRENT_RPT);
                 if (exField) {
                     data_fields.push(exField["data_field"]);
@@ -215,43 +229,17 @@ JpcFlowTabSrv.prototype.createNew = function(){
                     for (let j = 0; j < me.segments[i].length; j++) {
                         //3. start to sum
                         // rowGrandTotal[di] = rowGrandTotal[di] + 1.0 * JpcFieldHelper.getValue(data_fields[di], me.segments[i][j]);
-                        rowGrandTotal[di] = rowGrandTotal[di] + parseFloat(parseFloat(JpcFieldHelper.getValue(data_fields[di], me.segments[i][j])).toFixed(precisionAmt));
-                    }
-                }
-                me.segSumValLst.push(rowGrandTotal);
-            }
-        }
-    };
-    JpcFlowTabResult.getFlowFieldById = function (fieldKey, rptTpl) {
-        let rst = null;
-        if (rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP] && rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES] && rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES].length > 0) {
-            for (let grpLine of rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES]) {
-                if (grpLine[JV.PROP_GROUP_SUM_KEYS] && grpLine[JV.PROP_GROUP_SUM_KEYS].length > 0) {
-                    for (let sumKey of grpLine[JV.PROP_GROUP_SUM_KEYS]) {
-                        if (sumKey[JV.PROP_SUM_KEY] === fieldKey) {
-                            rst = sumKey;
-                            break;
-                        }
-                    }
-                }
-                if (rst) break;
-            }
-        }
-        if (!(rst) && rptTpl[JV.NODE_FLOW_INFO_EX] && rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP] && rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES] && rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES].length > 0) {
-            for (let grpLine of rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES]) {
-                if (grpLine[JV.PROP_GROUP_SUM_KEYS] && grpLine[JV.PROP_GROUP_SUM_KEYS].length > 0) {
-                    for (let sumKey of grpLine[JV.PROP_GROUP_SUM_KEYS]) {
-                        if (sumKey[JV.PROP_SUM_KEY] === fieldKey) {
-                            rst = sumKey;
-                            break;
+                        let sv = JpcFieldHelper.getValue(data_fields[di], me.segments[i][j]);
+                        if (sv) {
+                            rowGrandTotal[di] = rowGrandTotal[di] + parseFloat(parseFloat(sv).toFixed(precisionAmt));
                         }
                     }
                 }
-                if (rst) break;
+                me.segSumValLst.push(rowGrandTotal);
             }
         }
-        return rst;
     };
+
     JpcFlowTabResult.sumUpGrp = function (rptTpl, $CURRENT_RPT, dataObj, segIdx, preGrpIdx, nexGrpIdx) {
         let me = this, segDataIdx = me.segments[segIdx];
         for (let j = 0; j < me.group_sum_fields.length; j++) {
@@ -268,7 +256,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                     if (sum_field[JV.PROP_PRECISION] && sum_field[JV.PROP_PRECISION].type === `fixed`) {
                         precisionAmt = sum_field[JV.PROP_FIXED_PRECISION_AMT];
                     } else {
-                        let flowF = me.getFlowFieldById(me.group_sum_fields[j][JV.PROP_SUM_KEY], rptTpl);
+                        let flowF = me.group_sum_fields[j]; //调整后,me.group_sum_fields[j]就是group lines下数组SumKey_S的元素值,无需再找
                         if (flowF && !strUtil.isEmptyString(flowF[JV.PROP_FORMAT])) {
                             let idx = flowF[JV.PROP_FORMAT].indexOf('.');
                             if (idx >= 0) {
@@ -287,7 +275,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
     };
     JpcFlowTabResult.setupGroupingData = function (rptTpl, dataObj, $CURRENT_RPT) {
         let me = this;
-        if (me.group_fields.length > 0 && me.group_sum_fields.length > 0) {
+        if (me.group_check_fields.length > 0 && me.group_sum_fields.length > 0) {
             me.group_sum_values = [];
             me.group_node_info = [];
             let CURRENT_FLOW_INFO = (me.isEx)?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
@@ -307,8 +295,8 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 for (let di = 0; di < segDataIdx.length; di++) {
                     let hasDiff = false;
                     if (di > 1) {
-                        for (let i = 0; i < me.group_fields.length; i++) {
-                            let grp_field = JE.F(me.group_fields[i][JV.PROP_FIELD_ID], $CURRENT_RPT);
+                        for (let i = 0; i < me.group_check_fields.length; i++) {
+                            let grp_field = JE.F(me.group_check_fields[i][JV.PROP_FIELD_ID], $CURRENT_RPT);
                             if (grp_field) {
                                 let data_field = null;
                                 if (grp_field[JV.PROP_AD_HOC_DATA]) {
@@ -341,7 +329,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
             }
         }
     };
-    JpcFlowTabResult.setupAutoHeightData = function(bands, segIdx, rptTpl, dataObj, $CURRENT_RPT, defProperties) {
+    JpcFlowTabResult.setupAutoHeightData = function(bands, segIdx, rptTpl, dataObj, $CURRENT_RPT, defProperties, outputType) {
         let me = this;
         if (me.auto_height_fields_idx.length > 0) {
             let CURRENT_FLOW_INFO = (me.isEx)?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
@@ -372,11 +360,24 @@ JpcFlowTabSrv.prototype.createNew = function(){
             let private_get_max_lines_of_the_record = function(theRecIdx) {
                 let rst = 1;
                 for (let loop = 0; loop < me.auto_height_fields_idx.length; loop++) {
+                    /*
                     let data_field = null;
                     let tab_field = me.auto_height_fields_idx[loop][1];
                     if (me.auto_height_fields_idx[loop][0] !== JV.BLANK_FIELD_INDEX) {
                         data_field = data_details[me.auto_height_fields_idx[loop][0]];
                     }
+                    /*/
+                    let tab_field = me.auto_height_fields_idx[loop][1];
+                    let data_field = null,
+                        map_data_field = JE.F(tab_field[JV.PROP_FIELD_ID], $CURRENT_RPT);
+                    if (me.auto_height_fields_idx[loop][0] !== JV.BLANK_FIELD_INDEX && (typeof me.auto_height_fields_idx[loop][0] !== 'object')) {
+                        data_field = data_details[me.auto_height_fields_idx[loop][0]];
+                    } else {
+                        if (map_data_field) {
+                            data_field = map_data_field[JV.PROP_AD_HOC_DATA];
+                        }
+                    }
+                    //*/
                     if (data_field) {
                         let value = JpcFieldHelper.getValue(data_field, theRecIdx);
                         let area = JpcAreaHelper.outputArea(tab_field[JV.PROP_AREA], band, 1, 1, 0, 1, 0, 1, 0, false, false);
@@ -410,6 +411,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                             }
                         }
                         if (accAmt > rst) rst = accAmt;
+                        // if (hasSplitStr && outputType !== JV.OUTPUT_TYPE_EXCEL) {
                         if (hasSplitStr) {
                             let newValArr = [];
                             for (let i = 0; i < values.length; i++) {
@@ -423,6 +425,8 @@ JpcFlowTabSrv.prototype.createNew = function(){
                             splitStrArr = [];
                             newValArr = [];
                         }
+                        //备注: 如果outputType是excel类型,那么就只保留原始的分行符,无需介入分行,由excel本身去处理分行,只需要保留足够的空间即可。
+                        //      根据最新需求,暂时不考虑excel类型输出,换回原来逻辑
                     }
                 }
                 return rst;
@@ -455,7 +459,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         }
     };
 
-    JpcFlowTabResult.preSetupPages = function (rptTpl, dataObj, defProperties, option, $CURRENT_RPT, followTabEx) {
+    JpcFlowTabResult.preSetupPages = function (rptTpl, dataObj, defProperties, option, $CURRENT_RPT, followTabEx, outputType) {
         //换一种思路来整理流水式数据
         let me = this, rst = 1, counterRowRec = 0, counterRowRecEx = 0, maxRowRec = 1, pageIdx = 0, currentRecAmt = 0;
         me.paging_option = option||JV.PAGING_OPTION_NORMAL;
@@ -502,6 +506,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 maxRowRec = JpcFlowTabHelper.getMaxRowsPerPage(bands, rptTpl, me.isEx);
             }
             let handledRowAmt = 0; //handledRowAmt纪录的是真正处理过的显示行数,包含了空白行,主要是为分页用(自动行高)
+            let segRestRecAmt = 0; //一般情况下为0,只有在特殊情况下才需要,如09-x表中,正常流水一页显示不了的时候,就有大问题了
             function private_addPage(segIdx, grpSeqInfo, isFollow, isMix, mixSplitPoint) {
                 private_resetBandArea();
                 me.pageStatusLst.push(pageStatus.slice(0));
@@ -516,6 +521,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                         redundantRecAmt++;
                     }
                 }
+                let restRecAmt = 0;
                 if (isMix) {
                     //先处理上半部分
                     prePageLeftAutoHeightRecAmt = private_addPageValue(me.dispValueIdxLst, me.segments[segIdx], grpSeqInfo, counterRowRec, mixSplitPoint,me.page_seg_map, segIdx, pageIdx, grpPageInfo, false, me.auto_height_info, prePageLeftAutoHeightRecAmt);
@@ -523,7 +529,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                         private_chk_handle_rec_amt(dv, false);
                     }
                     //再处理下半部分
-                    let restRecAmt = maxRowRec - me.dispValueIdxLst[me.dispValueIdxLst.length - 1].length; //备注:在一些极端条件下,mixSplitPoint这个分割点不合适处理下半部分数据,以实际生成的value-index数量为准
+                    restRecAmt = maxRowRec - me.dispValueIdxLst[me.dispValueIdxLst.length - 1].length; //备注:在一些极端条件下,mixSplitPoint这个分割点不合适处理下半部分数据,以实际生成的value-index数量为准
                     // private_addPageValue(me.dispValueIdxLst, followTabEx.segments[segIdx], null, counterRowRecEx, maxRowRec - mixSplitPoint, me.page_seg_map, segIdx, pageIdx, null, true, null, 0);
                     private_addPageValue(me.dispValueIdxLst, followTabEx.segments[segIdx], null, counterRowRecEx, restRecAmt, me.page_seg_map, segIdx, pageIdx, null, true, null, 0);
                     for (let dv of me.dispValueIdxLst[me.dispValueIdxLst.length - 1]) {
@@ -548,6 +554,10 @@ JpcFlowTabSrv.prototype.createNew = function(){
                     }
                 }
                 currentRecAmt -= redundantRecAmt; //在自动行高调整场景下,需要减去冗余的数量
+                if (restRecAmt < 0) {
+                    currentRecAmt -= restRecAmt;
+                    segRestRecAmt = restRecAmt;
+                }
             }
             for (let segIdx = 0; segIdx < me.segments.length; segIdx++) {
                 let grpSeqInfo = (me.group_node_info)?me.group_node_info[segIdx]:null;
@@ -555,6 +565,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 let grpRecAmtEx = 0;
                 let accAutoHeightAmt = 0; //累计的自动行高数量
                 handledRowAmt = 0; //初始化每一段的已处理纪录行数
+                segRestRecAmt = 0;
                 if (followTabEx && followTabEx.group_node_info) {
                     grpRecAmtEx = followTabEx.group_node_info.length * followTabEx.group_lines_amt;
                 }
@@ -564,7 +575,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 grpPageInfo[JV.PROP_GRP_LINES] = me.group_lines_amt;
                 pageStatus[JV.STATUS_SEGMENT_START] = true;
                 private_resetBandArea();
-                me.setupAutoHeightData(bands, segIdx, rptTpl, dataObj, $CURRENT_RPT, defProperties);
+                me.setupAutoHeightData(bands, segIdx, rptTpl, dataObj, $CURRENT_RPT, defProperties, outputType);
                 let threshold = 0;
                 currentRecAmt = 0;
                 counterRowRec = 0;
@@ -572,10 +583,13 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 let ttlSegRecAmtNormal = me.segments[segIdx].length + grpRecAmt; //正常的segment下的数据长度累计(含grouping data)
                 let ttlSegRecAmt = (followTabEx)?(me.segments[segIdx].length + grpRecAmt + followTabEx.segments[segIdx].length + grpRecAmtEx):(me.segments[segIdx].length + grpRecAmt); //所有的segment下的数据长度累计(包括ex部分)
                 let adHocAutoHeightAmt = 0;
+                let normalContentAmt = 0;
+                let exBuffer = 0;
                 let adHocAutoHeightGrpStartIdx = 0;
                 if (me.auto_height_fields_idx.length > 0) {
                     for (let loop = 0; loop < me.auto_height_info[segIdx].length; loop++) {
                         adHocAutoHeightAmt += (me.auto_height_info[segIdx][loop] - 1);
+                        normalContentAmt++;
                         if (me.group_node_info && me.group_node_info[segIdx]) {
                             if (me.group_node_info[segIdx][adHocAutoHeightGrpStartIdx] === loop) {
                                 adHocAutoHeightGrpStartIdx++;
@@ -584,6 +598,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                     }
                     ttlSegRecAmtNormal += adHocAutoHeightAmt;
                     ttlSegRecAmt += adHocAutoHeightAmt;
+                    if (adHocAutoHeightAmt > 0) exBuffer = grpRecAmt;
                 }
                 //自动行高调整在多流水合并方式时,只支持前部分(后期需要再加)
                 while (true) {
@@ -604,8 +619,8 @@ JpcFlowTabSrv.prototype.createNew = function(){
                     }
                     if ((ttlSegRecAmtNormal < ttlSegRecAmt) || (followTabEx !== null)) {
                         //有流水拓展,并且是follow mode
-                        // if (currentRecAmt + adHocAutoHeightAmt + maxRowRec > ttlSegRecAmtNormal) {
-                        if (currentRecAmt + accAutoHeightAmt + adHocAutoHeightAmt + maxRowRec > ttlSegRecAmtNormal) {
+                        if (currentRecAmt + accAutoHeightAmt + exBuffer + maxRowRec > ttlSegRecAmtNormal) {
+                        // if (currentRecAmt + accAutoHeightAmt + adHocAutoHeightAmt + maxRowRec > ttlSegRecAmtNormal) {
                             // if (currentRecAmt + adHocAutoHeightAmt >= ttlSegRecAmtNormal) {
                             if (currentRecAmt + accAutoHeightAmt + adHocAutoHeightAmt >= ttlSegRecAmtNormal) {
                                 //纯 followTabEx 数据
@@ -647,7 +662,12 @@ JpcFlowTabSrv.prototype.createNew = function(){
                                         private_addPage(segIdx, grpSeqInfo, false, true, ttlSegRecAmtNormal);
                                     }
                                 } else {
-                                    private_addPage(segIdx, grpSeqInfo, false, true, ttlSegRecAmtNormal);
+                                    //在这里要考虑如果有多页正常的流水数据情况,那么就得考虑这页有多少条普通流水记录,不应该一刀切地用ttlSegRecAmtNormal
+                                    let splitPoint = ttlSegRecAmtNormal - handledRowAmt ;
+                                    // if (splitPoint > (exBuffer + maxRowRec)) {
+                                    //     splitPoint = splitPoint % (exBuffer + maxRowRec);
+                                    // }
+                                    private_addPage(segIdx, grpSeqInfo, false, true, splitPoint);
                                 }
                             }
                         } else {
@@ -684,7 +704,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                     }
                     //检测是否可退出
                     // if ((currentRecAmt + accAutoHeightAmt + adHocAutoHeightAmt >= ttlSegRecAmt) && (pageIdx % me.multiCols === 0)) {
-                    if (handledRowAmt >= ttlSegRecAmt && (pageIdx % me.multiCols === 0)) {
+                    if (handledRowAmt >= (ttlSegRecAmt + segRestRecAmt) && (pageIdx % me.multiCols === 0)) {
                         //备注:这里必须得考虑多栏的情况,否则会造成pageStatus出界的问题
                         break;
                     }
@@ -904,7 +924,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
                         for (let idx_ex = 0; idx_ex < tab_fields_ex.length; idx_ex++) {
                             let tab_fieldex = tab_fields_ex[idx_ex];
                             let data_fieldex = null, map_data_fieldex = JE.F(tab_fieldex[JV.PROP_FIELD_ID], $CURRENT_RPT);
-                            if (me.disp_fields_ex_idx[idx_ex] !== JV.BLANK_FIELD_INDEX && (typeof me.disp_fields_idx[idx_ex] !== 'object')) {
+                            if (me.disp_fields_ex_idx[idx_ex] !== JV.BLANK_FIELD_INDEX && (typeof me.disp_fields_ex_idx[idx_ex] !== 'object')) {
                                 data_fieldex = data_details_ex[me.disp_fields_ex_idx[idx_ex]];
                             } else {
                                 if (map_data_fieldex) {
@@ -949,7 +969,10 @@ JpcFlowTabSrv.prototype.createNew = function(){
                             }
                             // rowGrandTotal[di] = rowGrandTotal[di] + 1.0 * JpcFieldHelper.getValue(page_sum_data_fields[di], contentValuesIdx[rowIdx][2]);
                             if (contentValuesIdx[rowIdx][2] >= 0) {
-                                rowGrandTotal[di] = rowGrandTotal[di] + parseFloat(parseFloat(JpcFieldHelper.getValue(page_sum_data_fields[di], contentValuesIdx[rowIdx][2])).toFixed(precisionAmt));
+                                let psv = JpcFieldHelper.getValue(page_sum_data_fields[di], contentValuesIdx[rowIdx][2]);
+                                if (psv) {
+                                    rowGrandTotal[di] = rowGrandTotal[di] + parseFloat(parseFloat(psv).toFixed(precisionAmt));
+                                }
                             }
                         }
                     }
@@ -962,14 +985,11 @@ JpcFlowTabSrv.prototype.createNew = function(){
                             if (contentValuesIdx[rowIdx][3] === grpIdx) {
                                 let grp_line = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_GROUP_LINES][grpIdx];
                                 if (page === 1) {
-                                    let sumFields = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_GROUP][JV.PROP_SUM_FIELDS];
-                                    for (let sumF of sumFields) {
-                                        if (grp_line[JV.PROP_GROUP_SUM_KEYS] && grp_line[JV.PROP_GROUP_SUM_KEYS].length > 0) {
-                                            for (let grp_sum_field of grp_line[JV.PROP_GROUP_SUM_KEYS]) {
-                                                if (grp_sum_field[JV.PROP_SUM_KEY] === sumF[JV.PROP_SUM_KEY]) {
-                                                    let map_field = JE.F(sumF[JV.PROP_FIELD_ID], $CURRENT_RPT);
-                                                    JpcFieldHelper.resetFormat(grp_sum_field, map_field, customizeCfg);
-                                                }
+                                    if (grp_line[JV.PROP_GROUP_SUM_KEYS] && grp_line[JV.PROP_GROUP_SUM_KEYS].length > 0) {
+                                        for (let grp_sum_field of grp_line[JV.PROP_GROUP_SUM_KEYS]) {
+                                            if (grp_sum_field[JV.PROP_FIELD_ID]) {
+                                                let map_field = JE.F(grp_sum_field[JV.PROP_FIELD_ID], $CURRENT_RPT);
+                                                JpcFieldHelper.resetFormat(grp_sum_field, map_field, customizeCfg);
                                             }
                                         }
                                     }
@@ -1125,7 +1145,8 @@ JpcFlowTabSrv.prototype.createNew = function(){
             let segIdx = JpcCommonHelper.getSegIdxByPageIdx(page, me.page_seg_map);
             let curSegGrpSum = me.group_sum_values[segIdx];
             for (let sumFieldNode of grp_line[JV.PROP_GROUP_SUM_KEYS]) {
-                let value = curSegGrpSum[sumFieldNode[JV.PROP_SUM_KEY]][grpValueIdx[2]];
+                // let value = curSegGrpSum[sumFieldNode[JV.PROP_SUM_KEY]][grpValueIdx[2]];
+                let value = curSegGrpSum[`grp_sum_key_` + sumFieldNode[JV.PROP_FIELD_ID]][grpValueIdx[2]];
                 let sumFldRst = JpcTextHelper.outputDirectValue(sumFieldNode, value,  band, unitFactor, rows, rowIdx, cols, colIdx, me.multiCols, multiColIdx);
                 rst.push(sumFldRst);
             }
@@ -1236,13 +1257,13 @@ function combineAutoHeightCells(prepareObj, page, controls) {
                         rst.push(sameColCells[i].cellIdx); //记下Cell的位置,在函数外消除
                         //如果到了最后一条数据,得判断firstMergeCell是否满格(即数据是满的,有可能有些格数据也有折行但不是自动行高判断指标)
                         //不满格的cell的Vertical强制设置为 'center'
-                        if (i === sameColCells.length - 1 && validValueAmt !== fullValidValueAmt) {
+                        if (i === sameColCells.length - 1 && validValueAmt !== fullValidValueAmt && (fullValidValueAmt / validValueAmt > 2.5) ) {
                             firstMergeCell[JV.PROP_CONTROL].VerticalForExcel = 'center';
                         }
                     } else {
                         //碰到新开始的自动行高行,判断原先的firstMergeCell是否满格(即数据是满的,有可能有些格数据也有折行但不是自动行高判断指标)
                         //不满格的cell的Vertical强制设置为 'center'
-                        if (validValueAmt !== fullValidValueAmt) {
+                        if (validValueAmt !== fullValidValueAmt && (fullValidValueAmt / validValueAmt > 2.5)) {
                             firstMergeCell[JV.PROP_CONTROL].VerticalForExcel = 'center';
                         }
                         firstMergeCell = sameColCells[i].cell;

+ 2 - 2
modules/reports/util/rpt_construct_data_util.js

@@ -270,7 +270,7 @@ class Rpt_Data_Extractor {
                 setupFunc($PROJECT.SUMMARY, `ConstructDetail`, {"data": rawDataObj.ConstructDetail});
             }
             if (rawDataObj.Segment) {
-                setupMainFunc($PROJECT.SUMMARY, `Segment`, rawDataObj.Construct);
+                setupMainFunc($PROJECT.SUMMARY, `Segment`, rawDataObj.Segment);
             }
             if (rawDataObj.SegmentDetail) {
                 setupFunc($PROJECT.SUMMARY, `SegmentDetail`, {"data": rawDataObj.SegmentDetail});
@@ -1281,7 +1281,7 @@ function ext_getPropety(propKey) {
                     if (pi === propKey.length - 1) rst.push('');
                 }
             } else {
-                if (doc.hasOwnProperty("property")) {
+                if (doc.hasOwnProperty("property") && doc["property"].hasOwnProperty(propKey)) {
                     rst.push(doc["property"][propKey]);
                 } else if (doc.hasOwnProperty(propKey)) {
                     rst.push(doc[propKey]);

+ 6 - 2
modules/reports/util/rpt_excel_util.js

@@ -432,9 +432,13 @@ function writeSheet(pageData, sheetData, paperSize, sharedStrList, stylesObj, ap
         return rst;
     };
     let private_getSharedStrIdx = function(val) {
-        let rst = sharedStrList.indexOf(val);
+        let strVal = val;
+        if (val === null) {
+            strVal = "";
+        }
+        let rst = sharedStrList.indexOf(strVal);
         if (rst < 0) {
-            sharedStrList.push(val);
+            sharedStrList.push(strVal);
             rst = sharedStrList.length - 1;
         }
         return rst;

+ 1 - 1
modules/reports/util/rpt_pdf_util.js

@@ -234,7 +234,7 @@ function export_pdf_file (pageData, paperSize, fName, callback) {
                     doc.fontSize(dftFontHeight);
                     options.width = w;
                     options.height = dftFontHeight;
-                    doc.text(val,output[0], output[1], options);
+                    // doc.text(val,output[0], output[1], options);
                 } else {
                     let aH = dftFontHeight + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_BOTTOM] + JV.OUTPUT_OFFSET[JV.OFFSET_IDX_TOP] + 4;
                     if ((aH * actLines.length) < (area[JV.IDX_BOTTOM] - area[JV.IDX_TOP]) && (control && control.Vertical !== 'top')) {

+ 1 - 1
modules/std_billsGuidance_lib/facade/facades.js

@@ -127,7 +127,7 @@ async function getLibWithBills(libID){
     if(!billsLib){
         throw '引用的清单规则库不存在!';
     }
-    let bills = await stdBillsModel.find({billsLibId: billsLib.billsLibId}, '-_id code name ID NextSiblingID ParentID jobs items');
+    let bills = await stdBillsModel.find({billsLibId: billsLib.billsLibId}, '-_id code name ID NextSiblingID ParentID jobs items comment');
     return {guidanceLib: guidanceLib[0], bills};
 }
 

+ 1 - 1
modules/std_billsGuidance_lib/routes/routes.js

@@ -24,7 +24,7 @@ module.exports = function (app) {
     router.post('/getItemsByBills', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.getItemsByBills);
     router.post('/updateItems', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.updateItems);
     //test
-    router.post('/testItems', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.testItems);
+    //router.post('/testItems', billsGuideLibController.auth, billsGuideLibController.init, billsGuideLibController.testItems);
 
 
     app.use('/billsGuidance/api', router);

+ 1 - 0
modules/std_glj_lib/controllers/gljController.js

@@ -155,6 +155,7 @@ class GljController extends BaseController{
             lastOpr = req.body.lastOpr;
         gljDao.mixUpdateGljItems(repId, lastOpr, updateItems, addItems, removeIds, function(err, message, rst){
             if (err) {
+                console.log(err);
                 callback(req, res, err, message, null);
             } else {
                 callback(req, res, err, message, rst);

+ 5 - 0
modules/sys_tools/models/sys_model.js

@@ -22,6 +22,7 @@ const rationGljModel = mongoose.model('ration_glj');
 const rationCoeMolde = mongoose.model('ration_coe');
 const installationModel = mongoose.model('installation_fee');
 const rationInstallationModel = mongoose.model('ration_installation');
+const rationTemplateModel  = mongoose.model('ration_template')
 const quantityDetailModel = mongoose.model('quantity_detail');
 const unitPriceFileModel = mongoose.model('unit_price_file');
 const unitPriceModel = mongoose.model('unit_price');
@@ -79,6 +80,10 @@ async function clearJunkData(callback){
         functions.push(function(cb){
             rationInstallationModel.remove({projectID: {$in: junkProjIds}}, cb);
         });
+        //清除ration_installation
+        functions.push(function(cb){
+            rationTemplateModel.remove({projectID: {$in: junkProjIds}}, cb);
+        });
         //清除quantity_detail
         functions.push(function(cb){
             quantityDetailModel.remove({projectID: {$in: junkProjIds}}, cb);

+ 20 - 2
modules/users/controllers/compilation_controller.js

@@ -61,7 +61,9 @@ class CompilationController extends BaseController {
         } catch (error) {
             console.log(error);
         }
-
+        if (selectedCompilation.example && Array.isArray(selectedCompilation.example)) {
+            selectedCompilation.example = selectedCompilation.example.join(';');
+        }
         let renderData = {
             id: id,
             compilationList: compilationList,
@@ -238,7 +240,10 @@ class CompilationController extends BaseController {
         } catch (error) {
             console.log(error);
         }
-
+        //example Array to example String
+        if (selectedCompilation.example && Array.isArray(selectedCompilation.example)) {
+            selectedCompilation.example = selectedCompilation.example.join(';');
+        }
         let renderData = {
             section: section,
             valuationId: valuationId,
@@ -548,6 +553,19 @@ class CompilationController extends BaseController {
             response.json({err: 1, msg: err, data: null});
         }
     }
+    async setExample(request, response){
+        let compilationId = request.body.id,
+            example = request.body.example;
+        try {
+            let compilationModel = new CompilationModel();
+            await compilationModel.setExample(compilationId, example);
+            response.json({err: 0, msg: 'success', data: null});
+        }
+        catch (err){
+            console.log(err);
+            response.json({err: 1, msg: err, data: null});
+        }
+    }
 
     /**
      * 模板设置页面

+ 17 - 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, categoryID: 1, description: 1,overWriteUrl: 1, "ration_valuation.id": 1, "ration_valuation.name": 1, "ration_valuation.enable": 1,
+        let field = fields == null ?{_id: 1, name: 1, is_release: 1, categoryID: 1, description: 1,overWriteUrl: 1,example: 1, "ration_valuation.id": 1, "ration_valuation.name": 1, "ration_valuation.enable": 1,
             "bill_valuation.id": 1, "bill_valuation.name": 1, "bill_valuation.enable": 1}:fields;
         let compilationData = await this.findDataByCondition({name: {$ne: ''}}, field, false);
 
@@ -95,6 +95,22 @@ class CompilationModel extends BaseModel {
         return await this.updateById(compilationId, {overWriteUrl: overWriteUrl, priceProperties: priceProp, consumeAmtProperties: consumeAmtProp});
     }
 
+    /*
+    * 设置例题
+    * @param {String} compilationId
+    * @param {Array} example
+    * @return {Promise}
+    * */
+    async setExample(compilationId, example) {
+        let data = [];
+        if (example) {
+            for (let projId of example) {
+                data.push(parseInt(projId));
+            }
+        }
+        return await this.updateById(compilationId, {example: data});
+    }
+
     /**
      * 新增计价规则
      *

+ 11 - 6
modules/users/models/manager_model.js

@@ -25,7 +25,7 @@ class ManagerModel extends BaseModel {
      * @var
      */
     permission = {
-        'manager': '用户管理',
+        'user': '用户管理',
         'notify': '通知管理',
         'stdBillsmain': '清单规则编辑器',
         'rationRepository': '定额编辑器',
@@ -132,17 +132,17 @@ class ManagerModel extends BaseModel {
         let managerData = await this.findDataByCondition({username: username});
 
         // 没有找到对应数据
-        if (managerData === null || managerData._id === undefined) {
+        /*if (managerData === null || managerData._id === undefined) {
             throw {code: 44001, err: '用户名或密码错误'};
-        }
+        }*/
 
         // 是否禁止登录
-        if (managerData.can_login !== 1) {
+        if (managerData && managerData.can_login !== 1) {
             throw {code: 44002, err: '用户名不存在'};
         }
 
         // 如果不是超级管理员登录则走CLD接口登录流程
-        if (username !== this.adminUsername) {
+        if (managerData === null || managerData._id === undefined || username !== this.adminUsername) {
             let CLDLoginInfo = await this.CLDLogin(username, password, managerData);
             managerData = CLDLoginInfo;
         } else {
@@ -196,6 +196,7 @@ class ManagerModel extends BaseModel {
         // 不存在则新增
         this.setScene('cldInsert');
         let current = new Date().getTime();
+        //cld账号登录的统一设置可以看到用户管理和允许登录
         let insertData = {
             username: username,
             password: '',
@@ -203,7 +204,9 @@ class ManagerModel extends BaseModel {
             create_time: current,
             last_login: current,
             office: responseData.office,
-            can_login: 0
+            position: responseData.position,
+            permission: 'user',
+            can_login: 1
         };
         result = this.db.create(insertData);
 
@@ -220,6 +223,8 @@ class ManagerModel extends BaseModel {
         return new Promise(function(resolve, reject) {
             // 发起请求
             Request.post(postOption, function(error, response, body) {
+                console.log(`body`);
+                console.log(body);
                 if (error || response.statusCode !== 200) {
                     console.log(response.statusCode + ':' + error);
                     reject({code: 44002, err: '接口请求出错'});

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

@@ -22,6 +22,7 @@ module.exports = function (app) {
     router.post('/add', compilationController.auth, compilationController.init, compilationController.addCompilation);
     router.post('/setDescription', compilationController.auth, compilationController.init, compilationController.setDescription);
     router.post('/setOverWriteUrl', compilationController.auth, compilationController.init, compilationController.setOverWriteUrl);
+    router.post('/setExample', compilationController.auth, compilationController.init, compilationController.setExample);
     router.post('/add-valuation', compilationController.auth, compilationController.init, compilationController.addValuation);
     router.post('/save-valuation', compilationController.auth, compilationController.init, compilationController.saveValuation);
     router.post('/update-engineer', compilationController.auth, compilationController.init, compilationController.updateEngineer);

+ 4 - 0
public/web/id_tree.js

@@ -781,6 +781,10 @@ var idTree = {
         Tree.prototype.getDownLevelDatas = function (nodes) {
             let dataMap = {},updateDatas=[],nextID,last;//注释同m_downLevel 方法
             let newParent = nodes[0].preSibling;//{"type":"update","data":{"ID":3,"ParentID":-1,"NextSiblingID":5}}
+            let newPre = newParent.children && newParent.children.length > 0 ? newParent.children[newParent.children.length -1]:null;
+            if(newPre){ //如果新的父节点有子节点,则把新的父节点的最后一个子节点的下一节点的值改成第一个选中节点的ID
+                dataMap[newPre.getID()] = {"ID":newPre.getID(),"NextSiblingID":nodes[0].getID()}
+            }
             for(let n of nodes){
                 nextID = n.getNextSiblingID();
                 last = n;

+ 5 - 0
public/web/rpt_value_define.js

@@ -278,6 +278,11 @@ const JV = {
     PAGING_OPTION_NORMAL: 'normal',
     PAGING_OPTION_INFINITY: 'infinity',
 
+    OUTPUT_TYPE_NORMAL: 'normal',
+    OUTPUT_TYPE_SVG: 'svg',
+    OUTPUT_TYPE_PDF: 'pdf',
+    OUTPUT_TYPE_EXCEL: 'excel',
+
     DISPLAY_VAL_TYPE_NORMAL: 0,
     DISPLAY_VAL_TYPE_GROUP: 1,
     DISPLAY_VAL_TYPE_AUTO_HEIGHT: 2,

+ 11 - 4
test/demo/stringTest.js

@@ -31,10 +31,17 @@ let strUtil = require('../../public/stringUtil');
 //     t.end();
 // })
 
-test('string ', function(t){
-    let str = "{abc}";
-    console.log(str);
-    console.log(str.slice(1, -1));
+// test('string ', function(t){
+//     let str = "{abc}";
+//     console.log(str);
+//     console.log(str.slice(1, -1));
+//     t.end();
+// })
+
+test('splice', function(t){
+    let arr = ["a", "b"];
+    arr.splice(2, 0, "c");
+    console.log(arr);
     t.end();
 })
 

+ 173 - 160
web/common/js/slideResize.js

@@ -4,184 +4,197 @@
  *
  *
  * @author Zhong
- * @date 2018/10/22
+ * @date 2018/11/7
  * @version
  */
 
-let mouseMoveCount = 0;
+/*
+ * div之间的水平拖动,适应各种情况
+ * module: 所属模块,防止不同页面相同id导致localstorage数据被覆盖
+ * eleObj: resize, parent, left, right
+ * limit: min, max
+ * */
 
-/**
- * 拖动更改div大小
- *
- * @param {Object} eles - id:存储本地的标记 resize:拖动条 nearElement:左上外层div nearSpread:左上spread farElement:右下外层div evFixedSize:造价书左右拖动用
- * @param {Object} limit - min/max
- * @param {String} type - height/width
- * @param {function} callback - 成功后执行
- * @return {void}
- */
-function slideResize(eles, limit, type, callback) {
-    if(type !== 'height' && type !== 'width'){
-        return;
+const SlideResize = (function() {
+    //设置水平拖动条的宽度
+    //@param {Object dom}resize滚动条
+    function setResizeWidth (resize) {
+        const fixedWidth = 10;
+        //跟滚动条同层的其他节点
+        let bros = resize.parent().children();
+        //滚动条节点 及 同层非滚动条节点的索引
+        let index = bros.index(resize),
+            otherIndex = index ? 0 : 1;
+        const other = resize.parent().children(`:eq(${otherIndex})`);
+        let resizeParentWidth = resize.parent().width();
+        let resizeDecimalWidth = fixedWidth / resizeParentWidth,
+            otherDecimalWidth = 1 - resizeDecimalWidth;
+        let resizePercentWidth = resizeDecimalWidth * 100 + '%',
+            otherPercentWidth = otherDecimalWidth * 100 + '%';
+        resize.css('width', resizePercentWidth);
+        other.css('width', otherPercentWidth);
     }
-    //nearElement:左上, farElement:右下
-    let startP = 0;
-    let drag = false;
-    const resizeElement = eles.resize;
-    const nElement = eles.nearElement;
-    const fElement = eles.farElement;
-    const navContentEle = eles.nav ? eles.nav : null;
-    let nEleSize = 0;
-    let fEleSize = 0;
-    let navSize = 0;
-    let nEleChangeSize = 0;
-    let fEleChangeSize = 0;
-
-    // 鼠标点下时
-    resizeElement.mousedown(function(e) {
-        mouseMoveCount = 0;
-        drag = true;
-        startP = type === 'height' ? e.clientY : e.clientX;
-        // 获取左(上)部分的宽度(高度)
-        nEleSize = nElement[type]();
-        // 获取右(下)部分的宽度(高度)
-        fEleSize = fElement[type]();
-        // nav宽(高度)部分
-        if(navContentEle){
-            navSize = navContentEle[type]() + 4;
-        }
-        resizeElement.tooltip('hide');
-    });
-
-    // 鼠标移动
-    $("body").mousemove(function(e) {
-        if (drag) {
-            let moveSize = type === 'height' ? e.clientY - startP : e.clientX - startP;
-            // 判断拖动范围不能超出
-            nEleChangeSize = nEleSize + moveSize;
-            nEleChangeSize = nEleChangeSize < limit.min ? limit.min : nEleChangeSize;
-            nEleChangeSize = nEleChangeSize > limit.max ? limit.max + 9 : nEleChangeSize;
 
-            fEleChangeSize = fEleSize - moveSize;
-            fEleChangeSize = fEleChangeSize < limit.min ? limit.min : fEleChangeSize;
-            fEleChangeSize = fEleChangeSize > limit.max ? limit.max + 9 : fEleChangeSize;
+    let mouseMoveCount = 0;
+    function horizontalSlide(module, eleObj, limit, callback) {
+        const triggerCBSize = 5;
+        let drag = false,
+            startPoint = 0,
+            leftWidth = 0,
+            rightWidth = 0,
+            leftChange = 0,
+            rightChange = 0,
+            limitMax = 0;
 
-            if(type === 'width'){
-                if(eles.totalWidth) {
-                    nEleChangeSize = nEleChangeSize * eles.totalWidth;
-                    fEleChangeSize = fEleChangeSize * eles.totalWidth;
+        eleObj.resize.mousedown(function (e) {
+            drag = true;
+            startPoint = e.clientX;
+            leftWidth = eleObj.left.width();
+            rightWidth = eleObj.right.width();
+            limitMax = eval(limit.max);
+        });
+        $('body').mousemove(function (e) {
+            if (drag) {
+                let moveSize = e.clientX - startPoint;
+                leftChange = leftWidth + moveSize;
+                leftChange = leftChange < limit.min ? limit.min : leftChange;
+                leftChange = leftChange > limitMax ? limitMax - 3 : leftChange;
+                rightChange = rightWidth - moveSize;
+                rightChange = rightChange < limit.min ? limit.min : rightChange;
+                rightChange = rightChange > limitMax ? limitMax - 3 : rightChange;
+                let leftPercentWidth = leftChange / eleObj.parent.width() * 100 + '%',
+                    rightPercentWidth = rightChange / eleObj.parent.width() * 100 + '%';
+                eleObj.left.css('width', leftPercentWidth);
+                eleObj.right.css('width', rightPercentWidth);
+                setResizeWidth(eleObj.resize);
+                mouseMoveCount += Math.abs(moveSize);
+                if (mouseMoveCount > triggerCBSize && callback) {
+                    callback();
+                    mouseMoveCount = 0;
                 }
-                let rePercent = getResizeWidthPercent(nEleChangeSize, fEleChangeSize, eles.totalWidth);
-                eles.nearElement.css(type, rePercent.nearPercent);
-                eles.farElement.css(type, rePercent.farPercent);
             }
-            else{
-                eles.nearSpread[type](nEleChangeSize);
-                eles.farSpread[type](fEleChangeSize - navSize);
-                eles.farElement[type](fEleChangeSize);
-            }
-            //实时刷新页面
-            mouseMoveCount+=Math.abs(moveSize);//取移动的决对值
-            if(mouseMoveCount >=5){//当累计移动超过5个像素时,才刷新,减少刷新次数
-                if(callback) callback();
+        });
+        $('body').mouseup(function (e) {
+            if (drag) {
+                drag = false;
                 mouseMoveCount = 0;
+                //将宽度信息存储到localstorage
+                let leftWidthInfo = eleObj.left[0].style.width;
+                setLocalCache(`${module}${eleObj.left.attr('id')}Width`, leftWidthInfo);
+                let rightWidthInfo = eleObj.right[0].style.width;
+                setLocalCache(`${module}${eleObj.right.attr('id')}Width`, rightWidthInfo);
             }
-        }
-    });
+        });
+    }
 
-    // 鼠标弹起
-    $("body").mouseup(function(e) {
-        if (drag) {
-            callback();
-            drag = false;
-            // 存入本地缓存
-            const id = eles.id;
-            nEleChangeSize = nEleChangeSize >= limit.max ? limit.max + 9  : nEleChangeSize;
-            fEleChangeSize = fEleChangeSize >= limit.max ? limit.max + 9  : fEleChangeSize;
-            setLocalCache(`near${type}:${id}`, nEleChangeSize);
-            setLocalCache(`far${type}:${id}`, fEleChangeSize);
+    function loadHorizonWidth(module, resizes, eles, callback) {
+        for (let ele of eles) {
+            let cache = getLocalCache(`${module}${ele.attr('id')}Width`);
+            if (cache) {
+                ele.css('width', cache);
+            }
         }
-    });
-}
-
-/**
- * 读取设置的高度
- *
- * @param {String} tag - 顶层div的id
- * @param {function} callback - 回调函数
- * @return {void}
- */
-
-function loadSize(eles, type, callback) {
-    let tag = eles.id;
-    if (tag === '') {
-        return;
-    }
-    if(type !== 'height' && type !== 'width'){
-        return;
-    }
-    let o_nearSize = eles.nearSpread[type]();
-    let o_farSize = eles.farSpread[type]();
-    let nearSize = getLocalCache(`near${type}:${tag}`);
-    let farSize = getLocalCache(`far${type}:${tag}`);
-    if (nearSize === null || farSize === null) {
-        setDefaultSize(tag,eles,type);//zhang 2018-05-21
-        /* eles.nearSpread[type](o_nearSize);
-         eles.farSpread[type](o_farSize);*/
-    }else {
-        setSizeWithPercent(tag,eles,nearSize,farSize,type)//zhang 2018-06-04 改成按百分比设置
-    }
-    if(type === 'width'){//使用百分比
-        if (eles.totalWidth) {
-            o_nearSize = o_nearSize * eles.totalWidth;
-            o_farSize = o_farSize * eles.totalWidth;
+        for (let resize of resizes) {
+            setResizeWidth(resize);
+        }
+        if (callback) {
+            callback();
         }
-        let rePercent = getResizeWidthPercent(nearSize ? nearSize : o_nearSize, farSize ? farSize : o_farSize, eles.totalWidth);
-        eles.nearElement.css(type, rePercent.nearPercent);
-        eles.farElement.css(type, rePercent.farPercent);
     }
-    callback();
-}
 
-function getResizeWidthPercent(nearSize, farSize, totalWidth = 1){
-    const resizeWidth = 6;
-    nearSize = parseFloat(nearSize);
-    farSize = parseFloat(farSize);
-    let nearPercent = (nearSize / (resizeWidth + nearSize + farSize) * totalWidth * 100) + '%';
-    let farPercent = (farSize / (resizeWidth + nearSize + farSize) * totalWidth * 100) + '%';
-    return {nearPercent, farPercent};
-}
 
+    /*
+     * div上下拖动
+     * module: 所属模块,防止不同页面相同id导致localstorage数据被覆盖
+     * eleObj: resize, top, topSpread, bottom, bottomSpread
+     * limit: min, max, notTopSpread(上部分非spread部分的高度) notBottomSpread(下部分非spread部分的高度)
+     * */
+    function verticalSlide(module, eleObj, limit, callback) {
+        const triggerCBSize = 5;
+        let drag = false,
+            startPoint = 0,
+            topHeight = 0,
+            bottomHeight = 0,
+            topChange = 0,
+            bottomChange = 0,
+            limitMax = 0;
+
+        eleObj.resize.mousedown(function (e) {
+            drag = true;
+            startPoint = e.clientY;
+            topHeight = eleObj.top.height();
+            bottomHeight = eleObj.bottom.height();
+            limitMax = eval(limit.max);
+        });
+        $('body').mousemove(function (e) {
+            if (drag) {
+                let moveSize = e.clientY - startPoint;
+                topChange = topHeight + moveSize;
+                topChange = topChange < limit.min ? limit.min : topChange;
+                topChange = topChange > limitMax ? limitMax : topChange;
+                bottomChange = bottomHeight - moveSize;
+                bottomChange = bottomChange < limit.min ? limit.min : bottomChange;
+                bottomChange = bottomChange > limitMax ? limitMax : bottomChange;
 
-function setSizeWithPercent(tag,eles,nearSize,farSize,type) {
-    nearSize = parseFloat(nearSize);
-    farSize = parseFloat(farSize);
-    if(type !== 'width') {
-        let headerHeight = $(".header").height();
-        let toolsbarHeight = $(".toolsbar").height();
-        let exand = tag == "#main" ? 1:50;
-        let totalHeight = $(window).height() - headerHeight - toolsbarHeight-exand;
-        const navSize = eles.nav ? eles.nav[type]() + 4 : 0;
-        totalHeight = totalHeight - navSize;
-        nearSize = (nearSize/(nearSize + farSize))* totalHeight;
-        eles.nearSpread[type](nearSize);
-        eles.farSpread[type](totalHeight - nearSize);
-        eles.farElement[type](totalHeight - nearSize + navSize);
+                //设置上部分div高度
+                eleObj.top.height(topChange);
+                //设置上部分div内spread高度
+                eleObj.topSpread.height(topChange - limit.notTopSpread);
+                //设置下部分div高度
+                eleObj.bottom.height(bottomChange);
+                //设置下部分div内spread高度
+                eleObj.bottomSpread.height(bottomChange - limit.notBottomSpread);
+                mouseMoveCount += Math.abs(moveSize);
+                if (mouseMoveCount > triggerCBSize && callback) {
+                    callback();
+                    mouseMoveCount = 0;
+                }
+            }
+        });
+        $('body').mouseup(function (e) {
+            if (drag) {
+                drag = false;
+                mouseMoveCount = 0;
+                //将高度信息存储到localstorage
+                let topHeightInfo = eleObj.top.height();
+                setLocalCache(`${module}${eleObj.top.attr('id')}Height`, topHeightInfo);
+                let bottomHeightInfo = eleObj.bottom.height();
+                setLocalCache(`${module}${eleObj.bottom.attr('id')}Height`, bottomHeightInfo);
+            }
+        });
     }
-}
 
-function setDefaultSize(tag,eles,type) {
-    let o_nearSize = 5;
-    let o_farSize = 2;
-    if(type == 'height'){
-        let headerHeight = $(".header").height();
-        let toolsbarHeight = $(".toolsbar").height();
-        let exand = tag == "#main" ? 1:50;
-        let totalHeight = $(window).height() - headerHeight - toolsbarHeight-exand;
-        const navSize = eles.nav ? eles.nav[type]() + 4 : 0;
-        totalHeight = totalHeight - navSize;
-        let nearSize = (o_nearSize/(o_nearSize + o_farSize))* totalHeight;
-        eles.nearSpread[type](nearSize);
-        eles.farSpread[type](totalHeight - nearSize);
-        eles.farElement[type](totalHeight - nearSize + navSize);
+    /*
+     * 加载上下高度
+     * module: 所属模块,防止不同页面相同id导致localstorage数据被覆盖
+     * eleObj: top, topSpread, bottom, bottomSpread
+     * limit: totalHeight(实时的上下部分总高度) notTopSpread(上部分非spread部分的高度) notBottomSpread(下部分非spread部分的高度)
+     * */
+
+    function loadVerticalHeight(module, eleObj, limit, callback) {
+        let topHeight = getLocalCache(`${module}${eleObj.top.attr('id')}Height`),
+            bottomHeight = getLocalCache(`${module}${eleObj.bottom.attr('id')}Height`);
+        //默认上下比例
+        const topProp = 5;
+        const bottomProp = 2;
+        let topProportion = topProp / (topProp + bottomProp);
+        if (topHeight !== null && bottomHeight !== null) {
+            topHeight = parseFloat(topHeight);
+            bottomHeight = parseFloat(bottomHeight);
+            topProportion = topHeight / (topHeight + bottomHeight);
+        }
+        //设置当前窗口下的的上下部分高度
+        let totalHeight = eval(limit.totalHeight);
+        let curTopHeight = totalHeight * topProportion,
+            curBottomHeight = totalHeight - curTopHeight;
+        eleObj.top.height(curTopHeight);
+        eleObj.topSpread.height(curTopHeight - limit.notTopSpread);
+        eleObj.bottom.height(curBottomHeight);
+        eleObj.bottomSpread.height(curBottomHeight - limit.notBottomSpread);
+        if (callback) {
+            callback();
+        }
     }
-}
+
+    return {horizontalSlide, loadHorizonWidth, verticalSlide, loadVerticalHeight}
+})();

+ 2 - 2
web/maintain/billsGuidance_lib/css/main.css

@@ -301,8 +301,8 @@ body {
     border-bottom:1px solid #ddd
 }
 div.resize{
-    height: 6px;
-    background: #f7f7f9;
+    height: 10px;
+    background: #efefef;
     width: 100%;
     cursor: s-resize;
 }

+ 56 - 43
web/maintain/billsGuidance_lib/html/zhiyin.html

@@ -12,6 +12,7 @@
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
     <link rel="stylesheet" href="/lib/jquery-contextmenu/jquery.contextMenu.css" type="text/css">
     <script>
+        let userAccount = '<%= userAccount %>';
     </script>
 </head>
 
@@ -30,62 +31,73 @@
         </nav>
     </div>
     <div class="main">
-        <div class="content">
+        <div class="content" style="overflow: hidden">
             <div class="container-fluid">
-                <div class="row">
-                  <div id="billsSpread" class="main-side col-lg-4 p-" style="margin: 0; padding: 0;">
-                  </div>
-                  <div class="main-content col-lg-4 p-" style="margin: 0; padding: 0;">
-                    <div class="toolsbar px-1 d-flex justify-content-between">
-                      <div class="tools-btn btn-group align-top">
-                        <a id="insert" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-reply-all" aria-hidden="true"></i> 插入</a>
-                        <a id="del" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-remove" aria-hidden="true"></i> 删除</a>
-                        <a id="upLevel" href="javascript:void(0);" class="btn btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-arrow-left" aria-hidden="true"></i> 升级</a>
-                        <a id="downLevel" href="javascript:void(0);" class="btn btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-arrow-right" aria-hidden="true"></i> 降级</a>
-                        <a id="downMove" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-arrow-down" aria-hidden="true"></i> 下移</a>
-                        <a id="upMove" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-arrow-up" aria-hidden="true"></i> 上移</a>
-                        <a id="expandContract" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-minus-square-o" aria-hidden="true"></i> 收起定额</a>
-                      </div>
-                    </div>
-                      <div class="main-top-content">
-                          <div id="guideItemSpread" class="main-data"></div>
+                <div class="row" id="dataRow">
+                    <div class="main-side p-0" id="leftContent" style="width: 33%">
+                        <div id="billsSpread" class="main-side-top">
+                        </div>
+                        <div class="main-side-bottom">
+                            <textarea class="form-control"></textarea>
+                        </div>
                     </div>
-                      <div class="main-bottom-content">
-                          <textarea class="form-control"></textarea>
+                  <div class="main-content p-0" id="midContent" style="width: 34%">
+                      <div class="resize" id="slideResizeLeft" style="width: 1%; height: 100%; resize:horizontal; cursor: w-resize; float: left; background: #F1F1F1"></div>
+                      <div style="width: 99%; float: left">
+                          <div class="toolsbar px-1 d-flex justify-content-between">
+                              <div class="tools-btn btn-group align-top">
+                                  <a id="insert" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="插入"><i class="fa fa-reply-all" aria-hidden="true"></i> 插入</a>
+                                  <a id="del" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                                  <a id="upLevel" href="javascript:void(0);" class="btn btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
+                                  <a id="downLevel" href="javascript:void(0);" class="btn btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
+                                  <a id="downMove" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                                  <a id="upMove" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                                  <a id="expandContract" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="收起定额"><i class="fa fa-minus-square-o" aria-hidden="true"></i> 收起定额</a>
+                              </div>
+                          </div>
+                          <div class="main-top-content">
+                              <div id="guideItemSpread" class="main-data"></div>
+                          </div>
+                          <div class="main-bottom-content">
+                              <textarea class="form-control"></textarea>
+                          </div>
                       </div>
                   </div>
-                    <div class="main-side col-lg-4 p-" style="margin: 0; padding: 0;" id="de">
-                        <div class="sidebar-tools-bar container-fluid tools-bar-height-q">
-                            <div class="p-1 row">
-                                <div class="col-5 p-0">
-                                    <select class="form-control form-control-sm" id="rationLibSel">
-                                    </select>
-                                </div>
-                                <div class=" input-group col-5">
-                                    <input id="searchText" type="text" class="form-control form-control-sm" placeholder="搜索定额">
-                                    <span class="input-group-btn">
+                    <div class="main-side p-0" id="rightContent" style="width:33%">
+                        <div class="resize" id="slideResizeRight" style="width: 1%; height: 100%; resize:horizontal; cursor: w-resize; float: left; background: #F1F1F1"></div>
+                        <div style="width: 99%; float: left" id="de">
+                            <div class="sidebar-tools-bar container-fluid tools-bar-height-q">
+                                <div class="p-1 row">
+                                    <div class="col-5 p-0">
+                                        <select class="form-control form-control-sm" id="rationLibSel">
+                                        </select>
+                                    </div>
+                                    <div class=" input-group col-5">
+                                        <input id="searchText" type="text" class="form-control form-control-sm" placeholder="搜索定额">
+                                        <span class="input-group-btn">
                                         <button id="searchBtn" class="btn btn-secondary btn-sm" type="button"><i class="fa fa-search" aria-hidden="true"></i></button>
                                     </span>
+                                    </div>
+                                    <div class="col-2">
+                                        <button id="insertRation" class="btn btn-primary btn-sm" type="button">插入定额</button>
+                                    </div>
                                 </div>
-                                <div class="col-2">
-                                    <button id="insertRation" class="btn btn-primary btn-sm" type="button">插入定额</button>
+                                <!--搜索结果窗体-->
+                                <div class="side-search-box col-12 p-0" id="rationSearchResult" style="display: none;">
+                                    <div class="d-flex justify-content-between">
+                                        <span id="searchCount">搜索结果:153</span><a title="关闭搜索" class="btn btn-link btn-sm" href="javascript:void(0)"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                                    </div>
                                 </div>
                             </div>
-                            <!--搜索结果窗体-->
-                            <div class="side-search-box col-12 p-0" id="rationSearchResult" style="display: none;">
-                                <div class="d-flex justify-content-between">
-                                    <span id="searchCount">搜索结果:153</span><a title="关闭搜索" class="btn btn-link btn-sm" href="javascript:void(0)"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                            <div class="top-content" id="topContent" style="overflow: hidden; width: 100%">
+                                <div class="main-data-top" id="sectionSpread">
                                 </div>
                             </div>
-                        </div>
-                        <div class="top-content" style="overflow: hidden">
-                            <div class="main-data-top" id="sectionSpread">
+                            <div class="resize" id="deResize"></div>
+                            <div class="bottom-content" id="bottomContent">
+                                <div class="main-data-bottom" id="rationSpread"></div>
                             </div>
                         </div>
-                        <div class="resize" id="deResize"></div>
-                        <div class="bottom-content">
-                            <div class="main-data-bottom" id="rationSpread"></div>
-                        </div>
                     </div>
                   </div>
                 </div>
@@ -133,6 +145,7 @@
     <script src="/public/web/tree_sheet/tree_sheet_controller.js"></script>
     <script src="/public/web/tree_sheet/tree_sheet_helper.js"></script>
     <script src="/web/maintain/billsGuidance_lib/js/billsGuidance.js"></script>
+    <script src="/web/common/js/slideResize.js"></script>
 </body>
 <script type="text/javascript">
     autoFlashHeight();

+ 177 - 230
web/maintain/billsGuidance_lib/js/billsGuidance.js

@@ -11,7 +11,9 @@ const billsGuidance = (function () {
     function _isDef(v) {
         return typeof v !== 'undefined' && v !== null;
     }
-
+    let moduleName = 'stdBillsGuidance';
+    //上下拖动的拖动条高度
+    const verticalResize = 10;
     //自执行函数全局变量定义
     const libID = getQueryString('libID');
     //总工作内容数据
@@ -331,7 +333,8 @@ const billsGuidance = (function () {
             return;
         }
         bills.tree.selected = node;
-
+        //显示备注
+        $('.main-side-bottom').find('textarea').val(node.data.comment ? node.data.comment : '');
         if(!node.guidance.tree){
             getItemsByBills(libID, node.data.ID, function (rstData) {
                 initTree(node.guidance, guideSheet, guideItem.treeSetting, rstData);
@@ -814,10 +817,12 @@ const billsGuidance = (function () {
             });
         });
     }
+    let billsLibId = 0;
     //获取指引库信息及关联的清单
     //@param {Number}libID {Function}callback @return {Object}
     function getLibWithBills(libID, callback){
         CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function (rstData) {
+            billsLibId = rstData.guidanceLib.billsLibId;
             initRationLibs(rstData.guidanceLib.compilationId);
             bills.cache = rstData.bills;
             initLibName(rstData.guidanceLib.name);
@@ -859,6 +864,14 @@ const billsGuidance = (function () {
             setBillsHint(bills.tree.items, stdBillsJobData, stdBillsFeatureData);
         }
     }
+    //更新清单备注
+    function updateBillsComment(updateData, callback) {
+        CommonAjax.post('/stdBillsEditor/updateBills', updateData, function () {
+            if (callback) {
+                callback();
+            }
+        });
+    }
     //更新项目指引
     //@param {Array}updateDatas {Function}callback @return {void}
     function updateGuideItems(updateDatas, callback){
@@ -868,6 +881,8 @@ const billsGuidance = (function () {
             }
         });
     }
+    //编辑后自动去除换行符回车符
+    const deESC = /[\r, \n]/g;
     //项目指引编辑
     //@param {Object}sheet {Array}cells
     function edit(sheet, cells){
@@ -876,7 +891,9 @@ const billsGuidance = (function () {
         let syncDatas = [];
         for(let cell of cells){
             let text = sheet.getValue(cell.row, cell.col);
-            text = text ? text : '';
+            text = text ? text.toString() : '';
+            text = text.replace(deESC, '');
+            sheet.setValue(cell.row, cell.col, text);
             let node = bills.tree.selected.guidance.tree.items[cell.row];
             if(node.data.name != text){
                 syncDatas.push({node: node, text: text});
@@ -958,22 +975,42 @@ const billsGuidance = (function () {
     function del(){
         $.bootstrapLoading.start();
         let controller = bills.tree.selected.guidance.controller;
-        let selected = bills.tree.selected.guidance.tree.selected;
+        let selNodes = [];
+        let sheet = guideItem.workBook.getSheet(0);
+        let sel = sheet.getSelections()[0];
+        if(sel){
+            sel.row =  sel.row === -1 ? 0 : sel.row;
+            for(let i = 0; i < sel.rowCount; i++){
+                if(bills.tree.selected.guidance.tree.items[sel.row + i]){
+                    selNodes.push(bills.tree.selected.guidance.tree.items[sel.row + i]);
+                }
+            }
+        }
+        //选中的块节点
+        let blockNodes = getBlockNodes(selNodes);
         let updateDatas = [];
-        function getDelDatas(node){
-            updateDatas.push({updateType: updateType.del, findData: {ID: node.getID()}, updateData: {deleted: true}});
-            if(node.children.length > 0){
-                for(let c of node.children){
-                    getDelDatas(c);
+        function getDelDatas(nodes){
+            for (let node of nodes) {
+                updateDatas.push({updateType: updateType.del, findData: {ID: node.getID()}});
+                if (node.children.length > 0) {
+                    getDelDatas(node.children);
                 }
             }
         }
-        getDelDatas(selected);
-        if(selected.preSibling) {
-            updateDatas.push({updateType: updateType.update, findData: {ID: selected.preSibling.getID()}, updateData: {NextSiblingID: selected.getNextSiblingID()}});
+        getDelDatas(blockNodes);
+        //更新相关的前节点
+        for (let node of blockNodes) {
+            if (node.preSibling && !blockNodes.includes(node.preSibling)) {
+                let next = node;
+                while (next.nextSibling && blockNodes.includes(next.nextSibling)) {
+                    next = next.nextSibling;
+                }
+                updateDatas.push({updateType: updateType.update, findData: {ID: node.preSibling.getID()}, updateData: {NextSiblingID: next.getNextSiblingID()}});
+            }
         }
         updateGuideItems(updateDatas, function () {
-            controller.delete();
+            controller.m_delete(blockNodes);
+            guideItemInitSel(sheet.getActiveRowIndex());
             refreshBtn(bills.tree.selected.guidance.tree.selected);
             setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
             $.bootstrapLoading.end();
@@ -1277,8 +1314,6 @@ const billsGuidance = (function () {
             delete data._id;
             updateDatas.push({updateType: updateType.create, updateData: data});
         }
-        console.log(`node`);
-        console.log(node);
         console.log(`pasteDatas`);
         console.log(pasteDatas);
         //更新粘贴到的节点的NextSiblingID
@@ -1383,199 +1418,6 @@ const billsGuidance = (function () {
             }
         });
     }
-    //拖动相关
-    let mouseMoveCount = 0;
-    let rationLibResizeEles = {};
-    rationLibResizeEles.id = '#de';
-    rationLibResizeEles.resize = $('#deResize');
-    rationLibResizeEles.nearElement = $('#de').find('.top-content');
-    rationLibResizeEles.nearSpread = $('#sectionSpread');
-    rationLibResizeEles.farElement = $('#de').find('.bottom-content');
-    rationLibResizeEles.farSpread = $('#rationSpread');
-    rationLibResizeEles.nav = null;
-
-    function setDefaultSize(tag,eles,type) {
-        let o_nearSize = 5;
-        let o_farSize = 2;
-        if(type == 'height'){
-            let headerHeight = $(".header").height();
-            let toolsbarHeight = $(".sidebar-tools-bar").height();
-            let resizeHeight = 6;
-            let totalHeight = $(window).height() - headerHeight - toolsbarHeight - resizeHeight;
-            const navSize = eles.nav ? eles.nav[type]() + 4 : 0;
-            totalHeight = totalHeight - navSize;
-            let nearSize = (o_nearSize/(o_nearSize + o_farSize))* totalHeight;
-            eles.nearSpread[type](nearSize);
-            eles.nearElement[type](nearSize);
-            eles.farSpread[type](totalHeight - nearSize);
-            eles.farElement[type](totalHeight - nearSize);
-        }
-    }
-    function setSizeWithPercent(tag,eles,nearSize,farSize,type) {
-        nearSize = parseFloat(nearSize);
-        farSize = parseFloat(farSize);
-        if(type !== 'width') {
-            let headerHeight = $(".header").height();
-            let toolsbarHeight = $(".sidebar-tools-bar").height();
-            let resizeHeight = 6;
-            let totalHeight = $(window).height() - headerHeight - toolsbarHeight - resizeHeight;
-            const navSize = eles.nav ? eles.nav[type]() + 4 : 0;
-            totalHeight = totalHeight - navSize;
-            nearSize = (nearSize/(nearSize + farSize))* totalHeight;
-            eles.nearSpread[type](nearSize);
-            eles.nearElement[type](nearSize);
-            eles.farSpread[type](totalHeight - nearSize);
-            eles.farElement[type](totalHeight - nearSize);
-        }
-    }
-    /**
-     * 读取设置的高度
-     *
-     * @param {String} tag - 顶层div的id
-     * @param {function} callback - 回调函数
-     * @return {void}
-     */
-
-    function loadSize(eles, type, callback) {
-        let tag = eles.id;
-        if (tag === '') {
-            return;
-        }
-        if(type !== 'height' && type !== 'width'){
-            return;
-        }
-        let o_nearSize = eles.nearSpread[type]();
-        let o_farSize = eles.farSpread[type]();
-        let nearSize = getLocalCache(`near${type}:${tag}`);
-        let farSize = getLocalCache(`far${type}:${tag}`);
-        if (nearSize === null || farSize === null) {
-            setDefaultSize(tag,eles,type);
-        }else {
-            setSizeWithPercent(tag,eles,nearSize,farSize,type)//zhang 2018-06-04 改成按百分比设置
-        }
-        callback();
-    }
-    /**
-     * 拖动更改div大小
-     *
-     * @param {Object} eles - id:存储本地的标记 resize:拖动条 nearElement:左上外层div nearSpread:左上spread farElement:右下外层div evFixedSize:造价书左右拖动用
-     * @param {Object} limit - min/max
-     * @param {String} type - height/width
-     * @param {function} callback - 成功后执行
-     * @return {void}
-     */
-    function slideResize(eles, limit, type, callback) {
-        if(type !== 'height' && type !== 'width'){
-            return;
-        }
-        //nearElement:左上, farElement:右下
-        let startP = 0;
-        let drag = false;
-        const resizeElement = eles.resize;
-        const nElement = eles.nearElement;
-        const fElement = eles.farElement;
-        const navContentEle = eles.nav ? eles.nav : null;
-        let nEleSize = 0;
-        let fEleSize = 0;
-        let navSize = 0;
-        let nEleChangeSize = 0;
-        let fEleChangeSize = 0;
-
-        // 鼠标点下时
-        resizeElement.mousedown(function(e) {
-            drag = true;
-            startP = type === 'height' ? e.clientY : e.clientX;
-            // 获取左(上)部分的宽度(高度)
-            nEleSize = nElement[type]();
-            // 获取右(下)部分的宽度(高度)
-            fEleSize = fElement[type]();
-            // nav宽(高度)部分
-            if(navContentEle){
-                navSize = navContentEle[type]() + 4;
-            }
-            resizeElement.tooltip('hide');
-        });
-
-        // 鼠标移动
-        $("body").mousemove(function(e) {
-            if (drag) {
-                let moveSize = type === 'height' ? e.clientY - startP : e.clientX - startP;
-                // 判断拖动范围不能超出
-                nEleChangeSize = nEleSize + moveSize;
-                nEleChangeSize = nEleChangeSize < limit.min ? limit.min : nEleChangeSize;
-                nEleChangeSize = nEleChangeSize > limit.max ? limit.max + 9 : nEleChangeSize;
-
-                fEleChangeSize = fEleSize - moveSize;
-                fEleChangeSize = fEleChangeSize < limit.min ? limit.min : fEleChangeSize;
-                fEleChangeSize = fEleChangeSize > limit.max ? limit.max + 9 : fEleChangeSize;
-
-                if(type === 'width'){
-                    let rePercent = getResizeWidthPercent(nEleChangeSize, fEleChangeSize);
-                    eles.nearElement.css(type, rePercent.nearPercent);
-                    eles.farElement.css(type, rePercent.farPercent);
-                }
-                else{
-                    eles.nearSpread[type](nEleChangeSize);
-                    eles.nearElement[type](nEleChangeSize);
-                    eles.farSpread[type](fEleChangeSize - navSize);
-                    eles.farElement[type](fEleChangeSize - navSize);
-                }
-                //实时刷新页面
-                mouseMoveCount+=Math.abs(moveSize);//取移动的决对值
-                if(mouseMoveCount >=5){//当累计移动超过5个像素时,才刷新,减少刷新次数
-                    if(callback) callback();
-                    mouseMoveCount = 0;
-                }
-            }
-        });
-
-        // 鼠标弹起
-        $("body").mouseup(function(e) {
-            if (drag) {
-                callback();
-                drag = false;
-                // 存入本地缓存
-                const id = eles.id;
-                nEleChangeSize = nEleChangeSize >= limit.max ? limit.max + 9  : nEleChangeSize;
-                fEleChangeSize = fEleChangeSize >= limit.max ? limit.max + 9  : fEleChangeSize;
-                setLocalCache(`near${type}:${id}`, nEleChangeSize);
-                setLocalCache(`far${type}:${id}`, fEleChangeSize);
-            }
-        });
-    }
-    /**
-     * 读取设置的高度
-     *
-     * @param {String} tag - 顶层div的id
-     * @param {function} callback - 回调函数
-     * @return {void}
-     */
-    function loadSize(eles, type, callback) {
-        let tag = eles.id;
-        if (tag === '') {
-            return;
-        }
-        if(type !== 'height' && type !== 'width'){
-            return;
-        }
-        let o_nearSize = eles.nearSpread[type]();
-        let o_farSize = eles.farSpread[type]();
-        let nearSize = getLocalCache(`near${type}:${tag}`);
-        let farSize = getLocalCache(`far${type}:${tag}`);
-        if (nearSize === null || farSize === null) {
-            setDefaultSize(tag,eles,type);//zhang 2018-05-21
-            /* eles.nearSpread[type](o_nearSize);
-             eles.farSpread[type](o_farSize);*/
-        }else {
-            setSizeWithPercent(tag,eles,nearSize,farSize,type)//zhang 2018-06-04 改成按百分比设置
-        }
-        if(type === 'width'){//使用百分比
-            let rePercent = getResizeWidthPercent(nearSize ? nearSize : o_nearSize, farSize ? farSize : o_farSize);
-            eles.nearElement.css(type, rePercent.nearPercent);
-            eles.farElement.css(type, rePercent.farPercent);
-        }
-        callback();
-    }
     //初始化个按钮点击
     //@return {void}
     function initBtn(){
@@ -1669,23 +1511,74 @@ const billsGuidance = (function () {
             //恢复章节树下的定额
             sectionInitSel(section.workBook.getActiveSheet().getActiveRowIndex());
         });
+        let keyupTime = 0,
+            delayTime = 500;
+        function delayKeyup(callback) {
+            let nowTime = Date.now();
+            keyupTime = nowTime;
+            setTimeout(function () {
+                if (nowTime - keyupTime == 0) {
+                    callback();
+                }
+            }, delayTime);
+        }
         //执行搜索
         $('#searchText').keyup(function (e) {
-            $('#searchBtn').click();
+            delayKeyup(function () {
+                $('#searchBtn').click();
+            });
+        });
+        //编辑清单备注
+        $('.main-side-bottom').find('textarea').keyup(function () {
+            let me = this;
+            let node = bills.tree.selected;
+            let comment = $(me).val();
+            delayKeyup(function () {
+                if (node) {
+                    let updateData = {lastOperator: userAccount, billsLibId: billsLibId, updateId: node.getID(), field: 'comment', data: comment};
+                    updateBillsComment(updateData, function () {
+                        node.data.comment = comment;
+                    })
+                }
+            });
         });
-        //编辑备注
+        //编辑选项备注
         $('.main-bottom-content').find('textarea').keyup(function () {
+            let me = this;
             let node = bills.tree.selected.guidance.tree.selected;
-            if(node){
-                let comment = $(this).val();
-                let updateDatas = [{updateType: updateType.update, findData: {ID: node.getID()}, updateData: {comment: comment}}];
-                updateGuideItems(updateDatas, function (rstData) {
-                    node.data.comment = comment;
-                });
-            }
+            let comment = $(me).val();
+            delayKeyup(function () {
+                if(node){
+                    let updateDatas = [{updateType: updateType.update, findData: {ID: node.getID()}, updateData: {comment: comment}}];
+                    updateGuideItems(updateDatas, function (rstData) {
+                        node.data.comment = comment;
+                    });
+                }
+            });
         });
         //定额高度拖动调整
-        slideResize(rationLibResizeEles, {min: 147, max: 680}, 'height', function() {
+        let heightEleObj = {
+            resize: $('#deResize'),
+            top: $('#topContent'),
+            topSpread: $('#sectionSpread'),
+            bottom: $('#bottomContent'),
+            bottomSpread: $('#rationSpread')
+        },
+            heightLimit = {
+                min: 150,
+                max: `$(window).height()-$('.header').height()-$('.sidebar-tools-bar').height()-150-10`,
+                notTopSpread: 0,
+                notBottomSpread: 0,
+            };
+        SlideResize.verticalSlide(moduleName, heightEleObj, heightLimit, function () {
+            if(section.workBook){
+                section.workBook.refresh();
+            }
+            if(ration.workBook){
+                ration.workBook.refresh();
+            }
+        });
+        /*slideResize(rationLibResizeEles, {min: 147, max: 680}, 'height', function() {
             //autoFlashHeight();
             if(section.workBook){
                 section.workBook.refresh();
@@ -1693,6 +1586,70 @@ const billsGuidance = (function () {
             if(ration.workBook){
                 ration.workBook.refresh();
             }
+        });*/
+        //左右拖动
+        //清单表与项目指引表
+        let leftElesObj = {};
+        leftElesObj.resize = $('#slideResizeLeft');
+        leftElesObj.parent = $('#dataRow');
+        leftElesObj.left = $('#leftContent');
+        leftElesObj.right = $('#midContent');
+        SlideResize.horizontalSlide(moduleName, leftElesObj, {min: 200, max: `$('#dataRow').width() - $('#rightContent').width() - 200`}, function () {
+            refreshALlWorkBook();
+        });
+        //人材机表与人材机组成物表
+        let rightElesObj = {};
+        rightElesObj.resize = $('#slideResizeRight');
+        rightElesObj.parent = $('#dataRow');
+        rightElesObj.left = $('#midContent');
+        rightElesObj.right = $('#rightContent');
+        SlideResize.horizontalSlide(moduleName, rightElesObj, {min: 200, max: `$('#dataRow').width() - $('#leftContent').width() - 200`}, function () {
+            refreshALlWorkBook();
+        });
+    }
+    //刷新全部工作簿
+    //@return {void}
+    function refreshALlWorkBook() {
+        if (bills.workBook) {
+            bills.workBook.refresh();
+        }
+        if (guideItem.workBook) {
+            guideItem.workBook.refresh();
+        }
+        if (section.workBook) {
+            section.workBook.refresh();
+        }
+        if (ration.workBook) {
+            ration.workBook.refresh();
+        }
+        $('.main-side-bottom').find('textarea').height($('.main-side-bottom').height() - 20);
+        $('.main-side-bottom').find('textarea').width($('.main-side-bottom').width() - 25);
+        $('.main-bottom-content').find('textarea').height($('.main-bottom-content').height() - 20);
+        $('.main-bottom-content').find('textarea').width($('.main-bottom-content').width() - 25);
+    }
+    //读取拖动相关
+    //@return {void}
+    function initSlideSize() {
+        //定额表上下
+        let heightEleObj = {
+            top: $('#topContent'),
+            topSpread: $('#sectionSpread'),
+            bottom: $('#bottomContent'),
+            bottomSpread: $('#rationSpread')
+        };
+        SlideResize.loadVerticalHeight(moduleName, heightEleObj,
+            {totalHeight: `$(window).height()-$('.header').height()-$('.sidebar-tools-bar').height()-10`,
+             notTopSpread: 0, notBottomSpread: 0}, function () {
+                if(section.workBook){
+                    section.workBook.refresh();
+                }
+                if(ration.workBook){
+                    ration.workBook.refresh();
+                }
+            });
+        //水平
+        SlideResize.loadHorizonWidth(moduleName, [$('#slideResizeLeft'), $('#slideResizeRight')], [$('#leftContent'), $('#midContent'), $('#rightContent')], function () {
+            refreshALlWorkBook();
         });
     }
     //初始化视图
@@ -1703,23 +1660,13 @@ const billsGuidance = (function () {
         getLibWithBills(libID);
         initBtn();
         initContextMenu();
-        loadSize(rationLibResizeEles, 'height', function () {
-            if(section.workBook){
-                section.workBook.refresh();
-            }
-            if(ration.workBook){
-                ration.workBook.refresh();
-            }
-        });
+        initSlideSize();
     }
 
 
-    return {initViews};
+    return {initViews, initSlideSize};
 })();
 
 $(document).ready(function () {
     billsGuidance.initViews();
-    CommonAjax.post('/billsGuidance/api/testItems', {libID: getQueryString('libID')}, function (rstData) {
-        console.log(rstData);
-    });
 });

+ 7 - 2
web/maintain/billsGuidance_lib/js/global.js

@@ -5,7 +5,10 @@ function autoFlashHeight(){
     var toolsBar = $(".toolsbar").height();
     var toolsBarHeightQ = $(".tools-bar-height-q").height();
     $(".content").height($(window).height()-headerHeight);
-    $(".main-side").height($(window).height()-headerHeight-2);
+    $(".main-side-top").height(($(window).height()-headerHeight) * 0.85);
+    $(".main-side-bottom").height(($(window).height()-headerHeight) * 0.15);
+    $('.main-side-bottom').find('textarea').height($('.main-side-bottom').height() - 20);
+    $('.main-side-bottom').find('textarea').width($('.main-side-bottom').width() - 25);
     $(".fluid-content").height($(window).height()-headerHeight-1);
     $(".side-content").height($(window).height()-headerHeight);
     $(".poj-list").height($(window).height()-headerHeight);
@@ -18,7 +21,9 @@ function autoFlashHeight(){
     $(".main-data-full").height($(window).height()-headerHeight);
     $(".main-data-bottom").height($(window).height()-headerHeight-toolsBarHeightQ-topContentHeight-$('#rationSearchResult').height() + 30);
     $('.bottom-content').height($('.main-data-bottom').height());
-
+    if (typeof billsGuidance !== 'undefined') {
+        billsGuidance.initSlideSize();
+    }
 };
 $(window).resize(autoFlashHeight);
 /*全局自适应高度结束*/

+ 96 - 2
web/maintain/bills_lib/html/main.html

@@ -32,7 +32,7 @@
                   <div class="col-md-8">
                     <div class="warp-p2 mt-3">
                       <table class="table table-hover table-bordered">
-                        <thead><tr><th>清单规则名称</th><th width="160">添加时间</th><th width="90">操作</th></tr></thead>
+                        <thead><tr><th>清单规则名称</th><th width="160">添加时间</th><th width="90">操作</th><th width="90">导入</th></tr></thead>
                         <tbody id="showArea">
                           <!--<tr><td><a href="qingdan.html">XX清单规则</a></td><td>2017-01-01 </td><td><a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a> <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>
                           <tr><td><a href="qingdan.html">XX清单规则</a></td><td>2017-01-01 </td><td><a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a> <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>
@@ -116,10 +116,39 @@
             </div>
         </div>
     </div>
+    <!--弹出导入数据-->
+    <div class="modal fade" id="import" 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">
+                    <div class="alert alert-warning" role="alert">
+                        导入操作会覆盖数据,请谨慎操作!!
+                    </div>
+                    <form>
+                        <div class="form-group">
+                            <label>请选择Excel格式文件</label>
+                            <input class="form-control-file" type="file" accept=".xlsx,.xls" name="import_data"/>
+                        </div>
+                    </form>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-primary" id="data-import">确定导入</button>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                </div>
+            </div>
+        </div>
+    </div>
     <!-- JS. -->
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/tether/tether.min.js"></script>
     <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/public/web/PerfectLoad.js"></script>
     <script src="/public/web/common_ajax.js"></script>
     <script src="/web/maintain/bills_lib/scripts/global.js"></script>
     <script src="/web/maintain/bills_lib/scripts/bills_lib_ajax.js"></script>
@@ -223,7 +252,72 @@
                 alert("请输入名称!");
             }
         });
-        //test es6
+        //清空选择
+        $('#import').on('shown.bs.modal', function () {
+            $("input[name='import_data']").val('');
+        });
+        let selLibId = -1;
+        $("#showArea").on("click", ".import-data", function () {
+            let id = $(this).data("id");
+            id = parseInt(id);
+            if (isNaN(id) || id <= 0) {
+                return false;
+            }
+            selLibId = id;
+            $("#import").modal("show");
+        });
+        //导入数据
+        $("#data-import").click(function() {
+            $.bootstrapLoading.start();
+            const self = $(this);
+            try {
+                let formData = new FormData();
+                let file = $("input[name='import_data']")[0];
+                if (file.files.length <= 0) {
+                    throw '请选择文件!';
+                }
+                formData.append('file', file.files[0]);
+                // 获取库id
+                if (selLibId <= 0) {
+                    return false;
+                }
+                formData.append('billsLibId', selLibId);
+                $.ajax({
+                    url: '/stdBillsEditor/importBills',
+                    type: 'POST',
+                    data: formData,
+                    cache: false,
+                    contentType: false,
+                    processData: false,
+                    beforeSend: function() {
+                        self.attr('disabled', 'disabled');
+                        self.text('上传中...');
+                    },
+                    success: function(response){
+                        self.removeAttr('disabled');
+                        self.text('确定导入');
+                        if (response.error === 0) {
+                            $.bootstrapLoading.end();
+                            // 成功则关闭窗体
+                            $('#import').modal("hide");
+                        } else {
+                            $.bootstrapLoading.end();
+                            const message = response.msg !== undefined ? response.msg : '上传失败!';
+                            alert(message);
+                        }
+                    },
+                    error: function(){
+                        $.bootstrapLoading.end();
+                        alert("与服务器通信发生错误");
+                        self.removeAttr('disabled');
+                        self.text('确定导入');
+                    }
+                });
+            } catch(error) {
+                alert(error);
+                $.bootstrapLoading.end();
+            }
+        });
     });
 </script>
 

+ 6 - 2
web/maintain/bills_lib/scripts/bills_lib_ajax.js

@@ -68,7 +68,9 @@ var mainAjax = {
                             "<td>"+createDateFmt+" </td>" +
                             "<td><a href='javascript:void(0);' data-toggle='modal' data-target='#edit' title='编辑'>" +
                             "<i class='fa fa-pencil-square-o'></i></a> <a href='javascript:void(0);' data-toggle='modal' data-target='#del' class='text-danger' title='删除'>" +
-                            "<i class='fa fa-remove'></i></a></td></tr>");
+                            "<i class='fa fa-remove'></i></a></td>" +
+                            "<td><a class='btn btn-secondary btn-sm import-data' href='javacript:void(0);' data-id='"+ id +"' title='导入数据'><i class='fa fa-sign-in fa-rotate-90'></i>导入</a></td>"+
+                            "</tr>");
                         var newHref = "stdBills?billsLibId="+id;
                         $("#tempId td:first a").attr("href", newHref);
                         $("#tempId").attr("id", id);
@@ -92,7 +94,9 @@ var mainAjax = {
                     $("#showArea").append(
                         "<tr id='tempId'><td><a href='stdBills'>"+billsLibName+"</a></td><td>"+createDateFmt+" </td><td><a href='javascript:void(0);' data-toggle='modal' data-target='#edit' title='编辑'>" +
                         "<i class='fa fa-pencil-square-o'></i></a> <a href='javascript:void(0);' data-toggle='modal' data-target='#del' class='text-danger' title='删除'>" +
-                        "<i class='fa fa-remove'></i></a></td></tr>"
+                        "<i class='fa fa-remove'></i></a></td>" +
+                        "<td><a class='btn btn-secondary btn-sm import-data' href='javacript:void(0);' data-id='"+ id +"' title='导入数据'><i class='fa fa-sign-in fa-rotate-90'></i>导入</a></td>" +
+                        "</tr>"
                     );
                     var newHref = "stdBills?billsLibId="+id;
                     $("#tempId td:first a").attr("href", newHref);

Разлика између датотеке није приказан због своје велике величине
+ 1 - 1
web/maintain/main_col_lib/js/main_col_edit.js


+ 10 - 0
web/maintain/main_col_lib/js/main_tree_col.js

@@ -41,6 +41,16 @@ let MainTreeCol = {
 
     },
     readOnly: {
+        subType:function (node) {
+        },
+        calcProgramName:function (node) {
+        },
+        non_editSubType:function (node) {
+        },
+        commonUnitFee:function (node) {
+        },
+        commonTotalFee:function (node) {
+        },
         bills: function (node) {
             return node.sourceType === projectObj.project.Bills.getSourceType();
         },

+ 77 - 0
web/maintain/material_replace_lib/html/edit_新编辑版本.html

@@ -0,0 +1,77 @@
+<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="row">
+                <div class="tools-bar p-1 d-flex justify-content-between col-lg-12" style="background: #f7f7f7;">
+                    <div class="input-group input-group-sm col-lg-4">
+                        <input class="form-control" placeholder="搜索定位" type="text" id = 'keyword'>
+                        <span class="input-group-btn">
+                              <button class="btn btn-secondary" type="button"><i class="fa fa-search"></i></button>
+                            </span>
+                        <a class="btn btn-sm btn-link"  style="color: #0275d8;cursor:pointer" data-toggle="modal" data-target="#guize"">关于规则</a>
+                    </div>
+                </div>
+                <div class="main-content col-lg-4 p-0">
+                    <div class="main-data" id="billsSpread"></div>
+                </div>
+                <div class="col-lg-4 main-side p-0">
+
+                </div>
+                <div class="col-lg-4 main-side p-0" id="materialSpread"></div>
+
+            </div>
+        </div>
+        <input type="hidden" id="libID" value="<%= libID %>">
+        <input type="hidden" id="gljLibID" value="<%= gljLibID %>">
+        <input type="hidden" id="billsLibId" value="<%= billsLibId %>">
+        <div style="display: none">
+            <textarea  id = "testStd" type="hidden"><%= stdBills %></textarea>
+        </div>
+
+    </div>
+</div>
+
+<!--弹出关于规则-->
+<div class="modal fade" id="guize" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">关于规则</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <table class="table table-bordered">
+                    <thead><tr><th width="90">规则名称</th><th>规则解释</th></tr></thead>
+                    <tr><td>规则1</td><td>材料及规格:MU5烧结页岩空心砖</td></tr>
+                    <tr><td>规则2</td><td>1.混凝土种类:商品混凝土<br>2.混凝土强度等级:C30</td></tr>
+                </table>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+
+</div>
+
+<script type="text/javascript">
+    //自适应高度
+    $(".main-data").height($(window).height()-$(".header").height()-$(".tools-bar").height()-$(".navbar").height()-16);
+    let billsList = '<%- billsList %>';
+
+</script>
+<script type="text/javascript" src="/lib/jquery-contextmenu/jquery.contextMenu.js"></script>
+<script type="text/javascript" src="/public/web/sheet/sheet_common.js"></script>
+<script type="text/javascript" src="/public/web/sheet/sheet_data_helper.js"></script>
+
+<script type="text/javascript" src="/web/maintain/material_replace_lib/js/material_replace_edit.js"></script>

+ 478 - 0
web/maintain/material_replace_lib/js/material_replace_edit_新编辑版本.js

@@ -0,0 +1,478 @@
+/**
+ * Created by zhang on 2018/8/23.
+ */
+
+let materialOjb = {
+    billsSpread:null,
+    materialSpread:null,
+    allBills:JSON.parse(billsList),
+    billsList:JSON.parse(billsList),
+    stdBills:JSON.parse($("#testStd").val()),
+    materialList:[],
+    billsTreeSetting: {
+        treeCol: 0,
+        emptyRows: 0,
+        headRows: 1,
+        headRowHeight: [40],
+        defaultRowHeight: 21,
+        cols: [{
+            width: 200,
+            readOnly: true,
+            head: {
+                titleNames: ["项目编码"],
+                spanCols: [1],
+                spanRows: [1],
+                vAlign: [1],
+                hAlign: [1],
+                font: ["Arial"]
+            },
+            data: {
+                field: "code",
+                vAlign: 1,
+                hAlign: 0,
+                font: "Arial"
+            }
+        }, {
+            width: 200,
+            readOnly: true,
+            head: {
+                titleNames: ["项目名称"],
+                spanCols: [1],
+                spanRows: [1],
+                vAlign: [1],
+                hAlign: [1],
+                font: ["Arial"]
+            },
+            data: {
+                field: "name",
+                vAlign: 1,
+                hAlign: 0,
+                font: "Arial"
+            }
+        }]
+    },
+   /* billsSetting:{
+        header: [
+            {headerName: "清单编号", headerWidth: 180, dataCode: "code", dataType: "String",formatter: "@"},
+            {headerName: "清单名称", headerWidth: 240, dataCode: "name", dataType: "String"},
+            {headerName: "规则", headerWidth: 150, dataCode: "rule", hAlign: "left", dataType: "String",cellType:'comboBox',editorValueType:true,options:[{text:"规则1",value:1},{text:"规则2",value:2}]}
+        ],
+        view: {
+            lockColumns: [1]
+        },
+        headerHeight:45
+    },*/
+    materialSetting:{
+        header: [
+            {headerName: "材料编号", headerWidth: 180, dataCode: "code", dataType: "String",formatter: "@"},
+            {headerName: "材料名称", headerWidth: 240, dataCode: "name", dataType: "String",cellType:'tipsCell'},
+            {headerName: "规格", headerWidth: 150, dataCode: "specs", hAlign: "left", dataType: "String",cellType:'tipsCell'}
+        ],
+        view: {
+            lockColumns: [1,2]
+        },
+        headerHeight:45
+    },
+    initSpread:function () {
+      /*  if(!this.billsSpread){
+            this.billsSpread = SheetDataHelper.createNewSpread($("#billsSpread")[0]);
+        }
+        if(!this.materialSpread){
+            this.materialSpread = SheetDataHelper.createNewSpread($("#materialSpread")[0]);
+        }
+        this.billsSheet = this.billsSpread .getSheet(0);
+        sheetCommonObj.initSheet(this.billsSheet,this.billsSetting, 30);
+        this.billsSheet.name('billsSheet');
+        this.billsSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onBillsValueChange);
+        this.billsSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onBillsSelectionChange);
+        this.billsSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onBillsRangeChange);
+
+        this.initRightClick("billsSpread",this.billsSpread);
+
+
+        this.materialSheet = this.materialSpread .getSheet(0);
+        sheetCommonObj.initSheet(this.materialSheet,this.materialSetting, 30);
+        this.materialSheet.name('materialSheet');
+        this.materialSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onMaterialValueChange);
+        this.materialSheet.bind(GC.Spread.Sheets.Events.EditStarting, this.onMaterialEditStarting);
+        this.materialSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMaterialRangeChange);
+        this.initRightClick("materialSpread",this.materialSpread);
+        this.refreshSheet();*/
+
+    },
+    canDelete : function (sheet) {
+        let me = this;
+        let sel =  sheet.getSelections()[0];
+        let datas = sheet.name() == 'billsSheet'?me.billsList:me.materialList;
+        if(sel.row === undefined || sel.row < 0) return false ;//一行都没选中时,不能删除
+        if((sel.row + sel.rowCount) > datas.length) return false;//选中了空行,不能删除
+        return true;
+    },
+    deleteBills : async function(sheet){
+        let me = this,deleteList = [];
+        let sel = sheet.getSelections()[0];
+        for(let i = 0;i<sel.rowCount;i++){
+            if(me.billsList[sel.row + i]) deleteList.push(getDeleteDatas(me.billsList[sel.row + i]));
+        }
+        if(deleteList.length > 0) await me.saveBills(deleteList);
+        function getDeleteDatas(tem) {
+            return {type:'delete', ID:tem.ID}
+        }
+
+    },
+    deleteMaterial:async function(sheet){
+        let me = this,deleteList = [];
+        let sel = sheet.getSelections()[0];
+        for(let i = 0; i<sel.rowCount;i++){
+            if(me.materialList[sel.row + i]) deleteList.push(me.getMaterialUpdateData(null,me.materialList[sel.row + i].ID,true));
+        }
+        if(deleteList.length > 0) await me.saveMaterial(deleteList);
+    },
+    initRightClick : function(id,spread) {
+        let me = this;
+        let sheet = spread.getActiveSheet();
+        $.contextMenu({
+            selector: '#'+id,
+            build: function ($trigger, e) {
+                me.rightClickTarget = SheetDataHelper.safeRightClickSelection($trigger, e, spread);
+                return me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.viewport ||
+                    me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                "delete": {
+                    name: "删除",
+                    icon: 'fa-trash-o',
+                    disabled: function () {
+                        return !me.canDelete(sheet);
+                    },
+                    callback: function (key, opt) {
+                        sheet.name() == 'billsSheet' ? me.deleteBills(sheet):me.deleteMaterial(sheet);
+                       console.log( me.rightClickTarget);
+                    }
+                }
+            }
+        });
+    },
+    refreshSheet:async function(){
+        this.getBillsList();
+        sheetCommonObj.showData(this.billsSheet,this.billsSetting,this.billsList);
+        this.billsSheet.setRowCount(this.billsList.length + 30);
+        this.showMaterialList();
+    },
+    getBillsList:function () {
+        let keyword = $("#keyword").val();
+        if(isDef(keyword)&&keyword!==''){
+            this.billsList = _.filter(this.allBills,function (item) {
+                return item.code.indexOf(keyword)!=-1 || item.name.indexOf(keyword)!=-1;
+            })
+        }else {
+            this.billsList = this.allBills;
+        }
+        this.billsList = _.sortBy(this.billsList,'code');
+    },
+    getMateriaList:async function () {
+        let billsItemID =  this.getCurrentBillsID();
+        if(billsItemID){
+            this.materialList = await this.getMaterialByBillsID(billsItemID)//getMaterialByBills
+        }else {
+            this.materialList = [];
+        }
+    },
+    showMaterialList:async function () {
+        await this.getMateriaList();
+        this.refreshMaterialSheet();
+    },
+    refreshMaterialSheet:function () {
+        this.materialList = _.sortBy(this.materialList,'code');
+        sheetCommonObj.showData(this.materialSheet,this.materialSetting,this.materialList);
+        this.materialSheet.setRowCount(this.materialList.length + 30);
+    },
+    onBillsSelectionChange:function (sender,args) {
+        let me = materialOjb;
+        let nsel = args.newSelections?args.newSelections[0]:null;
+        let osel = args.oldSelections?args.oldSelections[0]:null;
+        if(nsel && osel && nsel.row != osel.row){
+            me.showMaterialList();
+            me.materialSheet.showRow(0, GC.Spread.Sheets.VerticalPosition.top);
+        }
+        args.sheet.repaint();
+    },
+    onBillsRangeChange:function (sender,args) {
+        let me = materialOjb;
+        let updateDatas = [];
+        if(args.action == GC.Spread.Sheets.RangeChangedAction.paste){
+            for(let c of args.changedCells){
+                let field = me.billsSetting.header[c.col].dataCode;
+                let newValue =  args.sheet.getCell(c.row,c.col).value();
+                let data = null;
+                if(me.validateBills(field,newValue)){
+                    if(c.row < me.billsList.length){
+                         data = me.getUpdateData(field,newValue,me.billsList[c.row].code);
+                    }else if(field == 'code'){//如果是在空白行粘贴,并且是编码列,则是新增,其它的忽略;
+                         data = me.getUpdateData(field,newValue,null);
+                    }
+                    if(data) updateDatas.push(data);
+                }else {
+                    break;
+                }
+            }
+            if(updateDatas.length > 0){
+                me.saveBills(updateDatas);
+                return;
+            }
+        }
+         me.refreshSheet();
+    },
+    onMaterialRangeChange:function(sender,args){
+        let me = materialOjb;
+        let updateDatas = [];
+        if(args.action == GC.Spread.Sheets.RangeChangedAction.paste){
+            for(let c of args.changedCells){
+                let code =  args.sheet.getCell(c.row,c.col).value(),data = null;
+                if(me.validateMaterial(code)){
+                    if(c.row < me.materialList.length){
+                         data = me.getMaterialUpdateData(code,me.materialList[c.row].ID);
+                    }else {//如果是在空白行粘贴,并且是编码列,则是新增,其它的忽略;
+                         data = me.getMaterialUpdateData(code,null);
+                    }
+                    if(data) updateDatas.push(data);
+                }else {
+                    break;
+                }
+            }
+            if(updateDatas.length > 0){
+                me.saveMaterial(updateDatas);
+                return;
+            }
+        }
+        me.showMaterialList();
+    },
+
+
+    onBillsValueChange: function(sender,args){
+        let me = materialOjb;
+        let field = me.billsSetting.header[args.col].dataCode;
+        let code = null;
+        if(args.row < me.billsList.length){
+            code = me.billsList[args.row].code;
+        }
+        if(me.validateBills(field,args.newValue)){
+            let data = me.getUpdateData(field,args.newValue,code);
+            if (data){
+                me.saveBills([data]);
+                return;
+            }
+        }
+        me.refreshSheet();
+    },
+    onMaterialEditStarting : function (sender,args) {
+        let me = materialOjb;
+        if(!me.getCurrentBillsID()) args.cancel = true; //如果没选中清单则不能编辑
+    },
+
+    onMaterialValueChange:function(sender,args){
+        let me = materialOjb;
+        let ID = null;
+        if(args.row < me.materialList.length){
+            ID = me.materialList[args.row].ID;
+        }
+        if(me.validateMaterial(args.newValue)){
+            let data = me.getMaterialUpdateData(args.newValue,ID);
+            if(data){
+                me.saveMaterial([data]);
+                return
+            }
+        }
+        me.showMaterialList();
+
+    },
+    validateMaterial:function (value) {
+        value = value.toString().replace(/[\s\r\n]/g, "");//去除空格换行等字符;
+        if(_.find(this.materialList,{code:value})){
+            alert("人材机:"+value+" 已存在");
+            return false;
+        }
+        return true;
+    },
+    validateBills:function (field,value) {
+        if(field == 'code'){
+            value = value.toString().replace(/[\s\r\n]/g, "");//去除空格换行等字符;
+            if(value.length !== 9){
+                alert("清单长度不正确");
+                return false;
+            }
+            if(_.find(this.billsList,{'code':value})) {
+                alert("清单:"+value+" 已存在");
+                return false;
+            }
+        }
+        return true;
+    },
+    getCurrentBillsID:function(){
+      let sel = this.billsSheet.getSelections()[0];
+      if(sel.row < this.billsList.length){
+           return this.billsList[sel.row].ID;
+      }
+      return null;
+    },
+    getMaterialUpdateData:function(code,ID,isDelete){
+        if(isDelete == true){
+            return {type:'delete', ID:ID}
+        }
+        code = code.toString().replace(/[\s\r\n]/g, "");//去除空格换行等字符;
+        if((!isDef(ID)||ID=='')&& code != null){//新增
+            let billsItemID = this.getCurrentBillsID();
+            return {
+                type:'add',
+                code:code,
+                billsItemID:billsItemID,
+                libID:$('#libID').val(),
+                gljLibID:parseInt($('#gljLibID').val())
+            }
+        }else { //替换材料
+            return {
+                type:'update',
+                ID:ID,
+                code:code,
+                gljLibID:parseInt($('#gljLibID').val())
+            }
+        }
+    },
+    getUpdateData:function (field,newValue,code) {
+        if(field == 'code'){
+            newValue = newValue.toString().replace(/[\s\r\n]/g, "");//去除空格换行等字符;
+            if((!isDef(code) || code =='')&&newValue!=null){//说明是新增
+                return {
+                    type:'add',
+                    code:newValue,
+                    libID:$('#libID').val(),
+                    billsLibId:parseInt($('#billsLibId').val())
+                }
+            }else {//说明是替换
+                return {
+                    type:'update',
+                    oldCode:code.toString(),
+                    newCode:newValue,
+                    libID:$('#libID').val(),
+                    billsLibId:parseInt($('#billsLibId').val())
+                }
+            }
+        }else if(isDef(code)){
+            let updateData = {};
+            updateData[field] = newValue;
+            return {
+                type:'update',
+                oldCode:code.toString(),
+                libID:$('#libID').val(),
+                updateData:updateData
+            }
+        }
+    },
+    saveMaterial:async function(datas){
+        try {
+            let result = await ajaxPost("/materialReplace/saveMaterial",datas);
+            let missCodes = [];
+            for(let r of result){
+                if(r.missCodes && r.missCodes.length >0) missCodes =missCodes.concat(r.missCodes);
+            }
+            if(missCodes.length > 0) alert(`没有找到人材机:${missCodes.join("、")}`);
+        }catch (err){
+            console.log(err);
+        }
+        this.showMaterialList();
+    },
+    saveBills:async function (datas) {
+        try {
+            let result = await ajaxPost("/materialReplace/saveBills",datas);
+            let missCodes = [];
+            for(let r of result){
+                if(r.missCodes && r.missCodes.length >0) missCodes =missCodes.concat(r.missCodes);
+                if(r.type == 'add'){
+                    this.allBills = this.allBills.concat(r.list);
+                }if(r.type == 'update'){
+                    for(let l of r.list){
+                       this.updateBillsCache(l.code,l.updateData);
+                    }
+                }if(r.type == 'delete'){
+                    _.remove(this.allBills,function (item) {
+                        return _.includes(r.list,item.ID)
+                    })
+                }
+            }
+            if(missCodes.length > 0) alert(`没有找到清单:${missCodes.join("、")}`);
+        }catch (err){
+            console.log(err);
+        }
+        this.refreshSheet();
+    },
+    saveDatas:async function (datas,type ='bills') {
+        try {
+            let currentList = type =='bills'?this.billsList:this.materialList;
+            let url = type =='bills'?"/materialReplace/saveBills":"/materialReplace/saveMaterial";
+            let text = type =='bills'?"清单":"人材机";
+            let result = await ajaxPost(url,datas);
+            let missCodes = [];
+            for(let r of result){
+                if(r.missCodes && r.missCodes.length >0) missCodes =missCodes.concat(r.missCodes);
+                if(r.type == 'add'){
+                    currentList = currentList.concat(r.list);
+                }if(r.type == 'update'){
+                    for(let l of r.list){
+                        type =='bills'?this.updateBillsCache(l.code,l.updateData):this.updateMaterialCache(l.ID,l.updateData);
+                    }
+                }if(r.type == 'delete'){
+                    _.remove(currentList,function (item) {
+                        return _.includes(r.list,item.ID)
+                    })
+                }
+            }
+            if(missCodes.length > 0) alert(`没有找到${text}:${missCodes.join("、")}`);
+        }catch (err){
+            console.log(err);
+        }
+
+    },
+    getMaterialByBillsID:async function(billsItemID){
+        try {
+            let result = await ajaxPost("/materialReplace/findMaterial",{billsItemID:billsItemID});
+            return result;
+        }catch (err){
+            console.log(err);
+            return [];
+        }
+    },
+    updateMaterialCache:function (ID,updateData) {
+        this.updateCache(this.materialList,{'ID':ID},updateData)
+    },
+
+    updateBillsCache:function (code,updateData) {
+         this.updateCache(this.allBills,{'code':code},updateData)
+    },
+
+    updateCache:function (list,condition,updateData) {
+        let item = _.find(list,condition);
+        for(let key in updateData){
+            item[key] = updateData[key]
+        }
+    }
+};
+let last = 0;
+
+$(document).ready(function () {
+    $("#keyword").on('input propertychange', function(event) {
+        last = event.timeStamp;//利用event的timeStamp来标记时间,这样每次事件都会修改last的值,注意last必需为全局变量
+        setTimeout(function () {    //设时延迟0.5s执行
+            if (last - event.timeStamp == 0) { //如果时间差为0(也就是你停止输入0.5s之内都没有其它的keyup事件发生)则做你想要做的事
+               materialOjb.refreshSheet();
+            }
+
+        }, 500);
+    })
+});
+
+function isDef(obj) {
+    return obj!==undefined && obj!==null;
+}
+
+materialOjb.initSpread();
+

+ 13 - 0
web/maintain/ration_repository/css/main.css

@@ -281,3 +281,16 @@ body {
 .btn.disabled, .btn:disabled {
     color: #999;
 }
+div.resize-y{
+    height: 10px;
+    background: #efefef;
+    width: 100%;
+    cursor: s-resize;
+}
+div.resize-x{
+    width: 10px;
+    background: #efefef;
+    height: 100%;
+    cursor: w-resize;
+    float: left;
+}

+ 29 - 15
web/maintain/ration_repository/dinge.html

@@ -57,19 +57,21 @@
     <div class="main" style="overflow: hidden">
         <div class="content">
             <div class="container-fluid">
-                <div class="row">
-                    <div class="main-side p-0" style="width: 25%; height: 100%; overflow: hidden">
-                        <div class="tab-bar">
-                            <a href="javascript:void(0);" id="tree_Insert" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="插入"><i class="fa fa-plus" aria-hidden="true"></i></a>
-                            <a href="javascript:void(0);" id="tree_remove" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
-                            <a href="javascript:void(0);" id="tree_upLevel" class="btn btn-sm " data-toggle="tooltip" data-placement="bottom" title="" data-original-title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
-                            <a href="javascript:void(0);" id="tree_downLevel" class="btn btn-sm " data-toggle="tooltip" data-placement="bottom" title="" data-original-title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
-                            <a href="javascript:void(0);" id="tree_downMove" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
-                            <a href="javascript:void(0);" id="tree_upMove" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
-                        </div>
-                        <div class="tab-content" id="sectionSpread" style="overflow: hidden">
-                            <!--<ul id="rationChapterTree" class="ztree"></ul>-->
+                <div class="row" id="dataRow">
+                    <div class="main-side p-0" id="leftContent" style="width: 25%; height: 100%; overflow: hidden">
+                        <div style="width: 99%; float: left">
+                            <div class="tab-bar">
+                                <a href="javascript:void(0);" id="tree_Insert" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="插入"><i class="fa fa-plus" aria-hidden="true"></i></a>
+                                <a href="javascript:void(0);" id="tree_remove" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                                <a href="javascript:void(0);" id="tree_upLevel" class="btn btn-sm " data-toggle="tooltip" data-placement="bottom" title="" data-original-title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
+                                <a href="javascript:void(0);" id="tree_downLevel" class="btn btn-sm " data-toggle="tooltip" data-placement="bottom" title="" data-original-title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
+                                <a href="javascript:void(0);" id="tree_downMove" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                                <a href="javascript:void(0);" id="tree_upMove" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                            </div>
+                            <div class="tab-content" id="sectionSpread" style="overflow: hidden">
+                            </div>
                         </div>
+                        <div class="resize-x" id="slideResizeLeft"></div>
                     </div>
                     <div class="main-content p-0" id="mainContent" style="width: 75%">
                         <!-- 右标签 -->
@@ -96,7 +98,8 @@
                                 <!--定额top-->
                                 <div id="rationItemsSheet" class="main-data-top"></div>
                                 <!--定额bottom-->
-                                <div class="bottom-content">
+                                <div class="resize-y" id="rationSubResize"></div>
+                                <div class="bottom-content" id="subContent">
                                     <!-- 标签 -->
                                     <ul class="nav nav-tabs" role="tablist">
                                         <li class="nav-item">
@@ -111,6 +114,9 @@
                                         <li class="nav-item">
                                             <a class="nav-link" id="linkAZZJ" data-toggle="tab" href="#" role="tab">安装增加费</a>
                                         </li>
+                                        <li class="nav-item">
+                                            <a class="nav-link" id="linkMBGL" data-toggle="tab" href="#" role="tab">模板关联</a>
+                                        </li>
                                     </ul>
                                     <!-- 内容 -->
                                     <div class="tab-content">
@@ -174,10 +180,11 @@
                         </div>
                     </div>
                     <div class="main-side p-0 main-side-right" id="zmhsContent" style="width: 25%; display: none">
-                        <div class="resize" id="sideResize" style="width: 1%; height: 100%; resize:horizontal; cursor: w-resize; float: left; background: #F1F1F1"></div>
+                        <div class="resize-x" id="slideResizeRight"></div>
                         <div style="width: 99%; float: left">
                             <div class="main-data-top-fluid" id="mainSpread">
                             </div>
+                            <div class="resize-y" id="zmhsAdjResize"></div>
                             <div class="bottom-content" id="contentSpread">
                             </div>
                         </div>
@@ -667,6 +674,7 @@
         <script src="/lib/codemirror/xml.js"></script>
         <script src="/web/common/js/uploadImg.js"></script>
         <script src="/web/common/js/slideResize.js"></script>
+        <script src="/web/maintain/ration_repository/js/ration_template.js"></script>
         <script type="text/javascript">
             var exEditor = CodeMirror.fromTextArea(document.getElementById("explanationShow"), {
                 mode: "text/html",
@@ -695,13 +703,14 @@
             $(document).ready(function(){
                 rationOprObj.buildSheet($("#rationItemsSheet")[0]);
                 // tabPanel 下有多个Spread时,相互之间不能正确显示。改成一个Spread下多个Sheet。
-                var rdSpread = sheetCommonObj.createSpread($("#rdSpread")[0], 4);
+                var rdSpread = sheetCommonObj.createSpread($("#rdSpread")[0], 5);
                 rationGLJOprObj.buildSheet(rdSpread.getSheet(0));
 
                 rationAssistOprObj.buildSheet(rdSpread.getSheet(1));
 
                 rationCoeOprObj.buildSheet(rdSpread.getSheet(2));
                 rationInstObj.buildSheet(rdSpread.getSheet(3));
+                RationTemplate.buildSheet(rdSpread.getSheet(4));
                 rationInstObj.getInstallation(parseInt(getQueryString("repository")));
                 pageOprObj.initPage();
 
@@ -710,6 +719,7 @@
                 rdSpreadEscSheets.push({sheet: rdSpread.getSheet(1), editStarting: rationAssistOprObj.onEditStarting, editEnded: rationAssistOprObj.onEditEnded});
                 rdSpreadEscSheets.push({sheet: rdSpread.getSheet(2), editStarting: rationCoeOprObj.onEditStarting, editEnded: rationCoeOprObj.onEditEnded});
                 rdSpreadEscSheets.push({sheet: rdSpread.getSheet(3), editStarting: rationInstObj.onEditStarting, editEnded: rationInstObj.onEditEnded});
+                rdSpreadEscSheets.push({sheet: rdSpread.getSheet(4), editStarting: null, editEnded: RationTemplate.events.onEditEnded});
                 sheetCommonObj.bindEscKey(rdSpread, rdSpreadEscSheets);
 
                 $("#linkGLJ").click(function(){
@@ -730,6 +740,10 @@
                     rationInstObj.bindRationInstDel();
                     rdSpread.setActiveSheetIndex(3);
                 });
+                $("#linkMBGL").click(function(){
+                    RationTemplate.bindRationTempDel();
+                    rdSpread.setActiveSheetIndex(4);
+                });
                 //解决spreadjs sheet初始化没高度宽度
                 $('#modalCon').width($(window).width()*0.5);
                 $('#gljSelTreeDiv').height($(window).height() - 300);

+ 165 - 31
web/maintain/ration_repository/js/coe.js

@@ -4,50 +4,164 @@
 //modiyied by zhong on 2017/9/21
 
 $(document).ready(function () {
-    //子目换算左右拖动
-    let sideResizeEles = {};
-    sideResizeEles.totalWidth = 0.75;
-    sideResizeEles.id = 'stdCoe';
-    sideResizeEles.resize = $('#sideResize');
-    sideResizeEles.evFixedSize = `$(window).width()-$('.main-nav').width()-5`;
-    sideResizeEles.nearElement = $('.main-content');
-    sideResizeEles.nearSpread = $('.main-content');
-    sideResizeEles.farElement = $('.main-side-right');
-    sideResizeEles.farSpread = $('.main-side-right');
-    sideResizeEles.nav = null;
-    slideResize(sideResizeEles, {min: 250, max: $('.content').width()-260}, 'width', function(){
-        if (sideResizeEles.id === 'stdCoe') {
-            coeOprObj.workBook.refresh();
-            gljAdjOprObj.workBook.refresh();
+    function refreshALlWorkBook() {
+        if (sectionTreeObj.workBook) {
+            sectionTreeObj.workBook.refresh();
+        }
+        if (rationOprObj.workBook) {
             rationOprObj.workBook.refresh();
+        }
+        if (rationGLJOprObj.sheet && rationGLJOprObj.sheet.getParent()) {
             rationGLJOprObj.sheet.getParent().refresh();
         }
+        if (coeOprObj.workBook) {
+            coeOprObj.workBook.refresh();
+        }
+        if (gljAdjOprObj.workBook) {
+            gljAdjOprObj.workBook.refresh();
+        }
+    }
+    //定额章节树与定额表
+    let leftElesObj = {};
+    leftElesObj.resize = $('#slideResizeLeft');
+    leftElesObj.parent = $('#dataRow');
+    leftElesObj.left = $('#leftContent');
+    leftElesObj.right = $('#mainContent');
+    let maxEval = `$('#zmhsContent').is(':visible') ? $('#dataRow').width() - $('#zmhsContent').width() - 300 : $('#dataRow').width()  - 300`;
+    SlideResize.horizontalSlide(moduleName, leftElesObj, {min: 300, max: maxEval}, function () {
+        refreshALlWorkBook();
     });
+    SlideResize.loadHorizonWidth(moduleName, [$('#slideResizeLeft')], [$('#leftContent'), $('#mainContent')], function () {
+        //refreshAfterZmhs(false);
+        let leftContentWidth = parseFloat($('#leftContent')[0].style.width.replace('%', '')),
+            mainContentWidth = parseFloat($('#mainContent')[0].style.width.replace('%', ''));
+        let surplus = 100 - leftContentWidth - mainContentWidth;
+        $('#leftContent').css('width', `${leftContentWidth + surplus / 2}%`);
+        $('#mainContent').css('width', `${mainContentWidth + surplus / 2}%`);
 
+        refreshALlWorkBook();
+    });
+    //定额表与子目换算表
+    let rightElesObj = {};
+    rightElesObj.resize = $('#slideResizeRight');
+    rightElesObj.parent = $('#dataRow');
+    rightElesObj.left = $('#mainContent');
+    rightElesObj.right = $('#zmhsContent');
+    let maxEvalRight = `$('#dataRow').width() - $('#leftContent').width() - 200`;
+    SlideResize.horizontalSlide(moduleName, rightElesObj, {min: 200, max: maxEvalRight}, function () {
+        refreshALlWorkBook();
+    });
+    //设置水平拖动条的宽度
+    //@param {Object dom}resize滚动条
+    function setResizeWidth (resize) {
+        const fixedWidth = 10;
+        //跟滚动条同层的其他节点
+        let bros = resize.parent().children();
+        //滚动条节点 及 同层非滚动条节点的索引
+        let index = bros.index(resize),
+            otherIndex = index ? 0 : 1;
+        const other = resize.parent().children(`:eq(${otherIndex})`);
+        let resizeParentWidth = resize.parent().width();
+        let resizeDecimalWidth = fixedWidth / resizeParentWidth,
+            otherDecimalWidth = 1 - resizeDecimalWidth;
+        let resizePercentWidth = resizeDecimalWidth * 100 + '%',
+            otherPercentWidth = otherDecimalWidth * 100 + '%';
+        resize.css('width', resizePercentWidth);
+        other.css('width', otherPercentWidth);
+    }
+    function refreshAfterZmhs(visible) {
+        const min = 20;
+        //宽度比例localstorage key
+        let leftContentKey = `${moduleName}${$('#leftContent').attr('id')}Width`,
+            mainContentKey = `${moduleName}${$('#mainContent').attr('id')}Width`,
+            zmhsContentKey = `${moduleName}${$('#zmhsContent').attr('id')}Width`;
+        let zmhsWidth = getLocalCache(zmhsContentKey) ? getLocalCache(zmhsContentKey) :$('#zmhsContent')[0].style.width,
+            mainContentWidth = $('#mainContent')[0].style.width,
+            leftContentWidth;
+        zmhsWidth = parseFloat(zmhsWidth.replace('%', ''));
+        mainContentWidth = parseFloat(mainContentWidth.replace('%', ''));
+        if (visible) {
+            mainContentWidth = mainContentWidth - zmhsWidth / 2 < min ? min : mainContentWidth - zmhsWidth / 2;
+            if (100 - mainContentWidth - zmhsWidth < min) {
+                leftContentWidth = min;
+                zmhsWidth = 100 - mainContentWidth - leftContentWidth;
+            } else {
+                leftContentWidth = 100 - mainContentWidth - zmhsWidth;
+            }
+        } else {
+            mainContentWidth += zmhsWidth / 2;
+            leftContentWidth = 100 - mainContentWidth;
+        }
+        $('#leftContent').css('width', `${leftContentWidth}%`);
+        setLocalCache(leftContentKey, `${leftContentWidth}%`);
+        $('#mainContent').css('width', `${mainContentWidth}%`);
+        setLocalCache(mainContentKey, `${mainContentWidth}%`);
+        $('#zmhsContent').css('width', `${zmhsWidth}%`);
+        setLocalCache(zmhsContentKey, `${zmhsWidth}%`);
+        let resizes = [$('#slideResizeLeft'), $('#slideResizeRight')];
+        for (let resize of resizes) {
+            setResizeWidth(resize);
+        }
+    }
     $('#zmhs').click(function () {
         if(!$(this).hasClass('active')){
             $(this).addClass('active');
-            $('#mainContent').css('width', '50%');
+            refreshAfterZmhs(true);
             $('#zmhsContent').show();
-            loadSize(sideResizeEles, 'width', function(){
-
-            });
             if(!coeOprObj.workBook){
                 pageObj.initPage();
             }
-            coeOprObj.workBook.refresh();
-            gljAdjOprObj.workBook.refresh();
-            rationOprObj.workBook.refresh();
-            rationGLJOprObj.sheet.getParent().refresh();
+            refreshALlWorkBook();
         } else {
             $(this).removeClass('active');
-            $('#mainContent').css('width', '75%')
+            refreshAfterZmhs(false);
             $('#zmhsContent').hide();
-            rationOprObj.workBook.refresh();
-            rationGLJOprObj.sheet.getParent().refresh();
+            refreshALlWorkBook();
         }
     });
+    //子目换算和调整表上下拖动
+    let zmhsAdjResize = getZmhsAdjResize();
+    SlideResize.verticalSlide(moduleName, zmhsAdjResize.eleObj, zmhsAdjResize.limit, function () {
+        if (coeOprObj.workBook) {
+            coeOprObj.workBook.refresh();
+        }
+        if (gljAdjOprObj.workBook) {
+            gljAdjOprObj.workBook.refresh();
+        }
+    });
+    loadZmhsAdjSize(zmhsAdjResize);
 });
+function getZmhsAdjResize() {
+    let zmhsAdjResize = {};
+    zmhsAdjResize.eleObj = {
+        resize: $('#zmhsAdjResize'),
+        top: $('#mainSpread'),
+        topSpread: $('#mainSpread'),
+        bottom: $('#contentSpread'),
+        bottomSpread: $('#contentSpread')
+    };
+    zmhsAdjResize.limit = {
+        min: 150,
+        max: `$(window).height()-$('.header').height()-150-verticalResize`,
+        totalHeight: `$(window).height()-$('.header').height()-verticalResize`,
+        notTopSpread: 0,
+        notBottomSpread: 0,
+    };
+    return zmhsAdjResize;
+}
+function loadZmhsAdjSize(resizeObj) {
+    if (!resizeObj) {
+        resizeObj = getZmhsAdjResize();
+    }
+    SlideResize.loadVerticalHeight(moduleName, resizeObj.eleObj, resizeObj.limit, function () {
+        if (coeOprObj.workBook) {
+            coeOprObj.workBook.refresh();
+        }
+        if (gljAdjOprObj.workBook) {
+            gljAdjOprObj.workBook.refresh();
+        }
+    });
+}
 var pageObj = {
     libID: null,
     gljLibID: null,
@@ -413,10 +527,12 @@ let gljAdjOprObj = {
             {headerName:"名称", headerWidth:100, dataCode:"gljName", dataType: "String", hAlign: "center", vAlign: "center", readOnly: true},
             {headerName:"操作符", headerWidth:60, dataCode:"operator", dataType: "String", hAlign: "center", vAlign: "center", readOnly: false},
             {headerName:"数量", headerWidth:80, dataCode:"amount", dataType: "String", hAlign: "center", vAlign: "center" , readOnly: false},
+            {headerName:"替换为编码", headerWidth:80, dataCode:"replaceCode", dataType: "String", formatter: '@', hAlign: "center", vAlign: "center", readOnly: false},
+            {headerName:"替换为名称", headerWidth:100, dataCode:"replaceName", dataType: "String", hAlign: "center", vAlign: "center", readOnly: true}
         ],
         comboItems: {
             //调整类型下拉菜单
-            coeType: ['定额', '人工', '材料', '机械', '主材', '设备', '单个工料机'],
+            coeType: ['定额', '人工', '材料', '机械', '主材', '设备', '单个工料机','替换人材机'],
             //操作符下拉菜单
             operator: ['+', '-', '*', '/', '=']
         }
@@ -463,8 +579,16 @@ let gljAdjOprObj = {
     },
     onEditStart: function (sender, args) {
         let me = gljAdjOprObj;
-        if(!coeOprObj.currentCoe || args.row >= me.currentGljAdjList.length && args.col === 1
-            || args.row < me.currentGljAdjList.length && args.col === 1 && me.currentGljAdjList[args.row].coeType !== '单个工料机'){
+        let dataCode = me.setting.header[args.col].dataCode;
+        if(!coeOprObj.currentCoe || args.row >= me.currentGljAdjList.length  ){//超出编辑范围
+            if(dataCode=== 'gljCode' || dataCode=== 'replaceCode') args.cancel = true;
+            return;
+        }
+        if(dataCode=== 'gljCode' && me.currentGljAdjList[args.row].coeType !== '单个工料机'&& me.currentGljAdjList[args.row].coeType !== '替换人材机'){ //单个人才机和替换人材机,编码才能编辑
+            args.cancel = true;
+            return;
+        }
+        if(dataCode=== 'replaceCode' && me.currentGljAdjList[args.row].coeType !== '替换人材机'){//替换人材机类型 替换编码才能编辑
             args.cancel = true;
         }
     },
@@ -481,14 +605,22 @@ let gljAdjOprObj = {
                 //update
                 if(args.row < me.currentGljAdjList.length && args.editingText.toString().trim() !== me.currentGljAdjList[args.row][dataCode]){
                     let updateObj = me.currentGljAdjList[args.row];
-                    if(dataCode === 'gljCode' && typeof updateObj.coeType !== 'undefined' && updateObj.coeType === '单个工料机'){
+                    if(dataCode === 'gljCode' && typeof updateObj.coeType !== 'undefined' && (updateObj.coeType === '单个工料机'||updateObj.coeType === '替换人材机')){
                         let gljName = me.getGljName(args.editingText, me.gljList);
                         if(gljName){
                             updateObj.gljCode = args.editingText;
                             updateObj.gljName = gljName;
                             isUpdate = true;
+                        } else {
+                            alert("不存在编号为"+ args.editingText +"的工料机");
                         }
-                        else {
+                    }else if(dataCode === 'replaceCode' && typeof updateObj.coeType !== 'undefined' && updateObj.coeType === '替换人材机'){
+                        let gljName = me.getGljName(args.editingText, me.gljList);
+                        if(gljName){
+                            updateObj.replaceCode = args.editingText;
+                            updateObj.replaceName = gljName;
+                            isUpdate = true;
+                        } else {
                             alert("不存在编号为"+ args.editingText +"的工料机");
                         }
                     }
@@ -497,6 +629,8 @@ let gljAdjOprObj = {
                         updateObj[dataCode] = args.editingText;
                         updateObj.gljCode = '';
                         updateObj.gljName = '';
+                        updateObj.replaceCode = '';
+                        updateObj.replaceName = '';
                     }
                     else if(dataCode !== 'gljCode') {
                         isUpdate = true;

+ 6 - 0
web/maintain/ration_repository/js/gljSelect.js

@@ -50,6 +50,12 @@ let gljSelOprObj = {
             timeout:20000,
             success:function(result){
                 if(!result.error) {
+                    if(priceProperties && priceProperties.length > 0){
+                        let priceField = priceProperties[0].price.dataCode;
+                        for(let glj of result.data){
+                            glj.basePrice = glj.priceProperty && glj.priceProperty[priceField] ? glj.priceProperty[priceField] : 0;
+                        }
+                    }
                     me.stdGljList = result.data;
                     me.switchToGljId(me.stdGljList);
                     me.sortGlj(me.stdGljList);

+ 2 - 0
web/maintain/ration_repository/js/global.js

@@ -25,6 +25,8 @@ function autoFlashHeight(){
     $('#explanationShow').height($(window).height()-headerHeight-toolsBar-100);
 //计算规则
     $('#ruleTextShow').height($(window).height()-headerHeight-toolsBar-100);
+    typeof loadRationSubSize !== 'undefined' ? loadRationSubSize() : '';
+    typeof loadZmhsAdjSize !== 'undefined' ? loadZmhsAdjSize() : '';
 };
 $(window).resize(autoFlashHeight);
 /*全局自适应高度结束*/

+ 64 - 3
web/maintain/ration_repository/js/ration.js

@@ -2,6 +2,58 @@
  * Created by Tony on 2017/4/28.
  */
 
+$(document).ready(function () {
+   //定额表与下方子表上下拖动
+    let rationSubResize = getRationSubResize();
+    SlideResize.verticalSlide(moduleName, rationSubResize.eleObj, rationSubResize.limit, function () {
+        if (rationOprObj.workBook) {
+            rationOprObj.workBook.refresh();
+        }
+        if (rationGLJOprObj.sheet && rationGLJOprObj.sheet.getParent()) {
+            rationGLJOprObj.sheet.getParent().refresh();
+        }
+    });
+    SlideResize.loadVerticalHeight(moduleName, rationSubResize.eleObj, rationSubResize.limit, function () {
+        if (rationOprObj.workBook) {
+            rationOprObj.workBook.refresh();
+        }
+        if (rationGLJOprObj.sheet && rationGLJOprObj.sheet.getParent()) {
+            rationGLJOprObj.sheet.getParent().refresh();
+        }
+    });
+});
+function getRationSubResize() {
+    let rationSubResize = {};
+    rationSubResize.eleObj = {
+        resize: $('#rationSubResize'),
+        top: $('#rationItemsSheet'),
+        topSpread: $('#rationItemsSheet'),
+        bottom: $('#subContent'),
+        bottomSpread: $('#rdSpread')
+    };
+    rationSubResize.limit = {
+        min: 150,
+        max: `$(window).height()-$('.header').height()-$('.tools-bar').height()-150-verticalResize`,
+        totalHeight: `$(window).height()-$('.header').height()-$('.tools-bar').height()-verticalResize`,
+        notTopSpread: 0,
+        notBottomSpread: $('#subContent ul').height(),
+    };
+    return rationSubResize;
+}
+function loadRationSubSize(resizeObj) {
+    if (!resizeObj) {
+        resizeObj = getRationSubResize();
+    }
+    SlideResize.loadVerticalHeight(moduleName, resizeObj.eleObj, resizeObj.limit, function () {
+        if (rationOprObj.workBook) {
+            rationOprObj.workBook.refresh();
+        }
+        if (rationGLJOprObj.sheet && rationGLJOprObj.sheet.getParent()) {
+            rationGLJOprObj.sheet.getParent().refresh();
+        }
+    });
+}
+
 const digital = {
     gljPrc: -3,//计算定额基价时单个工料机价格取三位
     rationBasePrc: -2,
@@ -85,6 +137,7 @@ let rationOprObj = {
         sheetCommonObj.cleanData(sheetAss, settingAss, -1);
         sheetCommonObj.cleanData(sheetInst, settingInst, -1);
         let cacheSection = me.getCache();
+        RationTemplate.rationInitSel(cacheSection[row]);
         if (cacheSection && row < cacheSection.length) {
             rationGLJOprObj.getGljItems(cacheSection[row], function () {
                 if (focusOnSection){
@@ -136,6 +189,12 @@ let rationOprObj = {
         }
         for (let i = removeIds.length - 1; i >= 0; i--) {
             for (let j = cacheSection.length - 1; j >= 0 ; j--) {
+                if (cacheSection[j].rationTemplateList) {
+                    //清除模板关联
+                    _.remove(cacheSection[j].rationTemplateList, function (data) {
+                        return removeIds.includes(data.rationID);
+                    });
+                }
                 if (cacheSection[j]["ID"] == removeIds[i]) {
                     cacheSection.splice(j,1);
                 }
@@ -165,6 +224,7 @@ let rationOprObj = {
                         updateArr[i]['rationCoeList'] = cacheSection[j]['rationCoeList'] ? cacheSection[j]['rationCoeList'] : [];
                         updateArr[i]['rationAssList'] = cacheSection[j]['rationAssList'];
                         updateArr[i]['rationInstList'] = cacheSection[j]['rationInstList'];
+                        updateArr[i]['rationTemplateList'] = cacheSection[j]['rationTemplateList'];
                         cacheSection[j] = updateArr[i];
                     }
                 } else {
@@ -176,6 +236,7 @@ let rationOprObj = {
                         updateArr[i]['rationCoeList'] = cacheSection[j]['rationCoeList'] ? cacheSection[j]['rationCoeList'] : [];
                         updateArr[i]['rationAssList'] = cacheSection[j]['rationAssList'];
                         updateArr[i]['rationInstList'] = cacheSection[j]['rationInstList'];
+                        updateArr[i]['rationTemplateList'] = cacheSection[j]['rationTemplateList'];
                         cacheSection[j] = updateArr[i];
                     }
                 }
@@ -636,7 +697,7 @@ let rationOprObj = {
             let me = rationOprObj;
             me.mixUpdate = 0;
             me.currentSectionId = sectionID;
-            if (me.currentRations["_SEC_ID_" + sectionID]) {
+            /*if (me.currentRations["_SEC_ID_" + sectionID]) {
                 //jobContent--
                 jobContentOprObj.currentRationItems = me.currentRations["_SEC_ID_" + sectionID];
                 jobContentOprObj.rationJobContentOpr(me.currentRations["_SEC_ID_" + sectionID]);
@@ -647,7 +708,7 @@ let rationOprObj = {
                 if(callback){
                     callback();
                 }
-            } else {
+            } else */{
                 $.ajax({
                     type:"POST",
                     url:"api/getRationItems",
@@ -784,4 +845,4 @@ let rationOprObj = {
             }
         }
     }
-}
+}

+ 1 - 1
web/maintain/ration_repository/js/ration_assist.js

@@ -8,7 +8,7 @@ var rationAssistOprObj = {
     setting: {
         header:[
             {headerName:"调整名称",headerWidth:110,dataCode:"name", dataType: "String", hAlign: "left"},
-            {headerName:"辅助定额号",headerWidth:90,dataCode:"assistCode", dataType: "String", hAlign: "center"},
+            {headerName:"辅助定额号",headerWidth:90,dataCode:"assistCode", dataType: "String", hAlign: "center", formatter: "@"},
             {headerName:"标准值",headerWidth:60,dataCode:"stdValue", dataType: "String", hAlign: "right"},
             {headerName:"步距",headerWidth:60,dataCode:"stepValue", dataType: "String", hAlign: "right"},
             {headerName:"精度",headerWidth:60,dataCode:"decimal",  dataType: "String", hAlign: "right"},

+ 6 - 0
web/maintain/ration_repository/js/ration_glj.js

@@ -439,6 +439,12 @@ var rationGLJOprObj = {
             success:function(result){
                 if (result) {
                     if(result.data.length > 0){
+                        if(priceProperties && priceProperties.length > 0){
+                            let priceField = priceProperties[0].price.dataCode;
+                            for(let glj of result.data){
+                                glj.basePrice = glj.priceProperty && glj.priceProperty[priceField] ? glj.priceProperty[priceField] : 0;
+                            }
+                        }
                         sheetCommonObj.cleanData(me.sheet, me.setting, -1);
                         var rstArr = [], dummyR = {gljId: 0, consumeAmt:0}, newAddArr = [];
                         for (var i = 0; i < result.data.length; i++) {

+ 197 - 0
web/maintain/ration_repository/js/ration_template.js

@@ -0,0 +1,197 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2018/11/28
+ * @version
+ */
+/*
+* 定额下模板关联
+* */
+
+const RationTemplate = (function () {
+    let curRation = null;
+    function _isDef(v) {
+        return typeof v !== 'undefined' && v !== null;
+    }
+    //当前定额下的定额模板关联数据
+    let templateData = [];
+    let templateSheet = null;
+    //重新设置templateData
+    function setTemplateData(newData) {
+        templateData = _isDef(newData) && Array.isArray(newData) ? newData : [];
+    }
+    let setting = {
+        header:[
+            {headerName:"关联类别",headerWidth:110,dataCode:"type", dataType: "String", hAlign: "left", formatter: "@"},
+            {headerName:"编码",headerWidth:90,dataCode:"code", dataType: "String", hAlign: "left", formatter: "@"},
+            {headerName:"名称",headerWidth:240,dataCode:"name", dataType: "String", hAlign: "left", formatter: "@"},
+            {headerName:"具体位置",headerWidth:90,dataCode:"billsLocation", dataType: "String", hAlign: "left", formatter: "@"}
+        ],
+        view:{},
+    };
+    //渲染时方法,停止渲染
+    //@param {Object}sheet {Function}func @return {void}
+    function renderSheetFunc(sheet, func){
+        sheet.suspendEvent();
+        sheet.suspendPaint();
+        if(func){
+            func();
+        }
+        sheet.resumeEvent();
+        sheet.resumePaint();
+    }
+    const items = ['模板关联', '超高关联'];
+    //设置下拉单元格
+    //@return {void}
+    function setComboCells() {
+        if (!templateSheet) {
+            return;
+        }
+        let combo = sheetCommonObj.getDynamicCombo();
+        combo.items(items).editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.text);
+        templateSheet.getRange(-1, 0, -1, 1).cellType(combo);
+    }
+    //有效数据
+    //@param {String}dataCode {String}text @return {String}
+    function validateData(dataCode, text) {
+        //类别只能为规定的两种关联,否则将类别自动恢复为''
+        if (dataCode === 'type') {
+            if (text !== '' && !items.includes(text)) {
+                text = '';
+            }
+        }
+        return text;
+    }
+    //从当前表格获取数据
+    //@return {Array}
+    function getDataFromSheet() {
+        let rst = [];
+        if (!templateSheet) {
+            return rst;
+        }
+        let rowCount = templateSheet.getRowCount(),
+            colCount = templateSheet.getColumnCount();
+        for (let row = 0; row < rowCount; row++) {
+            let rowData = {type: '', code: '', name: '', billsLocation: ''},
+                rowExistData = false;
+            for (let col = 0; col < colCount; col++) {
+                let text = templateSheet.getValue(row, col),
+                    dataCode = setting.header[col]['dataCode'];
+                text = _isDef(text) ? text : '';
+                text = validateData(dataCode, text);
+                if (text !== '') {
+                    rowExistData = true;
+                    rowData[dataCode] = text;
+                } else {
+                    if (dataCode === 'code') {
+                        templateSheet.setValue(row, col + 1, '');
+                    }
+                }
+            }
+            //不为空行
+            if (rowExistData) {
+                rst.push(rowData);
+            }
+        }
+        return rst;
+    }
+    //编辑,定额编号自动匹配定额名称,匹配过程在后端进行,前端进行名称的更新输出
+    //@return {void}
+    function edit() {
+        if (!curRation) {
+            return;
+        }
+        let sheetData = getDataFromSheet();
+        CommonAjax.post('/rationRepository/api/updateRationTemplate',
+            {rationRepId: getQueryString('repository'), rationID: curRation.ID, templateData: sheetData}, function (rstData) {
+            templateData = rstData;
+            curRation.rationTemplateList = templateData;
+            renderSheetFunc(templateSheet, function () {
+                sheetCommonObj.showData(templateSheet, setting, templateData);
+            });
+        }, function () {
+            renderSheetFunc(templateSheet, function () {
+                sheetCommonObj.showData(templateSheet, setting, templateData);
+            });
+        });
+
+    }
+    let events = {
+        onEnterCell: function (sender, args) {
+            args.sheet.repaint();
+        },
+        onEditEnded: function (sender, args) {
+            edit();
+        },
+        onRangeChanged: function (sender, args) {
+            edit();
+        }
+    };
+    //重新绑定del建
+    //@return {void}
+    function bindRationTempDel() {
+        if (!templateSheet) {
+            return;
+        }
+        let workBook = templateSheet.getParent();
+        workBook.commandManager().register('rationTempDel', function () {
+            renderSheetFunc(templateSheet, function () {
+                let sels = templateSheet.getSelections();
+                for (let sel of sels) {
+                    sel.row = sel.row === -1 ? 0 : sel.row;
+                    sel.col = sel.col === -1 ? 0 : sel.col;
+                    for (let row = sel.row; row < sel.rowCount + sel.row; row++) {
+                        for (let col = sel.col; col < sel.colCount + sel.col; col++) {
+                            templateSheet.setValue(row, col, '');
+                        }
+                    }
+                }
+            });
+            edit();
+        });
+        workBook.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
+        workBook.commandManager().setShortcutKey('rationTempDel', GC.Spread.Commands.Key.del, false, false, false, false);
+    }
+    //建表
+    //@param {Object}sheet @return {void}
+    function buildSheet(sheet) {
+        templateSheet = sheet;
+        sheetCommonObj.initSheet(templateSheet, setting, 30);
+        templateSheet.options.isProtected = true;
+        setComboCells();
+        const Events = GC.Spread.Sheets.Events;
+        sheet.bind(Events.EditEnded, events.onEditEnded);
+        sheet.bind(Events.RangeChanged, events.onRangeChanged);
+        sheet.bind(Events.EnterCell, events.onEnterCell);
+    }
+
+    //更改模板关联表锁定状态
+    //@param {Boolean}locked @return {void}
+    function changeLockMode(locked) {
+        if (templateSheet) {
+            if (!locked) {
+                templateSheet.getRange(-1, 0, -1, 2).locked(false);
+                templateSheet.getRange(-1, 3, -1, 1).locked(false);
+            } else {
+                templateSheet.getRange(-1, 0, -1, 2).locked(true);
+                templateSheet.getRange(-1, 3, -1, 1).locked(true);
+            }
+        }
+    }
+    //变更定额
+    function rationInitSel(ration) {
+        curRation = ration ? ration : null;
+        changeLockMode(!ration);
+        sheetCommonObj.cleanData(templateSheet, setting, -1);
+        if (ration) {
+            setTemplateData(ration.rationTemplateList);
+            sheetCommonObj.showData(templateSheet, setting, templateData);
+        } else {
+            setTemplateData([]);
+        }
+    }
+    return {buildSheet, rationInitSel, bindRationTempDel, events}
+})();

+ 6 - 1
web/maintain/ration_repository/js/section_tree.js

@@ -1,6 +1,9 @@
 /**
  * Created by Zhong on 2017/12/18.
  */
+const moduleName = 'stdRation';
+//上下拖动div节点的高度
+const verticalResize = 10;
 let pageOprObj = {
     rationLibName : null,
     rationLibId : null,
@@ -614,7 +617,9 @@ let sectionTreeObj = {
     },
     //模仿默认点击
     initSelection: function (node) {
-        node.tree.selected = node ? node : null;
+        if (node && node.tree){
+            node.tree.selected = node ? node : null;
+        }
         let me = this;
         if(!me.isDef(node)){
             sheetCommonObj.cleanSheet(rationOprObj.workBook.getActiveSheet(), rationOprObj.setting, -1);

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

@@ -45,6 +45,12 @@
                     <input class="form-control input-sm" id="element_content_width" type="number" value="4.0" step="0.1" min="0" max="50" onchange="zTreeOprObj.changeProperty(`流水式表_信息.流水式表_数据.CommonWidth`, this)" disabled>
                 </div>
             </div>
+            <div class="row" id="element_adhoc_flags">
+                <div class="input-group col-2">
+                    <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>
         </div>
     </div>
 </div>

+ 48 - 4
web/maintain/report/js/rpt_tpl_main.js

@@ -143,6 +143,9 @@ let zTreeOprObj = {
                 items: me.private_build_items(subNode.items, null),
                 name: subNode.name
             };
+            if (subNode.hasOwnProperty('flags')) {
+                rst.flags = subNode.flags;
+            }
         }
         return rst;
     },
@@ -163,6 +166,9 @@ let zTreeOprObj = {
                     ir.name = item.name;
                     ir.ID = item.ID;
                     ir.released = isReleased;
+                    if (item.hasOwnProperty('flags')) {
+                        ir.flags = item.flags;
+                    }
                     ir.items = me.private_build_items(item.items);
                     itemRst.push(ir);
                 }
@@ -353,7 +359,7 @@ let zTreeOprObj = {
         let canContinue = false;
         if (isCopy) {
             me.getNewNodeID(1, function (newNodeID) {
-                let orgID = treeNodes[0].ID;
+                let orgID = treeNodes[0].refId; //refId才是正确的模板ID(因可能copy一个有引用的节点),
                 treeNodes[0].ID = newNodeID;
                 if (confirm("是否引用相同的报表模板?")) {
                     newTopNode = me.buildRootNodeDoc(targetTopNode);
@@ -363,6 +369,9 @@ let zTreeOprObj = {
                             treeNodes[0].rptTpl.ID = newNodeID;
                         }
                         me.currentNode = treeNodes[0];
+                        me.chkAndSetDupRefTplIds(me.treeObj.getNodes(), null);
+                        me.treeObj.refresh();
+                        me.chkAndRreshRefTpl();
                     }, function(badRst){
                         displayMessage("更新模板节点失败!", "red", 2000);
                         // console.log(badRst.toString());
@@ -381,6 +390,9 @@ let zTreeOprObj = {
                                 treeNodes[0].rptTpl.ID = newNodeID;
                             }
                             me.currentNode = treeNodes[0];
+                            me.chkAndSetDupRefTplIds(me.treeObj.getNodes(), null);
+                            me.treeObj.refresh();
+                            me.chkAndRreshRefTpl();
                         }, function(badRst){
                             displayMessage("更新模板节点失败!", "red", 2000);
                             // console.log(badRst.toString());
@@ -393,9 +405,9 @@ let zTreeOprObj = {
                     });
                 }
             });
-            if (canContinue) {
-                me.chkAndRreshRefTpl();
-            }
+            // if (canContinue) {
+            //     me.chkAndRreshRefTpl();
+            // }
         } else {
             newTopNode = me.buildRootNodeDoc(targetTopNode);
             me.updateTreeRootNode(newTopNode, false, function(rst){
@@ -530,6 +542,10 @@ let zTreeOprObj = {
                     tplNode.icon = "/lib/ztree/css/img/diy/3.png";
                 }
                 // tplNode.style = "background:url(/lib/ztree/css/img/diy/3.png) 0 0 no-repeat;"
+            } else {
+                //设置白板
+                // if (!tplNode.isParent) tplNode.icon = "/lib/ztree/css/img/diy/10.png";
+                if (!tplNode.isParent) tplNode.className = "button ico_docu";
             }
             if (tplNode.items && tplNode.items.length > 0) {
                 for (let subTplNode of tplNode.items) {
@@ -727,6 +743,23 @@ let zTreeOprObj = {
             }
         }
     },
+    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;
+            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 = {};
@@ -816,6 +849,17 @@ let zTreeOprObj = {
                             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;
+                            }
+                        } else {
+                            $("#element_flags_select")[0].selectedIndex = 0;
+                        }
+
                         if ($("#rpt_tpl_visual_tab")[0].className === "nav-link p-1 active") {
                             setTimeout(function(){visualJumbo.iniSpreadJs(); visualJumbo.setupTpl()}, 50)
                         }

+ 10 - 5
web/maintain/std_glj_lib/html/gongliao.html

@@ -41,9 +41,9 @@
     <div class="main">
         <div class="content" style="z-index: 700; overflow: hidden">
             <div class="container-fluid">
-                <div class="row">
+                <div class="row" id="dataRow">
                     <!--org 3:7:2-->
-                  <div class="main-side col-lg-3 p-0" style="width: 100%; height: 100%; overflow: hidden">
+                  <div class="main-side p-0" id="leftContent" style="width: 25%; height: 100%; overflow: hidden">
                       <div class="tab-bar">
                           <a href="javascript:void(0);" id="tree_Insert" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="插入"><i class="fa fa-plus" aria-hidden="true"></i></a>
                           <a href="javascript:void(0);" id="tree_remove" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
@@ -56,11 +56,15 @@
                       </div>
                         <!--<ul id="repositoryTree" class="ztree"></ul>-->
                   </div>
-                  <div class="main-content col-lg-6 p-0">
-                    <div id="GLJListSheet" class="main-data">
+                  <div class="main-content p-0" style="width: 50%" id="midContent">
+                      <div class="resize" id="slideResizeLeft" style="width: 1%; height: 100%; resize:horizontal; cursor: w-resize; float: left; background: #F1F1F1"></div>
+                    <div id="GLJListSheet" class="main-data" style="width: 99%; float: left">
                     </div>
                   </div>
-                    <div id="gljComponentSheet" class="main-side col-lg-3 p-0">
+                    <div class="main-side-right p-0" style="width: 25%;" id="rightContent">
+                        <div class="resize" id="slideResizeRight" style="width: 1%; height: 100%; resize:horizontal; cursor: w-resize; float: left; background: #F1F1F1"></div>
+                        <div id="gljComponentSheet" class="main-side p-0" style="width: 99%; float: left">
+                    </div>
                     </div>
                 </div>
             </div>
@@ -218,6 +222,7 @@
     <script type="text/javascript" src="/public/web/sheet/sheet_common.js"></script>
     <script type="text/javascript" src="/web/maintain/std_glj_lib/js/sheetsOpr.js"></script>
     <script type="text/javascript" src="/public/web/storageUtil.js"></script>
+    <script src="/web/common/js/slideResize.js"></script>
     <% if(overWriteUrl){ %>
     <script type="text/javascript" src="<%= overWriteUrl %>"></script>
     <% } %>

+ 38 - 1
web/maintain/std_glj_lib/js/glj.js

@@ -2,6 +2,43 @@
  * Created by Zhong on 2017/8/14.
  */
 
+$(document).ready(function () {
+    let moduleName = 'stdGLj';
+    function refreshALlWorkBook() {
+        if (gljClassTreeObj.workBook) {
+            gljClassTreeObj.workBook.refresh();
+        }
+        if (repositoryGljObj.workBook) {
+            repositoryGljObj.workBook.refresh();
+        }
+        if (gljComponentOprObj.workBook) {
+            gljComponentOprObj.workBook.refresh();
+        }
+    }
+    SlideResize.loadHorizonWidth(moduleName, [$('#slideResizeLeft'), $('#slideResizeRight')], [$('#leftContent'), $('#midContent'), $('#rightContent')], function () {
+        refreshALlWorkBook();
+    });
+    //章节树与人材机表
+    let leftElesObj = {};
+    leftElesObj.resize = $('#slideResizeLeft');
+    leftElesObj.parent = $('#dataRow');
+    leftElesObj.left = $('#leftContent');
+    leftElesObj.right = $('#midContent');
+    SlideResize.horizontalSlide(moduleName, leftElesObj, {min: 200, max: `$('#dataRow').width() - $('#rightContent').width() - 200`}, function () {
+        refreshALlWorkBook();
+    });
+    //人材机表与人材机组成物表
+    let rightElesObj = {};
+    rightElesObj.resize = $('#slideResizeRight');
+    rightElesObj.parent = $('#dataRow');
+    rightElesObj.left = $('#midContent');
+    rightElesObj.right = $('#rightContent');
+    SlideResize.horizontalSlide(moduleName, rightElesObj, {min: 200, max: `$('#dataRow').width() - $('#leftContent').width() - 200`}, function () {
+       refreshALlWorkBook();
+    });
+});
+
+
 const digital = {
     basePrice: -2,
     consumeAmt: -3
@@ -1486,7 +1523,7 @@ let repositoryGljObj = {
             data:{"repositoryId": me.currentRepositoryId, "lastOpr": userAccount, "updateItems": JSON.stringify(updateArr), "addItems": JSON.stringify(addArr), "removeIds": JSON.stringify(removeIds)},
             dataType:"json",
             cache:false,
-            timeout:5000,
+            timeout:50000,
             success:function(result){
                 if (result.error) {
                     alert(result.message);

+ 39 - 1
web/maintain/std_glj_lib/js/global.js

@@ -40,4 +40,42 @@ $(function(){
         $(this).tooltip('show');
     });
     /*工具提示*/
-});
+});
+/**
+ * 设置本地缓存
+ *
+ * @param {String} key
+ * @param {String|Number} value
+ * @return {void}
+ */
+function setLocalCache(key, value) {
+    const storage = window.localStorage;
+    if (!storage || key === '' || value === '') {
+        return;
+    }
+
+    storage.setItem(key, value);
+}
+
+/**
+ * 获取本地缓存
+ *
+ * @param {String} key
+ * @return {String}
+ */
+function getLocalCache(key) {
+    const storage = window.localStorage;
+    if (!storage || key === '') {
+        return null;
+    }
+
+    return storage.getItem(key);
+}
+
+function removeLocalCache(key) {
+    const storage = window.localStorage;
+    if (!storage || key === '') {
+        return null;
+    }
+    return storage.removeItem(key);
+}

+ 40 - 0
web/users/js/compilation.js

@@ -5,6 +5,19 @@
  * @date 2017/7/28
  * @version
  */
+
+const delayTime = 500;
+let keyupTime;
+function delayKeyup(callback) {
+    let nowTime = Date.now();
+    keyupTime = nowTime;
+    setTimeout(function () {
+        if (nowTime - keyupTime == 0 && callback) {
+            callback();
+        }
+    }, delayTime);
+}
+
 $(document).ready(function() {
     let isAdding = false;
     let model = '';
@@ -281,6 +294,33 @@ $(document).ready(function() {
         });
     });
 
+    //例题建设项目ID, 用英文字符;分隔建设项目ID
+    $('#example').keyup(function () {
+        let exampleVal = $(this).val();
+        let tempExample = exampleVal.split(/[;,;]/g),
+            example = [];
+        for (let te of tempExample) {
+            let intTe = parseInt(te);
+            if (!isNaN(intTe)) {
+                example.push(intTe);
+            }
+        }
+        example = Array.from(new Set(example));
+        delayKeyup(function () {
+            $.ajax({
+                url: '/compilation/setExample',
+                type: 'post',
+                dataType: "json",
+                data: {id: id, example: example},
+                success: function(response) {
+                    if (response.err !== 0) {
+                        alert('更改失败');
+                    }
+                }
+            });
+        });
+    });
+
     // 计价规则启用/禁止
     $(".enable").click(function() {
         let goingChangeStatus = switchChange($(this));

+ 1 - 0
web/users/js/login.js

@@ -16,6 +16,7 @@ let rules = {
     }
 };
 $(document).ready(function() {
+    console.log($('#password').val());
     $("#login-form").validate({
         rules: rules,
         errorPlacement: function(error, element) {

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

@@ -100,6 +100,7 @@
             <table class="table">
                 <tr><td><p>软件版本介绍</p><textarea id="description" class="form-control" placeholder="请简要描述改版本"><%= selectedCompilation.description%></textarea></td></tr>
                 <tr><td><span>重写路径:</span><input class="form-control" type="text" id="overWriteUrl" value="<%= selectedCompilation.overWriteUrl%>"></td></tr>
+                <tr><td><span>例题建设项目ID:</span><input class="form-control" type="text" id="example" value="<%= selectedCompilation.example%>"></td></tr>
                 <tr><td><p>显示办事处销售信息</p>
                     <select class="form-control" style="width:200px" id="category-select">
                         <% categoryList.forEach(function(category) { %>

+ 2 - 2
web/users/views/login/index.html

@@ -27,13 +27,13 @@
                 <div class="form-group">
                     <div class="input-group">
                         <div class="input-group-addon"><i class="glyphicon glyphicon-user"></i></div>
-                        <input  class="form-control input-lg" placeholder="输入账号" name="username" id="username" value="admin">
+                        <input  class="form-control input-lg" placeholder="输入账号" name="username" id="username" value="">
                     </div>
                 </div>
                 <div class="form-group">
                     <div class="input-group">
                         <div class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></div>
-                        <input type="password" class="form-control input-lg"  placeholder="输入密码" id="password" name="password" value="">
+                        <input type="password" class="form-control input-lg"  placeholder="输入密码" autocomplete="new-password" id="password" name="password" value="">
                     </div>
                 </div>
                 <a class="btn btn-primary btn-lg btn-block" href="javascript:void(0);" id="login">登录</a>

+ 1 - 1
web/users/views/manager/index.html

@@ -66,7 +66,7 @@
                     <label>权限</label>
                     <div class="checkbox">
                         <label>
-                            <input type="checkbox" name="permission[]" data-permission="manager"> 用户管理
+                            <input type="checkbox" name="permission[]" data-permission="user"> 用户管理
                         </label>&nbsp;
                         <label>
                             <input type="checkbox" name="permission[]" data-permission="notify"> 通知管理