|  | @@ -45,7 +45,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              return recurCompare(aArr, bArr, 0);
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +    let curCompilationID = '';
 | 
	
		
			
				|  |  |      const locked = lockUtil.getLocked();
 | 
	
		
			
				|  |  |      let moduleName = 'stdBillsGuidance';
 | 
	
		
			
				|  |  |      //上下拖动的拖动条高度
 | 
	
	
		
			
				|  | @@ -186,7 +186,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              },
 | 
	
		
			
				|  |  |              {
 | 
	
		
			
				|  |  | -                width: 40,
 | 
	
		
			
				|  |  | +                width: 30,
 | 
	
		
			
				|  |  |                  readOnly: true,
 | 
	
		
			
				|  |  |                  head: {
 | 
	
		
			
				|  |  |                      titleNames: ["必填"],
 | 
	
	
		
			
				|  | @@ -202,13 +202,91 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |                      hAlign: 1,
 | 
	
		
			
				|  |  |                      font: "Arial"
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                width: 30,
 | 
	
		
			
				|  |  | +                readOnly: true,
 | 
	
		
			
				|  |  | +                head: {
 | 
	
		
			
				|  |  | +                    titleNames: ["材料"],
 | 
	
		
			
				|  |  | +                    spanCols: [1],
 | 
	
		
			
				|  |  | +                    spanRows: [1],
 | 
	
		
			
				|  |  | +                    vAlign: [1],
 | 
	
		
			
				|  |  | +                    hAlign: [1],
 | 
	
		
			
				|  |  | +                    font: ["Arial"]
 | 
	
		
			
				|  |  | +                },
 | 
	
		
			
				|  |  | +                data: {
 | 
	
		
			
				|  |  | +                    field: "isMaterial",
 | 
	
		
			
				|  |  | +                    vAlign: 1,
 | 
	
		
			
				|  |  | +                    hAlign: 1,
 | 
	
		
			
				|  |  | +                    font: "Arial"
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                width: 30,
 | 
	
		
			
				|  |  | +                readOnly: true,
 | 
	
		
			
				|  |  | +                head: {
 | 
	
		
			
				|  |  | +                    titleNames: ["默认"],
 | 
	
		
			
				|  |  | +                    spanCols: [1],
 | 
	
		
			
				|  |  | +                    spanRows: [1],
 | 
	
		
			
				|  |  | +                    vAlign: [1],
 | 
	
		
			
				|  |  | +                    hAlign: [1],
 | 
	
		
			
				|  |  | +                    font: ["Arial"]
 | 
	
		
			
				|  |  | +                },
 | 
	
		
			
				|  |  | +                data: {
 | 
	
		
			
				|  |  | +                    field: "isDefaultOption",
 | 
	
		
			
				|  |  | +                    vAlign: 1,
 | 
	
		
			
				|  |  | +                    hAlign: 1,
 | 
	
		
			
				|  |  | +                    font: "Arial"
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                width: 40,
 | 
	
		
			
				|  |  | +                readOnly: locked,
 | 
	
		
			
				|  |  | +                head: {
 | 
	
		
			
				|  |  | +                    titleNames: ["单位"],
 | 
	
		
			
				|  |  | +                    spanCols: [1],
 | 
	
		
			
				|  |  | +                    spanRows: [1],
 | 
	
		
			
				|  |  | +                    vAlign: [1],
 | 
	
		
			
				|  |  | +                    hAlign: [1],
 | 
	
		
			
				|  |  | +                    font: ["Arial"]
 | 
	
		
			
				|  |  | +                },
 | 
	
		
			
				|  |  | +                data: {
 | 
	
		
			
				|  |  | +                    field: "unit",
 | 
	
		
			
				|  |  | +                    vAlign: 1,
 | 
	
		
			
				|  |  | +                    hAlign: 1,
 | 
	
		
			
				|  |  | +                    font: "Arial",
 | 
	
		
			
				|  |  | +                    formatter: "@"
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                width: 80,
 | 
	
		
			
				|  |  | +                readOnly: locked,
 | 
	
		
			
				|  |  | +                head: {
 | 
	
		
			
				|  |  | +                    titleNames: ["区间"],
 | 
	
		
			
				|  |  | +                    spanCols: [1],
 | 
	
		
			
				|  |  | +                    spanRows: [1],
 | 
	
		
			
				|  |  | +                    vAlign: [1],
 | 
	
		
			
				|  |  | +                    hAlign: [1],
 | 
	
		
			
				|  |  | +                    font: ["Arial"]
 | 
	
		
			
				|  |  | +                },
 | 
	
		
			
				|  |  | +                data: {
 | 
	
		
			
				|  |  | +                    field: "interval",
 | 
	
		
			
				|  |  | +                    vAlign: 1,
 | 
	
		
			
				|  |  | +                    hAlign: 1,
 | 
	
		
			
				|  |  | +                    font: "Arial",
 | 
	
		
			
				|  |  | +                    formatter: "@"
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  |          ]
 | 
	
		
			
				|  |  |          },
 | 
	
		
			
				|  |  |          headers: [
 | 
	
		
			
				|  |  |              {name: '项目指引', dataCode: 'name', width: 400, vAlign: 'center', hAlign: 'left', formatter: '@'},
 | 
	
		
			
				|  |  |              {name: '输出特征', dataCode: 'outputItemCharacter', width: 40, vAlign: 'center', hAlign: 'center'},
 | 
	
		
			
				|  |  | -            {name: '必填', dataCode: 'required', width: 40, vAlign: 'center', hAlign: 'center'},
 | 
	
		
			
				|  |  | +            {name: '必填', dataCode: 'required', width: 30, vAlign: 'center', hAlign: 'center'},
 | 
	
		
			
				|  |  | +            {name: '材料', dataCode: 'isMaterial', width: 30, vAlign: 'center', hAlign: 'center'},
 | 
	
		
			
				|  |  | +            {name: '默认', dataCode: 'isDefaultOption', width: 30, vAlign: 'center', hAlign: 'center'},
 | 
	
		
			
				|  |  | +            {name: '单位', dataCode: 'unit', width: 40, vAlign: 'center', hAlign: 'center', formatter: '@'},
 | 
	
		
			
				|  |  | +            {name: '区间', dataCode: 'interval', width: 80, vAlign: 'center', hAlign: 'center', formatter: '@'},
 | 
	
		
			
				|  |  |          ],
 | 
	
		
			
				|  |  |          events: {
 | 
	
		
			
				|  |  |              SelectionChanged: function (sender, info) {
 | 
	
	
		
			
				|  | @@ -225,6 +303,9 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              },
 | 
	
		
			
				|  |  |              CellDoubleClick: function(sender, args) {
 | 
	
		
			
				|  |  |                  locateAtRation(args.row);
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            EnterCell: function(sender, args) {
 | 
	
		
			
				|  |  | +                console.log(args.row);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      };
 | 
	
	
		
			
				|  | @@ -313,6 +394,144 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /* 清单材料表 */
 | 
	
		
			
				|  |  | +    const materialHeaders =  [
 | 
	
		
			
				|  |  | +        {name: '材料编码', dataCode: 'code', width: 90, vAlign: 'center', hAlign: 'left', formatter: '@'},
 | 
	
		
			
				|  |  | +        {name: '材料名称', dataCode: 'name', width: 150, vAlign: 'center', hAlign: 'left', formatter: '@'},
 | 
	
		
			
				|  |  | +        {name: '规格', dataCode: 'specs', width: 130, vAlign: 'center', hAlign: 'left', formatter: '@'}
 | 
	
		
			
				|  |  | +    ];
 | 
	
		
			
				|  |  | +    const billMaterial = {
 | 
	
		
			
				|  |  | +        dom: $('#bill-material-spread'),
 | 
	
		
			
				|  |  | +        workBook: null,
 | 
	
		
			
				|  |  | +        cache: [],
 | 
	
		
			
				|  |  | +        headers: materialHeaders,
 | 
	
		
			
				|  |  | +        events: {
 | 
	
		
			
				|  |  | +            EditEnded: function (sender, args) {
 | 
	
		
			
				|  |  | +                editMaterials(args.sheet, [{row: args.row, col: args.col}]);
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            RangeChanged: function (sender, args) {
 | 
	
		
			
				|  |  | +                editMaterials(args.sheet, args.changedCells);
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* 清单辅助材料录入表 */
 | 
	
		
			
				|  |  | +    const billMaterialHelper = {
 | 
	
		
			
				|  |  | +        dom: $('#bill-material-helper-spread'),
 | 
	
		
			
				|  |  | +        workBook: null,
 | 
	
		
			
				|  |  | +        cache: [],
 | 
	
		
			
				|  |  | +        headers: materialHeaders,
 | 
	
		
			
				|  |  | +        events: {
 | 
	
		
			
				|  |  | +            // 双击添加到清单材料表
 | 
	
		
			
				|  |  | +            CellDoubleClick: function (sender, args) {
 | 
	
		
			
				|  |  | +                // 模拟清单材料表编辑(共用同一个接口)
 | 
	
		
			
				|  |  | +                if (!billMaterialHelper.cache[args.row]) {
 | 
	
		
			
				|  |  | +                    return;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                const code = billMaterialHelper.cache[args.row].code;
 | 
	
		
			
				|  |  | +                const row = billMaterial.cache.length;
 | 
	
		
			
				|  |  | +                const targetSheet = billMaterial.workBook.getSheet(0);
 | 
	
		
			
				|  |  | +                targetSheet.setValue(row, 0, code);
 | 
	
		
			
				|  |  | +                const changedCells = [{ row, col: 0 }];
 | 
	
		
			
				|  |  | +                editMaterials(billMaterial.workBook.getSheet(0), changedCells);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 显示清单材料数据
 | 
	
		
			
				|  |  | +    function showBillMaterialData(sheet, headers, datas, emptyRow = 0){
 | 
	
		
			
				|  |  | +        let fuc = function () {
 | 
	
		
			
				|  |  | +            const rowCount = datas.length + emptyRow;
 | 
	
		
			
				|  |  | +            sheet.setRowCount(rowCount);
 | 
	
		
			
				|  |  | +            for(let col = 0, cLen = headers.length; col < cLen; col++){
 | 
	
		
			
				|  |  | +                for(let row = 0; row < rowCount; row++){
 | 
	
		
			
				|  |  | +                    if (datas[row]) {
 | 
	
		
			
				|  |  | +                        sheet.setValue(row, col, datas[row][headers[col]['dataCode']] || '');
 | 
	
		
			
				|  |  | +                    } else {
 | 
	
		
			
				|  |  | +                        sheet.setValue(row, col, '');
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        renderSheetFunc(sheet, fuc);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 获取清单材料数据
 | 
	
		
			
				|  |  | +    async function getBillMaterials() {
 | 
	
		
			
				|  |  | +        if (!bills.tree.selected) {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        billMaterial.cache = [];
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | +            const { billMaterials, allGljList } = await ajaxPost('/billsGuidance/api/getBillMaterials', { libID, billID: bills.tree.selected.data.ID });
 | 
	
		
			
				|  |  | +            billMaterial.cache = billMaterials;
 | 
	
		
			
				|  |  | +            console.log(allGljList);
 | 
	
		
			
				|  |  | +            sortByCode(billMaterial.cache);
 | 
	
		
			
				|  |  | +            billMaterialHelper.cache = allGljList
 | 
	
		
			
				|  |  | +            sortByCode(billMaterialHelper.cache);
 | 
	
		
			
				|  |  | +        } catch (error) {
 | 
	
		
			
				|  |  | +            $('#alert-info').text(error.message);
 | 
	
		
			
				|  |  | +            $('#alert').modal('show');
 | 
	
		
			
				|  |  | +        } finally {
 | 
	
		
			
				|  |  | +            showBillMaterialData(billMaterial.workBook.getSheet(0), billMaterial.headers, billMaterial.cache, 30);
 | 
	
		
			
				|  |  | +            billMaterial.workBook.getSheet(0).showRow(0, GC.Spread.Sheets.VerticalPosition.top);
 | 
	
		
			
				|  |  | +            showBillMaterialData(billMaterialHelper.workBook.getSheet(0), billMaterialHelper.headers, billMaterialHelper.cache);
 | 
	
		
			
				|  |  | +            billMaterialHelper.workBook.getSheet(0).showRow(0, GC.Spread.Sheets.VerticalPosition.top);
 | 
	
		
			
				|  |  | +            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    function getText(sheet, row, col) {
 | 
	
		
			
				|  |  | +        let text = sheet.getValue(row, col);
 | 
	
		
			
				|  |  | +        text = text ? text.toString().trim() : '';
 | 
	
		
			
				|  |  | +        return text;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 编辑材料表
 | 
	
		
			
				|  |  | +    async function editMaterials(sheet, cells){
 | 
	
		
			
				|  |  | +        let isChanged = false;
 | 
	
		
			
				|  |  | +        for(let cell of cells){
 | 
	
		
			
				|  |  | +            const itemCode = billMaterial.cache[cell.row] && billMaterial.cache[cell.row].code || '';
 | 
	
		
			
				|  |  | +            if (itemCode !== getText(sheet, cell.row, 0)) {
 | 
	
		
			
				|  |  | +                isChanged = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (!isChanged) {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        let gljCodes = new Set();
 | 
	
		
			
				|  |  | +        const count = sheet.getRowCount();
 | 
	
		
			
				|  |  | +        for (let row = 0; row < count; row++) {
 | 
	
		
			
				|  |  | +            const code = getText(sheet, row, 0);
 | 
	
		
			
				|  |  | +            if (code) {
 | 
	
		
			
				|  |  | +                gljCodes.add(code);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 提交数据
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            $.bootstrapLoading.start();
 | 
	
		
			
				|  |  | +            billMaterial.cache = await ajaxPost('/billsGuidance/api/editBillMaterials', { libID, billID: bills.tree.selected.data.ID, gljCodes: [...gljCodes], compilationID: curCompilationID }, undefined, true);
 | 
	
		
			
				|  |  | +            sortByCode(billMaterial.cache);
 | 
	
		
			
				|  |  | +        } catch (error) {
 | 
	
		
			
				|  |  | +            $('#alert-info').html(error);
 | 
	
		
			
				|  |  | +            $('#alert').modal('show');
 | 
	
		
			
				|  |  | +        } finally {
 | 
	
		
			
				|  |  | +            showBillMaterialData(billMaterial.workBook.getSheet(0), billMaterial.headers, billMaterial.cache, 30);
 | 
	
		
			
				|  |  | +            $.bootstrapLoading.end();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 是否为工序行
 | 
	
		
			
				|  |  | +    function isProcessNode(node) {
 | 
	
		
			
				|  |  | +        return node && node.depth() % 2 === 0 && _isDef(node.data.type) && node.data.type === itemType.job
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 是否是选项行
 | 
	
		
			
				|  |  | +    function isOptionNode(node) {
 | 
	
		
			
				|  |  | +        return node && node.depth() % 2 === 1 && _isDef(node.data.type) && node.data.type === itemType.job
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      //渲染时方法,停止渲染
 | 
	
		
			
				|  |  |      //@param {Object}sheet {Function}func @return {void}
 | 
	
		
			
				|  |  |      function renderSheetFunc(sheet, func){
 | 
	
	
		
			
				|  | @@ -382,8 +601,18 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |                  sheet.getRange(-1, 1, -1, -1).locked(true);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |              else if(module === guideItem){
 | 
	
		
			
				|  |  | +                sheet.name('stdBillsGuidance_guidance');
 | 
	
		
			
				|  |  |                  sheetCommonObj.bindEscKey(module.workBook, [{sheet: sheet, editStarting: null, editEnded: module.events.EditEnded}]);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +            else if (module === billMaterial) {
 | 
	
		
			
				|  |  | +                sheet.options.isProtected = true;
 | 
	
		
			
				|  |  | +                sheet.getRange(-1, 0, -1, 1).locked(locked);
 | 
	
		
			
				|  |  | +                sheet.getRange(-1, 1, -1, -1).locked(true);
 | 
	
		
			
				|  |  | +                sheet.getRange(-1, 2, -1, -1).locked(true);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else if (module === billMaterialHelper) {
 | 
	
		
			
				|  |  | +                sheet.options.isProtected = true;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  |              setOptions(module.workBook, options);
 | 
	
		
			
				|  |  |              buildHeader(module.workBook.getActiveSheet(), module.headers);
 | 
	
		
			
				|  |  |              bindEvent(module.workBook, module.events);
 | 
	
	
		
			
				|  | @@ -423,6 +652,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          cleanData(guideSheet, guideItem.headers, -1);
 | 
	
		
			
				|  |  |          let node = bills.tree.items[row];
 | 
	
		
			
				|  |  |          if(!node){
 | 
	
		
			
				|  |  | +            $('#editMaterial').addClass('disabled');
 | 
	
		
			
				|  |  |              return;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          const billSheet = bills.workBook.getActiveSheet();
 | 
	
	
		
			
				|  | @@ -432,13 +662,14 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              setBgColor(billSheet, oldSel.row, orgNode && orgNode.isSearch ? searchBgColor : 'white');
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          bills.tree.selected = node;
 | 
	
		
			
				|  |  | +        $('#editMaterial').removeClass('disabled');
 | 
	
		
			
				|  |  |          //显示备注
 | 
	
		
			
				|  |  |          $('.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);
 | 
	
		
			
				|  |  |                  setNodesExpandState(node.guidance.tree.items, curExpandState);
 | 
	
		
			
				|  |  | -                showCheckBox(guideSheet, node.guidance.tree.items);
 | 
	
		
			
				|  |  | +                setProcessNodes(guideSheet, node.guidance.tree.items);
 | 
	
		
			
				|  |  |                  renderSheetFunc(guideSheet, function () {
 | 
	
		
			
				|  |  |                      TREE_SHEET_HELPER.refreshNodesVisible(node.guidance.tree.roots, guideSheet, true);
 | 
	
		
			
				|  |  |                  });
 | 
	
	
		
			
				|  | @@ -450,36 +681,75 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          } else{
 | 
	
		
			
				|  |  |              setNodesExpandState(node.guidance.tree.items, curExpandState);
 | 
	
		
			
				|  |  |              node.guidance.controller.showTreeData();
 | 
	
		
			
				|  |  | -            showCheckBox(guideSheet, node.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setProcessNodes(guideSheet, node.guidance.tree.items);
 | 
	
		
			
				|  |  |              //设置底色
 | 
	
		
			
				|  |  |              setNodesColor(guideSheet, node.guidance.tree.items);
 | 
	
		
			
				|  |  |              //项目指引初始焦点
 | 
	
		
			
				|  |  |              guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      function showCheckBox(sheet, nodes) {
 | 
	
		
			
				|  |  |          // const checkBoxType = locked ? sheetCommonObj.getReadOnlyCheckBox() : sheetCommonObj.getCheckBox();
 | 
	
		
			
				|  |  |          const checkBoxType = new GC.Spread.Sheets.CellTypes.CheckBox();
 | 
	
		
			
				|  |  |          const baseType = new GC.Spread.Sheets.CellTypes.Base();
 | 
	
		
			
				|  |  | +        const outputItemCol = guideItem.headers.findIndex(item => item.dataCode === 'outputItemCharacter');
 | 
	
		
			
				|  |  | +        const requiredCol = guideItem.headers.findIndex(item => item.dataCode === 'required');
 | 
	
		
			
				|  |  | +        const materialCol = guideItem.headers.findIndex(item => item.dataCode === 'isMaterial');
 | 
	
		
			
				|  |  | +        const defaultOption = guideItem.headers.findIndex(item => item.dataCode === 'isDefaultOption');
 | 
	
		
			
				|  |  |          renderSheetFunc(sheet, function () {
 | 
	
		
			
				|  |  |              nodes.forEach(node => {
 | 
	
		
			
				|  |  |                  const row = node.serialNo();
 | 
	
		
			
				|  |  | -                if (node.depth() % 2 === 0 && _isDef(node.data.type) && node.data.type === itemType.job) {
 | 
	
		
			
				|  |  | -                    sheet.setCellType(row, 1, checkBoxType);
 | 
	
		
			
				|  |  | -                    sheet.setCellType(row, 2, checkBoxType);
 | 
	
		
			
				|  |  | -                    sheet.setValue(row, 1, node.data.outputItemCharacter || false);
 | 
	
		
			
				|  |  | -                    sheet.setValue(row, 2, node.data.required || false);
 | 
	
		
			
				|  |  | +                if (isOptionNode(node)) {
 | 
	
		
			
				|  |  | +                    sheet.setCellType(row, defaultOption, checkBoxType);
 | 
	
		
			
				|  |  | +                    sheet.setValue(row, defaultOption, node.data.isDefaultOption || false);
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    sheet.setCellType(row, defaultOption, baseType);
 | 
	
		
			
				|  |  | +                    sheet.setValue(row, defaultOption, '');
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                if (isProcessNode(node)) {
 | 
	
		
			
				|  |  | +                    sheet.setCellType(row, outputItemCol, checkBoxType);
 | 
	
		
			
				|  |  | +                    sheet.setCellType(row, requiredCol, checkBoxType);
 | 
	
		
			
				|  |  | +                    sheet.setCellType(row, materialCol, checkBoxType);
 | 
	
		
			
				|  |  | +                    sheet.setValue(row, outputItemCol, node.data.outputItemCharacter || false);
 | 
	
		
			
				|  |  | +                    sheet.setValue(row, requiredCol, node.data.required || false);
 | 
	
		
			
				|  |  | +                    sheet.setValue(row, materialCol, node.data.isMaterial || false);
 | 
	
		
			
				|  |  |                  } else {
 | 
	
		
			
				|  |  | -                    sheet.setCellType(row, 1, baseType);
 | 
	
		
			
				|  |  | -                    sheet.setCellType(row, 2, baseType);
 | 
	
		
			
				|  |  | -                    sheet.setValue(row, 1, '');
 | 
	
		
			
				|  |  | -                    sheet.setValue(row, 2, '');
 | 
	
		
			
				|  |  | +                    sheet.setCellType(row, outputItemCol, baseType);
 | 
	
		
			
				|  |  | +                    sheet.setCellType(row, requiredCol, baseType);
 | 
	
		
			
				|  |  | +                    sheet.setCellType(row, materialCol, baseType);
 | 
	
		
			
				|  |  | +                    sheet.setValue(row, outputItemCol, '');
 | 
	
		
			
				|  |  | +                    sheet.setValue(row, requiredCol, '');
 | 
	
		
			
				|  |  | +                    sheet.setValue(row, materialCol, '');
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              })
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    function setReadOnly(sheet, nodes) {
 | 
	
		
			
				|  |  | +        if (locked) {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 单位仅特征/工序行可输入
 | 
	
		
			
				|  |  | +        // 区间仅仅选项行可输入
 | 
	
		
			
				|  |  | +        const unitCol = guideItem.headers.findIndex(item => item.dataCode === 'unit');
 | 
	
		
			
				|  |  | +        const intervalCol = guideItem.headers.findIndex(item => item.dataCode === 'interval');
 | 
	
		
			
				|  |  | +        renderSheetFunc(sheet, function () {
 | 
	
		
			
				|  |  | +            nodes.forEach(node => {
 | 
	
		
			
				|  |  | +                const row = node.serialNo();
 | 
	
		
			
				|  |  | +                sheet.getCell(row, unitCol).locked(!isProcessNode(node));
 | 
	
		
			
				|  |  | +                sheet.getCell(row, intervalCol).locked(!isOptionNode(node));
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 设置选项行相关
 | 
	
		
			
				|  |  | +    function setProcessNodes(sheet, nodes) {
 | 
	
		
			
				|  |  | +        showCheckBox(sheet, nodes);
 | 
	
		
			
				|  |  | +        setReadOnly(sheet, nodes);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      //设置项目节点展开收起状态:展开全部、收起定额
 | 
	
		
			
				|  |  |      //@param {Array}nodes(当前清单下的所有项目指引节点) {Number}expandState(展开全部1或收起定额0).
 | 
	
		
			
				|  |  |      function setNodesExpandState(nodes, expandState) {
 | 
	
	
		
			
				|  | @@ -524,8 +794,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |      function setNodesColor(sheet, nodes) {
 | 
	
		
			
				|  |  |          renderSheetFunc(sheet, function () {
 | 
	
		
			
				|  |  |              for(let node of nodes){
 | 
	
		
			
				|  |  | -                const nDepth = node.depth();
 | 
	
		
			
				|  |  | -                const color = nDepth % 2 == 0 && _isDef(node.data.type) && node.data.type === itemType.job ? selectedBgColor : 'White';
 | 
	
		
			
				|  |  | +                const color = isProcessNode(node) ? selectedBgColor : 'White';
 | 
	
		
			
				|  |  |                  setBgColor(sheet, node.serialNo(), color);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          });
 | 
	
	
		
			
				|  | @@ -574,6 +843,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          //全部设为无效
 | 
	
		
			
				|  |  |          $('.tools-btn').children().addClass('disabled');
 | 
	
		
			
				|  |  | +        $('#generate-class').removeClass('disabled');
 | 
	
		
			
				|  |  |          $('#insertRation').addClass('disabled');
 | 
	
		
			
				|  |  |          $('#insertAll').addClass('disabled');
 | 
	
		
			
				|  |  |          $('.main-bottom-content').find('textarea').attr('readonly', true);
 | 
	
	
		
			
				|  | @@ -620,7 +890,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              $('#insertAll').removeClass('disabled');
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          //备注,奇数节点可用
 | 
	
		
			
				|  |  | -        if(node && (node.depth() + 1) % 2 === 1 && node.data.type !== itemType.ration){
 | 
	
		
			
				|  |  | +        if(isProcessNode(node)){
 | 
	
		
			
				|  |  |              $('.main-bottom-content').find('textarea').attr('readonly', false);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -718,8 +988,9 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |                                      .css("border", "1px #C0C0C0 solid")
 | 
	
		
			
				|  |  |                                      .css("box-shadow", "1px 2px 5px rgba(0,0,0,0.4)")
 | 
	
		
			
				|  |  |                                      .css("font", "0.9rem Calibri")
 | 
	
		
			
				|  |  | -                                    .css("background", "white")
 | 
	
		
			
				|  |  |                                      .css("padding", 5)
 | 
	
		
			
				|  |  | +                                    .css("background", '#303133')
 | 
	
		
			
				|  |  | +                                    .css("color", '#fff')
 | 
	
		
			
				|  |  |                                      .attr("id", 'autoTip1');
 | 
	
		
			
				|  |  |                                  $(div).hide();
 | 
	
		
			
				|  |  |                                  document.body.insertBefore(div, null);
 | 
	
	
		
			
				|  | @@ -983,6 +1254,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function (rstData) {
 | 
	
		
			
				|  |  |              billsLibId = rstData.guidanceLib.billsLibId;
 | 
	
		
			
				|  |  |              initRationLibs(rstData.guidanceLib.compilationId);
 | 
	
		
			
				|  |  | +            curCompilationID = rstData.guidanceLib.compilationId;
 | 
	
		
			
				|  |  |              bills.cache = rstData.bills;
 | 
	
		
			
				|  |  |              initLibName(rstData.guidanceLib.name);
 | 
	
		
			
				|  |  |              /*initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, bills.cache);
 | 
	
	
		
			
				|  | @@ -1067,16 +1339,16 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          for(let cell of cells){
 | 
	
		
			
				|  |  |              const field = guideItem.headers[cell.col].dataCode;
 | 
	
		
			
				|  |  |              let node = bills.tree.selected.guidance.tree.items[cell.row];
 | 
	
		
			
				|  |  | -            if (field === 'name') {
 | 
	
		
			
				|  |  | +            if (field === 'name' || field === 'unit' || field === 'interval') {
 | 
	
		
			
				|  |  |                  let text = sheet.getValue(cell.row, cell.col);
 | 
	
		
			
				|  |  |                  text = text ? text.toString() : '';
 | 
	
		
			
				|  |  |                  text = text.replace(deESC, '');
 | 
	
		
			
				|  |  |                  sheet.setValue(cell.row, cell.col, text);
 | 
	
		
			
				|  |  | -                if(node.data.name != text){
 | 
	
		
			
				|  |  | +                if(node.data[field] != text){
 | 
	
		
			
				|  |  |                      syncDatas.push({node: node, text: text, field, cell});
 | 
	
		
			
				|  |  | -                    updateDatas.push({updateType: updateType.update, findData: {ID: node.getID()}, updateData: {name: text}});
 | 
	
		
			
				|  |  | +                    updateDatas.push({updateType: updateType.update, findData: {ID: node.getID()}, updateData: {[field]: text}});
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  | -            } else if (field === 'outputItemCharacter' || field === 'required') {
 | 
	
		
			
				|  |  | +            } else if (field === 'outputItemCharacter' || field === 'required' || field === 'isMaterial' || field === 'isDefaultOption') {
 | 
	
		
			
				|  |  |                  const val = !sheet.getValue(cell.row, cell.col);
 | 
	
		
			
				|  |  |                  sheet.setValue(cell.row, cell.col, val);
 | 
	
		
			
				|  |  |                  syncDatas.push({node: node, text: val, field, cell });
 | 
	
	
		
			
				|  | @@ -1111,7 +1383,8 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          for(let i = 0; i < datas.length; i++){
 | 
	
		
			
				|  |  |              let newNodeData = {
 | 
	
		
			
				|  |  |                  libID: libID, ID: uuid.v1(), ParentID: selected ? selected.getParentID() : -1, NextSiblingID: selected ? selected.getNextSiblingID() : -1,
 | 
	
		
			
				|  |  | -                billsID: bills.tree.selected.getID()
 | 
	
		
			
				|  |  | +                billsID: bills.tree.selected.getID(),
 | 
	
		
			
				|  |  | +                outputItemCharacter: true,
 | 
	
		
			
				|  |  |              };
 | 
	
		
			
				|  |  |              //定额类型插入当前工作内容焦点行,
 | 
	
		
			
				|  |  |              if(selected && ((selected.data.type === itemType.job && datas[i].type === itemType.ration) || tobeChild)){
 | 
	
	
		
			
				|  | @@ -1136,6 +1409,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              updateDatas.push({updateType: updateType.create, updateData: newDataIndex[i]});
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          updateGuideItems(updateDatas, function () {
 | 
	
		
			
				|  |  | +            const outputItemCol = guideItem.headers.findIndex(item => item.dataCode === 'outputItemCharacter');
 | 
	
		
			
				|  |  |              for(let updateData of updateDatas){
 | 
	
		
			
				|  |  |                  if(updateData.updateType === updateType.create){
 | 
	
		
			
				|  |  |                      let newNode = controller.insertByIDS(updateData.updateData.ID, updateData.updateData.ParentID, updateData.updateData.NextSiblingID);
 | 
	
	
		
			
				|  | @@ -1144,9 +1418,9 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |                      const row = newNode.serialNo();
 | 
	
		
			
				|  |  |                      sheet.setValue(row, 0, newNode.data.name);
 | 
	
		
			
				|  |  |                      if (newNode.data.outputItemCharacter !== undefined) {
 | 
	
		
			
				|  |  | -                        sheet.setValue(row, 1, newNode.data.outputItemCharacter);
 | 
	
		
			
				|  |  | +                        sheet.setValue(row, outputItemCol, newNode.data.outputItemCharacter);
 | 
	
		
			
				|  |  |                      }
 | 
	
		
			
				|  |  | -                    showCheckBox(sheet, [newNode]);
 | 
	
		
			
				|  |  | +                    setProcessNodes(sheet, [newNode]);
 | 
	
		
			
				|  |  |                      refreshBtn(newNode);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
	
		
			
				|  | @@ -1245,7 +1519,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              guideItemInitSel(sheet.getActiveRowIndex());
 | 
	
		
			
				|  |  |              refreshBtn(bills.tree.selected.guidance.tree.selected);
 | 
	
		
			
				|  |  |              setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | -            showCheckBox(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setProcessNodes(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  |              if (bills.tree.selected.data.hasGuide && !bills.tree.selected.guidance.tree.items.length) {
 | 
	
		
			
				|  |  |                  bills.tree.selected.data.hasGuide = false;
 | 
	
		
			
				|  |  |                  setBillsForeColor([bills.tree.selected]);
 | 
	
	
		
			
				|  | @@ -1265,7 +1539,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          updateDatas.push({updateType: updateType.update, findData: {ID: selected.getParentID()}, updateData: {NextSiblingID: selected.getID()}});
 | 
	
		
			
				|  |  |          //更新选中节点
 | 
	
		
			
				|  |  |          updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()},
 | 
	
		
			
				|  |  | -            updateData: {ParentID: selected.parent.getParentID(), NextSiblingID: selected.parent.getNextSiblingID()}});
 | 
	
		
			
				|  |  | +            updateData: {ParentID: selected.parent.getParentID(), NextSiblingID: selected.parent.getNextSiblingID(), unit: '', interval: ''}});
 | 
	
		
			
				|  |  |          if(selected.nextSibling && selected.children.length > 0){
 | 
	
		
			
				|  |  |              //更新选中节点最末子节点
 | 
	
		
			
				|  |  |              let lastChild = selected.children[selected.children.length - 1];
 | 
	
	
		
			
				|  | @@ -1283,9 +1557,14 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          updateGuideItems(updateDatas, function () {
 | 
	
		
			
				|  |  |              controller.upLevel();
 | 
	
		
			
				|  |  | +            const sheet = guideItem.workBook.getActiveSheet();
 | 
	
		
			
				|  |  |              refreshBtn(bills.tree.selected.guidance.tree.selected);
 | 
	
		
			
				|  |  | -            setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | -            showCheckBox(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setNodesColor(sheet, bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setProcessNodes(sheet, bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            const unitCol = guideItem.headers.findIndex(item => item.dataCode === 'unit');
 | 
	
		
			
				|  |  | +            const intervalCol = guideItem.headers.findIndex(item => item.dataCode === 'interval');
 | 
	
		
			
				|  |  | +            sheet.setValue(selected.serialNo(), unitCol, '');
 | 
	
		
			
				|  |  | +            sheet.setValue(selected.serialNo(), intervalCol, '');
 | 
	
		
			
				|  |  |              $.bootstrapLoading.end();
 | 
	
		
			
				|  |  |              guideItem.workBook.focus(true)//31574
 | 
	
		
			
				|  |  |          });
 | 
	
	
		
			
				|  | @@ -1305,12 +1584,17 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              updateDatas.push({updateType: updateType.update, findData: {ID: lastChild.getID()}, updateData: {NextSiblingID: selected.getID()}});
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          //更新选中节点
 | 
	
		
			
				|  |  | -        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {ParentID: selected.preSibling.getID(), NextSiblingID: -1}});
 | 
	
		
			
				|  |  | +        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {ParentID: selected.preSibling.getID(), NextSiblingID: -1, unit: '', interval: ''}});
 | 
	
		
			
				|  |  |          updateGuideItems(updateDatas, function () {
 | 
	
		
			
				|  |  |              controller.downLevel();
 | 
	
		
			
				|  |  | +            const sheet = guideItem.workBook.getActiveSheet();
 | 
	
		
			
				|  |  |              refreshBtn(bills.tree.selected.guidance.tree.selected);
 | 
	
		
			
				|  |  | -            setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | -            showCheckBox(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setNodesColor(sheet, bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setProcessNodes(sheet, bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            const unitCol = guideItem.headers.findIndex(item => item.dataCode === 'unit');
 | 
	
		
			
				|  |  | +            const intervalCol = guideItem.headers.findIndex(item => item.dataCode === 'interval');
 | 
	
		
			
				|  |  | +            sheet.setValue(selected.serialNo(), unitCol, '');
 | 
	
		
			
				|  |  | +            sheet.setValue(selected.serialNo(), intervalCol, '');
 | 
	
		
			
				|  |  |              $.bootstrapLoading.end();
 | 
	
		
			
				|  |  |              guideItem.workBook.focus(true)
 | 
	
		
			
				|  |  |          });
 | 
	
	
		
			
				|  | @@ -1334,7 +1618,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              controller.upMove();
 | 
	
		
			
				|  |  |              refreshBtn(bills.tree.selected.guidance.tree.selected);
 | 
	
		
			
				|  |  |              setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | -            showCheckBox(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setProcessNodes(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  |              $.bootstrapLoading.end();
 | 
	
		
			
				|  |  |              guideItem.workBook.focus(true)
 | 
	
		
			
				|  |  |          });
 | 
	
	
		
			
				|  | @@ -1358,7 +1642,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              controller.downMove();
 | 
	
		
			
				|  |  |              refreshBtn(bills.tree.selected.guidance.tree.selected);
 | 
	
		
			
				|  |  |              setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | -            showCheckBox(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setProcessNodes(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  |              $.bootstrapLoading.end();
 | 
	
		
			
				|  |  |              guideItem.workBook.focus(true)
 | 
	
		
			
				|  |  |          });
 | 
	
	
		
			
				|  | @@ -1572,7 +1856,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |              cleanData(guideItem.workBook.getActiveSheet(), guideItem.headers, -1);
 | 
	
		
			
				|  |  |              itemObj.controller.showTreeData();
 | 
	
		
			
				|  |  |              setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | -            showCheckBox(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            setProcessNodes(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  |          }, function () {
 | 
	
		
			
				|  |  |              $.bootstrapLoading.end();
 | 
	
		
			
				|  |  |          });
 | 
	
	
		
			
				|  | @@ -1752,7 +2036,7 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // 初始化定额右键菜单
 | 
	
		
			
				|  |  | +    // 初始化清单右键菜单
 | 
	
		
			
				|  |  |      function initRationContextMenu() {
 | 
	
		
			
				|  |  |          $.contextMenu({
 | 
	
		
			
				|  |  |              selector: '#rationSpread',
 | 
	
	
		
			
				|  | @@ -1803,6 +2087,53 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    // 初始化定额右键菜单
 | 
	
		
			
				|  |  | +    function initBillsContextMenu() {
 | 
	
		
			
				|  |  | +        $.contextMenu({
 | 
	
		
			
				|  |  | +            selector: '#billsSpread',
 | 
	
		
			
				|  |  | +            build: function($triggerElement, e){
 | 
	
		
			
				|  |  | +                //控制允许右键菜单在哪个位置出现
 | 
	
		
			
				|  |  | +                let sheet = bills.workBook.getActiveSheet();;
 | 
	
		
			
				|  |  | +                let offset = $("#billsSpread").offset(),
 | 
	
		
			
				|  |  | +                    x = e.pageX - offset.left,
 | 
	
		
			
				|  |  | +                    y = e.pageY - offset.top;
 | 
	
		
			
				|  |  | +                let target = sheet.hitTest(x, y);
 | 
	
		
			
				|  |  | +                if(target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){//在表格内
 | 
	
		
			
				|  |  | +                    let sel = sheet.getSelections()[0];
 | 
	
		
			
				|  |  | +                    if(sel && sel.rowCount === 1){
 | 
	
		
			
				|  |  | +                        sheet.setActiveCell(target.row, target.col);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    sel = sheet.getSelections()[0];
 | 
	
		
			
				|  |  | +                    if(sel){
 | 
	
		
			
				|  |  | +                        sel.row =  sel.row === -1 ? 0 : sel.row;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    //右键在多选内则不重设焦点
 | 
	
		
			
				|  |  | +                    if(!sel || sel.rowCount === 1 || !(target.row >= sel.row && target.row <= sel.row + sel.rowCount - 1)){
 | 
	
		
			
				|  |  | +                        sheet.setActiveCell(target.row, target.col);
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    billsInitSel(target.row, { row: bills.tree.selected.serialNo() });
 | 
	
		
			
				|  |  | +                    return {
 | 
	
		
			
				|  |  | +                        callback: function(){},
 | 
	
		
			
				|  |  | +                        items: {
 | 
	
		
			
				|  |  | +                            "replace": {
 | 
	
		
			
				|  |  | +                                name: "配置材料",
 | 
	
		
			
				|  |  | +                                disabled: function () {
 | 
	
		
			
				|  |  | +                                    return !bills.tree.selected;
 | 
	
		
			
				|  |  | +                                },
 | 
	
		
			
				|  |  | +                                icon: "fa-edit",
 | 
	
		
			
				|  |  | +                                callback: function (key, opt) {
 | 
	
		
			
				|  |  | +                                    $('#bill-material-modal').modal('show');
 | 
	
		
			
				|  |  | +                                }},
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                    };
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                else{
 | 
	
		
			
				|  |  | +                    return false;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      //展开至搜索出来点的节点
 | 
	
		
			
				|  |  |      //@param {Array}nodes @return {void}
 | 
	
		
			
				|  |  |      function expandSearchNodes(sheet, nodes, roots){
 | 
	
	
		
			
				|  | @@ -1933,9 +2264,22 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    //初始化个按钮点击
 | 
	
		
			
				|  |  | +    //初始化dom时间
 | 
	
		
			
				|  |  |      //@return {void}
 | 
	
		
			
				|  |  | -    function initBtn(){
 | 
	
		
			
				|  |  | +    function initDomEvents(){
 | 
	
		
			
				|  |  | +        // 清单材料窗口
 | 
	
		
			
				|  |  | +        $("#bill-material-modal").on('hidden.bs.modal', function () {
 | 
	
		
			
				|  |  | +            billMaterial.cache = [];
 | 
	
		
			
				|  |  | +            showBillMaterialData(billMaterial.workBook.getSheet(0), billMaterial.headers, billMaterial.cache, 30);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        $("#bill-material-modal").on('shown.bs.modal', function () {
 | 
	
		
			
				|  |  | +            if (billMaterial.workBook && billMaterialHelper.workBook) {
 | 
	
		
			
				|  |  | +                billMaterialHelper.workBook.refresh();
 | 
	
		
			
				|  |  | +                billMaterial.workBook.refresh();
 | 
	
		
			
				|  |  | +                getBillMaterials();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          $('#insert').click(function () {
 | 
	
		
			
				|  |  |              insert([{type: itemType.job, name: '', outputItemCharacter: true }], false);
 | 
	
		
			
				|  |  |          });
 | 
	
	
		
			
				|  | @@ -1996,6 +2340,12 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |                  TREE_SHEET_HELPER.refreshNodesVisible(tree.roots, itemSheet, true);
 | 
	
		
			
				|  |  |              });
 | 
	
		
			
				|  |  |          });
 | 
	
		
			
				|  |  | +        // 配置材料
 | 
	
		
			
				|  |  | +        $('#editMaterial').click(function () {
 | 
	
		
			
				|  |  | +            if (bills && bills.tree && bills.tree.selected) {
 | 
	
		
			
				|  |  | +                $('#bill-material-modal').modal('show');
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  |          // 插入选中定额
 | 
	
		
			
				|  |  |          $('#insertRation').click(function () {
 | 
	
		
			
				|  |  |              let checkedRows = getCheckedRationRows();
 | 
	
	
		
			
				|  | @@ -2227,17 +2577,125 @@ const billsGuidance = (function () {
 | 
	
		
			
				|  |  |      //初始化视图
 | 
	
		
			
				|  |  |      //@param {void} @return {void}
 | 
	
		
			
				|  |  |      function initViews(){
 | 
	
		
			
				|  |  | -        let modules = [bills, guideItem, section, ration];
 | 
	
		
			
				|  |  | +        let modules = [bills, guideItem, section, ration, billMaterial, billMaterialHelper];
 | 
	
		
			
				|  |  |          initWorkBooks(modules);
 | 
	
		
			
				|  |  |          lockUtil.lockTools($(document.body), locked);
 | 
	
		
			
				|  |  |          getLibWithBills(libID);
 | 
	
		
			
				|  |  | -        initBtn();
 | 
	
		
			
				|  |  | +        initDomEvents();
 | 
	
		
			
				|  |  |          initContextMenu();
 | 
	
		
			
				|  |  |          initRationContextMenu();
 | 
	
		
			
				|  |  | +        //initBillsContextMenu();
 | 
	
		
			
				|  |  |          initSlideSize();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /* 生成特征分类: 前端测试使用,想要前端测试,需要在zhiyin.html中,将id=generate-classa的按钮放开 */
 | 
	
		
			
				|  |  | +    function getItemCharacterData(nodes, prefix) {
 | 
	
		
			
				|  |  | +        const processNodes = nodes.filter(node => isProcessNode(node));
 | 
	
		
			
				|  |  | +        const classGroups = []; // 同层必填选项的数组(二维数组)
 | 
	
		
			
				|  |  | +        processNodes.forEach(processNode => {
 | 
	
		
			
				|  |  | +            const classItems = [];
 | 
	
		
			
				|  |  | +            const optionNodes = processNode.children.filter(node => isOptionNode(node));
 | 
	
		
			
				|  |  | +            optionNodes.forEach(optionNode => {
 | 
	
		
			
				|  |  | +                // const name = prefix ? `${prefix}@${optionNode.data.name}` : optionNode.data.name;
 | 
	
		
			
				|  |  | +                if (optionNode.parent && optionNode.parent.data.required && (!optionNode.children 
 | 
	
		
			
				|  |  | +                    || !optionNode.children.length 
 | 
	
		
			
				|  |  | +                    || (optionNode.children[0].data && optionNode.children[0].data.rationID) 
 | 
	
		
			
				|  |  | +                    || !optionNode.children.some(node => isProcessNode(node)))) {
 | 
	
		
			
				|  |  | +                    // 必套定额
 | 
	
		
			
				|  |  | +                    const requiredRationIDs = optionNode.children && optionNode.children.length ?
 | 
	
		
			
				|  |  | +                        optionNode.children.filter(node => !!node.data.rationID).map(node => node.data.rationID) : [];
 | 
	
		
			
				|  |  | +                    classItems.push({ name: optionNode.data.name, requiredRationIDs });
 | 
	
		
			
				|  |  | +                } else {
 | 
	
		
			
				|  |  | +                    classItems.push(...getItemCharacterData(optionNode.children, optionNode.parent && optionNode.parent.data.required ? optionNode.data.name : ''));
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +            if (classItems.length) {
 | 
	
		
			
				|  |  | +                classGroups.push(classItems);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        // 拼接上一文本
 | 
	
		
			
				|  |  | +        if (classGroups[0] && classGroups[0].length) {
 | 
	
		
			
				|  |  | +            // classGroups[0] = classGroups[0].map(name => prefix ? `${prefix}@${name}` : name);
 | 
	
		
			
				|  |  | +            classGroups[0] = classGroups[0].map(item => {
 | 
	
		
			
				|  |  | +                item.name = prefix ? `${prefix}@${item.name}` : item.name
 | 
	
		
			
				|  |  | +                return item;
 | 
	
		
			
				|  |  | +            });
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 二维数组内容排列组合
 | 
	
		
			
				|  |  | +        while (classGroups.length > 1) {
 | 
	
		
			
				|  |  | +            const prevClassItems = classGroups[0];
 | 
	
		
			
				|  |  | +            const nextClassItems = classGroups[1];
 | 
	
		
			
				|  |  | +            const mergedClassItems = [];
 | 
	
		
			
				|  |  | +            for (let i = 0; i < prevClassItems.length; i++) {
 | 
	
		
			
				|  |  | +                for (let j = 0; j < nextClassItems.length; j++) {
 | 
	
		
			
				|  |  | +                    // 拼接文本
 | 
	
		
			
				|  |  | +                    const mergedName = `${prevClassItems[i].name}@${nextClassItems[j].name}`;
 | 
	
		
			
				|  |  | +                    // 拼接必套定额
 | 
	
		
			
				|  |  | +                    const mergedRationIDs = [...prevClassItems[i].requiredRationIDs, ...nextClassItems[j].requiredRationIDs];
 | 
	
		
			
				|  |  | +                    mergedClassItems.push({name: mergedName, requiredRationIDs: mergedRationIDs});
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            classGroups.splice(0, 2, mergedClassItems);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 去重(类别别名要唯一)
 | 
	
		
			
				|  |  | +        const items = classGroups[0] || [];
 | 
	
		
			
				|  |  | +        const nameMap = {};
 | 
	
		
			
				|  |  | +        const rst = [];
 | 
	
		
			
				|  |  | +        items.forEach(item => {
 | 
	
		
			
				|  |  | +            if (!nameMap[item.name]) {
 | 
	
		
			
				|  |  | +                rst.push(item);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            nameMap[item.name] = true;
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return rst;
 | 
	
		
			
				|  |  | +        
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 获取选套定额:把所有分类数据的必套定额确定好了先。选套定额就是清单下所有定额除了必套的
 | 
	
		
			
				|  |  | +    function getOptionalRationIDs(itemClassData, guideNodes) {
 | 
	
		
			
				|  |  | +        // 所有必套定额
 | 
	
		
			
				|  |  | +        let requiredRationIDs = [];
 | 
	
		
			
				|  |  | +        itemClassData.forEach(item => {
 | 
	
		
			
				|  |  | +            if (item.requiredRationIDs) {
 | 
	
		
			
				|  |  | +                requiredRationIDs.push(...item.requiredRationIDs);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        requiredRationIDs = [...new Set(requiredRationIDs)];
 | 
	
		
			
				|  |  | +        // 选套定额就是清单下所有定额除了必套的
 | 
	
		
			
				|  |  | +        const optionalRationIDs = [];
 | 
	
		
			
				|  |  | +        guideNodes.forEach(node => {
 | 
	
		
			
				|  |  | +            if (node.data.rationID && !requiredRationIDs.includes(node.data.rationID)) {
 | 
	
		
			
				|  |  | +                optionalRationIDs.push(node.data.rationID);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return [...new Set(optionalRationIDs)];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // 获取错套定额:清单下所有定额,除了分类对应的必套、选套定额
 | 
	
		
			
				|  |  | +    function getErrorRationIDs(requiredRationIDs, optionalRationIDs, guideNodes) {
 | 
	
		
			
				|  |  | +        const errorRationIDs = [];
 | 
	
		
			
				|  |  | +        guideNodes.forEach(node => {
 | 
	
		
			
				|  |  | +            if (node.data.rationID && !requiredRationIDs.includes(node.data.rationID) && !optionalRationIDs.includes(node.data.rationID)) {
 | 
	
		
			
				|  |  | +                errorRationIDs.push(node.data.rationID);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +        return [...new Set(errorRationIDs)];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    $('#generate-class').click(() => {
 | 
	
		
			
				|  |  | +        if (bills.tree.selected && bills.tree.selected.guidance.tree) {
 | 
	
		
			
				|  |  | +            const classData = getItemCharacterData(bills.tree.selected.guidance.tree.roots);
 | 
	
		
			
				|  |  | +            const optionalRationIDs = getOptionalRationIDs(classData, bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            classData.forEach(item => {
 | 
	
		
			
				|  |  | +                item.errorRationIDs = getErrorRationIDs(item.requiredRationIDs, optionalRationIDs, bills.tree.selected.guidance.tree.items);
 | 
	
		
			
				|  |  | +            })
 | 
	
		
			
				|  |  | +            console.log(optionalRationIDs);
 | 
	
		
			
				|  |  | +            console.log(classData);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      return {initViews, initSlideSize};
 | 
	
		
			
				|  |  |  })();
 | 
	
		
			
				|  |  |  
 |