/** * Created by chen on 2017/8/1. */ var feeRateObject={ mainFeeRateSpread:null, mainFeeRateSheet:null, mainFeeRateData:null, mainFeeRateSetting:{ header: [ {headerName: "专业名称", headerWidth: 250, dataCode: "name", dataType: "String"}, {headerName: "值%", headerWidth: 80, dataCode: "rate", dataType: "Number",hAlign: "right",decimalField:"feeRate"}, {headerName: "备注", headerWidth: 150, dataCode: "memo", dataType: "String"} ], view: { lockColumns: [0] } }, mainViews:null, datas:null, datasBackup:null, canEdit:false, activateFeeRate:null, needCascadeSet:false, selectionLoad:false, changeInfo:null, feeRateSpreads:null, editingCell:null, feeRateSelection:null, sheetSetting: { header: [ {headerName: "专业名称", headerWidth: 200, dataCode: "name", dataType: "String"}, {headerName: "值%", headerWidth: 120, dataCode: "rate", dataType: "Number",hAlign: "right",decimalField:"feeRate"}, {headerName: "备注", dataCode: "memo", dataType: "String"} ], view: { comboBox: [], lockColumns: [0, 1, 2] } }, columns: [ { id: 'name', caption: '专业名称', dataField: 'name', width: 450, allowEditing: false }, { id: 'rate', caption: '值%', dataField: 'rate', width: 120, minWidth: 50, allowEditing: true }, { id: 'memo', caption: '备注', dataField: 'memo', minWidth: 120, allowEditing: true }, { id: 'ID', caption: 'ID', dataField: 'ID', width: 80, visible: false, allowEditing: false }, { id: 'subFeeRate', caption: '子费率', dataField: 'subFeeRate', width: 80, visible: false, allowEditing: false }, { id: '_id', caption: '自动ID', dataField: '_id', width: 80, visible: false, allowEditing: false }, { id: 'ParentID', caption: '父结点ID', dataField: 'ParentID', width: 80, visible: false, allowEditing: false } ], options :{ allowSorting: false, showRowHeader: true, colMinWidth: 80, rowHeight: 30, allowEditing: true, editMode: 'inline', editUnit: 'cell', selectionUnit: "row", hierarchy: { keyField: 'ID', parentField: 'ParentID', collapsed: false, column: 'name' } }, dataSource : { loadRange: function(params) { params.success(feeRateObject.datas); }, update: function(params) { if(!params.hasOwnProperty('sourceIndex')){ var selected = feeRateObject.mainViews.getSelections()[0]; params.sourceIndex = selected.sourceRow; } params.success(); if(!$('#cascadeSet').prop('checked')||params.hasOwnProperty('viewIndex')){ projectObj.project.FeeRate.updateFeeRateByEdit(params,feeRateObject.activateFeeRate); } } }, createSheet:function(){ var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate(); feeRateObject.feeRateSpreads=sheetCommonObj.buildSheet($('#fee_rate_sheet')[0], feeRateObject.sheetSetting,feeRateFile.rates.length); sheetCommonObj.spreadDefaultStyle(feeRateObject.feeRateSpreads); feeRateObject.feeRateSheet = feeRateObject.feeRateSpreads.getSheet(0); feeRateObject.feeRateSheet.selectionUnit(1)//0 cell,1 row,2 col; feeRateObject.feeRateSheet.options.isProtected = true; feeRateObject.feeRateSheet.name('fee_rate'); feeRateObject.feeRateSheet.bind(GC.Spread.Sheets.Events.CellClick,feeRateObject.onCellClick); feeRateObject.feeRateSheet.bind(GC.Spread.Sheets.Events.CellDoubleClick,feeRateObject.onCellDoubleClick); }, showFeeRateTree:function (sheet,setting,data) { console.log(data); let ch = GC.Spread.Sheets.SheetArea.viewport; let parentMap=_.groupBy(data, 'ParentID'); let visibleMap = {}; sheet.suspendPaint(); sheet.suspendEvent(); for (let col = 0; col < setting.header.length; col++) { let hAlign = "left", vAlign = "center"; if (setting.header[col].hAlign) { hAlign = setting.header[col].hAlign; } else if (setting.header[col].dataType !== "String"){ hAlign = "right"; } vAlign = setting.header[col].vAlign?setting.header[col].vAlign:vAlign; sheetCommonObj.setAreaAlign(sheet.getRange(-1, col, -1, 1), hAlign, vAlign); if (setting.header[col].formatter) { sheet.setFormatter(-1, col, setting.header[col].formatter, GC.Spread.Sheets.SheetArea.viewport); } for (let row = 0; row < data.length; row++) { let val = data[row][setting.header[col].dataCode]; if(val&&setting.header[col].dataType === "Number"){ if(setting.header[col].hasOwnProperty('decimalField')){ let decimal = getDecimal(setting.header[col].decimalField); val =scMathUtil.roundToString(val,decimal); sheet.setFormatter(-1, col,getFormatter(decimal), GC.Spread.Sheets.SheetArea.viewport); }else { val =scMathUtil.roundToString(val,2); } } sheet.setValue(row, col, val, ch); if(col==0){ let treeType = sheetCommonObj.getTreeNodeCellType(data,row,parentMap); sheet.getCell(row, 0).cellType(treeType); visibleMap[data[row].ID] = treeType.collapsed; feeRateObject.setRowVisible(data,row,visibleMap,sheet); } } } sheet.resumeEvent(); sheet.resumePaint(); }, setRowVisible:function (data,row,visibleMap,sheet) { sheet.getRange(row , -1, 1, -1).visible(getVisible(data[row].ParentID));//显示或隐藏 function getVisible(ParentID) { if(visibleMap[ParentID]) return false //如果父节点是缩起的,那就隐藏本身。 if(visibleMap[ParentID] == false){//如果父节点不是缩起的,要再往父节点找看 let pnode = _.find(data,{'ID':ParentID}); if(pnode) return getVisible(pnode.ParentID);//如果有父节点,递归调用 return true;//没有,返回显示 } } }, getFeeRateLevel:function (rate,data) { if(rate.ParentID){ let prate = _.find(data,{'ID':rate.ParentID}); return this.getFeeRateLevel(prate,data) + 1; }else { return 0 } }, initFeeRateEditDiv:function(optionValue){//“0” 手工输入; “1” 选择费率 let radioValue = 1,feeRateValue; $("#customFeeRate").val("");//先清空输入 if(!gljUtil.isDef(optionValue)){ let fID = 0; if ($("#calc_program_manage").is(":visible")){ fID = calcProgramManage.getSelectionInfo().calcItem.feeRateID; feeRateValue = calcProgramManage.getSelectionInfo().calcItem.feeRate; } else if ($("#zaojiashu").is(":visible")){ fID = projectObj.project.mainTree.selected.data.feeRateID; feeRateValue = projectObj.project.mainTree.selected.data.feeRate; } if(fID){ feeRateValue = projectObj.project.FeeRate.getFeeRateByID(fID).rate; } if(!fID&&gljUtil.isDef(feeRateValue)) radioValue = 0; //2019-04-18 只有在没有费率ID,但是有费率值的情况下才显示自定义费率页,其它所有的情况都显示费率选择页面 if(!isNaN(feeRateValue))$("#customFeeRate").val(feeRateValue); } $("input[name='editFeeRateOptions'][value='"+radioValue+"']").prop("checked",true); if(radioValue == "0"){ $("#selfDiv").show(); $("#fee_rate_sheet").hide(); }else { $("#selfDiv").hide(); $("#fee_rate_sheet").show(); } }, locate: function(){ // CSL,2018.07.18 let sheet = feeRateObject.feeRateSpreads.getSheet(0); let fID = 0; if ($("#calc_program_manage").is(":visible")) fID = calcProgramManage.getSelectionInfo().calcItem.feeRateID; else if ($("#zaojiashu").is(":visible")) fID = projectObj.project.mainTree.selected.data.feeRateID; let rates = projectObj.project.FeeRate.getActivateFeeRate().rates; let rowIdx = 0, pID = 0; if (fID){ fID = parseInt(fID); rowIdx = _.findIndex(rates,{ID:fID}); if(rowIdx != -1) pID = rates[rowIdx].ParentID; } // 费率现有可能有多层节点,所以要递归展开父节点 if(pID) expandParent(pID,rates,sheet); sheet.setSelection(rowIdx, -1, 1, -1); sheet.showRow(rowIdx, GC.Spread.Sheets.VerticalPosition.center); feeRateObject.onCellClick({type: 'CellClick'}, {row:rowIdx}); function expandParent(ID,datas,sheet) {//递归展开父节点 let cellType = setCollapsed(ID); cellType.refreshChildrenVisible(sheet); function setCollapsed(parentID){ let index = _.findIndex(datas,{'ID':parentID}); let type = sheet.getCellType(index,0); type.collapsed = false; if(datas[index].ParentID){ setCollapsed(datas[index].ParentID) } return type } } }, getTreeNodeCellType:function (datas,row,parentMap) {// 2018-09-26 不用spreadjs默认的树结构,自定义控件 var ns = GC.Spread.Sheets; let rectW = 10; let rectH = 10; let margin = 3; function TreeNodeCellType() { this.collapsed = true; //默认是折叠的 this.rectInfo = {}; } TreeNodeCellType.prototype = new ns.CellTypes.Text(); TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) { let offset = 0; let step = 7; let level = getTreeLevel(datas[row],datas);//从0开始,取当前节点是第几级的 let tem = offset+margin+ rectW/2+step;//两条线之间的间隔 let t_offset = offset; let temParentID = datas[row].ParentID; for(let i = level;i>0;i--){//这里是画子节点前面的竖线,从第二级开始 let temParent = getParent(temParentID,datas); if(temParent){//父节点有下一个兄弟节点才需要画 if(hasNextBrother(parentMap,temParent)) sheetCommonObj.drawLine(ctx,x+t_offset+tem*i,y,x+t_offset+tem*i,y+h); temParentID = temParent.ParentID; } offset +=tem; } offset+=step; if(hasChildern(datas[row].ID,datas)){//如果是有子节点 //第一条不用画方框头上那条竖线其它都要 if(row !=0) sheetCommonObj.drawLine(ctx,x+offset+ rectW/2+margin,y,x+offset+ rectW/2+margin,y + Math.round(h / 2) - rectH / 2); //画方框下面的那条竖线,如果没有下一个兄弟节点,则不用画 if(hasNextBrother(parentMap,datas[row])) sheetCommonObj.drawLine(ctx,x+offset+ rectW/2+margin,y + Math.round(h / 2) + rectH / 2,x+offset+ rectW/2+margin,y + h); sheetCommonObj.drowRect(ctx, x+offset, y, w, h,rectW,rectH,margin); sheetCommonObj.drowSymbol(ctx, x+offset, y, w, h,rectW,rectH,margin, this.collapsed); this.rectInfo = {x:x+offset+margin,rectW:rectW}//计录一下可点击位置 }else { let hasNext = datas[row+1]?datas[row+1].ParentID == datas[row].ParentID:false; sheetCommonObj.drowSubItem(ctx, x, y, w, h, offset,hasNext,margin+ rectW/2); } offset += step; offset += rectW; x = x + offset;//设置偏移 w = w - offset; GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments); }; // override getHitInfo to allow cell type get mouse messages TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) { return { x: x, y: y, row: context.row, col: context.col, cellStyle: cellStyle, cellRect: cellRect, sheetArea: context.sheetArea }; } TreeNodeCellType.prototype.processMouseDown = function (hitinfo) { ////方框外1像素内都有效 if (!_.isEmpty(this.rectInfo)&&Math.floor(hitinfo.x) <= this.rectInfo.x+this.rectInfo.rectW+2 && Math.floor(hitinfo.x) >= this.rectInfo.x-2) { this.collapsed = !this.collapsed; this.refreshChildrenVisible(hitinfo.sheet); hitinfo.sheet.invalidateLayout(); hitinfo.sheet.repaint(); } }; TreeNodeCellType.prototype.refreshChildrenVisible = function (sheet) { sheet.suspendPaint(); sheet.suspendEvent(); refreshVisible(datas[row]); sheet.resumeEvent(); sheet.resumePaint(); function refreshVisible(item){ if(parentMap[item.ID]){ for(let sub of parentMap[item.ID]){ refreshVisible(sub) } } let visible = getVisible(item); let trow = datas.indexOf(item); sheet.getRange(trow , -1, 1, -1).visible(visible); } function getVisible(item) { if(item.ParentID){ let parent = getParent(item.ParentID,datas); if(!parent) return true; let p_row= datas.indexOf(parent); let visible = !sheet.getCellType(p_row,0).collapsed; if(visible == true){ //如果是显示的,则要再往父节点的父节点检查,只要有一个节点是隐藏的,则都是隐藏 return getVisible(parent); }else { return visible } }else {//如果parentID 为空则是最根节点 return true; } } }; return new TreeNodeCellType() function getTreeLevel(item,data) { if(item.ParentID){ let pitem = _.find(data,{'ID':item.ParentID}); return getTreeLevel(pitem,data) + 1; }else { return 0 } } function hasChildern(ID,data) {//返回是否有子项 let p = _.find(data,{'ParentID':ID}); if(p) return true; return false } function getParent(ParentID,data) { let p = _.find(data,{'ID':ParentID}); return p; } function hasNextBrother(parentMap,item){ let children =parentMap[item.ParentID]; if(children && children.indexOf(item) == children.length -1) return false; return true } }, getFeeRateEditCellType:function () { var ns = GC.Spread.Sheets; function FeeRateEditCellType() { var init=false; } FeeRateEditCellType.prototype = new ns.CellTypes.Text(); //2018-12-12 按新需求隐藏费率选择按钮 /* FeeRateEditCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) { GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments); if(feeRateObject.editingCell && !projectReadOnly){ if(feeRateObject.editingCell.row==options.row&&feeRateObject.editingCell.col==options.col){ var image = document.getElementById('f_btn'),imageMagin = 3; var imageHeight = h-2*imageMagin; var imageWidth = w*2/7; var imageX = x + w - imageWidth- imageMagin, imageY = y + h / 2 - imageHeight / 2; ctx.save(); ctx.drawImage(image, imageX, imageY,imageWidth,imageHeight); ctx.beginPath(); ctx.arc(imageX+imageWidth/2,imageY+imageHeight/2,1,0,360,false); ctx.arc(imageX+imageWidth/2-4,imageY+imageHeight/2,1,0,360,false); ctx.arc(imageX+imageWidth/2+4,imageY+imageHeight/2,1,0,360,false); ctx.fillStyle="black";//填充颜色,默认是黑色 ctx.fill();//画实心圆 ctx.closePath(); ctx.restore(); } } }; FeeRateEditCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) { return { x: x, y: y, row: context.row, col: context.col, cellStyle: cellStyle, cellRect: cellRect, sheetArea: context.sheetArea }; }; FeeRateEditCellType.prototype.processMouseDown = function (hitinfo) { let me=feeRateObject; if(me.editingCell && hitinfo.row==me.editingCell.row){ var offset=hitinfo.cellRect.x+hitinfo.cellRect.width-6; var imageMagin=3; var imageHeight = hitinfo.cellRect.height-2*imageMagin; var imageWidth = hitinfo.cellRect.width*2/7; if(hitinfo.xoffset-imageWidth){ if(!projectReadOnly && me.ifFeeRateEdit(hitinfo.row,hitinfo.sheet.name())){ $('#calcBaseFeeRateConf').attr('toggle', 'feeRate'); changeCalcBaseFeeRate('feeRate'); $('#tabFeeRate').tab('show'); me.showSelectModal(hitinfo); } }else {//鼠标点击其它地方,消失 hideButton(hitinfo); } } }; FeeRateEditCellType.prototype.processMouseEnter = function (hitinfo){ let me=feeRateObject; me.pmLeave = false; if(me.editingCell==null){ var showSelectBtn = true; if(hitinfo.sheet.name()!='calc_detail'){ showSelectBtn=me.ifFeeRateEdit(hitinfo.row,hitinfo.sheet.name()); } if(showSelectBtn){ me.editingCell={ row:hitinfo.row, col:hitinfo.col }; hitinfo.sheet.invalidateLayout(); hitinfo.sheet.repaint(); } } }; FeeRateEditCellType.prototype.processMouseLeave = function (hitinfo) { hideButton(hitinfo); }; function hideButton(hitinfo) { if(!feeRateObject.pmLeave){ feeRateObject.editingCell=null; hitinfo.sheet.invalidateLayout(); hitinfo.sheet.repaint(); feeRateObject.pmLeave = true; } }*/ return new FeeRateEditCellType(); }, showSelectModal:function (hitinfo) { let project = projectObj.project; let field = projectObj.mainController.setting.cols[hitinfo.col].data.field; if(MainTreeCol.lockBillChecking(project.mainTree.selected,field)){ //锁定的清单不显示 return; } //$("#fee_rate_tree").modal({show:true}); $("#calcBaseFeeRate").modal({show:true}); $('#edit_from').val(hitinfo.sheet.name()); }, getChildrenCount:function (id,data) { var me=this; var sum=0; var children=_.filter(data,{'ParentID':id}); if(children&&children.length==0){ return 0; } for(var i=0;i0){//有子节点时不能编辑费率列 return false; } return true; }, onMainFeeRateSheetValueChange:function (e,info) { feeRateObject.updateFeerateWhenCellsChange([info]); }, onMainFeeRateRangeChanged:function (e,info) { let me = feeRateObject; let changeCells = []; for(let c of info.changedCells){ let tem = { row:c.row, col:c.col, newValue:info.sheet.getCell(c.row,c.col).value() }; changeCells.push(tem); } me.updateFeerateWhenCellsChange(changeCells); }, updateFeerateWhenCellsChange:function (cells) {// col,row,newValue let me = feeRateObject,updateDatas = [],feeRate = projectObj.project.FeeRate;//[{rateID:rateID,doc:doc}] let refreshA = [];//记录刷新条数的数组 for(let c of cells){ let temData = {}; let recode = me.mainFeeRateData[c.row]; let fieldID = me.mainFeeRateSetting.header[c.col].dataCode; let value = c.newValue; let oldValue = recode[fieldID]; if(!me.mainFeeRateEditChecking(c.row, c.col)){ me.mainFeeRateSheet.setValue(c.row, c.col, oldValue); continue; }else if(fieldID == 'rate'&&value !== null && value!==0){ let checkResult = scMathUtil.isNumOrFormula(value); if(checkResult!=null && !isNaN(checkResult)){ value = scMathUtil.roundForObj(checkResult,getDecimal("feeRate")); }else { alert('当前输入的数据类型不正确,请重新输入。'); me.mainFeeRateSheet.setValue(c.row, c.col, oldValue); continue; } } if(recode[fieldID] == value){//没有改变 continue; } temData[fieldID] = value ; updateDatas.push({rateID:recode.ID,doc:temData}); refreshA.push({col:c.col,row:c.row,fieldID:fieldID,value:value,rateID:recode.ID}); } if(updateDatas.length > 0){ $.bootstrapLoading.start(); feeRate.updateFeeRatesByIDs(updateDatas,function () { let feerateInfo = []; for(let r of refreshA){ me.mainFeeRateSheet.setValue(r.row, r.col, r.value); if(r.fieldID == 'rate'){ feerateInfo.push({rateID:r.rateID,value:r.value}); } } if(feerateInfo.length > 0){ feeRate.onFeeRatesChange(feerateInfo); }else { $.bootstrapLoading.end(); } }) } }, onMainFeeRateSelectChanged:function (e, info) { let me = feeRateObject; let row = info.newSelections[0].row; me.onMainFeeRateSelect(row); }, onMainFeeRateSelect:function (row) { let me = this; if(row!=-1){ subRateObject.initSubRateSpread(me.mainFeeRateData[row]); } }, updateBySelect:function (rate,selectMap,mapID) { let selected = this.mainFeeRateSheet.getSelections()[0]; projectObj.project.FeeRate.backupDatas(); let item = this.mainFeeRateData[selected.row]; item.rate = rate; for(let key in selectMap){ let recode = item.subFeeRate.recodes[key]; let optionList = recode.optionList; for(let o of optionList){ if(o.value==selectMap[key]){ o.selected=true; }else { o.selected = false; } } } if($('#cascadeSet').prop('checked')){ this.cascadeSetRates(item,selected.row,mapID,selectMap); }else { projectObj.project.FeeRate.batchUpdateFeeRate([{rateIndex:selected.row,rate:item}],feeRateObject.activateFeeRate); } }, cascadeSetRates:function(selectedItem,sourceRow,mapID,selectMap){ let items=[]; items.push({rateIndex:sourceRow,rate:selectedItem}); _.forEach(this.mainFeeRateData,function (recode,Index) { if(Index!=sourceRow&&recode.subFeeRate){ let valueMaps = recode.subFeeRate.valueMaps; let valueMap = _.find(valueMaps,{ID:mapID}); if(valueMap){//选项完全一样的情况 if(valueMap.value==recode.rate){ return; }else { recode.rate = valueMap.value; _.forEach(selectMap,function (value,key) { let tempRecode = recode.subFeeRate.recodes[key]; let optionList = tempRecode.optionList; for(let o of optionList){ o.value===value? o.selected = true:o.selected = false; } }); items.push({rateIndex:Index,rate:recode}); } }else {//某条选项一样的情况 let needUpdate = false; let selectList = mapID.split('-'); let newList=[]; _.forEach(recode.subFeeRate.recodes,function (r) { let oList = r.optionList, oldSelectIndex=0, hasChange=false; _.forEach(oList,function (o,key) { if(o.selected) oldSelectIndex = key; if(_.includes(selectList,o.value)){ needUpdate=true; o.selected=true; hasChange=true; newList.push(o.value); }else { o.selected=false; } }); if(!hasChange){ oList[oldSelectIndex].selected=true; newList.push(oList[oldSelectIndex].value) } }); if(needUpdate){ let newValue = _.find(valueMaps,{ID:newList.join("-")})//取出费率值并更新 if(newValue){ if(recode.rate != newValue.value){ recode.rate = newValue.value; items.push({rateIndex:Index,rate:recode}); } } } } } }); projectObj.project.FeeRate.batchUpdateFeeRate(items,feeRateObject.activateFeeRate); }, loadPageContent:function(){ var feeRateFile = projectObj.project.FeeRate.getActivateFeeRate(); var usageProjects = feeRateFile.usageProjects; $('#feeRateFileName').text(feeRateFile.name); $('#feeRateLibName').text(feeRateFile.libName); $('#projectCount').text(usageProjects.length); }, loadFeeRateSelection:function() { if(!this.selectionLoad){ var selectedID=0; _.forEach(projectObj.project.FeeRate.datas,function (data) { var option = $("