<template>
  <el-col :span="hideSideBar ? 0 : colSpan"
    :xs="24"
    @click.native="cancelSel">
    <div v-show="!hideSideBar"
      class="content">
      <div class="buttons_wrap">
        <!-- 扩展的按钮 -->
        <slot name="buttons"></slot>
        <el-input v-model="queryParams.searchKey"
          :placeholder="placeholder"
          clearable
          prefix-icon="Search"
          @click.stop />
      </div>
      <div class="scroll"
        :class="{ 'row_gap': customOptions.rowGap }">
        <el-tree :data="options"
          v-loading="customOptions.loading"
          :props="defaultProps"
          :expand-on-click-node="false"
          :filter-node-method="filterNode"
          ref="treeRef"
          :node-key="nodeKey"
          highlight-current
          default
          :default-expanded-keys="defaultExpandList"
          @node-click="handleNodeClick">
          <template class="custom-tree-node"
            v-slot="{ node, data }"
            :style="{ margin: rowGap + 'px !important' }">
            <svg-icon v-if="customOptions.showIcon"
              icon-class="floader"
              class="floader-icon" />
            <span>{{ node.label }}</span>
            <span v-if="customOptions.showTool"
              class="edit_del">
              <span style="margin-right: 10px;">创建人：{{ data.createBy }}</span>
              <el-icon class="el-icon-edit"
                @click.stop="$emit('flodEdit', data)">
                <Edit />
              </el-icon>
              <el-icon class="el-icon-delete"
                @click.stop="$emit('flodDel', data)">
                <Delete />
              </el-icon>
            </span>
          </template>
        </el-tree>
        <!-- 分页 -->
        <pagination v-if="customOptions.showPagination"
          :total="customOptions.total"
          v-model:page="queryParams.pageNum"
          v-model:limit="queryParams.pageSize"
          @pagination="getPageList" />
        <!-- 折叠分类侧边栏 -->
        <div class="arrow"
          @click="handleClick">
          <svg-icon icon-class="left-arrow" />
        </div>
      </div>
    </div>
    <!-- 展开分类侧边栏 -->
    <div class="arrow"
      v-show="hideSideBar"
      @click="handleClick">
      <svg-icon icon-class="right-arrow" />
    </div>
  </el-col>
</template>

<script setup>
const props = defineProps({
  // 树结构数据
  options: {
    type: Array,
    required: true,
    default: () => {
      return []
    }
  },
  // 树结构主键
  nodeKey: {
    type: String,
    default: 'id'
  },
  // 树结构使用字段
  defaultProps: {
    type: Object
  },
  // 默认展开哪些行
  defaultExpandList: {
    type: Array
  },
  // 搜索占位符
  placeholder: {
    type: String,
    default: '搜索关键字'
  },

  // 选中某行数据对象
  modelValue: {
    type: [Number, String],
    default: ''
  },
  // el-col 宽度
  colSpan: {
    type: Number,
    default: 6
  },
  // 详细配置左侧分类框
  customOptions: {
    type: Object,
    default: () => ({
      // 右侧工具是否显示
      showTool: false,
      // // 左侧图表是否显示
      // showIcon: false,
      // 行与行间隙
      rowGap: 0,
      // 底部分页是否显示
      showPagination: false,
      // 分页数据总条数
      total: 0,
      // 加载状态
      loading: false
    })
  }
})

// 隐藏左侧分类框
const hideSideBar = ref(false)
// 上次点击的行对象
const lastRow = ref(null)
// 分页参数
const queryParams = reactive({
  pageNum: 1,
  pageSize: 10,
  searchKey: ''
})
const treeRef = ref(null)

// search：让外部触发业务的搜索
// listChange: 让外部重新搜索本分类列表数据
const emits = defineEmits(['update:modelValue', 'search', 'listChange', 'flodEdit', 'flodDel'])

watch(() => queryParams.searchKey, (val) => {
  if (!props.customOptions.showPagination) {
    // 没有分页，用本地列表搜索
    treeRef.value.filter(val);
  } else {
    // 有分页，走外面接口搜索
    queryParams.searchKey = val
    emits('listChange', queryParams)
  }
})

// 如果有 v-model 则设置默认选中值
watch(() => props.modelValue, (val) => {
  if (val) {
    nextTick(() => {
      treeRef.value.setCurrentKey(val)
      lastRow[props.nodeKey] = val
    })
  }
})

// 点击空白位置-取消选中效果
const cancelSel = () => {
  // 刚才有过点击的某行
  if (lastRow.value) {
    treeRef.value.setCurrentKey(null)
    lastRow.value = null
    emits('update:modelValue', '')
    emits('search', null)
  }
}

// 点击某行
const handleNodeClick = (row) => {
  // 当前点击和上次点击一样->取消
  if (lastRow.value && (lastRow.value[props.nodeKey] === row[props.nodeKey])) {
    treeRef.value.setCurrentKey(null)
    lastRow.value = null
  } else {
    lastRow.value = row
  }
  emits('update:modelValue', lastRow.value ? row[props.nodeKey] : '')
  emits('search', lastRow.value)
}

// tree 筛选节点
const filterNode = (value, data) => {
  if (!value) return true;
  return data[props.defaultProps.label].indexOf(value) !== -1;
}

// 分页逻辑触发
const getPageList = () => {
  emits('listChange', queryParams)
}

const handleClick = () => {
  hideSideBar.value = !hideSideBar.value
}
</script>

<style scoped
  lang="scss">
  .el-col {
    padding: 0 !important;
    height: 100%;
    display: flex;
    flex-direction: column;
    transition: all .3s;
    position: relative;

    .content {
      height: 100%;
      display: flex;
      flex-direction: column;
      border-right: 1px solid rgb(208, 208, 208);

      /* 按钮集合 */
      .buttons_wrap {
        display: flex;
        gap: 50px;
        margin-bottom: 20px;
      }

      .scroll {
        flex: 1;
        overflow-y: scroll;

        /* 灰色滚动条背景 */
        &::-webkit-scrollbar-track {
          background-color: transparent;
        }
      }

      /* 向左折叠的箭头 */
      .arrow {
        right: -5px;
      }

      .buttons_wrap {
        padding-right: 20px;
      }

      .edit_del {
        padding-right: 10px;
        margin-left: auto;
        font-size: calc(var(--xl-fontsize));
        display: flex;
        align-items: center;

        i {
          margin-right: 10px;
        }
      }

      .scroll {
        display: flex;
        flex-direction: column;

        .el-tree {
          flex: 1;
          font-size: var(--xl-fontsize);
        }

        .pagination-container {
          position: sticky;
          bottom: 10px;
          margin-top: auto;
        }
      }
    }

    .arrow {
      position: absolute;
      top: 40%;
      width: 10px;
      height: 40px;
      display: flex;
      justify-content: center;
      align-items: center;
      border-radius: 5px;
      font-size: 12px;
      box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
      background-color: white;
      z-index: 2;
    }
  }

  ::v-deep(.el-tree-node){
    margin-top: 5px;
  }

  ::v-deep(.el-tree-node__content){
    .el-icon, .svg-icon{
      font-size: 16px;
    }
    .floader-icon{
      margin-right: 10px;
    }
  }

  ::v-deep(.custom-tree-node) {
    width: 100%;
    padding-right: 20px;
    font-size: 14px;
  }

  /* 间距放大 */
  ::v-deep(.row_gap .el-tree-node .el-tree-node__content) {
    padding: 20px 0;
    height: auto;
  }

  /* el-tree 取消选中时背景还有个颜色去掉 */
  ::v-deep(.el-tree-node:focus>.el-tree-node__content) {
    background-color: transparent;
  }

  /* el-tree 选中时的背景色设置 */
  ::v-deep(.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content) {
    background-color: #edf6ff !important;
  }

  ::v-deep(.el-input--small) {
    padding-right: 10px;
  }

  ::v-deep(.el-input__suffix:last-of-type) {
    padding-right: 10px;
  }

</style>
