使用组件
html
复制代码
<TreeNode v-for="(node, index) in nodes" :key="index" :node="node" />
JSON数据
javascript
复制代码
let nodes=[
{
"id": 2030,
"show_id": "MC1813024492270223360",
"detail_type": 1,
"title": "1",
"description": "",
"class_hour": 10,
"children": [
{
"id": 2031,
"show_id": "MC1813024625619734528",
"detail_type": 1,
"title": "2",
"description": "",
"class_hour": 2,
"children": [
{
"id": 1940,
"show_id": "MC1813024654644314112",
"detail_type": 2,
"title": "31",
"description": "我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介我是课程视频简介",
"class_hour": 0,
"children": null,
"study_status_str": "未学习",
"lesson_number": 0,
"level": 3
}
],
"study_status_str": "",
"lesson_number": 0,
"level": 2
}
],
"study_status_str": "",
"lesson_number": 1,
"level": 1
}
]
组件
html
复制代码
<template>
<div :style="{ paddingLeft: level * 20 + 'px' }" class="tree-node">
<div
@click="toggle"
class="tree-node-header"
:class="{ 'first-level': node.level == 1 }"
>
<img :src="node.level == 1 ? imgs.group : imgs.dot" alt="" />
<span class="title">{{ node.title }}</span>
<template v-if="node.level == 1">
<span class="class-hour all-hour">总学时 {{ node.class_hour }}</span>
<span class="class-hour">视频课{{ node.lesson_number }}</span>
</template>
<template v-if="!node.children && node.detail_type == 2">
<span @click="handleClassHour(node)" class="class-hour play"
><i class="iconfont"></i>视频课</span
>
<!-- <span class="class-hour schedule" >已学习 {{ '100%' }}</span> -->
<span class="class-hour schedule">{{ node.study_status_str }}</span>
</template>
<span v-if="hasChildren" class="arrow">
<i v-show="isOpen" class="el-icon-arrow-up" />
<i v-show="!isOpen" class="el-icon-arrow-down" />
<!-- {{ isOpen ? "-" : "+" }} -->
</span>
</div>
<div class="content" v-if="!node.children && node.level != 1">
{{ node.description }}
</div>
<transition name="expand">
<div v-if="isOpen" class="tree-node-children">
<TreeNode
v-for="(child, index) in node.children"
:key="index"
:node="child"
:level="level + 1"
/>
</div>
</transition>
</div>
</template>
<script>
export default {
name: "TreeNode",
props: {
node: {
type: Object,
required: true,
},
level: {
type: Number,
default: 1,
},
},
data() {
return {
isOpen: false,
imgs: {
group: require("@/pages/web_site_front/resource_manage/pages/onlineCourses/assets/group.png"),
dot: require("@/pages/web_site_front/resource_manage/pages/onlineCourses/assets/dot.png"),
},
};
},
computed: {
hasChildren() {
return (this.node.children && this.node.children?.length) || 0;
},
},
methods: {
toggle() {
if (this.hasChildren) {
this.isOpen = !this.isOpen;
}
},
handleClassHour(node) {
document.querySelector(".main-content").scrollTop = 0;
this.$store.dispatch("user/setCourseVideoId", node.id);
},
},
components: {
TreeNode: () => import("./treeNode.vue"),
},
};
</script>
<style scoped lang="scss">
.tree-node {
margin: 5px 0;
.tree-node-header {
cursor: pointer;
padding: 5px;
margin-bottom: 16px;
display: flex;
font-weight: bold;
img {
width: 10px;
align-self: center;
margin: 0 5px;
}
.title {
max-width: calc(100% - 160px);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.play {
font-size: 12px;
color: #00ab6b;
line-height: 20px;
height: 20px;
border: 0.5px solid #c3e7da;
border-radius: 4px;
padding: 0 4px;
margin-left: 8px;
display: inline-table;
i {
font-size: 14px;
margin-right: 4px;
}
}
.schedule {
font-size: 12px;
color: #00000040;
margin-left: 8px;
}
.arrow {
flex: 1;
text-align: right;
color: #00ab6b;
margin-right: 31px;
}
}
.first-level {
height: 40px;
line-height: 40px;
display: flex;
margin-bottom: 16px;
background: #fafafa;
border-radius: 8px;
font-weight: bold;
font-size: 16px;
span {
align-self: center;
}
img {
width: 30px;
align-self: center;
}
.class-hour {
color: #000000a6;
line-height: 22px;
padding: 0 8px;
background: #f5f5f5;
border-radius: 2px;
margin-right: 6px;
font-size: 14px;
}
.all-hour {
margin-left: 26px;
}
}
.content {
color: #00000073;
line-height: 22px;
border-bottom: 1px solid #f0f0f0;
padding-bottom: 16px;
margin-left: 26px;
}
}
.tree-node-children {
margin-top: 5px;
// border-left: 2px solid #ccc;
padding-left: 0px;
.tree-node{
padding-left: 20px !important;
}
}
/* Animation Styles */
.expand-enter-active,
.expand-leave-active {
transition: all 0.3s ease;
}
.expand-enter, .expand-leave-to /* .expand-leave-active in <2.1.8 */ {
height: 0;
opacity: 0;
overflow: hidden;
}
</style>