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