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

      <!-- 模态框 Start -->
      <DragModal
          :visible="modalVisible"
          :title="$t('' + title + '')"
          :width="1000"
          :destroyOnClose="true"
          :maskClosable="false"
          @cancel="modalVisible = false"
          :footer="null">
        <!-- 多级结构 -->
        <AddMultistageStructure
            v-if="actionName === 'addMultistageStructure'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initLeftTree="initLeftTree"
            @initRightTree="initRightTree"/>
        <!-- 功能 -->
        <AddFunction
            v-if="actionName === 'addFunction'"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 产品特性 -->
        <AddProductFeature
            v-if="actionName === 'addProductFeature'"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 要求 -->
        <AddRequire
            v-if="actionName === 'addRequire'"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 失效 -->
        <AddFault
            v-if="actionName === 'addFault'"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 预防措施 -->
        <AddPreventionMeasure
            v-if="actionName === 'addPreventionMeasure'"
            :tab="tab"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 探测措施 -->
        <AddProbeMeasure
            v-if="actionName === 'addProbeMeasure'"
            :tab="tab"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 评审意见 -->
        <AddReviewComments
            v-if="actionName === 'addReviewComments'"
            :checkedNode="checkedNode"
            @initLeftTree="initLeftTree"
            @initRightTree="initRightTree"
            @closeModal="closeModal"/>
        <!-- 功能合并 -->
        <MergeFunction
            v-if="actionName === 'mergeFunction'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 产品特性合并 -->
        <MergeProductFeature
            v-if="actionName === 'mergeProductFeature'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 要求合并 -->
        <MergeRequire
            v-if="actionName === 'mergeRequire'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 失效合并 -->
        <MergeFault
            v-if="actionName === 'mergeFault'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 优化措施合并 -->
        <MergeOptimizeMeasure
            v-if="actionName === 'mergeOptimizeMeasure'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 措施组合并 -->
        <MergeGroup
            v-if="actionName === 'mergeGroup'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 预防措施合并 -->
        <MergePreventionMeasure
            v-if="actionName === 'mergePreventionMeasure'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 探测措施合并 -->
        <MergeProbeMeasure
            v-if="actionName === 'mergeProbeMeasure'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 结构属性 -->
        <PropertyStructure
            v-if="actionName === 'propertyStructure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initLeftTree="initLeftTree"
            @initRightTree="initRightTree"/>
        <!-- 接口属性 -->
        <PropertyInterface
            v-if="actionName === 'propertyInterface'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initLeftTree="initLeftTree"
            @initRightTree="initRightTree"/>
        <!-- 功能属性 -->
        <PropertyFunction
            v-if="actionName === 'propertyFunction'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 产品特性属性 -->
        <PropertyProductFeature
            v-if="actionName === 'propertyProductFeature'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 要求属性 -->
        <PropertyRequire
            v-if="actionName === 'propertyRequire'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 失效属性 -->
        <PropertyFault
            v-if="actionName === 'propertyFault'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 当前措施属性 -->
        <PropertyCurrentMeasure
            v-if="actionName === 'propertyCurrentMeasure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 优化措施属性 -->
        <PropertyOptimizeMeasure
            v-if="actionName === 'propertyOptimizeMeasure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 措施组属性 -->
        <PropertyGroup
            v-if="actionName === 'propertyGroup'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 预防措施属性 -->
        <PropertyPreventionMeasure
            v-if="actionName === 'propertyPreventionMeasure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
        <!-- 探测措施属性 -->
        <PropertyProbeMeasure
            v-if="actionName === 'propertyProbeMeasure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRightTree="initRightTree"/>
      </DragModal>
      <!-- 模态框 End -->

      <!-- 功能网 -->
      <FunctionNetModal
          ref="functionNet"
          :showFunctionNetEventListener="showFunctionNetEventListener"
          :showFunctionNetModal="showFunctionNetModal"
          @closeFunctionNetModal="closeFunctionNetModal"
          @initRightTree="initRightTree"/>
      <!-- 失效网 -->
      <FaultNetModal
          ref="faultNet"
          :showFaultNetEventListener="showFaultNetEventListener"
          :showFaultNetModal="showFaultNetModal"
          @closeFaultNetModal="closeFaultNetModal"
          @initRightTree="initRightTree"/>
      <!-- 管理历史失效 -->
      <HistoryFaultModal
          ref="historyFault"
          :showHistoryFaultModal="showHistoryFaultModal"
          @closeHistoryFaultModal="closeHistoryFaultModal"
          @initRightTree="initRightTree"/>
    </div>
  </div>
</template>
<script>

import DragModal from "@/components/DragModal";
import AddMultistageStructure from "../AddModal/AddMultistageStructure";
import AddFunction from "../AddModal/AddFunction";
import AddProductFeature from "../AddModal/AddProductFeature";
import AddRequire from "../AddModal/AddRequire";
import AddFault from "../AddModal/AddFault";
import AddPreventionMeasure from "../AddModal/AddPreventionMeasure";
import AddProbeMeasure from "../AddModal/AddProbeMeasure";
import AddReviewComments from "../AddModal/AddReviewComments";
import MergeFunction from "../MergeModal/MergeFunction";
import MergeProductFeature from "../MergeModal/MergeProductFeature";
import MergeRequire from "../MergeModal/MergeRequire";
import MergeFault from "../MergeModal/MergeFault";
import MergeOptimizeMeasure from "../MergeModal/MergeOptimizeMeasure";
import MergeGroup from "../MergeModal/MergeGroup";
import MergePreventionMeasure from "../MergeModal/MergePreventionMeasure";
import MergeProbeMeasure from "../MergeModal/MergeProbeMeasure";
import PropertyStructure from "../PropertyModal/PropertyStructure";
import PropertyInterface from "../PropertyModal/PropertyInterface";
import PropertyFunction from "../PropertyModal/PropertyFunction";
import PropertyProductFeature from "../PropertyModal/PropertyProductFeature";
import PropertyRequire from "../PropertyModal/PropertyRequire";
import PropertyFault from "../PropertyModal/PropertyFault";
import PropertyCurrentMeasure from "../PropertyModal/PropertyCurrentMeasure";
import PropertyOptimizeMeasure from "../PropertyModal/PropertyOptimizeMeasure";
import PropertyGroup from "../PropertyModal/PropertyGroup";
import PropertyPreventionMeasure from "../PropertyModal/PropertyPreventionMeasure";
import PropertyProbeMeasure from "../PropertyModal/PropertyProbeMeasure";
import FunctionNetModal from "../Net/FunctionNetModal";
import FaultNetModal from "../Net/FaultNetModal";
import HistoryFaultModal from "../HistoryFaultModal/index";
import {
  filterNetNode,
  filterNode,
  replaceNullName,
  handleGeometricToArray,
  handleGeometricToStr,
  arrayToTreeCompare
} from "@/utils/tree";
import {showCurConvertBtn, showMergeBtn, showMoveDownBtn, showMoveUpBtn, showPasteBtn} from "@/utils/treeMenuBtn";
import xeUtils from 'xe-utils';
import AntSpinDot from "@/components/AntSpinDot/index.vue";
import {getUrlParam} from "@/common/common"
import {toLogin} from "@/providers/http.js"; // 返回登陆页面

export default {
  name: "RightTree",
  components: {
    AntSpinDot,
    DragModal,
    AddMultistageStructure,
    AddFunction,
    AddProductFeature,
    AddRequire,
    AddFault,
    AddPreventionMeasure,
    AddProbeMeasure,
    AddReviewComments,
    MergeFunction,
    MergeProductFeature,
    MergeRequire,
    MergeFault,
    MergeOptimizeMeasure,
    MergeGroup,
    MergePreventionMeasure,
    MergeProbeMeasure,
    PropertyStructure,
    PropertyInterface,
    PropertyFunction,
    PropertyProductFeature,
    PropertyRequire,
    PropertyFault,
    PropertyCurrentMeasure,
    PropertyOptimizeMeasure,
    PropertyGroup,
    PropertyPreventionMeasure,
    PropertyProbeMeasure,
    FunctionNetModal,
    FaultNetModal,
    HistoryFaultModal,
  },
  data() {
    return {
      doBatchChangeFlag: false, // 是否正在执行批量替换的标识
      leftTreeFocusingNode: undefined, // 左树聚焦的节点
      leftNodeChangeFlag: false, // 左树聚焦节点是否改变标识
      selectedRows: [], // 批量替换时选中的值
      charToFind: undefined, // 批量替换时搜索的替换内容
      oldSelectedNode: undefined, // 过去批量替换时选中的值
      sodMap: {}, // 判断sod后统一放入该集合
      fssMap: {}, // 严重度
      fsoMap: {}, // 发生度
      fsdMap: {}, // 探测度

      /** 跳转点击右侧树 **/
      clickRight: null,
      /** 功能完整性检查开关 **/
      funInspectionShowHide: false,
      /** 失效完整性检查开关 **/
      failInspectionShowHide: false,
      /** 要求完整性检查开关 **/
      requestInspectionShowHide: false,
      /** sod值完整性检查开关 **/
      sodInspectionShowHide: false,
      /** 高风险项检查开关 **/
      highRiskInspectionShowHide: false,
      /** 关联历史失效显示隐藏：开关 */
      historyShowOrHide: false,
      /** 完整性检查数据 */
      funComp: [],
      reqComp: [],
      faiComp: [],
      sodComp: [],
      riskComp: [],
      historyComp: [],
      /** 初始数据 */
      initData: [],
      /** 初始tree数据 */
      initTreeData: [],
      /** 模态框状态 */
      modalVisible: false,
      /** 模态框唯一Key */
      actionName: "",
      /** 模态框标题 */
      title: "",
      /** 模态框，tab名称 */
      tab: "",
      /** 模态框，选项卡Key */
      tabKey: "",
      /** 节点类型CODE */
      struTypeCode: "",
      /** 选中节点 */
      checkedNode: "",
      /** 功能网模态框开关 */
      showFunctionNetModal: false,
      /** 失效网模态框开关 */
      showFaultNetModal: false,
      /** 历史失效网模态框开关 */
      showHistoryFaultModal: false,
      /** 失效网模态框开关 */
      showFunctionNetEventListener: false,
      /** 失效网模态框开关 */
      showFaultNetEventListener: false,
      /** 潜在关键特性子集 */
      keyFeatureChildren: [],
      /** 加载对象 */
      loader: undefined,
      /** 形位公差数据数组 */
      geometricArray: [],
      /** 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: getUrlParam("enterState") === true ? false : true,
            prev: this.canDragPrev,
            next: this.canDragNext,
            inner: this.canDragInner
          },
          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,
          onDblClick: this.handleOnDblClick,
          onRename: this.handleOnRename,
          onDrop: this.zTreeOnDrop,
          onCollapse: this.treeNodeCollapse,
          onExpand: this.treeNodeExpand,
        }
      },
      // 刷新后选择的节点id
      onAsyncSuccessSelectId: "",
      // 折叠节点ids
      foldNodeIds: [],
    };
  },
  props: {
    filterTypeCode: {
      type: String,
      default: ''
    },
    functionNetShowHide: {
      type: Boolean,
      default: false
    },
    faultNetShowHide: {
      type: Boolean,
      default: false
    },
    versionDiffCloseFlag: {
      type: Boolean,
      default: false
    },
    versionLibraryDiffCloseFlag: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    leftTreeFocusingNode() {
      // 监听左树聚焦节点是否改变
      this.$nextTick(() => {
        this.leftNodeChangeFlag = true;
      })
    },
    filterTypeCode(v) {
      // 处理节点显示/隐藏
      this.handleShowHideNodes();
    },
    functionNetShowHide(v) {
      // 处理节点显示/隐藏
      this.handleShowHideNodes();
    },
    faultNetShowHide(v) {
      // 处理节点显示/隐藏
      this.handleShowHideNodes();
    },
    modalVisible(v) {
      // 关闭监听键盘事件
      this.keyListenerChange(v);
    },
    showFunctionNetModal(v) {
      // 关闭监听键盘事件
      this.keyListenerChange(v);
    },
    showFaultNetModal(v) {
      // 关闭监听键盘事件
      this.keyListenerChange(v);
    },
    selectedNode(v) {
      this.$store.dispatch("fmeaTree/set", {
        key: "multiSelectedNode",
        value: v
      });
    },
    // 监听差异处理弹框标志
    versionDiffCloseFlag(v) {
      if (v) {
        this.initRightTree();
      }
    },
    // 监听知识库差异处理弹框标志
    versionLibraryDiffCloseFlag(v) {
      if (v) {
        this.initRightTree();
      }
    }
  },
  created() {
  },
  mounted() {
    this.forbidRightClick();
    this.initKeyFeature();
    window.handleRAnnexIconClick = this.handleAnnexIconClick;
    jQuery(document).on('mouseout', '.context-menu-item', function() {
      jQuery('.tooltip').remove();
    });
  },
  destroyed() {
  },
  methods: {
    // 批量替换查找改变树节点状态
    changeSelectNodesColor(selectedRows, charToFind) {
      let _that = this;
      _that.leftNodeChangeFlag = false; // 左树聚焦节点是否改变标识
      _that.selectedRows = selectedRows; // 批量替换时选中的row
      _that.charToFind = charToFind; // 批量替换时的替换内容
      // 把之前在查找和替换选中的节点的颜色变为原色
      if (_that.oldSelectedNode) {
        let nodeId = `#${_that.oldSelectedNode.tId}_a`;
        if ($(nodeId)[0]) {
          // 获取高亮标签
          let dom = document.getElementById("yellow_span");
          if (dom) {
            // 被替换的字符串
            let beReplacedStr = '<span style="color: yellow" id="yellow_span">' + dom.innerHTML + '</span>';
            // 替换后的字符串
            let replacement = dom.innerHTML;
            // 替换
            $(nodeId)[0].innerHTML = $(nodeId)[0].innerHTML.replaceAll(beReplacedStr, replacement)
            // 从过去高亮的节点列表中移除该节点
            _that.oldSelectedNode = undefined;
          }
        }
      }
      // 获取左树节点
      if (selectedRows) {
        _that.doBatchChangeFlag = true;
        let leftTree = $.fn.zTree.getZTreeObj('leftTree');
        let leftTreeFocusingNode = leftTree.getNodeByParam("id", selectedRows[0].parentStruId)
        _that.leftTreeFocusingNode = leftTreeFocusingNode; // 左树聚焦节点是
        // 根据右树节点选中左树
        this.$emit('handleLeftNode', leftTreeFocusingNode);
      }
      _that.changeNodeCss(selectedRows, charToFind)
    },
    // 改变右树聚焦节点颜色
    changeNodeCss(selectedRows, charToFind) {
      let _that = this;
      // 现在查找和替换选中的节点的颜色变为黄色
      if (selectedRows) {
        // 获取右树
        let rightTree = $.fn.zTree.getZTreeObj('rightTree');
        let node = rightTree.getNodeByParam("id", selectedRows[0].struId);
        if (node) {
          // 获取节点a标签
          let nodeId = `#${node.tId}_a`;
          // 替换内容
          let description = node.description;
          let replacement = description.replaceAll(charToFind, '<span style="color: yellow" id="yellow_span">' + charToFind + '</span>');
          let beforeStr = $(nodeId)[0].innerHTML.slice(0, $(nodeId)[0].innerHTML.length - 7 - node.description.length);
          // 替换
          $(nodeId)[0].innerHTML = beforeStr + replacement + '</span>';
          _that.oldSelectedNode = node;
          // 右数节点选中
          _that.handleBeforeClick("rightTree", node, 1);
        }
      }
    },
    /******************************************* zTree Start **************************************************/
    /**
     * 初始化右侧树
     */
    initRightTree(zNodes = []) {
      let _that = this;
      // let struId = _that.$store.getters.checkedLeftNode ? _that.$store.getters.checkedLeftNode.id : "";
      //先查是否为评审意见跳转（struIdFromComments）
      let struId = _that.$store.getters.rightParentStruIdFromComments ? _that.$store.getters.rightParentStruIdFromComments :
          _that.$store.getters.checkedLeftNode ? _that.$store.getters.checkedLeftNode.id : "";
      if (_that.$store.getters.commentsParentIds != undefined) {
        _that.expandedKeys = JSON.parse(JSON.stringify(_that.$store.getters.commentsParentIds));
      }
      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.rfmeaId,
        struId: struId
      };
      // 查看权限不允许拖拽节点
      settings.edit.drag.isMove = this.canMove();
      // 初始化ztree
      $.fn.zTree.init($("#rightTree"), settings, zNodes);
      // 若左树聚焦节点改变且正在执行批量替换查找
      if (_that.leftNodeChangeFlag && _that.doBatchChangeFlag) {
        _that.changeNodeCss(_that.selectedRows, _that.charToFind);
        // 执行后将标识设为false
        _that.leftNodeChangeFlag = false;
        _that.doBatchChangeFlag = false;
      }
      if (_that.clickRight) {
        let clickRight = document.getElementById("rightTreeNode" + _that.clickRight);
        if (clickRight !== null) {
          clickRight.click();
        }
      }
      // 获取右侧zTree
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      // 循环所有折叠状态节点将其折叠
      for (let i = 0; i < _that.foldNodeIds.length; i++) {
        treeObj.expandNode(treeObj.getNodeByParam("id", _that.foldNodeIds[i]), false, true, false );
      }
    },
    /**
     * 用于对 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;
      this.initData = 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);
        // 评论意见跳转高亮节点
        if (this.$store.getters.rightStruIdFromComments && node.id == this.$store.getters.rightStruIdFromComments) {
          this.$store.dispatch("fmeaTree/set", {
            key: "checkedRightNode",
            value: node
          });
          this.cleanCommentJumpStruNode()
        }
      }
      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;
      // 缓存treeData数据
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      _that.initTreeData = treeObj.getNodes();
      // 处理节点显示/隐藏
      _that.handleShowHideNodes();
      // 处理选中ZTree节点
      let nodes = [_that.$store.getters.checkedRightNode];
      _that.handleSelectZTreeNodes(treeId, nodes);
      // 刷新移动节点标识状态
      _that.refreshMoveNodeFlag();
      // 刷新顶部按钮状态
      _that.refreshBtnStatus();
      // 恢复高亮复制节点【结构、接口除外】
      let lastCopyOrCutNode = this.$store.getters.lastCopyOrCutNode;
      if (lastCopyOrCutNode && "01,99".indexOf(lastCopyOrCutNode.struTypeCode) === -1) {
        _that.restoreHighLightCopyNode();
      }
      // 关闭加载...
      _that.handleShowHideLoading(false);
      // 设置节点选中
      _that.selectNode(treeId);
      // 处理措施组高中低风险背景色
      _that.handleMeasureGroupBackgroundColor();
    },
    /**
     * 用于捕获 zTree 上鼠标双击之后的事件回调函数
     * @param event
     * @param treeId
     * @param treeNode
     */
    handleOnDblClick(event, treeId, treeNode) {
      // 进入编制状态若为查看，禁用双击重命名
      if (getUrlParam("enterState")) return false;
      // 防止，双击展开折叠时报错
      if (treeNode) {
        // 右侧01结构、右侧99接口、当前措施14、优化措施07不可改名
        if ('01,99,07,14'.indexOf(treeNode?.struTypeCode) !== -1) {
          return false;
        }

        let treeObj = $.fn.zTree.getZTreeObj(treeId);
        treeNode.name = treeNode.description;
        treeObj.editName(treeNode);
        // 禁用快捷键
        this.keyListenerChange(true)
      }
    },
    /**
     * 用于捕获节点编辑名称结束之后的事件回调函数。
     * @param event
     * @param treeId
     * @param treeNode
     * @param isCancel
     */
    handleOnRename(event, treeId, treeNode, isCancel) {
      let _that = this;
      let treeObj = $.fn.zTree.getZTreeObj(treeId);
      // 非空
      if (!treeNode.name) {
        treeNode.name = treeNode.description;
      }
      // 未更改
      if (treeNode.name === treeNode.description) {

      } else {
        if (treeNode.name.length < 500) {
          // 调接口
          _that.$api.updateNodeName({
            fmeaId: _that.$store.getters.rfmeaId,
            struId: treeNode.id,
            struName: treeNode.name,
          }).then((res) => {
            if (res.flag) {
              _that.$message.success(res.message, 1);
              _that.initRightTree();
            } else {
              _that.$message.error(res.message, 1);
            }
          }).catch((error) => {
            _that.$message.error(error.response.data.message);
          });
        } else {
          _that.$message.warn(_that.$t('global-message.warn.node-name-length'));
          treeNode.name = treeNode.description;
        }
      }
      treeNode.description = treeNode.name;
      treeNode.name = this.getNodeName(treeNode);
      treeObj.updateNode(treeNode);
      // 启用快捷键
      this.keyListenerChange(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;';
      }
      // ai生成
      if (node.isAiAdd && node.isAiAdd === '0' && window.apiObj.isAiSwtich) {
        nodeName += `<i class="iconfont iconrengongzhineng-AIkaifapingtai"></i>` + '&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.linkName) {
        nodeName += node.linkName + '&nbsp;';
      }
      // 前缀
      if (node.middleInfo) {
        nodeName += node.middleInfo + '&nbsp;';
      }
      if (node.beginInfo) {
        nodeName += node.beginInfo + '&nbsp;';
      }
      // 特性分类
      if (node.lname) {
        nodeName += xeUtils.escape(node.lname) + '&nbsp;';
      } else if (node.fileName) {
        let preUrl = this.$api.baseUrl + "/DFMEA/file/";
        nodeName += '<img width="25" height="25" src=' + preUrl + node.fileName + ' alt=""/>' + '&nbsp;';
      }
      nodeName += node.description;
      // 后缀
      if (node.endInfo) {
        nodeName += '&nbsp;' + node.endInfo;
        // 形位公差符号
        if (node.geometric) {
          nodeName += '&nbsp;' + this.getGeometricName(node, true);
        }
      }
      // 形位公差符号
      // if (node.geometric) {
      //   nodeName += '&nbsp;' + this.getGeometricName(node,true);
      // }
      // 完整性检查
      if ('02,04'.indexOf(node.struTypeCode) != -1 && this.funInspectionShowHide && this.funComp.indexOf(node.id) != -1) {
        nodeName += '<span style="color: #de0b0b">(' + this.$t("functional-analysis.top-btn.lose-function") + ')</span>';
      } else if ('02,04'.indexOf(node.struTypeCode) != -1 && this.failInspectionShowHide && this.faiComp.indexOf(node.id) != -1) {
        nodeName += '<span style="color: #de0b0b">(' + this.$t("functional-analysis.top-btn.lose-failure") + ')</span>';
      } else if ('02'.indexOf(node.struTypeCode) != -1 && this.requestInspectionShowHide && this.reqComp.indexOf(node.id) != -1) {
        nodeName += '<span style="color: #de0b0b">(' + this.$t("functional-analysis.top-btn.lose-require") + ')</span>';
      } else if ('02,04'.indexOf(node.struTypeCode) != -1 && this.sodInspectionShowHide && this.sodComp.indexOf(node.id) != -1) {
        nodeName += '<span style="color: #de0b0b">(' + this.$t("functional-analysis.top-btn.lose-sod") + ')</span>';
      } else if ('08'.indexOf(node.struTypeCode) != -1 && this.highRiskInspectionShowHide && this.riskComp.indexOf(node.id) != -1) {
        nodeName += '<span style="color: #de0b0b">(' + this.$t("functional-analysis.top-btn.has-high-risk") + ')</span>';
      }
      // 历史失效显示/隐藏
      if ('06'.indexOf(node.struTypeCode) != -1 && this.historyShowOrHide && this.historyComp.indexOf(node.id) != -1) {
        nodeName += '<span style="color: #de0b0b">(' + this.$t("functional-analysis.top-btn.invalid-associated-history") + ')</span>';
      }


      return nodeName;
    },
    /**
     * 完整性检查
     */
    changeCheckNodes() {
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      // 还原完整性检查的节点数据，防止切换完整性检查时出现脏数据
      this.cleanCurrentRightTreeNodes();
      // 功能完整性检查
      if (this.funInspectionShowHide && this.funComp.length > 0) {
        this.funComp.forEach((nodeId) => {
          let funcNode = treeObj.getNodeByParam("id", nodeId);
          if (funcNode && funcNode.struTypeCode !== "01") {
            funcNode.name = this.getNodeName(funcNode);
            treeObj.updateNode(funcNode);
          }
        })
        // 失效完整性检查
      } else if (this.failInspectionShowHide && this.faiComp.length > 0) {
        this.faiComp.forEach((nodeId) => {
          let failNode = treeObj.getNodeByParam("id", nodeId);
          if (failNode && failNode.struTypeCode !== "01") {
            failNode.name = this.getNodeName(failNode);
            treeObj.updateNode(failNode);
          }
        })
        // 要求完整性检查
      } else if (this.requestInspectionShowHide && this.reqComp.length > 0) {
        this.reqComp.forEach((nodeId) => {
          let reqNode = treeObj.getNodeByParam("id", nodeId);
          if (reqNode && reqNode.struTypeCode !== "01") {
            reqNode.name = this.getNodeName(reqNode);
            treeObj.updateNode(reqNode);
          }
        })
        // sod完整性检查
      } else if (this.sodInspectionShowHide && this.sodComp.length > 0) {
        this.sodComp.forEach((nodeId) => {
          let sodNode = treeObj.getNodeByParam("id", nodeId);
          if (sodNode && sodNode.struTypeCode !== "01") {
            sodNode.name = this.getNodeName(sodNode);
            treeObj.updateNode(sodNode);
          }
        })
        // 高风险项完整性检查
      } else if (this.highRiskInspectionShowHide && this.riskComp.length > 0) {
        this.riskComp.forEach((nodeId) => {
          let riskNode = treeObj.getNodeByParam("id", nodeId);
          if (riskNode && riskNode.struTypeCode !== "01") {
            riskNode.name = this.getNodeName(riskNode);
            treeObj.updateNode(riskNode);
          }
        })
      } else if (this.historyShowOrHide && this.historyComp.length > 0) {
        this.historyComp.forEach((nodeId) => {
          let historyNode = treeObj.getNodeByParam("id", nodeId);
          if (historyNode && historyNode.struTypeCode !== "01") {
            historyNode.name = this.getNodeName(historyNode);
            treeObj.updateNode(historyNode);
          }
        })
      } else {
        this.reductionCheckNodes();
      }
      // this.initRightTree();
    },
    /**
     * 清除当前右树的节点完整性检查
     */
    cleanCurrentRightTreeNodes() {
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      if (this.initData.length > 0) {
        this.initData.forEach(node => {
          let rightTreeNode = treeObj.getNodeByParam("id", node.id);
          if (rightTreeNode) {
            rightTreeNode.name = this.getNodeName(rightTreeNode);
            treeObj.updateNode(rightTreeNode);
          }
        })
      }
    },
    /**
     * 还原完整性检查节点
     */
    reductionCheckNodes() {
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      this.funComp.forEach((nodeId) => {
        let funcNode = treeObj.getNodeByParam("id", nodeId);
        if (funcNode) {
          funcNode.name = this.getNodeName(funcNode);
          treeObj.updateNode(funcNode);
        }
      })
      this.faiComp.forEach((nodeId) => {
        let failNode = treeObj.getNodeByParam("id", nodeId);
        if (failNode) {
          failNode.name = this.getNodeName(failNode);
          treeObj.updateNode(failNode);
        }
      })
      this.reqComp.forEach((nodeId) => {
        let reqNode = treeObj.getNodeByParam("id", nodeId);
        if (reqNode) {
          reqNode.name = this.getNodeName(reqNode);
          treeObj.updateNode(reqNode);
        }
      })
      this.sodComp.forEach((nodeId) => {
        let sodNode = treeObj.getNodeByParam("id", nodeId);
        if (sodNode) {
          sodNode.name = this.getNodeName(sodNode);
          treeObj.updateNode(sodNode);
        }
      })
      this.riskComp.forEach((nodeId) => {
        let riskNode = treeObj.getNodeByParam("id", nodeId);
        if (riskNode) {
          riskNode.name = this.getNodeName(riskNode);
          treeObj.updateNode(riskNode);
        }
      })
      this.historyComp.forEach((nodeId) => {
        let historyNode = treeObj.getNodeByParam("id", nodeId);
        if (historyNode) {
          historyNode.name = this.getNodeName(historyNode);
          treeObj.updateNode(historyNode);
        }
      })
    },
    /**
     * 取得行位公差名称
     * @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);
        }
      }
    },
    /**
     * 默认展开全部节点
     * @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);
        }
      }
    },
    /**
     * 单级折叠/展开（顶部按钮）
     */
    collapseExpand() {
      let _that = this;
      let checkedNode = _that.$store.getters.lastCheckedNode;
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      treeObj.expandNode(checkedNode, !checkedNode?.open, true, true);
      _that.saveFoldNodeIds(checkedNode);
    },
    /**
     * 全部折叠/展开（顶部按钮）
     */
    collapseExpandAll() {
      let _that = this;
      let checkedNode = _that.$store.getters.lastCheckedNode;
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      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);
        _that.saveFoldNodeIds(nodes[i]);
      }
    },
    /**
     * 树节点折叠
     */
    treeNodeCollapse(event, treeId, treeNode) {
      this.saveFoldNodeIds(treeNode);
    },
    /**
     * 树节点展开
     */
    treeNodeExpand(event, treeId, treeNode) {
      this.saveFoldNodeIds(treeNode);
    },
    /**
     * 保存节点展开折叠状态
     */
    saveFoldNodeIds(checkedNode) {
      let _that = this;
      // open：f为折叠 t为展开
      if (!checkedNode?.open) {
        // 存储折叠节点ID
        _that.foldNodeIds.push(checkedNode.id)
      } else {
        // 清除节点折叠状态
        _that.foldNodeIds = _that.foldNodeIds.filter(item => item !== checkedNode.id);
      }
    },
    /**
     * 处理节点显示/隐藏
     */
    handleShowHideNodes() {
      let _that = this;
      let showNodes = [];
      let filterNodes = _that.$store.getters.variantFilterNodes;
      jQuery.extend(true, showNodes, _that.initData);
      let rootNode = _that.initData[0];
      let historyShowHide = _that.historyShowOrHide;
      if (_that.filterTypeCode || filterNodes.length > 0) {
        // 过滤节点类型
        // 兼容完整性检查 需要对initData的节点名称进行处理
        let initData = _that.initData;
        if (initData.length > 0) {
          initData.forEach((node) => {
            node.name = _that.getNodeName(node);
          });
        };
        filterNode(_that.initTreeData, initData, rootNode.pid, _that.filterTypeCode,
            filterNodes, showNodes = [], historyShowHide);
      }
      if (!_that.functionNetShowHide || !_that.faultNetShowHide) { // 过滤功能网、失效网完整性检查
        let netType = this.getNodeNetType();
        let filterNetTypeCode = !_that.functionNetShowHide ? '02,04,05' : '06';
        showNodes = filterNetNode(showNodes, netType, filterNetTypeCode);
      }
      // 左序号升序
      showNodes.sort((a, b) => {
        return a.leftNo - b.leftNo
      });
      _that.initRightTree(showNodes);
    },
    /**
     * 取得节点的连接方式
     */
    getNodeNetType() {
      let structureNode = this.initData[0];
      let netType;
      // 当前结构为根节点
      if (structureNode.deep === 1) netType = '01,11';
      // 当前结构为叶子节点
      else if (this.isLeafNode(structureNode.id)) netType = '10,11';
      // 当前结构为中间部分
      else netType = '11';
      return netType;
    },
    /**
     * 是否是叶子节点
     * @param id
     */
    isLeafNode(id) {
      let treeObj = $.fn.zTree.getZTreeObj('leftTree');
      let node = treeObj.getNodeByParam("id", id);
      if (node.children) {
        return false;
      }
      return true;
    },
    /**
     * 是否最大层级
     * @param id
     */
    isMaxDeep(id) {
      let maxDeepNodes = [];
      let treeObj = $.fn.zTree.getZTreeObj('leftTree');
      let nodes = treeObj.transformToArray(treeObj.getNodes());
      let maxDeep = 1;
      for (let i = 0, len = nodes.length; i < len; i++) {
        if (nodes[i].deep > maxDeep) maxDeep = nodes[i].deep;
      }
      for (let i = 0, len = nodes.length; i < len; i++) {
        if (nodes[i].deep === maxDeep) maxDeepNodes.push(nodes[i].id);
      }
      return maxDeepNodes.indexOf(id) !== -1;
    },
    /**
     * 显示、隐藏 -- 加载Loading
     * @param flag
     */
    handleShowHideLoading(flag) {
      if (flag) {
        if (this.loader) this.loader.hide();
        this.loader = this.$loading.show({
          container: this.$refs.rightTree,
          color: '#1890FF',
        }, {
          // 自定义加载动画组件
          default: this.$createElement('ant-spin-dot'),
        });
      } else {
        this.loader.hide();
      }
    },
    /**
     * 处理措施组背景颜色
     */
    handleMeasureGroupBackgroundColor() {
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      let nodes = treeObj.getNodesByParam('struTypeCode', '08');
      nodes.forEach(node => {
        let k = node.struTypeCode + '_' + node.beginInfo.substr(-1);
        let v = this.$store.getters.nodeTypeDict.zTreeRNodeColor[k];
        $('#' + node.tId + '_span').css("background-color", v);
      });
    },
    /******************************************* zTree End **************************************************/

    /******************************************* 右键菜单 Start **************************************************/
    /**
     * 获取右键菜单项
     */
    getMenuBtn() {
      // 选中节点
      let checkedNode = this.$store.getters.lastCheckedNode;
      // 复制剪切的节点
      let lastCopyOrCutNode = this.$store.getters.lastCopyOrCutNode;
      // 复制剪切的标识位：copy、cut
      let lastCopyOrCut = this.$store.getters.lastCopyOrCut;
      // 获取节点类型对应的菜单列表(只有菜单的code)
      let cNodeMenus = this.getCurrentNodeMenus(checkedNode);
      let menuBtn = {};
      this.$store.getters.rightTreeMenus.map((item) => {
        if (cNodeMenus.indexOf(item.key) !== -1) {
          switch (item.key) {
            case "paste": // 粘贴
              if (!lastCopyOrCut) return false; // 没有复制或剪切，不允许粘贴
              // 剪切的节点不能粘贴在它的子节点下(包含自己)
              if (showPasteBtn('rightTree', this.$store.getters.nodeTypeDict.paste,
                  lastCopyOrCutNode, checkedNode, lastCopyOrCut) === 1) return false;
              break;
            case "merge": // 合并
              if (checkedNode.deep === 1) return false;  // 根节点不能合并
              else if (!showMergeBtn('rightTree', checkedNode)) return false;
              break;
            case "addParent": // 添加上级
              if (checkedNode.deep !== 1) return false;  // 根节点可以添加
              break;
            case "moveUp": // 上移
              if (checkedNode.deep === 1) return false;  // 根节点不能移动
              else if (!showMoveUpBtn('rightTree', checkedNode)) return false;
              break;
            case "moveDown": // 下移
              if (checkedNode.deep === 1) return false;  // 根节点不能移动
              else if (!showMoveDownBtn('rightTree', checkedNode)) return false;
              break;
            case "keyFeature": // 关键产品特性
              if (this.keyFeatureChildren.length === 0) return false;
              item.children = this.keyFeatureChildren;
              break;
            case "convert": // 转换
              if (!showCurConvertBtn('rightTree', checkedNode)) return false;
              item.label = this.getConvertMenuLabel(checkedNode);
              break;
            case "addCurrentMeasure": // 当前措施
              // 若失效下存在"当前措施"，不显示。
              if (this.isExistCurrentMeasure(checkedNode)) return false;
              break;
            case "addCurrentPreventionMeasure": // 当前预防控制
              if (!this.showCurOptMeasureBtn(checkedNode, item.key)) return false;
              break;
            case "addCurrentProbeMeasure": // 当前探测控制
              if (!this.showCurOptMeasureBtn(checkedNode, item.key)) return false;
              break;
            case "addOptimizePreventionMeasure": // 优化预防控制
              if (!this.showCurOptMeasureBtn(checkedNode, item.key)) return false;
              break;
            case "addOptimizeProbeMeasure": // 优化探测控制
              if (!this.showCurOptMeasureBtn(checkedNode, item.key)) return false;
              break;
            case "addCurrentPreventionMeasureInference": // 当前预防控制推理
              if (!window.apiObj.isAiSwtich) return false;
              if (!this.showCurOptMeasureBtn(checkedNode, item.key)) return false;
              break;
            case "addCurrentProbeMeasureInference": // 当前探测控制推理
              if (!window.apiObj.isAiSwtich) return false;
              if (!this.showCurOptMeasureBtn(checkedNode, item.key)) return false;
              break;
            case "addOptimizePreventionMeasureInference": // 优化预防控制推理
              if (!window.apiObj.isAiSwtich) return false;
              if (!this.showCurOptMeasureBtn(checkedNode, item.key)) return false;
              break;
            case "addOptimizeProbeMeasureInference": // 优化探测控制推理
              if (!window.apiObj.isAiSwtich) return false;
              if (!this.showCurOptMeasureBtn(checkedNode, item.key)) return false;
              break;
            case "addFunctionInference": // 功能推理
              if (!window.apiObj.isAiSwtich) return false;
              break;
            case "addFaultInference": // 失效推理
              if (!window.apiObj.isAiSwtich) return false;
              break;
            case "addSeverityInference": // 严重度(S)推理
              if (!window.apiObj.isAiSwtich) return false;
              break;
            case "addOccurrenceInference": // 发生度(O)推理
              if (!window.apiObj.isAiSwtich) return false;
              break;
            case "addDetectionInference": // 探测度(D)推理
              if (!window.apiObj.isAiSwtich) return false;
              break;
              /*case "property": // 属性
                if (checkedNode.connectId) return false;  // 连线结构没有属性
                break;*/
            default:
              break;
          }
          // 追加菜单项
          let menuObj = {name: this.$t('' + item.label + ''), icon: "fas iconfont " + item.icon};
          let children = {};
          if (item.children && item.children.length > 0) {
            // 遍历该菜单项的children，查询是否为HTML标签
            // 主要是为了特性分类图标而做的处理，在特性分类初始化(initKeyFeature方法)时，如果该特性分类是图标就会设置<img>标签，所以要在右键菜单做一下处理，区分一下是否是HTML标签，否则显示异常
            for (let i = 0, len = item.children.length; i < len; i++) {
              children['' + item.children[i].key + ''] = {
                name: this.$t('' + item.children[i].label + ''),
                isHtmlName: item.children[i].isHtmlName
              };
            }
            menuObj['items'] = children;
          }
          menuBtn['' + item.key + ''] = menuObj;
        }
      });
      // 处理右键菜单的分割线
      menuBtn = this.handleContextMenuSep(menuBtn);
      return menuBtn;
    },
    /**
     * 处理右键菜单的分割线
     * @param menuBtn
     */
    handleContextMenuSep(menuBtn) {
      let afterFilter = Object.keys(menuBtn);
      let operationTypes = this.$store.getters.nodeTypeDict.operationType;
      let sepIndex = 1;
      for (let i = 0; i < operationTypes.length; i++) {
        let innerJoinArray = afterFilter.filter((v) => operationTypes[i].includes(v));
        if (innerJoinArray && innerJoinArray.length > 0) {
          let index = afterFilter.findIndex(val => val === innerJoinArray[innerJoinArray.length - 1]);
          // 最后一组分割线不显示
          if (i < operationTypes.length - 1 && afterFilter.length > 1) {
            afterFilter.splice(index + 1, 0, 'sep' + sepIndex++);
          }
        }
      }
      let newMenuBtn = {};
      for (let i = 0; i < afterFilter.length; i++) {
        for (let j in menuBtn) {
          if (afterFilter[i] === j) {
            newMenuBtn['' + afterFilter[i] + ''] = menuBtn[j];
            break;
          } else {
            newMenuBtn['' + afterFilter[i] + ''] = "---------";
          }
        }
      }
      return newMenuBtn;
    },
    /**
     * 处理右键菜单
     * @param node 节点
     * @param items 菜单项
     */
    handleContextMenu(node, items) {
      let _that = this;
      if ($('.context-menu-item')) {
        $('.context-menu-item').off('mouseover');
      }
      _that.getSeverityToolTip(); // 获取评分标准 SOD
      // 隐藏上次菜单
      let selector = '#' + node.tId + '_a'
      jQuery.contextMenu('destroy', selector);
      jQuery.contextMenu({
        selector: selector,
        autoHide: true,
        zIndex: 10,
        items: items,
        callback: function (itemKey, opt) {
          let arr = itemKey.split("_");
          let key, label, classify;
          key = arr[0];
          if (arr.length > 1) {
            if (key === 'addSeverity'
                || key === 'addOccurrence'
                || key === 'addDetection') { // 严重度(S)、发生度(O)、探测度(D)
              label = opt.items[arr[0]].items[itemKey].name;
            } else if (key === 'keyFeature') { // 潜在关键特性
              classify = arr[1];
            }
          } else {
            label = opt.items[arr[0]].name;
          }
          let actionInfo = {key: key, label: label, classify: classify};
          _that.menuAction(actionInfo);
        },
      });
      // 在菜单渲染后，为每个li绑定鼠标悬停事件
      jQuery(document).on('mouseover', '.context-menu-item', function(e) {
        let tooltipContent = e.target.innerText; // 获取当前元素的文本内容作为提示框内容
        if (tooltipContent.includes('(') && tooltipContent.includes(')')) {
          // 取括号中的内容
          const regex = /\(([^()]*)\)/;
          const match = tooltipContent.match(regex);
          const content = match[1];
          // 判断S， O， D
          if (content.includes('S')) {
            _that.sodMap = _that.fssMap;
          }
          if (content.includes('O')) {
            _that.sodMap = _that.fsoMap;
          }
          if (content.includes('D')) {
            _that.sodMap = _that.fsdMap;
          }
        }
        // 创建提示框元素
        let tooltip = document.createElement('div');
        if (_that.sodMap[tooltipContent]) {
          tooltip.className = 'tooltip'; // 添加样式类名
          tooltip.innerHTML = _that.sodMap[tooltipContent] // 设置tooltip值
          tooltip.style.position = 'absolute'; // 绝对定位
          tooltip.style.background = 'rgba(0, 0, 0, 0.7)'; /* 黑色背景，70%透明度 */
          tooltip.style.color = 'white'; /* 文字颜色 */
          tooltip.style.fontSize = '15px'; /* 字体大小 */
          tooltip.style.borderRadius = '4px'; /* 圆角 */
          tooltip.style.padding = '3px'; /* 设置内边距 */
          tooltip.style.textAlign = 'center'; /* 文字居中对齐 */
          document.body.appendChild(tooltip); // 将提示框添加到body中
        }

        // 获取菜单元素
        let menuElement = e.target.closest('.context-menu-item');
        let menuRect = menuElement.getBoundingClientRect();

        // 计算提示框的位置，使其出现在菜单右侧
        tooltip.style.top = `${menuRect.top}px`; // 距离顶部的距离不变
        tooltip.style.left = `${menuRect.right + 5}px`; // 距离左侧等于菜单元素的右侧

        // 移除之前的提示框，避免重复
        jQuery('.tooltip').not(tooltip).remove();
      });
    },
    // 获取评分标准 SOD
    getSeverityToolTip() {
      let _that = this;
      // 获取当前FMEA正在使用的评分标准
      _that.$api.getScoringCriteria({
        fmeaId: _that.$store.getters.rfmeaId
      }).then(res => {
        if (res.flag) {
          let defaultStandardId = res.data.defaultStandardId;
          if (!defaultStandardId) return;
          _that.$api.getScoringCriteriaDetail({
            standardId: defaultStandardId,
          }).then(res => {
            if (res.flag) {
              // 严重度 fss List -> Map
              let fssList = res.data.fss;
              fssList.forEach(item => {
                this.fssMap[item.standardLevel] = item.attr2;
              });
              // 发生度 fso List -> Map
              let fsoList = res.data.fso;
              fsoList.forEach(item => {
                this.fsoMap[item.standardLevel] = item.attr2;
              });
              // 探测度 fsd List -> Map
              let fsdList = res.data.fsd;
              fsdList.forEach(item => {
                this.fsdMap[item.standardLevel] = item.attr2;
              });
            } else {
              this.$message.error(res.message, 1);
            }
          });
        } else {
          _that.$message.error(res.message, 1);
        }
      });
    },
    /**
     * 取得转换菜单项：名称
     * @param node 节点
     */
    getConvertMenuLabel(node) {
      let label;
      let converts = this.$store.getters.nodeTypeDict.convertMenus;
      for (let i = 0, len = converts.length; i < len; i++) {
        if ("09,10".indexOf(node.struTypeCode) !== -1) {
          let treeObj = $.fn.zTree.getZTreeObj('rightTree');
          let groupNode = treeObj.getNodeByParam("id", node.pid, null);
          let measureNode = treeObj.getNodeByParam("id", groupNode.pid, null);
          if (converts[i].key === (measureNode.struTypeCode + node.struTypeCode)) {
            label = converts[i].label;
            break;
          }
        }
        if (converts[i].key === node.struTypeCode) {
          label = converts[i].label;
          break;
        }
      }
      return label;
    },
    /**
     * 是否存在当前措施
     * @param node 节点
     */
    isExistCurrentMeasure(node) {
      let treeObj = $.fn.zTree.getZTreeObj('rightTree');
      let children = treeObj.getNodesByParam("pid", node.id, null);
      let curNode = (children || []).filter((item) => {
        return item.struTypeCode === '14';
      })[0];
      return !!curNode;
    },
    /**
     * 展示当前/优化 预防控制、探测控制
     * @param node 节点
     * @param menuKey 菜单标识
     */
    showCurOptMeasureBtn(node, menuKey) {
      if (node.struTypeCode === '08') {
        let treeObj = $.fn.zTree.getZTreeObj('rightTree');
        let measureNode = treeObj.getNodeByParam("id", node.pid, null);
        if (measureNode.struTypeCode === '14' && this.$store.getters.nodeTypeDict.curGroup.indexOf(menuKey) !== -1) {
          return true;
        }
        return measureNode.struTypeCode === '07' && this.$store.getters.nodeTypeDict.optGroup.indexOf(menuKey) !== -1;
      }
      return true;
    },
    /**
     * 右键菜单事件
     * @param actionInfo 菜单项信息
     */
    menuAction(actionInfo) {
      let checkedNode = this.$store.getters.lastCheckedNode;
      this.checkedNode = checkedNode;
      this.actionName = actionInfo.key;
      switch (actionInfo.key) {
        case "addMultistageStructure": // 多级添加
          this.clearHighLightCopyCutNode();
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addFunction": // 功能
          this.clearHighLightCopyCutNode();
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addFunctionInference": // 功能推理
          this.clearHighLightCopyCutNode();
          this.saveNodeAiInference(checkedNode, "02");
          break;
        case "addProductFeature": // 产品特性
          this.clearHighLightCopyCutNode();
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addRequire": // 要求
          this.clearHighLightCopyCutNode();
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addFault": // 添加失效
          this.clearHighLightCopyCutNode();
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addFaultInference": // 失效推理
          this.clearHighLightCopyCutNode();
          this.saveNodeAiInference(checkedNode, "06");
          break;
        case "showFunctionNet": // 显示功能网
          this.clearHighLightCopyCutNode();
          this.$refs.functionNet.setCheckedNode(checkedNode.id);
          this.$refs.functionNet.initFunctionNet(checkedNode.id, 1, 1);
          this.$refs.functionNet.handleCenterMenuItems(checkedNode.id);
          this.$refs.functionNet.firstFunctionNetNode = {id: checkedNode.id, name: checkedNode.description};
          this.$refs.functionNet.initLeftTree();
          this.$refs.functionNet.title = checkedNode.description;
          this.$refs.functionNet.structureSwitch = true;
          this.showFunctionNetEventListener = true;
          this.showFunctionNetModal = true;
          this.$refs.functionNet.forbiddenRightClick();
          break;
        case "showFaultNet": // 显示失效网
          this.clearHighLightCopyCutNode();
          this.$refs.faultNet.setCheckedNode(checkedNode.id, checkedNode.pid);
          this.$refs.faultNet.initFaultNet(checkedNode.id, 1, 1);
          this.$refs.faultNet.handleCenterMenuItems(checkedNode.id);
          this.$refs.faultNet.firstFaultNetNode = {
            id: checkedNode.id,
            pid: checkedNode.pid,
            name: checkedNode.description
          };
          this.$refs.faultNet.initLeftTree();
          this.$refs.faultNet.title = checkedNode.description;
          this.$refs.faultNet.structureSwitch = true;
          this.$refs.faultNet.functionSwitch = true;
          this.showFaultNetEventListener = true;
          this.showFaultNetModal = true;
          this.$refs.faultNet.forbiddenRightClick();
          break;
        case "joinHistoryFault": // 关联历史失效案例库
          this.clearHighLightCopyCutNode();
          this.$refs.historyFault.initDict();
          this.$refs.historyFault.list();
          this.showHistoryFaultModal = true;
          this.$refs.historyFault.handleResize();
          this.$nextTick(() => {
            this.$refs.historyFault.initTableColumns();
          });
          break;
        case "addSeverity": // 严重度(S)
          this.clearHighLightCopyCutNode();
          this.updateNodeSOD(checkedNode.id, actionInfo.label, 1);
          break;
        case "addSeverityInference": // 严重度(S)推理
          this.clearHighLightCopyCutNode();
          this.saveSodAiInference(checkedNode, 1);
          break;
        case "addOccurrence": // 发生度(O)
          this.clearHighLightCopyCutNode();
          this.updateNodeSOD(checkedNode.id, actionInfo.label, 2);
          break;
        case "addOccurrenceInference": // 发生度(O)推理
          this.clearHighLightCopyCutNode();
          this.saveSodAiInference(checkedNode, 2);
          break;
        case "addDetection": // 探测度(D)
          this.clearHighLightCopyCutNode();
          this.updateNodeSOD(checkedNode.id, actionInfo.label, 3);
          break;
        case "addDetectionInference": // 探测度(D)推理
          this.clearHighLightCopyCutNode();
          this.saveSodAiInference(checkedNode, 3);
          break;
        case "keyFeature": // 潜在关键特性
          // if (!actionInfo.classify) break;
          this.clearHighLightCopyCutNode();
          this.updateNodeClassify(checkedNode, actionInfo.classify);
          break;
        case "addCurrentMeasure": // 当前措施
          this.clearHighLightCopyCutNode();
          this.addMeasure(checkedNode, this.$t('functional-analysis.add-modal.append.current.measure'), '14');
          break;
        case "addGroup": // 措施组
          this.clearHighLightCopyCutNode();
          this.addGroup(checkedNode);
          break;
        case "addCurrentPreventionMeasure": // 当前预防控制
          this.clearHighLightCopyCutNode();
          this.actionName = "addPreventionMeasure"; // 使用预防措施组件
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addCurrentPreventionMeasureInference": // 当前预防控制推理
          this.clearHighLightCopyCutNode();
          this.saveMeasureiAiInference(checkedNode, "09", "14");
          break;
        case "addCurrentProbeMeasure": // 当前探测控制
          this.clearHighLightCopyCutNode();
          this.actionName = "addProbeMeasure"; // 使用探测措施组件
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addCurrentProbeMeasureInference": // 当前探测控制推理
          this.clearHighLightCopyCutNode();
          this.saveMeasureiAiInference(checkedNode, "10", "14");
          break;
        case "addOptimizeMeasure": // 优化措施
          this.clearHighLightCopyCutNode();
          this.addMeasure(checkedNode, this.$t('functional-analysis.add-modal.append.optimize.measure'), '07');
          break;
        case "addOptimizePreventionMeasure": // 优化预防控制
          this.clearHighLightCopyCutNode();
          this.actionName = "addPreventionMeasure"; // 使用预防措施组件
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addOptimizePreventionMeasureInference": // 优化预防控制推理
          this.clearHighLightCopyCutNode();
          this.saveMeasureiAiInference(checkedNode, "09", "07");
          break;
        case "addOptimizeProbeMeasure": // 优化探测控制
          this.clearHighLightCopyCutNode();
          this.actionName = "addProbeMeasure"; // 使用探测措施组件
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addOptimizeProbeMeasureInference": // 优化探测控制推理
          this.clearHighLightCopyCutNode();
          this.saveMeasureiAiInference(checkedNode, "10", "07");
          break;
        case "copy": // 复制
          this.setHighLightCopyCutNode("copy");
          this.refreshBtnStatus();
          break;
        case "cut": // 剪切
          this.setHighLightCopyCutNode("cut");
          this.refreshBtnStatus();
          break;
        case "paste": // 粘贴
          this.paste();
          break;
        case "merge": // 合并
          this.clearHighLightCopyCutNode();
          this.handleMergeModal(checkedNode);
          this.modalVisible = true;
          break;
        case "delete": // 删除
          this.clearHighLightCopyCutNode();
          this.deleteNode(checkedNode);
          break;
        case "moveUp": // 上移
          this.clearHighLightCopyCutNode();
          this.moveNode(checkedNode, -1);
          break;
        case "moveDown": // 下移
          this.clearHighLightCopyCutNode();
          this.moveNode(checkedNode, 1);
          break;
        case "convert": // 转换
          this.clearHighLightCopyCutNode();
          this.convertNode(checkedNode);
          break;
        case "property": // 属性
          this.clearHighLightCopyCutNode();
          this.handlePropertyModal(checkedNode);
          this.modalVisible = true;
          break;
        case "addReviewComments": // 添加评审意见
          this.clearHighLightCopyCutNode();
          this.handleReviewCommentsModal(checkedNode);
          this.modalVisible = true;
          break;
      }
    },
    /**
     * 处理添加
     * @param node 节点
     * @param menuKey 菜单标识
     */
    handleAddModal(node, menuKey) {
      let name = node.description;
      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;
        }
      }
    },
    /**
     * 处理合并Modal逻辑
     * @param node 节点
     */
    handleMergeModal(node) {
      let struTypeCode = node.struTypeCode;
      let merges = this.$store.getters.nodeTypeDict.mergeModals;
      for (let i = 0; i < merges.length; i++) {
        if (merges[i].key === struTypeCode) {
          this.actionName = merges[i].action;
          this.title = this.$t('' + merges[i].title + '');
          return;
        }
      }
    },
    /**
     * 处理属性Modal逻辑
     * @param node 节点
     * @param tabKey 选项卡Key
     */
    handlePropertyModal(node, tabKey = "") {
      let name = "14,07".indexOf(node.struTypeCode) !== -1 ? "" : node.description;
      let merges = this.$store.getters.nodeTypeDict.propertyModals;
      let merge = {};
      for (let i = 0; i < merges.length; i++) {
        if ("09,10".indexOf(node.struTypeCode) !== -1) {
          let treeObj = $.fn.zTree.getZTreeObj("rightTree");
          let grouNode = treeObj.getNodeByParam("id", node.pid, null);
          let measureNode = treeObj.getNodeByParam("id", grouNode.pid, null);
          if (merges[i].key === (measureNode.struTypeCode + node.struTypeCode)) {
            merge = merges[i];
            break;
          }
        }
        if (merges[i].key === node.struTypeCode) {
          merge = merges[i];
          break;
        }
      }
      this.actionName = merge.action;
      this.title = this.$t('' + merge.title + '') + name;
      this.tabKey = tabKey;
    },
    /**
     * 处理评审意见Modal逻辑
     * @param node 节点
     */
    handleReviewCommentsModal(node) {
      let name = "14,07".indexOf(node.struTypeCode) !== -1 ? "" : node.description;
      let reviewComments = this.$store.getters.nodeTypeDict.reviewCommentsModals;
      for (let i = 0, len = reviewComments.length; i < len; i++) {
        if ("09,10".indexOf(node.struTypeCode) !== -1) {
          let treeObj = $.fn.zTree.getZTreeObj("rightTree");
          let grouNode = treeObj.getNodeByParam("id", node.pid, null);
          let measureNode = treeObj.getNodeByParam("id", grouNode.pid, null);
          if (reviewComments[i].key === measureNode.struTypeCode) {
            this.title = this.$t('' + reviewComments[i].title + '') + name;
            return;
          }
        }
        if (reviewComments[i].key === node.struTypeCode) {
          this.title = this.$t('' + reviewComments[i].title + '') + name;
          return;
        }
      }
    },
    /**
     * 初始化潜在关键特性
     */
    initKeyFeature() {
      let _that = this;
      // 获取当前FMEA正在使用的特性种类
      _that.$api.getCharacteristicType({
        fmeaId: _that.$store.getters.rfmeaId
      }).then(res => {
        if (res.flag) {
          let defaultPductClassifyId = res.data.defaultPductClassifyId;
          if (!defaultPductClassifyId) return;
          _that.$api.getKeyFeature({
            pductClassifyId: defaultPductClassifyId,
          }).then(res => {
            if (res.flag) {
              // 获取特性分类图标文件位置
              let preUrl = _that.$api.baseUrl + "/DFMEA/file/";
              let resData = res.data.rfmPductClassifyDetailModels.filter(item => {
                // 状态'0'，启用
                return item.state === '0';
              }).map(item => {
                return {
                  key: "keyFeature_" + item.detailId,
                  // 如果特性分类是图标，则插入DOM元素<img/>标签，图标位置为preUrl + 图标文件名称
                  // 在获取右键菜单方法getMenuBtn（）中，会遍历是否是HTML元素
                  label: item.classifyType === '1' ? '<img width="25" height="25" src=' + preUrl + item.fileName + ' alt=""/>' : item.lexplain,
                  state: item.state,
                  isHtmlName: true
                }
              });
              // 取消关键特性
              if (resData && resData.length > 0) {
                resData.unshift({
                  key: "keyFeature_",
                  label: this.$t('functional-analysis.property-modal.unflag-key-features'),
                  state: '0'
                });
              }
              _that.keyFeatureChildren = resData || [];
            } else {
              _that.$message.error(res.message, 1);
            }
          });
        } else {
          _that.$message.error(res.message, 1);
        }
      });
    },
    /******************************************* 右键菜单 End **************************************************/

    /******************************************* 父组件方法 Start **************************************************/
    /**
     * 监听快捷键
     * @param flag true、false
     */
    keyListenerChange(flag) {
      this.$emit("keyListenerChange", flag);
    },
    /**
     * 刷新顶部按钮
     */
    refreshBtnStatus() {
      this.$emit("refreshBtnStatus");
    },
    /**
     * 刷新移动节点标识状态
     */
    refreshMoveNodeFlag() {
      this.$emit("refreshMoveNodeFlag");
    },
    /**
     * 刷新左侧树
     */
    initLeftTree() {
      this.$emit("initLeftTree");
    },
    /**
     * 存储当前节点信息
     */
    setCheckedNode(node) {
      this.$emit("setCheckedNode", node, "rightTree");
    },
    /**
     * 取得当前节点的右键菜单项
     */
    getCurrentNodeMenus(node) {
      let data = {};
      this.$emit('getCurrentNodeMenus', node, "rightTree", val => {
        data = val;
      })
      return data;
    },
    /**
     * 设置：复制/剪切时，节点高亮
     */
    setHighLightCopyCutNode(copyCut) {
      this.$emit("setHighLightCopyCutNode", copyCut, "rightTree");
    },
    /**
     * 清除：复制/剪切时，节点高亮
     */
    clearHighLightCopyCutNode() {
      this.$emit("clearHighLightCopyCutNode", "rightTree");
    },
    /**
     * 恢复高亮复制节点,目的：允许一次复制多次粘贴
     */
    restoreHighLightCopyNode() {
      this.$emit("restoreHighLightCopyNode", "rightTree");
    },
    /**
     * 粘贴
     */
    paste() {
      this.$emit("paste", "rightTree");
    },
    /**
     * 删除节点
     */
    deleteNode(node) {
      this.$emit("deleteNode", node);
    },
    /**
     * 移动节点
     */
    moveNode(node, optType) {
      this.$emit("moveNode", node, optType);
    },
    /**
     * 转换节点
     */
    convertNode(node) {
      this.$emit("convertNode", node);
    },
    /**
     * 添加措施状态(当前措施、优化措施)
     * @param node 节点
     * @param label 内容
     * @param struTpeCode 节点类型CODE
     */
    addMeasure(node, label, struTpeCode) {
      this.$emit("addMeasure", node, label, struTpeCode, "rightTree");
    },
    /**
     * 添加措施组
     * @param node 节点
     */
    addGroup(node) {
      this.$emit("addGroup", node);
    },
    /**
     * 修改节点SOD
     * @param nodeId 节点ID
     * @param val sod值
     * @param sodFlag 1:S、2:O、3:D
     */
    updateNodeSOD(nodeId, val, sodFlag) {
      this.$emit("updateNodeSOD", nodeId, val, sodFlag);
    },
    /**
     * 修改节点潜在关键特性
     * @param node 节点
     * @param classify 特性标识
     */
    updateNodeClassify(node, classify) {
      this.$emit("updateNodeClassify", node, classify);
    },
    /**
     * 修改左侧treeData节点数据（名称）
     * @param node 节点
     */
    leftUpdateTreeDataNode(node) {
      this.$emit("leftUpdateTreeDataNode", node);
    },
    /******************************************* 父组件方法 End **************************************************/

    /******************************************* 子组件方法 Start **************************************************/
    /**
     * 关闭：功能网模态框
     */
    closeFunctionNetModal() {
      this.showFunctionNetModal = false;
      this.showFunctionNetEventListener = false;
    },
    /**
     * 关闭：失效网模态框
     */
    closeFaultNetModal() {
      this.showFaultNetModal = false;
      this.showFaultNetEventListener = false;
    },
    /**
     * 关闭：历史失效模态框
     */
    closeHistoryFaultModal() {
      this.showHistoryFaultModal = false;
    },
    /**
     * 关闭模态框
     */
    closeModal() {
      this.modalVisible = false;
    },
    /**
     * 点击附件图标
     */
    handleAnnexIconClick(id) {
      let _that = this;
      _that.clearHighLightCopyCutNode();
      let node = _that.initData.find(item => {
        return item.id === id;
      });
      if (node) {
        _that.checkedNode = node;
        _that.handlePropertyModal(node, "remarks");
        _that.modalVisible = true;
      }
    },
    /******************************************* 子组件方法 End **************************************************/

    /**
     * 清除：评审意见跳转储存id
     */
    cleanCommentJumpStruNode() {
      this.$store.dispatch("fmeaTree/set", {
        key: "rightParentStruIdFromComments",
        value: undefined
      });
      this.$store.dispatch("fmeaTree/set", {
        key: "rightStruIdFromComments",
        value: undefined
      });
      this.$store.dispatch("fmeaTree/set", {
        key: "commentsParentIds",
        value: undefined
      });
    },

    /**
     * 在区域禁用浏览器右键菜单
     */
    forbidRightClick() {
      document.getElementById("rightTree").oncontextmenu = function (e) {
        return false;
      };
    },
    /*******************************************ztree拖拽Start*************************/
    // 拖拽到目标节点上方
    canDragPrev(treeId, nodes, targetNode) {
      var treeObj = $.fn.zTree.getZTreeObj(treeId);
      if (!targetNode || !nodes) {
        return false;
      }
      // 判断选择节点是否是从当前树上选取的节点
      if (nodes[0].tId.indexOf(treeId) === -1) {
        return false;
      }
      // 功能/产品特性节点，只能拖拽功能/产品特性节点上方
      if ("0204".indexOf(nodes[0].struTypeCode) > -1) {
        if ("0204".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 要求只能拖拽到要求上方
      if ("05".indexOf(nodes[0].struTypeCode) > -1) {
        // 要求和失效可以相互换位置
        if ("0506".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
        // 如果要求拖拽目标节点是失效的话需要判断目标节点父级
        let targetParentNode = treeObj.getNodeByParam("id", targetNode.pid);
        if (targetParentNode && "02".indexOf(targetParentNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 失效只能拖拽到失效上方
      if ("06".indexOf(nodes[0].struTypeCode) > -1) {
        if ("0506".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 当前措施不允许拖拽
      if ("14".indexOf(nodes[0].struTypeCode) > -1) {
        return false;
      }
      // 优化措施只能拖拽到优化措施上方
      if ("07".indexOf(nodes[0].struTypeCode) > -1) {
        if ("07".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 措施组只能拖拽到措施组上方
      if ("08".indexOf(nodes[0].struTypeCode) > -1) {
        if ("08".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 预防和探测，只能拖拽预防和探测节点上方
      if ("0910".indexOf(nodes[0].struTypeCode) > -1) {
        if ("0910".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      return true;
    },
    // 拖拽到目标节点下方
    canDragNext(treeId, nodes, targetNode) {
      var treeObj = $.fn.zTree.getZTreeObj(treeId);
      if (!targetNode || !nodes) {
        return false;
      }
      // 判断选择节点是否是从当前树上选取的节点
      if (nodes[0].tId.indexOf(treeId) === -1) {
        return false;
      }
      // 功能/产品特性节点，只能拖拽功能/产品特性节点下方
      if ("0204".indexOf(nodes[0].struTypeCode) > -1) {
        if ("0204".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 要求只能拖拽到要求下方
      if ("05".indexOf(nodes[0].struTypeCode) > -1) {
        if ("0506".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
        // 如果要求拖拽目标节点是失效的话需要判断目标节点父级
        let targetParentNode = treeObj.getNodeByParam("id", targetNode.pid);
        if (targetParentNode && "02".indexOf(targetParentNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 失效只能拖拽到失效下方
      if ("06".indexOf(nodes[0].struTypeCode) > -1) {
        if ("0506".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 当前措施不允许拖拽
      if ("14".indexOf(nodes[0].struTypeCode) > -1) {
        return false;
      }
      // 优化措施只能拖拽到优化措施下方
      if ("07".indexOf(nodes[0].struTypeCode) > -1) {
        if ("0714".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 措施组只能拖拽到措施组下方
      if ("08".indexOf(nodes[0].struTypeCode) > -1) {
        if ("08".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 预防和探测，只能拖拽预防和探测节点下方
      if ("0910".indexOf(nodes[0].struTypeCode) > -1) {
        if ("0910".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      return true;
    },
    // 拖拽到目标节点里
    canDragInner(treeId, nodes, targetNode) {
      if (!targetNode || !nodes) {
        return false;
      }
      // 判断选择节点是否是从当前树上选取的节点
      if (nodes[0].tId.indexOf(treeId) === -1) {
        return false;
      }
      // 功能/产品特性节点，只能拖拽功能/产品特性节点里
      if ("0204".indexOf(nodes[0].struTypeCode) > -1) {
        return false;
      }
      // 要求只能拖拽到要求里
      if ("05".indexOf(nodes[0].struTypeCode) > -1) {
        if ("02".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 失效只能拖拽到失效里
      if ("06".indexOf(nodes[0].struTypeCode) > -1) {
        if ("020405".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 当前措施不允许拖拽
      if ("14".indexOf(nodes[0].struTypeCode) > -1) {
        return false;
      }
      // 优化措施只能拖拽到优化措施里
      if ("07".indexOf(nodes[0].struTypeCode) > -1) {
        if ("06".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 措施组只能拖拽到措施组里
      if ("08".indexOf(nodes[0].struTypeCode) > -1) {
        if ("07".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      // 预防和探测，只能拖拽预防和探测节点里
      if ("0910".indexOf(nodes[0].struTypeCode) > -1) {
        if ("08".indexOf(targetNode.struTypeCode) === -1) {
          return false;
        }
      }
      return true;
    },
    // 拖拽完成后的回调函数
    zTreeOnDrop(event, treeId, treeNodes, targetNode, moveType) {
      if (!targetNode) return false;
      var treeObj = $.fn.zTree.getZTreeObj(treeId);
      var nodes = treeObj.getNodes();
      let data = {};
      data.struId = targetNode.id;
      data.fmeaId = this.$store.getters.rfmeaId;
      data.source = treeNodes;
      data.target = targetNode;
      data.moveType = moveType;
      this.$api.dropNode(data).then((res) => {
        if (res.flag) {
          this.$message.success(res.message, 1);
          this.onAsyncSuccessSelectId = treeNodes[0].id;
          // 刷新变体数据
          this.$emit("cleanVariantSelect");
          // 刷新树
          this.initRightTree();
        } else {
          this.$message.error(res.message, 1);
        }
      }).catch((error) => {
        this.$message.error(error.response.data.message, 1);
      })
      nodes = undefined;
    },
    // 设置节点选中
    selectNode(treeId) {
      let treeObj = $.fn.zTree.getZTreeObj(treeId);
      let node = treeObj.getNodeByParam("id", this.onAsyncSuccessSelectId);
      if (node) {
        // 设置节点选中
        this.handleBeforeClick(treeId, node, 1);
        this.onAsyncSuccessSelectId = "";
      }
    },
    // 判断权限是否可移动
    canMove() {
      if (getUrlParam("enterState")) {
        return false;
      }
      return true;
    },
    /*******************************************ztree拖拽End*************************/
    // 粘贴回调方法设置目标选中节点id
    setPasteCompletedNodeId(id) {
      this.onAsyncSuccessSelectId = id;
    },
    /**
     * 功能/失效 ai推理
     */
    saveNodeAiInference(node, struTypeCode) {
      this.$emit("saveNodeAiInference", node, struTypeCode);
    },
    /**
     * 严重度(S) ai推理
     */
    saveSodAiInference(node, sodFlag) {
      this.$emit("saveSodAiInference", node, sodFlag);
    },
    /**
     * 预防/探测措施AI推理
     */
    saveMeasureiAiInference(node, struTypeCode, measureCode) {
      let nodeId = node.id;
      if (node.struTypeCode !== '06') measureCode = null;
      if (node.struTypeCode === '06' && node.children && node.children.length > 0) {
        let measureNodes = node.children.filter(item => item.struTypeCode === measureCode);
        if (measureNodes && measureNodes.length > 0) {
          measureNodes = measureNodes.sort((a, b) => a.leftNo - b.leftNo);
          nodeId = measureNodes[measureNodes.length - 1].id;
          measureCode = null;
        }
      }
      this.$emit("saveMeasureiAiInference", nodeId, struTypeCode, measureCode);
    },
  }
};

/**
 * 右侧树附件点击
 * @param id
 */
window.handleRAnnexIconClick = function (id) {
  handleRAnnexIconClick(id);
}
</script>
<style lang="less" scoped>

@import "~@/styles/zTree";

</style>
