소스 검색

个人画像-知识点图谱添加筛选条件

吴朋磊 2 달 전
부모
커밋
9f54e7bff3
3개의 변경된 파일170개의 추가작업 그리고 71개의 파일을 삭제
  1. 6 2
      src/http/api/personalProfile.js
  2. 81 11
      src/views/analysisReport/personalProfile/index.vue
  3. 83 58
      src/views/analysisReport/personalProfile/zeroScoreKnowledge.vue

+ 6 - 2
src/http/api/personalProfile.js

@@ -11,8 +11,12 @@ const report = {
         return post(`${base.prefix}/api/v1/studentPinpoint/examKnowledgePointTrack`,data);
     },
     // 知识点图谱
-    knowledgeTreeData(data){
-        return post(`${base.prefix}/api/v1/studentPinpoint/knowledgeTreeData`,data);
+    studentKnowledgeGraph(data){
+        return post(`${base.prefix}/api/v1/studentPinpoint/studentKnowledgeGraph`,data);
+    },
+    // 知识点树
+    studentKnowledgeDataTree(data){
+        return post(`${base.prefix}/api/v1/studentPinpoint/studentKnowledgeDataTree`,data);
     },
     // 历次变化
     knowledgeExamPrevious(data){

+ 81 - 11
src/views/analysisReport/personalProfile/index.vue

@@ -23,6 +23,7 @@
             :high-vulnerability="highVulnerability" 
             :all-knowledge-list="allKnowledgeList"
             @activeTabChange="handleActiveTabChange" 
+            @legend-change="handleLegendChange"
             v-loading="zeroloading"
         />
 
@@ -289,7 +290,6 @@ export default {
                         if (data.dropKnowledgeList) {
                             this.knowledgeMapData.dropKnowledgeList = data.dropKnowledgeList.join('、') || '';
                         }
-                        console.log(this.knowledgeMapData.knowledgeList);
                     }else{
                         // 加载状态
                         this.knowledgeloading = false;
@@ -332,15 +332,13 @@ export default {
                 subjectCode: this.portraitData.subjectCode, //学科code
                 knowledgeId: this.portraitData.knowledgeId, //	知识点id(针对历次和试题查询)
             };
-            this.$api.personalProfile.knowledgeTreeData(examParams).then(res => {
+            this.$api.personalProfile.studentKnowledgeGraph(examParams).then(res => {
                 if (res.code === 200) {
                     let data = res.data;
                     if (data) {
                         // 加载状态-清空数据
                         this.zeroloading = false;
 
-                        // 知识点树状图数据
-                        this.treeData = data.tree || [];
                         // 将字符串转换为数字类型
                         this.subjectScoreRate = parseFloat(data.subjectScoreRate) || 0; //科目得分率
                         // 零分知识点数据
@@ -350,12 +348,9 @@ export default {
                         // 所有知识点数据
                         this.allKnowledgeList = data.allKnowledgeList || [];
 
-                        // 接口调用成功后,刷新图表
-                        this.$nextTick(() => {
-                            if (this.$refs.knowledgeGraphRef) {
-                                this.$refs.knowledgeGraphRef.updateChart();
-                            }
-                        });
+                        // 新增:调用studentKnowledgeDataTree API获取treeData
+                        this.getStudentKnowledgeDataTree();
+                        
                         // 获取知识点第一条数据id 全部>高频错题>零分知识点
                         if (this.allKnowledgeList.length > 0) {
                             this.knowledgeName = this.allKnowledgeList[0].knowledgeName || '';
@@ -373,7 +368,6 @@ export default {
                             }
                         }
                         
-                        
                         // 首次加载默认获取知识点
                         this.KnowledgeTrackData();
                         // 加载推送试题
@@ -410,6 +404,58 @@ export default {
                 }
             })
         },
+        
+        // 新增:获取知识点树状图数据
+        getStudentKnowledgeDataTree(knowledgeType = 0, scoreRateTypes = null) {
+            this.treeData = [];
+            let params = {
+                examId: this.portraitData.examId, //当前考试id
+                examIds: this.portraitData.examIds, //历次考试ids
+                subjectCode: this.portraitData.subjectCode, //学科code
+                knowledgeId: this.portraitData.knowledgeId, //知识点id(针对历次和试题查询)
+                scoreRateTypes: scoreRateTypes, // 得分率类型 1薄弱 2良好 3优秀(精准提升),为空是全部
+                knowledgeType: knowledgeType // 知识点类型 0全部 1高频错题知识点 2零分知识点(精准提升)
+            };
+            
+            this.$api.personalProfile.studentKnowledgeDataTree(params).then(res => {
+                if (res.code === 200) {
+                    let data = res.data;
+                    if (data) {
+                        // 从新API获取treeData
+                        this.treeData = data || [];
+                        
+                        // 接口调用成功后,刷新图表
+                        this.$nextTick(() => {
+                            if (this.$refs.knowledgeGraphRef) {
+                                this.$refs.knowledgeGraphRef.updateChart();
+                            }
+                        });
+                    } else {
+                        this.treeData = [];
+                        // 接口调用成功后,刷新图表
+                        this.$nextTick(() => {
+                            if (this.$refs.knowledgeGraphRef) {
+                                this.$refs.knowledgeGraphRef.updateChart();
+                            }
+                        });
+                    }
+                } else {
+                    this.treeData = [];
+                    // 接口调用成功后,刷新图表
+                    this.$nextTick(() => {
+                        if (this.$refs.knowledgeGraphRef) {
+                            this.$refs.knowledgeGraphRef.updateChart();
+                        }
+                    });
+                }
+            });
+        },
+        
+        // 处理图例变化事件
+        handleLegendChange(data) {
+            // 调用getStudentKnowledgeDataTree方法,传递knowledgeType和scoreRateTypes
+            this.getStudentKnowledgeDataTree(data.knowledgeType, data.scoreRateTypes);
+        },
 
         // 获取历次变化数据
         KnowledgeTrackData() {
@@ -542,8 +588,11 @@ export default {
             // highFreq 高频
             // zero 零分
             // all 所有知识点
+            let knowledgeType = 0;
+            
             if (tab === 'highFreq') {
                 // 高频知识点
+                knowledgeType = 1;
                 if(this.highVulnerability.length > 0) {
                     this.knowledgeId = this.highVulnerability[0].knowledgeId ;
                     this.knowledgeName = this.highVulnerability[0].knowledgeName;
@@ -553,6 +602,7 @@ export default {
                 }
             } else if (tab === 'zero') {
                 // 零分知识点
+                knowledgeType = 2;
                 if(this.fatalVulnerability.length > 0) {
                     this.knowledgeId = this.fatalVulnerability[0].knowledgeId || 0;
                     this.knowledgeName = this.fatalVulnerability[0].knowledgeName || '';
@@ -562,6 +612,7 @@ export default {
                 }
             } else if (tab === 'all') {
                 // 所有知识点
+                knowledgeType = 0;
                 if(this.allKnowledgeList.length > 0) {
                     this.knowledgeId = this.allKnowledgeList[0].knowledgeId || 0;
                     this.knowledgeName = this.allKnowledgeList[0].knowledgeName || '';
@@ -570,6 +621,25 @@ export default {
                     this.knowledgeName = '';
                 }
             }
+            
+            // 重置图例状态:让三个图例恢复成原先的模样
+            if (this.$refs.knowledgeGraphRef) {
+                this.$refs.knowledgeGraphRef.selectedLegend = {
+                    weak: true,
+                    good: true,
+                    excellent: true
+                };
+                // 重置后更新图表
+                this.$refs.knowledgeGraphRef.$nextTick(() => {
+                    if (this.$refs.knowledgeGraphRef.activeView === 'graph' && this.$refs.knowledgeGraphRef.chart) {
+                        this.$refs.knowledgeGraphRef.updateChart();
+                    }
+                });
+            }
+            
+            // 根据tab切换调用新API,传递对应的knowledgeType和重置后的scoreRateTypes=null
+            this.getStudentKnowledgeDataTree(knowledgeType, null);
+            
             if(!this.knowledgeId){
                 this.historicalChangeData = {
                     personalList: [],

+ 83 - 58
src/views/analysisReport/personalProfile/zeroScoreKnowledge.vue

@@ -16,17 +16,17 @@
     <div class="graph_header" v-if="activeView === 'list'">
       <!-- 自定义图例 -->
       <div class="legend">
-        <div class="legend_item" :class="{ 'selected': selectedLegend.weak }">
-          <span class="legend_dot weak"></span>
-          <span class="legend_text">{{ '薄弱(0%≤得分率<60%)' }}</span>
+        <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>
         </div>
-        <div class="legend_item" :class="{ 'selected': selectedLegend.good }">
-          <span class="legend_dot good"></span>
-          <span class="legend_text">{{ '良好(60%≤得分率<85%)' }}</span>
+        <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>
         </div>
-        <div class="legend_item" :class="{ 'selected': selectedLegend.excellent }">
-          <span class="legend_dot excellent"></span>
-          <span class="legend_text">{{ '优秀(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>
       <!-- 视图切换按钮 - 移到knowledge_graph容器下 -->
@@ -55,18 +55,17 @@
         <div class="top_container">
           <!-- 自定义图例 -->
           <div class="legend">
-            <!-- @click="toggleLegend('weak')"  @click="toggleLegend('good')" @click="toggleLegend('excellent')" -->
-            <div class="legend_item" :class="{ 'selected': selectedLegend.weak }">
-              <span class="legend_dot weak"></span>
-              <span class="legend_text">{{ '薄弱(0%≤得分率<60%)' }}</span>
+            <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>
             </div>
-            <div class="legend_item" :class="{ 'selected': selectedLegend.good }">
-              <span class="legend_dot good"></span>
-              <span class="legend_text">{{ '良好(60%≤得分率<85%)' }}</span>
+            <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>
             </div>
-            <div class="legend_item" :class="{ 'selected': selectedLegend.excellent }">
-              <span class="legend_dot excellent"></span>
-              <span class="legend_text">{{ '优秀(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>
           <!-- 视图切换按钮  -->
@@ -398,7 +397,7 @@ export default {
       // 这是为了避免在视图切换时重复调用接口
       if (this._isMounted && newTab !== oldTab) {
         // 向父组件发送tab切换事件
-        this.$emit('active-tab-change', newTab);
+        this.$emit('activeTabChange', newTab);
       }
     },
     // 监听数据变化,重新设置默认选中项
@@ -576,6 +575,35 @@ export default {
       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') {
+        knowledgeType = 1;
+      } else if (this.activeTab === 'zero') {
+        knowledgeType = 2;
+      } else {
+        knowledgeType = 0;
+      }
+      
+      this.$emit('legend-change', { scoreRateTypes, knowledgeType });
+      
+    },
+
     // 根据得分率获取对应的颜色
     getNodeColor(scoreRate) {
       const rate = parseFloat(scoreRate);
@@ -664,38 +692,46 @@ export default {
         const generateTreeData = (data, level = 0, overrideKnowledgeId = null) => {
           // 使用传入的overrideKnowledgeId或默认使用vm.selectedKnowledgeId
           const currentKnowledgeId = overrideKnowledgeId !== null ? overrideKnowledgeId : vm.selectedKnowledgeId;
-          
-          return data.filter(item => {
-            // 获取节点级别
-            const nodeLevel = vm.classLevel === 0 ? getNodeLevel(item.gradeScoreRate) : getNodeLevel(item.classScoreRate);
-            // 根据图例选中状态决定是否显示节点
-            return vm.selectedLegend[nodeLevel];
-          }).map(item => {
+
+          return data.map(item => {
             // 根据节点是否为最外围节点
             const isOutermost = !item.children || item.children.length === 0;
-            
+
             // 检查当前节点是否匹配选中的知识点ID
             const isMatched = isOutermost && String(item.knowledgeId) === String(currentKnowledgeId);
-            
+
             // 设置节点大小:选中状态16px,未选中状态10px,非叶子节点5px
             let symbolSize = 5;
             if (isOutermost) {
               symbolSize = isMatched ? 15 : 10;
             }
+
+            // 获取节点级别,优先使用对应级别的得分率,若缺失则使用另一级别作为备选
+            const scoreRate = item.personalScoreRate
+            const nodeLevel = getNodeLevel(scoreRate);
             
-            // 计算节点样式
-            const itemColor = isOutermost ? 
-              vm.getNodeColor(vm.classLevel === 0 || vm.classLevel === 1 ? item.gradeScoreRate : item.classScoreRate) : 
+            // 计算节点样式,使用与nodeLevel相同的得分率逻辑
+            const itemColor = isOutermost ?
+              vm.getNodeColor(scoreRate) :
               '#BFC1C7';
+            // 仅对最外层节点应用图例过滤,非外层节点始终显示
+            const shouldShow = !isOutermost || vm.selectedLegend[nodeLevel];
+            
+            // 设置节点透明度:显示为1,隐藏为0
+            const opacity = shouldShow ? 1 : 0;
             
             const node = {
               name: item.knowledgeName,
               symbolSize: symbolSize,
-              // 根据班级名称是否为年级来选择使用gradeScoreRate或classScoreRate
-              value: vm.classLevel === 0 || vm.classLevel === 1 ? item.gradeScoreRate : item.classScoreRate,
+              // 使用已计算的scoreRate作为value,确保数据一致性
+              value: scoreRate,
               itemStyle: {
                 color: itemColor,
-                opacity: 1
+                opacity: opacity
+              },
+              // 当节点是最外层且被隐藏时,隐藏连接到该节点的线
+              lineStyle: {
+                opacity: shouldShow ? 1 : 0
               },
               // 添加isOutermost属性用于tooltip判断
               isOutermost: isOutermost,
@@ -937,19 +973,7 @@ 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) {
             // 点击空白区域或非最外层节点,恢复所有节点透明度
@@ -1086,13 +1110,13 @@ export default {
     // 根据知识点得分率获取对应的点颜色
     getDotColor(item) {
       // 优先使用classScoreRate,若不存在或为空则使用gradeScoreRate
-      const scoreRate = item.classScoreRate || item.gradeScoreRate;
+      const scoreRate = item.personalScoreRate;
       const rate = parseFloat(scoreRate);
       if (rate >= 85) {
         return '#3BA272'; // 优秀 - 绿色
-      } else if (rate > 60) {
+      } else if (rate >= 60 && rate < 84) {
         return '#FAC858'; // 良好 - 黄色
-      } else {
+      } else if (rate < 59) {
         return '#EE6666'; // 薄弱 - 红色
       }
     }
@@ -1140,10 +1164,12 @@ export default {
         display: flex;
         align-items: center;
         gap: 5px;
-
+        cursor: pointer;
+        opacity: 0.7;
+        transition: all 0.3s ease;
+        font-weight: 500;
         &.selected {
           opacity: 1;
-          font-weight: 500;
         }
 
         &:hover {
@@ -1380,13 +1406,12 @@ export default {
           display: flex;
           align-items: center;
           gap: 5px;
-          // cursor: pointer;
-          // opacity: 0.7;
-          // transition: all 0.3s ease;
-
+          cursor: pointer;
+          opacity: 0.7;
+          transition: all 0.3s ease;
+          font-weight: 500;
           &.selected {
             opacity: 1;
-            font-weight: 500;
           }
 
           &:hover {