let unitOptions = ['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件', '根', '组', '系统', '台', '套', '株', '丛', '缸', '支', '只', '块', '座', '对', '份', '樘', '攒', '榀'] let equipmentPurchaseObj = { IDMap:{}, parentMap:{}, setting:{ header: [ {headerName: "编号", headerWidth: 160, dataCode: "code", dataType: "String",formatter: "@",spanRows: [2]}, {headerName: "设备名称", headerWidth: 200, dataCode: "name", dataType: "String",spanRows: [2]}, {headerName: "单位", headerWidth: 60, dataCode: "unit", dataType: "String",hAlign: "center",cellType:'comboBox',editable:true,options:unitOptions,spanRows: [2]}, {headerName: ["设备价格","设备原价"], headerWidth: 160, dataCode: "originalPrice", hAlign: "right", dataType: "Number",validator:'number',spanCols: [4,1]}, {headerName: ["","设备运杂费"], headerWidth: 160, dataCode: "freight", hAlign: "right", dataType: "Number",validator:'number',spanCols: [0,1]}, {headerName: ["","备品备件费"], headerWidth: 160, dataCode: "sparePartCost", hAlign: "right", dataType: "Number",validator:'number',spanCols: [0,1]}, {headerName: ["","单价"], headerWidth: 160, dataCode: "unitPrice", hAlign: "right", dataType: "Number",validator:'number',spanCols: [0,1]}, {headerName: "数量", headerWidth: 160, dataCode: "quantity", hAlign: "right", dataType: "Number",validator:'number',spanRows: [2]}, {headerName: "合价", headerWidth: 160, dataCode: "totalPrice", hAlign: "right", dataType: "Number",spanRows: [2]}, ], headRows:2, view: { lockColumns: ["totalPrice",'unitPrice'], rowHeaderWidth:40, } }, sheet:null, initSpread:function () { if(this.sheet == null){ this.spread = SheetDataHelper.createNewSpread($("#equipmentSpread")[0]); sheetCommonObj.spreadDefaultStyle(this.spread); this.sheet = this.spread.getSheet(0); sheetCommonObj.initSheet(this.sheet, this.setting, 0); this.sheet.bind(GC.Spread.Sheets.Events.ValueChanged,this.onValueChange); this.sheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onSheetRangeChange); this.sheet.bind(GC.Spread.Sheets.Events.EditStarting, this.onEditStarting); this.sheet.bind(GC.Spread.Sheets.Events.SelectionChanged, function (e,args) { args.sheet.repaint(); equipmentPurchaseObj.checkBtn(); }); if (projectReadOnly) { sheetCommonObj.disableSpread(this.spread); } else { this.initRightClick(); } } }, checkBtn:function(){ let me = equipmentPurchaseObj; let selected = me.getSelected(); let preNode = me.getPreNode(selected); let afterNode = me.getAfterNode(selected); //工具栏按钮的有效性 me.validateBtn($('#equipment_upMove'),preNode); me.validateBtn($('#equipment_downMove'),afterNode); me.validateBtn($('#equipment_upLevel'),selected && selected.ParentID !=='-1'); me.validateBtn($('#equipment_downLevel'),preNode); }, validateBtn:function(btn,validate){ if(validate){ btn.removeClass('disabled'); }else{ btn.addClass('disabled'); } }, getTreeData:function(){ let treeData = []; let roots = this.parentMap['-1']; let me = this; getChildren(roots,treeData); return treeData; function getChildren(nodes,data){ if(nodes){ for(let n of nodes){ data.push(n); getChildren(me.parentMap[n.ID],data) } } } }, getSelected:function(){ let sel = this.sheet.getSelections()[0]; let row = sel.row == -1 || sel.row == "" ? 0 : sel.row; if(this.data && this.data.length>0){ return this.data[row]; } return null; }, getParentNode:function(node){ if(node.ParentID === '-1') return null; return this.IDMap[node.ParentID]; }, //取前兄弟节点 getPreNode:function(node){ if(node){ let nodes = this.parentMap[node.ParentID]; let index = nodes.indexOf(node); return nodes[index-1] } return null; }, //取后兄弟节点 getAfterNode:function(node){ if(node){ let nodes = this.parentMap[node.ParentID]; let index = nodes.indexOf(node); return nodes[index+1] } return null; }, //取所有后兄弟节点 getAllAfterNodes:function(node){ let brothers = this.parentMap[node.ParentID]; let index = brothers.indexOf(node); if(brothers.length >= index + 2){ return brothers.slice(index+1); } return []; }, //插入为最后一个子节点的序号 getLastChildrenSeq:function(node){ let seq = 1; let children = this.parentMap[node.ID]; if(children && children.length > 0){ return children[children.length-1].seq +1 } return seq; }, showData:function(){ let equipment_purchase = projectObj.project.equipment_purchase; this.sourceData = equipment_purchase.datas; let data = this.sourceData.equipments; this.IDMap = {}; this.parentMap = {}; data = _.sortBy(data,'seq'); for(let d of data){ let node = ({...d,collapsed:false}) this.IDMap[node.ID] = node; this.parentMap[node.ParentID] ?this.parentMap[node.ParentID].push(node):this.parentMap[node.ParentID]=[node]; } let treeData = this.getTreeData(); this.data = treeData; sheetCommonObj.showTreeData(this.sheet, this.setting,treeData); this.checkBtn(); $('#equipment_total').text(this.sourceData.total); }, onEditStarting: function (sender, args) { let me = equipmentPurchaseObj; let row = args.row; let col = args.col; if (me.editChecking(row, col) == false) { args.cancel = true; } }, editChecking:function (row,col) { let me = equipmentPurchaseObj let dataCode = me.setting.header[col].dataCode; let equipment = me.data[row]; let children = me.parentMap[equipment.ID]; if(children && children.length>0){//父节点只有这三列才能编辑 return dataCode === 'unit'||dataCode === 'name'||dataCode === 'code' } return true; }, onValueChange:function (e,info) { let me = equipmentPurchaseObj,row = info.row, col = info.col; let dataCode = me.setting.header[col].dataCode; let value = info.newValue; let equipment = me.data[row]; if (value&&! sheetCommonObj.checkData(col,me.setting,value)) { alert('输入的数据类型不对,请重新输入!'); return me.showData(); } let data = {doc:{},ID:equipment.ID}; if(dataCode == 'quantity' || dataCode == 'originalPrice'|| dataCode == 'freight'|| dataCode == 'sparePartCost'){ value = me.calcTotalPrice(value,dataCode,data.doc,equipment); } if(equipment[dataCode] == value) return me.showData(); data.doc[dataCode] = value; me.updateEquipments([data]); }, //计算父节点 calcParent:function(updateData){ let me = this; let temIDMap = {}; let temParentMap = {}; let deleteMap = {}; for(let d of updateData){ if(d.doc){ temIDMap[d.ID] = d; if(d.doc.ParentID){ temParentMap[d.doc.ParentID]?temParentMap[d.doc.ParentID].push(d):temParentMap[d.doc.ParentID]=[d]; } } if(d.type === 'delete')deleteMap[d.ID] = true } for(let d of this.data){ let children = this.parentMap[d.ID]; let newChildren = temParentMap[d.ID]; if((children&&children.length > 0) || (newChildren && newChildren.length > 0)){ let totalPrice = getTotalPrice(d.ID); if(d.totalPrice !== totalPrice) updateData.push({ID:d.ID,doc: {totalPrice,unitPrice:'',sparePartCost:'',freight:'',originalPrice:'',quantity:''} }) } } function getTotalPrice(ID){ let sum = 0; let children = me.parentMap[ID]; let newChildren = temParentMap[ID]; if((children&&children.length > 0) || (newChildren && newChildren.length > 0)){ if(children&&children.length > 0){ for(let c of children){ let newChild = temIDMap[c.ID]; if(deleteMap[c.ID]) continue;//如果是删除操作,不用计算 if(newChild && newChild.doc){ if(newChild.doc.ParentID && newChild.doc.ParentID!=ID) continue;//升级操作时,子节点可能已经不是它的子节点了 } let totalPrice = getTotalPrice(c.ID); sum = scMathUtil.roundForObj(sum + totalPrice,getDecimal('process')); } } if(newChildren && newChildren.length > 0){ for(let c of newChildren){ let totalPrice = getTotalPrice(c.ID); sum = scMathUtil.roundForObj(sum + totalPrice,getDecimal('process')); } } return scMathUtil.roundForObj(sum,getDecimal('glj.unitPrice')); } let tem = temIDMap[ID]; if(tem && tem.doc){ let doc = tem.doc; if(gljUtil.isDef(doc.totalPrice)) return doc.totalPrice; } return me.IDMap[ID].totalPrice?scMathUtil.roundForObj(me.IDMap[ID].totalPrice,getDecimal('glj.unitPrice')):0 } }, calcTotalPrice:function(newValue = 0,dataCode,doc,equipment){ //设备原价 let originalPrice = equipment.originalPrice?scMathUtil.roundForObj(equipment.originalPrice,getDecimal('glj.unitPrice')):0; //设备运杂费 let freight = equipment.freight?scMathUtil.roundForObj(equipment.freight,getDecimal('glj.unitPrice')):0; //备品备件费 let sparePartCost = equipment.sparePartCost?scMathUtil.roundForObj(equipment.sparePartCost,getDecimal('glj.quantity')):0; let quantity = equipment.quantity?scMathUtil.roundForObj(equipment.quantity,getDecimal('glj.quantity')):0; let unitPrice = 0; if(gljUtil.isDef(doc.originalPrice)) originalPrice = doc.originalPrice; if(gljUtil.isDef(doc.freight)) freight = doc.freight; if(gljUtil.isDef(doc.sparePartCost)) sparePartCost = doc.sparePartCost; if(gljUtil.isDef(doc.quantity)) quantity = doc.quantity; if(dataCode === 'quantity') { newValue = scMathUtil.roundForObj(newValue,getDecimal('glj.quantity')); quantity = newValue; } if(dataCode === 'originalPrice') { newValue = scMathUtil.roundForObj(newValue,getDecimal('glj.unitPrice')); originalPrice = newValue; } if(dataCode === 'freight') { newValue = scMathUtil.roundForObj(newValue,getDecimal('glj.unitPrice')); freight = newValue; } if(dataCode === 'sparePartCost') { newValue = scMathUtil.roundForObj(newValue,getDecimal('glj.unitPrice')); sparePartCost = newValue; } unitPrice = scMathUtil.roundForObj(originalPrice + freight,getDecimal('process')); unitPrice = scMathUtil.roundForObj(unitPrice + sparePartCost,getDecimal('glj.unitPrice')); doc.unitPrice = unitPrice; doc.totalPrice = scMathUtil.roundForObj(quantity * unitPrice,getDecimal('glj.unitPrice')); return newValue; }, //计算序列号,返回要改变的兄弟节点数据 calcSeq:function(ParentID,seq){ let data = []; let nodes = this.parentMap[ParentID]; let temSeq = seq+1; if(nodes && nodes.length > 0){ for(let n of nodes){ if(n.seq >= seq){ data.push({doc:{seq:temSeq},ID:n.ID}) temSeq+=1; } } } return data; }, onSheetRangeChange:function(e,args){ let updateMap = {}; let updateData = [] let me = equipmentPurchaseObj; for(let c of args.changedCells){ let dataCode = me.setting.header[c.col].dataCode; let value= args.sheet.getCell(c.row, c.col).text(); let equipment = me.data[c.row]; if (me.editChecking(c.row, c.col) == false) { continue } if (value&&!sheetCommonObj.checkData(c.col,me.setting,value)) { alert('输入的数据类型不对,请重新输入!'); me.showData(); return ; } let tem = updateMap[equipment.ID]?updateMap[equipment.ID]:{}; if(dataCode == 'quantity' || dataCode == 'originalPrice'|| dataCode == 'freight'|| dataCode == 'sparePartCost'){ value = me.calcTotalPrice(value,dataCode,tem,equipment); } tem[dataCode] = value; updateMap[equipment.ID] = tem; } for(let ID in updateMap){ let data = {doc:updateMap[ID],ID:ID}; updateData.push(data); } updateData.length > 0? me.updateEquipments(updateData): me.showData(); }, newEquipment:function(ParentID='-1',seq=0){ return {ID:uuid.v1(),ParentID,seq} }, sumTotal: function(updateData){ let dataMap = {}; let temParentMap = {}; let total = 0; let deleteMap = {}; for(let d of updateData){ if(d.doc){ dataMap[d.ID] = d; if(d.doc.ParentID){ temParentMap[d.doc.ParentID]?temParentMap[d.doc.ParentID].push(d):temParentMap[d.doc.ParentID]=[d]; } } if(d.type === 'delete')deleteMap[d.ID] = true } for(let d of this.data){ //累加所有底层节点就行 if(!this.parentMap[d.ID] && !temParentMap[d.ID] ){ if(deleteMap[d.ID]) continue; let totalPrice = d.totalPrice?scMathUtil.roundForObj(d.totalPrice,getDecimal('glj.unitPrice')):0; let data = dataMap[d.ID]; if(data && gljUtil.isDef(data.doc.totalPrice))totalPrice = data.doc.totalPrice; total =scMathUtil.roundForObj(total + totalPrice,getDecimal('glj.unitPrice')) } } return total; }, //上移 moveUp:async function(node){ let preNode = this.getPreNode(node); if(preNode){ let updateData = []; updateData.push({doc:{seq:node.seq},ID:preNode.ID}); updateData.push({doc:{seq:preNode.seq},ID:node.ID}); await this.updateEquipments(updateData); } }, updateEquipments:async function(updateData){ try { this.calcParent(updateData); $.bootstrapLoading.start(); let projectID = projectObj.project.ID(); let total = this.sumTotal(updateData); await ajaxPost('/equipmentPurchase/updateEquipments', { projectID, updateData,total }); for(let data of updateData){ if(data.type === 'insert'){ this.sourceData.equipments.push(...data.documents); }else if (data.type === 'delete'){ _.remove( this.sourceData.equipments,{ID:data.ID}); } else{ let equipment = _.find(this.sourceData.equipments,{ID:data.ID}); if(equipment){ Object.assign(equipment,data.doc); } } } projectObj.project.equipment_purchase.datas.total = total; } catch (error) { console.log(error); alert('更新失败,请重试'); } this.showData(); $.bootstrapLoading.end(); }, insertEquipments:async function(equipments){ try { $.bootstrapLoading.start(); let projectID = projectObj.project.ID(); await ajaxPost('/equipmentPurchase/insertData', { projectID, equipments }); this.sourceData.equipments.push(...equipments) this.showData(); } catch (error) { alert('插入失败,请重试'); } $.bootstrapLoading.end(); }, deleteEquipment:async function(ID){ try { let projectID = projectObj.project.ID(); await ajaxPost('/equipmentPurchase/deleteEquipment', { projectID, ID }); _.remove( this.sourceData.equipments,{ID}); this.showData(); } catch (error) { alert('删除失败,请重试'); } }, registerInputContextMenuItem:function(){ const insertEquipmentHtml = `插入    行`; let me = this; return sheetCommonObj.registerInputContextMenuItem('insertEquipment', insertEquipmentHtml, 'fa-sign-in', async function () { const number = +$('#insert-equipment-number').val(); if (!number) { return; } const newData = []; let row = me.rightClickTarget.row; let seq = 0; let ParentID = '-1'; let brotherNodes = []; if(row == undefined){//没有选中节点的情况,添加到最后 brotherNodes = me.parentMap['-1']; if(brotherNodes && brotherNodes.length > 0){ seq = brotherNodes[brotherNodes.length -1].seq; } }else{ let node = me.data[row];//选中节点时插入为选中的下一行 seq = node.seq; ParentID = node.ParentID; } for (let i = 0; i < number; i++) { seq+=1; newData.push(me.newEquipment(ParentID,seq)); } let updateData = me.calcSeq(ParentID,seq); updateData.push({documents:newData,type:'insert'}); me.updateEquipments(updateData) }); }, initRightClick: function () { let me = this; $.contextMenu({ selector: '#equipmentSpread', build: function ($trigger, e) { me.rightClickTarget = SheetDataHelper.safeRightClickSelection($trigger, e, me.spread); me.checkBtn(); return me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.viewport || me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader; }, items: { "insert": { type: me.registerInputContextMenuItem(), disabled: function () { return false; }, /* callback: function (key, opt) { me.insertEquipments([me.newEquipment()]) } */ }, "delete": { name: "删除", icon: 'fa-times', disabled: function () { return me.rightClickTarget.row === undefined; }, callback: function (key, opt) { let row = me.rightClickTarget.row; me.updateEquipments([{ID:me.data[row].ID,type:'delete'}]); //me.preApplyInfoPrice(row); } } } }); }, } $(function () { $('#tab_equipment_purchase').on('shown.bs.tab', function (e) { sessionStorage.setItem('mainTab', '#tab_equipment_purchase'); $(e.relatedTarget.hash).removeClass('active'); equipmentPurchaseObj.initSpread(); equipmentPurchaseObj.showData(); }) //降级 $('#equipment_downLevel').click(function(){ let me = equipmentPurchaseObj; let selected = me.getSelected(); if(selected){ let preNode = me.getPreNode(selected); if(preNode){ let seq = me.getLastChildrenSeq(preNode); me.updateEquipments([{doc:{ParentID:preNode.ID,seq},ID:selected.ID}]) } } }) //升级 - 后兄弟节点变成子节点 $('#equipment_upLevel').click(function(){ let me = equipmentPurchaseObj; let selected = me.getSelected(); if(selected){ let parentNode = me.getParentNode(selected); if(parentNode){ let seq = parentNode.seq+1; let updateData = me.calcSeq(parentNode.ParentID,seq); updateData.push({doc:{ParentID:parentNode.ParentID,seq},ID:selected.ID}) let brothers = me.getAllAfterNodes(selected); let subSeq = 0; //后兄弟节点变成子节点 for(let b of brothers){ subSeq+=1; updateData.push({doc:{ParentID:selected.ID,seq:subSeq},ID:b.ID}) } me.updateEquipments(updateData) } } }) //上移 $('#equipment_upMove').click(async function (){ let me = equipmentPurchaseObj; let selected = me.getSelected(); if(selected){ let sel = me.sheet.getSelections()[0]; me.sheet.setSelection(sel.row -1 , sel.col, sel.rowCount, sel.colCount); await me.moveUp(selected); } }) //下移 $('#equipment_downMove').click(async function(){ let me = equipmentPurchaseObj; let selected = me.getSelected(); if(selected){ let sel = me.sheet.getSelections()[0]; let node = me.getAfterNode(selected); if(node){ me.sheet.setSelection(sel.row +1 , sel.col, sel.rowCount, sel.colCount); await me.moveUp(node); } } }) })