import json import os from typing import Dict, List, Any, Tuple def read_json_file(file_path: str) -> Dict: """读取JSON文件""" try: with open(file_path, "r", encoding="utf-8") as f: data = json.load(f) return data except Exception as e: print(f"读取JSON文件时出错: {e}") return {} def find_leaf_project_divisions( node: Any, project_name: str = None, path: List = None ) -> List[Tuple[str, str, str, List[str]]]: """ 递归查找最子集的项目划分节点 Args: node: 当前节点 project_name: 当前工程名称 path: 当前路径 Returns: List[Tuple[str, str, str, List[str]]]: 项目划分节点名称、调差类型、GUID和路径的列表 """ results = [] if path is None: path = [] # 如果节点是字典 if isinstance(node, dict): # 判断是否是项目划分节点 is_project_division = node.get("type") == "项目划分" has_children = "children" in node and isinstance(node["children"], list) and node["children"] if is_project_division: # 获取GUID node_guid = node.get("GUID") or node.get("guid", "") # 保存当前节点的名称到路径 current_path = path + [node.get("项目名称", "未命名")] # 如果没有子节点或子节点不是项目划分节点,则认为是最子集的项目划分节点 if not has_children or not any(child.get("type") == "项目划分" for child in node["children"]): results.append((node.get("项目名称", "未命名"), node_guid, current_path)) # 递归处理子节点 if has_children: for child in node["children"]: results.extend(find_leaf_project_divisions(child, project_name, current_path)) else: # 遍历所有键值对 for key, value in node.items(): # 如果是工程名称 if isinstance(value, dict) and key != "children": new_project_name = key # 遍历调差类型 for adj_type, adj_value in value.items(): if isinstance(adj_value, list): for item in adj_value: results.extend( find_leaf_project_divisions(item, new_project_name, path + [new_project_name]) ) # 处理其他可能的字典或列表 elif isinstance(value, (dict, list)): results.extend(find_leaf_project_divisions(value, project_name, path)) # 如果节点是列表 elif isinstance(node, list): for item in node: results.extend(find_leaf_project_divisions(item, project_name, path)) return results def find_all_project_divisions(json_file_path: str) -> List[Tuple[str, str, List[str]]]: """ 查找JSON文件中所有最子集的项目划分节点和对应的调差类型 Args: json_file_path: JSON文件路径 Returns: List[Tuple[str, str, List[str]]]: 项目划分节点名称、调差类型和路径的列表 """ # 读取JSON文件 data = read_json_file(json_file_path) # 获取projectDivision project_division = data.get("projectData", {}).get("projectDivision", {}) # 查找所有最子集的项目划分节点 results = find_leaf_project_divisions(project_division) return results def process_project_and_save(json_file_path: str, project_name: str, output_dir: str = "计算结果") -> str: """ 处理指定的项目划分和调差类型,计算费用并保存结果 Args: json_file_path: JSON文件路径 project_name: 项目划分名称 output_dir: 输出目录 Returns: str: 输出文件路径 """ # 确保输出目录存在 os.makedirs(output_dir, exist_ok=True) # 设置输出文件名 output_file = os.path.join(output_dir, f"{project_name}.json") # 返回输出文件路径 return output_file def print_project_divisions(results: List[Tuple[str, str, List[str]]]): """打印项目划分节点和调差类型""" print(f"找到 {len(results)} 个最子集项目划分节点:") for i, (name, adj_type, path) in enumerate(results, 1): path_str = " > ".join(path) print(f"{i}. 项目划分: {name}") print(f" 调差类型: {adj_type}") print(f" 路径: {path_str}") print() def get_project_divisions_list(json_file_path: str) -> List[Tuple[str, str, str]]: """ 获取JSON文件中所有项目划分节点和调差类型的列表,返回名称、调差类型和GUID Args: json_file_path: JSON文件路径 Returns: List[Tuple[str, str, str]]: 项目划分节点名称、调差类型和GUID的列表 """ results = find_all_project_divisions(json_file_path) # 返回项目名称、调差类型和GUID,不包括路径 return [(name, guid) for name, guid, _ in results]