修改代码

This commit is contained in:
chentianrui
2025-10-16 09:53:37 +08:00
parent 0a4dedda1c
commit 6c2354c897
24 changed files with 1280876 additions and 3384 deletions
+3 -3
View File
@@ -301,7 +301,7 @@ def _configure_bcl_logging(log_dir: str):
log_path = os.path.join(log_dir, "bcl_calculator.log")
logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.setLevel(logging.DEBUG)
# 移除已有的 FileHandler,避免写到旧位置或重复写
for h in list(logger.handlers):
@@ -315,14 +315,14 @@ def _configure_bcl_logging(log_dir: str):
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
file_handler = logging.FileHandler(log_path, mode="w", encoding="utf-8")
file_handler.setLevel(logging.INFO)
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# 确保有一个控制台输出
if not any(isinstance(h, logging.StreamHandler) for h in logger.handlers):
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
stream_handler.setLevel(logging.DEBUG)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
+163 -35
View File
@@ -33,9 +33,64 @@ from equipment_calculation.item_acquisition import (
# 缓存已计算过的费用
calculated_fees = {}
# # 添加一个全局变量和一个缓存字典来存储清单数量
# _BILL_QUANTITY = 1.0
# bill_quantity_cache = {}
# 软件类别名称映射字典,将各种变体映射到标准类别
CATEGORY_MAPPING = {
# 主网及其变体
"主网": "主网",
"主网工程": "主网",
"主网项目": "主网",
# 配网及其变体
"配网": "配网",
"配网造价": "配网",
"配网清单": "配网",
# 技改及其变体
"技改": "技改",
"技改工程": "技改",
"技改项目": "技改",
"技改造价": "技改",
"技改清单": "技改",
}
def parse_json_content(json_data: dict) -> Tuple[Optional[str], Optional[str]]:
"""
从JSON内容(字典)中解析:
- 软件类别: 来自 basicData["软件类别"](若无则尝试 basicData["软件名称"] 作为兜底)
- 项目划分: 来自 projectData.projectInfo["项目划分"]
不再解析或返回“项目类型”(原 basicData 中的字段)。
:param json_data: 已加载的JSON内容(字典)
:return: (category, engineering_type) 元组,解析失败对应位置返回 None
"""
try:
# 提取 basicData
basic_data = json_data.get("basicData", {}) if isinstance(json_data, dict) else {}
# 软件类别(优先 软件类别,其次 软件名称)
category = basic_data.get("软件类别") or basic_data.get("软件名称")
# 规范化软件类别
if category:
if category in CATEGORY_MAPPING:
category = CATEGORY_MAPPING[category]
else:
print(f"警告: basicData中的软件名称/类别 '{category}' 不是有效值,将使用默认值 '主网'")
category = "主网"
# 提取工程类型:projectData.projectInfo.项目划分
project_info = json_data.get("projectData", {}).get("projectInfo", {})
project_type = project_info.get("项目划分")
# 打印解析结果(便于调试)
# print(f"解析完成: 软件类别={category}, 项目类型={project_type}")
return category, project_type
except Exception as e:
print(f"解析JSON内容时出错: {str(e)}")
return None, None
# 主网架线处理地形系数
@@ -107,8 +162,76 @@ def process_DXdata(json_data):
return result_list
# # 技改处理地形系数
# def JG_process_DXdata(json_data):
# 主网通信线路处理地形系数
def process_MainNetwork_CommunicationLine_DXdata(json_data):
"""
处理 projectData 中的线路特征段数据,计算每条 综合地形比例增加系数 记录的加权值,
并返回一个字典列表,每个字典包含 '特征段': "1"(固定) 和对应的 ItemName: 计算结果。
注意:当前数据结构中 lineParameters 是 dict,不是 list。
:param json_data: 解析后的 JSON 数据(字典格式)
:return: 字典列表,例如 [{"工地运输...": 21.8}, ...]
"""
result_list = []
# 直接获取 lineParameters 字典
line_params = json_data.get("projectData", {}).get("lineParameters", {})
# 获取 "综合地形比例增加系数" 列表
table_list = line_params.get("综合地形比例增加系数", [])
# 如果未来需要支持多个特征段,这里可能需要调整;目前按单段处理
for item in table_list:
try:
# 提取字段并转换为浮点数(默认为0
KnapScale = float(item.get("调整系数_高山", 0))
Knap = float(item.get("地形比例_高山", 0))
HillScale = float(item.get("调整系数_山地", 0))
Hill = float(item.get("地形比例_山地", 0))
EdelweissScale = float(item.get("调整系数_丘陵", 0))
edelweiss = float(item.get("地形比例_丘陵", 0))
MountainScale = float(item.get("调整系数_河网", 0))
Mountain = float(item.get("地形比例_河网", 0))
SloughScale = float(item.get("调整系数_泥沼", 0))
Slough = float(item.get("地形比例_泥沼", 0))
RiverScale = float(item.get("调整系数_峻岭", 0))
River = float(item.get("地形比例_峻岭", 0))
DesertScale = float(item.get("调整系数_沙漠", 0))
Desert = float(item.get("地形比例_沙漠", 0))
# 执行计算
total = (
(KnapScale * Knap)
+ (HillScale * Hill)
+ (EdelweissScale * edelweiss)
+ (MountainScale * Mountain)
+ (SloughScale * Slough)
+ (RiverScale * River)
+ (DesertScale * Desert)
) * 0.01
# 获取名称
item_name = item.get("名称", "未知项目")
# 构建结果字典:每个元素是一个 {名称: 值} 的字典
result_list.append({item_name: round(total, 6)}) # 可选保留小数位
except (ValueError, TypeError) as e:
print(f"数据转换错误,跳过该项: {e}")
continue
return result_list
# # 技改架线处理地形系数
# def JGJX_process_DXdata(json_data):
# # 技改通信线路处理地形系数
# def JGTXXL_process_DXdata(json_data):
# # 技改配网处理地形系数
# def JGPW_process_DXdata(json_data):
# 在create_list_from_node函数后添加一个包装函数
@@ -472,9 +595,32 @@ def calculate_all_fees(
with open(json_file_path, "r", encoding="utf-8") as file:
data = json.load(file)
processed_data = process_DXdata(data)
# 解析软件类别与项目类型,并按条件选择处理函数
category, project_type = parse_json_content(data)
is_overhead = category == "主网" and project_type == "架空输电线路工程"
is_comm = category == "主网" and project_type == "通信线路工程"
DXITEM = [BCLDataSourceItem(item) for item in processed_data]
if is_overhead:
processed_data = process_DXdata(data)
elif is_comm:
processed_data = process_MainNetwork_CommunicationLine_DXdata(data)
else:
# 默认保持原有处理逻辑(视为架空处理)
processed_data = process_DXdata(data)
# 构建数据源项(供链式上下文使用)
DXITEM = [BCLDataSourceItem(item) for item in processed_data] if processed_data else []
# 若为通信线路工程,准备一个前缀上下文 @地形系数,直接以字典映射赋值
terrain_context = None
if is_comm:
terrain_map = {}
for item in processed_data or []:
if isinstance(item, dict):
terrain_map.update(item)
# 以与 @工程信息、@价差系数 相同的方式,前缀上下文直赋
terrain_context = ZjProjectBCLContext(prefix="@地形系数", prevContext=project_context)
terrain_context.add_variables_from_dict(terrain_map)
# 2. 构建数据源链式上下文
if engineering_type == "清单工程":
@@ -499,8 +645,11 @@ def calculate_all_fees(
# 创建工程量对象
project_obj = create_node_from_type(project_node)
dxitem_context = BCLDataSourceContext(DXITEM, project_context)
dxitem_context.variables["@特征段地形系数"] = BCLVariant(DXITEM)
# 通信线路工程将 @地形系数 作为前缀上下文直接赋值;否则沿用链式对象变量
prev_ctx = terrain_context if terrain_context is not None else project_context
dxitem_context = BCLDataSourceContext(DXITEM, prev_ctx)
if is_overhead or (not is_comm):
dxitem_context.variables["@特征段地形系数"] = BCLVariant(DXITEM)
# 递归数据源链式上下文
billItem = BCLDataSourceItem(bill_obj)
@@ -529,18 +678,6 @@ def calculate_all_fees(
bill_context = BCLDataSourceContext([billItem], dxitem_context)
# # 构建人材机数据源项(若存在)并接入上下文
# rcj_nodes_for_parent = project_node.get("_rcj_nodes", [])
# moe_items = []
# if rcj_nodes_for_parent:
# try:
# for rcj_node in rcj_nodes_for_parent:
# node_obj = create_material_or_equipment_from_node(rcj_node)
# moe_items.append(BCLDataSourceItem(node_obj, QuantityItem))
# except Exception as e:
# print(f"构建人材机数据源项出错: {e}")
# items_chain = [QuantityItem] + moe_items if moe_items else [QuantityItem]
context = BCLDataSourceContext([QuantityItem], bill_context)
# 如果计算策略存在,设置清单数量
@@ -552,8 +689,11 @@ def calculate_all_fees(
# 非清单工程 - 工程信息 -> 工程量节点
project_obj = create_node_from_type(project_node)
dxitem_context = BCLDataSourceContext(DXITEM, project_context)
dxitem_context.variables["@特征段地形系数"] = BCLVariant(DXITEM)
# 通信线路工程将 @地形系数 作为前缀上下文直接赋值;否则沿用链式对象变量
prev_ctx = terrain_context if terrain_context is not None else project_context
dxitem_context = BCLDataSourceContext(DXITEM, prev_ctx)
if is_overhead or (not is_comm):
dxitem_context.variables["@特征段地形系数"] = BCLVariant(DXITEM)
# 如果无法创建工程量对象,则跳过并返回当前已计算结果,避免未定义的 QuantityItem
if not project_obj:
@@ -572,18 +712,6 @@ def calculate_all_fees(
QuantityItem.set_childs(childItems)
# # 构建人材机数据源项(若存在)并接入上下文
# rcj_nodes_for_parent = project_node.get("_rcj_nodes", [])
# moe_items = []
# if rcj_nodes_for_parent:
# try:
# for rcj_node in rcj_nodes_for_parent:
# node_obj = create_material_or_equipment_from_node(rcj_node)
# moe_items.append(BCLDataSourceItem(node_obj, QuantityItem))
# except Exception as e:
# print(f"构建人材机数据源项出错: {e}")
# items_chain = [QuantityItem] + moe_items if moe_items else [QuantityItem]
context = BCLDataSourceContext([QuantityItem], dxitem_context)
# 查找包含取费基数的节点