|
@@ -26,11 +26,11 @@
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 子节点容器 -->
|
|
<!-- 子节点容器 -->
|
|
|
- <view v-if="nodeData.children && nodeData.children.length > 0"
|
|
|
|
|
- :class="['ml-40 overflow-hidden transition-all duration-300 h-0']"
|
|
|
|
|
- :style="{ height: nodeData.actualHeight + 'px' }">
|
|
|
|
|
|
|
+ <view v-if="nodeData.children && nodeData.children.length > 0" :id="`knowledge-children-${nodeData.id}`"
|
|
|
|
|
+ :class="['ml-40 overflow-hidden transition-all duration-300', { 'is-measuring': isMeasuringHeight }]"
|
|
|
|
|
+ :style="{ height: measuredHeight + 'px' }">
|
|
|
<knowledge-tree-node v-for="child in nodeData.children" :key="child.name" :node-data="child"
|
|
<knowledge-tree-node v-for="child in nodeData.children" :key="child.name" :node-data="child"
|
|
|
- :parent-data="nodeData" @node-click="handleNodeClick" @update-height="handleUpdateHeight"
|
|
|
|
|
|
|
+ :parent-data="nodeData" @node-click="handleNodeClick"
|
|
|
@start-practice="handleChildStartPractice">
|
|
@start-practice="handleChildStartPractice">
|
|
|
<template #default>
|
|
<template #default>
|
|
|
<slot></slot>
|
|
<slot></slot>
|
|
@@ -54,9 +54,10 @@ const props = defineProps({
|
|
|
default: null
|
|
default: null
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+const isMeasuringHeight = ref(false);
|
|
|
|
|
+const measuredHeight = ref(0);
|
|
|
// 定义 emits
|
|
// 定义 emits
|
|
|
-const emit = defineEmits(['nodeClick', 'updateHeight', 'startPractice']);
|
|
|
|
|
|
|
+const emit = defineEmits(['nodeClick', 'startPractice']);
|
|
|
|
|
|
|
|
// 计算子节点高度
|
|
// 计算子节点高度
|
|
|
const calculateChildrenHeight = (node: Study.KnowledgeNode): number => {
|
|
const calculateChildrenHeight = (node: Study.KnowledgeNode): number => {
|
|
@@ -78,28 +79,38 @@ const calculateChildrenHeight = (node: Study.KnowledgeNode): number => {
|
|
|
return height;
|
|
return height;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+const getRect = (selector: string) => {
|
|
|
|
|
+ return new Promise((resolve: (rect: { top: number, height: number }) => void) => {
|
|
|
|
|
+ const query = uni.createSelectorQuery();
|
|
|
|
|
+ query.select(selector).boundingClientRect(function (rect) {
|
|
|
|
|
+ resolve(rect as { top: number, height: number });
|
|
|
|
|
+ }).exec();
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const measureHeight = () => {
|
|
|
|
|
+ isMeasuringHeight.value = true;
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ getRect(`#knowledge-children-${props.nodeData.id}`).then((res: any) => {
|
|
|
|
|
+ isMeasuringHeight.value = false;
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ measuredHeight.value = res.height;
|
|
|
|
|
+ });
|
|
|
|
|
+ }, 0);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 处理节点点击
|
|
// 处理节点点击
|
|
|
const handleClick = () => {
|
|
const handleClick = () => {
|
|
|
|
|
|
|
|
// 切换展开状态
|
|
// 切换展开状态
|
|
|
props.nodeData.isExpanded = !props.nodeData.isExpanded;
|
|
props.nodeData.isExpanded = !props.nodeData.isExpanded;
|
|
|
-
|
|
|
|
|
- // 计算并设置实际高度
|
|
|
|
|
if (props.nodeData.isExpanded) {
|
|
if (props.nodeData.isExpanded) {
|
|
|
- props.nodeData.actualHeight = calculateChildrenHeight(props.nodeData);
|
|
|
|
|
|
|
+ measureHeight();
|
|
|
} else {
|
|
} else {
|
|
|
- props.nodeData.actualHeight = 0;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 通知父组件节点被点击
|
|
|
|
|
- emit('nodeClick', {
|
|
|
|
|
- node: props.nodeData,
|
|
|
|
|
- parent: props.parentData
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 如果有父节点,通知父节点更新高度
|
|
|
|
|
- if (props.parentData) {
|
|
|
|
|
- emit('updateHeight', props.parentData);
|
|
|
|
|
|
|
+ measuredHeight.value = 0;
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -119,20 +130,6 @@ const handleNodeClick = (eventData: { node: Study.KnowledgeNode; parent: Study.K
|
|
|
emit('nodeClick', eventData);
|
|
emit('nodeClick', eventData);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 处理高度更新事件
|
|
|
|
|
-const handleUpdateHeight = (parentNode: Study.KnowledgeNode) => {
|
|
|
|
|
-
|
|
|
|
|
- // 重新计算父节点高度
|
|
|
|
|
- if (parentNode.isExpanded) {
|
|
|
|
|
- parentNode.actualHeight = calculateChildrenHeight(parentNode);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 继续向上传递高度更新事件
|
|
|
|
|
- if (props.parentData) {
|
|
|
|
|
- emit('updateHeight', props.parentData);
|
|
|
|
|
- }
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
const getCorrectRate = (rate: number): number => {
|
|
const getCorrectRate = (rate: number): number => {
|
|
|
if (!rate) {
|
|
if (!rate) {
|
|
|
return 0;
|
|
return 0;
|
|
@@ -152,4 +149,12 @@ const getProgressPercent = (nodeData: Study.KnowledgeNode): number => {
|
|
|
};
|
|
};
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
-<style lang="scss" scoped></style>
|
|
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.is-measuring {
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ z-index: -1;
|
|
|
|
|
+ transform: translateX(-100%);
|
|
|
|
|
+ height: auto !important;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|