<template>
  <div>
    <a-form class="ml10" layout="vertical">
      <a-row :gutter="24">
        <a-col :span="22" style="padding-left: 2px; padding-right: 0px;">
          <a-form-item>
            <a-input v-model="name" allowClear :placeholder="$t('functional-analysis.add-modal.please-enter-name')" />
          </a-form-item>
        </a-col>
        <a-col :span="2">
          <a-form-item>
            <a-button style="float:right" type="primary" @click="search">
              {{ $t('global-btn.search') }}
            </a-button>
          </a-form-item>
        </a-col>
      </a-row>
      <a-row>
        <a-form-item>
          <a-radio-group name="selectType" @change="radioChange" :default-value="1">
            <a-radio :value="1">
              {{ $t('functional-analysis.add-modal.all-nodes') }}
            </a-radio>
            <a-radio :value="2">
              {{ $t('functional-analysis.add-modal.only-current-node') }}
            </a-radio>
          </a-radio-group>
        </a-form-item>
      </a-row>
    </a-form>
    <div class="treeContent">
      <div class="treeDiv">
        <!--Tree Start-->
        <a-spin :tip="spinTip" :delay="delayTime" :spinning="treeLoading" v-for="(item, index) in treeDatas">
          <span style="margin-left: 9px; color: #ccc" :title="parentNodesName[index]">{{ parentNodesName[index] }}</span>
          <a-tree v-if="item && item.length > 0" key="tree" :tree-data="item" :selected-keys="[]" :blockNode="true"
            :replaceFields="replaceFields" :expandedKeys="expandedKeys" :autoExpandParent="autoExpandParent"
            @expand="expand" @select="nodeSelect" @setCheckedNode="setCheckedNode" @setHighLightNode="setHighLightNode">
            <template slot="treeDataSlot" slot-scope="node">
              <a :id="'treeNode' + node.id">
                <span>{{ "\xa0" }}</span>
                <i v-if="getNodeIcon(node)" :class="getNodeIcon(node)"/>
                <span :title="node.name" :class="getNodeClass(node)">
                  {{ node.name }}
                </span>
              </a>
            </template>
          </a-tree>
        </a-spin>
        <div class="noData" v-if="chartsShow">
          {{ $t('functional-analysis.no-node') }}
        </div>
        <!--Tree End-->
    </div>
      <a-pagination v-if="pageShow" class="treeTurnPages" :current="current" :total="total" @change="onTurnPages" />
    </div>
  </div>
</template>

<script>

import { addClass, removeClass } from "@/utils/index";
import { i18nRender } from '@/locales/index'

export default {
  name: "AddDFMEAKnowledgeBase",
  props: {
    struTypeCode: {
      default: '',
      type: String
    },
    struId: {
      default: '',
      type: String
    }
  },
  data() {
    return {
      name: '',
      /** 搜索名称 */
      searchName: '',
      replaceFields: { key: "id", title: "name" },
      current: 1,
      total: 0,
      /** tree数据 */
      treeDatas: [],
      parentNodesName: [],
      /** tree数据 */
      libraryIds: {},
      nodeIndexes: {},
      /** (受控)展开指定的树节点 */
      expandedKeys: [],
      /** 是否自动展开父节点   */
      autoExpandParent: false,
      /** 加载中 */
      spinTip: "",
      /** 延迟显示加载效果的时间（防止闪烁）*/
      delayTime: 500,
      /** tree加载中状态 */
      treeLoading: false,
      /** 选中类型 */
      nodeType: "",
      /** 页码展示 */
      pageShow: false,
      /** 暂无数据 */
      chartsShow: true
    };
  },
  created() {
    // 初始化加载知识库树
    this.initKnowledgeBaseTree();
    // 清空FMEA树选中节点
    this.cleanCheckedNode();
  },
  methods: {
    /**
     * 初始化：DFMEA知识库结构树
     */
    async initKnowledgeBaseTree(message) {
      let _that = this;
      _that.treeLoading = true;
      await _that.$api.getDFMEAKnowledgeBaseTree({
        struTypeCode: _that.struTypeCode,
        pageCurrent: _that.current,
        name: message,
      }).then((res) => {
        if (res.flag) {
          // 节点树
          let resultChildTree = res.data.childTree;
          // 存储节点上级信息
          let parentNodes = res.data.parentTree;
          // 清空存储信息
          _that.treeDatas = [];
          _that.parentNodesName = [];
          // 获取数据总数，供分页控件计算页数
          if (res.data.rowTotal !== 0) {
            this.total = res.data.rowTotal;
            this.chartsShow = false;
            this.pageShow = true;
          } else {
            this.chartsShow = true;
            this.pageShow = false;
          }
          if (resultChildTree !== null && parentNodes!== null) {
            // 存储节点Name信息
            let parentNames = {};
            // 循环拿出节点ID
            for (var key in parentNodes) {
              // 取出节点ID
              let parentNode = parentNodes[key];
              // 按struTypeCode排序用于展示
              let len = parentNode.length;
              for (let i = 0; i < len; i++) {
                for (let j = 0; j < len - 1 - i; j++) {
                  if (parentNode[j].struTypeCode == null) {
                  } else if (parentNode[j].struTypeCode > parentNode[j + 1].struTypeCode) {
                    [parentNode[j], parentNode[j + 1]] = [parentNode[j + 1], parentNode[j]];
                  }
                }
              }
              // 定义拼接上级内容
              let parentTitle = '';
              // 拼接名字
              parentNodes[key].forEach((item, index) => {
                // 最后一个不拼接符号
                if (index !== parentNode.length - 1) {
                  parentTitle += item.name + '-';
                } else {
                  parentTitle += item.name;
                }
              })
              // 拼接内容赋值
              parentNames[key] = parentTitle;
            }
            resultChildTree.forEach((item, index) => {
              // 存储libraaryId
              _that.libraryIds[item.struId] = item.libraryId;
              // 存储节点对应的上级节点名称
              this.parentNodesName.push(parentNames[item.struId]);
              _that.nodeIndexes[item.struId] = index;
              // 判断是否有子节点
              let isParent = item.rightNo - item.leftNo > 1 ? true : false;
              // 初始化时，生成一个虚拟的节点
              let inventedNode = [{
                struId: '001',
                pid: item.struId
              }];
              // 如果没有子节点，则不需要虚拟节点（不需要展开按钮）
              if (!isParent) {
                inventedNode = [];
              }
              // 构建：treeData数据
              _that.buildTreeData(item, inventedNode);
            })
          }
        } else {
          _that.$message.error(res.message, 1);
        }
      }).finally(() => {
        _that.treeLoading = false;
        _that.selectedNode = [];
      });
    },
    /**
     * 构建：treeData数据
     * @param targetNode 目标节点
     * @param nodes 节点数组
     */
    buildTreeData(targetNode, nodes) {
      // 数组转Tree
      let treeData = this.arrayToTree(targetNode, nodes);
      // 添加插槽
      this.treeDatas.push(this.addScopedSlots(treeData));
      // 默认不展开全部节点
      this.expandedKeys = [];
    },
    /**
     * 构建：treeData数据
     * @param targetNode 目标节点
     * @param nodes 节点数组
     */
    updateTreeData(index, targetNode, nodes) {
      // 数组转Tree
      let treeData = this.arrayToTree(targetNode, nodes);
      // 添加插槽
      this.treeDatas[index] = this.addScopedSlots(treeData);
      // 展开全部子节点
      this.defaultExpandedAllKeys(treeData);
    },
    /**
     * 默认展开全部节点
     * @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);
        }
      }
    },
    /**
     * 数组转Tree
     * @param targetNode 目标节点
     * @param nodeArray 节点数组
     * @returns {*[]}
     */
    arrayToTree(targetNode, nodeArray) {
      targetNode = this.cleanNodeData([targetNode])[0];
      this.findChildren(targetNode, this.cleanNodeData(nodeArray), "");
      return [targetNode];
    },
    /**
     * 添加插槽
     * @param nodes 节点数组
     */
    addScopedSlots(nodes) {
      for (let i = 0, len = nodes.length; i < len; i++) {
        // 通过vue 自带的$set 给每条数据加上一个名为scopedSlots，值为{title: 'node'}，的插槽
        this.$set(nodes[i], "scopedSlots", { title: "treeDataSlot" });
        if (nodes[i].children && nodes[i].children.length > 0) {
          this.addScopedSlots(nodes[i].children);
        }
      }
      return nodes;
    },
    /**
     * 翻页
     */
    onTurnPages(current) {
      // 翻页页码
      this.current = current;
      // 清空FMEA树选中节点
      this.cleanCheckedNode();
      // 判断是否需要带搜索名称翻页
      if (this.searchName != null) {
        this.initKnowledgeBaseTree(this.searchName);
      } else {
        // 查询页码数据
        this.initKnowledgeBaseTree();
      }
    },
    /**
     * 搜索
     */
    search() {
      // 搜索时默认跳到第一页
      this.current = 1;
      // 搜索的名称只能通过点击搜索查询
      if (this.searchName != this.name) {
        this.searchName = this.name;
        // 清空FMEA树选中节点
        this.cleanCheckedNode();
        // 名称查询数据
        this.initKnowledgeBaseTree(this.searchName);
      } else {
        return
      }
    },
    /**
     * 图标展开/收起节点时触发
     * @param expandedKeys
     * @param e
     */
    expand(expandedKeys, e) {
      // 展开时查询，折叠时不需要查询, 只需要展开第一级时查询
      if (e.expanded && e.node.pos === "0-0") {
        // 点击节点的STRU_ID
        let struId = expandedKeys[expandedKeys.length - 1];
        // 点击节点的LIBRARY_ID
        let libraryId = this.libraryIds[expandedKeys[expandedKeys.length - 1]];
        // 点击节点在treeDatas的索引
        let nodeIndex = this.nodeIndexes[expandedKeys[expandedKeys.length - 1]];
        // 根据库ID和节点ID查询节点下的子节点
        this.$api.getDFMEAKnowledgeDetailTree({
          struId: struId,
          libraryId: libraryId
        }).then((res) => {
          if (res.flag) {
            let nodes = res.data.childTree;
            // 根据根节点类型选择以谁为根节点
            this.checkExpandTypeCode(nodes);
            // 根据treeDatas的索引更新treeDatas指定的(点击展开的)数据
            this.updateTreeData(nodeIndex, this.targetNode, res.data.childTree);
            this.autoExpandParent = false;
            e.node.dataRef.expanded = e.expanded;
          }
        });
      } else {
        this.expandedKeys = expandedKeys;
        this.autoExpandParent = false;
        e.node.dataRef.expanded = e.expanded;
      }
    },
    /**
     * 判断展开节点类型
     */
    checkExpandTypeCode(nodes) {
      if (this.struTypeCode == "01") {
        // 查询到的结果的根节点
        this.targetNode = nodes.filter((item) => {
          return item.struTypeCode === '01'
        })[0];
      } else if (this.struTypeCode == "02") {
        this.targetNode = nodes.filter((item) => {
          return item.struTypeCode === '02'
        })[0];
      } else if (this.struTypeCode == "04") {
        this.targetNode = nodes.filter((item) => {
          return item.struTypeCode === '04'
        })[0];
      } else if (this.struTypeCode == "05") {
        this.targetNode = nodes.filter((item) => {
          return item.struTypeCode === '05'
        })[0];
      } else if (this.struTypeCode == "06") {
        this.targetNode = nodes.filter((item) => {
          return item.struTypeCode === '06'
        })[0];
      }
    },
    /**
     * 单选框改变事件
     */
    radioChange(e) {
      this.$emit('update:selectType', e.target.value);
    },
    /**
     * 节点单击事件
     * 参数：selectedKeys, e:{selected: bool, selectedNodes, node, event}
     */
    async nodeSelect(selectedKeys, e) {
      // 根据添加类型限制可选节点
      if (e.selectedNodes[0].data.props.struTypeCode == this.struTypeCode) {
        // 存储当前节点信息
        this.setCheckedNode(e.node.dataRef, "treeNode");
        // 高亮当前节点
        this.setHighLightNode(e.node.dataRef, "treeNode");
      } else {
        return;
      }
    },
    /**
     * 获取节点样式
     * @param node
     */
    getNodeClass(node) {
      let color = "node rightTreeNode";
      color += this.getNodeColor(node);
      return color;
    },
    /**
     * 取得节点颜色样式
     * @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;
    },
    /**
     * 根据节点类型不同,展示不同的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 iconClass === "iconfont " ? false : iconClass;
    },
    /**
     * 清洗节点数据
     * @param sourceArray 源数组
     * @param curOptTypeCode 当前优化类型标识位
     * @returns {*}
     */
    cleanNodeData(sourceArray, curOptTypeCode) {
      let array = sourceArray.map((item) => {
        return {
          // TODO
          id: item.struId ? item.struId : item.id,
          pid: item.pid ? item.pid : '00000000000000000000000000000000',
          libraryId: item.libraryId,
          name: this.replaceNullName(item),
          children: [],
          leftNo: item.leftNo,
          rightNo: item.rightNo,
          struTypeCode: item.struTypeCode,
        }
      });
      return array.filter((item) => item != null);
    },
    /**
     * 填补措施，措施组的名称
     * @param node 节点
     * @returns {*}
     */
    replaceNullName(node) {
      let name = node.name;
      switch (node.struTypeCode) {
        case '14':
          name = i18nRender('global-dict.current-measures');
          break;
        case '07':
          name = i18nRender('global-dict.optimization-measures');
          break;
        case '08':
          name = node.name ? node.name : i18nRender('global-dict.group');
          break;
      }
      return name;
    },
    /**
     * 递归取得子集
     * curOptTypeCode参数：当前优化类型标识位
     * 1：区分当前措施组（1408）或优化预防措施（0708）
     * 2：区分当前预防措施（1409）或优化预防措施（0709）
     * 3：区分当前探测措施（1410）或优化探测措施（0710）
     * @param node 节点
     * @param nodeArray 节点数组
     * @param measureTypeCode 措施状态类型CODE：14、07
     * @returns {*}
     */
    findChildren(node, nodeArray, measureTypeCode) {
      for (let i = 0, len = nodeArray.length; i < len; i++) {
        if ("14,07".indexOf(nodeArray[i].struTypeCode) !== -1) {
          measureTypeCode = nodeArray[i].struTypeCode;
        }
        if ("08,09,10".indexOf(nodeArray[i].struTypeCode) !== -1) {
          nodeArray[i].curOptTypeCode = measureTypeCode + nodeArray[i].struTypeCode;
        }
        if (node.id === nodeArray[i].pid) {
          node.children.push(this.findChildren(nodeArray[i], nodeArray, measureTypeCode));
        }
      }
      return node;
    },
    /**
     * 存储当前节点信息
     */
    setCheckedNode(node, treeFlag) {
      this.$store.dispatch("fmeaTree/set", {
        key: "lastCheckedNode",
        value: node
      });
      this.$store.dispatch("fmeaTree/set", {
        key: "lastCheckedLRTreeFlag",
        value: treeFlag
      });
    },
    /**
     * 选中节点时，清除当前节点信息
     */
    cleanCheckedNode() {
      this.$store.dispatch("fmeaTree/set", {
        key: "lastCheckedNode",
        value: undefined
      });
      this.$store.dispatch("fmeaTree/set", {
        key: "checkedRightNode",
        value: undefined
      });
      this.$store.dispatch("fmeaTree/set", {
        key: "lastCheckedLRTreeFlag",
        value: undefined
      });
    },
    /**
     * 左侧树高亮节点
     */
    setHighLightNode(node, treeFlag) {
      let className = treeFlag + "-node-selected";
      let treeEleId = treeFlag;
      let arr = document.getElementsByClassName(className);
      // 清除其他高亮节点
      if (arr) {
        for (let i = 0; i < arr.length; i++) {
          removeClass(arr[i], className);
        }
      }
      addClass(
        document.getElementById(treeEleId + node.id),
        className
      );
    },
  }
};
</script>

<style lang="less" scoped>
/deep/ .ant-table-tbody {
  .ant-table-row-cell-ellipsis:nth-of-type(2) {
    text-align: left !important;
  }
}

.treeNode-node-selected {
  background-color: #9bf2eb;
  border-radius: 2px;
}

.left-tree-node-border {
  border: 2px solid #e6fffc;
}

.left-tree-node-complete-border {
  color: #fb0505 !important;
}

/deep/ .ant-tree li .ant-tree-node-content-wrapper {
  padding: 0 0 !important;
}

/deep/ .ant-tree li {
  padding: 2px 0 !important;
}

/deep/ .ant-tree-title {
  a {
    width: 100%;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    display: inline-block;

    input {
      width: 80%;
      height: 20px;
      padding: 0px;
    }
  }
}

/deep/ .treeContent {
  border-top: 0.5px solid rgb(233, 233, 233);
  border-bottom: 0.5px solid rgb(233, 233, 233);
}

/deep/ .treeDiv {
  width: 100%;
  height: 500px;
  overflow-y: auto;
}

/deep/ .treeTurnPages {
  text-align: center;
  margin: 0px 0px 10px 0px;
}

/deep/ .noData {
  line-height: 480px;
  text-align: center;
  color: #ccc;
}
</style>