feat: 添加字段自定义报表名头功能
Coze-Commit-Type: user Coze-User-ID: 3722323274763196 Coze-Conversation-ID: 9894087
This commit is contained in:
15
app.py
15
app.py
@@ -67,6 +67,7 @@ def create_config():
|
|||||||
time_periods = data.get('time_periods', {})
|
time_periods = data.get('time_periods', {})
|
||||||
merge_telecom = 1 if data.get('merge_telecom') else 0
|
merge_telecom = 1 if data.get('merge_telecom') else 0
|
||||||
telecom_vehicle_no = data.get('telecom_vehicle_no', '')
|
telecom_vehicle_no = data.get('telecom_vehicle_no', '')
|
||||||
|
field_custom_names = data.get('field_custom_names', {})
|
||||||
|
|
||||||
if not config_name or not split_type or not split_value:
|
if not config_name or not split_type or not split_value:
|
||||||
return jsonify({'success': False, 'message': '缺少必填字段'}), 400
|
return jsonify({'success': False, 'message': '缺少必填字段'}), 400
|
||||||
@@ -84,8 +85,8 @@ def create_config():
|
|||||||
sql = """
|
sql = """
|
||||||
INSERT INTO t_daily_report_config
|
INSERT INTO t_daily_report_config
|
||||||
(id, config_name, split_type, split_value, split_name, selected_fields,
|
(id, config_name, split_type, split_value, split_name, selected_fields,
|
||||||
sum_fields, time_periods, merge_telecom, telecom_vehicle_no, is_active, sort_order, create_time, update_time)
|
sum_fields, time_periods, merge_telecom, telecom_vehicle_no, field_custom_names, is_active, sort_order, create_time, update_time)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 1, %s, NOW(), NOW())
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 1, %s, NOW(), NOW())
|
||||||
"""
|
"""
|
||||||
|
|
||||||
params = (
|
params = (
|
||||||
@@ -99,6 +100,7 @@ def create_config():
|
|||||||
json.dumps(time_periods, ensure_ascii=False),
|
json.dumps(time_periods, ensure_ascii=False),
|
||||||
merge_telecom,
|
merge_telecom,
|
||||||
telecom_vehicle_no,
|
telecom_vehicle_no,
|
||||||
|
json.dumps(field_custom_names, ensure_ascii=False) if field_custom_names else None,
|
||||||
sort_order
|
sort_order
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -127,12 +129,13 @@ def update_config(config_id):
|
|||||||
time_periods = data.get('time_periods', {})
|
time_periods = data.get('time_periods', {})
|
||||||
merge_telecom = 1 if data.get('merge_telecom') else 0
|
merge_telecom = 1 if data.get('merge_telecom') else 0
|
||||||
telecom_vehicle_no = data.get('telecom_vehicle_no', '')
|
telecom_vehicle_no = data.get('telecom_vehicle_no', '')
|
||||||
|
field_custom_names = data.get('field_custom_names', {})
|
||||||
|
|
||||||
sql = """
|
sql = """
|
||||||
UPDATE t_daily_report_config
|
UPDATE t_daily_report_config
|
||||||
SET config_name = %s, split_type = %s, split_value = %s, split_name = %s,
|
SET config_name = %s, split_type = %s, split_value = %s, split_name = %s,
|
||||||
selected_fields = %s, sum_fields = %s, time_periods = %s,
|
selected_fields = %s, sum_fields = %s, time_periods = %s,
|
||||||
merge_telecom = %s, telecom_vehicle_no = %s, update_time = NOW()
|
merge_telecom = %s, telecom_vehicle_no = %s, field_custom_names = %s, update_time = NOW()
|
||||||
WHERE id = %s
|
WHERE id = %s
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -146,6 +149,7 @@ def update_config(config_id):
|
|||||||
json.dumps(time_periods, ensure_ascii=False),
|
json.dumps(time_periods, ensure_ascii=False),
|
||||||
merge_telecom,
|
merge_telecom,
|
||||||
telecom_vehicle_no,
|
telecom_vehicle_no,
|
||||||
|
json.dumps(field_custom_names, ensure_ascii=False) if field_custom_names else None,
|
||||||
config_id
|
config_id
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -188,8 +192,8 @@ def copy_config(config_id):
|
|||||||
# 插入新配置
|
# 插入新配置
|
||||||
execute_insert(
|
execute_insert(
|
||||||
'''INSERT INTO t_daily_report_config
|
'''INSERT INTO t_daily_report_config
|
||||||
(id, config_name, split_type, split_value, split_name, selected_fields, sum_fields, time_periods, merge_telecom, telecom_vehicle_no, is_active, sort_order, create_time, update_time)
|
(id, config_name, split_type, split_value, split_name, selected_fields, sum_fields, time_periods, merge_telecom, telecom_vehicle_no, field_custom_names, is_active, sort_order, create_time, update_time)
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())''',
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), NOW())''',
|
||||||
(
|
(
|
||||||
new_id,
|
new_id,
|
||||||
new_name,
|
new_name,
|
||||||
@@ -201,6 +205,7 @@ def copy_config(config_id):
|
|||||||
original.get('time_periods', ''),
|
original.get('time_periods', ''),
|
||||||
original.get('merge_telecom', 0),
|
original.get('merge_telecom', 0),
|
||||||
original.get('telecom_vehicle_no', ''),
|
original.get('telecom_vehicle_no', ''),
|
||||||
|
original.get('field_custom_names', None),
|
||||||
original['is_active'],
|
original['is_active'],
|
||||||
sort_order
|
sort_order
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -416,7 +416,8 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
|
|||||||
split_name=config.get('split_name', config['split_value']),
|
split_name=config.get('split_name', config['split_value']),
|
||||||
start_time=start_time_str,
|
start_time=start_time_str,
|
||||||
end_time=end_time_str,
|
end_time=end_time_str,
|
||||||
id_name_maps=id_name_maps
|
id_name_maps=id_name_maps,
|
||||||
|
field_custom_names=config.get('field_custom_names')
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"[日报生成] Excel文件已生成: {file_path}")
|
print(f"[日报生成] Excel文件已生成: {file_path}")
|
||||||
@@ -491,12 +492,13 @@ def generate_daily_report(config_id, start_time=None, end_time=None):
|
|||||||
|
|
||||||
def generate_excel(orders, selected_fields, sum_fields, sum_results,
|
def generate_excel(orders, selected_fields, sum_fields, sum_results,
|
||||||
config_name, split_name, start_time, end_time,
|
config_name, split_name, start_time, end_time,
|
||||||
id_name_maps=None):
|
id_name_maps=None, field_custom_names=None):
|
||||||
"""
|
"""
|
||||||
生成Excel文件
|
生成Excel文件
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
id_name_maps: ID到名称的映射字典,格式为 {field_name: {id_value: name_value}}
|
id_name_maps: ID到名称的映射字典,格式为 {field_name: {id_value: name_value}}
|
||||||
|
field_custom_names: 字段自定义名头字典,格式为 {field_key: custom_name}
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: 文件路径
|
str: 文件路径
|
||||||
@@ -532,10 +534,14 @@ def generate_excel(orders, selected_fields, sum_fields, sum_results,
|
|||||||
|
|
||||||
# 写入表头(中文)
|
# 写入表头(中文)
|
||||||
header_row = 4
|
header_row = 4
|
||||||
|
field_custom_names = field_custom_names or {}
|
||||||
for col_idx, field in enumerate(selected_fields, 1):
|
for col_idx, field in enumerate(selected_fields, 1):
|
||||||
cell = ws.cell(row=header_row, column=col_idx)
|
cell = ws.cell(row=header_row, column=col_idx)
|
||||||
|
# 优先使用自定义名头
|
||||||
|
if field in field_custom_names and field_custom_names[field]:
|
||||||
|
display_name = field_custom_names[field]
|
||||||
# 如果是ID字段且有名称映射,表头显示为名称而不是ID
|
# 如果是ID字段且有名称映射,表头显示为名称而不是ID
|
||||||
if field in id_name_maps and id_name_maps[field]:
|
elif field in id_name_maps and id_name_maps[field]:
|
||||||
# 将"用户ID"改为"用户","企业ID"改为"企业"等
|
# 将"用户ID"改为"用户","企业ID"改为"企业"等
|
||||||
display_name = get_field_display_name(field).replace('ID', '')
|
display_name = get_field_display_name(field).replace('ID', '')
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1125,6 +1125,9 @@
|
|||||||
document.getElementById('split-type').value = '';
|
document.getElementById('split-type').value = '';
|
||||||
document.getElementById('split-value').innerHTML = '<option value="">请先选择拆分方式</option>';
|
document.getElementById('split-value').innerHTML = '<option value="">请先选择拆分方式</option>';
|
||||||
|
|
||||||
|
// 重置字段自定义名头
|
||||||
|
fieldCustomNames = {};
|
||||||
|
|
||||||
// 重置合并特来电配置
|
// 重置合并特来电配置
|
||||||
const mergeTelecomCheckbox = document.getElementById('merge-telecom');
|
const mergeTelecomCheckbox = document.getElementById('merge-telecom');
|
||||||
const telecomVehicleNoInput = document.getElementById('telecom-vehicle-no');
|
const telecomVehicleNoInput = document.getElementById('telecom-vehicle-no');
|
||||||
@@ -1212,12 +1215,20 @@
|
|||||||
refreshSelectedFieldsOrder(checkedFields);
|
refreshSelectedFieldsOrder(checkedFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 字段自定义名头存储
|
||||||
|
let fieldCustomNames = {};
|
||||||
|
|
||||||
// 刷新已选字段顺序列表
|
// 刷新已选字段顺序列表
|
||||||
function refreshSelectedFieldsOrder(selectedFields) {
|
function refreshSelectedFieldsOrder(selectedFields, customNames = null) {
|
||||||
const orderGroup = document.getElementById('selected-fields-order-group');
|
const orderGroup = document.getElementById('selected-fields-order-group');
|
||||||
const orderList = document.getElementById('selected-fields-order');
|
const orderList = document.getElementById('selected-fields-order');
|
||||||
if (!orderList) return;
|
if (!orderList) return;
|
||||||
|
|
||||||
|
// 如果传入了自定义名头,更新全局变量
|
||||||
|
if (customNames !== null) {
|
||||||
|
fieldCustomNames = {...customNames};
|
||||||
|
}
|
||||||
|
|
||||||
// 根据是否有已选字段,显示/隐藏字段顺序区域
|
// 根据是否有已选字段,显示/隐藏字段顺序区域
|
||||||
if (orderGroup) {
|
if (orderGroup) {
|
||||||
orderGroup.style.display = selectedFields.length > 0 ? 'block' : 'none';
|
orderGroup.style.display = selectedFields.length > 0 ? 'block' : 'none';
|
||||||
@@ -1229,12 +1240,16 @@
|
|||||||
orderList.innerHTML = selectedFields.map((fieldKey, index) => {
|
orderList.innerHTML = selectedFields.map((fieldKey, index) => {
|
||||||
const field = allFields.find(f => f.key === fieldKey);
|
const field = allFields.find(f => f.key === fieldKey);
|
||||||
const displayName = field ? field.display : fieldKey;
|
const displayName = field ? field.display : fieldKey;
|
||||||
|
const customName = fieldCustomNames[fieldKey] || '';
|
||||||
const isFirst = index === 0;
|
const isFirst = index === 0;
|
||||||
const isLast = index === selectedFields.length - 1;
|
const isLast = index === selectedFields.length - 1;
|
||||||
return `
|
return `
|
||||||
<div class="selected-field-item" data-field="${fieldKey}">
|
<div class="selected-field-item" data-field="${fieldKey}">
|
||||||
<span class="field-index">#${index + 1}</span>
|
<span class="field-index">#${index + 1}</span>
|
||||||
<span class="field-name">${displayName}</span>
|
<span class="field-name" title="${displayName}">${displayName}</span>
|
||||||
|
<input type="text" class="field-custom-name" placeholder="自定义报表名头" value="${customName}"
|
||||||
|
onchange="updateFieldCustomName('${fieldKey}', this.value)"
|
||||||
|
style="flex: 1; min-width: 100px; padding: 4px 8px; font-size: 12px;">
|
||||||
<div class="field-actions">
|
<div class="field-actions">
|
||||||
<button type="button" class="btn-move" onclick="moveFieldUp(${index})" ${isFirst ? 'disabled' : ''} title="上移">↑</button>
|
<button type="button" class="btn-move" onclick="moveFieldUp(${index})" ${isFirst ? 'disabled' : ''} title="上移">↑</button>
|
||||||
<button type="button" class="btn-move" onclick="moveFieldDown(${index})" ${isLast ? 'disabled' : ''} title="下移">↓</button>
|
<button type="button" class="btn-move" onclick="moveFieldDown(${index})" ${isLast ? 'disabled' : ''} title="下移">↓</button>
|
||||||
@@ -1244,6 +1259,20 @@
|
|||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新字段自定义名头
|
||||||
|
function updateFieldCustomName(fieldKey, customName) {
|
||||||
|
if (customName && customName.trim()) {
|
||||||
|
fieldCustomNames[fieldKey] = customName.trim();
|
||||||
|
} else {
|
||||||
|
delete fieldCustomNames[fieldKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取字段自定义名头
|
||||||
|
function getFieldCustomNames() {
|
||||||
|
return {...fieldCustomNames};
|
||||||
|
}
|
||||||
|
|
||||||
// 字段上移
|
// 字段上移
|
||||||
function moveFieldUp(index) {
|
function moveFieldUp(index) {
|
||||||
@@ -1631,6 +1660,9 @@
|
|||||||
alert('请输入特来电车量自编号');
|
alert('请输入特来电车量自编号');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取字段自定义名头
|
||||||
|
const fieldCustomNamesData = getFieldCustomNames();
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
config_name: configName,
|
config_name: configName,
|
||||||
@@ -1641,7 +1673,8 @@
|
|||||||
sum_fields: sumFields,
|
sum_fields: sumFields,
|
||||||
time_periods: timePeriods,
|
time_periods: timePeriods,
|
||||||
merge_telecom: mergeTelecom,
|
merge_telecom: mergeTelecom,
|
||||||
telecom_vehicle_no: telecomVehicleNo
|
telecom_vehicle_no: telecomVehicleNo,
|
||||||
|
field_custom_names: fieldCustomNamesData
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1697,8 +1730,9 @@
|
|||||||
// 加载字段并回显选中状态
|
// 加载字段并回显选中状态
|
||||||
await loadFields(config.selected_fields, config.sum_fields);
|
await loadFields(config.selected_fields, config.sum_fields);
|
||||||
|
|
||||||
// 加载字段顺序
|
// 加载字段顺序和自定义名头
|
||||||
refreshSelectedFieldsOrder(config.selected_fields);
|
const customNames = config.field_custom_names || {};
|
||||||
|
refreshSelectedFieldsOrder(config.selected_fields, customNames);
|
||||||
|
|
||||||
// 初始化时段编辑器并加载配置
|
// 初始化时段编辑器并加载配置
|
||||||
initTimePeriodEditor();
|
initTimePeriodEditor();
|
||||||
|
|||||||
Reference in New Issue
Block a user