<template>
  <div class="sideRightTree" ref="sideRightTree">
    <div>
      <!-- zTree Start -->
      <ul id="sideRightTree" class="ztree" style="li a input {margin-left: 100px;}"/>
      <!-- zTree End -->
    </div>
  </div>
</template>
<script>

import {replaceNullName, handleGeometricToArray, handleGeometricToStr} from "@/utils/tree";
import xeUtils from 'xe-utils';
import AntSpinDot from "@/components/AntSpinDot/index.vue";
import {addClass, removeClass} from "@/utils";
import {toLogin} from "@/providers/http.js"; // 返回登陆页面

export default {
  name: "RightTree",
  components: {
    AntSpinDot,
  },
  data() {
    return {
      /** 加载对象 */
      loader: undefined,
      /** zTree 配置项 */
      setting: {
        data: {
          key: {
            title: "description"
          },
          simpleData: {
            enable: true,
            idKey: "id",
            pIdKey: "pid",
          }
        },
        view: {
          /** 显示 / 不显示 连线 */
          showLine: true,
          /** 显示 / 隐藏 提示信息 */
          showTitle: false,
          /** 支持 / 不支持 HTML 脚本 */
          nameIsHTML: true,
          /** 显示 / 隐藏 图标 */
          showIcon: false,
          /** 双击节点 切换 / 不切换 展开状态 */
          dblClickExpand: false,
          /** 是否允许同时选中多个节点 */
          selectedMulti: false,
          /** 是否允许可以选择 zTree DOM 内的文本 */
          txtSelectedEnable: true,
          /** 显示动画效果 */
          expandSpeed: "fast"
        },
        edit: {
          enable: true,
          drag: {
            isCopy: false,
            isMove: false,
            prev: false,
            next: false,
            inner: false
          },
          editNameSelectAll: true,
          showRenameBtn: false,
          showRemoveBtn: false,
        },
        async: {
          enable: true,
          url: "/DFMEA/mfmea/funAnalysis/rb0426314/fail",
          dataType: "json",
          type: "post",
          dataFilter: this.handleDataFilter
        },
        callback: {
          beforeClick: this.handleBeforeClick,
          beforeRightClick: this.handleBeforeRightClick,
          beforeAsync: this.handleBeforeAsync,
          onAsyncSuccess: this.handleOnAsyncSuccess,
        }
      },
    };
  },
  props: {},
  watch: {},
  created() {
  },
  mounted() {
  },
  destroyed() {
  },
  methods: {
    /******************************************* zTree Start **************************************************/
    /**
     * 初始化右侧树
     */
    initRightTree(zNodes = []) {
      let _that = this;
      let struId = _that.$store.getters.sideCheckedLeftNode ? _that.$store.getters.sideCheckedLeftNode.id : "";
      let settings = $.extend({}, _that.setting);
      settings.view.fontCss = _that.setNodeFontCss;
      settings.view.showTitle = true; // 设置鼠标移入显示
      settings.async.contentType = "application/json";
      settings.async.otherParam = {
        fmeaId: _that.$store.getters.sideRfmeaId,
        struId: struId
      };
      // 初始化ztree
      $.fn.zTree.init($("#sideRightTree"), settings, zNodes);
    },
    /**
     * 用于对 Ajax 返回数据进行预处理的函数
     * @param treeId
     * @param parentNode
     * @param responseData
     */
    handleDataFilter(treeId, parentNode, responseData) {
      // 登录超时返回登录页面
      if (responseData.code == 304 || responseData.code == 100) {
        console.log("系统登出！：", responseData);
        toLogin();
        throw new Error('登录超时');
      }
      let childNodes = responseData.data.mfmeaStruTreeModels;
      for (let i = 0, l = childNodes.length; i < l; i++) {
        let node = childNodes[i];
        // 设置【description】为节点的title
        node['description'] = replaceNullName(node);
        node.name = this.getNodeName(node);
      }
      return childNodes;
    },
    /**
     * 用于捕获单击节点之前的事件回调函数，并且根据返回值确定是否允许单击操作
     * @param treeId
     * @param treeNode
     * @param clickFlag
     */
    handleBeforeClick(treeId, treeNode, clickFlag) {
      // 处理选中ZTree节点
      this.handleSelectZTreeNodes(treeId, [treeNode]);
      // 存储当前节点信息
      this.setCheckedNode(treeNode);
    },
    /**
     * 用于捕获 zTree 上鼠标右键点击之前的事件回调函数，并且根据返回值确定触发 onRightClick 事件回调函数
     * @param treeId
     * @param treeNode
     */
    handleBeforeRightClick(treeId, treeNode) {
      // 右键非节点时，忽略
      if (!treeNode) return;
      // 处理选中ZTree节点
      this.handleSelectZTreeNodes(treeId, [treeNode]);
      // 存储当前节点信息
      this.setCheckedNode(treeNode);
      // 获取右键菜单项
      let bthMenuBtn = this.getMenuBtn();
      // 处理右键菜单
      this.handleContextMenu(treeNode, bthMenuBtn);
    },
    /**
     * 用于捕获异步加载之前的事件回调函数，zTree 根据返回值确定是否允许进行异步加载
     * @param treeId
     * @param treeNode
     */
    handleBeforeAsync(treeId, treeNode) {
      // 开启加载...
      this.handleShowHideLoading(true);
    },
    /**
     * 用于捕获异步加载正常结束的事件回调函数
     * 如果设置了 setting.callback.beforeAsync 方法，且返回 false，
     * 将无法触发 onAsyncSuccess / onAsyncError 事件回调函数。
     */
    handleOnAsyncSuccess(event, treeId, treeNode, msg) {
      let _that = this;
      // 关闭加载...
      _that.handleShowHideLoading(false);
    },
    /**
     * 设置功能、失效、要求和产品特征字体着色
     * @param treeId
     * @param treeNode
     * @returns {*}
     */
    setNodeFontCss(treeId, treeNode) {
      return this.$store.getters.nodeTypeDict.zTreeRNodeColor[treeNode.struTypeCode];
    },
    /**
     * 取得节点名称
     * @param node
     * @returns {string}
     */
    getNodeName(node) {
      let nodeName = '&nbsp;';
      // 关系网图标
      let netIcon = this.getNetIcon(node);
      if (netIcon) {
        nodeName += netIcon + '&nbsp;';
      }
      // 节点图标
      let nodeIcon = this.getNodeIcon(node);
      if (nodeIcon) {
        nodeName += nodeIcon + '&nbsp;';
      }
      // 关联历史失效
      if (node.hasFmeaResearch) {
        nodeName += `<i class="iconfont iconguanlian2"></i>` + '&nbsp;';
      }
      // 附件标识 0：无，1：有
      if (node.annexFlag === '1') {
        nodeName += "<i class='iconfont iconshuxing1' onclick='handleRAnnexIconClick(\"" + node.id + "\")'></i>" + "&nbsp;";
      }
      // 评审意见
      if (node.hasStruComment) {
        nodeName += `<i class="iconfont iconxiaoxi_right"></i>` + '&nbsp;';
      }
      // 前缀
      if (node.middleInfo) {
        nodeName += node.middleInfo + '&nbsp;';
      }
      if (node.beginInfo) {
        nodeName += node.beginInfo + '&nbsp;';
      }
      // 特性分类
      if (node.lname) {
        nodeName += xeUtils.escape(node.lname) + '&nbsp;';
      }
      nodeName += node.description;
      // 后缀
      if (node.endInfo) {
        nodeName += '&nbsp;' + node.endInfo;
        // 形位公差符号
        if (node.geometric) {
          nodeName += '&nbsp;' + this.getGeometricName(node, true);
        }
      }
      return nodeName;
    },
    /**
     * 取得行位公差名称
     * @param node 节点
     * @param titleFlag
     */
    getGeometricName(node, titleFlag) {
      if (titleFlag) {
        return handleGeometricToStr(node.geometric);
      } else {
        return handleGeometricToArray(node.geometric);
      }
    },
    /**
     * 取得网图标
     * @param node 节点
     */
    getNetIcon(node) {
      let iconClass = "iconfont ";
      if ("02,04,05,06".indexOf(node.struTypeCode) !== -1) {
        iconClass += this.getNetRelationIcon(node) + this.getNodeColor(node);
        return `<i class="${iconClass}"></i>`;
      }
      return '';
    },
    /**
     * 取得节点颜色样式
     * @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 节点
     */
    getNetRelationIcon(node) {
      let icon;
      if (node.netParentCnt !== 0 && node.netChildCnt !== 0) {
        icon = this.$store.getters.treeIcons.full;
      } else if (node.netParentCnt !== 0 && node.netChildCnt === 0) {
        icon = this.$store.getters.treeIcons.left;
      } else if (node.netParentCnt === 0 && node.netChildCnt !== 0) {
        icon = this.$store.getters.treeIcons.right;
      } else {
        icon = this.$store.getters.treeIcons.none;
      }
      return icon;
    },
    /**
     * 根据节点类型不同,展示不同的Icon
     * @param node 节点
     */
    getNodeIcon(node) {
      let iconClass = "iconfont ";
      switch (node.struTypeCode) {
        case '01': // 结构
          iconClass += this.$store.getters.treeIcons.structure;
          break;
        case '99': // 接口
          iconClass += this.$store.getters.treeIcons.interface;
          break;
        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;
        case '14': // 当前措施
          iconClass += this.$store.getters.treeIcons.currentMeasure;
          break;
        case '07': // 优化措施
          iconClass += this.$store.getters.treeIcons.optimizeMeasure;
          break;
        case '08': // 措施组
          iconClass += this.$store.getters.treeIcons.group;
          break;
        case '09': // 预防措施
          iconClass += this.$store.getters.treeIcons.preventionMeasure;
          break;
        case '10': // 探测措施
          iconClass += this.$store.getters.treeIcons.probeMeasure;
          break;
      }
      return `<i class="${iconClass}"></i>`;
    },
    /**
     * 选中ztree节点
     * @param treeId
     * @param nodes
     */
    handleSelectZTreeNodes(treeId, nodes) {
      let treeObj = $.fn.zTree.getZTreeObj(treeId);
      for (let i = 0; i < nodes.length; i++) {
        let node = treeObj.getNodeByParam("id", nodes[i]?.id, null);
        if (node) {
          treeObj.selectNode(node);
          // 重新赋值，保持缓存节点数据一致
          this.setCheckedNode(node);
        }
      }
    },
    /**
     * 单级折叠/展开
     */
    collapseExpand() {
      let _that = this;
      let checkedNode = _that.$store.getters.sideLastCheckedNode;
      let treeObj = $.fn.zTree.getZTreeObj('sideRightTree');
      treeObj.expandNode(checkedNode, !checkedNode?.open, true, true);
    },
    /**
     * 全部折叠/展开
     */
    collapseExpandAll() {
      let _that = this;
      let checkedNode = _that.$store.getters.sideLastCheckedNode;
      let treeObj = $.fn.zTree.getZTreeObj('sideRightTree');
      let nodes = treeObj.getNodesByParam("level", checkedNode.level, null);
      let expandFlag = checkedNode?.open;
      for (let i = 0, len = nodes.length; i < len; i++) {
        // 聚焦当前选中节点
        treeObj.expandNode(nodes[i], !expandFlag, true, checkedNode.id === nodes[i].id);
      }
    },
    /**
     * 显示、隐藏 -- 加载Loading
     * @param flag
     */
    handleShowHideLoading(flag) {
      if (flag) {
        if (this.loader) this.loader.hide();
        this.loader = this.$loading.show({
          container: this.$refs.sideRightTree,
          color: '#1890FF',
        }, {
          // 自定义加载动画组件
          default: this.$createElement('ant-spin-dot'),
        });
      } else {
        this.loader.hide();
      }
    },
    /******************************************* zTree End **************************************************/

    /******************************************* 右键菜单 Start **************************************************/
    /**
     * 获取右键菜单项
     */
    getMenuBtn() {
      return {
        "copy": {name: this.$t('global-constant.contextmenu.copy'), icon: "fas iconfont iconfuzhi4"},
        "sep": "---------",
        "collapseExpand": {
          name: this.$t('global-constant.contextmenu.collapse-expand'),
          icon: "fas iconfont iconzhedie2"
        },
        "collapseExpandAll": {
          name: this.$t('global-constant.contextmenu.collapse-expand-all'),
          icon: "fas iconfont iconzhedie111"
        },
      };
    },
    /**
     * 处理右键菜单
     * @param node 节点
     * @param items 菜单项
     */
    handleContextMenu(node, items) {
      let _that = this;
      // 隐藏上次菜单
      let selector = '#' + node.tId + '_a'
      jQuery.contextMenu('destroy', selector);
      jQuery.contextMenu({
        selector: selector,
        autoHide: true,
        zIndex: 10,
        items: items,
        callback: function (itemKey, opt) {
          let actionInfo = {key: itemKey};
          _that.menuAction(actionInfo);
        },
      });
    },
    /**
     * 右键菜单事件
     * @param actionInfo 菜单项信息
     */
    menuAction(actionInfo) {
      switch (actionInfo.key) {
        case "copy": // 复制
          this.setHighLightCopyCutNode("copy");
          break;
        case "collapseExpand": // 折叠/展开
          this.collapseExpand();
          break;
        case "collapseExpandAll": // 全部折叠/展开
          this.collapseExpandAll();
          break;
      }
    },
    /******************************************* 右键菜单 End **************************************************/
    /**
     * 存储当前节点信息
     */
    setCheckedNode(node) {
      this.$store.dispatch("fmeaTree/set", {
        key: "sideLastCheckedNode",
        value: node
      });
    },
    /**
     * 设置：复制/剪切时，节点高亮
     * @param cutCopy 'copy'、'cut'
     */
    setHighLightCopyCutNode(cutCopy) {
      let sideLastCheckedNode = this.$store.getters.sideLastCheckedNode;
      if (!sideLastCheckedNode) return;
      this.clearHighLightCopyCutNode();
      addClass(document.getElementById(sideLastCheckedNode.tId + '_a'), "curCopyCutNode");
      this.$store.dispatch("fmeaTree/set", {
        key: "lastCopyOrCutNode",
        value: sideLastCheckedNode
      });
      // 存储操作树标识位：leftTree or rightTree
      this.$store.dispatch("fmeaTree/set", {
        key: "lastCopyOrCutLRTreeFlag",
        value: 'sideLeftTree'
      });
      // 存储操作类型标识位：复制=copy or 剪切=cut
      this.$store.dispatch("fmeaTree/set", {
        key: "lastCopyOrCut",
        value: cutCopy
      });
    },
    /**
     * 清除：复制/剪切时，节点高亮
     */
    clearHighLightCopyCutNode() {
      let lastCopyOrCutNode = this.$store.getters.lastCopyOrCutNode;
      let treeId = lastCopyOrCutNode?.tId.split('_')[0];
      if (lastCopyOrCutNode && treeId) {
        let treeObj = $.fn.zTree.getZTreeObj(treeId);
        let node = treeObj.getNodeByParam("id", lastCopyOrCutNode?.id, null);
        if (node) {
          removeClass(document.getElementById(node.tId + '_a'), "curCopyCutNode");
        }
        this.$store.dispatch("fmeaTree/clearCopyOrCut");
      }
    },
  }
};
</script>
<style lang="less" scoped>

@import "~@/styles/zTree";

</style>
