const billsCompareField = ['quantity', 'total_price', ]; const posCompareField = ['quantity']; $(document).ready(() => { autoFlashHeight(); const billsSpreadSetting = { cols: [ {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 185, formatter: '@', cellType: 'tree'}, {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 100, formatter: '@'}, {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 235, formatter: '@'}, {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@'}, {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number'}, {title: '合计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sum_quantity', hAlign: 2, width: 80, type: 'Number'}, {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sum_total_price', hAlign: 2, width: 80, type: 'Number'}, ], baseCols: [ {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 185, formatter: '@', cellType: 'tree'}, {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 100, formatter: '@'}, {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 235, formatter: '@'}, {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@'}, {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number'}, ], extraCols: [ {title: '标段1|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity_1', hAlign: 2, width: 80, type: 'Number', formatTitle: '%s|数量', formatField: 'quantity_%d'}, {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price_1', hAlign: 2, width: 80, type: 'Number', formatField: 'total_price_%d'}, ], endCols: [ {title: '合计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sum_quantity', hAlign: 2, width: 80, type: 'Number'}, {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sum_total_price', hAlign: 2, width: 80, type: 'Number'}, ], emptyRows: 0, headRows: 2, headRowHeight: [32, 25], defaultRowHeight: 21, headerFont: '12px 微软雅黑', font: '12px 微软雅黑', readOnly: true, }; const posSpreadSetting = { cols: [ {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 235, formatter: '@'}, {title: '差值', colSpan: '1', rowSpan: '1', field: 'su,_quantity', hAlign: 2, width: 100, type: 'Number'}, ], baseCols: [ {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 235, formatter: '@'}, ], extraCols: [ {title: '标段1', colSpan: '1', rowSpan: '1', field: 'quantity_1', hAlign: 2, width: 100, type: 'Number', formatTitle: '%s', formatField: 'quantity_%d'}, ], endCols: [ {title: '合计', colSpan: '1', rowSpan: '1', field: 'sum_quantity', hAlign: 2, width: 100, type: 'Number'}, ], emptyRows: 0, headRows: 1, headRowHeight: [32], defaultRowHeight: 21, headerFont: '12px 微软雅黑', font: '12px 微软雅黑', readOnly: true, }; const billsSpread = SpreadJsObj.createNewSpread($('#bills-spread')[0]); const billsSheet = billsSpread.getActiveSheet(); sjsSettingObj.setFxTreeStyle(billsSpreadSetting, sjsSettingObj.FxTreeStyle.jz); SpreadJsObj.initSheet(billsSheet, billsSpreadSetting); const posSpread = SpreadJsObj.createNewSpread($('#pos-spread')[0]); const posSheet = posSpread.getActiveSheet(); SpreadJsObj.initSheet(posSheet, posSpreadSetting); const treeSetting = { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', full_path: 'full_path', rootId: -1, keys: ['id', 'tender_id', 'ledger_id'], calcFields: ['sum_tp'], // todo 判断同一清单时,是否应区分 清单是否含计量单元? // findNode: function(tree, node, parent, source) { // const siblings = parent ? parent.children : tree.children; // const checkData = { code: node.code || '', b_code: node.b_code || '', name: node.name || '', unit: node.unit || '', unit_price: node.unit_price || 0 }; // return siblings.find(function (x) { // if (!checkData.b_code) return x.code === checkData.code && x.name === checkData.name; // const posRange = source.pos.getLedgerPos(node.id); // const hasPos = posRange && posRange.length > 0; // const xHasPos = x.pos && x.pos.length > 0; // return hasPos === xHasPos && x.b_code === checkData.b_code && x.name === checkData.name && x.unit === checkData.unit && x.unit_price === checkData.unit_price; // }); // }, loadInfo: function (node, sourceNode, index, source) { for (const f of billsCompareField) { node[f + '_' + index] = sourceNode[f]; } const posRange = source.pos.getLedgerPos(sourceNode.id); if (posRange && posRange.length > 0) { if (!node.pos) node.pos = []; for (const p of posRange) { let nP = _.find(node.pos, {name: p.name || ''}); if (!nP) { nP = {name: p.name || ''}; node.pos.push(nP); } for (const f of posCompareField) { nP[f + '_' + index] = p[f]; } } } }, calcSum: function(data, count) { for (const f of billsCompareField) { data['sum_' + f] = 0; for (let i = 1; i <= count; i++) { data['sum_' + f] = ZhCalc.add(data['sum_' + f], data[f + '_' + i]); } } for (const p of data.pos) { for (const f of posCompareField) { p['sum_' + f] = 0; for (let i = 1; i <= count; i++) { p['sum_' + f] = ZhCalc.add(p['sum_' + f], p[f + '_' + i]); } } } }, }; const billsTree = createNewPathTree('tree-gather', treeSetting); const billsTreeSpreadObj = { selectionChanged: function (e, info) { if (info.newSelections) { if (!info.oldSelections || info.newSelections[0].row !== info.oldSelections[0].row) { posSpreadObj.loadCurPosData(); } } }, rebuildSpreadSetting(tenders) { billsSpreadSetting.cols = [...billsSpreadSetting.baseCols]; posSpreadSetting.cols = [...posSpreadSetting.baseCols]; for (const [i, tender] of tenders.entries()) { for (const col of billsSpreadSetting.extraCols) { const newCol = JSON.parse(JSON.stringify(col)); if (newCol.formatTitle) newCol.title = newCol.formatTitle.replace('%s', tender.name); if (newCol.formatField) newCol.field = newCol.formatField.replace('%d', i + 1); billsSpreadSetting.cols.push(newCol); } for (const col of posSpreadSetting.extraCols) { const newCol = JSON.parse(JSON.stringify(col)); if (newCol.formatTitle) newCol.title = newCol.formatTitle.replace('%s', tender.name); if (newCol.formatField) newCol.field = newCol.formatField.replace('%d', i + 1); posSpreadSetting.cols.push(newCol) } } billsSpreadSetting.cols.push(...billsSpreadSetting.endCols); posSpreadSetting.cols.push(...posSpreadSetting.endCols); } }; billsSpread.bind(spreadNS.Events.SelectionChanged, billsTreeSpreadObj.selectionChanged); const posSpreadObj = { loadCurPosData: function () { const node = SpreadJsObj.getSelectObject(billsSheet); console.log(node); if (node) { SpreadJsObj.loadSheetData(posSheet, 'data', node.pos || []); } else { SpreadJsObj.loadSheetData(posSheet, 'data', []); } }, }; const tenderSelect = TenderSelectMulti({ title: '汇总标段', type: 'gather', dataType: 'ledger', afterSelect: function(select) { const data = { filter: 'ledger', tender: select }; postData(`/sp/${spid}/spss/load`, data, function(result) { billsTreeSpreadObj.rebuildSpreadSetting(result); SpreadJsObj.reLoadSheetHeader(billsSheet); SpreadJsObj.reLoadSheetHeader(posSheet); treeSetting.calcFields = ['sum_total_price']; for (let i = 1; i <= result.length; i++) { treeSetting.calcFields.push('total_price_' + i); } const tenderTreeSetting = { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, keys: ['id', 'tender_id', 'ledger_id'], calcFields: ['total_price'], }; const posSetting = { id: 'id', ledgerId: 'lid' }; const tenders = []; for (const t of result) { const tender = { billsTree: createNewPathTree('ledger', tenderTreeSetting), pos: new PosData(posSetting), }; tender.billsTree.loadDatas(t.bills); tender.pos.loadDatas(t.pos); tenders.push(tender); } billsTree.clearDatas(); billsTree.loadGatherData(tenders); treeCalc.calculateAll(billsTree); SpreadJsObj.loadSheetData(billsSheet, SpreadJsObj.DataType.Tree, billsTree, true); posSpreadObj.loadCurPosData(); }); }, }); $('#gather-select').click(tenderSelect.showSelect); $('#export-excel').click(function() { const excelData = []; for (const node of billsTree.nodes) { const data = {}; for (const c of billsSpreadSetting.cols) { data[c.field] = node[c.field]; } excelData.push(data); for (const p of node.pos) { const pData = {}; for (const c of posSpreadSetting.cols) { pData[c.field] = p[c.field]; } excelData.push(pData); } } SpreadExcelObj.exportSimpleXlsxSheet(billsSpreadSetting, excelData, "台账汇总.xlsx"); }); $.divResizer({ select: '#pos-resize', callback: function () { billsSpread.refresh(); let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0; $(".sp-wrap").height(bcontent-30); posSpread.refresh(); } }); // 显示层次 (function (select, sheet) { $(select).click(function () { if (!sheet.zh_tree) return; const tag = $(this).attr('tag'); const tree = sheet.zh_tree; switch (tag) { case "1": case "2": case "3": case "4": case "5": tree.expandByLevel(parseInt(tag)); SpreadJsObj.refreshTreeRowVisible(sheet); break; case "last": tree.expandByCustom(() => { return true; }); SpreadJsObj.refreshTreeRowVisible(sheet); break; case "leafXmj": tree.expandToLeafXmj(); SpreadJsObj.refreshTreeRowVisible(sheet); break; case "differ": tree.expandByCustom(function (x) { const posterity = tree.getPosterity(x); if (posterity.length === 0) return x.differ_qty || x.differ_tp; for (const p of posterity) { if (x.differ_qty || x.differ_tp) return true; } return false; }); SpreadJsObj.refreshTreeRowVisible(sheet); } }); })('a[name=showLevel]', billsSheet); $.subMenu({ menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list', toMenu: '#to-menu', toMiniMenu: '#to-mini-menu', key: 'menu.1.0.0', miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1', callback: function (info) { if (info.mini) { $('.panel-title').addClass('fluid'); $('#sub-menu').removeClass('panel-sidebar'); $('.c-body table thead').css('left', '56px'); } else { $('.panel-title').removeClass('fluid'); $('#sub-menu').addClass('panel-sidebar'); $('.c-body table thead').css('left', '176px'); } autoFlashHeight(); billsSpread.refresh(); posSpread.refresh(); } }); });