64 lines
1.6 KiB
Vue
64 lines
1.6 KiB
Vue
<template>
|
|
<view class="tree-container">
|
|
<view v-for="item in nodeData" :key="item.id">
|
|
<view class="tree-item" :style="item.id == selectedNodeId ? { borderColor: '#1879ff' } : { color: '#000' }"
|
|
@click.stop="toCurrentNode(item)">
|
|
<image class="tree-item-icon" :src="$fileUrl(filePath(item.picUrl))" @error="$fileRetry(filePath(item.picUrl))" />
|
|
<text>{{ item.name }}</text>
|
|
</view>
|
|
|
|
<node-tree v-model="selectedNodeId" v-if="item.children && item.children.length" :node-data="item.children"
|
|
:style="{ marginLeft: `${getLevel() * 60}rpx` }" @currentNode="(v) => emit('currentNode', v)" />
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { getCurrentInstance } from "vue"
|
|
import { filePath } from "../utils/file"
|
|
import NodeTree from "./node-tree.vue"
|
|
|
|
withDefaults(defineProps<{ nodeData: any[] }>(), { nodeData: () => [] })
|
|
const emit = defineEmits(["currentNode"])
|
|
const selectedNodeId = defineModel<any>("modelValue")
|
|
defineOptions({ name: "node-tree-item" })
|
|
|
|
const compInstance = getCurrentInstance()
|
|
|
|
const toCurrentNode = (item) => {
|
|
emit("currentNode", { ...item, level: getLevel() })
|
|
selectedNodeId.value = item.id
|
|
}
|
|
|
|
const getLevel = () => {
|
|
let level = 1
|
|
let $parent = compInstance?.parent
|
|
while ($parent && $parent.proxy?.$options.name === "node-tree-item") {
|
|
level++
|
|
$parent = $parent.parent
|
|
}
|
|
return level
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.tree-container {
|
|
overflow: hidden;
|
|
}
|
|
|
|
.tree-item {
|
|
border: 4rpx solid #e4e7ed;
|
|
margin-bottom: 16rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 10rpx 20rpx;
|
|
border-radius: 10rpx;
|
|
}
|
|
|
|
.tree-item-icon {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
margin-right: 10rpx;
|
|
}
|
|
</style>
|