#!/usr/bin/env python3 """ Tab5内容生成器 - 实质与形式的双向支撑关系图 展示:选题点(来自实质) ← 实质点 → 形式点 → 选题点(来自形式) """ import html as html_module import json from typing import Dict, Any, List def get_intent_support_data(element: Dict[str, Any]) -> Dict[str, Any]: """ 获取元素的意图支撑数据(兼容新旧数据结构) 优先使用"意图支撑"字段,如果没有则使用"多维度评分"字段 这两个字段内部存储的都是意图支撑数据 Args: element: 元素数据 Returns: 意图支撑数据字典,格式:{"灵感点": [...], "目的点": [...], "关键点": [...]} """ # 优先使用"意图支撑"字段 intent_support = element.get('意图支撑') if intent_support and isinstance(intent_support, dict): return intent_support # 如果没有"意图支撑",则使用"多维度评分"字段(兼容旧数据) multi_scores = element.get('多维度评分') if multi_scores and isinstance(multi_scores, dict): return multi_scores # 都没有则返回空字典 return {} def generate_tab5_content(data: Dict[str, Any]) -> str: """生成Tab5内容:实质与形式的双向支撑关系图(4列布局)""" html = '
\n' # 提取数据 script_data = data.get('脚本理解', {}) form_list = script_data.get('形式列表', []) substance_list = script_data.get('实质列表', []) # 处理灵感点:可能是列表,也可能在对象中 inspiration_data = data.get('灵感点', []) if isinstance(inspiration_data, list): inspiration_points = inspiration_data elif isinstance(inspiration_data, dict): inspiration_points = inspiration_data.get('inspiration_points', []) else: inspiration_points = [] # 处理目的点:可能是列表,也可能在对象的purposes字段中 purpose_data = data.get('目的点', []) if isinstance(purpose_data, list): purpose_points = purpose_data elif isinstance(purpose_data, dict): purpose_points = purpose_data.get('purposes', []) else: purpose_points = [] # 处理关键点:可能是列表,也可能在对象的key_points字段中 keypoint_data = data.get('关键点', []) if isinstance(keypoint_data, list): key_points = keypoint_data elif isinstance(keypoint_data, dict): key_points = keypoint_data.get('key_points', []) else: key_points = [] if not substance_list and not form_list: html += '
暂无实质点和形式点数据
\n' html += '
\n' return html # 分类实质点 concrete_elements = [] concrete_concepts = [] implicit_concepts = [] abstract_concepts = [] for substance in substance_list: dimension_2 = substance.get('维度', {}).get('二级', '') elem_type = substance.get('类型', '') # 隐含概念:优先通过类型判断(因为维度二级可能是"隐含概念"或"抽象概念") if elem_type == '隐含概念': implicit_concepts.append(substance) elif dimension_2 == '具体元素': concrete_elements.append(substance) elif dimension_2 == '具象概念': # 修改:从"具体概念"改为"具象概念" concrete_concepts.append(substance) elif dimension_2 == '抽象概念': abstract_concepts.append(substance) # 分类形式点 concrete_element_forms = [] concrete_concept_forms = [] overall_forms = [] for form in form_list: dimension_2 = form.get('维度', {}).get('二级', '') if dimension_2 == '具体元素形式': concrete_element_forms.append(form) elif dimension_2 == '具象概念形式': # 修改:从"具体概念形式"改为"具象概念形式" concrete_concept_forms.append(form) elif dimension_2 == '整体形式': overall_forms.append(form) # 构建关系数据 relationships = build_bidirectional_relationships( concrete_elements, concrete_concepts, implicit_concepts, abstract_concepts, concrete_element_forms, concrete_concept_forms, overall_forms, inspiration_points, purpose_points, key_points ) # 添加标题和说明 html += '
\n' html += '

实质与形式的双向支撑关系图

\n' html += '
\n' html += '

4列展示:选题点(实质支撑)实质点 | 形式点选题点(形式支撑)

\n' html += '\n' html += '
\n' html += '
\n' # SVG 连线容器(放在4列布局之前,作为背景层) html += '
\n' html += '\n' html += '\n' html += '\n' html += '
\n' # 主要内容区域(4列布局) html += '
\n' # 第1列:左侧选题点(来自实质点的支撑关系) html += '
\n' html += '

选题点
(实质支撑)

\n' # 灵感点(左) if inspiration_points: html += '
\n' html += '

灵感点

\n' html += '
\n' for idx, point in enumerate(inspiration_points, 1): # 确保 point 是字典 if not isinstance(point, dict): continue # 使用提取的特征中的特征名称,每个特征名称一个卡片 features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: # 为每个特征名称创建一个独立ID的卡片 for feature_idx, feature_name in enumerate(feature_names, 1): feature_id = f'inspiration-{idx}-{feature_idx}' html += f'
\n' html += f'
#{idx}-{feature_idx}
\n' html += f'
{html_module.escape(feature_name)}
\n' html += '
\n' else: # 如果没有特征,使用原始的灵感点文本 display_text = point.get('灵感点', '') html += f'
\n' html += f'
#{idx}
\n' html += f'
{html_module.escape(display_text)}
\n' html += '
\n' html += '
\n' html += '
\n' # 关键点(左) if key_points: html += '
\n' html += '

关键点

\n' html += '
\n' for idx, point in enumerate(key_points, 1): # 确保 point 是字典 if not isinstance(point, dict): continue # 使用提取的特征中的特征名称,每个特征名称一个卡片 features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: # 为每个特征名称创建一个独立ID的卡片 for feature_idx, feature_name in enumerate(feature_names, 1): feature_id = f'keypoint-{idx}-{feature_idx}' html += f'
\n' html += f'
#{idx}-{feature_idx}
\n' html += f'
{html_module.escape(feature_name)}
\n' html += '
\n' else: # 如果没有特征,使用原始的关键点文本 display_text = point.get('关键点', '') html += f'
\n' html += f'
#{idx}
\n' html += f'
{html_module.escape(display_text)}
\n' html += '
\n' html += '
\n' html += '
\n' # 目的点(左) if purpose_points: html += '
\n' html += '

目的点

\n' html += '
\n' for idx, point in enumerate(purpose_points, 1): # 确保 point 是字典 if not isinstance(point, dict): continue # 使用提取的特征中的特征名称,每个特征名称一个卡片 features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: # 为每个特征名称创建一个独立ID的卡片 for feature_idx, feature_name in enumerate(feature_names, 1): feature_id = f'purpose-{idx}-{feature_idx}' html += f'
\n' html += f'
#{idx}-{feature_idx}
\n' html += f'
{html_module.escape(feature_name)}
\n' html += '
\n' else: # 如果没有特征,使用原始的目的点文本 display_text = point.get('目的点', '') html += f'
\n' html += f'
#{idx}
\n' html += f'
{html_module.escape(display_text)}
\n' html += '
\n' html += '
\n' html += '
\n' html += '
\n' # 第2列:实质点 html += '
\n' html += '

实质点

\n' # 具体元素 if concrete_elements: html += '
\n' html += '

具体元素

\n' html += '
\n' for substance in concrete_elements: html += render_substance_card(substance, 'concrete-element') html += '
\n' html += '
\n' # 具象概念 if concrete_concepts: html += '
\n' html += '

具象概念

\n' html += '
\n' for substance in concrete_concepts: html += render_substance_card(substance, 'concrete-concept') html += '
\n' html += '
\n' # 隐含概念 if implicit_concepts: html += '
\n' html += '

隐含概念

\n' html += '
\n' for substance in implicit_concepts: html += render_substance_card(substance, 'implicit-concept') html += '
\n' html += '
\n' # 抽象概念 if abstract_concepts: html += '
\n' html += '

抽象概念

\n' html += '
\n' for substance in abstract_concepts: html += render_substance_card(substance, 'abstract-concept') html += '
\n' html += '
\n' html += '
\n' # 第3列:形式点 html += '
\n' html += '

形式点

\n' # 具体元素形式 if concrete_element_forms: html += '
\n' html += '

具体元素形式

\n' html += '
\n' for form in concrete_element_forms: html += render_form_card(form, 'concrete-element-form') html += '
\n' html += '
\n' # 具象概念形式 if concrete_concept_forms: html += '
\n' html += '

具象概念形式

\n' html += '
\n' for form in concrete_concept_forms: html += render_form_card(form, 'concrete-concept-form') html += '
\n' html += '
\n' # 整体形式 if overall_forms: html += '
\n' html += '

整体形式

\n' html += '
\n' for form in overall_forms: html += render_form_card(form, 'overall-form') html += '
\n' html += '
\n' html += '
\n' # 第4列:右侧选题点(来自形式点的支撑关系) html += '
\n' html += '

选题点
(形式支撑)

\n' # 灵感点(右) if inspiration_points: html += '
\n' html += '

灵感点

\n' html += '
\n' for idx, point in enumerate(inspiration_points, 1): # 确保 point 是字典 if not isinstance(point, dict): continue # 使用提取的特征中的特征名称,每个特征名称一个卡片 features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: # 为每个特征名称创建一个独立ID的卡片 for feature_idx, feature_name in enumerate(feature_names, 1): feature_id = f'inspiration-{idx}-{feature_idx}' html += f'
\n' html += f'
#{idx}-{feature_idx}
\n' html += f'
{html_module.escape(feature_name)}
\n' html += '
\n' else: # 如果没有特征,使用原始的灵感点文本 display_text = point.get('灵感点', '') html += f'
\n' html += f'
#{idx}
\n' html += f'
{html_module.escape(display_text)}
\n' html += '
\n' html += '
\n' html += '
\n' # 关键点(右) if key_points: html += '
\n' html += '

关键点

\n' html += '
\n' for idx, point in enumerate(key_points, 1): # 确保 point 是字典 if not isinstance(point, dict): continue # 使用提取的特征中的特征名称,每个特征名称一个卡片 features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: # 为每个特征名称创建一个独立ID的卡片 for feature_idx, feature_name in enumerate(feature_names, 1): feature_id = f'keypoint-{idx}-{feature_idx}' html += f'
\n' html += f'
#{idx}-{feature_idx}
\n' html += f'
{html_module.escape(feature_name)}
\n' html += '
\n' else: # 如果没有特征,使用原始的关键点文本 display_text = point.get('关键点', '') html += f'
\n' html += f'
#{idx}
\n' html += f'
{html_module.escape(display_text)}
\n' html += '
\n' html += '
\n' html += '
\n' # 目的点(右) if purpose_points: html += '
\n' html += '

目的点

\n' html += '
\n' for idx, point in enumerate(purpose_points, 1): # 确保 point 是字典 if not isinstance(point, dict): continue # 使用提取的特征中的特征名称,每个特征名称一个卡片 features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: # 为每个特征名称创建一个独立ID的卡片 for feature_idx, feature_name in enumerate(feature_names, 1): feature_id = f'purpose-{idx}-{feature_idx}' html += f'
\n' html += f'
#{idx}-{feature_idx}
\n' html += f'
{html_module.escape(feature_name)}
\n' html += '
\n' else: # 如果没有特征,使用原始的目的点文本 display_text = point.get('目的点', '') html += f'
\n' html += f'
#{idx}
\n' html += f'
{html_module.escape(display_text)}
\n' html += '
\n' html += '
\n' html += '
\n' html += '
\n' html += '
\n' # 嵌入关系数据 html += '\n' html += '\n' return html def render_substance_card(substance: Dict[str, Any], css_class: str) -> str: """渲染实质点卡片""" substance_id = substance.get('id', '') substance_name = substance.get('名称', '') description = substance.get('描述', '') html = f'
\n' html += f'
\n' html += f'
#{html_module.escape(substance_id)}
\n' html += f'
{html_module.escape(substance_name)}
\n' html += '
\n' if description: html += f'
{html_module.escape(description[:50])}{"..." if len(description) > 50 else ""}
\n' html += '
\n' return html def render_form_card(form: Dict[str, Any], css_class: str) -> str: """渲染形式点卡片""" form_id = form.get('id', '') form_name = form.get('名称', '') description = form.get('描述', '') weight_score = form.get('权重分') html = f'
\n' html += f'
\n' html += f'
#{html_module.escape(form_id)}
\n' html += f'
{html_module.escape(form_name)}
\n' if weight_score is not None: html += f'
权重分: {weight_score:.1f}
\n' html += '
\n' if description: html += f'
{html_module.escape(description[:50])}{"..." if len(description) > 50 else ""}
\n' html += '
\n' return html def build_bidirectional_relationships( concrete_elements: List[Dict], concrete_concepts: List[Dict], implicit_concepts: List[Dict], abstract_concepts: List[Dict], concrete_element_forms: List[Dict], concrete_concept_forms: List[Dict], overall_forms: List[Dict], inspiration_points: List[Dict], purpose_points: List[Dict], key_points: List[Dict] ) -> Dict[str, Any]: """ 构建双向支撑关系数据 返回结构: { "substance_to_target": { "substance_id": { "inspiration": [{target_id, score, ...}], "purpose": [...], "keypoint": [...] } }, "form_to_target": { "form_id": { "inspiration": [{target_id, score, ...}], "purpose": [...], "keypoint": [...] } }, "target_from_substance": { "inspiration-1": [substance_ids with scores], "keypoint-1": [...], "purpose-1": [...] }, "target_from_form": { "inspiration-1": [form_ids with scores], ... }, "form_to_substance": { "form_id": [substance_ids], ... }, "substance_from_form": { "substance_id": [form_ids], ... } } """ relationships = { "substance_to_target": {}, "form_to_target": {}, "target_from_substance": {}, "target_from_form": {}, "form_to_substance": {}, # 新增:形式点→实质点 "substance_from_form": {} # 新增:实质点←形式点(反向) } # 合并所有实质点和形式点 all_substances = concrete_elements + concrete_concepts + implicit_concepts + abstract_concepts all_forms = concrete_element_forms + concrete_concept_forms + overall_forms # 注意:优先使用"意图支撑"字段,如果没有则使用"多维度评分"字段(兼容旧数据) # 这两个字段内部存储的都是意图支撑数据,每个项目就是一个支撑点 # 不再需要阈值过滤,所有支撑点都会显示连线 # 1. 构建实质点到选题点的关系(基于意图支撑数据) for substance in all_substances: substance_id = substance.get('id', '') if not substance_id: continue dimension_2 = substance.get('维度', {}).get('二级', '') intention_support = get_intent_support_data(substance) relationships["substance_to_target"][substance_id] = { "name": substance.get('名称', ''), "type": dimension_2, "inspiration": [], "purpose": [], "keypoint": [] } # 处理灵感点(意图支撑) for support_item in intention_support.get('灵感点', []): point_name = support_item.get('点') if not point_name: continue # 在灵感点列表中查找匹配的点,以便复用Tab1中的卡片id/特征结构 idx = next( (i for i, p in enumerate(inspiration_points, 1) if isinstance(p, dict) and p.get('灵感点') == point_name), None ) if idx is None: continue point = inspiration_points[idx - 1] features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: # 为每个特征创建独立的关系 for feature_idx in range(1, len(feature_names) + 1): target_id = f'inspiration-{idx}-{feature_idx}' relationships["substance_to_target"][substance_id]["inspiration"].append({ "target_id": target_id, "point": point_name, "support_reason": support_item.get('支撑理由', '') }) # 反向关系 if target_id not in relationships["target_from_substance"]: relationships["target_from_substance"][target_id] = [] relationships["target_from_substance"][target_id].append({ "substance_id": substance_id, "name": substance.get('名称', ''), "type": dimension_2, "support_reason": support_item.get('支撑理由', '') }) else: # 没有特征,使用主索引 target_id = f'inspiration-{idx}' relationships["substance_to_target"][substance_id]["inspiration"].append({ "target_id": target_id, "point": point_name, "support_reason": support_item.get('支撑理由', '') }) # 反向关系 if target_id not in relationships["target_from_substance"]: relationships["target_from_substance"][target_id] = [] relationships["target_from_substance"][target_id].append({ "substance_id": substance_id, "name": substance.get('名称', ''), "type": dimension_2, "support_reason": support_item.get('支撑理由', '') }) # 处理目的点(意图支撑) for support_item in intention_support.get('目的点', []): point_name = support_item.get('点') if not point_name: continue idx = next( (i for i, p in enumerate(purpose_points, 1) if isinstance(p, dict) and p.get('目的点') == point_name), None ) if idx is None: continue point = purpose_points[idx - 1] features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: for feature_idx in range(1, len(feature_names) + 1): target_id = f'purpose-{idx}-{feature_idx}' relationships["substance_to_target"][substance_id]["purpose"].append({ "target_id": target_id, "point": point_name, "support_reason": support_item.get('支撑理由', '') }) if target_id not in relationships["target_from_substance"]: relationships["target_from_substance"][target_id] = [] relationships["target_from_substance"][target_id].append({ "substance_id": substance_id, "name": substance.get('名称', ''), "type": dimension_2, "support_reason": support_item.get('支撑理由', '') }) else: target_id = f'purpose-{idx}' relationships["substance_to_target"][substance_id]["purpose"].append({ "target_id": target_id, "point": point_name, "support_reason": support_item.get('支撑理由', '') }) if target_id not in relationships["target_from_substance"]: relationships["target_from_substance"][target_id] = [] relationships["target_from_substance"][target_id].append({ "substance_id": substance_id, "name": substance.get('名称', ''), "type": dimension_2, "support_reason": support_item.get('支撑理由', '') }) # 处理关键点(意图支撑) for support_item in intention_support.get('关键点', []): point_name = support_item.get('点') if not point_name: continue idx = next( (i for i, p in enumerate(key_points, 1) if isinstance(p, dict) and p.get('关键点') == point_name), None ) if idx is None: continue point = key_points[idx - 1] features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: for feature_idx in range(1, len(feature_names) + 1): target_id = f'keypoint-{idx}-{feature_idx}' relationships["substance_to_target"][substance_id]["keypoint"].append({ "target_id": target_id, "point": point_name, "support_reason": support_item.get('支撑理由', '') }) if target_id not in relationships["target_from_substance"]: relationships["target_from_substance"][target_id] = [] relationships["target_from_substance"][target_id].append({ "substance_id": substance_id, "name": substance.get('名称', ''), "type": dimension_2, "support_reason": support_item.get('支撑理由', '') }) else: target_id = f'keypoint-{idx}' relationships["substance_to_target"][substance_id]["keypoint"].append({ "target_id": target_id, "point": point_name, "support_reason": support_item.get('支撑理由', '') }) if target_id not in relationships["target_from_substance"]: relationships["target_from_substance"][target_id] = [] relationships["target_from_substance"][target_id].append({ "substance_id": substance_id, "name": substance.get('名称', ''), "type": dimension_2, "support_reason": support_item.get('支撑理由', '') }) # 2. 构建形式点到选题点的关系 for form in all_forms: form_id = form.get('id', '') if not form_id: continue dimension_2 = form.get('维度', {}).get('二级', '') # 优先使用"意图支撑"字段,如果没有则使用"多维度评分"字段 intent_support_data = get_intent_support_data(form) relationships["form_to_target"][form_id] = { "name": form.get('名称', ''), "type": dimension_2, "inspiration": [], "purpose": [], "keypoint": [] } # 处理灵感点(每个项目就是一个支撑点) if '灵感点' in intent_support_data: for support_point in intent_support_data['灵感点']: if not isinstance(support_point, dict): continue # 每个项目就是一个支撑点,直接使用 point_name = support_point.get('点', '') if not point_name: continue # 根据点名称找到对应的灵感点索引 point_idx = None for idx, point in enumerate(inspiration_points, 1): if point.get('灵感点') == point_name or point.get('名称') == point_name: point_idx = idx break if point_idx and point_idx <= len(inspiration_points): point = inspiration_points[point_idx - 1] features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: # 为每个特征创建独立的关系 for feature_idx in range(1, len(feature_names) + 1): target_id = f'inspiration-{point_idx}-{feature_idx}' relationships["form_to_target"][form_id]["inspiration"].append({ "target_id": target_id, "point": point_name, "support_reason": support_point.get('支撑理由', '') }) # 反向关系 if target_id not in relationships["target_from_form"]: relationships["target_from_form"][target_id] = [] relationships["target_from_form"][target_id].append({ "form_id": form_id, "name": form.get('名称', ''), "type": dimension_2, "support_reason": support_point.get('支撑理由', '') }) else: # 没有特征,使用主索引 target_id = f'inspiration-{point_idx}' relationships["form_to_target"][form_id]["inspiration"].append({ "target_id": target_id, "point": point_name, "support_reason": support_point.get('支撑理由', '') }) # 反向关系 if target_id not in relationships["target_from_form"]: relationships["target_from_form"][target_id] = [] relationships["target_from_form"][target_id].append({ "form_id": form_id, "name": form.get('名称', ''), "type": dimension_2, "support_reason": support_point.get('支撑理由', '') }) # 处理目的点(每个项目就是一个支撑点) if '目的点' in intent_support_data: for support_point in intent_support_data['目的点']: if not isinstance(support_point, dict): continue # 每个项目就是一个支撑点,直接使用 point_name = support_point.get('点', '') if not point_name: continue # 根据点名称找到对应的目的点索引 point_idx = None for idx, point in enumerate(purpose_points, 1): if point.get('目的点') == point_name or point.get('名称') == point_name: point_idx = idx break if point_idx and point_idx <= len(purpose_points): point = purpose_points[point_idx - 1] features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: for feature_idx in range(1, len(feature_names) + 1): target_id = f'purpose-{point_idx}-{feature_idx}' relationships["form_to_target"][form_id]["purpose"].append({ "target_id": target_id, "point": point_name, "support_reason": support_point.get('支撑理由', '') }) if target_id not in relationships["target_from_form"]: relationships["target_from_form"][target_id] = [] relationships["target_from_form"][target_id].append({ "form_id": form_id, "name": form.get('名称', ''), "type": dimension_2, "support_reason": support_point.get('支撑理由', '') }) else: target_id = f'purpose-{point_idx}' relationships["form_to_target"][form_id]["purpose"].append({ "target_id": target_id, "point": point_name, "support_reason": support_point.get('支撑理由', '') }) if target_id not in relationships["target_from_form"]: relationships["target_from_form"][target_id] = [] relationships["target_from_form"][target_id].append({ "form_id": form_id, "name": form.get('名称', ''), "type": dimension_2, "support_reason": support_point.get('支撑理由', '') }) # 处理关键点(每个项目就是一个支撑点) if '关键点' in intent_support_data: for support_point in intent_support_data['关键点']: if not isinstance(support_point, dict): continue # 每个项目就是一个支撑点,直接使用 point_name = support_point.get('点', '') if not point_name: continue # 根据点名称找到对应的关键点索引 point_idx = None for idx, point in enumerate(key_points, 1): if point.get('关键点') == point_name or point.get('名称') == point_name: point_idx = idx break if point_idx and point_idx <= len(key_points): point = key_points[point_idx - 1] features = point.get('提取的特征', []) feature_names = [f.get('特征名称', '') for f in features if f.get('特征名称')] if feature_names: for feature_idx in range(1, len(feature_names) + 1): target_id = f'keypoint-{point_idx}-{feature_idx}' relationships["form_to_target"][form_id]["keypoint"].append({ "target_id": target_id, "point": point_name, "support_reason": support_point.get('支撑理由', '') }) if target_id not in relationships["target_from_form"]: relationships["target_from_form"][target_id] = [] relationships["target_from_form"][target_id].append({ "form_id": form_id, "name": form.get('名称', ''), "type": dimension_2, "support_reason": support_point.get('支撑理由', '') }) else: target_id = f'keypoint-{point_idx}' relationships["form_to_target"][form_id]["keypoint"].append({ "target_id": target_id, "point": point_name, "support_reason": support_point.get('支撑理由', '') }) if target_id not in relationships["target_from_form"]: relationships["target_from_form"][target_id] = [] relationships["target_from_form"][target_id].append({ "form_id": form_id, "name": form.get('名称', ''), "type": dimension_2, "support_reason": support_point.get('支撑理由', '') }) # 3. 构建形式点到实质点的支撑关系 for form in all_forms: form_id = form.get('id', '') if not form_id: continue dimension_2 = form.get('维度', {}).get('二级', '') support_data = form.get('支撑', []) if not support_data: continue # 初始化形式点的支撑关系 if form_id not in relationships["form_to_substance"]: relationships["form_to_substance"][form_id] = [] # 支撑字段可能是列表或字典 support_items = [] if isinstance(support_data, list): # 列表格式:[{id, 名称}, ...] support_items = support_data elif isinstance(support_data, dict): # 字典格式:{'具体元素': [...], '具象概念': [...]} for _category, items in support_data.items(): if isinstance(items, list): support_items.extend(items) for support_item in support_items: if not isinstance(support_item, dict): continue substance_id = support_item.get('id', '') substance_name = support_item.get('名称', '') if not substance_id: continue # 形式点 → 实质点 relationships["form_to_substance"][form_id].append({ "substance_id": substance_id, "name": substance_name }) # 实质点 ← 形式点(反向) if substance_id not in relationships["substance_from_form"]: relationships["substance_from_form"][substance_id] = [] relationships["substance_from_form"][substance_id].append({ "form_id": form_id, "name": form.get('名称', ''), "type": dimension_2 }) return relationships