Files
ylt_diy/public/static/js/sum_data.js

851 lines
34 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 求和数据管理
let sumDataCurrentPage = 1;
let sumDataPageSize = 10;
let editingSumDataId = null;
let sumDataGroupedList = [];
let sumDataDynamicFields = [];
// 分组并渲染求和数据列表
function renderSumDataList(rawList) {
const tbody = document.getElementById('sum-data-list');
const totalColCount = 7 + (rawList ? 0 : 0) + 3; // 占位,后面重新计算
if (!rawList || rawList.length === 0) {
// 清空动态表头
const chargeTh = document.getElementById('th-charge-degree');
const totalOrdersTh = document.getElementById('th-total-orders');
let nextSibling = chargeTh.nextElementSibling;
while (nextSibling && nextSibling !== totalOrdersTh) {
const toRemove = nextSibling;
nextSibling = nextSibling.nextElementSibling;
toRemove.remove();
}
tbody.innerHTML = '<tr><td colspan="10" class="empty">暂无数据</td></tr>';
return;
}
// 获取全局配置的允许显示字段charge_degree 始终显示)
// 如果没有配置,则显示所有字段(向后兼容)
const hasConfig = sumDataConfigFields && sumDataConfigFields.length > 0;
const allowedFields = hasConfig ? new Set(sumDataConfigFields) : null;
// 收集所有动态求和字段(除了充电电量 charge_degree且只收集允许显示的字段
const fieldMap = {};
rawList.forEach(item => {
const key = item.sum_field_key;
if (key && key !== 'charge_degree' && !fieldMap[key]) {
// 如果配置了允许字段,则只收集允许的字段;否则收集所有字段
if (!hasConfig || allowedFields.has(key)) {
fieldMap[key] = item.sum_field_name || key;
}
}
});
// 排序:尖峰平谷按顺序
const fieldOrder = ['sharp_electricity', 'peak_electricity', 'flat_electricity', 'valley_electricity'];
sumDataDynamicFields = Object.keys(fieldMap).sort((a, b) => {
const idxA = fieldOrder.indexOf(a);
const idxB = fieldOrder.indexOf(b);
if (idxA >= 0 && idxB >= 0) return idxA - idxB;
if (idxA >= 0) return -1;
if (idxB >= 0) return 1;
return a.localeCompare(b);
});
// 渲染动态列表头(在充电电量列之后插入)
const chargeTh = document.getElementById('th-charge-degree');
const totalOrdersTh = document.getElementById('th-total-orders');
// 先移除旧的动态 th充电电量和订单数之间的
let nextSibling = chargeTh.nextElementSibling;
while (nextSibling && nextSibling !== totalOrdersTh) {
const toRemove = nextSibling;
nextSibling = nextSibling.nextElementSibling;
toRemove.remove();
}
// 插入新的动态 th
sumDataDynamicFields.forEach(key => {
const name = fieldMap[key];
const th = document.createElement('th');
th.style.minWidth = '110px';
th.textContent = name;
totalOrdersTh.before(th);
});
// 按 报表日期 + 配置ID + 拆分值 分组
const groupMap = {};
rawList.forEach(item => {
const groupKey = `${item.report_date}_${item.config_id}_${item.split_value}`;
if (!groupMap[groupKey]) {
groupMap[groupKey] = {
report_date: item.report_date,
config_id: item.config_id,
config_name: item.config_name,
split_type: item.split_type,
split_value: item.split_value,
split_name: item.split_name,
sort_order: item.sort_order || 9999,
total_orders: item.total_orders || 0,
data_source: item.data_source,
remark: item.remark || '',
fields: {},
ids: []
};
}
groupMap[groupKey].fields[item.sum_field_key] = {
value: item.sum_value,
id: item.id,
name: item.sum_field_name
};
groupMap[groupKey].ids.push(item.id);
// 取最新的备注和数据来源
if (item.remark) groupMap[groupKey].remark = item.remark;
if (item.data_source === 'manual') groupMap[groupKey].data_source = 'manual';
});
sumDataGroupedList = Object.values(groupMap).sort((a, b) => {
if (a.report_date !== b.report_date) return b.report_date.localeCompare(a.report_date);
return (a.sort_order || 9999) - (b.sort_order || 9999);
});
// 分页处理
const total = sumDataGroupedList.length;
const start = (sumDataCurrentPage - 1) * sumDataPageSize;
const pageData = sumDataGroupedList.slice(start, start + sumDataPageSize);
const totalColSpan = 9 + sumDataDynamicFields.length; // 复选+日期+配置+拆分值+充电电量+动态列+订单数+来源+备注+操作
if (pageData.length === 0) {
tbody.innerHTML = `<tr><td colspan="${totalColSpan}" class="empty">暂无数据</td></tr>`;
renderSumDataPagination(total);
return;
}
tbody.innerHTML = pageData.map(group => {
const chargeDegree = group.fields['charge_degree'];
const chargeValue = chargeDegree && chargeDegree.value !== null && chargeDegree.value !== undefined
? Number(chargeDegree.value).toFixed(3) : '-';
const dataSource = group.data_source === 'auto' ? '自动采集' : '手动编辑';
const dataSourceClass = group.data_source === 'auto' ? 'status-active' : 'status-inactive';
const remark = group.remark || '-';
const dynamicCells = sumDataDynamicFields.map(key => {
const field = group.fields[key];
const val = field && field.value !== null && field.value !== undefined
? Number(field.value).toFixed(3) : '-';
return `<td>${val}</td>`;
}).join('');
const firstId = chargeDegree ? chargeDegree.id : (group.ids[0] || 0);
return `
<tr>
<td><input type="checkbox" class="sum-data-checkbox" value="${group.ids.join(',')}"></td>
<td>${group.report_date || '-'}</td>
<td>${group.config_name || '-'}</td>
<td title="${group.split_name || ''}">${group.split_name || group.split_value || '-'}</td>
<td style="background: #f8fafc; font-weight: 600; color: #1d4ed8;">${chargeValue}</td>
${dynamicCells}
<td>${group.total_orders || 0}</td>
<td><span class="status-badge ${dataSourceClass}">${dataSource}</span></td>
<td title="${remark}" style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${remark}</td>
<td>
<button class="btn btn-sm btn-primary" onclick='showEditSumDataGroup(${JSON.stringify(group.ids)})'>编辑</button>
<button class="btn btn-sm btn-danger" onclick='deleteSumDataGroup(${JSON.stringify(group.ids)})'>删除</button>
</td>
</tr>
`;
}).join('');
renderSumDataPagination(total);
}
// 渲染分页
function renderSumDataPagination(total) {
const pagination = document.getElementById('sum-data-pagination');
const totalPages = Math.ceil(total / sumDataPageSize);
if (totalPages <= 1) {
pagination.innerHTML = '';
return;
}
let html = '';
if (sumDataCurrentPage > 1) {
html += `<button class="btn btn-sm" onclick="loadSumData(${sumDataCurrentPage - 1})">上一页</button>`;
}
html += `<span class="page-info">第 ${sumDataCurrentPage} / ${totalPages} 页,共 ${total} 条</span>`;
if (sumDataCurrentPage < totalPages) {
html += `<button class="btn btn-sm" onclick="loadSumData(${sumDataCurrentPage + 1})">下一页</button>`;
}
pagination.innerHTML = html;
}
// 加载求和数据
async function loadSumData(page = 1) {
sumDataCurrentPage = page;
const startDate = document.getElementById('sum-data-start-date').value;
const endDate = document.getElementById('sum-data-end-date').value;
const configName = document.getElementById('sum-data-config-name').value;
const dataSource = document.getElementById('sum-data-source').value;
const listTbody = document.getElementById('sum-data-list');
if (listTbody) {
listTbody.innerHTML = '<tr><td colspan="12" class="loading">加载中...</td></tr>';
}
// 先加载全局配置
try {
const configResponse = await fetch('/api/global-config/sum-data-fields?_t=' + Date.now());
const configResult = await configResponse.json();
if (configResult.success) {
sumDataConfigFields = configResult.data || [];
}
} catch (error) {
console.log('加载全局配置失败:', error);
}
const params = new URLSearchParams();
params.append('page_size', '1000');
if (startDate) params.append('start_date', startDate);
if (endDate) params.append('end_date', endDate);
if (configName) params.append('config_name', configName);
if (dataSource) params.append('data_source', dataSource);
try {
const response = await fetch(`/api/sum-data?${params.toString()}&_t=${Date.now()}`);
const result = await response.json();
if (result.success) {
renderSumDataList(result.data.list || []);
} else {
if (listTbody) {
listTbody.innerHTML = '<tr><td colspan="12" class="empty">加载失败: ' + (result.message || '未知错误') + '</td></tr>';
}
}
} catch (error) {
if (listTbody) {
listTbody.innerHTML = '<tr><td colspan="12" class="empty">加载失败: ' + error.message + '</td></tr>';
}
}
}
// 清除查询
function clearSumDataQuery() {
document.getElementById('sum-data-start-date').value = '';
document.getElementById('sum-data-end-date').value = '';
document.getElementById('sum-data-config-name').value = '';
document.getElementById('sum-data-source').value = '';
loadSumData(1);
}
// 全选/取消全选
function toggleSelectAllSumData() {
const checked = document.getElementById('select-all-sum-data').checked;
document.querySelectorAll('.sum-data-checkbox').forEach(cb => {
cb.checked = checked;
});
}
// 从历史记录采集
async function collectSumDataFromHistory() {
const startDate = document.getElementById('sum-data-start-date').value;
const endDate = document.getElementById('sum-data-end-date').value;
if (!startDate || !endDate) {
showToast('请先选择日期范围');
return;
}
if (!confirm(`确定要从 ${startDate}${endDate} 的历史记录中采集求和数据吗?\n(会先清除该日期范围内旧的自动采集数据)`)) return;
const resultDiv = document.getElementById('sum-data-list');
resultDiv.innerHTML = '<tr><td colspan="12" class="empty">正在采集中,请稍候...</td></tr>';
try {
const response = await fetch('/api/sum-data/collect', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
start_date: startDate,
end_date: endDate
})
});
const result = await response.json();
if (result.success) {
showToast(result.message);
loadSumData(1);
} else {
showToast('采集失败: ' + (result.message || '未知错误'));
loadSumData(1);
}
} catch (error) {
showToast('采集失败: ' + error.message);
loadSumData(1);
}
}
// 显示添加模态框
function showAddSumDataModal() {
editingSumDataId = null;
document.getElementById('sum-data-modal-title').textContent = '手动添加求和数据';
document.getElementById('sum-data-id').value = '';
document.getElementById('sum-data-report-date-input').value = '';
document.getElementById('sum-data-config-name-input').value = '';
document.getElementById('sum-data-split-type-input').value = 'company_id';
document.getElementById('sum-data-split-value-input').value = '';
document.getElementById('sum-data-split-name-input').value = '';
document.getElementById('sum-data-charge-degree-input').value = '';
document.getElementById('sum-data-peak-degree-input').value = '';
document.getElementById('sum-data-peak-time-input').value = '';
document.getElementById('sum-data-normal-time-input').value = '';
document.getElementById('sum-data-valley-time-input').value = '';
document.getElementById('sum-data-total-orders-input').value = 0;
document.getElementById('sum-data-remark-input').value = '';
document.getElementById('sum-data-modal').classList.add('active');
}
// 显示编辑分组模态框
let editingGroupIds = [];
let editingGroupData = null;
async function showEditSumDataGroup(ids) {
try {
const response = await fetch('/api/sum-data/batch-query', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: ids })
});
const result = await response.json();
if (!result.success) {
showToast('加载详情失败');
return;
}
const groupItems = result.data || [];
if (groupItems.length === 0) {
showToast('未找到该记录');
return;
}
editingGroupIds = ids;
editingGroupData = groupItems;
const chargeItem = groupItems.find(i => i.sum_field_key === 'charge_degree') || groupItems[0];
document.getElementById('sum-data-modal-title').textContent = '编辑求和数据';
document.getElementById('sum-data-id').value = chargeItem.id;
document.getElementById('sum-data-report-date-input').value = chargeItem.report_date || '';
document.getElementById('sum-data-config-name-input').value = chargeItem.config_name || '';
document.getElementById('sum-data-split-type-input').value = chargeItem.split_type || 'company_id';
document.getElementById('sum-data-split-value-input').value = chargeItem.split_value || '';
document.getElementById('sum-data-split-name-input').value = chargeItem.split_name || '';
renderEditGroupFields(groupItems);
document.getElementById('sum-data-total-orders-input').value = chargeItem.total_orders || 0;
document.getElementById('sum-data-remark-input').value = chargeItem.remark || '';
document.getElementById('sum-data-modal').classList.add('active');
} catch (error) {
showToast('加载详情失败: ' + error.message);
}
}
// 渲染编辑分组时的动态字段输入
function renderEditGroupFields(items) {
// 隐藏静态字段输入区域(整个求和字段值区域)
const chargeDegreeInput = document.getElementById('sum-data-charge-degree-input');
if (chargeDegreeInput) {
chargeDegreeInput.parentElement.parentElement.parentElement.style.display = 'none';
}
// 先构造动态字段区域
let fieldsHtml = '<div style="margin-bottom: 15px;"><label style="display: block; margin-bottom: 8px; font-weight: 600;">求和字段值:</label>';
fieldsHtml += '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">';
// 先放充电电量
const chargeItem = items.find(i => i.sum_field_key === 'charge_degree');
if (chargeItem) {
fieldsHtml += `
<div class="form-group" style="margin-bottom: 0;">
<label>${chargeItem.sum_field_name || chargeItem.sum_field_key} (必选)</label>
<input type="number" step="0.001" class="form-control"
data-field-key="${chargeItem.sum_field_key}"
data-field-name="${chargeItem.sum_field_name || chargeItem.sum_field_key}"
data-field-id="${chargeItem.id}"
value="${chargeItem.sum_value || 0}">
</div>
`;
}
// 再放其他字段
items.filter(i => i.sum_field_key !== 'charge_degree').forEach(item => {
fieldsHtml += `
<div class="form-group" style="margin-bottom: 0;">
<label>${item.sum_field_name || item.sum_field_key}</label>
<input type="number" step="0.001" class="form-control"
data-field-key="${item.sum_field_key}"
data-field-name="${item.sum_field_name || item.sum_field_key}"
data-field-id="${item.id}"
value="${item.sum_value || 0}">
</div>
`;
});
fieldsHtml += '</div></div>';
// 插入到订单数前面
const totalOrdersGroup = document.getElementById('sum-data-total-orders-input').parentElement;
// 检查是否已经有动态区域了
let dynamicArea = document.getElementById('sum-data-dynamic-fields');
if (!dynamicArea) {
dynamicArea = document.createElement('div');
dynamicArea.id = 'sum-data-dynamic-fields';
totalOrdersGroup.parentElement.insertBefore(dynamicArea, totalOrdersGroup);
}
dynamicArea.innerHTML = fieldsHtml;
}
// 保存求和数据(支持分组编辑)
async function saveSumData() {
const remark = document.getElementById('sum-data-remark-input').value;
// 编辑时修改原因为必填
if (editingGroupIds && editingGroupIds.length > 0 && !remark.trim()) {
showToast('请填写修改原因');
return;
}
const totalOrders = document.getElementById('sum-data-total-orders-input').value;
try {
// 分组编辑模式
if (editingGroupIds && editingGroupIds.length > 0) {
let needCreateNew = false; // 是否需要创建新记录(删除了自动采集记录时)
// 先获取分组信息,确定需要删除的自动采集记录
if (editingGroupData && editingGroupData.length > 0) {
const chargeItem = editingGroupData.find(i => i.sum_field_key === 'charge_degree') || editingGroupData[0];
// 查询该分组下所有自动采集的记录
const deleteResponse = await fetch('/api/sum-data/batch-query', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
conditions: {
report_date: chargeItem.report_date,
config_id: chargeItem.config_id,
split_type: chargeItem.split_type,
split_value: chargeItem.split_value,
data_source: 'auto'
}
})
});
const deleteResult = await deleteResponse.json();
// 如果有自动采集记录,删除它们并标记需要创建新记录
if (deleteResult.success && deleteResult.data && deleteResult.data.length > 0) {
const autoIds = deleteResult.data.map(d => d.id);
for (const autoId of autoIds) {
await fetch(`/api/sum-data/${autoId}`, { method: 'DELETE' });
}
console.log(`已删除 ${autoIds.length} 条自动采集记录`);
needCreateNew = true;
}
}
// 读取动态字段值
const fieldInputs = document.querySelectorAll('#sum-data-dynamic-fields input[data-field-key]');
let successCount = 0;
if (needCreateNew) {
// 自动采集记录已删除,需要创建新的手动记录
if (editingGroupData && editingGroupData.length > 0) {
const chargeItem = editingGroupData.find(i => i.sum_field_key === 'charge_degree') || editingGroupData[0];
// 收集所有字段
const fieldsData = [];
for (const input of fieldInputs) {
fieldsData.push({
sum_field_key: input.getAttribute('data-field-key'),
sum_field_name: input.getAttribute('data-field-name') || input.getAttribute('data-field-key'),
sum_value: parseFloat(input.value) || 0
});
}
// 批量新增手动记录
const response = await fetch('/api/sum-data/batch-add', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
report_date: chargeItem.report_date,
config_id: chargeItem.config_id,
config_name: chargeItem.config_name,
split_type: chargeItem.split_type,
split_value: chargeItem.split_value,
split_name: chargeItem.split_name,
total_orders: parseInt(totalOrders) || 0,
data_source: 'manual',
remark: remark,
fields: fieldsData
})
});
const result = await response.json();
if (result.success) {
successCount = fieldsData.length;
}
console.log(`新增手动记录结果: ${JSON.stringify(result)}`);
}
} else {
// 原记录是手动的,直接更新
for (const input of fieldInputs) {
const fieldId = input.getAttribute('data-field-id');
const fieldValue = input.value;
console.log(`更新字段ID: ${fieldId}, 值: ${fieldValue}`);
const response = await fetch(`/api/sum-data/${fieldId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sum_value: fieldValue,
total_orders: totalOrders,
remark: remark,
data_source: 'manual'
})
});
const result = await response.json();
console.log(`更新结果: ${JSON.stringify(result)}`);
if (result.success) successCount++;
}
}
if (successCount > 0) {
showToast(`更新成功(${successCount} 个字段)`);
closeSumDataModal();
loadSumData(sumDataCurrentPage);
} else {
showToast('更新失败');
}
return;
}
// 单条新增模式(批量添加多个字段)
const fieldsData = [];
const chargeDegree = document.getElementById('sum-data-charge-degree-input').value;
const peakDegree = document.getElementById('sum-data-peak-degree-input').value;
const peakTime = document.getElementById('sum-data-peak-time-input').value;
const normalTime = document.getElementById('sum-data-normal-time-input').value;
const valleyTime = document.getElementById('sum-data-valley-time-input').value;
if (!chargeDegree && !peakDegree && !peakTime && !normalTime && !valleyTime) {
showToast('请至少输入一个求和字段值');
return;
}
if (chargeDegree) {
fieldsData.push({
sum_field_key: 'charge_degree',
sum_field_name: '充电电量(kWh)',
sum_value: chargeDegree
});
}
if (peakDegree) {
fieldsData.push({
sum_field_key: 'sharp_electricity',
sum_field_name: '尖时电量(kWh)',
sum_value: peakDegree
});
}
if (peakTime) {
fieldsData.push({
sum_field_key: 'peak_electricity',
sum_field_name: '峰时电量(kWh)',
sum_value: peakTime
});
}
if (normalTime) {
fieldsData.push({
sum_field_key: 'flat_electricity',
sum_field_name: '平时电量(kWh)',
sum_value: normalTime
});
}
if (valleyTime) {
fieldsData.push({
sum_field_key: 'valley_electricity',
sum_field_name: '谷时电量(kWh)',
sum_value: valleyTime
});
}
const data = {
report_date: document.getElementById('sum-data-report-date-input').value,
config_name: document.getElementById('sum-data-config-name-input').value,
split_type: document.getElementById('sum-data-split-type-input').value,
split_value: document.getElementById('sum-data-split-value-input').value,
split_name: document.getElementById('sum-data-split-name-input').value,
total_orders: totalOrders,
remark: remark,
fields: fieldsData
};
if (!data.report_date) {
showToast('请选择报表日期');
return;
}
const response = await fetch('/api/sum-data/batch-add', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const result = await response.json();
if (result.success) {
showToast('添加成功');
closeSumDataModal();
loadSumData(sumDataCurrentPage);
} else {
showToast('保存失败: ' + (result.message || '未知错误'));
}
} catch (error) {
showToast('保存失败: ' + error.message);
}
}
// 关闭模态框
function closeSumDataModal() {
document.getElementById('sum-data-modal').classList.remove('active');
editingGroupIds = [];
editingGroupData = null;
// 清空新增字段输入
document.getElementById('sum-data-charge-degree-input').value = '';
document.getElementById('sum-data-peak-degree-input').value = '';
document.getElementById('sum-data-peak-time-input').value = '';
document.getElementById('sum-data-normal-time-input').value = '';
document.getElementById('sum-data-valley-time-input').value = '';
// 恢复静态字段区域显示
const chargeDegreeInput = document.getElementById('sum-data-charge-degree-input');
if (chargeDegreeInput) {
chargeDegreeInput.parentElement.parentElement.parentElement.style.display = '';
}
// 清理动态区域
const dynamicArea = document.getElementById('sum-data-dynamic-fields');
if (dynamicArea) {
dynamicArea.remove();
}
}
// 删除单条(分组)
async function deleteSumDataGroup(ids) {
if (!confirm(`确定要删除这组求和数据吗?(共 ${ids.length} 条字段记录)`)) return;
try {
let success = true;
for (const id of ids) {
const response = await fetch(`/api/sum-data/${id}`, { method: 'DELETE' });
const result = await response.json();
if (!result.success) success = false;
}
if (success) {
showToast('删除成功');
loadSumData(sumDataCurrentPage);
} else {
showToast('部分删除失败');
}
} catch (error) {
showToast('删除失败: ' + error.message);
}
}
// 兼容旧函数名
function deleteSumData(id) {
deleteSumDataGroup([id]);
}
// 批量删除
async function batchDeleteSumData() {
const checkboxes = document.querySelectorAll('.sum-data-checkbox:checked');
if (checkboxes.length === 0) {
showToast('请选择要删除的记录');
return;
}
const ids = [];
checkboxes.forEach(cb => {
const val = cb.value;
if (val.indexOf(',') >= 0) {
val.split(',').forEach(id => ids.push(parseInt(id)));
} else {
ids.push(parseInt(val));
}
});
if (!confirm(`确定要删除选中的 ${ids.length} 条求和数据吗?`)) return;
try {
const response = await fetch('/api/sum-data/batch-delete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ids: ids })
});
const result = await response.json();
if (result.success) {
showToast('删除成功');
loadSumData(sumDataCurrentPage);
} else {
showToast('删除失败: ' + (result.message || '未知错误'));
}
} catch (error) {
showToast('删除失败: ' + error.message);
}
}
async function exportSumData() {
const startDate = document.getElementById('sum-data-start-date').value;
const endDate = document.getElementById('sum-data-end-date').value;
const configName = document.getElementById('sum-data-config-name').value;
const dataSource = document.getElementById('sum-data-source').value;
const params = new URLSearchParams();
if (startDate) params.append('start_date', startDate);
if (endDate) params.append('end_date', endDate);
if (configName) params.append('keyword', configName);
if (dataSource) params.append('data_source', dataSource);
try {
const response = await fetch(`/api/sum-data/export?${params.toString()}`);
const result = await response.json();
if (result.success) {
if (result.total === 0) {
showToast('没有可导出的数据');
return;
}
const a = document.createElement('a');
a.href = result.file_path;
a.download = result.filename || '求和数据导出.xlsx';
a.target = '_blank';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} else {
showToast('导出失败: ' + (result.message || '未知错误'));
}
} catch (error) {
showToast('导出失败: ' + error.message);
}
}
// 求和数据可配置的采集字段列表
const SUM_DATA_AVAILABLE_FIELDS = [
{ key: 'sharp_electricity', name: '尖时电量(kWh)' },
{ key: 'peak_electricity', name: '峰时电量(kWh)' },
{ key: 'flat_electricity', name: '平时电量(kWh)' },
{ key: 'valley_electricity', name: '谷时电量(kWh)' },
{ key: 'charge_elecfee_amount', name: '实收电费(元)' },
{ key: 'charge_servicefee_amount', name: '实收服务费(元)' },
{ key: 'charge_amount', name: '实收总金额(元)' },
{ key: 'charge_frequency', name: '充电次数' },
{ key: 'custom_service_fee', name: '自定义服务费(元)' },
{ key: 'custom_total_amount', name: '自定义实收总金额(元)' }
];
let sumDataConfigFields = [];
// 初始化全局配置
async function initSumDataConfig() {
try {
const response = await fetch('/api/global-config/sum-data-fields?_t=' + Date.now());
const result = await response.json();
if (result.success) {
sumDataConfigFields = result.data || [];
}
} catch (error) {
console.log('初始化全局配置失败:', error);
}
}
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', initSumDataConfig);
// 显示求和数据全局配置模态框
async function showSumDataConfigModal() {
const modal = document.getElementById('sum-data-config-modal');
const fieldsList = document.getElementById('sum-data-config-fields-list');
fieldsList.innerHTML = '<div class="loading">加载中...</div>';
try {
const response = await fetch('/api/global-config/sum-data-fields?_t=' + Date.now());
const result = await response.json();
if (result.success) {
sumDataConfigFields = result.data || [];
renderSumDataConfigFields(sumDataConfigFields);
} else {
fieldsList.innerHTML = '<div class="empty">加载失败</div>';
}
} catch (error) {
fieldsList.innerHTML = '<div class="empty">加载失败: ' + error.message + '</div>';
}
modal.classList.add('active');
}
// 关闭求和数据全局配置模态框
function closeSumDataConfigModal() {
document.getElementById('sum-data-config-modal').classList.remove('active');
}
// 渲染求和数据配置字段列表
function renderSumDataConfigFields(selectedFields) {
const fieldsList = document.getElementById('sum-data-config-fields-list');
fieldsList.innerHTML = SUM_DATA_AVAILABLE_FIELDS.map(field => `
<div class="checkbox-item ${selectedFields.includes(field.key) ? 'checked' : ''}" onclick="toggleSumDataConfigField(this)">
<input type="checkbox" value="${field.key}"
${selectedFields.includes(field.key) ? 'checked' : ''}>
<label>${field.name} <span class="field-key-name">(${field.key})</span></label>
</div>
`).join('');
}
// 切换求和数据配置字段选中状态
function toggleSumDataConfigField(item) {
const checkbox = item.querySelector('input[type="checkbox"]');
checkbox.checked = !checkbox.checked;
item.classList.toggle('checked', checkbox.checked);
}
// 保存求和数据全局配置
async function saveSumDataConfig() {
const checkboxes = document.querySelectorAll('#sum-data-config-fields-list input[type="checkbox"]');
const selectedFields = Array.from(checkboxes)
.filter(cb => cb.checked)
.map(cb => cb.value);
try {
const response = await fetch('/api/global-config/sum-data-fields', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ sum_data_fields: selectedFields })
});
const result = await response.json();
if (result.success) {
showToast('配置保存成功');
sumDataConfigFields = selectedFields;
closeSumDataConfigModal();
loadSumData(sumDataCurrentPage);
} else {
showToast('保存失败: ' + (result.message || '未知错误'));
}
} catch (error) {
showToast('保存失败: ' + error.message);
}
}