// 配置方法
const tableSettings = computed(() => {
return {
...hotTableParams,
nestedHeaders: false,
filters: false,
columnSorting: false,
height: 358,
rowHeaders: false,
colHeaders: [
'企业名称',
'类型',
'1月',
'2月',
'3月',
'4月',
'5月',
'6月',
'7月',
'8月',
'9月',
'10月',
'11月',
'12月',
'操作',
],
columns: [
{
data: 'name',
className: 'htCenter htMiddle',
readOnly: false, // 企业名称固定只读
},
{
data: 'type',
className: 'htCenter htMiddle',
readOnly: true, // 类型(电量/电价)固定只读
},
// 月份列(可编辑)
{ data: 'one', type: 'numeric', className: 'htRight' },
{ data: 'two', type: 'numeric', className: 'htRight' },
{ data: 'three', type: 'numeric', className: 'htRight' },
{ data: 'four', type: 'numeric', className: 'htRight' },
{ data: 'five', type: 'numeric', className: 'htRight' },
{ data: 'six', type: 'numeric', className: 'htRight' },
{ data: 'seven', type: 'numeric', className: 'htRight' },
{ data: 'eight', type: 'numeric', className: 'htRight' },
{ data: 'nine', type: 'numeric', className: 'htRight' },
{ data: 'ten', type: 'numeric', className: 'htRight' },
{ data: 'eleven', type: 'numeric', className: 'htRight' },
{ data: 'twelve', type: 'numeric', className: 'htRight' },
// 操作列(自定义渲染+合并)
{
renderer: (instance, td, row) => {
td.innerHTML = '';
if(props.isEdit) return td;
if(row === 0 || row === 1) return td;
if(row % 2 === 0) {
const container = document.createElement('div');
container.style.width = '100%';
container.style.height = '100%';
container.style.display = 'flex';
container.style.alignItems = 'center';
container.style.justifyContent = 'center';
container.style.gap = '8px';
// 新增按钮
const addBtn = document.createElement('span');
addBtn.className = 'mdi mdi-plus';
addBtn.style.fontSize = '18px';
addBtn.style.width = '18px';
addBtn.style.height = '18px';
addBtn.style.cursor = 'pointer';
addBtn.style.display = 'flex';
addBtn.style.alignItems = 'center';
addBtn.style.justifyContent = 'center';
addBtn.onclick = (e) => {
e.stopPropagation();
const hot = instance;
const currentRow = row;
hot.alter('insert_row_below', currentRow + 1, 2);
hot.setDataAtCell(currentRow + 2, 0, '');
hot.setDataAtCell(currentRow + 2, 1, '电量');
hot.setDataAtCell(currentRow + 3, 0, '');
hot.setDataAtCell(currentRow + 3, 1, '电价');
const currentMergedCells = [
...hot.getPlugin('mergeCells').mergedCellsCollection
.mergedCells,
];
currentMergedCells.push(
{ row: currentRow + 2, col: 0, rowspan: 2, colspan: 1 },
{ row: currentRow + 2, col: 14, rowspan: 2, colspan: 1 },
);
hot.updateSettings({ mergeCells: currentMergedCells });
};
// 删除按钮
const delBtn = document.createElement('span');
delBtn.className = 'mdi mdi-trash-can-outline';
delBtn.style.fontSize = '18px';
delBtn.style.width = '18px';
delBtn.style.height = '18px';
delBtn.style.cursor = 'pointer';
delBtn.style.display = 'flex';
delBtn.style.alignItems = 'center';
delBtn.style.justifyContent = 'center';
delBtn.onclick = (e) => {
e.stopPropagation();
const hot = instance;
if(hot.countRows() <= 4) return;
const currentRow = row;
const rowsToRemove = 2;
// 1. 获取原始合并规则并深拷贝
const mergeCellsPlugin = hot.getPlugin('mergeCells');
const originalMerged = JSON.parse(
JSON.stringify(
mergeCellsPlugin.mergedCellsCollection.mergedCells,
),
);
// 2. 删除2行
hot.alter('remove_row', currentRow, rowsToRemove);
// 3. 处理合并规则:过滤重复 + 位移行索引
const updatedMerged = originalMerged
.filter(
(cell) =>
!(
cell.row >= currentRow &&
cell.row < currentRow + rowsToRemove
),
) // 过滤已删除行的规则
.map((cell) => {
if(cell.row > currentRow) {
return { ...cell, row: cell.row - rowsToRemove }; // 后续规则行索引减2
}
return cell;
})
// 去重:确保每个(row, col)组合唯一
.filter((cell, index, self) => {
return (
self.findIndex(
(c) => c.row === cell.row && c.col === cell.col,
) === index
);
});
// 4. 重新设置合并规则
hot.updateSettings({ mergeCells: updatedMerged });
};
container.appendChild(addBtn);
container.appendChild(delBtn);
td.appendChild(container);
}
else {
td.style.visibility = 'visible';
td.style.pointerEvents = 'none';
}
return td;
},
},
],
dropdownMenu: false,
cells: (row, col) => {
// 合计行(0、1行)所有单元格只读
if(row === 0 || row === 1 || col === 14) {
return { readOnly: true };
}
// 企业名称列(0列)和类型列(1列)只读
if(
((col === 0 || col === 1) && (row === 0 || row === 1)) ||
col === 1 ||
col === 14
) {
return { readOnly: true };
}
return { readOnly: props.isEdit };
},
mergeCells: true,
async afterChange(changes) {
if(!changes || changes.length === 0) return;
const hot = this; // Handsontable实例
const data = hot.getSourceData(); // 表格原始数据
// 定义月份字段映射(与columns中“1月-12月”的data属性对应)
const monthFields = [
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten',
'eleven',
'twelve',
];
// 遍历每个月份,分别计算“电量合计”和“电价合计”
monthFields.forEach((field) => {
let elecSum = 0; // 电量合计
let priceSum = 0; // 电价合计
// 遍历所有企业行(跳过前2行“合计行”)
for(let i = 2; i < data.length; i += 2) {
// 电量行(类型为“电量”)
const elecRow = data[i];
elecSum += Number(elecRow[field] || 0); // 确保转为数字
// 电价行(类型为“电价”)
const priceRow = data[i + 1];
priceSum += Number(priceRow[field] || 0); // 确保转为数字
}
// 更新“合计行”的对应月份值
data[0][field] = elecSum; // 电量合计行(第0行)
data[1][field] = priceSum; // 电价合计行(第1行)
});
let totalElecSum = 0; // 总电量合计(所有月份电量合计的总和)
let weightedPriceSum = 0; // 加权电价合计
// 1. 计算总电量(合计行的电量总和)
monthFields.forEach((field) => {
totalElecSum += Number(data[0]?.[field] || 0); // 用可选链操作符?.避免data[0]为undefined
});
// 2. 遍历所有企业行,计算加权电价
for(let i = 2; i < data.length; i += 2) { // 企业行是“电量行+电价行”,每次跳2行
monthFields.forEach((field) => {
const enterpriseElec = Number(data[i]?.[field] || 0); // 企业当月电量(防undefined)
const enterprisePrice = Number(data[i + 1]?.[field] || 0); // 企业当月电价(防undefined)
if(totalElecSum > 0) {
const weight = enterpriseElec / totalElecSum; // 企业电量占总电量的权重
weightedPriceSum += enterprisePrice * weight; // 累加该企业的加权电价
}
});
}
// 更新总合计值
totalElec.value = totalElecSum;
totalPrice.value = weightedPriceSum.toFixed(2);
// 重新渲染表格(确保合计值显示)
hot.loadData(data);
},
};
});
浙公网安备 33010602011771号