Browse Source

fix: 修复折叠展开功能失效问题

问题原因:
- 不同类型的点(灵感点/关键点/目的点)使用相同的索引生成ID
- 导致HTML中出现重复ID,getElementById只能获取第一个匹配元素
- 部分点的折叠展开功能失效

修复方案:
- 在元素ID中加入点类型区分(current_point_type)
- ID格式从 post-{idx}-insp-{idx}-feat-{idx} 改为 post-{idx}-{type}-{idx}-feat-{idx}
- 确保所有元素ID唯一,折叠展开功能正常工作
- 添加event.stopPropagation()防止事件冒泡

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
yangxiaohui 1 week ago
parent
commit
f6ed3307f2
1 changed files with 29 additions and 11 deletions
  1. 29 11
      script/data_processing/visualize_how_results.py

+ 29 - 11
script/data_processing/visualize_how_results.py

@@ -546,7 +546,7 @@ def generate_match_results_html(how_steps: List[Dict], feature_idx: int, insp_id
             continue
             continue
 
 
         # 生成该层级的折叠区域
         # 生成该层级的折叠区域
-        level_section_id = f"post-{post_idx}-insp-{insp_idx}-feat-{feature_idx}-level-{level_name}"
+        level_section_id = f"post-{post_idx}-{current_point_type}-{insp_idx}-feat-{feature_idx}-level-{level_name}"
 
 
         # 找出该层级的最高分匹配
         # 找出该层级的最高分匹配
         all_level_matches = level_data["标签"] + level_data["分类"]
         all_level_matches = level_data["标签"] + level_data["分类"]
@@ -604,7 +604,7 @@ def generate_match_results_html(how_steps: List[Dict], feature_idx: int, insp_id
 
 
         matches_html += f'''
         matches_html += f'''
         <div class="level-group-section">
         <div class="level-group-section">
-            <div class="level-group-header" onclick="toggleMatchGroup('{level_section_id}')">
+            <div class="level-group-header" onclick="toggleMatchGroup(event, '{level_section_id}')">
                 <div class="level-header-left">
                 <div class="level-header-left">
                     <span class="expand-icon" id="{level_section_id}-icon">▶</span>
                     <span class="expand-icon" id="{level_section_id}-icon">▶</span>
                     <h4 class="level-group-title">{feature_number}.{level_index} 匹配人设{level_name} ({total_count})</h4>
                     <h4 class="level-group-title">{feature_number}.{level_index} 匹配人设{level_name} ({total_count})</h4>
@@ -618,7 +618,7 @@ def generate_match_results_html(how_steps: List[Dict], feature_idx: int, insp_id
         # 该层级下的标签分组
         # 该层级下的标签分组
         subgroup_index = 1
         subgroup_index = 1
         if level_data["标签"]:
         if level_data["标签"]:
-            group_id = f"post-{post_idx}-insp-{insp_idx}-feat-{feature_idx}-level-{level_name}-label"
+            group_id = f"post-{post_idx}-{current_point_type}-{insp_idx}-feat-{feature_idx}-level-{level_name}-label"
             group_matches_html = ""
             group_matches_html = ""
 
 
             # 找出标签中的最高分
             # 找出标签中的最高分
@@ -666,7 +666,7 @@ def generate_match_results_html(how_steps: List[Dict], feature_idx: int, insp_id
 
 
             matches_html += f'''
             matches_html += f'''
             <div class="match-subgroup-section">
             <div class="match-subgroup-section">
-                <div class="match-subgroup-header" onclick="toggleMatchGroup('{group_id}')">
+                <div class="match-subgroup-header" onclick="toggleMatchGroup(event, '{group_id}')">
                     <div class="subgroup-header-left">
                     <div class="subgroup-header-left">
                         <span class="expand-icon" id="{group_id}-icon">▼</span>
                         <span class="expand-icon" id="{group_id}-icon">▼</span>
                         <h5 class="match-subgroup-title">{feature_number}.{level_index}.{subgroup_index} 标签 ({len(level_data["标签"])})</h5>
                         <h5 class="match-subgroup-title">{feature_number}.{level_index}.{subgroup_index} 标签 ({len(level_data["标签"])})</h5>
@@ -682,7 +682,7 @@ def generate_match_results_html(how_steps: List[Dict], feature_idx: int, insp_id
 
 
         # 该层级下的分类分组
         # 该层级下的分类分组
         if level_data["分类"]:
         if level_data["分类"]:
-            group_id = f"post-{post_idx}-insp-{insp_idx}-feat-{feature_idx}-level-{level_name}-category"
+            group_id = f"post-{post_idx}-{current_point_type}-{insp_idx}-feat-{feature_idx}-level-{level_name}-category"
             group_matches_html = ""
             group_matches_html = ""
 
 
             # 找出分类中的最高分
             # 找出分类中的最高分
@@ -730,7 +730,7 @@ def generate_match_results_html(how_steps: List[Dict], feature_idx: int, insp_id
 
 
             matches_html += f'''
             matches_html += f'''
             <div class="match-subgroup-section">
             <div class="match-subgroup-section">
-                <div class="match-subgroup-header" onclick="toggleMatchGroup('{group_id}')">
+                <div class="match-subgroup-header" onclick="toggleMatchGroup(event, '{group_id}')">
                     <div class="subgroup-header-left">
                     <div class="subgroup-header-left">
                         <span class="expand-icon" id="{group_id}-icon">▼</span>
                         <span class="expand-icon" id="{group_id}-icon">▼</span>
                         <h5 class="match-subgroup-title">{feature_number}.{level_index}.{subgroup_index} 分类 ({len(level_data["分类"])})</h5>
                         <h5 class="match-subgroup-title">{feature_number}.{level_index}.{subgroup_index} 分类 ({len(level_data["分类"])})</h5>
@@ -789,7 +789,7 @@ def generate_match_results_html(how_steps: List[Dict], feature_idx: int, insp_id
 
 
     html = f'''
     html = f'''
     <div class="match-results-section">
     <div class="match-results-section">
-        <div class="match-section-header collapsible-header" onclick="toggleFeatureSection('{section_id}')">
+        <div class="match-section-header collapsible-header" onclick="toggleFeatureSection(event, '{section_id}')">
             <div class="header-left">
             <div class="header-left">
                 <span class="expand-icon" id="{section_id}-icon">▼</span>
                 <span class="expand-icon" id="{section_id}-icon">▼</span>
                 <h4>{feature_number}. 匹配结果: {html_module.escape(feature_name)} <span class="feature-weight-display">(权重: {feature_weight})</span></h4>
                 <h4>{feature_number}. 匹配结果: {html_module.escape(feature_name)} <span class="feature-weight-display">(权重: {feature_weight})</span></h4>
@@ -3150,11 +3150,20 @@ def generate_combined_html(posts_data: List[Dict], category_mapping: Dict = None
                 }}
                 }}
             }}
             }}
 
 
-            function toggleFeatureSection(sectionId) {{
+            function toggleFeatureSection(event, sectionId) {{
+                event.stopPropagation();
+
                 var content = document.getElementById(sectionId + '-content');
                 var content = document.getElementById(sectionId + '-content');
                 var icon = document.getElementById(sectionId + '-icon');
                 var icon = document.getElementById(sectionId + '-icon');
 
 
-                if (content.style.display === 'none') {{
+                if (!content || !icon) {{
+                    console.error('Element not found:', sectionId);
+                    return;
+                }}
+
+                var isHidden = content.style.display === 'none' || !content.style.display || window.getComputedStyle(content).display === 'none';
+
+                if (isHidden) {{
                     content.style.display = 'flex';
                     content.style.display = 'flex';
                     icon.textContent = '▼';
                     icon.textContent = '▼';
                 }} else {{
                 }} else {{
@@ -3176,11 +3185,20 @@ def generate_combined_html(posts_data: List[Dict], category_mapping: Dict = None
                 }}
                 }}
             }}
             }}
 
 
-            function toggleMatchGroup(groupId) {{
+            function toggleMatchGroup(event, groupId) {{
+                event.stopPropagation();
+
                 var content = document.getElementById(groupId + '-content');
                 var content = document.getElementById(groupId + '-content');
                 var icon = document.getElementById(groupId + '-icon');
                 var icon = document.getElementById(groupId + '-icon');
 
 
-                if (content.style.display === 'none') {{
+                if (!content || !icon) {{
+                    console.error('Element not found:', groupId);
+                    return;
+                }}
+
+                var isHidden = content.style.display === 'none' || !content.style.display || window.getComputedStyle(content).display === 'none';
+
+                if (isHidden) {{
                     // 根据class决定使用什么display值
                     // 根据class决定使用什么display值
                     if (content.classList.contains('match-subgroup-content')) {{
                     if (content.classList.contains('match-subgroup-content')) {{
                         content.style.display = 'flex';
                         content.style.display = 'flex';