<template>
  <el-tree
    ref="treeRef"
    class="file-tree"
    :data="orgData"
    :props="defaultProps"
    @node-click="handleNodeClick"
    node-key="id"
    :highlight-current="true"
    :filter-node-method="filterNode"
    :expand-on-click-node="false"
    :default-expand-all="true">
    <template #default="{ node, data }">
      <div class="custom_tree_node">
        <span class="label-text" :title="data.name">{{ data.name }} </span>
        <span
          v-if="data.data_type === 2"
          class="tree-action-box first_node"
          :class="{ first_node_focus: (selectData && selectData.id === data.id) || !selectData }"
          @click.stop="showAction($event, data, node)">
          <bg-icon class="tree-more" icon="#bg-ic-s-more"></bg-icon>
        </span>
        <span v-else class="tree-action-box" @click.stop="showAction($event, data, node)">
          <bg-icon class="tree-more" icon="#bg-ic-s-more"></bg-icon>
        </span>
      </div>
    </template>
  </el-tree>
  <Teleport to="body">
    <div
      ref="treeActionRef"
      class="tree-action"
      v-show="actionFlag"
      :style="{ top: acTop, left: acLeft, bottom: acBottom }">
      <!-- 平台用户组织 -->
      <div
        v-if="selectData && selectData.data_type === 2"
        class="action"
        @click="treeAction({ type: 'directory', action: 'create', target: null })">
        新增目录
      </div>
      <div
        v-if="selectData && selectData.data_type === 2"
        class="action"
        @click="treeAction({ type: 'org', action: 'create', target: null })">
        新增组织
      </div>
      <!-- 目录 -->
      <div
        v-if="selectData && selectData.data_type === 0"
        class="action"
        @click="treeAction({ type: 'directory', action: 'create', target: 'local' })">
        新增本级目录
      </div>
      <div
        v-if="selectData && selectData.data_type === 0"
        class="action"
        @click="treeAction({ type: 'directory', action: 'create', target: 'child' })">
        新增下级目录
      </div>
      <div
        v-if="selectData && selectData.data_type === 0 && selectData.level !== 1"
        class="action"
        @click="treeAction({ type: 'org', action: 'create', target: 'local' })">
        新增本级组织
      </div>
      <div
        v-if="selectData && selectData.data_type === 0"
        class="action"
        @click="treeAction({ type: 'org', action: 'create', target: 'child' })">
        新增下级组织
      </div>
      <div
        v-if="selectData && selectData.data_type === 0"
        class="action"
        @click="treeAction({ type: 'directory', action: 'edit', target: 'local' })">
        编辑目录
      </div>
      <div
        v-if="selectData && selectData.data_type === 0"
        class="action"
        @click="treeAction({ type: 'directory', action: 'delete', target: 'local' })">
        删除
      </div>
      <div
        :class="{
          disable:
            mvDataParent.indexOf(selectData) === 0 ||
            (mvDataParent.indexOf(selectData) === 1 && mvDataParent[0].data_type == 2),
        }"
        v-if="selectData && selectData.data_type === 0"
        class="action"
        @click="treeAction({ type: 'directory', action: 'mvup', target: 'local' })">
        上移
      </div>
      <div
        :class="{ disable: mvDataParent.indexOf(selectData) === mvDataParent.length - 1 }"
        v-if="selectData && selectData.data_type === 0"
        class="action"
        @click="treeAction({ type: 'directory', action: 'mvdown', target: 'local' })">
        下移
      </div>
      <!-- 组织 -->
      <div
        v-if="selectData && selectData.data_type === 1"
        class="action"
        @click="treeAction({ type: 'org', action: 'create', target: 'local' })">
        新增本级组织
      </div>
      <div
        v-if="selectData && selectData.data_type === 1"
        class="action"
        @click="treeAction({ type: 'org', action: 'edit', target: 'local' })">
        编辑组织
      </div>
      <div
        v-if="selectData && selectData.data_type === 1"
        class="action"
        @click="treeAction({ type: 'org', action: 'delete', target: 'local' })">
        删除
      </div>
      <div
        :class="{ disable: mvDataParent.indexOf(selectData) === 0 }"
        v-if="selectData && selectData.data_type === 1"
        class="action"
        @click="treeAction({ type: 'org', action: 'mvup', target: 'local' })">
        上移
      </div>
      <div
        :class="{ disable: mvDataParent.indexOf(selectData) === mvDataParent.length - 1 }"
        v-if="selectData && selectData.data_type === 1"
        class="action"
        @click="treeAction({ type: 'org', action: 'mvdown', target: 'local' })">
        下移
      </div>
    </div>
  </Teleport>
</template>

<script setup>
import { ref, onBeforeMount, onBeforeUnmount, nextTick } from "vue";
import { useRoute } from "vue-router";
import axios from "@/request/http.js";
import { ElMessage } from "element-plus";
const route = useRoute();

const acTop = ref("");
const acLeft = ref("");
const acBottom = ref("");
const actionFlag = ref(false);
const selectData = ref(null);
const selectDataParent = ref(null);
const mvDataParent = ref([]);
const treeRef = ref(null);
const treeActionRef = ref(null);
const bottomGap = ref(30); //弹窗吸底高度
const orgData = ref([]);
const selectNodeObj = ref(null);
const customNodeClass = (data, node) => {
  if (data.data_type == 0) {
    return "noFocus";
  } else {
    return "";
  }
};
const defaultProps = {
  label: "name",
  children: "Child",
  value: "organization_id",
  class: customNodeClass,
};

const getOrgTree = (data) => {
  axios.get(`/v1/api/org/tree`).then((res) => {
    if (res.data.code == 200) {
      orgData.value = res.data.data || [];
      if (route.query.id) {
        searchItem(orgData.value, route.query.id);
        data = selectNodeObj.value;
      }
      if (data) {
        nextTick(() => {
          setCurrentNode(data);
        });
      } else {
        nextTick(() => {
          setCurrentNode(orgData.value[0].id);
        });
      }
    } else {
      ElMessage.error(res.data.data);
    }
  });
};

const searchItem = (data, id) => {
  data.forEach((e) => {
    if (e.organization_id == id) {
      selectNodeObj.value = e;
    } else {
      if (e.Child) {
        searchItem(e.Child, id);
      }
    }
  });
};
const filterTree = (val) => {
  treeRef.value.filter(val);
};

const setCurrentNode = (data) => {
  if (data) {
    treeRef.value.setCurrentKey(data, true);
    const curNode = treeRef.value.getCurrentNode();
    selectData.value = curNode;
    emit("select", { data: ref(curNode), type: "click" });
  } else {
    treeRef.value.setCurrentKey(orgData.value[0].id, true);
    const curNode = treeRef.value.getCurrentNode();
    selectData.value = curNode;
    emit("select", { data: ref(curNode), type: "click" });
  }
};

const filterNode = (value, data) => {
  if (!value) return true;
  return data.name.includes(value);
};

const showAction = (e, data, node) => {
  acTop.value = "";
  acLeft.value = "";
  acBottom.value = "";
  var allHeight = document.body.scrollHeight;
  actionFlag.value = true;
  selectData.value = data;
  selectDataParent.value = node.parent.data.name ? node.parent.data : null;
  mvDataParent.value = node.parent.data.Child ? node.parent.data.Child : node.parent.data;
  const rect = e.target.getBoundingClientRect(); //获取点击的dom的位置
  nextTick().then(() => {
    setTimeout(() => {
      var height = window.getComputedStyle(treeActionRef.value).height;
      height = parseInt(height);
      //判断弹窗位置是否超过屏幕，超过则吸底展示
      if (height + rect.y - 17 > allHeight - bottomGap.value) {
        acBottom.value = bottomGap.value + "px";
        acLeft.value = rect.x + 35 + "px";
      } else {
        acTop.value = rect.y - 17 + "px";
        acLeft.value = rect.x + 35 + "px";
      }
    });
  });
  // acTop.value = rect.y - 17 + "px";
  // acLeft.value = rect.x + 35 + "px";
};

const isSticky = (data) => {
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  context.font = "14px MicrosoftYaHei";
  const { width } = context.measureText(data);
  return width > 255 ? true : false;
};

const closeAction = () => {
  actionFlag.value = false;
};

const emit = defineEmits(["action", "select"]);
const handleNodeClick = (node, nodeAttr, treeNode, event) => {
  if (node.data_type !== 0) {
    selectData.value = node;
    emit("select", { data: selectData, type: "click" });
  } else {
    nextTick(() => {
      treeRef.value.setCurrentKey(null);
    });
  }
  //只读则无操作事件
  closeAction();
};

const treeAction = (params) => {
  emit("select", { data: selectData, type: "action" });
  let data = null;
  if (params.action === "create") {
    if (params.target === "local") {
      data = selectDataParent;
    } else if (params.target === "child") {
      data = selectData;
    } else {
    }
  } else if (params.action === "mvup") {
    // 已经是第一个元素 或者上一个元素是平台组织 则不可上移  平台组织始终在第一个
    if (
      mvDataParent.value.indexOf(selectData.value) === 0 ||
      (mvDataParent.value.indexOf(selectData.value) === 1 && mvDataParent.value[0].data_type == 2)
    ) {
      // ElMessage.error('已经是第一个元素，不可上移')
      return 0;
    } else {
      let brother = mvDataParent.value[mvDataParent.value.indexOf(selectData.value) - 1];
      data = [
        { id: selectData.value.id, sort: brother.sort },
        { id: brother.id, sort: selectData.value.sort },
      ];
    }
  } else if (params.action === "mvdown") {
    if (mvDataParent.value.indexOf(selectData.value) === mvDataParent.value.length - 1) {
      // ElMessage.error('已经是最后一个元素，不可下移')
      return 0;
    } else {
      let brother = mvDataParent.value[mvDataParent.value.indexOf(selectData.value) + 1];
      data = [
        { id: selectData.value.id, sort: brother.sort },
        { id: brother.id, sort: selectData.value.sort },
      ];
    }
  } else {
    data = selectData;
  }
  emit("action", { type: params.type, action: params.action, data: data });
};

onBeforeMount(() => {
  //只读则无操作事件
  window.addEventListener("click", closeAction);
  window.addEventListener("scroll", closeAction, true);
  getOrgTree();
});

onBeforeUnmount(() => {
  //只读则无操作事件
  window.removeEventListener("click", closeAction);
  window.removeEventListener("scroll", closeAction);
});

defineExpose({ getOrgTree, filterTree, setCurrentNode });
</script>

<style scoped>
.tree-action-box {
  display: none;
  position: absolute;
  right: -5px;
  top: 0px;
  width: 44px;
  height: 36px;
  line-height: 36px;
  text-align: center;
  background-color: #f2f3f7;
  box-shadow: -3px 0px 8px -3px rgba(0, 7, 101, 0.15);
}
.position_sticky {
  position: sticky;
  position: -webkit-sticky;
}
.tree-more {
  font-size: 12px;
  color: #3759be;
}

.file-tree :deep() .el-tree-node__content:hover .tree-action-box {
  display: inline-block;
}
.file-tree :deep() .el-tree-node__content:hover + .label-text {
  width: calc(100% - 48px);
}
.file-tree :deep() .el-tree-node__content .first_node {
  display: inline-block;
  background-color: #fff;
  box-shadow: none;
}
.file-tree :deep() .el-tree-node__content .first_node_focus {
  background-color: #f2f3f7;
  box-shadow: -3px 0px 8px -3px rgba(0, 7, 101, 0.15);
}
.file-tree :deep() .el-tree-node__content:hover .first_node {
  background-color: #f2f3f7;
  box-shadow: -3px 0px 8px -3px rgba(0, 7, 101, 0.15);
}
.file-tree :deep() .el-tree-node > .el-tree-node__children {
  overflow: visible;
}
.file-tree :deep() .el-tree-node__content {
  position: relative;
}
.action-box:hover .tree-action {
  display: block;
}
.label-text {
  font-size: 14px;
  color: #404a62;
  display: inline-block;
  width: calc(100% - 24px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tree-action-box:hover + .label-text {
  padding: 8px 0;
  background-color: var(--el-tree-node-hover-bg-color);
}

.label-text:hover {
  padding: 8px 0;
  /* background-color: var(--el-tree-node-hover-bg-color); */
  width: calc(100% - 48px);
}
.is_active {
  padding: 8px 0;
  background-color: var(--el-color-primary-light-9);
}

.custom_tree_node {
  width: 100%;
  font-size: 14px;
  color: #202531;
  padding-right: 16px;
}
.text_clip {
  width: 100%;
  display: inline-block;
}

.tree-action .action {
  width: 100%;
  height: 34px;
  line-height: 34px;
  padding-left: 16px;
  font-size: 14px;
  color: #202531;
  cursor: pointer;
}
.tree-action :deep().el-upload {
  width: 100%;
}
.tree-action .action:hover {
  background-color: #eff2fa;
  color: #3759be;
}

.tree-action .disable {
  cursor: not-allowed;
  color: #616f94;
}
.tree-action .disable:hover {
  background-color: #fff;
  color: #616f94;
}

.tree-action {
  /* display: none; */
  width: 144px;
  background-color: #ffffff;
  box-shadow: 0px 1px 4px 0px rgba(0, 7, 101, 0.15);
  padding: 4px 0;
  border-radius: 4px;
  position: fixed;
  z-index: 9;
}

.file-tree :deep().el-tree-node__content {
  height: 36px !important;
}

.tree-action .disable {
  cursor: not-allowed;
  color: #616f94;
}
.tree-action .disable:hover {
  background-color: #fff;
  color: #616f94;
}

.file-tree :deep().noFocus:focus > .el-tree-node__content {
  background-color: #fff;
}
</style>
