<template>
  <div id="riskAnalysisNet" class="riskAnalysisNet" ref="riskAnalysisNet">
    <div>
      <div class="net-center beauty-Scroll pr">
        <a-spin
            :delay="delayTime"
            :spinning="treeLoading">
          <a-list v-show="isEmpty" :data-source="[]"/>
          <RiskAnalysisNet
              ref="riskAnalysisNet"
              v-if="riskAnalysisNetData && riskAnalysisNetData.length > 0"
              :netData="riskAnalysisNetData"
              :functionSwitch="functionSwitch"
              :structureSwitch="structureSwitch"
              :measureSwitch="measureSwitch"
              @clickNode="clickNode"
              @doubleClick="doubleClick"
              @keyup="keyup"
              @updateName="updateName"
              @rightClick="contextmenu"/>
        </a-spin>
      </div>
    </div>
    <div>
      <!-- 模态框 Start -->
      <DragModal
          :visible="modalVisible"
          :title="title"
          :width="1000"
          destroy-on-close
          @cancel="modalVisible = false"
          :footer="null">
        <!-- 预防措施 -->
        <AddPreventionMeasure
            v-if="actionName === 'addPreventionMeasure'"
            :tab="tab"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 探测措施 -->
        <AddProbeMeasure
            v-if="actionName === 'addProbeMeasure'"
            :tab="tab"
            :struTypeCode="struTypeCode"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 评审意见 -->
        <AddReviewComments
            v-if="actionName === 'addReviewComments'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"/>
        <!-- 优化措施合并 -->
        <MergeOptimizeMeasure
            v-if="actionName === 'mergeOptimizeMeasure'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 措施组合并 -->
        <MergeGroup
            v-if="actionName === 'mergeGroup'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 预防措施合并 -->
        <MergePreventionMeasure
            v-if="actionName === 'mergePreventionMeasure'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 探测措施合并 -->
        <MergeProbeMeasure
            v-if="actionName === 'mergeProbeMeasure'"
            :checkedNode="checkedNode"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 失效属性 -->
        <PropertyFault
            v-if="actionName === 'propertyFault'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 当前措施属性 -->
        <PropertyCurrentMeasure
            v-if="actionName === 'propertyCurrentMeasure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 优化措施属性 -->
        <PropertyOptimizeMeasure
            v-if="actionName === 'propertyOptimizeMeasure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 措施组属性 -->
        <PropertyGroup
            v-if="actionName === 'propertyGroup'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 预防措施属性 -->
        <PropertyPreventionMeasure
            v-if="actionName === 'propertyPreventionMeasure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
        <!-- 探测措施属性 -->
        <PropertyProbeMeasure
            v-if="actionName === 'propertyProbeMeasure'"
            :checkedNode="checkedNode"
            :tabKey="tabKey"
            @closeModal="closeModal"
            @initRiskNet="initRiskNet"/>
      </DragModal>
      <!-- 模态框 End -->
      <!-- 失效网 -->
      <FaultNetModal
          ref="faultNet"
          :showFaultNetEventListener="showFaultNetEventListener"
          :showFaultNetModal="showFaultNetModal"
          @closeFaultNetModal="closeFaultNetModal"
          @initRiskNet="initRiskNet"/>
      <!-- 管理历史失效 -->
      <HistoryFaultModal
          ref="historyFault"
          :showHistoryFaultModal="showHistoryFaultModal"
          @closeHistoryFaultModal="closeHistoryFaultModal"
          @initRiskNet="initRiskNet"/>
    </div>
  </div>
</template>
<script>

import {addClass, toggleClass} from "@/utils/index";
import DragModal from "@/components/DragModal";
import RiskAnalysisNet from "./components/RiskAnalysisNet";
import AddPreventionMeasure from "./components/AddModal/AddPreventionMeasure.vue";
import AddProbeMeasure from "./components/AddModal/AddProbeMeasure.vue";
import AddReviewComments from "./components/AddModal/AddReviewComments.vue";
import MergeOptimizeMeasure from "./components/MergeModal/MergeOptimizeMeasure.vue";
import MergeGroup from "./components/MergeModal/MergeGroup.vue";
import MergePreventionMeasure from "./components/MergeModal/MergePreventionMeasure.vue";
import MergeProbeMeasure from "./components/MergeModal/MergeProbeMeasure.vue";
import {cleanRiskNetData, getTopStructDeep, showCurConvertBtn, showMergeBtn,} from "@/utils/riskTree";
import PropertyFault from "./components/PropertyModal/PropertyFault";
import PropertyCurrentMeasure from "./components/PropertyModal/PropertyCurrentMeasure";
import PropertyOptimizeMeasure from "./components/PropertyModal/PropertyOptimizeMeasure";
import PropertyGroup from "./components/PropertyModal/PropertyGroup";
import PropertyPreventionMeasure from "./components/PropertyModal/PropertyPreventionMeasure";
import PropertyProbeMeasure from "./components/PropertyModal/PropertyProbeMeasure";
import FaultNetModal from "./components/FaultNetModal/FaultNetModal";
import HistoryFaultModal from "./components/HistoryFaultModal/index";
import html2canvas from 'html2canvas';

export default {
  name: "Net",
  components: {
    DragModal,
    RiskAnalysisNet,
    AddPreventionMeasure,
    AddProbeMeasure,
    AddReviewComments,
    MergeOptimizeMeasure,
    MergeGroup,
    MergePreventionMeasure,
    MergeProbeMeasure,
    PropertyFault,
    PropertyCurrentMeasure,
    PropertyOptimizeMeasure,
    PropertyGroup,
    PropertyPreventionMeasure,
    PropertyProbeMeasure,
    FaultNetModal,
    HistoryFaultModal,
  },
  props: {
    functionSwitch: {
      type: Boolean,
      default: undefined
    },
    structureSwitch: {
      type: Boolean,
      default: undefined
    },
    measureSwitch: {
      type: Boolean,
      default: undefined
    },
    versionDiffCloseFlag: {
      type: Boolean,
      default: false
    },
    versionLibraryDiffCloseFlag: {
      type: Boolean,
      default: false
    }
  },
  watch: {
    // 监听差异处理弹框标志
    versionDiffCloseFlag(v) {
      if (v) {
        this.initRiskNet();
      }
    },
    // 监听知识库差异处理弹框标志
    versionLibraryDiffCloseFlag(v) {
      if (v) {
        this.initRiskNet();
      }
    }
  },
  data() {
    return {
      sodMap: {}, // 判断sod后统一放入该集合
      fssMap: {}, // 严重度
      fsoMap: {}, // 发生度
      fsdMap: {}, // 探测度
      /** 风险分析检索条件 */
      queryParameter: {
        fmeaId: this.$store.getters.rfmeaId,
        name: "",
        parameterKey: "",
        parameterSymbol: "",
        parameterValue: "",
      },
      /** 风险分析数据 */
      riskAnalysisNetData: [],
      /** 模态框状态 */
      modalVisible: false,
      /** 模态框唯一Key */
      actionName: "",
      /** 模态框标题 */
      title: "",
      /** 模态框，tab名称 */
      tab: "",
      /** 节点类型CODE */
      struTypeCode: "",
      /** 选中节点 */
      checkedNode: "",
      /** tree加载中状态 */
      treeLoading: false,
      /** 延迟显示加载效果的时间（防止闪烁）*/
      delayTime: 300,
      /** 是否显示空状态 */
      isEmpty: true,
      /** 删除弹出框 */
      deleteModal: undefined,
      /** 潜在关键特性子集 */
      keyFeatureChildren: [],
      /** 模态框，选项卡Key */
      tabKey: "",
      /** 失效网模态框开关 */
      showFaultNetEventListener: false,
      /** 失效网模态框开关 */
      showFaultNetModal: false,
      /** 历史失效网模态框开关 */
      showHistoryFaultModal: false,
    };
  },
  created() {
    this.forbidRightClick();
  },
  mounted() {
    window.addEventListener("keydown", this.keyCodeForEvent);
    this.$once('hook:beforeDestroy', () => {
      window.removeEventListener("keydown", this.keyCodeForEvent);
    });
    this.initKeyFeature();
  },
  methods: {
    /**
     * 刷新风险分析
     */
    initRiskNet() {
      let _that = this;
      _that.treeLoading = true;
      // 取的左侧选中节点
      let zTree = jQuery.fn.zTree.getZTreeObj('leftTree');
      let selectedNodes = zTree.getSelectedNodes();
      _that.queryParameter.faultId = selectedNodes[0].id;
      _that.$api.getRiskFailNet(_that.queryParameter).then((res) => {
        if (res.flag) {
          let resData = res.data;
          if (resData) cleanRiskNetData([resData]);
          _that.isEmpty = !resData;
          _that.riskAnalysisNetData = resData ? [resData] : [];
        } else {
          _that.$message.error(res.message);
        }
      }).catch((error) => {
        _that.$message.error(error.response.data.message, 1);
      }).finally(() => {
        _that.treeLoading = false;
      });
    },
    /**
     * 右键菜单
     * @param e
     * @param node 节点
     */
    contextmenu(e, node) {
      this.clickNode(node);
      // 获取右键菜单项
      let bthMenuBtn = this.getMenuBtn(node);
      // 处理右键菜单
      this.handleContextMenu(node, bthMenuBtn);
    },
    /**
     * 获取右键菜单项
     * @param checkedNode 选中节点
     */
    getMenuBtn(checkedNode) {
      // 取得当前节点的右键菜单项
      let cNodeMenus = this.getCurrentNodeMenus(checkedNode);
      let menuBtn = {};
      this.$store.getters.rightTreeMenus.map((item) => {
        if (cNodeMenus.indexOf(item.key) !== -1) {
          switch (item.key) {
            case "merge": // 合并
              if (showMergeBtn(this.riskAnalysisNetData, checkedNode) === 1) return false;
              break;
            case "convert": // 转换
              if (showCurConvertBtn(this.riskAnalysisNetData, checkedNode) === 1) return false;
              item.label = this.getConvertMenuLabel(checkedNode);
              break;
            case "keyFeature": // 潜在关键特性
              if (this.keyFeatureChildren.length === 0) return false;
              item.children = this.keyFeatureChildren;
              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;
            default:
              break;
          }
          // 追加菜单项
          let menuObj = {name: this.$t('' + item.label + ''), icon: "fas iconfont " + item.icon};
          let children = {};
          if (item.children && item.children.length > 0) {
            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;
    },
    // 获取评分标准 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 节点
     * @param items 菜单项
     */
    handleContextMenu(node, items) {
      let _that = this;
      _that.getSeverityToolTip(); // 获取评分标准 SOD
      jQuery.contextMenu('destroy'); // 销毁所有菜单。
      jQuery.contextMenu({
        selector: '#' + node.key + "Name" + node.id,
        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();
      });

      // 鼠标离开后，移除tooltip元素
      jQuery(document).on('mouseout', '.context-menu-item, .tooltip', function() {
        jQuery('.tooltip').remove();
      });
    },
    /**
     * 取得当前节点的右键菜单项
     * @param checkNode 选中节点
     */
    getCurrentNodeMenus(checkNode) {
      let nodeTypeDict = this.$store.getters.nodeTypeDict.riskAnalysis.filter((item) => {
        return item.key === checkNode.struTypeCode;
      })[0];
      if (nodeTypeDict) { // 无右键菜单时undefined
        // 1：只读，2：编制
        if (this.$api.isLook === '1') return nodeTypeDict.rightMenuReadOnly;
        // 编制
        return nodeTypeDict.rightMenu;
      } else {
        return null;
      }
    },
    /**
     * 处理合并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;
        }
      }
    },
    /**
     * 取得转换菜单项：名称
     * @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
            && converts[i].key === node.curOptTypeCode) {
          label = converts[i].label;
          break;
        }
        if (converts[i].key === node.struTypeCode) {
          label = converts[i].label;
          break;
        }
      }
      return label;
    },
    /**
     * 初始化潜在关键特性
     */
    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
                }
              });
              _that.keyFeatureChildren = resData || [];
            } else {
              _that.$message.error(res.message, 1);
            }
          });
        } else {
          _that.$message.error(res.message, 1);
        }
      });
    },
    /**
     * 是否存在当前措施
     * @param node 节点
     */
    isExistCurrentMeasure(node) {
      let curNode = node.measureChildren && node.measureChildren.filter(item => item.struTypeCode === '14')[0];
      return !!curNode;
    },
    /**
     * 展示当前/优化 预防控制、探测控制
     * @param node 节点
     * @param menuKey 菜单标识
     */
    showCurOptMeasureBtn(node, menuKey) {
      if (node.struTypeCode === '08') {
        if (node.curOptTypeCode === '1408'
            && this.$store.getters.nodeTypeDict.curGroup.indexOf(menuKey) !== -1) {
          return true;
        }
        return node.curOptTypeCode === '0708'
            && this.$store.getters.nodeTypeDict.optGroup.indexOf(menuKey) !== -1;
      }
      return true;
    },
    /**
     * 菜单事件
     */
    menuAction(actionInfo) {
      let checkedNode = this.$store.getters.lastCheckedNode;
      this.checkedNode = checkedNode;
      this.actionName = actionInfo.key;
      switch (actionInfo.key) {
        case "showFaultNet": // 显示失效网
          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.name
          };
          this.$refs.faultNet.initLeftTree();
          this.$refs.faultNet.title = checkedNode.name;
          this.$refs.faultNet.structureSwitch = true;
          this.$refs.faultNet.functionSwitch = true;
          this.showFaultNetEventListener = true;
          this.showFaultNetModal = true;
          this.$refs.faultNet.forbiddenRightClick();
          break;
        case "joinHistoryFault": // 关联历史失效案例库
          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.updateNodeSOD(checkedNode.id, actionInfo.label, 1);
          break;
        case "addOccurrence": // 发生度(O)
          this.updateNodeSOD(checkedNode.id, actionInfo.label, 2);
          break;
        case "addDetection": // 探测度(D)
          this.updateNodeSOD(checkedNode.id, actionInfo.label, 3);
          break;
        case "keyFeature": // 潜在关键特性
          if (!actionInfo.classify) break;
          this.updateNodeClassify(checkedNode, actionInfo.classify);
          break;
        case "addCurrentMeasure": // 当前措施
          this.addMeasure(checkedNode, this.$t('risk-analysis.add-modal.append.current.measure'), '14');
          break;
        case "addGroup": // 措施组
          this.addGroup(checkedNode);
          break;
        case "addCurrentPreventionMeasure": // 当前预防控制
          this.actionName = "addPreventionMeasure"; // 使用预防措施组件
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addCurrentProbeMeasure": // 当前探测控制
          this.actionName = "addProbeMeasure"; // 使用探测措施组件
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addOptimizeMeasure": // 优化措施
          this.addMeasure(checkedNode, this.$t('risk-analysis.add-modal.append.optimize.measure'), '07');
          break;
        case "addOptimizePreventionMeasure": // 优化预防控制
          this.actionName = "addPreventionMeasure"; // 使用预防措施组件
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "addOptimizeProbeMeasure": // 优化探测控制
          this.actionName = "addProbeMeasure"; // 使用探测措施组件
          this.handleAddModal(checkedNode, actionInfo.key);
          this.modalVisible = true;
          break;
        case "merge": // 合并
          this.handleMergeModal(checkedNode);
          this.modalVisible = true;
          break;
        case "delete": // 删除
          this.deleteNode(checkedNode);
          break;
        case "convert": // 转换
          this.convertNode(checkedNode);
          break;
        case "property": // 属性
          this.handlePropertyModal(checkedNode);
          this.modalVisible = true;
          break;
        case "addReviewComments": // 添加评审意见
          this.handleReviewCommentsModal(checkedNode);
          this.modalVisible = true;
          break;
      }
    },
    /**
     * 关闭：历史失效模态框
     */
    closeHistoryFaultModal() {
      this.showHistoryFaultModal = false;
    },
    /**
     * 关闭：失效网模态框
     */
    closeFaultNetModal() {
      this.showFaultNetModal = false;
      this.showFaultNetEventListener = false;
    },
    /**
     * 修改节点潜在关键特性
     * @param node 节点
     * @param classify 特性标识
     */
    updateNodeClassify(node, classify) {
      this.$emit("updateNodeClassify", node, classify);
    },
    /**
     * 处理属性Modal逻辑
     * @param node 节点
     * @param tabKey 选项卡Key
     */
    handlePropertyModal(node, tabKey = "") {
      // 节点为当前或者优化措施
      let name = "14,07".indexOf(node.struTypeCode) !== -1 ? "" : node.name;
      // 属性Modal业务
      let merges = this.$store.getters.nodeTypeDict.propertyModals;
      let merge = {};
      // 循环遍历 merges 数组
      for (let i = 0; i < merges.length; i++) {
        // 节点为探测或者预防措施
        if ("09,10".indexOf(node.struTypeCode) !== -1) {
          // 当前探测/预防措施 或者 优化探测/预防措施
          if (merges[i].key === node.curOptTypeCode) {
            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;
    },
    /**
     * 处理添加
     * @param node 节点
     * @param menuKey 菜单标识
     */
    handleAddModal(node, menuKey) {
      let name = node.name;
      let adds = this.$store.getters.nodeTypeDict.addModals;
      for (let i = 0, len = adds.length; i < len; i++) {
        if (adds[i].menuKey === menuKey) {
          this.title = this.$t('' + adds[i].title + '') + name;
          this.struTypeCode = adds[i].struTypeCode;
          this.tab = this.$t('' + adds[i].label + '');
          return;
        }
      }
    },
    /**
     * 处理评审意见Modal逻辑
     * @param node 节点
     */
    handleReviewCommentsModal(node) {
      let name = "14,07".indexOf(node.struTypeCode) !== -1 ? "" : node.name;
      let reviewComments = this.$store.getters.nodeTypeDict.reviewCommentsModals;
      for (let i = 0, len = reviewComments.length; i < len; i++) {
        if ("09,10".indexOf(node.struTypeCode) !== -1
            && reviewComments[i].key === node.curOptTypeCode) {
          this.title = this.$t('' + reviewComments[i].title + '') + name;
          return;
        }
        if (reviewComments[i].key === node.struTypeCode) {
          this.title = this.$t('' + reviewComments[i].title + '') + name;
          return;
        }
      }
    },
    /**
     * 转换节点
     */
    convertNode(node) {
      let _that = this;
      if ('07,14'.indexOf(node.struTypeCode) !== -1) { // 措施状态（当前/优化）
        _that.$api.convertMeasure({
          fmeaId: _that.$store.getters.rfmeaId,
          struId: node.id,
          parentStruId: node.pid,
          measureState: node.struTypeCode,
        }).then((res) => {
          if (res.flag) {
            _that.$message.success(res.message, 1);
            _that.initRiskNet();
          } else {
            _that.$message.error(res.message, 1);
          }
        }).catch((error) => {
          _that.$message.error(error.response.data.message, 1);
        });
      } else {
        _that.$api.convertNode({
          fmeaId: _that.$store.getters.rfmeaId,
          struId: node.id
        }).then((res) => {
          if (res.flag) {
            _that.$message.success(res.message, 1);
            _that.initRiskNet();
          } else {
            _that.$message.error(res.message, 1);
          }
        }).catch((error) => {
          _that.$message.error(error.response.data.message, 1);
        });
      }
    },
    /**
     * 修改节点SOD值
     * @param nodeId 节点ID
     * @param val sod值
     * @param sodFlag 1:S、2:O、3:D
     */
    updateNodeSOD(nodeId, val, sodFlag) {
      let _that = this;
      _that.$api.updateNodeSOD({
        fmeaId: _that.$store.getters.fmeaId,
        rfmeaId: _that.$store.getters.rfmeaId,
        struId: nodeId,
        levelId: val,
        sodFlag: sodFlag,
      }).then((res) => {
        if (res.flag) {
          _that.$message.success(res.message, 1);
          _that.initRiskNet();
        } else {
          _that.$message.error(res.message, 1);
        }
      }).catch((error) => {
        _that.$message.error(error.response.data.message, 1);
      });
    },
    /**
     * 添加措施状态
     * @param node 节点
     * @param label 内容
     * @param struTypeCode 14：当前措施，07：优化措施
     */
    addMeasure(node, label, struTypeCode) {
      let content = this.$t('global-message.remind.append.measure', [label]);
      let _that = this;
      _that.$confirm({
        title: this.$t('global-message.remind'),
        content: content,
        icon: "aaoopqa", //图标，不想用就随便写一个
        okText: this.$t('global-btn.ok'),
        cancelText: this.$t('global-btn.cancel'),
        onOk() {
          _that.$api.saveMeasure({
            fmeaId: _that.$store.getters.rfmeaId,
            struId: node.id,
            struTypeCode: struTypeCode,
          }).then((res) => {
            if (res.flag) {
              _that.$message.success(res.message, 1);
              _that.initRiskNet();
            } else {
              _that.$message.error(res.message, 1);
            }
          }).catch((error) => {
            _that.$message.error(error.response.data.message, 1);
          })
        },
        onCancel() {
        }
      });
    },
    /**
     * 添加措施组
     * @param node 节点
     */
    addGroup(node) {
      let content = this.$t('global-message.remind.append.group');
      let _that = this;
      _that.$confirm({
        title: this.$t('global-message.remind'),
        content: content,
        icon: "aaoopqa", //图标，不想用就随便写一个
        okText: this.$t('global-btn.ok'),
        cancelText: this.$t('global-btn.cancel'),
        onOk() {
          _that.$api.saveGroup({
            fmeaId: _that.$store.getters.rfmeaId,
            struId: node.id,
          }).then((res) => {
            if (res.flag) {
              _that.$message.success(res.message, 1);
              _that.initRiskNet();
            } else {
              _that.$message.error(res.message, 1);
            }
          }).catch((error) => {
            _that.$message.error(error.response.data.message, 1);
          })
        },
        onCancel() {
        }
      });
    },
    /**
     * 删除节点
     * @param node 节点
     */
    deleteNode(node) {
      let _that = this;
      // 确保唯一
      if (_that.deleteModal) {
        // 销毁
        _that.deleteModal.destroy();
      }
      let deleteContent = undefined;
      let deleteNumber = undefined;
      let data = {
        rfmeaId: _that.$store.getters.rfmeaId,
        struId: node.id
      };
      // 发送请求，统计删除的节点数量
      _that.$api.getDeleteNodeNumber(data).then(res => {
        if (res.flag) {
          deleteNumber = res.data;
          // 根据删除的节点类型，设置不同的删除提示语
          switch (node.struTypeCode) {
            //  优化措施
            case '07':
              deleteContent = _that.$t('global-message.warn.optimizationes.delete', [deleteNumber]);
              break;
            //  当前措施
            case '14':
              deleteContent = _that.$t('global-message.warn.current.measures.delete', [deleteNumber]);
              break;
            //  措施组
            case '08':
              deleteContent = _that.$t('global-message.warn.action.group.delete', [deleteNumber]);
              break;
            //  预防
            case '09':
              deleteContent = _that.$t('global-message.warn.mensura.preventiva.delete', [deleteNumber]);
              break;
            //  探测
            case '10':
              deleteContent = _that.$t('global-message.warn.detection.measures.delete', [deleteNumber]);
              break;
            default:
              break;
          }
          _that.deleteModal = _that.$confirm({
            title: _that.$t('global-message.warn'),
            content: deleteContent,
            okText: _that.$t('global-btn.ok'),
            cancelText: _that.$t('global-btn.cancel'),
            onCancel() {},
            onOk() {
              _that.$api.deleteNode({
                fmeaId: _that.$store.getters.rfmeaId,
                struId: node.id
              }).then((res) => {
                if (res.flag) {
                  _that.$message.success(res.message, 1);
                  _that.initRiskNet();
                } else {
                  _that.$message.error(res.message, 1);
                }
              }).catch((error) => {
                _that.$message.error(error.response.data.message, 1);
              })
            },
          });
        }
      });
    },
    /**
     * 点击节点
     * @param node 节点
     */
    clickNode(node) {
      this.setHighNode(node);
      this.setHighLable(node);
      this.setCheckedNode(node);
    },
    /**
     * 选中节点时，存储当前节点信息
     * @param node 节点
     */
    setCheckedNode(node) {
      this.$store.dispatch("fmeaTree/set", {
        key: "lastCheckedNode",
        value: node
      });
    },
    /**
     * 设置高亮节点
     * @param node 节点
     */
    setHighNode(node) {
      let arr = document.getElementsByClassName("node-selected");
      // 清除其他高亮节点
      if (arr[0]) arr[0].classList.remove("node-selected");
      addClass(
          document.getElementById(node.key + node.id),
          "node-selected"
      );
    },
    /**
     * 设置表格高亮
     * @param node
     */
    setHighLable(node) {
      let arr = document.getElementsByClassName("label-selected");
      //清除其他高亮节点
      if (arr[0])  arr[0].classList.remove("label-selected");
      let parentNode = document.getElementById(node.key + node.id).parentNode;
      for (let i = 0; i < 6; i++) {
        if (parentNode.id.indexOf('riskAnalysis') != -1 ){
          addClass(parentNode, "label-selected");
          break;
        }
        parentNode=  parentNode.parentNode;
      }
    },
    /**
     * 双击节点
     * @param node 节点
     */
    doubleClick(node) {
      if (this.$api.isLook === '1') return;
      if ("14,07".indexOf(node.struTypeCode) !== -1) return false;
      this.ecsFlag = false;
      let nodeName = document.getElementById(node.key + "Name" + node.id);
      let nodeInput = document.getElementById(node.key + "Input" + node.id);
      nodeInput.value = node.name;
      toggleClass(nodeName, "hide");
      toggleClass(nodeInput, "hide");
      setTimeout(() => {
        nodeInput.focus();
        // nodeInput.select();
      }, 100);
      event.stopPropagation();
      this.setRiskAnalysisSwitch(true);
    },
    /**
     * 键盘松开事件
     * @param e event对象
     * @param node 节点
     */
    keyup(e, node) {
      if (e.keyCode === 13) { // Enter
        document.getElementById(node.key + "Input" + node.id).blur();
        this.setRiskAnalysisSwitch(undefined);
      } else if (e.keyCode === 27) { // ESC
        this.ecsFlag = true;
        let nodeName = document.getElementById(node.key + "Name" + node.id);
        let nodeInput = document.getElementById(node.key + "Input" + node.id);
        toggleClass(nodeName, "hide");
        toggleClass(nodeInput, "hide");
        this.keyListenerChange(false);
        this.setRiskAnalysisSwitch(undefined);
      }
    },
    /**
     * 修改节点名称
     * @param node 节点
     */
    updateName(node) {
      let _that = this;
      if (_that.ecsFlag) return;
      let nodeName = document.getElementById(node.key + "Name" + node.id);
      let nodeInput = document.getElementById(node.key + "Input" + node.id);
      let newName = nodeInput.value;
      // input框值为空、new与old名称一样时，不调接口
      if (!newName || newName === node.name) {
        toggleClass(nodeName, "hide");
        toggleClass(nodeInput, "hide");
        _that.setRiskAnalysisSwitch(undefined);
        _that.keyListenerChange(false);
        return;
      }
      //调接口改变值
      _that.$api.updateNodeName({
        fmeaId: _that.$store.getters.rfmeaId,
        struId: node.id,
        struName: newName,
      }).then((res) => {
        if (res.flag) {
          _that.$message.success(res.message, 1);
          node.name = newName;
          _that.updateRiskNetDataNode(_that.riskAnalysisNetData, node);
        } else {
          _that.$message.error(res.message, 1);
        }
      }).catch((error) => {
        _that.$message.error(error.response.data.message);
      }).finally(() => {
        toggleClass(nodeName, "hide");
        toggleClass(nodeInput, "hide");
        _that.setRiskAnalysisSwitch(undefined);
        _that.keyListenerChange(false);
      });
    },
    /**
     * 修改风险数据节点（名称）
     * @param nodes 节点数组
     * @param targetNode 目标节点
     */
    updateRiskNetDataNode(nodes, targetNode) {
      for (let i = 0, len = nodes.length; i < len; i++) {
        if (nodes[i].id === targetNode.id) {
          nodes[i].name = targetNode.name;
        }
        if (nodes[i].children && nodes[i].children.length > 0) {
          this.updateRiskNetDataNode(nodes[i].children, targetNode);
        }
        if (nodes[i].measureChildren && nodes[i].measureChildren.length > 0) {
          this.updateRiskNetDataNode(nodes[i].measureChildren, targetNode);
        }
        if (nodes[i].structureParent) {
          this.updateRiskNetDataNode([nodes[i].structureParent], targetNode);
        }
        if (nodes[i].functionParent) {
          this.updateRiskNetDataNode([nodes[i].functionParent], targetNode);
        }
        if (nodes[i].requireParent) {
          this.updateRiskNetDataNode([nodes[i].requireParent], targetNode);
        }
      }
    },
    /**
     * 默认值为undefined，当双击改名时，移动失效，改名后移动继续生效
     * @param val
     */
    setRiskAnalysisSwitch(val) {
      this.$store.dispatch("fmeaTree/set", {
        key: "riskAnalysisSwitch",
        value: val
      });
    },
    /**
     * 监听键盘，快捷键
     */
    keyListenerChange(v) {
      if (v) {
        window.removeEventListener("keydown", this.keyCodeForEvent);
      } else {
        window.addEventListener("keydown", this.keyCodeForEvent);
      }
    },
    /**
     * 监听键盘，触发事件
     */
    keyCodeForEvent(e) {
      // 选中节点
      let checkedNode = this.$store.getters.lastCheckedNode;
      if (!checkedNode) return;
      // 取得左右侧菜单信息
      let lrTreeMenus = this.$store.getters.rightTreeMenus;
      // 当前节点菜单项
      let cNodeMenus = this.getCurrentNodeMenus(checkedNode)
      let actionInfo;
      switch (e.keyCode) {
        case 71: // 当前预防控制(Ctrl+G)
          if (!e.ctrlKey) return false;
          actionInfo = this.getNodeActionInfo(lrTreeMenus, cNodeMenus, "addCurrentPreventionMeasure");
          if (actionInfo) this.menuAction(actionInfo);
          break;
        case 66: // 当前探测控制(Ctrl+B)
          if (!e.ctrlKey) return false;
          actionInfo = this.getNodeActionInfo(lrTreeMenus, cNodeMenus, "addCurrentProbeMeasure");
          if (actionInfo) this.menuAction(actionInfo);
          break;
        case 77: // 合并(Alt+M)
          if (!e.altKey) return false;
          if (checkedNode.deep === 1) return false; // 根节点不能合并
          else if (showMergeBtn(lrTree.treeData, checkedNode) === 1) return false;
          actionInfo = this.getNodeActionInfo(lrTreeMenus, cNodeMenus, "merge");
          if (actionInfo) this.menuAction(actionInfo);
          break;
        case 46: // Delete
          if (checkedNode.deep === 1) return false; // 根节点不能删除
          actionInfo = this.getNodeActionInfo(lrTreeMenus, cNodeMenus, "delete");
          if (actionInfo) this.menuAction(actionInfo);
          break;
        case 78: // 评审意见(Shift+N)
          if (!e.shiftKey) return false;
          actionInfo = this.getNodeActionInfo(lrTreeMenus, cNodeMenus, "addReviewComments");
          if (actionInfo) this.menuAction(actionInfo);
          break;
        default:
          break;
      }
    },
    /**
     * 取得节点对应的菜单信息
     * @param lrTreeMenus 左右树总菜单
     * @param nodeMens 该节点菜单
     * @param menuKey 菜单标识
     */
    getNodeActionInfo(lrTreeMenus, nodeMens, menuKey) {
      let actionInfo;
      if (nodeMens.indexOf(menuKey) === -1) return;
      lrTreeMenus.forEach((item) => {
        if (item.key === menuKey) actionInfo = item;
      });
      return actionInfo;
    },
    /**
     * 关闭模态框
     */
    closeModal() {
      this.modalVisible = false;
    },
    /**
     * 在区域禁用浏览器右键菜单
     */
    forbidRightClick() {
      document.body.oncontextmenu = function () {
        return false;
      };
    },
    /**
     * 导出图片
     */
    exportImage() {
      // 获取画布元素
      let element = this.$refs.riskAnalysisNet.getNetElement();
      // 获取高亮的元素
      let nodeList = element.querySelectorAll('.highLightNode');
      // 删除高亮背景色
      if (nodeList && nodeList.length > 0) {
        nodeList.forEach(data => {
          data.classList.remove('highLightNode');
        });
      }
      // 获取类名为'htree'的ul元素的宽度，除目标节点外的所有子节点总长度
      var children = document.querySelector('ul.htree');
      var childrenWidth = children ? children.offsetWidth : 0;
      // 使用html2canvas将元素转换为canvas
      html2canvas(element,
        {
          // 设置canvas的窗口高度为浏览器窗口高度 / 2
          windowHeight: $(window).height() / 2,
          // 设置canvas的窗口宽度为目标元素宽度（300）加上childrenWidth
          windowWidth: 500 + childrenWidth
        }).then(canvas => {
          // 将canvas转换为图片URL
          const imgData = canvas.toDataURL('image/png');
          // 创建一个隐藏的链接元素
          const link = document.createElement('a');
          link.href = imgData;
          link.download = 'riskAnalysis.png';
          link.style.display = 'none'; // 隐藏链接
          // 将链接添加到DOM中
          document.body.appendChild(link);
          // 触发点击事件
          link.click();
          // 移除链接
          document.body.removeChild(link);
        });
      // 恢复高亮背景色
      if (nodeList && nodeList.length > 0) {
        nodeList.forEach(data => {
          data.classList.add('highLightNode');
        });
      }
    }
  },
  // 销毁
  destroyed() {
    this.$store.dispatch("fmeaTree/clear");
  }
};
</script>
<style lang="scss">
.funcNetDialog {
  .a-modal__body {
    padding: 0 !important;
  }
}
</style>
<style lang="scss" scoped>

.contextmenu {
  width: 200px;
  background: #FFF;
  border: 1px solid #bebebe;
  border-radius: 0.5em;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
  display: inline-block;
  font-family: inherit;
  font-size: inherit;
  list-style-type: none;
  max-width: 16em;
  min-width: 8em;
  position: absolute;

  ul {
    margin-bottom: 0;
  }

  li:hover {
    background-color: #2980B9;
    color: #FFF;
    cursor: pointer;
    border-radius: 0.5em !important;
  }

  //li:hover:first-child {
  //  border-radius: 0.5em 0.5em 0 0 !important;
  //}
  //
  //li:hover:last-child {
  //  border-radius: 0 0 0.5em 0.5em !important;
  //}

  a {
    display: block;
    //font-weight: 700;
    line-height: 24px;
    padding: 2px 12px;

    .rightIcon {
      float: right !important;
    }
  }

  .subMenu {
    width: 80px;
    background: #FFF;
    border: 1px solid #bebebe;
    border-radius: 0.5em;
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
    display: inline-block;
    font-family: inherit;
    font-size: inherit;
    list-style-type: none;
    position: absolute;
    color: #666;

    a {
      text-align: center;
    }
  }
}

</style>
<style lang="scss">
</style>

