<template>
  <div id="treeKey" :ref="treeKey">
    <div>
      <!-- Tree Start -->
      <a-tree
          v-if="treeData && treeData.length > 0"
          :selected-keys="[]"
          :tree-data="treeData"
          :blockNode="true"
          checkable
          checkStrictly
          :expandedKeys="expandedKeys"
          :checkedKeys="checkedKeys"
          :replaceFields="replaceFields"
          :autoExpandParent="autoExpandParent"
          @expand="onExpand"
          @check="onCheck"
          @rightClick="onRightClick">
        <template slot="treeDataSlot" slot-scope="node">
          <a :id="'treeNode' + node.id">
            <i v-if="getNodeIcon(node)" :class="getNodeIcon(node)"/>
            <span
                :id="'treeNodeName' + node.id"
                :title="getLinkName(node) + getNodeName(node)"
                @dblclick="doubleClick(node)"
                :class="getNodeClass(node)">
                  {{ getLinkName(node) }}
                  {{ getNodeName(node) }}
              </span>
            <a-input
                :id="'treeNodeInput' + node.id"
                :maxLength="500"
                @blur="updateNodeName(node)"
                @keyup="($event) => {keyup($event, node);}"
                class="hide"
                type="text"/>
          </a>
        </template>
      </a-tree>
      <!-- Tree End -->

      <!-- 模态框 Start -->
      <DragModal
          :visible="modalVisible"
          :title="title"
          :width="1000"
          :destroyOnClose="true"
          :maskClosable="false"
          @cancel="modalVisible = false"
          :footer="null">
        <!-- 失效 -->
        <AddFault
            v-if="actionName === 'addFault'"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initTree="initTree"/>
      </DragModal>
      <!-- 模态框 End -->
    </div>
  </div>
</template>
<script>


import {toggleClass} from "@/utils/index";
import DragModal from "@/components/DragModal";
import AddFault from "../AddModal/AddFault";
import $ from "jquery";

export default {
  name: "FunctionNetTree",
  components: {
    DragModal,
    AddFault,
  },
  props: {
    treeData: {
      type: Array,
      default: []
    },
    directFlag: {
      type: Number,
      default: 0 // 0：左侧；1：右侧
    },
    treeKey: {
      type: String,
      default: ""
    },
  },
  watch: {
    treeData: {
      handler(v) {
        this.allNode = [];
        // 添加插槽
        this.addScopedSlots(v);
        // 默认展开所有
        this.expandedKeys = [];
        this.defaultExpandedAllKeys(v);
        // 默认选中节点
        this.checkedKeys = [];
        this.defaultCheckedKeys(v);
      },
      immediate: true,
    },
  },
  data() {
    return {
      /** 用于改名时 ecs 退出会触发input blur，esc不能触发blur */
      ecsFlag: false,
      /** 把tree组件的节点 key改为id */
      replaceFields: {key: "id", title: "name"},
      /** 展开指定的树节点 */
      expandedKeys: [],
      /** 所有节点 */
      allNode: [],
      /** 选中复选框的树节点 */
      checkedKeys: [],
      /** 是否自动展开父节点 */
      autoExpandParent: false,
      /** 右键菜单字典 */
      faultNetMenuDict: {
        edit: [
          {
            key: "addFault",
            icon: "iconimage_0",
            label: this.$t('global-constant.contextmenu.failure')
          },
          {
            key: "delete",
            icon: "iconshanchu",
            label: this.$t('global-constant.contextmenu.delete')
          },
          {
            key: "allCollapseExpand",
            icon: "iconzhedie111",
            label: this.$t('global-constant.contextmenu.collapse-expand-all')
          },
        ],
        look: [
          {
            key: "allCollapseExpand",
            icon: "iconzhedie111",
            label: this.$t('global-constant.contextmenu.collapse-expand-all')
          },
        ]
      },
      /** 模态框状态 */
      modalVisible: false,
      /** 模态框唯一Key */
      actionName: "",
      /** 模态框标题 */
      title: "",
      /** 节点类型CODE */
      struTypeCode: "",
      /** 选中节点 */
      checkedNode: {},
    };
  },
  methods: {
    /**
     * 添加插槽
     * @param nodes 节点数组
     */
    addScopedSlots(nodes) {
      for (let i = 0, len = nodes.length; i < len; i++) {
        // 默认节点展开状态
        nodes[i]['expanded'] = true;
        this.allNode.push(nodes[i]);
        // 结构、接口不设置复选框
        if ("01,99,02,04,05".indexOf(nodes[i].struTypeCode) !== -1)
          nodes[i]['checkable'] = false;
        // 通过vue 自带的$set 给每条数据加上一个名为scopedSlots，值为{title: 'node'}，的插槽
        this.$set(nodes[i], "scopedSlots", {title: "treeDataSlot"});
        if (nodes[i].children && nodes[i].children.length > 0) {
          this.addScopedSlots(nodes[i].children);
        }
      }
      return nodes;
    },
    /**
     * 默认展开全部节点
     * @param treeData tree绑定数据
     */
    defaultExpandedAllKeys(treeData) {
      let _that = this;
      for (let i = 0; i < treeData.length; i++) {
        _that.expandedKeys.push(treeData[i].id);
        if (treeData[i].children && treeData[i].children.length > 0) {
          _that.defaultExpandedAllKeys(treeData[i].children);
        }
      }
    },
    /**
     * 默认选中复选框的树节点
     * @param treeData tree绑定数据
     */
    defaultCheckedKeys(treeData) {
      let _that = this;
      for (let i = 0; i < treeData.length; i++) {
        if (treeData[i].checked) _that.checkedKeys.push(treeData[i].id);
        if (treeData[i].children && treeData[i].children.length > 0) {
          _that.defaultCheckedKeys(treeData[i].children);
        }
      }
    },
    /** 图标展开/收起节点时触发
     * @param expandedKeys
     * @param e
     */
    onExpand(expandedKeys, e) {
      this.expandedKeys = expandedKeys;
      this.autoExpandParent = false;
      e.node.dataRef.expanded = e.expanded;
    },
    /**
     * 点击复选框触发
     * @param checkedKeys
     * @param e
     */
    onCheck(checkedKeys, e) {
      let node = e.node.dataRef;
      if (e.checked) this.addNetNode(node);
      else this.deleteNetNode(node);
    },
    /**
     * 右键点击节点
     * @param info
     */
    onRightClick(info) {
      // 选中节点
      this.checkedNode = info.node.dataRef;
      // 获取右键菜单项
      let bthMenuBtn = this.getMenuBtn(info.node.dataRef);
      if (Object.keys(bthMenuBtn).length > 0) {
        // 右键菜单位置
        this.handleContextMenu(info.node.dataRef, bthMenuBtn);
      }
    },
    /**
     * 获取右键菜单项
     * @param node 节点
     */
    getMenuBtn(node) {
      // 取得当前节点的右键菜单项
      let cNodeMenus;
      if ("01,99".indexOf(node.struTypeCode) !== -1) { // 结构、接口
        cNodeMenus = ["allCollapseExpand"];
      } else if ("02,04,05".indexOf(node.struTypeCode) !== -1) { // 功能、产品特性、要求
        cNodeMenus = ["addFault", "allCollapseExpand"];
      } else if ("06".indexOf(node.struTypeCode) !== -1) { // 失效
        cNodeMenus = ["delete"];
      }
      let menuBtn = {};
      let functionNetMenuDict = this.$api.isLook === '1' ?
          this.faultNetMenuDict.look : this.faultNetMenuDict.edit;
      functionNetMenuDict.forEach((item) => {
        if (cNodeMenus.indexOf(item.key) !== -1) {
          // 追加菜单项
          let menuObj = {name: item.label, icon: "fas iconfont " + item.icon};
          // 全部展开/折叠，增加分割线。
          if (this.$api.isLook !== '1'
              && "01,99".indexOf(node.struTypeCode) ===-1
              && item.key === 'allCollapseExpand') {
            menuBtn['sep'] = "---------";
          }
          menuBtn['' + item.key + ''] = menuObj;
        }
      });
      return menuBtn;
    },
    /**
     * 处理右键菜单
     * @param node 节点
     * @param items 菜单项
     */
    handleContextMenu(node, items) {
      let _that = this;
      $.contextMenu('destroy'); // 销毁所有菜单。
      $.contextMenu({
        selector: '#treeNode' + node.id,
        autoHide: true,
        zIndex: 10,
        items: items,
        callback: function (itemKey, opt) {
          let actionInfo = {key: itemKey};
          _that.menuAction(actionInfo, node);
        },
      });
    },
    /**
     * 右键菜单事件
     * @param actionInfo 菜单项信息
     * @param node 节点
     */
    menuAction(actionInfo, node) {
      this.actionName = actionInfo.key;
      switch (actionInfo.key) {
        case "addFault": // 失效
          this.handleAddModal(this.checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "delete": // 删除
          this.deleteNode(this.checkedNode);
          break;
        case "allCollapseExpand": // 全部展开/折叠
          this.allCollapseExpand(node);
          break;
      }
    },
    /**
     * 处理添加
     * @param node 节点
     * @param menuKey 菜单标识
     */
    handleAddModal(node, menuKey) {
      let name = node.name;
      let adds = this.$store.getters.nodeTypeDict.addModals;
      for (let i = 0, len = adds.length; i < len; i++) {
        if (adds[i].menuKey === menuKey) {
          this.title = this.$t('' + adds[i].title + '') + name;
          this.struTypeCode = adds[i].struTypeCode;
          this.tab = this.$t('' + adds[i].label + '');
          return;
        }
      }
    },
    /**
     * 取得节点名称
     * @param node 节点
     */
    getNodeName(node) {
      return node.name + (node.suffix ? "\xa0\xa0" + node.suffix : node.suffix);
    },
    /**
     * 连线名称
     * @param node
     */
    getLinkName(node) {
        return node.linkName ? (node.linkName + "\xa0\xa0") : '';
    },
    /**
     * 根据节点类型不同,展示不同的Icon
     * @param node 节点
     */
    getNodeIcon(node) {
      let iconClass = "iconfont ";
      switch (node.struTypeCode) {
        case '02': // 功能
          iconClass += this.$store.getters.treeIcons.function + this.getNodeColor(node);
          break;
        case '04': // 产品特性
          iconClass += this.$store.getters.treeIcons.productFeature + this.getNodeColor(node);
          break;
        case '05': // 要求
          iconClass += this.$store.getters.treeIcons.require + this.getNodeColor(node);
          break;
        case '06': // 失效
          iconClass += this.$store.getters.treeIcons.fault + this.getNodeColor(node);
          break;
      }
      return iconClass === "iconfont " ? false : iconClass;
    },
    /**
     * 动态生成节点的Class，满足不同类型节点样式不一样
     * @param node 节点
     */
    getNodeClass(node) {
      return this.getNodeColor(node);
    },
    /**
     * 取得节点颜色样式
     * @param node 节点
     */
    getNodeColor(node) {
      let color = " ";
      let obj = this.$store.getters.nodeTypeDict.color.filter(item => item.key === node.struTypeCode)[0]
      if (obj) color += obj.value;
      return color;
    },
    /**
     * 双击节点
     * @param node 节点
     */
    doubleClick(node) {
      let _that = this;
      // 1：查看：2：编制
      if (_that.$api.isLook === '1') return;
      if ("01,99,02,04,05".indexOf(node.struTypeCode) !== -1) return false;
      _that.ecsFlag = false;
      _that.keyListenerChange(true);
      let dom = this.$refs[`${this.treeKey}`];
      let rightTreeNodeName = dom.querySelector("#treeNodeName" + node.id);
      let rightTreeNodeInput = dom.querySelector("#treeNodeInput" + node.id);
      rightTreeNodeInput.value = node.name;
      toggleClass(rightTreeNodeName, "hide");
      toggleClass(rightTreeNodeInput, "hide");
      setTimeout(() => {
        rightTreeNodeInput.focus();
        // rightTreeNodeInput.select();
      }, 100);
      event.stopPropagation();
    },
    /**
     * 键盘松开事件
     * @param e event对象
     * @param node 节点
     */
    keyup(e, node) {
      let dom = this.$refs[`${this.treeKey}`];
      if (e.keyCode === 13) { // Enter
        dom.querySelector("#treeNodeInput" + node.id).blur();
      } else if (e.keyCode === 27) {  // Ecs
        this.ecsFlag = true;
        let rightTreeNodeName = dom.querySelector("#treeNodeName" + node.id);
        let rightTreeNodeInput = dom.querySelector("#treeNodeInput" + node.id);
        toggleClass(rightTreeNodeName, "hide");
        toggleClass(rightTreeNodeInput, "hide");
        this.keyListenerChange(false);
      }
    },
    /**
     * 修改节点名称
     * @param node 节点
     */
    updateNodeName(node) {
      let _that = this;
      if (_that.ecsFlag) return;
      let dom = this.$refs[`${this.treeKey}`];
      let rightTreeNodeName = dom.querySelector("#treeNodeName" + node.id);
      let rightTreeNodeInput = dom.querySelector("#treeNodeInput" + node.id);
      let newName = rightTreeNodeInput.value;
      // input框值为空、new与old名称一样时，不调接口
      if (!newName || newName === node.name) {
        toggleClass(rightTreeNodeName, "hide");
        toggleClass(rightTreeNodeInput, "hide");
        _that.keyListenerChange(false);
        return;
      }
      //调接口改变值
      _that.$api.updateNodeName({
        fmeaId: _that.$store.getters.rfmeaId,
        struId: node.id,
        struName: newName,
      }).then((res) => {
        if (res.flag) {
          _that.$message.success(res.message, 1);
          node.name = newName;
          _that.updateFaultNetNode(node);
        } else {
          _that.$message.error(res.message, 1);
        }
      }).catch((error) => {
        _that.$message.error(error.response.data.message, 1);
      }).finally(() => {
        toggleClass(rightTreeNodeName, "hide");
        toggleClass(rightTreeNodeInput, "hide");
        _that.keyListenerChange(false);
      });
    },
    /**
     * 全部折叠/展开
     * @param node 节点
     */
    allCollapseExpand(node) {
      let _that = this;
      let expands = [];
      if (node.expanded) {
        (_that.allNode || []).filter((item, index) => {
          if (item.deep !== node.deep) expands.push(item.id);
        });
      } else {
        (_that.allNode || []).filter((item, index) => {
          expands.push(item.id);
        });
      }
      node.expanded = !node.expanded;
      _that.expandedKeys = expands;
      _that.updateNodeCollapseExpand(_that.treeData, expands);
    },
    /**
     * 修改节点展开/折叠
     * @param sourceNodes 源节点
     * @param targetNodes 目标节点
     */
    updateNodeCollapseExpand(sourceNodes, targetNodes) {
      for (let i = 0, len = sourceNodes.length; i < len; i++) {
        sourceNodes[i]['expanded'] = targetNodes.indexOf(sourceNodes[i].id) !== -1;
        if (sourceNodes[i].children && sourceNodes[i].children.length > 0) {
          this.updateNodeCollapseExpand(sourceNodes[i].children, targetNodes);
        }
      }
    },
    /**
     * 关闭模态框
     */
    closeModal() {
      this.modalVisible = false;
    },
    initTree() {
      this.$emit("initTree");
    },
    /**
     * 监听快捷键
     * @param flag 标识位 true、false
     */
    keyListenerChange(flag) {
      this.$emit("keyListenerChange", flag);
    },
    /**
     * 添加网节点
     * @param node 节点
     */
    addNetNode(node) {
      this.$emit("addNetNode", this.directFlag, node);
    },
    /**
     * 删除网节点
     * @param node 节点
     */
    deleteNetNode(node) {
      this.$emit("deleteNetNode", this.directFlag, node);
    },
    /**
     * 删除节点
     * @param node 节点
     */
    deleteNode(node) {
      this.$emit("deleteNode", node, this.treeKey);
    },
    /**
     * 修改失效网节点
     * @param node 节点
     */
    updateFaultNetNode(node) {
      this.$emit("updateFaultNetNode", node);
    },
  },
};
</script>
<style lang="less" scoped>

</style>
