<template>
  <div class="root">
    <div class="container1">
      <el-col :span="24">
        <div class="itemBox" :span="24">
          <el-row :gutter="10" class="flex-box">
            <el-col :span="6">
              <span class="label">标签名称</span>
              <el-autocomplete v-model="searchParam.searchLabel" :fetch-suggestions="getLabelList" placeholder="请输入标签名"
                @select="handleSelect" class="el-select"></el-autocomplete>
            </el-col>
            <el-col :span="2" class="mt10">
              <el-checkbox v-model="searchParam.radioTime" @change="isShowTimeinfo">显示时间</el-checkbox>
            </el-col>
            <el-col :span="2" class="mt10">
              <el-checkbox v-model="searchParam.radioItemStatus" @change="isShowItemStatus">显示状态</el-checkbox>
            </el-col>

            <div class="crumb-nav2">
              <template v-for="(nav, index) in crumbNavs">
                {{ index > 0 ? '>' : '' }}
                <!-- <el-button type="primary" :key="nav.id" @click="changeNode(nav)">{{ nav.label }}</el-button>-->
                <span class="nav-text" @click="changeNode(nav)">{{ nav.label }}</span>
              </template>
            </div>
          </el-row>
        </div>
        <div class="canvaBox">

          <div class="minimap">
          </div>
          <!-- 树图相关 -->
          <div id="treeDiv" class="whr100">
            <div class="text">安泰安全管理模块展示</div>
          </div>
          <!-- 重命名节点Dialog -->
          <el-dialog title="提示" :visible.sync="renameDialogVisible" width="30%" :before-close="editDialogClose">
            <el-input v-model="inputLabel.name" placeholder="请输入"></el-input>
            <span slot="footer" class="dialog-footer">
              <el-button @click="renameDialogVisible = false">取 消</el-button>
              <el-button type="primary" @click="renameSubmit">确 定</el-button>
            </span>
          </el-dialog>
          <!-- 删除dialog -->
          <el-dialog title="提示" :visible.sync="delDialogVisible" width="20%" :before-close="delDialogClose">
            <div class="title">是否确认删除？</div>
            <span slot="footer" class="dialog-footer">
              <el-button @click="delDialogVisible = false">取 消</el-button>
              <el-button type="primary" @click="delSubmit">确 定</el-button>
            </span>
          </el-dialog>
        </div>
      </el-col>
      <el-drawer title="节点信息" :visible.sync="dataInfoDrawerVisible" class="dataInfo-drawer-dialog" @close="dataInfoClose"
        size="50%">
        <el-form ref="dataInfoForm" :model="dataInfoForm" label-width="90px">
          <el-form-item label="节点名称">
            <el-col :span="11">
              <el-input v-model="dataInfoForm.name"></el-input>
            </el-col>
          </el-form-item>

          <el-form-item label="详细情况">
            <el-col :span="11">
              <el-input v-model="dataInfoForm.content"></el-input>
            </el-col>
          </el-form-item>
        </el-form>
        <div class="dataInfoFootDiv">
          <el-button @click="dataInfoDrawerVisible = false">取 消</el-button>
          <el-button type="primary" @click="dataInfoSubmit">保 存</el-button>
        </div>
      </el-drawer>
      <el-dialog title="文件预览" :visible.sync="dialogVisible" destroy-on-close width="90%" top="6vh" height="90%">
        <el-button size="small" type="primary" icon="el-icon-download" @click="downloadFile(chart.fileData)"
          :loading="loading" style="position: absolute; right: 100px; top: 20px;">
          点击保存
        </el-button>
        <iframe :src="previewUrl" width="100%" :height="singleTableHeight"></iframe>
      </el-dialog>
    </div>
    <!-- 上传器 -->
    <el-dialog title="文件重新上传" :visible.sync="dialogVisible2" destroy-on-close width="15%" top="6vh" height="90%">
      <el-upload class="upload-demo" ref="upload2" action="" :http-request="del_fileName" :loading="uploadloading"
        :auto-upload="true">
        <el-button slot="trigger" size="small" type="primary" :loading="loading" icon="el-icon-plus">选取文件
        </el-button>
      </el-upload>
    </el-dialog>
    <el-dialog title="文件上传" :visible.sync="dialogVisible1" destroy-on-close width="15%" top="6vh" height="90%">
      <el-upload class="upload-demo" ref="upload1" :file-list="fileList" action=""
        :loading="loading" :auto-upload="false" :on-change="handleChange" :on-remove="handleRemove">
        <el-button slot="trigger" size="small" type="primary" :loading="loading" icon="el-icon-plus">选取文件
        </el-button>
        <el-button size="small" type="primary" icon="el-icon-bottom-right" @click="beforeUpload">上传
        </el-button>
        <div slot="tip" class="el-upload__tip">上传文件总和请不要超过10mb</div>
      </el-upload>
    </el-dialog>

    <el-dialog title="文件信息预览" :visible.sync="dialogVisible3" destroy-on-close width="85%" top="6vh" height="90%" >
      <el-table :data="tableData" border style="width: 100%" max-height="500" stripe = "true">
        <el-table-column prop="createtime" label="上传时间" width="180">
        </el-table-column>
        <el-table-column prop="createman" label="上传人" width="80">
        </el-table-column>
        <el-table-column prop="filepath" label="文件地址" width="350">
        </el-table-column>
        <el-table-column prop="filename" label="文件名">
        </el-table-column>
        <el-table-column label="操作" width="200">
          <template slot-scope="scope">
            <el-button @click="preview(scope.row)">预 览</el-button>
            <el-button type="primary" @click="test3(scope.row)">重新上传</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>
<script>
import moment from "moment";
import { Message } from "element-ui";
import G6 from "@antv/g6";
import insertCss from "insert-css";


const { Util, TreeGraph, registerNode, Menu, Tooltip, Minimap } = G6;
let graph = {};
//节点类型颜色
const nodeType2Color = {
  0: "#BBDAFB",
  100: "#FFFFCC",
  200: "#FBD4D4",
  300: "#BCF2DA",
  400: "#CCFF99",
  500: "#FBD4D4",
  600: "#BBDAFB",
};
//根据节点状态颜色
const itemStatusColor = {
  0: "#5B8FF9",
  100: "#EEBC20",
  200: "#5BD8A6",
  300: "#F46649",
};
export default {
  name: "root",

  data() {
    return {
      rowNodeid: '',
      rowDataid: '',
      pageNum: 1,
      pageSize: 100,
      fileList: [],
      tableData: [],
      dialogVisible3: false,
      graph: null,
      thereDataId: '',
      crumbNavs: [],
      canvasWidth: 0, // 画布宽度
      canvasHeight: 0,// 画布高度
      singleTableHeight: '720px',
      previewUrl: '',
      activeMenu: '',
      nodeid: '',
      NodeData: {

      },
      selectFileType: "",
      uploadData: [],
      uploadIf: true,
      tableHeight: 500,
      uploadStop: false,
      dialogVisible: false,
      dialogVisible1: false,
      dialogVisible2: false,
      loading: false,
      loading2: false,
      uploadloading: false,
      tableLoading: false,
      chart: {
        height: '1024px',
        show: false,
        fileData: {
          fileName: '',
          fileUrl: ''
        },
        option: {
          tooltip: {
            trigger: 'item',
            triggerOn: 'mousemove'
          },
          toolbox: {
            feature: {
              saveAsImage: {}
            }
          },
          series: [{
            type: 'tree',
            data: [],
            top: '2%',
            left: '25%',
            bottom: '1%',
            right: '20%',
            symbolSize: 8,
            nodePadding: 50,
            label: {
              position: 'left',
              verticalAlign: 'bottom',
              align: 'right',
              fontSize: 15
            },
            leaves: {
              label: {
                position: 'right',
                verticalAlign: 'middle',
                align: 'left'
              }
            },
            emphasis: {
              focus: 'descendant'
            },
            initialTreeDepth: 2,
            expandAndCollapse: true,
            animationDuration: 550,
            animationDurationUpdate: 750,
            roam: true
          }]
        }
      },
      initTinymce: {
        language: "zh_CN", //语言
        height: 300, //编辑器高度
        branding: false, //是否禁用“Powered by TinyMCE”
        menubar: false, //顶部菜单栏显示
      },
      renameDialogVisible: false,
      delDialogVisible: false,
      dataInfoDrawerVisible: false,
      dataInfoForm: {
        id: "",
        name: "",
        itemtype: "",
        itemstatus: "",
        content: "",
        createtime: "",
        tlevel: "",
        parentid: "",
        filename: ""
      },
      file: {
        id: "",
        filename: ""
      },
      itemStatusList: {
        100: "无文件",
        200: "有文件",
      },
      dataList: [],
      itemTypeList: {
        100: "项目准备工作相关",
        200: "项目程序制作",
        300: "项目测试相关"
      },
      dataInfo: [],
      selectLabelList: [],
      findLabeltimeout: false,
      lastSelectedNodeArr: [], // 上次选中节点
      itemNode: {}, // 右键菜单项 点击时的节点
      inputLabel: {
        name: "",
      },
      treeData: [],
      treeData1: [],
      listData: [],
      searchParam: {
        searchLabel: "",
        searchItemStatus: "",
        itemtype: "",
        radioItemStatus: "",
      },
    };
  },
  created() {
    //  this.treeData3();
    this.getGxNameData();

  },
  mounted() {
  },
  methods: {
    changeNode(node) {
      if (node) {
        console.log('casdasd', node)
        if (node.tlevel === 1) {
          this.crumbNavs = null;
        }
        graph.changeData(node);
        //graph.changeData(JSON.parse(JSON.stringify(node)));
        graph.fitView([140, 40, 20, 40]);
      } else {
        console.log("没有数据")
      }

    },
    treeData3() {
      //获取tree数据
      // this.treeData = require('../securitys/treeData2.json');
      let that = this;
      // 根据tree获取平级数组../
      const treeData = JSON.parse(JSON.stringify(this.treeData));
      this.listData = this.treeToList(treeData);

      // select数据
      this.listData.forEach((item) => {
        this.selectLabelList.push({
          value: item.name,
          name: item.name,
          id: item.id,
          levle: item.tlevel
        });
      });
      this.$nextTick(() => {
        this.treeInit();
      });
    },
    treeInit() {
      const that = this;
      that.styleCss(); // 样式函数
      // 创建G6右键菜单
      const menu = new Menu({
        itemTypes: ["node"],
        getContent(evt) {
          const model = evt.item.getModel();
          let menuHtml = `
              <div class="contextmenu__item" id="addLabel">新建标签</div>
              <div class="contextmenu__item" id="editLabel">重命名</div>
              <div class="contextmenu__item" id="delLabel">删除</div>
              <div class="contextmenu__item" id="beforeUpload">上传文件</div>`;
          return menuHtml;
        },
        handleMenuClick(target, item) {
          if (target.id == "addLabel") {
            // 新建
            that.itemNode = item;
            Object.keys(that.dataInfoForm).forEach((key) => {
              that.dataInfoForm[key] = "";
            });
            that.dataInfoDrawerVisible = true;
          } else if (target.id == "editLabel") {
            // 重命名
            that.itemNode = item;
            that.renameDialog();
          } else if (target.id == "beforeUpload") {
            // 上传文件
            that.itemNode = item;
            that.dialogVisible1 = true;
            console.log('fileitemNode', that.itemNode)
          }else if (target.id == "delLabel") {
            // 删除
            that.itemNode = item;
            that.delDialogVisible = true;
          } else if (target.id == "dataInfoLabel") {
          } else if (target.id == "detailLabel") {
            // 修改
            that.itemNode = item;
            that.dataInfoForm = that.itemNode.getModel();
            that.dataInfoForm.content = that.dataInfoForm.content.toString();
            that.dataInfoDrawerVisible = true;
          }
        },
      });
      //弹出层
      const tooltip = new Tooltip({
        getContent(e) {
          var tooltipHtml = "";
          const model = e.item.getModel();
          if (model.content && model.content.toString().length > 0) {
            tooltipHtml =
              `
                <div class="tooltip-header" >` +
              model.createtime +
              `（` +
              model.itemStatusName +
              `)</div>
                <div class="tooltip-content" ><h3>` +
              model.name +
              `</h3>` +
              model.content +
              `</div> `;
          }
          return tooltipHtml;
        },
        shouldBegin(e) {
          //设置条件，没有内容不显示tooltip
          const model = e.item.getModel();
          return model.content ? true : false;
        },
        itemTypes: ["node"],
        offsetX: 1,
        offsetY: 0,
        fixToNode: false,
        offset: 10,
      });
      // 实例化 minimap 插件
      const minimap = new Minimap({
        container: document.querySelector(".minimap"),
        size: [200, 200],
      });
      // G6增加自定义节点信息;
      registerNode(
        "rNode",
        {
          drawShape: (cfg, group) => {
            const {
              id,
              name,
              itemtype,
              style,
              size,
              itemstatus,
              itemStatusName,
              createtime,
              tlevel,
              file_name,
              file_url
            } = cfg;
            const rect = group.addShape("rect", {
              attrs: {
                ...style,
                x: -size[0] / 2,
                y: -size[1] / 2,
                width: size[0],
                height: size[1],
                fill: nodeType2Color[itemtype],
              },
              name: "rect",
            });
            // text time
            group.addShape("text", {
              attrs: {
                text: that.searchParam.radioTime
                  ? moment(createtime).format("YYYY-MM-DD")
                  : "",
                x: -size[0] / 2,
                y: -size[1] / 2 - 15,
                opacity: 1,
                fill: "#999",
                textBaseline: "top",
              },
              name: "rect-shape-text1",
            });
            // text itemStatusName
            group.addShape("text", {
              attrs: {
                text: that.searchParam.radioItemStatus ? "(" + itemStatusName + ")" : "",
                x: size[0] / 2 - 70,
                y: size[1] / 2 - 46,
                opacity: 1,
                fill: itemStatusColor[itemstatus],
                textBaseline: "top",
              },
              name: "rect-shape-text2",
            });
            return rect;
          },
          update: (cfg, item) => {
            const { id, name, createtime, itemstatus, itemStatusName } = cfg;
            const group = item.getContainer();
            // 更新节点名
            const label = group.find((e) => e.get("name") === "text-shape");
            label.attr("text", this.formatLabel(name));
            // 更新时间
            const text1 = group.find((e) => e.get("name") === "rect-shape-text1");
            text1.attr(
              "text",
              that.searchParam.radioTime
                ? moment(createtime).format("YYYY-MM-DD")
                : ""
            );
            // 更新状态及样式
            const text2 = group.find((e) => e.get("name") === "rect-shape-text2");
            text2.attr({
              text: that.searchParam.radioItemStatus ? "(" + itemStatusName + ")" : "",
              fill: itemStatusColor[itemstatus],
            });
          },
        },
        "rect"
      );

      const treeDiv = document.querySelector("#treeDiv");

      graph = new TreeGraph({
        plugins: [menu, minimap, tooltip],
        container: "treeDiv",
        width: window.innerWidth - 100,
        height: window.innerHeight - 100,
        fitView: true,
        pixelRatio: 2,
        modes: {
          // 内置行为参考 https://antv-g6.gitee.io/zh/docs/manual/middle/states/defaultBehavior
          default: ["collapse-expand", "drag-canvas", "zoom-canvas", "drag-node"],
        },
        // 设置一些状态时节点变化
        nodeStateStyles: {
          mouseenter: {
            // 鼠标划入样式设置
            shadowColor: "#CCC",
            shadowBlur: 1,
          },
          clicked: {
            // 选中样式设置
            stroke: "#409EFF",
            lineWidth: 2,
            shadowColor: "#409EFF",
            shadowBlur: 10
          },
        },
        // 节点类型及样式
        defaultNode: {
          size: [100, 30],
          type: "rNode",
          style: {
            // 节点阴影颜色和宽度
            shadowColor: "#CCC",
            shadowBlur: 20,
            // 阴影偏移量
            shadowOffsetX: 5,
            shadowOffsetY: 5,
            // 边框颜色和宽度
            stroke: "",
            lineWidth: 0,
          },
        },
        // 连线类型及样式
        defaultEdge: {
          type: "polyline",
          style: {
            // 节点阴影颜色和宽度
            shadowColor: "#CCC",
            shadowBlur: 10,
            // 阴影偏移量
            shadowOffsetX: 5,
            shadowOffsetY: 5,
            // 颜色和宽度
            stroke: "#999",
            lineWidth: 2,
          },
        },
        //布局和绘图类型
        layout: {
          type: "mindmap",
          direction: "H",
          getHeight: function getHeight() {
            return 40;
          },
          getWidth: function getWidth() {
            return 150;
          },
          getVGap: function getVGap() {
            return 10;
          },
          getHGap: function getHGap() {
            return 80;
          },
        },

      });

      // 格式化tree数据
      Util.traverseTree(this.treeData, (item) => {
        if (item.tlevel >= 2) {
          item.collapsed = true;
        }
        Object.keys(that.itemStatusList).forEach(function (k) {
          if (k == item.itemstatus) {
            item.itemStatusName = that.itemStatusList[k];
          }
        });
        item.label = that.formatLabel(item.name);
      });
      graph.read(this.treeData);

      if (typeof window !== "undefined")
        window.onresize = () => {
          this.$nextTick(() => {
            if (!graph || graph.get("destroyed")) return;
            if (!treeDiv || !treeDiv.scrollWidth || !treeDiv.scrollHeight) return;
            graph.changeSize(treeDiv.scrollWidth, treeDiv.scrollHeight);
            graph.render();
            graph.fitView();
          });
        };
      graph.on("node:click", function (event) {
        const { item } = event;
        const nodeItem = event.item // 获取被点击的节点元素对象
        const nodeModel = item.getModel();
        that.tableData = [];
        if (nodeModel.itemtype === 200) {
          that.dialogVisible3 = true;
          let arg = {
            fileUrl: nodeModel.file_url,
            fileName: nodeModel.file_name
          }
          //that.preview(arg);
          that.gettableData(nodeModel.id);
        }
        that.findNodesByModels([nodeModel]);
        that.crumbNavs = [];
        that.getParentNodes(that.treeData, nodeModel, nodeModel.id);
        that.changeDat(nodeModel);

        // if (nodeModel.tlevel > 1) {
        //   graph.changeData(nodeModel),
        //     graph.fitView([230, 240, 390, 390]);

        // }

      });
      // 鼠标点击画布，显示所有节点和边 
      graph.on('canvas:click', function (event) {
        const nodes = graph.getNodes();
        const edges = graph.getEdges();
        nodes.forEach((node) => {
          node.show();
        });
        edges.forEach((edge) => {
          edge.show();
        });
        graph.paint();
      });
      // 鼠标移入节点 node:mouseenter
      graph.on("node:mouseenter", (evt) => {
        const { item } = evt;
        graph.setItemState(item, "mouseenter", true);
        // // 获得当前鼠标操作的目标节点
        // const node = item;
        // // 获得目标节点的所有相关边
        // const edges = node.getEdges();
        // // 将所有相关边的 running 状态置为 true，此时将会触发自定义节点的 setState 函数
        // edges.forEach((edge) => graph.setItemState(edge, "running", true));
      });
      // 鼠标移出节点 node:mouseleave
      graph.on("node:mouseleave", (evt) => {
        const { item } = evt;
        graph.setItemState(item, "mouseenter", false);
        // // 获得当前鼠标操作的目标节点
        // const node = item;
        // // 获得目标节点的所有相关边
        // const edges = node.getEdges();
        // // 将所有相关边的 running 状态置为 false，此时将会触发自定义节点的 setState 函数
        // edges.forEach((edge) => graph.setItemState(edge, "running", false));
      });
    },
    gettableData(id) {
      let that = this;
      let pageNum = 0;
      let params = {
        nodeId: id
      }
      that.pageNum = pageNum || that.pageNum;
      let url =
        "pass/ems/v1/tfileoperates/?pageNum=" +
        that.pageNum +
        "&pageSize=" +
        that.pageSize;
      that.axios.get(url, {
        params: params
      }).then(res => {
        if (res.code === '0') {
          let arr = [];
          for (let e of res.data.list) {
            arr.push({
              createman: e.createman,
              createtime: e.createtime,
              filename: e.fileName,
              filepath: e.filePath,
              NodeId: e.nodeId,
              bz: e.bz,
              type: e.fileType,
              updateman: e.updateman,
              updatetime: e.updatetime,
              id: e.id,
            });
          }
          that.tableData = arr;
          console.log(res);
        } else {
          that.$message.error(res.message);
        }
      })

    },
    getParentNodes(data, node) {
      let no1 = 0;
      //如果点击的是第二层，只显示导航到第一层
      if (node.tlevel === 2) {
        this.crumbNavs.push(data);
      }
      //如果点击的是第三层，只显示导航到第二层和第一层

      if (node.tlevel === 3) {
        no1 = 1;
        const $id = node.parentid;
        const $node = data.children.find(item => item.id === $id);
        if ($node) {
          this.crumbNavs.push($node);
          this.thereData = $node.id;
        }
      }
      //如果点击的是第四层，只显示导航到第二层和第一层还有第三层
      if (node.tlevel === 4) {
        no1 = 1;
        const $id = node.parentid;
        const $node = data.children.find(item => item.id === this.thereData);
        const $node2 = $node.children.find(item => item.id === $id)
        if ($node2) {
          this.crumbNavs.push($node2);
          this.crumbNavs.push($node);
          this.fiveData = $node2.id;

        }
      }
      if (node.tlevel === 5) {
        no1 = 1;
        const $id = node.parentid;
        const $node = data.children.find(item => item.id === this.thereData);
        console.log('$node', $node)
        const $node2 = $node.children.find(item => item.id ===this.fiveData)
        const $node3 = $node2.children.find(item => item.id === $id)
        if ($node3) {
          this.crumbNavs.push($node3);
          this.crumbNavs.push($node2);
          this.crumbNavs.push($node);
        }
      }
      if (no1 === 1) {
        this.crumbNavs.push(data);//第一层
      }
    },
    // 获取节点结构数据
    getGxNameData() {
      let that = this
      let url = 'pass/ems/v1/emssecuernodes/findAll';
      that.axios.post(url)
        .then(res => {
          if (res.code === '0') {
            that.treeData = res.data[0];
            that.treeData3();
          } else {
            that.$message.error(res.message);
          }
        })
    },
    //changeDat
    changeDat(node) {
      if (node) {
        if (node.tlevel > 1 && node.tlevel<6) {
          //graph.changeData(JSON.parse(JSON.stringify(node))),
          graph.changeData(node)
          graph.fitView([230, 240, 390, 390]);
        } else {
          console.log("没有数据")
        }
      }

    },

    // 获取节点结构数据
    getGxNameData3() {
      let that = this
      let url = 'pass/ems/v1/emssecuernodes/findAll';
      that.axios.post(url)
        .then(res => {
          if (res.code === '0') {
            that.treeData = res.data[0];
          } else {
            that.$message.error(res.message);
          }
        })
    },
    getGxNameData2(id) {
      let that = this
      let url = `pass/ems/v1/emssecuernodes/${id}`;
      that.axios.get(url)
        .then(res => {
          if (res.code === '0') {
            that.nodeid = res.data.id;
            that.test();
          } else {
            that.$message.error(res.message);
          }
        })
    },
    //查询是否有文件信息
    getFileMeg(id) {
      let that = this
      let url = `pass/ems/v1/uploadfiles/${id}`;
      that.axios.get(url)
        .then(res => {
          if (res.code === '0') {
            if (res.fileName) {
              that.selectFileType = "1";
            }
          } else {
            that.$message.error(res.message);
          }
        })
    },
    //搜索相关
    getLabelList(queryString, cb) {
      var selectLabelList = this.selectLabelList;
      var results = queryString
        ? selectLabelList.filter(this.createStateFilter(queryString))
        : selectLabelList;

      clearTimeout(this.findLabeltimeout);
      this.findLabeltimeout = setTimeout(() => {
        cb(results);
      }, 100);
    },
    createStateFilter(queryString) {
      return (searchLabel) => {
        return searchLabel.value.toLowerCase().indexOf(queryString.toLowerCase()) != -1;
      };
    },
    handleSelect(item) {
      // 清空searchLabel
      this.searchParam.searchItemStatus = "";
      const node = graph.findById(item.id);
      graph.focusItem(node, true, {
        easing: "easeCubic",
        duration: 500,
      });
      graph.translate(0, -200);
      this.findNodesByModels([item]);
    },
    initTree(data) {
      // 文本超出隐藏 (字段, 最大长度, 字体大小)
      const fittingString = (str, maxWidth, fontSize) => {
        const ellipsis = '...';
        const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
        let currentWidth = 0;
        let res = str;
        const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
        str.split('').forEach((letter, i) => {
          if (currentWidth > maxWidth - ellipsisLength) return;
          if (pattern.test(letter)) {
            // Chinese charactors
            currentWidth += fontSize;
          } else {
            // get the width of single letter according to the fontSize
            currentWidth += G6.Util.getLetterWidth(letter, fontSize);
          }
          if (currentWidth > maxWidth - ellipsisLength) {
            res = `${str.substr(0, i)}${ellipsis}`;
          }
        });
        return res;
      };
    },
    findNodesByModels(arr) {
      // 查询是否有被选中节点,并清除样式
      if (this.lastSelectedNodeArr) {
        this.lastSelectedNodeArr.map((val) => {
          graph.setItemState(val.id, "clicked", false);
        });
        this.lastSelectedNodeArr = [];
      }
      // arr为空，就不走下面选中逻辑了
      if (arr) {
        arr.map((item) => {
          let findobj = graph.findById(item.id);
          if (findobj) {
            // 保存选中节点
            this.lastSelectedNodeArr.push(findobj.getModel());
            // 修改选中节点样式
            graph.setItemState(item.id, "clicked", true);
          }
        });
      }
    },
    // 重置条件
    searchResetFn() {
      Object.keys(this.searchParam).forEach((key) => {
        this.searchParam[key] = "";
      });
      this.findNodesByModels();
    },
    searchFn() {
      // 清空searchLabel
      this.searchParam.searchLabel = "";
      console.log('searchParam', this.searchParam)
      //搜索状态fn
      let searchNodes = [];
      let searchNodeModels = [];
      //获取选中状态的所有节点
      searchNodes = graph.findAll("node", (node) => {
        return node.get("model").itemstatus == this.searchParam.searchItemStatus;
      });
      //获取选中状态的所有model
      searchNodes.forEach((item) => {
        searchNodeModels.push(item.get("model"));
      });
      this.findNodesByModels(searchNodeModels);
    },
    isShowTimeinfo() {
      graph.render();
      graph.fitView();
    },
    isShowItemStatus() {
      graph.render();
      graph.fitView();
    },
    renameDialog() {
      this.inputLabel.name = this.itemNode._cfg.model.name;
      this.renameDialogVisible = true;
    },
    dataInfoSubmit() {
      let that = this;
      if (this.dataInfoForm.name == "") {
        Message.error("请输入名称");
        return;
      }
      //add 新建子节点
      if (!this.dataInfoForm.id) {
        //this.dataInfoForm.id = `n-${Math.random()}`;
        this.dataInfoForm.label = this.formatLabel(this.dataInfoForm.name);
        this.dataInfoForm.itemtype = this.itemNode._cfg.model.itemtype;
        this.dataInfoForm.itemstatus = 0;
        this.dataInfoForm.tlevel = this.itemNode._cfg.model.tlevel + 1;
        this.dataInfoForm.parentid = this.itemNode._cfg.model.id;
        this.addGxNameData(this.dataInfoForm)
        const model = this.itemNode.getModel();
        if (!model.children) {
          model.children = [];
        }
        this.dataInfoForm.id = that.nodeid;
        console.log('that.nodeid', that.nodeid)
        model.children.push(this.dataInfoForm);
        graph.updateChild(model, model.id);
      } else {
        //修改节点
        const model = this.itemNode.getModel();
        const originStyle = this.itemNode.get("originStyle");
        let updateModel = {
          ...model,
          ...this.dataInfoForm,
          itemstatus: 0,
          itemStatusName: "已保存",
          name: this.dataInfoForm.name,
        };
        const nodeItem = graph.findById(model.id);
        graph.updateItem(nodeItem, updateModel);
      }
      this.dataInfoDrawerVisible = false;
      Message.success("新建成功");
    },
    test() {
      //this.dataInfoForm.id = `n-${Math.random()}`;
      let that = this;
      this.dataInfoForm.label = this.formatLabel(this.dataInfoForm.name);
      this.dataInfoForm.itemtype = this.itemNode._cfg.model.itemtype;
      this.dataInfoForm.itemstatus = 0;
      this.dataInfoForm.tlevel = this.itemNode._cfg.model.tlevel + 1;
      this.dataInfoForm.parentid = this.itemNode._cfg.model.id;
      const model = this.itemNode.getModel();
      if (!model.children) {
        model.children = [];
      }
      this.dataInfoForm.id = that.nodeid;
      console.log('that.nodeid', that.nodeid)
      model.children.push(this.dataInfoForm);
      graph.updateChild(model, model.id);

    },
    test3(row) {
      let that = this;
      that.dialogVisible2 = true;
      that.rowDataid = row.id;
      that.rowNodeid = row.NodeId;
    },

    renameSubmit() {
      const model = this.itemNode.getModel();
      const updateModel = {
        ...model,
        name: this.inputLabel.name,
        label: this.formatLabel(this.inputLabel.name),
      };
      const updateModel2 = {
        name: this.inputLabel.name,
        content: this.inputLabel.content
      };
      let id = model.id;
      this.updateNameData(id, updateModel2);
      console.log('renanme model', id)
      this.itemNode.update(updateModel);
      Message.success("修改成功");
      this.renameDialogVisible = false;
    },
    delSubmit() {
      this.delDialogVisible = false;
      const model = this.itemNode.getModel();
      if (model.depth != 0) {
        //根节点不能删除，这里写删除访问后台接口逻辑
        let id = model.id;
        this.getFileMeg(id);
        if (this.selectFileType === '1') {
          this.open1();
        }
        this.but_del_plural(id);
        graph.removeChild(model.id);
        //停止缩进动画，不加就像收起节点一样，视觉显示错误
        graph.stopAnimate();
        Message.success("删除成功");
      }
    },
    updateDatepicker(arr) {
      //时间更新
      this.dataInfoForm = {
        ...this.dataInfoForm,
        startTime: arr[0],
        endTime: arr[1],
      };
    },
    downloadImage() {
      graph.downloadFullImage('tree');
    },
    editDialogClose() {
      this.renameDialogVisible = false;
    },
    delDialogClose() {
      this.renameDialogVisible = false;
    },
    dataInfoClose() {
      this.dataInfoDrawerVisible = false;
    },
    //格式化label
    formatLabel(str) {
      return str.length > 20 ? str.substr(0, 20) + "..." : str;
    },
    // js实现文件下载而不直接打开
    saveAs(data, fileName) {
      this.loading = true;
      let urlObject = window.URL || window.webkitURL || window;
      // 将二进制流转为blob
      let exportBlob = new Blob([data]);
      if (typeof window.navigator.msSaveBlob !== 'undefined') {
        // 兼容IE，window.navigator.msSaveBlob：以本地方式保存文件
        window.navigator.msSaveBlob(exportBlob, decodeURI(fileName));
        this.loading = false;
      } else {
        // 创建新的URL并指向File对象或者Blob对象的地址
        let blobURL = urlObject.createObjectURL(exportBlob);
        let saveLink = document.createElement('a');
        // 兼容：某些浏览器不支持HTML5的download属性
        if (typeof saveLink.download === 'undefined') {
          saveLink.setAttribute('target', '_blank');
        } else {
          saveLink.download = fileName;
        }
        // 创建新的URL并指向File对象或者Blob对象的地址
        saveLink.href = blobURL;
        saveLink.click();
        // 释放blob URL地址
        urlObject.revokeObjectURL(exportBlob);
        this.loading = false;
        // let blob = new Blob([data])
        // let fileURL = urlObject.createObjectURL(blob);
        // 下载代码
        // let downEle = document.createElement('a')
        // let fname = `download` //下载文件的名字
        // downEle.href = fileURL
        // downEle.setAttribute('download', fname)
        // document.body.appendChild(downEle)
        // downEle.click()
        // window.open(fileURL);
      }
    },
    // 文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用,function(file, fileList)
    handleChange(file, fileList) {
      this.fileList = fileList
      let size  = 0;
      this.fileList.forEach((item)=>{
        size +=item.size
      })
       let fileSize = size/1024/1024 < 10 ?0:1
       if(fileSize===1){
        this.$message.error("上传文件大小请不要超过10MB!")
       }
      console.log(fileSize ===1)
    },
    // 删除文件之前的钩子，参数为上传的文件和文件列表，若返回 false 或者返回 Promise 且被 reject，则停止删除。function(file, fileList)
    handleRemove(file, fileList) {
      this.fileList = fileList
    },
    // 新增节点结构数据
    addGxNameData(arr1) {
      let that = this
      let url = 'pass/ems/v1/emssecuernodes/';
      that.axios.post(url, arr1)
        .then(res => {
          if (res.code === '0') {
            let id = res.data.id;
            that.getGxNameData2(id);

          } else {
            that.$message.error(res.message);
          }
        })
    },
    // 更改节点名称
    updateNameData(arr1, arr2) {
      let that = this
      let url = `pass/ems/v1/emssecuernodes/${arr1}`;
      that.axios.put(url, arr2)
        .then(res => {
          if (res.code === '0') {

            console.log('res', res)
          } else {
            that.$message.error(res.message);
          }
        })
    },
    // 更改文件信息
    updateNameData2(arr1, arr2) {
      let that = this
      let url = `pass/ems/v1/emssecuernodes/${arr1}`;
      that.axios.put(url, arr2)
        .then(res => {
          if (res.code === '0') {

            console.log('res', res)
          } else {
            that.$message.error(res.message);
          }
        })
    },
    //删除提示
    open1() {
      const h = this.$createElement;
      this.$notify({
        title: '删除警告',
        message: h('i', { style: 'color: teal' }, '该节点存在文件，请确认是否永久删除！！！')
      });
    },
    //上传文件
    beforeUpload() {
      let that = this;
      // that.uploadloading = true;

      let foorData = new FormData();
      that.fileList.forEach((file => {
        foorData.append('files', file.raw);
      }))
      //foorData.append('files', file.file);
      foorData.append('id', that.itemNode._cfg.id);
      //foorData.append('name', that.itemNode._cfg.model.label);
      that.axios.post('pass/ems/v1/tfileoperates/fileUpload', foorData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(function (res) {
        if (res.code === '0') {
          that.$message({
            message: '上传成功',
            type: 'success'
          });
          let arr2 = {
            itemstatus: 200,
            itemtype: 200
          }
          that.updateNameData2(that.itemNode._cfg.id, arr2);
          that.uploadloading = false;
          that.$refs.upload1.clearFiles();
          that.getGxNameData();
          graph.changeData();
          location.reload();
        }
        else {
          that.$message.error(res.message);
          that.$refs.upload1.clearFiles();
        }
        that.tableLoading = false;
        that.uploadloading = false;
        that.fileList = [];
      })
    },
    //重新上传文件
    beforeUpload2(file) {
      console.log('beforeUpload2', file)
      let that = this;
      that.uploadloading = true;
      let foorData = new FormData();
      foorData.append('files', file.file);
      foorData.append('id', that.rowDataid);
      //foorData.append('name', that.itemNode._cfg.model.label);
      // that.del_fileName(that.itemNode._cfg.id);
      that.axios.post('pass/ems/v1/tfileoperates/fileUploa2', foorData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then(function (res) {
        if (res.code === '0') {
          that.$message({
            message: '修改成功',
            type: 'success'
          });
          that.loading = false;
          that.dialogVisible2 = false;
          that.$refs.upload2.clearFiles();
          console.log(that.rowNodeid);
          that.gettableData(that.rowNodeid);
          graph.changeData();
        }
        else {
          that.$message.error(res.message);
          that.$refs.upload2.clearFiles();
        }
        that.tableLoading = false;
        that.loading = false;
        that.uploadloading = false;
      })
    },
    // 删除上传的文件
    del_fileName(file) {
      let that = this;
      let id = that.rowDataid;
      if (id) {
        that.axios.delete('pass/ems/v1/tfileoperates/' + id)
          .then(function (res) {
            if (res.code === '0') {
              that.$message({
                message: '上传成功',
                type: 'success'
              });
              that.beforeUpload2(file);
            } else {
              if (res.code === '51') {
              }
              that.$message.error(res.message);
            }
          }).catch(function () {
          });
      }
    },
    // 删除节点
    but_del_plural(val1) {
      let that = this;
      if (val1) {
        that.axios.delete('pass/ems/v1/emssecuernodes/' + val1)
          .then(function (res) {
            if (res.code === '0') {
              that.$message({
                message: '删除成功',
                type: 'success'
              });
            } else {
              if (res.code === '51') {
              }
              that.$message.error(res.message);
            }
          }).catch(function () {
          });
      }
    },

    //预览文件
    preview(data) {
      let that = this;
      that.loading = true;
      that.chart.fileData = data;
      console.log(data)
      let SubmitData = {
        fileName: data.filename,
        fileUrl: data.filepath
      };
      let urla = 'pass/ems/v1/uploadfiles/getfile/';
      let type = 'text/html';
      let responseType = 'application/json';
      if (data.filename !== null) {
        let fileExtension = data.filename.substring(data.filename.lastIndexOf('.') + 1);
        if (fileExtension === 'pdf') {
          urla = 'pass/ems/v1/uploadfiles/downloadFile/';
          type = 'application/pdf';
          responseType = 'blob';
        }
        that.axios.get(urla, {
          params: SubmitData,
          responseType: responseType
        }).then(function (res) {
          console.log('111');
          let urlObject = window.URL || window.webkitURL || window;
          // 将二进制流转为blob
          let blob = new Blob([res], {
            type: type
          });
          if (fileExtension !== 'pdf') {
            blob = new Blob([res.data], {
              type: type
            });
          }
          // if (typeof window.navigator.msSaveBlob !== 'undefined') {
          //   // 兼容IE，window.navigator.msSaveBlob：以本地方式保存文件
          //   window.navigator.msSaveBlob(blob, decodeURI(fileName))
          // } else {
          // 创建新的URL并指向File对象或者Blob对象的地址
          let blobURL = urlObject.createObjectURL(blob);
          that.dialogVisible = true;
          that.previewUrl = blobURL;
          that.tableLoading = false;
          that.loading = false;
          // 'https://file.keking.cn/onlinePreview?url=' + encodeURIComponent(blobURL)
          // http://view.officeapps.live.com/op/view.aspx?src' + blobURL;
          // 创建a标签，用于跳转至下载链接
          // let tempLink = document.createElement('a')
          // tempLink.style.display = 'none'
          // tempLink.href = blobURL;
          // tempLink.setAttribute('download', decodeURI(fileName))
          // 兼容：某些浏览器不支持HTML5的download属性
          // if (typeof tempLink.download === 'undefined') {
          //   tempLink.setAttribute('target', '_blank')
          // }
          // // 挂载a标签
          // document.body.appendChild(tempLink)
          // tempLink.click()
          // // 销毁a标签
          // document.body.removeChild(tempLink)
          // 释放blob URL地址
          // urlObject.revokeObjectURL(blobURL);
          setTimeout(() => {
            urlObject.revokeObjectURL(blobURL);
          }, 1000)
        }).catch(function () {
          //that.tableLoading = false;
          that.$message.error('预览失败');
          that.loading = true;
        })
      }

    },
    //下载文件
    downloadFile(data) {
      let that = this;
      let SubmitData = {
        fileName: data.filename,
        fileUrl: data.filepath
      };
      that.loading = true;
      let urla = 'pass/ems/v1/uploadfiles/downloadFile/';
      that.axios.get(urla, {
        params: SubmitData,
        responseType: 'blob'
      }).then(function (res) {
        that.saveAs(res, data.filename);
        that.$message({
          message: '下载成功',
          type: 'success'
        });
        that.loading = false;
      }).catch(function () {
        that.$message.error('下载失败');
        that.loading = false;
      })
    },
    /* tree转化平级数组 */
    treeToList(tree) {
      var queen = [];
      var out = [];
      queen = queen.concat(tree);
      while (queen.length) {
        var first = queen.shift();
        if (first.children) {
          queen = queen.concat(first.children);
          delete first["children"];
        }
        out.push(first);
      }
      return out;
    },
    back() {
      this.$router.go(-1);
    },
    // 浮框样式
    styleCss() {
      insertCss(`
          .g6-component-tooltip {
            max-width: 600px;
            max-height: 500px;
            overflow-y: auto;
            position: absolute;
            left: -150px;
            z-index: 5;
            border: 1px solid #e2e2e2;
            border-radius: 4px;
            font-size: 14px;
            color: #545454;
            background-color: rgba(255, 255, 255, 0.9);
            padding: 10px 8px;
            box-shadow: rgb(174, 174, 174) 0px 0px 10px;
            text-align: justify;
            text-justify: newspaper;
            word-break: break-all;
          }
  
        .contextmenu__item {
          display: block;
          line-height: 34px;
          text-align: center;
        }
        .contextmenu__item:not(:last-child) {
          border-bottom: 1px solid rgba(0, 0, 0, 0.1);
        }
        .g6-component-contextmenu {
          width: 150px;
        }
        .contextmenu__item:hover {
          cursor: pointer;
          background: #66b1ff;
          border-color: #66b1ff;
          color: #fff;
        }
        .tooltip-header{
          padding:5px;
          text-align: left;
          border-bottom: 1px solid rgba(0, 0, 0, 0.1);
          font-size: 14px;
        }
        .tooltip-content{
          line-height:26px;
          font-size: 14px;
          padding:5px;
          text-align: left;
        }
      `);
    },
  },
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.root {
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  position: absolute;
}

.minimap {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  border: 1px solid #994343;
  background-color: #e0f0e9;
}

.container1 {
  border: 1px solid #305d91;
  height: 100%;
  position: relative;
  overflow: visible;

  .top {
    display: flex;
    justify-content: space-between;
    width: 100%;
    height: 50px;
    background-color: rgb(43, 104, 137);
    padding: 0 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 10px;

    .cursor {
      cursor: pointer;
      font-size: 20px;
    }

    .el-button {
      min-width: 70px;
    }
  }

  .itemBox {
    background-color: white;
    padding: 15px;
    font-size: 14px;

    .form-item {
      display: flex;
      align-items: center;
      justify-content: space-between;

      ::v-deep {
        .el-form-item {
          padding-bottom: 10px !important;
        }
      }
    }

    span {
      color: rgba(0, 0, 0, 0.65);
    }
  }

  .dataInfoFootDiv {
    text-align: center;
    margin-bottom: 20px;

    ::v-deep {
      .el-button {
        width: 100px;
        margin-right: 30px;
      }
    }
  }

  .el-form-item {
    margin-bottom: 10px;
  }

  .flex-box {
    padding-bottom: 15px;
    border-bottom: 1px solid rgba(151, 151, 151, 0.35);

    .el-row {
      display: flex;
      align-items: center;
      margin-bottom: 15px;
    }

    .el-col {
      display: flex;
      align-items: center;
    }

    .label {
      margin-right: 5px;
    }

    .el-select,
    .el-input,
    .el-autocomplete,
    .el-date-editor {
      width: 80%;
    }
  }

  .canvaBox {
    height: 100%;
    position: relative;
    background: url(../../../../assets/img/img/filebg8.jpg) center bottom no-repeat;
    background-size: 100% 100%;
  }

  .whr100 {
    width: 100%;
    height: 100%;
    position: relative;
  }

  .mt10 {
    margin-top: 10px;
  }
}

::v-deep {
  .dataInfo-drawer-dialog {
    :focus {
      outline: 0;
    }

    .el-drawer__header {
      border-bottom: 1px solid rgba(151, 151, 151, 0.35);
      padding-bottom: 10px;
      margin-bottom: 10px;
    }

    .el-drawer__body {
      padding: 0 5px;
    }
  }

  .el-progress-bar__outer,
  .el-progress-bar__inner {
    border-radius: 0;
  }

  .el-date-editor--daterange.el-input__inner {
    width: 394px;
  }
}

.uploader-example {
  width: 880px;
  padding: 15px;
  margin: 40px auto 0;
  font-size: 12px;
  box-shadow: 0 0 10px rgba(0, 0, 0, .4);
}

.uploader-example .uploader-btn {
  margin-right: 4px;
}

.uploader-example .uploader-list {
  max-height: 440px;
  overflow: auto;
  overflow-x: hidden;
  overflow-y: auto;
}

.crumb-nav {
  position: absolute;
  top: 20px;
  left: 40px;
  background: #73bf8f;
  border-radius: 4px;
  color: #fff;
  margin-left: 500px;
}

.nav-text {
  display: inline-block;
  height: 36px;
  line-height: 36px;
  margin: 0 10px;
  cursor: pointer;
}

.crumb-nav2 {
  height: 36px;
  line-height: 36px;
  margin: 0 10px;
  cursor: pointer;
  margin-left: 800px;
}

.text {
  margin-left: 550px;
  font-size: 50px;
  position: absolute;

  top: 60px;
}
</style>
  
  