Kaynağa Gözat

个人画像-知识点图谱更改

吴朋磊 2 ay önce
ebeveyn
işleme
d21a6e783a

+ 229 - 128
src/views/analysisReport/personalProfile/zeroScoreKnowledge.vue

@@ -1,32 +1,25 @@
 <template>
   <div class="knowledge_graph">
-    <!-- 顶部切换按钮 -->
-    <div class="graph_header" >
-      <!-- 学生模式:显示对比选择器和视图切换按钮 -->
-      <div class="comparison_selector">
-        <el-button-group>
-          <el-button v-for="option in comparisonOptions" :key="option.key"
-            :type="activeComparison === option.key ? 'primary' : 'default'" @click="activeComparison = option.key">
-            {{ option.label }}
-          </el-button>
-        </el-button-group>
-      </div>
-    </div>
+
 
     <div class="graph_header" v-if="activeView === 'list'">
       <!-- 自定义图例 -->
       <div class="legend">
         <div class="legend_item" :class="{ 'selected': selectedLegend.weak }" @click="toggleLegend('weak')">
           <span class="legend_dot weak" :style="selectedLegend.weak ? {} : { backgroundColor: '#ccc' }"></span>
-          <span class="legend_text" :style="selectedLegend.weak ? {} : { color: '#999999' }">{{ '薄弱(0%≤得分率<60%)' }}</span>
+          <span class="legend_text" :style="selectedLegend.weak ? {} : { color: '#999999' }">{{ '薄弱(0%≤得分率<60%)'
+              }}</span>
         </div>
         <div class="legend_item" :class="{ 'selected': selectedLegend.good }" @click="toggleLegend('good')">
           <span class="legend_dot good" :style="selectedLegend.good ? {} : { backgroundColor: '#ccc' }"></span>
-          <span class="legend_text" :style="selectedLegend.good ? {} : { color: '#999999' }">{{ '良好(60%≤得分率<85%)' }}</span>
+          <span class="legend_text" :style="selectedLegend.good ? {} : { color: '#999999' }">{{ '良好(60%≤得分率<85%)'
+              }}</span>
         </div>
         <div class="legend_item" :class="{ 'selected': selectedLegend.excellent }" @click="toggleLegend('excellent')">
-          <span class="legend_dot excellent" :style="selectedLegend.excellent ? {} : { backgroundColor: '#ccc' }"></span>
-          <span class="legend_text" :style="selectedLegend.excellent ? {} : { color: '#999999' }">{{ '优秀(85%≤得分率)' }}</span>
+          <span class="legend_dot excellent"
+            :style="selectedLegend.excellent ? {} : { backgroundColor: '#ccc' }"></span>
+          <span class="legend_text" :style="selectedLegend.excellent ? {} : { color: '#999999' }">{{ '优秀(85%≤得分率)'
+            }}</span>
         </div>
       </div>
       <!-- 视图切换按钮 - 移到knowledge_graph容器下 -->
@@ -57,15 +50,20 @@
           <div class="legend">
             <div class="legend_item" :class="{ 'selected': selectedLegend.weak }" @click="toggleLegend('weak')">
               <span class="legend_dot weak" :style="selectedLegend.weak ? {} : { backgroundColor: '#ccc' }"></span>
-              <span class="legend_text" :style="selectedLegend.weak ? {} : { color: '#999999' }">{{ '薄弱(0%≤得分率<60%)' }}</span>
+              <span class="legend_text" :style="selectedLegend.weak ? {} : { color: '#999999' }">{{ '薄弱(0%≤得分率<60%)'
+                  }}</span>
             </div>
             <div class="legend_item" :class="{ 'selected': selectedLegend.good }" @click="toggleLegend('good')">
               <span class="legend_dot good" :style="selectedLegend.good ? {} : { backgroundColor: '#ccc' }"></span>
-              <span class="legend_text" :style="selectedLegend.good ? {} : { color: '#999999' }">{{ '良好(60%≤得分率<85%)' }}</span>
+              <span class="legend_text" :style="selectedLegend.good ? {} : { color: '#999999' }">{{ '良好(60%≤得分率<85%)'
+                  }}</span>
             </div>
-            <div class="legend_item" :class="{ 'selected': selectedLegend.excellent }" @click="toggleLegend('excellent')">
-              <span class="legend_dot excellent" :style="selectedLegend.excellent ? {} : { backgroundColor: '#ccc' }"></span>
-              <span class="legend_text" :style="selectedLegend.excellent ? {} : { color: '#999999' }">{{ '优秀(85%≤得分率)' }}</span>
+            <div class="legend_item" :class="{ 'selected': selectedLegend.excellent }"
+              @click="toggleLegend('excellent')">
+              <span class="legend_dot excellent"
+                :style="selectedLegend.excellent ? {} : { backgroundColor: '#ccc' }"></span>
+              <span class="legend_text" :style="selectedLegend.excellent ? {} : { color: '#999999' }">{{ '优秀(85%≤得分率)'
+                }}</span>
             </div>
           </div>
           <!-- 视图切换按钮  -->
@@ -108,21 +106,20 @@
             <span>暂无数据</span>
           </div>
           <!-- 正常列表数据 -->
-           
+
           <div class="list_item" v-for="(item, index) in knowledgeItems" :key="index"
             @click="handleItemClick(item, index)" :class="{ active: selectedIndex === index }" v-else>
             <div class="item_header">
-              <span class="item_dot" :style="{ backgroundColor: getDotColor(item) }"></span>
+              <span class="item_dot" :style="{ backgroundColor: getDotColor(item, 'personalScoreRate') }"></span>
               <el-tooltip :content="item.knowledgeName" placement="top" effect="light"
                 :disabled="!item.knowledgeName || item.knowledgeName.length < 15">
                 <span class="item_title">{{ item.knowledgeName }}</span>
               </el-tooltip>
-              <span class="item_tag" 
-                v-if="item.scoreRateDiff" :style="{ backgroundColor: parseFloat(item.scoreRateDiff) > 0 ? '#3BA272' : '#F56C6C' }">
+              <span class="item_tag" v-if="item.scoreRateDiff"
+                :style="{ backgroundColor: parseFloat(item.scoreRateDiff) > 0 ? '#3BA272' : '#F56C6C' }">
                 {{ item.scoreRateDiff }}%
               </span>
-              <span class="item_tag" 
-                v-if="item.isPush == 1" style="background-color: #2E64FA;">
+              <span class="item_tag" v-if="item.isPush == 1" style="background-color: #2E64FA;">
                 有推题
               </span>
             </div>
@@ -131,11 +128,13 @@
               <!-- 班级/学生得分率 -->
               <span class="item_score">
                 <span class="score_label" v-if="item.personalScoreRate">个人得分率:</span>
-                <span :style="{color: getDotColor(item)}" v-if="item.personalScoreRate">{{ item.personalScoreRate }}%</span>
+                <span :style="{ color: getDotColor(item, 'personalScoreRate') }" v-if="item.personalScoreRate">{{
+                  item.personalScoreRate }}%</span>
                 <span class="score_separator" v-if="item.classScoreRate">|</span>
                 <span class="score_label">班级得分率:</span>
                 <span v-if="item.classScoreRate" class="score_second">{{ item.classScoreRate }}%</span>
-                <span v-if="!item.classScoreRate" :style="{color: getDotColor(item)}">{{ item.classScoreRate }}%</span>
+                <span v-if="!item.classScoreRate" :style="{ color: getDotColor(item, 'classScoreRate') }">{{
+                  item.classScoreRate }}%</span>
               </span>
 
               <!-- 班级/学生得分率 -->
@@ -152,7 +151,7 @@
       <vxe-table ref="treeTable" :data="tableData" style="width: 100%;" maxHeight="480px" border show-header
         :tree-config="{ childrenField: 'children', hasChildField: 'hasChildren', showIcon: true, iconOpen: 'el-icon-remove', iconClose: 'el-icon-circle-plus' }"
         :scroll-y="{ enabled: true, gt: 480 }" fixed-header :header-cell-style="{ color: '#333' }"
-        @row-click="handleRowClick" @cell-click="handleCellClick" :row-class-name="rowClassName" >
+        @row-click="handleRowClick" @cell-click="handleCellClick" :row-class-name="rowClassName">
 
         <vxe-table-column type="tree" tree-node prop="title" :title="subjectName">
           <template #default="{ row }">
@@ -163,7 +162,7 @@
         </vxe-table-column>
 
         <!-- 个人得分率 -->
-        <vxe-table-column  prop="personalScoreRate" title="个人得分率" width="180" align="center">
+        <vxe-table-column prop="personalScoreRate" title="个人得分率" width="180" align="center">
           <template #default="{ row }">
             <div class="rate_info" v-if="row.personalScoreRate !== null">
               <span class="rate_dot" :class="getRateClass(row.personalScoreRate)"></span>
@@ -184,7 +183,7 @@
         </vxe-table-column>
 
         <!-- 班级得分率 -->
-        <vxe-table-column  prop="classScoreRate" title="班级得分率" width="180" align="center">
+        <vxe-table-column prop="classScoreRate" title="班级得分率" width="180" align="center">
           <template #default="{ row }">
             <div class="rate_info" v-if="row.classScoreRate !== null">
               <span class="rate_dot" :class="getRateClass(row.classScoreRate)"></span>
@@ -205,8 +204,7 @@
         </vxe-table-column>
 
         <!-- 只有当班级名称不是年级且不为空时,才显示得分率差列 -->
-        <vxe-table-column  prop="diff" title="得分率差" width="150"
-          align="center">
+        <vxe-table-column prop="diff" title="得分率差" width="150" align="center">
           <template #default="{ row }">
             <div class="rate_info" v-if="row.scoreRateDiff !== null">
               <span class="rate_dot" :class="getRateClass(row.scoreRateDiff)"></span>
@@ -295,17 +293,6 @@ export default {
       _isFirstRender: true,
       // Tab切换状态
       activeTab: 'all',
-      // 对比选择器数据
-      activeComparison: 'grade', // 默认对比年级
-      studentPosition: 'C层', // 学生位置
-      comparisonOptions: [
-        // { key: 'grade', label: '对比年级' },
-        // { key: 'a', label: '对比A层' },
-        // { key: 'b', label: '对比B层' },
-        // { key: 'c', label: '对比C层' },
-        // { key: 'd', label: '对比D层' },
-        // { key: 'e', label: '对比E层' }
-      ],
       // 图例选中状态
       selectedLegend: {
         weak: true,
@@ -345,7 +332,7 @@ export default {
     // 监听classLevel变化,当对比选择器数据变化时更新对比选项
     classLevel: {
       handler(newVal, oldVal) {
-        
+
       },
       immediate: true
     },
@@ -378,7 +365,7 @@ export default {
     // 监听tab切换,更新选中索引并通知父组件
     activeTab(newTab, oldTab) {
       this.selectedIndex = 0;
-      
+
       // 根据当前tab获取对应的数据列表
       const currentList = this.knowledgeItems;
       // 如果有数据,更新selectedKnowledgeId为第一条数据的ID
@@ -486,8 +473,8 @@ export default {
         }
         this.selectedIndex = 0;
         selectedItem = this.fatalVulnerability[0];
-      } 
-      
+      }
+
       // 如果有选中项,更新selectedKnowledgeId,实现初始化默认选择
       if (selectedItem) {
         this.selectedKnowledgeId = selectedItem.knowledgeId;
@@ -496,7 +483,7 @@ export default {
           this.updateChart();
         }
       }
-      
+
       // 只有当tab值实际发生变化时,才触发选中事件
       // 初始化时不触发,避免重复调用接口
       if (this._isMounted && oldActiveTab !== this.activeTab) {
@@ -507,11 +494,11 @@ export default {
     // 递归收集所有节点的key,用于展开所有树形节点
     collectAllRowKeys() {
       const keys = [];
-      
+
       // 递归函数,收集所有有children的节点key
       const collectKeys = (data) => {
         if (!data || !Array.isArray(data)) return;
-        
+
         data.forEach(item => {
           // 如果节点有children,将其key添加到keys数组中
           if (item.children && item.children.length > 0) {
@@ -522,10 +509,10 @@ export default {
           }
         });
       };
-      
+
       // 调用递归函数
       collectKeys(this.tableData);
-      
+
       // 更新expandRowKeys数组
       this.expandRowKeys = keys;
     },
@@ -547,7 +534,7 @@ export default {
           });
         };
         collectExpandNodes(this.tableData);
-        
+
         // 使用vxe-table 3.7.5兼容的API展开所有节点
         if (treeTable.setExpandRows) {
           // 如果支持setExpandRows方法
@@ -571,25 +558,25 @@ export default {
     classIsGroup() {
       if (this.classLevel == 1) {
         return true;
-      }else
-      return false;
+      } else
+        return false;
     },
 
     // 切换图例选中状态
     toggleLegend(type) {
       this.selectedLegend[type] = !this.selectedLegend[type];
-      
+
       // 生成scoreRateTypes数组
       let scoreRateTypes = [];
       if (this.selectedLegend.weak) scoreRateTypes.push(1);
       if (this.selectedLegend.good) scoreRateTypes.push(2);
       if (this.selectedLegend.excellent) scoreRateTypes.push(3);
-      
+
       // 如果包含所有值,则传null,否则传数组
       if (scoreRateTypes.length === 3) {
         scoreRateTypes = null;
       }
-      
+
       // 向父组件发送图例变化事件,包含scoreRateTypes和当前activeTab对应的knowledgeType
       let knowledgeType = 0;
       if (this.activeTab === 'highFreq') {
@@ -599,9 +586,9 @@ export default {
       } else {
         knowledgeType = 0;
       }
-      
+
       this.$emit('legend-change', { scoreRateTypes, knowledgeType });
-      
+
     },
 
     // 根据得分率获取对应的颜色
@@ -616,28 +603,65 @@ export default {
       }
     },
 
-    // 根据屏幕宽度计算合适的缩放值
-    getZoomValue() {
-      const screenWidth = window.innerWidth;
-      if (screenWidth < 1100) {
-        return 1.0; // 小屏幕
-      } else if (screenWidth >= 1100 && screenWidth <= 1200) {
-        return 1.15; // 中等屏幕
-      } else {
-        return 1.2; // 超大屏幕
-      }
-    },
-
-    // 更新图表缩放
-    updateChartZoom() {
+    // 更新图表缩放和布局参数,防止窗口变化时图表变形
+    updateChartLayout() {
       if (this.chart) {
-        const zoom = this.getZoomValue();
+        // 重新计算最外层知识点数量
+        const countOutermostNodes = (data) => {
+          let count = 0;
+          const traverse = (nodes) => {
+            nodes.forEach(node => {
+              if (node.children && node.children.length > 0) {
+                traverse(node.children);
+              } else {
+                count++;
+              }
+            });
+          };
+          traverse(data);
+          return count;
+        };
+        
+        const outermostCount = countOutermostNodes(this.tableData);
+        
+        // 重新计算合适的缩放比例
+        const getOptimalZoom = () => {
+          const screenWidth = window.innerWidth;
+          let zoom = 1.05;
+          
+          if (screenWidth < 1100) {
+            zoom = 1.05;
+          } else if (screenWidth >= 1100 && screenWidth <= 1200) {
+            zoom = 1.05;
+          } else {
+            zoom = 1.05;
+          }
+          
+          if (outermostCount <= 5) {
+            zoom *= 1.0;
+          }
+          
+          return zoom;
+        };
+        
+        // 重新计算内外半径
+        const getOptimalRadius = () => {
+          if (outermostCount <= 5) {
+            return ['20%', '65%'];
+          }
+          return ['12%', '75%'];
+        };
+        
+        // 更新图表的所有动态参数
         this.chart.setOption({
-          series: [
-            {
-              zoom: zoom,
-            }
-          ]
+          series: [{
+            // 更新缩放比例
+            zoom: getOptimalZoom(),
+            // 更新内外半径
+            radius: getOptimalRadius(),
+            // 更新层级间距
+            layerPadding: outermostCount <= 5 ? [20, 10] : [10, 5]
+          }]
         });
       }
     },
@@ -678,6 +702,10 @@ export default {
         // 根据得分率获取对应的级别
         const getNodeLevel = (scoreRate) => {
           const rate = parseFloat(scoreRate);
+          // 处理scoreRate为null、undefined或非数字的情况
+          if (isNaN(rate)) {
+            return 'weak'; // 默认为薄弱
+          }
           if (rate >= 85) {
             return 'excellent'; // 优秀
           } else if (rate >= 60) {
@@ -707,13 +735,11 @@ export default {
             }
 
             // 获取节点级别,优先使用对应级别的得分率,若缺失则使用另一级别作为备选
-            const scoreRate = item.personalScoreRate
+            const scoreRate = item.personalScoreRate;
             const nodeLevel = getNodeLevel(scoreRate);
             
             // 计算节点样式,使用与nodeLevel相同的得分率逻辑
-            const itemColor = isOutermost ?
-              vm.getNodeColor(scoreRate) :
-              '#BFC1C7';
+            const itemColor = isOutermost ? vm.getNodeColor(scoreRate) : '#BFC1C7';
             // 仅对最外层节点应用图例过滤,非外层节点始终显示
             const shouldShow = !isOutermost || vm.selectedLegend[nodeLevel];
             
@@ -747,6 +773,57 @@ export default {
           });
         };
 
+        // 计算最外层知识点数量(叶子节点数量),用于动态调整布局
+        const countOutermostNodes = (data) => {
+          let count = 0;
+          const traverse = (nodes) => {
+            nodes.forEach(node => {
+              if (node.children && node.children.length > 0) {
+                traverse(node.children);
+              } else {
+                count++;
+              }
+            });
+          };
+          traverse(data);
+          return count;
+        };
+        
+        // 获取最外层知识点数量
+        const outermostCount = countOutermostNodes(this.tableData);
+        
+        // 计算合适的缩放比例,根据屏幕宽度和节点数量动态调整
+        const getOptimalZoom = () => {
+          const screenWidth = window.innerWidth;
+          let zoom = 1.05;
+          
+          // 根据屏幕宽度调整缩放
+          if (screenWidth < 1100) {
+            zoom = 1.05;
+          } else if (screenWidth >= 1100 && screenWidth <= 1200) {
+            zoom = 1.05;
+          } else {
+            zoom = 1.05;
+          }
+          
+          // 根据节点数量调整缩放,节点少的时候适当放大
+          if (outermostCount <= 5) {
+            zoom *= 1.0;
+          }
+          
+          return zoom;
+        };
+        
+        // 根据节点数量动态调整内外半径,防止节点遮盖
+        const getOptimalRadius = () => {
+          // 节点数量少的时候,增大内半径,缩小外半径,使节点分布更合理
+          if (outermostCount <= 5) {
+            return ['20%', '65%'];
+          }
+          // 节点数量多的时候,使用默认半径
+          return ['12%', '75%'];
+        };
+        
         // 配置项
         const option = {
           tooltip: {
@@ -756,11 +833,11 @@ export default {
                 // 根节点也属于非最外层节点,只显示名称
                 return params.name;
               }
-              
+
               // 检查节点是否为最外层节点(叶子节点)
               // 使用isOutermost属性或检查data.isOutermost
               const isOutermost = params.data && params.data.isOutermost;
-              
+
               if (isOutermost) {
                 // 最外层节点显示完整信息(名称+得分率)
                 return `${params.name}<br/>得分率: ${params.value !== null && params.value !== undefined ? params.value : '0'}%`;
@@ -782,26 +859,34 @@ export default {
               // 调整树状图布局参数,确保节点均匀分布
               orient: 'radial',
               roam: true,
-
-              // 使用基础配置实现居中
-              center: ['10%', '7%'],
-
-              zoom: this.getZoomValue(),
+              
+              // 使用边距控制图表位置,实现水平垂直居中
+              left: '8%',   // 左边距(百分比/像素)
+              right: '8%',  // 右边距
+              top: '8%',    // 上边距
+              bottom: '8%', // 下边距
+
+              // 根据节点数量动态调整内外半径,防止节点遮盖
+              radius: getOptimalRadius(),
+              
+              // 动态计算合适的缩放比例,根据屏幕宽度和节点数量调整
+              zoom: getOptimalZoom(),
               scaleLimit: {
                 min: 0.2,
                 max: 5
               },
 
-              // 调整节点大小比例和间距,确保图表在容器中居中
+              // 调整节点大小比例和间距,确保节点不遮盖
               nodeScaleRatio: 1,
-              layerPadding: [10, 5],
+              // 根据节点数量调整层级间距,节点少的时候增大间距
+              layerPadding: outermostCount <= 5 ? [20, 10] : [10, 5],
               roam: true,
 
               // 使用表格数据生成树形结构
               data: [
                 {
                   name: this.subjectName,
-                  symbolSize: 5,
+                  symbolSize: 5, // 根节点大小
                   value: this.subjectScoreRate, // 添加value属性,用于显示得分率
                   itemStyle: {
                     // 根节点为非最外层节点,使用#EBEEF5颜色
@@ -835,14 +920,14 @@ export default {
 
         // 初始化后调用resize确保图表正确显示
         this.chart.resize();
-        
+
         // 添加图表点击事件监听
         this.chart.on('click', (params) => {
           // 明确识别点击类型
           const isOuterNodeClick = params.data && params.data.isOutermost;
           const isEmptyAreaClick = !params.data || !params.componentType || params.componentType === '';
           const isNonOuterNodeClick = params.data && !params.data.isOutermost;
-          
+
           if (isOuterNodeClick) {
             // 处理最外层节点点击
             // 确定当前显示的列表数据
@@ -854,15 +939,15 @@ export default {
             } else {
               targetList = this.allKnowledgeList;
             }
-            
+
             // 1. 首先尝试直接从当前列表中根据名称查找
             let knowledgeItem = targetList.find(item => item.knowledgeName === params.name);
             let targetIndex = -1;
-            
+
             if (knowledgeItem) {
               targetIndex = targetList.findIndex(item => item.knowledgeId === knowledgeItem.knowledgeId);
-            } 
-            
+            }
+
             // 2. 如果在当前列表中找不到,尝试从其他列表中查找
             if (!knowledgeItem) {
               const allLists = [this.allKnowledgeList, this.highVulnerability, this.fatalVulnerability];
@@ -885,7 +970,7 @@ export default {
                 }
               }
             }
-            
+
             // 3. 如果还是找不到,尝试从tableData中查找
             if (!knowledgeItem) {
               const findKnowledgeItem = (data) => {
@@ -900,9 +985,9 @@ export default {
                 }
                 return null;
               };
-              
+
               knowledgeItem = findKnowledgeItem(this.tableData);
-              
+
               if (knowledgeItem) {
                 // 在所有列表中查找匹配的knowledgeId
                 const allLists = [this.allKnowledgeList, this.highVulnerability, this.fatalVulnerability];
@@ -928,21 +1013,21 @@ export default {
                 }
               }
             }
-            
+
             if (knowledgeItem && targetIndex !== -1) {
               // 向父组件发送事件
-              this.$emit('knowledge-item-click', { 
+              this.$emit('knowledge-item-click', {
                 item: knowledgeItem,
-                index: targetIndex 
+                index: targetIndex
               });
-              
+
               // 更新选中索引和选中知识点ID
               this.selectedIndex = targetIndex;
               this.selectedKnowledgeId = knowledgeItem.knowledgeId;
-              
+
               // 将首次渲染标志设为false,后续点击操作将应用透明度降低逻辑
               // this._isFirstRender = false;
-              
+
               // 重新生成图表数据,确保只有当前选中节点高亮
               this.chart.setOption({
                 series: [{
@@ -964,7 +1049,7 @@ export default {
                 animation: true,
                 animationDuration: 300
               });
-              
+
               // 滚动到选中项
               this.$nextTick(() => {
                 const listContainer = this.$el.querySelector('.knowledge_list');
@@ -973,13 +1058,25 @@ export default {
                   listContainer.scrollTop = listItems[targetIndex].offsetTop - 100;
                 }
               });
-            } 
+            } else {
+              // 打印详细调试信息
+              console.log('点击处理调试信息:', {
+                paramsName: params.name,
+                params: params,
+                knowledgeItem: knowledgeItem,
+                targetIndex: targetIndex,
+                activeTab: this.activeTab,
+                targetListLength: targetList.length,
+                targetListSample: targetList.slice(0, 3),
+                tableDataSample: this.tableData.slice(0, 1)
+              });
+            }
           }
           else if (isEmptyAreaClick || isNonOuterNodeClick) {
             // 点击空白区域或非最外层节点,恢复所有节点透明度
             // 清空selectedKnowledgeId,确保所有节点都高亮
             this.selectedKnowledgeId = '';
-            
+
             // 调用generateTreeData时传入overrideKnowledgeId为空字符串,确保所有节点都不透明
             const updatedOption = {
               series: [{
@@ -1004,11 +1101,11 @@ export default {
               animation: true,
               animationDuration: 300
             });
-            
+
             // 向父组件发送事件,清除选中的知识点ID
-            this.$emit('knowledge-item-click', { 
+            this.$emit('knowledge-item-click', {
               item: null,
-              index: -1 
+              index: -1
             });
           }
         });
@@ -1017,7 +1114,7 @@ export default {
         window.addEventListener('resize', () => {
           if (this.chart) {
             this.chart.resize();
-            this.updateChartZoom();
+            this.updateChartLayout();
           }
         });
       }
@@ -1080,7 +1177,7 @@ export default {
       this.selectedKnowledgeId = item.knowledgeId;
       // 向父组件发送事件,传递点击的知识点数据
       this.$emit('knowledge-item-click', { item, index });
-      
+
       // 如果当前是图形视图且图表已初始化,更新图表选中状态
       if (this.activeView === 'graph' && this.chart) {
         this.updateChart();
@@ -1108,9 +1205,9 @@ export default {
     },
 
     // 根据知识点得分率获取对应的点颜色
-    getDotColor(item) {
-      // 优先使用classScoreRate,若不存在或为空则使用gradeScoreRate
-      const scoreRate = item.personalScoreRate;
+    getDotColor(item, scoreRateType) {
+      // 个人得分率personalScoreRate
+      const scoreRate = scoreRateType === 'personalScoreRate' ? item.personalScoreRate : item.classScoreRate;
       const rate = parseFloat(scoreRate);
       if (rate >= 85) {
         return '#3BA272'; // 优秀 - 绿色
@@ -1168,6 +1265,7 @@ export default {
         opacity: 0.7;
         transition: all 0.3s ease;
         font-weight: 500;
+
         &.selected {
           opacity: 1;
         }
@@ -1371,7 +1469,6 @@ export default {
 
     .knowledge_right_container {
       width: 350px;
-      height: 630px;
       display: flex;
       flex-direction: column;
     }
@@ -1383,7 +1480,6 @@ export default {
       border: 1px solid #E9EBEF;
       position: relative;
       padding: 20px;
-      height: 590px;
       overflow: hidden;
 
       .top_container {
@@ -1410,6 +1506,7 @@ export default {
           opacity: 0.7;
           transition: all 0.3s ease;
           font-weight: 500;
+
           &.selected {
             opacity: 1;
           }
@@ -1467,7 +1564,9 @@ export default {
       }
 
       .chart {
-        width: 100%;
+        display: flex;
+        justify-content: center;
+        align-items: center;
         min-height: 590px;
       }
 
@@ -1647,7 +1746,7 @@ export default {
         border-radius: 8px;
         overflow-y: auto;
         overflow-x: hidden;
-        
+
         // 使用CSS变量设置全局行高
         --vxe-ui-table-row-height-default: 20px !important;
 
@@ -1668,6 +1767,7 @@ export default {
 
         // 行样式 - 使用更具体的选择器
         .vxe-table--body {
+
           // 表格行样式
           tbody {
             tr {
@@ -1695,7 +1795,7 @@ export default {
             }
           }
         }
-        
+
         // 单元格样式,设置内边距为0,确保行高由行高属性控制
         .vxe-body--column,
         .vxe-header--column {
@@ -1705,7 +1805,7 @@ export default {
           min-height: 20px !important;
           max-height: 20px !important;
         }
-        
+
         // 表格主体最小高度设置
         .vxe-table--body {
           min-height: 0 !important;
@@ -1775,6 +1875,7 @@ export default {
       position: absolute;
       top: 8px;
       left: 2px;
+
       &.rate_excellent {
         background-color: #3BA272;
       }