|
@@ -207,35 +207,31 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
watch: {
|
|
watch: {
|
|
|
- // 监听学科变化,重新调用知识图谱接口
|
|
|
|
|
|
|
+ // 监听学科变化,科目就绪后再拉图谱(等年级勾选也就绪,避免空 gradeCodes)
|
|
|
subjectCode(newVal, oldVal) {
|
|
subjectCode(newVal, oldVal) {
|
|
|
if (newVal && newVal !== oldVal) {
|
|
if (newVal && newVal !== oldVal) {
|
|
|
- this.fetchKnowledgeGraph();
|
|
|
|
|
|
|
+ this.scheduleFetchKnowledgeGraph();
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- // 监听 vuex store 中 gradesList 变化(TargetSubject 异步接口返回后会更新 store)
|
|
|
|
|
|
|
+ // TargetSubject 异步写入年级后:补齐默认勾选,再请求图谱
|
|
|
'$store.state.target.gradesList'(newVal) {
|
|
'$store.state.target.gradesList'(newVal) {
|
|
|
- if (Array.isArray(newVal) && newVal.length > 0 && this.gradeList.length === 0) {
|
|
|
|
|
- this.loadGradeListFromStorage();
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (!Array.isArray(newVal) || newVal.length === 0) return;
|
|
|
|
|
+ this.loadGradeListFromStorage();
|
|
|
|
|
+ this.scheduleFetchKnowledgeGraph();
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
mounted() {
|
|
mounted() {
|
|
|
- // 从localStorage读取年级列表
|
|
|
|
|
this.loadGradeListFromStorage();
|
|
this.loadGradeListFromStorage();
|
|
|
- // 初始化容器高度
|
|
|
|
|
this.calculateContainerHeight();
|
|
this.calculateContainerHeight();
|
|
|
- // 监听窗口大小变化
|
|
|
|
|
window.addEventListener('resize', this.calculateContainerHeight);
|
|
window.addEventListener('resize', this.calculateContainerHeight);
|
|
|
- // 首次加载知识图谱数据(含分区四区)
|
|
|
|
|
- this.fetchKnowledgeGraph();
|
|
|
|
|
|
|
+ this.scheduleFetchKnowledgeGraph();
|
|
|
},
|
|
},
|
|
|
// 当从其他路由切回来时(keep-alive),重新加载年级列表
|
|
// 当从其他路由切回来时(keep-alive),重新加载年级列表
|
|
|
activated() {
|
|
activated() {
|
|
|
this.loadGradeListFromStorage();
|
|
this.loadGradeListFromStorage();
|
|
|
},
|
|
},
|
|
|
beforeDestroy() {
|
|
beforeDestroy() {
|
|
|
- // 移除窗口大小变化监听
|
|
|
|
|
|
|
+ clearTimeout(this._fetchGraphTimer);
|
|
|
window.removeEventListener('resize', this.calculateContainerHeight);
|
|
window.removeEventListener('resize', this.calculateContainerHeight);
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
@@ -264,44 +260,72 @@ export default {
|
|
|
value: item.value ?? item.code ?? item.label ?? item.name ?? String(item)
|
|
value: item.value ?? item.code ?? item.label ?? item.name ?? String(item)
|
|
|
}));
|
|
}));
|
|
|
|
|
|
|
|
- // 默认只选中最后一个年级
|
|
|
|
|
- // 例:[{高一,10},{高二,11}] → currentGradeList = ['11'](仅选中高二)
|
|
|
|
|
- // 同"加入练习接口 gradeCode = gradeList 末尾 value"规则保持一致
|
|
|
|
|
- this.currentGradeList = this.gradeList.length > 0
|
|
|
|
|
- ? [this.gradeList[this.gradeList.length - 1].value]
|
|
|
|
|
- : [];
|
|
|
|
|
|
|
+ // 已有勾选且仍在列表中则保留;否则默认只选中最后一个年级
|
|
|
|
|
+ const validSelected = (this.currentGradeList || []).filter(code =>
|
|
|
|
|
+ this.gradeList.some(g => String(g.value) === String(code))
|
|
|
|
|
+ );
|
|
|
|
|
+ this.currentGradeList = validSelected.length > 0
|
|
|
|
|
+ ? validSelected
|
|
|
|
|
+ : (this.gradeList.length > 0 ? [this.gradeList[this.gradeList.length - 1].value] : []);
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
console.warn('[KnowledgeGraph] 解析 localStorage.student_gradesList 失败:', e);
|
|
console.warn('[KnowledgeGraph] 解析 localStorage.student_gradesList 失败:', e);
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 当前请求应使用的年级 codes:勾选值 → 否则默认最后一个年级
|
|
|
|
|
+ */
|
|
|
|
|
+ getGradeCodes() {
|
|
|
|
|
+ if (Array.isArray(this.currentGradeList) && this.currentGradeList.length > 0) {
|
|
|
|
|
+ return this.currentGradeList;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Array.isArray(this.gradeList) && this.gradeList.length > 0) {
|
|
|
|
|
+ const last = this.gradeList[this.gradeList.length - 1].value;
|
|
|
|
|
+ this.currentGradeList = last !== undefined && last !== null && last !== '' ? [last] : [];
|
|
|
|
|
+ return this.currentGradeList;
|
|
|
|
|
+ }
|
|
|
|
|
+ return [];
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 科目 + 年级都就绪后再请求;同一 tick 内多次触发合并成一次
|
|
|
|
|
+ */
|
|
|
|
|
+ scheduleFetchKnowledgeGraph() {
|
|
|
|
|
+ clearTimeout(this._fetchGraphTimer);
|
|
|
|
|
+ this._fetchGraphTimer = setTimeout(() => {
|
|
|
|
|
+ this.fetchKnowledgeGraph();
|
|
|
|
|
+ }, 0);
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 【接口调用】获取知识图谱数据
|
|
* 【接口调用】获取知识图谱数据
|
|
|
* 参数:
|
|
* 参数:
|
|
|
* - levelCode: 学段CODE(localStorage.student_level_code)
|
|
* - levelCode: 学段CODE(localStorage.student_level_code)
|
|
|
* - gradeCodes: 年级codes数组(checkbox选中的value,即使只有1个也要传)
|
|
* - gradeCodes: 年级codes数组(checkbox选中的value,即使只有1个也要传)
|
|
|
* - subjectCode: 学科code(vuex -> target.subjectCode)
|
|
* - subjectCode: 学科code(vuex -> target.subjectCode)
|
|
|
- * 调用成功后打印返回数据
|
|
|
|
|
*/
|
|
*/
|
|
|
fetchKnowledgeGraph() {
|
|
fetchKnowledgeGraph() {
|
|
|
- // 读取学段CODE
|
|
|
|
|
const levelCode = localStorage.getItem('student_level_code') || '';
|
|
const levelCode = localStorage.getItem('student_level_code') || '';
|
|
|
- // 年级codes:优先取checkbox勾选的value;未初始化时取最后一个年级的value(与默认勾选最后一个逻辑一致)
|
|
|
|
|
- let gradeCodes = this.currentGradeList && this.currentGradeList.length
|
|
|
|
|
- ? this.currentGradeList
|
|
|
|
|
- : (this.gradeList && this.gradeList.length > 0
|
|
|
|
|
- ? [this.gradeList[this.gradeList.length - 1].value]
|
|
|
|
|
- : []);
|
|
|
|
|
- // 学科code
|
|
|
|
|
|
|
+ const gradeCodes = this.getGradeCodes();
|
|
|
const subjectCode = this.subjectCode || '';
|
|
const subjectCode = this.subjectCode || '';
|
|
|
const classType = 1;
|
|
const classType = 1;
|
|
|
|
|
+
|
|
|
|
|
+ // 科目或年级未就绪时不请求,避免空 gradeCodes 查出全部年级 / 先展示暂无数据
|
|
|
|
|
+ if (!subjectCode || !gradeCodes.length) return;
|
|
|
|
|
+
|
|
|
const params = {
|
|
const params = {
|
|
|
levelCode,
|
|
levelCode,
|
|
|
gradeCodes,
|
|
gradeCodes,
|
|
|
subjectCode,
|
|
subjectCode,
|
|
|
classType
|
|
classType
|
|
|
};
|
|
};
|
|
|
|
|
+ const reqKey = JSON.stringify(params);
|
|
|
|
|
+ if (this._graphReqKey === reqKey) return;
|
|
|
|
|
+ this._graphReqKey = reqKey;
|
|
|
|
|
+ this._graphReqSeq = (this._graphReqSeq || 0) + 1;
|
|
|
|
|
+ const seq = this._graphReqSeq;
|
|
|
this.$api.target.knowledgeGraph(params).then(res => {
|
|
this.$api.target.knowledgeGraph(params).then(res => {
|
|
|
|
|
+ if (seq !== this._graphReqSeq) return;
|
|
|
if (res.code == 200 && res.data) {
|
|
if (res.code == 200 && res.data) {
|
|
|
const d = res.data;
|
|
const d = res.data;
|
|
|
// 1. 统计数据
|
|
// 1. 统计数据
|
|
@@ -330,10 +354,12 @@ export default {
|
|
|
};
|
|
};
|
|
|
this.setDefaultSelectionFromPartition();
|
|
this.setDefaultSelectionFromPartition();
|
|
|
} else {
|
|
} else {
|
|
|
- // 接口失败 / code !== 200 / 无data:清空数据,扩散图和统计数字归零
|
|
|
|
|
|
|
+ this._graphReqKey = '';
|
|
|
this.resetKnowledgeGraphEmpty();
|
|
this.resetKnowledgeGraphEmpty();
|
|
|
}
|
|
}
|
|
|
}).catch(err => {
|
|
}).catch(err => {
|
|
|
|
|
+ if (seq !== this._graphReqSeq) return;
|
|
|
|
|
+ this._graphReqKey = '';
|
|
|
console.error('[KnowledgeGraph] knowledgeGraph 接口异常:', err);
|
|
console.error('[KnowledgeGraph] knowledgeGraph 接口异常:', err);
|
|
|
this.resetKnowledgeGraphEmpty();
|
|
this.resetKnowledgeGraphEmpty();
|
|
|
});
|
|
});
|
|
@@ -504,9 +530,15 @@ export default {
|
|
|
|
|
|
|
|
// 年级切换(多选)
|
|
// 年级切换(多选)
|
|
|
handleGradeChange(gradeList) {
|
|
handleGradeChange(gradeList) {
|
|
|
|
|
+ // 不允许空选:勾选被清空时回退到最后一个年级,避免空 gradeCodes 查询全部年级
|
|
|
|
|
+ if (!Array.isArray(gradeList) || gradeList.length === 0) {
|
|
|
|
|
+ if (this.gradeList.length > 0) {
|
|
|
|
|
+ this.currentGradeList = [this.gradeList[this.gradeList.length - 1].value];
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
this.currentGradeList = gradeList;
|
|
this.currentGradeList = gradeList;
|
|
|
this.$emit('grade-change', gradeList);
|
|
this.$emit('grade-change', gradeList);
|
|
|
- // 年级变化后重新请求知识图谱(含分区四区)
|
|
|
|
|
this.fetchKnowledgeGraph();
|
|
this.fetchKnowledgeGraph();
|
|
|
},
|
|
},
|
|
|
|
|
|