吴朋磊 1 сар өмнө
parent
commit
56caa8527f

+ 65 - 35
src/views/targetImprove/components/CommonTree.vue

@@ -1,6 +1,12 @@
 <template>
 
-  <div class="common_tree_wrapper common_tree">
+  <div
+    class="common_tree_wrapper common_tree"
+    v-loading="loading"
+    element-loading-text="加载中……"
+    element-loading-spinner="el-icon-loading"
+    element-loading-background="#ffffff"
+  >
     <el-tree
       ref="commonTree"
       class="tree_container"
@@ -167,6 +173,12 @@ export default {
       type: Boolean,
       default: false,
     },
+
+    /** 树数据加载中(父组件请求期间传 true) */
+    loading: {
+      type: Boolean,
+      default: false,
+    },
   },
   inject: ["openAiRobot"], //注入Ai机器人组件调用方法
   // ==================== 数据状态 ====================
@@ -187,10 +199,7 @@ export default {
   // ==================== 生命周期 ====================
   mounted() {
     if (Array.isArray(this.treeData) && this.treeData.length > 0) {
-      clearTimeout(this._defaultSelectTimer);
-      this._defaultSelectTimer = setTimeout(() => {
-        this.applyDefaultFirstNode(this.treeData);
-      }, 100);
+      this.scheduleDefaultFirstNode(this.treeData);
     }
   },
 
@@ -202,22 +211,13 @@ export default {
   watch: {
     treeData: {
       handler(newVal) {
-        if (!Array.isArray(newVal) || newVal.length === 0) return;
-        // 用 setTimeout 确保 el-tree 内部节点已完全渲染
-        clearTimeout(this._defaultSelectTimer);
-        this._defaultSelectTimer = setTimeout(() => {
-          // 如果已有手动勾选的节点,在新数据上重新应用状态
-          if (this.manuallyCheckedKeys.length > 0 && this.showCheckbox) {
-            this._isUpdating = true;
-            this.reapplyCheckStates();
-            this.$nextTick(() => {
-              this._isUpdating = false;
-            });
-          } else {
-            // 没有手动勾选节点时,执行默认选中第一个节点
-            this.applyDefaultFirstNode(newVal);
-          }
-        }, 100);
+        // 数据切换(换人/换科目/重新筛选)时,清空旧勾选并重新默认勾选+展开第一个节点
+        this.manuallyCheckedKeys = [];
+        if (!Array.isArray(newVal) || newVal.length === 0) {
+          this.clearChecked();
+          return;
+        }
+        this.scheduleDefaultFirstNode(newVal);
       },
     },
   },
@@ -433,27 +433,57 @@ export default {
       this.$refs.commonTree.setCurrentKey(key);
     },
 
+    /**
+     * 延迟执行默认勾选/展开,确保 el-tree 内部节点已渲染完成
+     * @param {Array} data - 树形数据
+     */
+    scheduleDefaultFirstNode(data) {
+      clearTimeout(this._defaultSelectTimer);
+      this._defaultSelectTimer = setTimeout(() => {
+        this.$nextTick(() => {
+          this.applyDefaultFirstNode(data);
+        });
+      }, 100);
+    },
+
     /**
      * 默认勾选并展开第一个一级节点
-     * 新逻辑:只勾选第一个节点本身(手动勾选),其祖先和后代自动勾选+置灰
+     * - 无论树只有 1 个节点还是多个节点,都勾选第一个顶层节点
+     * - 展开该节点下全部子孙节点
      * @param {Array} data - 树形数据
+     * @param {Number} retry - 内部重试次数(树尚未渲染完时)
      */
-    applyDefaultFirstNode(data) {
+    applyDefaultFirstNode(data, retry = 0) {
       if (!data || data.length === 0) return;
       const treeRef = this.$refs.commonTree;
-      if (!treeRef || !treeRef.store || !treeRef.store.root) return;
-
-      // 1. 获取第一个顶层节点实例
-      const rootNode = treeRef.store.root;
-      const childNodes = rootNode.childNodes;
-      if (!childNodes || childNodes.length === 0) return;
+      const childNodes =
+        treeRef && treeRef.store && treeRef.store.root
+          ? treeRef.store.root.childNodes
+          : null;
+
+      // 树尚未渲染出节点时短暂重试,避免切换数据后漏勾选/漏展开
+      if (!childNodes || childNodes.length === 0) {
+        if (retry < 8) {
+          clearTimeout(this._defaultSelectTimer);
+          this._defaultSelectTimer = setTimeout(() => {
+            this.applyDefaultFirstNode(data, retry + 1);
+          }, 50);
+        }
+        return;
+      }
 
       const firstNodeInstance = childNodes[0];
       if (!firstNodeInstance) return;
 
-      // 2. 默认勾选第一个节点(手动勾选,只传该节点 key)
+      const firstKey =
+        firstNodeInstance.key != null
+          ? firstNodeInstance.key
+          : firstNodeInstance.data && firstNodeInstance.data[this.nodeKey];
+      if (firstKey == null || firstKey === "") return;
+
+      // 1. 默认勾选第一个节点(含「只有一个节点」的场景)
       if (this.showCheckbox) {
-        this.manuallyCheckedKeys = [firstNodeInstance.key];
+        this.manuallyCheckedKeys = [firstKey];
         this._isUpdating = true;
         this.reapplyCheckStates();
         this.$nextTick(() => {
@@ -461,10 +491,10 @@ export default {
         });
       }
 
-      // 3. 默认高亮选中第一个节点
-      treeRef.setCurrentKey(firstNodeInstance.key);
+      // 2. 默认高亮选中第一个节点
+      treeRef.setCurrentKey(firstKey);
 
-      // 4. 默认展开第一个节点及其全部子节点(所有层级)
+      // 3. 默认展开第一个节点及其全部子节点(所有层级;单节点叶子也设 expanded)
       const expandAllChildren = (node) => {
         if (!node) return;
         node.expanded = true;
@@ -475,7 +505,7 @@ export default {
       };
       expandAllChildren(firstNodeInstance);
 
-      // 5. 只传递手动勾选的节点 key(即第一个节点本身)
+      // 4. 回传手动勾选的节点 key(即第一个节点本身)
       if (this.showCheckbox) {
         this.$emit("nodeCheck", [...this.manuallyCheckedKeys]);
       }

+ 21 - 15
src/views/targetImprove/consolidate/index.vue

@@ -49,6 +49,7 @@
             node-key="knowledgeId"
             show-checkbox
             :default-expand-all="false"
+            :loading="treeLoading"
             @nodeCheck="HandleTestNodeCheck"
           />
         </div>
@@ -204,7 +205,8 @@ export default {
         pageSize: 5,
         total: 0
       },
-      loading:false,//加载中
+      loading:false,//错题列表加载中
+      treeLoading:false,//知识点树加载中
       showExportDialog:false,//导出错题本pdf弹窗
     }
   },
@@ -426,29 +428,33 @@ export default {
         params.endAt=this.endTime+' 23:59:59';//结束时间
       }
 
-      this.$api.target.getTargetErrorKnowledgeList(params).then().then(res => {
+      // 切换人员/筛选后重新拉树:先清空旧勾选,等待树组件默认勾选第一个节点后再拉错题
+      this.knowledgeIds = [];
+      this.treeLoading = true;
+      this.$api.target.getTargetErrorKnowledgeList(params).then(res => {
         console.log('打印知识点列表数据', res)
         if(res.code == 200)
         {
-
-          this.mockTreeData=res.data || [];//知识点数据
-          if(this.mockTreeData.length==0)
+          this.mockTreeData = res.data || [];
+          if(this.mockTreeData.length == 0)
           {
-            this.questionList=[];
-            this.pageInfo.total=0;
+            this.questionList = [];
+            this.pageInfo.total = 0;
           }
-          else
-          {
-
-            this.GetQuestionList();//获取错题列表
-          }
-        
+          // 有数据时由 CommonTree 默认勾选并发出 nodeCheck,再触发 GetQuestionList
         }
         else
         {
-          this.mockTreeData=[];
-          this.questionList=[];
+          this.mockTreeData = [];
+          this.questionList = [];
+          this.pageInfo.total = 0;
         }
+      }).catch(() => {
+        this.mockTreeData = [];
+        this.questionList = [];
+        this.pageInfo.total = 0;
+      }).finally(() => {
+        this.treeLoading = false;
       });
     },