<template>
  <div class="blank-page page-view w-100 h-100">
    <div class="header pa-15">
      <div class="flex-row-sb-c">
        <div class="header-title">算法推理：算法结果指标(PDP算法) - 1.1</div>
        <div>
          <!-- <el-button type="primary" icon="el-icon-picture" @click="getMindData">获取数据</el-button> -->
          <!-- <el-button type="primary" icon="el-icon-circle-check" @click="save">保存</el-button> -->
          <el-dropdown class="save-dropdown" trigger="click">
            <el-button icon="el-icon-circle-check" type="primary"> 保存 <i class="el-icon-arrow-down el-icon--right"></i> </el-button>
            <el-dropdown-menu slot="dropdown" class="save-dropdown-menu">
              <el-dropdown-item class="save-dropdown-item"><i class="el-icon-document-checked"></i>保存</el-dropdown-item>
              <el-dropdown-item class="save-dropdown-item"><i class="el-icon-document-copy"></i>另存为</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
          <el-button type="primary" plain icon="el-icon-picture" @click="exportImage">导出</el-button>
          <el-button type="success" icon="el-icon-setting" @click="toggleSideEditor()">工作面板</el-button>
        </div>
      </div>
    </div>
    <div class="flex-1 ma-15 overflow-h">
      <div class="jsmind-map flex-col">
        <div class="flex-1 overflow-h flex-row-s-c flex-gap-10">
          <div
            id="jsmind_container"
            @contextmenu.prevent.stop="nodePreventClick"
            @click="nodeClick"
            ref="container"
            :class="['jsmind_layout', 'bg-white border-radius-5', 'h-100', showSideEditor ? 'short-layout' : 'wild-layout']"
          ></div>
          <div :class="['side-editor', 'bg-white', 'border-radius-5', 'h-100', 'flex-1', showSideEditor ? 'w-p-370' : 'w-p-0']">
            <div class="tab-wrapper" v-if="showSideEditor">
              <el-tabs v-model="activeName" @tab-click="handleClickTab">
                <el-tab-pane name="first">
                  <span slot="label" title="基础样式"><i class="tab-title-icon el-icon-menu"></i></span>
                  <div class="h-100 tab-content-wrapper" v-if="currentNode">
                    <el-form ref="form" :model="currentNode" label-width="80px" label-position="left">
                      <div class="edit-type-header">类型</div>
                      <div class="flex flex-gap-16">
                        <div class="flex">
                          <span class="icon-type-text">多推一</span>
                          <div :class="['iconType', 'flex-row-c', { active: mapType === 'single' }]" title="多推一" @click="changeMapType('single')">
                            <div class="single"></div>
                          </div>
                        </div>
                        <div class="flex">
                          <span class="icon-type-text">一推多</span>
                          <div :class="['iconType', 'flex-row-c', { active: mapType === 'multi' }]" title="一推多" @click="changeMapType('multi')">
                            <div class="multi"></div>
                          </div>
                        </div>
                      </div>
                      <div class="edit-type-header">标签</div>
                      <el-form-item label="节点标题">
                        <el-input v-model="currentNode.topic" @change="changeNodeTopic"></el-input>
                      </el-form-item>
                      <div class="edit-type-header">字体</div>
                      <div class="flex flex-gap-16">
                        <el-select title="设置选中文本字体大小" style="width: 80px" v-model="currentNode.data['font-size']" @change="changeTextSize">
                          <template v-for="i in 30">
                            <el-option v-if="i >= 12" :key="i" :label="i" :value="i" />
                          </template>
                        </el-select>
                        <div
                          :class="['iconType', 'flex-row-c', { active: currentNode.data['font-weight'] === 'bold' }]"
                          title="加粗选中文本"
                          @click="changeFontWeight"
                        >
                          <div class="bold"></div>
                        </div>
                        <div
                          :class="['iconType', 'flex-row-c', { active: currentNode.data['font-style'] === 'italic' }]"
                          title="将选中文本变为斜体"
                          @click="changeFontStyle"
                        >
                          <div class="italic"></div>
                        </div>
                      </div>
                      <div class="edit-type-header">主题</div>
                      <el-row>
                        <el-col :span="12">
                          <el-form-item label="文字颜色">
                            <el-color-picker
                              v-model="currentNode.data['foreground-color']"
                              :predefine="predefineColors"
                              @change="changeTextColor"
                            ></el-color-picker>
                          </el-form-item>
                        </el-col>
                        <el-col :span="12">
                          <el-form-item label="背景颜色">
                            <el-color-picker
                              v-model="currentNode.data['background-color']"
                              :predefine="predefineColors"
                              @change="changeNodeColor"
                            ></el-color-picker>
                          </el-form-item>
                        </el-col>
                      </el-row>
                    </el-form>
                  </div>
                  <div class="flex-row-c h-100" v-else>
                    <el-empty :image="require('@/assets/img/components/mindMap/empty.svg')" :image-size="240" description="请选择节点"></el-empty>
                  </div>
                </el-tab-pane>
                <el-tab-pane name="second">
                  <span slot="label" title="指标利用"><i class="tab-title-icon el-icon-thumb"></i> </span>
                  <div class="h-100 flex-col" v-if="targetData.length">
                    <div class="search-wrapper">
                      <el-row :gutter="16">
                        <el-col :span="24" class="mb-10">
                          <el-radio-group v-model="searchTarget.type">
                            <el-radio-button :label="1"><i class="el-icon-question"></i>&nbsp;&nbsp;问题指标</el-radio-button>
                            <el-radio-button :label="2"><i class="el-icon-s-opportunity"></i>&nbsp;&nbsp;结果指标</el-radio-button>
                            <el-radio-button :label="3"><i class="el-icon-star-on"></i>&nbsp;&nbsp;属性指标</el-radio-button>
                          </el-radio-group>
                        </el-col>
                        <el-col :span="24">
                          <el-input clearable v-model="searchTarget.name" placeholder="请输入指标名称" prefix-icon="el-icon-search" />
                        </el-col>
                      </el-row>
                    </div>
                    <div class="table-wrapper felx-1 overflow-h">
                      <el-table :data="targetData" class="broad-table" border height="100%" size="small">
                        <el-table-column align="center" type="index" label="序号" width="60" />
                        <el-table-column align="center" prop="name" label="指标名称" show-overflow-tooltip />
                        <el-table-column align="center" label="操作" width="100">
                          <template slot-scope="scope">
                            <el-button
                              class="table-btn"
                              size="mini"
                              icon="el-icon-plus"
                              type="primary"
                              @click="addChildByTarget(scope.row)"
                              title="添加为子节点"
                            ></el-button>
                          </template>
                        </el-table-column>
                      </el-table>
                    </div>
                    <el-pagination
                      ref="paginationPanel"
                      :current-page="pagination.page"
                      :page-size="pagination.pageSize"
                      :page-sizes="[20, 30]"
                      :total="pagination.total"
                      align="right"
                      background
                      class="pagination"
                      layout="total, prev, pager, next, jumper"
                      @size-change="handleSizeChange"
                      @current-change="handleCurrentChange"
                    />
                  </div>
                  <div class="flex-row-c h-100" v-else>
                    <el-empty :image="require('@/assets/img/components/mindMap/empty.svg')" :image-size="240" description="请选择节点"></el-empty>
                  </div>
                </el-tab-pane>
                <el-tab-pane name="third">
                  <span slot="label" title="指标关联"><i class="tab-title-icon el-icon-magic-stick"></i> </span>
                  <div class="h-100 tab-content-wrapper" v-if="currentNode">
                    <el-form ref="form" :model="addTarget" label-width="100px" label-position="top">
                      <el-form-item label="指标名称">
                        <el-input v-model="addTarget.topic" placeholder="请输入指标名称"></el-input>
                      </el-form-item>
                      <el-form-item label="指标编码">
                        <el-input v-model="addTarget.code" placeholder="请输入指标编码"></el-input>
                      </el-form-item>
                      <el-form-item label="指标分类">
                        <el-radio-group v-model="addTarget.type">
                          <el-radio-button :label="1"><i class="el-icon-question"></i>&nbsp;&nbsp;问题指标</el-radio-button>
                          <el-radio-button :label="2"><i class="el-icon-s-opportunity"></i>&nbsp;&nbsp;结果指标</el-radio-button>
                          <el-radio-button :label="3"><i class="el-icon-star-on"></i>&nbsp;&nbsp;属性指标</el-radio-button>
                        </el-radio-group>
                      </el-form-item>
                      <el-form-item label="指标描述">
                        <el-input v-model="addTarget.desc" row="3" type="textarea" placeholder="请输入指标描述"></el-input>
                      </el-form-item>
                      <el-form-item label="归属数据库">
                        <el-radio-group v-model="addTarget.source">
                          <el-radio-button :label="2">DWD明细层</el-radio-button>
                          <el-radio-button :label="3">APP应用层</el-radio-button>
                        </el-radio-group>
                      </el-form-item>
                      <el-form-item label="数据库表名">
                        <el-select v-model="addTarget.tableName" @change="handleTableChange" placeholder="请选择数据库表">
                          <el-option v-for="tb in tableList" :key="tb.id" :label="tb.name" :value="tb.id"> </el-option>
                        </el-select>
                      </el-form-item>
                      <el-form-item label="表中文名">
                        <el-input v-model="addTarget.tableNameCn" disabled placeholder="根据数据库表名自动填充" />
                      </el-form-item>
                      <el-row :gutter="16">
                        <el-col :span="12">
                          <el-form-item label="字段名">
                            <el-select v-model="addTarget.fieldName" @change="handleFieldChange" placeholder="请选择字段">
                              <el-option v-for="fed in fieldList" :key="fed.id" :label="fed.name" :value="fed.id"> </el-option>
                            </el-select>
                          </el-form-item>
                        </el-col>
                        <el-col :span="12">
                          <el-form-item label="字段中文名">
                            <el-input v-model="addTarget.fieldNameCn" disabled placeholder="根据字段名自动填充" />
                          </el-form-item>
                        </el-col>
                      </el-row>
                      <el-row :gutter="16">
                        <el-col :span="12">
                          <el-form-item label="字段类别">
                            <el-input v-model="addTarget.fieldType" disabled placeholder="根据字段名自动填充" />
                          </el-form-item>
                        </el-col>
                        <el-col :span="12">
                          <el-form-item label="字典名" v-if="addTarget.fieldType && addTarget.fieldType !== '普通字段'">
                            <el-input v-model="addTarget.fieldDictName" disabled placeholder="根据字段名自动填充" />
                          </el-form-item>
                        </el-col>
                      </el-row>
                      <el-form-item label="字段值" v-if="addTarget.fieldType && addTarget.fieldType !== '普通字段'">
                        <div v-if="addTarget.fieldType === '枚举字典'" class="flex flex-gap-6">
                          <el-tag size="medium" v-for="item in addTarget.fieldDict" :key="item.id">{{ item.name }}</el-tag>
                        </div>
                        <div v-if="addTarget.fieldType === '多维字典'">
                          <el-tree :data="addTarget.fieldDict" :props="defaultProps" accordion>
                            <div slot-scope="{ node, data }" class="flex-row-s-c overflow-h dict-tree-item">
                              <svg-icon
                                :class="{ 'is-dir': !data.children || !data.children.length }"
                                :icon-class="data.children && data.children.length ? 'wenjianjia1' : 'drxx49'"
                                class="mr-5"
                                icon-style="icon "
                              />
                              <div :title="data.name" class="flex-1 text-ellipsis">{{ data.name }}</div>
                            </div>
                          </el-tree>
                        </div>
                      </el-form-item>
                    </el-form>
                    <div class="w-100 flex-row-c">
                      <el-button type="primary" size="mini" icon="el-icon-success">保存指标</el-button>
                    </div>
                  </div>
                  <div class="flex-row-c h-100" v-else>
                    <el-empty :image="require('@/assets/img/components/mindMap/empty.svg')" :image-size="240" description="请选择节点"></el-empty>
                  </div>
                </el-tab-pane>
                <el-tab-pane name="fourth">
                  <span slot="label" title="计算说明"><i class="tab-title-icon el-icon-reading"></i> </span>
                  <div class="h-98 tab-content-wrapper" v-if="currentNode">
                    <el-form ref="form" :model="currentNode" label-width="80px" label-position="top">
                      <div class="edit-type-header">当前节点</div>
                      <span class="tag-label"><i class="el-icon-s-flag"></i>{{ currentNode.topic }}</span>
                      <div class="edit-type-header">父节点</div>
                      <template v-if="currentNode.parent">
                        <el-form-item :label="currentNode.parent.topic" :key="currentNode.parent.id">
                          <template slot="label">
                            <span class="tag-label"><i class="el-icon-s-flag"></i>{{ currentNode.parent.topic }}</span>
                          </template>
                          <el-input
                            type="textarea"
                            :rows="4"
                            v-model="currentNode.parent.data.memo"
                            @change="(val) => changeNodeMemo(val, currentNode.parent.id)"
                            placeholder="请填写计算说明"
                          ></el-input>
                        </el-form-item>
                      </template>
                      <div class="edit-type-header">子节点</div>
                      <template v-for="item in currentNode.children">
                        <el-form-item :label="item.topic" :key="item.id">
                          <template slot="label">
                            <span class="tag-label"><i class="el-icon-s-flag"></i>{{ item.topic }}</span>
                          </template>
                          <el-input
                            type="textarea"
                            :rows="4"
                            v-model="item.data.memo"
                            @change="(val) => changeNodeMemo(val, item.id)"
                            placeholder="请填写计算说明"
                          ></el-input>
                        </el-form-item>
                      </template>
                    </el-form>
                  </div>
                  <div class="flex-row-c h-100" v-else>
                    <el-empty :image="require('@/assets/img/components/mindMap/empty.svg')" :image-size="240" description="当前节点暂无子节点"></el-empty>
                  </div>
                </el-tab-pane>
                <el-tab-pane name="fifth">
                  <span slot="label" title="关系说明"><i class="tab-title-icon el-icon-connection"></i> </span>
                  <div class="h-100 tab-content-wrapper" v-if="currentNode">
                    <el-button size="mini" type="primary" icon="el-icon-plus" @click="handleAddRelation">添加</el-button>
                    <el-form ref="form" :model="currentNode" label-width="80px">
                      <template v-for="(item, index) in currentNode.data.relation">
                        <el-descriptions direction="vertical" :column="1" border :key="item.key" class="mt-16">
                          <el-descriptions-item>
                            <template slot="label">
                              <span class="flex-row-sb-c">
                                <span> {{ index + 1 }}、关联指标 </span>
                                <el-button
                                  size="mini"
                                  class="table-btn"
                                  type="danger"
                                  @click="handleDeleteRelation(item, index)"
                                  title="删除关联"
                                  icon="el-icon-delete"
                                ></el-button>
                              </span>
                            </template>
                            <el-cascader
                              :props="{ label: 'topic', value: 'id', checkStrictly: true }"
                              v-model="item.target"
                              class="w-100"
                              :show-all-levels="false"
                              :options="[mindData.data]"
                              @change="(val) => changeNodeRelation(val, item, index, 'target')"
                            ></el-cascader>
                          </el-descriptions-item>
                          <el-descriptions-item label="关联说明">
                            <el-input type="textarea" :rows="3" v-model="item.desc" @change="(val) => changeNodeRelation(val, item, index, 'desc')"></el-input>
                          </el-descriptions-item>
                        </el-descriptions>
                      </template>
                    </el-form>
                  </div>
                  <div class="flex-row-c h-100" v-else>
                    <el-empty :image="require('@/assets/img/components/mindMap/empty.svg')" :image-size="240" description="请选择节点"></el-empty>
                  </div>
                </el-tab-pane>
                <el-tab-pane name="sixty">
                  <span slot="label" title="版本管理"><i class="tab-title-icon el-icon-price-tag"></i> </span>
                  <div class="h-100" v-if="versionData.length">
                    <el-table :data="versionData" class="broad-table" border height="98%" :row-class-name="tableRowClassName">
                      <el-table-column align="center" prop="versionNum" label="版本号" width="80"> </el-table-column>
                      <el-table-column align="center" prop="time" label="存档时间"> </el-table-column>
                      <el-table-column align="center" label="操作" width="120">
                        <template slot-scope="scope">
                          <el-button size="mini" class="table-btn" type="primary" @click="handleVersionChange(scope.row)" title="查看版本" icon="el-icon-view">
                          </el-button>
                          <el-button
                            size="mini"
                            class="table-btn"
                            plain
                            type="primary"
                            @click="handleVersionChange(scope.row)"
                            title="复制版本"
                            icon="el-icon-document-copy"
                          >
                          </el-button>
                        </template>
                      </el-table-column>
                    </el-table>
                  </div>
                  <div class="flex-row-c h-100" v-else>
                    <el-empty
                      :image="require('@/assets/img/components/mindMap/version.svg')"
                      :image-size="240"
                      description="暂无存档版本，请先保存！"
                    ></el-empty>
                  </div>
                </el-tab-pane>
              </el-tabs>
            </div>
          </div>
        </div>

        <!-- 右键菜单 -->
        <el-menu
          class="context-menu"
          v-show="showMenu"
          :style="{
            left: menuStyle.left,
            top: menuStyle.top,
            bottom: menuStyle.bottom,
            right: menuStyle.right,
          }"
          ref="context"
        >
          <slot>
            <el-menu-item @click="addChild">
              <i class="el-icon-circle-plus-outline" style="color: #409eff"></i>
              新增节点</el-menu-item
            >
            <!-- <el-menu-item @click="importChild">
              <i class="el-icon-paperclip" style="color: #409eff"></i>
              导入节点</el-menu-item
            > -->
            <el-menu-item @click="delCard" v-if="!isroot" style="color: #f56c6c">
              <i class="el-icon-circle-close" style="color: #f56c6c"></i>
              删除节点</el-menu-item
            >
          </slot>
        </el-menu>

        <div
          class="common-tip"
          v-show="showPopover"
          :style="{
            left: tipStyle.left,
            top: tipStyle.top,
            bottom: tipStyle.bottom,
            right: tipStyle.right,
          }"
        >
          {{ currentMemo }}
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import domtoimage from 'dom-to-image';
import utils from '@/utils.js';
import 'jsmind/style/jsmind.css';
import 'jsmind/es6/jsmind.draggable-node.js';
import 'jsmind/es6/jsmind.screenshot.js';
import jsMind from 'jsmind';
export default {
  name: 'mindMap',
  data() {
    return {
      // 配置信息
      showSideEditor: false,
      pagination: {
        // 分页初始化数据
        page: 1,
        total: 0,
        pageSize: 20,
      },
      searchTarget: {
        type: 1,
        name: '',
      },
      addTarget: {
        topic: '',
        code: '',
        type: 1,
        desc: '',
        source: 1,
      },
      activeName: 'first',
      tableList: [
        {
          id: '1.2',
          name: 'table01',
          nameCn: '表中文名01',
        },
        {
          id: '1.3',
          name: 'table02',
          nameCn: '表中文名02',
        },
        {
          id: '1.4',
          name: 'table03',
          nameCn: '表中文名03',
        },
      ],
      fieldList: [
        {
          id: '1.2',
          name: 'name',
          nameCn: '姓名',
          type: '普通字段',
        },
        {
          id: '1.3',
          name: 'sex',
          nameCn: '性别',
          type: '枚举字典',
          dictName: 'sexDict',
          dict: [
            {
              name: '男',
              id: '1',
            },
            {
              name: '女',
              id: '2',
            },
          ],
        },
        {
          id: '1.4',
          name: 'type',
          nameCn: '类型',
          type: '多维字典',
          dictName: 'sportsDict',
          dict: [
            {
              name: '运动',
              id: '1',
              children: [
                {
                  name: '水上运动水上运动水上运动水上运动水上运动水上运动水上运动水上运动水上运动水上运动水上运动水上运动',
                  id: '11',
                  children: [
                    {
                      name: '赛艇',
                      id: '111',
                    },
                    {
                      name: '翻板',
                      id: '112',
                    },
                    {
                      name: '皮划艇',
                      id: '113',
                    },
                  ],
                },
                {
                  name: '冬季运动',
                  id: '12',
                  children: [
                    {
                      name: '冰壶',
                      id: '121',
                    },
                    {
                      name: '花样滑冰',
                      id: '122',
                    },
                    {
                      name: '短道速滑',
                      id: '123',
                    },
                  ],
                },
                {
                  name: '球类运动',
                  id: '13',
                  children: [
                    {
                      name: '篮球',
                      id: '131',
                    },
                    {
                      name: '足球',
                      id: '132',
                    },
                    {
                      name: '曲棍球',
                      id: '133',
                    },
                  ],
                },
              ],
            },
          ],
        },
      ],
      defaultProps: {
        value: 'id',
        label: 'name',
      },
      versionData: [
        {
          versionNum: '1.2',
          time: '2025-01-10 10:55:22',
        },

        {
          versionNum: '1.1',
          time: '2025-01-11 11:55:22',
        },
        {
          versionNum: '1.0',
          time: '2025-01-10 10:55:22',
        },
      ],
      mapType: 'single', //multi  single
      targetData: [
        {
          name: '老虎型',
          id: utils.uuid(),
          type: '属性指标',
        },
        {
          name: '孔雀型',
          id: utils.uuid(),
          type: '属性指标',
        },
        {
          name: '考拉型',
          id: utils.uuid(),
          type: '属性指标',
        },
        {
          name: '猫头鹰型',
          id: utils.uuid(),
          type: '属性指标',
        },
        {
          name: '你组织能力好吗？',
          id: utils.uuid(),
          type: '问题指标',
        },
        {
          name: '你有活力吗？',
          id: utils.uuid(),
          type: '问题指标',
        },
        {
          name: '你爱说话吗？',
          id: utils.uuid(),
          type: '问题指标',
        },
        {
          name: '你个性温和吗？',
          id: utils.uuid(),
          type: '问题指标',
        },
        {
          name: '竞争心强',
          id: utils.uuid(),
          type: '结果指标',
        },
        {
          name: '主动且企图心强烈',
          id: utils.uuid(),
          type: '结果指标',
        },
        {
          name: '个性积极',
          id: utils.uuid(),
          type: '结果指标',
        },
        {
          name: '胸怀大志',
          id: utils.uuid(),
          type: '结果指标',
        },
        {
          name: '注重实质回报',
          id: utils.uuid(),
          type: '结果指标',
        },
      ],
      // 脑图信息
      // 脑图数据
      jm: null,
      editor: null,
      mindData: {
        meta: {
          name: '算法推理思维导图',
          author: 'artfess',
          version: '0.0.1',
        },
        format: 'node_tree',
        data: {
          id: 'root',
          topic: '算法结果指标(PDP算法)',
          'background-color': '#409eff',
          level: 0,
          children: [
            {
              id: utils.uuid(), // [必选] ID, 所有节点的ID不应有重复，否则ID重复的结节将被忽略
              topic: '你独立吗?', // [必选] 节点上显示的内容
              direction: 'right', // [可选] 节点的方向，此数据仅在第一层节点上有效，目前仅支持 left 和 right 两种，默认为 right
              expanded: true, // [可选] 该节点是否是展开状态，默认为 true
              'background-color': '#67c23a',
              memo: '这是节点备注这是节点备注这是节点备注这是节点备注这是节点备注',
              level: 1,
              children: [
                {
                  id: utils.uuid(),
                  topic: '孔雀型',
                  'background-color': '#e6a23c',
                  level: 2,
                  children: [
                    { id: utils.uuid(), 'background-color': '#f56c6c', topic: '你外向吗？', level: 3 },
                    { id: utils.uuid(), 'background-color': '#f56c6c', topic: '你爱说话吗？', level: 3 },
                    { id: utils.uuid(), 'background-color': '#f56c6c', topic: '你组织能力好吗？', level: 3 },
                  ],
                },
                { id: utils.uuid(), topic: '猫头鹰型', 'background-color': '#e6a23c', level: 2 },
                { id: utils.uuid(), topic: '变色龙型', 'background-color': '#e6a23c', level: 2 },
              ],
            },
            {
              id: utils.uuid(),
              topic: '你大胆吗?',
              direction: 'right',
              expanded: true,
              'background-color': '#67c23a',
              level: 1,
              children: [
                { id: utils.uuid(), 'background-color': '#e6a23c', topic: '猫头鹰型', level: 2 },
                { id: utils.uuid(), 'background-color': '#e6a23c', topic: '老虎型', level: 2 },
                {
                  id: utils.uuid(),
                  'background-color': '#e6a23c',
                  topic: '变色龙型',
                  memo: '这是节点备注这是节点备注这是节点备注这是节点备注这是节点备注',
                  level: 2,
                },
              ],
            },
            {
              id: utils.uuid(),
              topic: '你是否积极主动?', // 标题
              direction: 'right', // 方向   right  left
              'font-weight': 'normal', // 字体粗细 bold  normal
              'font-style': 'normal', // 字体样式 italic  normal
              'font-size': 18, // 字体大小
              'foreground-color': '#fff', // 文字颜色
              'background-color': '#67c23a', // 背景颜色
              memo: '这是节点备注', // 计算说明
              relation: [
                {
                  // 关联节点
                  key: utils.uuid(),
                  target: '', // 关联节点Topic
                  targetId: '', // 关联节点id
                  desc: '', // 关联描述
                },
              ],
              level: 1, // 层级
              children: [
                // 子节点
                { id: utils.uuid(), 'background-color': '#e6a23c', topic: '老虎型', level: 2 },
                { id: utils.uuid(), 'background-color': '#e6a23c', topic: '孔雀型', level: 2 },
                { id: utils.uuid(), 'background-color': '#e6a23c', topic: '考拉型', level: 2 },
              ],
            },
          ],
        },
      },
      // 脑图配置
      options: {
        container: 'jsmind_container', // [必选] 容器的ID
        editable: true, // [可选] 是否启用编辑
        theme: 'primary', // [可选] 主题
        support_html: true,
        log_level: 'debug', // 设置日志级别为 debug
        view: {
          engine: 'canvas', // 思维导图各节点之间线条的绘制引擎
          enable_device_pixel_ratio: true, // 按设备像素比例绘制高清思维导图
          hmargin: 100, // 思维导图距容器外框的最小水平距离
          vmargin: 50, // 思维导图距容器外框的最小垂直距离
          line_width: 2, // 思维导图线条的粗细
          line_color: '#ddd', // 思维导图线条的颜色
          draggable: true, // 是否允许拖动画布
          hide_scrollbars_when_draggable: true,
          node_overflow: 'hidden',
          zoom: {
            // 缩放配置
            min: 0.1, // 最小缩放比例
            max: 2.1, // 最大缩放比例
            step: 0.1, // 缩放比例步长
          },
          expander_style: 'number',
          line_style: 'curved',
          custom_line_render: null,
        },
        layout: {
          hspace: 100, // 节点之间的水平间距
          vspace: 20, // 节点之间的垂直间距
        },
        shortcut: {
          // 禁用快捷键
          enable: false,
        },
      },
      predefineColors: ['#1e90ff', '#67c23a', '#e6a23c', '#f56c6c', '#ff4500', '#ff8c00', '#ffd700', '#90ee90', '#00ced1', '#409eff', '#c71585'], // 预定义颜色

      structure: {
        active: 'right',
      },

      createType: '', // 添加平级or子级
      currentNode: null, // 选中节点信息
      showMenu: false, // 是否显示右键菜单栏
      isroot: false,
      menuStyle: {
        top: '',
        bottom: '',
        left: '',
        right: '',
      },
      tipStyle: { top: '', bottom: '', left: '', right: '' },
      showPopover: false,
      currentMemo: '',
    };
  },
  mounted() {
    var that = this;
    this.options.view.custom_line_render = function ({ ctx, start_point, end_point }) {
      that.drawArrow(ctx, start_point, end_point);
    };
    this.loadMind();
  },
  methods: {
    loadMind() {
      this.jm = null;
      this.jm = new jsMind(this.options);
      this.jm.show(this.mindData);
      this.editor = this.jm.view.e_editor;
      this.init();
      this.mouseWheel();
      this.mouseDrag();
    },
    handleDeleteRelation(item, index) {
      let data = this.currentNode.data;
      data.relation.splice(index, 1);
      this.$set(this.currentNode, 'data', data);
      this.$forceUpdate();

      this.loopTreeData(this.mindData.data.children, (item, i) => {
        console.log(item, 'this.currentNode');
        if (item.id === this.currentNode.id) {
          item.relation = this.currentNode.data.relation;
        }
      });

      this.jm.show(this.mindData);
      this.stopDBclick();
      this.tipsClick();
      this.jm.select_node(this.currentNode.id);
      this.nodeClick();
    },
    changeNodeRelation(val, item, index, type) {
      let data = this.currentNode.data;
      item[type] = val;
      data.relation.splice(index, 1, item);
      this.$set(this.currentNode, 'data', data);
      this.$forceUpdate();

      this.loopTreeData(this.mindData.data.children, (item, i) => {
        console.log(item, 'this.currentNode');
        if (item.id === this.currentNode.id) {
          item.relation = this.currentNode.data.relation;
        }
      });

      this.jm.show(this.mindData);
      this.stopDBclick();
      this.tipsClick();
      this.jm.select_node(this.currentNode.id);
      this.nodeClick();
    },
    handleAddRelation() {
      let relation = this.currentNode.data.relation || [];
      const newData = {
        key: utils.uuid(),
        target: '',
        targetId: '',
        desc: '',
      };

      relation.push(newData);

      this.currentNode.data.relation = relation;

      this.loopTreeData(this.mindData.data.children, (item, i) => {
        console.log(item, 'this.currentNode');
        if (item.id === this.currentNode.id) {
          item.relation = relation;
        }
      });

      this.jm.show(this.mindData);
      this.stopDBclick();
      this.tipsClick();
      this.jm.select_node(this.currentNode.id);
      this.nodeClick();
      this.$forceUpdate();
      console.log(this.currentNode);
    },
    handleTableChange(val) {
      const target = this.tableList.filter((i) => i.id === val)[0];
      this.addTarget.tableNameCn = target?.nameCn || '';
    },
    handleFieldChange(val) {
      const target = this.fieldList.filter((i) => i.id === val)[0];
      this.addTarget.fieldNameCn = target?.nameCn || '';
      this.addTarget.fieldType = target?.type || '';
      this.addTarget.fieldDict = target?.dict || [];
      this.addTarget.fieldDictName = target?.dictName || [];
    },
    handleSizeChange() {
      this.pagination.pageSize = val;
    },
    handleCurrentChange(val) {
      this.pagination.page = val;
    },
    // 类型切换
    changeMapType(type) {
      this.mapType = type;
      this.reloadMind();
    },
    reloadMind() {
      var that = this;
      this.options.view.custom_line_render = function ({ ctx, start_point, end_point }) {
        if (this.mapType === 'single') {
          that.drawArrow(ctx, end_point, start_point);
        } else {
          that.drawArrow(ctx, start_point, end_point);
        }
      };
      console.log(this.options.view.custom_line_render);
      this.loadMind();
    },
    drawArrow(ctx, start_point, end_point) {
      let fromX, fromY, toX, toY;
      fromX = end_point.x;
      fromY = end_point.y;
      toX = start_point.x;
      toY = start_point.y;

      var theta = 30,
        headlen = 12,
        width = 2,
        color = '#666';
      // 计算直线中点坐标

      var midX = (fromX + toX) / 2;
      var midY = (fromY + toY) / 2;

      // 计算箭头起点和终点的坐标
      var angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI;
      var angle1 = ((angle + theta) * Math.PI) / 180;
      var angle2 = ((angle - theta) * Math.PI) / 180;

      var topX = headlen * Math.cos(angle1);
      var topY = headlen * Math.sin(angle1);
      var botX = headlen * Math.cos(angle2);
      var botY = headlen * Math.sin(angle2);

      var arrowX, arrowY;

      ctx.beginPath();
      ctx.moveTo(fromX, fromY);
      ctx.lineTo(toX, toY);
      //   ctx.bezierCurveTo(start_point.x + ((end_point.x - start_point.x) * 2) / 3, start_point.y, start_point.x, end_point.y, end_point.x, end_point.y);

      arrowX = midX + topX;
      arrowY = midY + topY;
      ctx.moveTo(arrowX, arrowY);
      ctx.lineTo(midX, midY);

      arrowX = midX + botX;
      arrowY = midY + botY;
      ctx.lineTo(arrowX, arrowY);
      ctx.strokeStyle = color;
      ctx.lineWidth = width;
      ctx.stroke();
    },
    // tab切换
    handleClickTab() {},
    // 配置编辑显示隐藏
    toggleSideEditor(type) {
      this.showSideEditor = type || !this.showSideEditor;
      setTimeout(() => {
        this.reset();
      }, 200);
    },
    // 缩小
    zoomOut() {
      this.jm.view.zoom_out();
    },
    // 放大
    zoomIn() {
      this.jm.view.zoom_in();
    },

    // 重置视图
    reset() {
      this.jm.resize();
    },

    exportImage() {
      let jm = jsMind.current;
      jm.shoot();
    },

    // 循环树结构
    loopTreeData(list, callback) {
      (function doOneFloor(list) {
        if (Array.isArray(list)) {
          for (let i = 0; i < list.length; i++) {
            const item = list[i];
            callback(item, i);
            if (item.children && item.children.length > 0) {
              doOneFloor(item.children);
            }
          }
        }
      })(list);
    },

    // 编辑节点

    // 禁用双击编辑
    stopDBclick() {
      const jmnodes = document.getElementsByTagName('jmnode');
      Object.values(jmnodes).forEach((jmnode) => {
        jmnode.ondblclick = function (e) {
          e.preventDefault();
          e.stopPropagation();
        };
      });
    },

    showTip(event) {
      if (this.showPopover) {
        return;
      }
      this.currentMemo = event?.fromElement?.children[0]?.dataset?.memo || '';
      const el = document.querySelector('.common-tip');
      const width = parseFloat(window.getComputedStyle(el).width);
      const height = parseFloat(window.getComputedStyle(el).height) * 3 + 12;
      const windowHeight = window.innerHeight;
      const windowWidth = window.innerWidth;
      // 极限位置 避免越界
      if (event.clientY + height > windowHeight) {
        this.tipStyle.left = event.clientX + 'px';
        this.tipStyle.top = 'unset';
        this.tipStyle.bottom = 0;
      } else if (event.clientX + width > windowWidth) {
        this.tipStyle.top = event.clientY + 'px';
        this.tipStyle.left = 'unset';
        this.tipStyle.right = 0;
      } else {
        this.tipStyle.left = event.clientX + 'px';
        this.tipStyle.top = event.clientY + 'px';
        this.tipStyle.bottom = 'unset';
      }
      if (this.currentMemo) {
        this.showPopover = true;
      }
    },

    hideTip() {
      this.currentMemo = '';
      this.showPopover = false;
    },

    // 备注绑定点击事件
    tipsClick() {
      const tips = document.getElementsByClassName('tip-icon showTip');
      Object.values(tips).forEach((tip) => {
        tip.removeEventListener('mouseover', this.showTip);
        tip.addEventListener('mouseover', this.showTip);
      });
      Object.values(tips).forEach((tip) => {
        tip.removeEventListener('mouseleave', this.hideTip);
        tip.addEventListener('mouseleave', this.hideTip);
      });
    },

    // 右键点击新增
    rightClickMenu() {
      // 右键菜单
      this.jm.view.add_event(this.editor, 'contextmenu', (e) => {
        const selectedNode = this.jm.get_selected_node();

        if (selectedNode) {
          this.isroot = selectedNode.id === 'root';
          e.preventDefault();
          const el = document.querySelector('.context-menu .el-menu-item');
          let menu = this.$refs.context.$el;

          //   const width = parseFloat(window.getComputedStyle(el).width);
          //   const height = parseFloat(window.getComputedStyle(el).height) * 3 + 12;
          const width = parseFloat(menu.offsetWidth);
          const height = parseFloat(menu.offsetHeight) * 2 + 12;
          const windowHeight = window.innerHeight;
          const windowWidth = window.innerWidth;

          // 极限位置 避免越界
          if (e.clientY + height > windowHeight) {
            this.menuStyle.left = e.clientX + 'px';
            this.menuStyle.top = 'unset';
            this.menuStyle.bottom = 0;
          } else if (e.clientX + width > windowWidth) {
            this.menuStyle.top = e.clientY + 'px';
            this.menuStyle.left = 'unset';
            this.menuStyle.right = 0;
          } else {
            this.menuStyle.left = e.clientX + 20 + 'px';
            this.menuStyle.top = e.clientY + 20 + 'px';
            this.menuStyle.bottom = 'unset';
          }
          this.showMenu = true;
        } else {
          this.showMenu = false;
        }
      });
    },

    // 初始化配置
    init() {
      this.jm.expand_all();

      this.stopDBclick();

      this.tipsClick();

      this.rightClickMenu();
    },
    // 获取选中标签的 ID
    get_selected_nodeid() {
      const selectedNode = this.jm.get_selected_node();
      if (selectedNode) {
        return selectedNode.id;
      } else {
        return null;
      }
    },

    // 切换思维导图结构
    toggleStucture(type) {
      if (this.structure.active === type) return;
      this.structure.active = type;
      switch (type) {
        case 'side':
          // 两边分布
          this.loopTreeData(this.mindData.data.children, (item, i) => {
            item.direction = i % 2 ? 'left' : 'right';
          });
          break;

        case 'left':
          // 向左分布
          this.loopTreeData(this.mindData.data.children, (item) => {
            item.direction = 'left';
          });
          break;

        case 'right':
          // 向右分布
          this.loopTreeData(this.mindData.data.children, (item) => {
            item.direction = 'right';
          });
          break;

        default:
          break;
      }

      this.jm.show(this.mindData);
      this.init();
    },

    // 拖拽
    handleDrop(draggingNode, dropNode) {
      // 前一个兄弟节点
      const prevNode = this.jm.find_node_before(dropNode);
      // 获取移动后的node
      const dragForm = {
        modelId: '',
        treeNum: !prevNode ? draggingNode : prevNode.id,
        thisTreeNum: dropNode,
      };
      console.log('dragForm', dragForm);

      // TODO 调接口
    },
    // 单击重置选中背景颜色
    nodeClick() {
      this.showMenu = false;
      const selectedNode = this.jm.get_selected_node();
      if (selectedNode) {
        console.log('selectedNode', selectedNode);

        this.currentNode = selectedNode;
        this.addTarget.topic = this.currentNode.topic || '';
        this.toggleSideEditor(true);
      }
    },
    // 阻止冒泡
    nodePreventClick() {},

    // 编辑节点 ---------------

    // 改变topic
    changeNodeTopic(val) {
      if (val) {
        this.jm.update_node(this.currentNode.id, val);
        this.tipsClick();
        this.stopDBclick();
      } else {
        this.$message.error('请输入节点标题');
      }
    },
    changeFontWeight() {
      const fontWeight = this.currentNode?.data?.['font-weight'] === 'bold' ? 'normal' : 'bold';
      this.jm.set_node_font_style(this.currentNode.id, null, fontWeight, null);
      let data = this.currentNode.data || {};
      data['font-weight'] = fontWeight;
      this.$set(this.currentNode, 'data', data);
      console.log(this.currentNode);
      this.$forceUpdate();
    },
    changeFontStyle() {
      const fontStyle = this.currentNode?.data?.['font-style'] === 'italic' ? 'normal' : 'italic';
      this.jm.set_node_font_style(this.currentNode.id, null, null, fontStyle);
      let data = this.currentNode.data || {};
      data['font-style'] = fontStyle;
      this.$set(this.currentNode, 'data', data);
      this.$forceUpdate();
    },
    changeTextSize(val) {
      if (val) {
        this.jm.set_node_font_style(this.currentNode.id, val, null, null);
      } else {
        this.$message.error('请选择字体大小');
      }
    },
    // 改变文字颜色
    changeTextColor(val) {
      if (val) {
        this.jm.set_node_color(this.currentNode.id, null, val);
      } else {
        this.$message.error('请选择文字颜色');
      }
    },
    // 改变背景颜色
    changeNodeColor(val) {
      if (val) {
        this.jm.set_node_color(this.currentNode.id, val, null);
      } else {
        this.$message.error('请选择背景颜色');
      }
    },

    // 编辑节点计算公式
    changeNodeMemo(val, id) {
      if (val) {
        this.loopTreeData(this.mindData.data.children, (item, i) => {
          if (item.id === id) {
            item.memo = val;
          }
        });
        this.jm.show(this.mindData);
        this.stopDBclick();
        this.tipsClick();
      } else {
        this.$message.error('请输入节点计算公式');
      }
    },

    // 导入子级
    importChild() {},

    // 插入子级
    addChild() {
      const selectedNode = this.jm.get_selected_node();
      if (selectedNode) {
        let id = utils.uuid();
        this.jm.add_node(selectedNode, id, '新增节点', {
          level: selectedNode.data.level + 1,
          'background-color':
            selectedNode.data.level + 1 > this.predefineColors.length ? this.predefineColors[1] : this.predefineColors[selectedNode.data.level + 1],
        });
        this.getMindData();
        this.jm.select_node(id);
        this.stopDBclick();
        this.nodeClick();
      } else {
        this.$message.error('请选择节点');
      }

      this.showMenu = false;
    },

    addChildByTarget(row) {
      const selectedNode = this.jm.get_selected_node();
      if (selectedNode) {
        let id = utils.uuid();
        this.jm.add_node(selectedNode, id, row.name, {
          level: selectedNode.data.level + 1,
          'background-color':
            selectedNode.data.level + 1 > this.predefineColors.length ? this.predefineColors[1] : this.predefineColors[selectedNode.data.level + 1],
        });
        this.getMindData();
        this.jm.select_node(id);
        this.stopDBclick();
        this.nodeClick();
      } else {
        this.$message.error('请选择节点');
      }
    },

    // 删除卡片
    delCard() {
      const selectedNode = this.jm.get_selected_node();
      if (selectedNode.data) {
        this.jm.remove_node(selectedNode.id);
        this.getMindData();
      } else {
        this.$message.error('请选择节点');
      }
      this.showMenu = false;
    },

    // 获取数据
    getMindData() {
      this.mindData = this.jm.get_data();
      console.log(this.mindData, 'this.dataUpdata');
    },

    // 鼠标滚轮放大缩小
    mouseWheel() {
      if (document.addEventListener) {
        document.addEventListener('domMouseScroll', this.scrollFunc, false);
      }
      this.$refs.container.onmousewheel = this.scrollFunc;
    },

    // 滚轮缩放
    scrollFunc(e) {
      this.showMenu = false;
      e = e || window.event;
      if (e.wheelDelta) {
        if (e.wheelDelta > 0) {
          this.zoomIn();
        } else {
          this.zoomOut();
        }
      } else if (e.detail) {
        if (e.detail > 0) {
          this.zoomIn();
        } else {
          this.zoomOut();
        }
      }
      e.preventDefault();

      this.jm.resize();
    },

    // 鼠标拖拽
    mouseDrag() {
      // 里层
      const el = document.querySelector('.jsmind-inner');
      // 选中节点
      let selected;

      el.onmousedown = (ev) => {
        // 选中节点
        selected = this.jm.get_selected_node();
        // 标识 是否拖拽节点 避免冲突
        this.dragNodeFlag = !!selected;

        const disX = ev.clientX;
        const disY = ev.clientY;
        const originalScrollLeft = el.scrollLeft;
        const originalScrollTop = el.scrollTop;
        const originalScrollBehavior = el.style['scroll-behavior'];
        const originalPointerEvents = el.style['pointer-events'];
        // auto: 默认值，表示滚动框立即滚动到指定位置。
        el.style['scroll-behavior'] = 'auto';
        // 鼠标移动事件是监听的整个document，这样可以使鼠标能够在元素外部移动的时候也能实现拖动
        document.onmousemove = (ev) => {
          if (this.dragNodeFlag) return;
          this.drag = false;
          ev.preventDefault();
          // 计算拖拽的偏移距离
          const distanceX = ev.clientX - disX;
          const distanceY = ev.clientY - disY;

          el.scrollTo(originalScrollLeft - distanceX, originalScrollTop - distanceY);

          // 在鼠标拖动的时候将点击事件屏蔽掉
          el.style['pointer-events'] = 'none';
          el.style.cursor = 'grabbing';
        };
        document.onmouseup = () => {
          if (!this.dragNodeFlag) {
            el.style['scroll-behavior'] = originalScrollBehavior;
            el.style['pointer-events'] = originalPointerEvents;
            el.style.cursor = 'grab';
          }
          document.onmousemove = document.onmouseup = null;
        };
      };
    },

    save() {},
    handleVersionChange(row) {
      const { id = '', name = '', tableClass = '' } = row;
      // 打开新的页面 到 href 这个页面
      const href = this.$router.resolve({
        path: '/arithmeticManage/arithmeticTask/mindMapPage',
        query: { id },
      }).href;
      window.open(href, '_blank');
    },
    tableRowClassName({ row, rowIndex }) {
      if (rowIndex === 1) {
        return 'current-row';
      }
      return '';
    },
  },

  beforeDestroy() {
    document.removeEventListener('domMouseScroll', this.scrollFunc, false);
  },
};
</script>

<style lang="scss" scoped>
@import '@/components/mindMap/mindMapStyle.scss';
</style>

<style lang="scss">
.save-dropdown-menu.el-dropdown-menu--small {
  .save-dropdown-item.el-dropdown-menu__item {
    line-height: 220% !important;
    font-size: 16px !important;
  }
}
</style>
