123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- <template>
- <div class="vtl-node" :id="model.id" :class="{ 'vtl-leaf-node': !isFolder, 'vtl-tree-node': isFolder }">
- <div :class="treeNodeClass" @mouseover="mouseOver" @mouseout="mouseOut" @click.stop="toggle">
- <div class="vtl-border-text">
- <template v-if="isFolder">
- <slot v-if="expanded" :item="{ title: model.title, isFolder: true, expanded: true }" name="icon"> </slot>
- <slot v-else :item="{ title: model.title, isFolder: true, expanded: false }" name="icon"></slot>
- </template>
- <slot v-else :item="{ title: model.title, isFolder: false }" name="icon"></slot>
- <span class="vtl-node-content ellipsis">
- {{ model.title }}
- </span>
- </div>
- <div class="vtl-operation" v-show="isHover && !isFolder">
- <span @click.stop.prevent="delNode">
- <slot name="operation" type="detailNode"></slot>
- </span>
- </div>
- </div>
- </div>
- <div class="vtl-tree-margin" v-show="expanded">
- <!-- 这里无法使用$attr来透传属性官方还未解决此bug -->
- <treeList
- @on-click="(depth) => $emit('onClick', depth)"
- @detail-node="(depth) => $emit('detailNode', depth)"
- v-for="newmodel in model.children"
- :selected="selected"
- :model="newmodel"
- :key="newmodel.id"
- >
- <template #icon="slotProps">
- <slot name="icon" v-bind="slotProps"></slot>
- </template>
- <template #operation="slotProps">
- <slot name="operation" v-bind="slotProps"></slot>
- </template>
- </treeList>
- </div>
- </template>
- <script setup lang="ts">
- import { computed, ref } from 'vue';
- interface IFileSystem {
- id: string;
- title: string;
- pid: string;
- isFolder: boolean;
- isAdd: boolean;
- children?: IFileSystem[];
- }
- // 吐出去的事件
- const emit = defineEmits(['onClick', 'detailNode']);
- // 拿到传入的值
- const props = withDefaults(
- defineProps<{
- model: IFileSystem;
- selected: IFileSystem;
- }>(),
- {
- // draggable: false,
- }
- );
- //是否移入
- const isHover = ref(false);
- // 是否展开
- const expanded = ref(false);
- // 是否是文件夹
- const isFolder = computed(() => {
- return props.model.isFolder;
- });
- const isSelected = computed(() => props.selected.id === props.model.id);
- // 拖拽样式
- const treeNodeClass = computed(() => {
- return {
- 'vtl-node-main': true,
- selected: isSelected.value,
- };
- });
- // 删除目录
- const delNode = () => {
- emit('detailNode', {
- ...props.model,
- eventType: 'detail',
- });
- };
- // 展开收起
- const toggle = () => {
- if (isFolder.value) {
- expanded.value = !expanded.value;
- emit('onClick', {
- ...props.model,
- }); //lxh
- } else {
- emit('onClick', {
- ...props.model,
- });
- }
- };
- // 拖拽结束
- const mouseOver = () => {
- isHover.value = true;
- };
- // 移出
- const mouseOut = () => {
- isHover.value = false;
- };
- </script>
- <style lang="less">
- @import '/@/design/theme.less';
- @{theme-deepblue} {
- .vtl-node {
- --node-select-bg: #3f506a;
- }
- }
- .vtl-node {
- --node-select-bg: #1c4869;
- .vtl-node-main {
- display: flex;
- align-items: center;
- padding: 2px 0 2px 2px;
- cursor: pointer;
- &:hover {
- .vtl-border-text {
- width: 80%;
- }
- }
- .vtl-border-text {
- display: flex; //lxh
- flex: 1;
- align-items: center; //lxh
- width: 100%;
- padding-left: 5px;
- .iconfont {
- width: 16px;
- height: 16px;
- vertical-align: text-bottom;
- }
- }
- &.selected {
- // background-color: rgba(45, 113, 134, 0.2);
- background-color: var(--node-select-bg);
- }
- .vtl-node-content {
- color: #fff;
- padding-left: 5px;
- font-size: 14px;
- width: 80%;
- display: inline-block;
- vertical-align: bottom;
- }
- &:hover {
- .vtl-node-content {
- color: #fff;
- overflow: hidden;
- }
- }
- .vtl-operation {
- padding-right: 10px;
- }
- }
- }
- .vtl-tree-margin {
- padding-left: 1em;
- }
- </style>
|