<template>
  <div class="comp-content">
    <div class="content">
      <div v-if="!hideTree" class="left-content" :class="{ hide: !isToggleShow }">
        <div class="options">
          <slot name="options" />
        </div>
        <div class="tree-data">
          <el-tree
            v-if="visible"
            ref="treeRef"
            :node-key="dataKey.id"
            highlight-current
            :load="loadMoreFun"
            lazy
            :props="{
              label: dataKey.name,
              children: 'children',
              isLeaf: 'leaf',
            }"
            @node-click="nodeClickFun"
            @current-change="currentChangeFun"
          >
            <template #default="{ data, node }">
              <div class="tree-item">
                <div class="name">
                  <div class="icon">
                    <template v-if="data.dataType === 1">
                      <el-icon :size="18">
                        <Folder v-if="!node.expanded" />
                        <FolderOpened v-else />
                      </el-icon>
                    </template>
                    <template v-if="data.dataType === 2">
                      <el-icon :size="18">
                        <Document />
                      </el-icon>
                    </template>
                  </div>
                  <div class="label">{{ data[dataKey.name] }}</div>
                </div>
                <div class="actions">
                  <slot name="treeAction" :data="data" :node="node" />
                </div>
              </div>
            </template>
          </el-tree>
        </div>
      </div>
      <div class="toggle-btn" :class="{ hide: !isToggleShow }" @click="toggleFun">
        <el-icon :size="12">
          <DArrowLeft />
        </el-icon>
      </div>
      <div class="right-content">
        <div class="tree-menu">
          <el-breadcrumb :separator-icon="ArrowRight">
            <el-breadcrumb-item v-for="(item) in navList" :key="item[dataKey.id]" @click="openDirFun(item[dataKey.id])">
              {{ item[dataKey.name] }}
            </el-breadcrumb-item>
          </el-breadcrumb>
        </div>
        <div class="table">
          <slot name="table" />
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import { ArrowRight, Folder, FolderOpened, Document, DArrowLeft } from '@element-plus/icons-vue';

interface Props {
  api: any;
  hideTree?: boolean;
  dataKey?: any;
}

const props = withDefaults(defineProps<Props>(), {
  api: null,
  hideTree: false,
  dataKey: {
    id: 'id',
    pId: 'parentDirId',
    name: 'originalName',
  },
});

const emit = defineEmits(['choseNode', 'updateNav']);

const treeRef = ref<any>();
const navList = ref<any>([]);
const visible = ref(true);
const isToggleShow = ref(true);

// 加载节点
const loadMoreFun = async(node: any, resolve: any) => {
  const listData: any = await getDataFun(node.data[props.dataKey.id] || '');
  if (node.level >= 1) {
    node.data.children = listData;
    choseNodeFun(node.data);
  }
  return resolve(listData);
};

// 获取节点数据
const getDataFun = async(pId: string) => {
  if (props.api) {
    const params: any = {};
    params[props.dataKey.pId] = pId || '';
    const res: any = await props.api(params);
    if (res.code === 200) {
      return res.data;
    } else {
      return [];
    }
  }
};

// 树形节点点击
const nodeClickFun = (data: any, node: any) => {
  updateNavFun([]);
  getTreeMenuFun(node);
  choseNodeFun(data);
};

// 循环获取父节点
const getTreeMenuFun = (node: any) => {
  if (node.label && node.parent) {
    const data = navList.value;
    data.unshift(node.data);
    updateNavFun(data);
    getTreeMenuFun(node.parent);
  }
};

// 打开目录
const openDirFun = (id: any) => {
  const node = treeRef.value.getNode(String(id));
  if (node) {
    node.loaded = false;
    node.expand();
    treeRef.value.setCurrentKey(id);
    choseNodeFun(node.data);
  }
};

// 返回上一级
const backFun = () => {
  const data = navList.value[navList.value.length - 2];
  openDirFun(data[props.dataKey.id]);
};

// 当前节点更改
const currentChangeFun = (data: any, node: any) => {
  updateNavFun([]);
  getTreeMenuFun(node);
};

// 选中节点
const choseNodeFun = (data: any) => {
  emit('choseNode', data);
};

// 导航变更
const updateNavFun = (data: any) => {
  navList.value = data;
  emit('updateNav', data);
};

const reloadFun = () => {
  visible.value = false;
  setTimeout(() => {
    visible.value = true;
  }, 0);
};

const toggleFun = () => {
  isToggleShow.value = !isToggleShow.value;
};

defineExpose({
  backFun,
  openDirFun,
  reloadFun,
});
</script>

<style lang="scss" scoped>
.comp-content {
  height: 100%;
  .content {
    position: relative;
    height: 100%;
    display: flex;
    .toggle-btn {
      position: absolute;
      display: flex;
      justify-content: center;
      align-items: center;
      top: 50%;
      left: 400px;
      margin-top: -20px;
      background-color: var(--el-bg-color);
      border-radius: 0 4px 4px 0;
      width: 14px;
      height: 40px;
      border: solid 1px var(--el-border-color-darker);
      border-left: 0;
      color: var(--el-text-color-regular);
      cursor: pointer;
      transition: all 0.3s;
      &.hide {
        left: -14px;
        transform: rotateZ(180deg);
      }
    }
    .left-content {
      width: 400px;
      overflow: auto;
      margin-right: var(--margin-normal);
      background-color: var(--el-bg-color);
      border-radius: var(--border-radius-normal);
      padding: var(--padding-normal);
      border-right: solid 1px var(--el-border-color-darker);
      transition: all 0.3s;
      &.hide {
        width: 0;
        padding: 0;
        margin: 0;
      }
      .tree-item {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: space-between;
        min-height: 20px;
        width: 0;
        .name {
          flex: 1;
          display: flex;
          align-items: center;
          overflow: hidden;
          text-overflow: ellipsis;
          .icon {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 20px;
            height: 20px;
            margin-right: var(--margin-tiny);
          }
          .label {
            display: flex;
            align-items: center;
            min-height: 20px;
          }
        }
        .actions {
          padding-left: var(--padding-normal);
          display: flex;
          align-items: center;
          min-height: 20px;
        }
      }
    }
    .right-content {
      flex: 1;
      overflow: auto;
      background-color: var(--el-bg-color);
      border-radius: var(--border-radius-normal);
      padding: var(--padding-normal);
      .tree-menu {
        display: flex;
        align-items: center;
        height: 40px;
      }
    }
  }
}
</style>
