sprinboot+vue集成neo4j图数据库

一 、java后台

1.1

package com.admin.domain;

/**
 * 功能描述:
 *
 * @author wangwei
 * @date 2024-01-15 22:13
 */
public class ConnectWeb {

    private String connectWebId;

    private String connectWebName;

    private String connectWebInfo;

    private String personWebIdAlpha;

    private String personWebIdBeta;

    private String personWebIdAlphaName;

    private String personWebIdBetaName;

    public String getPersonWebIdAlphaName() {
        return personWebIdAlphaName;
    }

    public void setPersonWebIdAlphaName(String personWebIdAlphaName) {
        this.personWebIdAlphaName = personWebIdAlphaName;
    }

    public String getPersonWebIdBetaName() {
        return personWebIdBetaName;
    }

    public void setPersonWebIdBetaName(String personWebIdBetaName) {
        this.personWebIdBetaName = personWebIdBetaName;
    }

    public String getConnectWebId() {
        return connectWebId;
    }

    public void setConnectWebId(String connectWebId) {
        this.connectWebId = connectWebId;
    }

    public String getConnectWebName() {
        return connectWebName;
    }

    public void setConnectWebName(String connectWebName) {
        this.connectWebName = connectWebName;
    }

    public String getConnectWebInfo() {
        return connectWebInfo;
    }

    public void setConnectWebInfo(String connectWebInfo) {
        this.connectWebInfo = connectWebInfo;
    }

    public String getPersonWebIdAlpha() {
        return personWebIdAlpha;
    }

    public void setPersonWebIdAlpha(String personWebIdAlpha) {
        this.personWebIdAlpha = personWebIdAlpha;
    }

    public String getPersonWebIdBeta() {
        return personWebIdBeta;
    }

    public void setPersonWebIdBeta(String personWebIdBeta) {
        this.personWebIdBeta = personWebIdBeta;
    }

    @Override
    public String toString() {
        return "ConnectWeb{" +
                "connectWebId='" + connectWebId + '\'' +
                ", connectWebName='" + connectWebName + '\'' +
                ", connectWebInfo='" + connectWebInfo + '\'' +
                ", personWebIdAlpha='" + personWebIdAlpha + '\'' +
                ", personWebIdBeta='" + personWebIdBeta + '\'' +
                ", personWebIdAlphaName='" + personWebIdAlphaName + '\'' +
                ", personWebIdBetaName='" + personWebIdBetaName + '\'' +
                '}';
    }
}

1.2

package com.admin.domain;

/**
 * 功能描述:
 *人物属性实体描述
 *
 * @author wangwei
 * @date 2024-01-15 22:12
 */
public class PersonWeb {

    private String personWebId;


    private String personWebName;

    private String personWebPic;

    private String personWebShow;

    private String personWebLink;

    private String personWebPlatform;

    private String personWebField;

    private String personWebInfo;

    private String personWebKey;

    public String getPersonWebId() {
        return personWebId;
    }

    public void setPersonWebId(String personWebId) {
        this.personWebId = personWebId;
    }

    public String getPersonWebName() {
        return personWebName;
    }

    public void setPersonWebName(String personWebName) {
        this.personWebName = personWebName;
    }

    public String getPersonWebPlatform() {
        return personWebPlatform;
    }

    public void setPersonWebPlatform(String personWebPlatform) {
        this.personWebPlatform = personWebPlatform;
    }

    public String getPersonWebField() {
        return personWebField;
    }

    public void setPersonWebField(String personWebField) {
        this.personWebField = personWebField;
    }

    public String getPersonWebInfo() {
        return personWebInfo;
    }

    public void setPersonWebInfo(String personWebInfo) {
        this.personWebInfo = personWebInfo;
    }

    public String getPersonWebKey() {
        return personWebKey;
    }

    public void setPersonWebKey(String personWebKey) {
        this.personWebKey = personWebKey;
    }

    public String getPersonWebPic() {
        return personWebPic;
    }

    public void setPersonWebPic(String personWebPic) {
        this.personWebPic = personWebPic;
    }

    public String getPersonWebShow() {
        return personWebShow;
    }

    public void setPersonWebShow(String personWebShow) {
        this.personWebShow = personWebShow;
    }

    public String getPersonWebLink() {
        return personWebLink;
    }

    public void setPersonWebLink(String personWebLink) {
        this.personWebLink = personWebLink;
    }

    @Override
    public String toString() {
        return "PersonWeb{" +
                "personWebId='" + personWebId + '\'' +
                ", personWebName='" + personWebName + '\'' +
                ", personWebPic='" + personWebPic + '\'' +
                ", personWebShow='" + personWebShow + '\'' +
                ", personWebLink='" + personWebLink + '\'' +
                ", personWebPlatform='" + personWebPlatform + '\'' +
                ", personWebField='" + personWebField + '\'' +
                ", personWebInfo='" + personWebInfo + '\'' +
                ", personWebKey='" + personWebKey + '\'' +
                '}';
    }
}

1.3

package com.admin.controller;

import com.admin.common.core.controller.BaseController;
import com.admin.common.core.domain.AjaxResult;
import com.admin.common.core.page.TableDataInfo;
import com.admin.domain.ConnectWeb;
import com.admin.domain.PersonWeb;
import com.admin.service.WebService;
import com.admin.utils.transport.Result;
import org.neo4j.driver.Record;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 功能描述:
 *
 * @author wangwei
 * @date 2024-01-16 11:09
 */
@RestController
@RequestMapping("/people/web")
public class WebController extends BaseController {

    @Autowired
    private WebService webService;

    @GetMapping("/map")
    public TableDataInfo getPersonWebMap() {
        List<Record> list = webService.selectPersonWebMap();
        return getDataTable(list);
    }

    @GetMapping("/list")
    public TableDataInfo getPersonWebList() {
        List<PersonWeb> list = webService.selectPersonWebList();
        return getDataTable(list);
    }

    @GetMapping("/search/{personWebName}")
    public AjaxResult getPersonWebSearchList(@PathVariable("personWebName") String personWebName) {
        List<PersonWeb> list = webService.selectPersonWebSearchList(personWebName);
        return AjaxResult.success(list);
    }

    @GetMapping("/search/{personWebId}/{personWebName}")
    public AjaxResult getPersonWebSearchListOther(@PathVariable("personWebName") String personWebName, @PathVariable("personWebId") String personWebId) {
        List<PersonWeb> list = webService.selectPersonWebSearchListOther(personWebName, personWebId);
        return AjaxResult.success(list);
    }

    @GetMapping(value = "/person/{personWebId}")
    public AjaxResult getPersonWebInfo(@PathVariable("personWebId") String personWebId) {
        return AjaxResult.success(webService.selectPersonWebById(personWebId));
    }

    @PostMapping("/person")
    public AjaxResult addPersonWeb(@RequestBody PersonWeb personWeb) {
        return toAjax(webService.insertPersonWeb(personWeb));
    }

    @PutMapping("/person")
    public AjaxResult editPersonWeb(@RequestBody PersonWeb personWeb) {
        return toAjax(webService.updatePersonWeb(personWeb));
    }

    @DeleteMapping("/person/{personWebId}")
    public AjaxResult removePersonWeb(@PathVariable String personWebId) {
        try{
            int rsg = webService.deletePersonWeb(personWebId);
            return toAjax(rsg);
        } catch (Exception e){
            return AjaxResult.error(500, "此节点仍与其他节点有关联关系!");
        }
    }

    @GetMapping(value = "/connect/{connectWebId}")
    public AjaxResult getInfoConnectWeb(@PathVariable("connectWebId") String connectWebId) {
        return AjaxResult.success(webService.selectConnectWebById(connectWebId));
    }

    @PostMapping("/connect")
    public AjaxResult addConnectWeb(@RequestBody ConnectWeb connectWeb) {
        return toAjax(webService.insertConnectWeb(connectWeb));
    }

    @PutMapping("/connect")
    public AjaxResult editConnectWeb(@RequestBody ConnectWeb connectWeb) {
        return toAjax(webService.updateConnectWeb(connectWeb));
    }

    @DeleteMapping("/connect/{connectWebId}")
    public AjaxResult removeConnectWeb(@PathVariable String connectWebId) {
        return toAjax(webService.deleteConnectWeb(connectWebId));
    }
}

1.4

package com.admin.service;

import com.admin.domain.ConnectWeb;
import com.admin.domain.PersonWeb;
import org.neo4j.driver.Record;

import java.util.List;

public interface WebService {
    List<Record> selectPersonWebMap();

    public List<PersonWeb> selectPersonWebList() ;

    public List<PersonWeb> selectPersonWebSearchList(String personWebName) ;

    public List<PersonWeb> selectPersonWebSearchListOther(String personWebName, String personWebId) ;

    public PersonWeb selectPersonWebById(String personWebId) ;

    public int insertPersonWeb(PersonWeb personWeb) ;

    public int updatePersonWeb(PersonWeb personWeb) ;

    public int deletePersonWeb(String personWebId) ;

    public ConnectWeb selectConnectWebById(String connectWebId) ;

    public int insertConnectWeb(ConnectWeb connectWeb) ;

    public int updateConnectWeb(ConnectWeb connectWeb) ;

    public int deleteConnectWeb(String connectWebId) ;


}

1.5 

package com.admin.service.impl;

import com.admin.common.annotation.DataSource;
import com.admin.common.enums.DataSourceType;
import com.admin.domain.ConnectWeb;
import com.admin.domain.PersonWeb;
import com.admin.mapper.ConnectWebMapper;
import com.admin.mapper.PersonWebMapper;
import com.admin.service.WebService;
import com.admin.utils.SnowflakeIdWorker;
import org.neo4j.driver.Record;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class WebServiceImpl implements WebService {


    @Autowired
    private PersonWebMapper personWebMapper;

    @Autowired
    private ConnectWebMapper connectWebMapper;

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;



    @DataSource(value = DataSourceType.SLAVE)
    public List<Record> selectPersonWebMap() {
        return personWebMapper.selectPersonWebMap();
    }

    @DataSource(value = DataSourceType.SLAVE)
    public List<PersonWeb> selectPersonWebList() {
        List<PersonWeb> personWebs = personWebMapper.selectPersonWebList();
        return  personWebs;
    }

    @DataSource(value = DataSourceType.SLAVE)
    public List<PersonWeb> selectPersonWebSearchList(String personWebName) {
//        System.out.println(personWebName);
        return personWebMapper.selectPersonWebSearchList(personWebName);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public List<PersonWeb> selectPersonWebSearchListOther(String personWebName, String personWebId) {
//        System.out.println(personWebName);
        return personWebMapper.selectPersonWebSearchListOther(personWebName, personWebId);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public PersonWeb selectPersonWebById(String personWebId) {
        return personWebMapper.selectPersonWebById(personWebId);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public int insertPersonWeb(PersonWeb personWeb) {
        personWeb.setPersonWebId(snowflakeIdWorker.nextId());
        return personWebMapper.insertPersonWeb(personWeb);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public int updatePersonWeb(PersonWeb personWeb) {
        return personWebMapper.updatePersonWeb(personWeb);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public int deletePersonWeb(String personWebId) {
        return personWebMapper.deletePersonWeb(personWebId);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public ConnectWeb selectConnectWebById(String connectWebId) {
        return connectWebMapper.selectConnectWebById(connectWebId);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public int insertConnectWeb(ConnectWeb connectWeb) {
        connectWeb.setConnectWebId(snowflakeIdWorker.nextId());
        return connectWebMapper.insertConnectWeb(connectWeb);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public int updateConnectWeb(ConnectWeb connectWeb) {
        return connectWebMapper.updateConnectWeb(connectWeb);
    }

    @DataSource(value = DataSourceType.SLAVE)
    public int deleteConnectWeb(String connectWebId) {
        return connectWebMapper.deleteConnectWeb(connectWebId);
    }
}

1.6

package com.admin.mapper;

import com.admin.domain.ConnectWeb;
import org.springframework.stereotype.Repository;

/**
 * @author wangwei
 */
@Repository
public interface ConnectWebMapper {

    /**
     * 查询单个连接信息
     *
     * @param connectWebId 连接id
     * @return ConnectWeb实体信息
     */
    ConnectWeb selectConnectWebById(String connectWebId);

    /**
     * 插入单个连接信息
     *
     * @param connectWeb 连接实体
     * @return 插入个数
     */
    int insertConnectWeb(ConnectWeb connectWeb);

    /**
     * 修改单个连接信息
     *
     * @param connectWeb 修改实体
     * @return 插入个数
     */
    int updateConnectWeb(ConnectWeb connectWeb);

    /**
     * 删除单个连接
     *
     * @param connectWebId 连接实体
     * @return 删除个数
     */
    int deleteConnectWeb(String connectWebId);
}

1.7

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/DTD Mapper 3.0" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.admin.mapper.ConnectWebMapper">

    <select id="selectConnectWebById" parameterType="String" resultType="com.admin.domain.ConnectWeb">
        MATCH (m)-[c:ConnectWeb{
        connectWebId: #{connectWebId}
        }]->(n)
        RETURN
        c.connectWebId as connectWebId,
        c.connectWebName as connectWebName,
        c.connectWebInfo as connectWebInfo,
        m.personWebId as personWebIdAlpha,
        m.personWebName as personWebIdAlphaName,
        n.personWebId as personWebIdBeta,
        n.personWebName as personWebIdBetaName
    </select>

    <insert id="insertConnectWeb" parameterType="com.admin.domain.ConnectWeb">
        match(pa:PersonWeb{
        personWebId: #{personWebIdAlpha}
        }),(pb:PersonWeb{
        personWebId: #{personWebIdBeta}
        })
        merge (pa)-[c:ConnectWeb{
        connectWebId: #{connectWebId},
        connectWebName: #{connectWebName},
        connectWebInfo: #{connectWebInfo}
        }]->(pb)
    </insert>

    <update id="updateConnectWeb" parameterType="com.admin.domain.ConnectWeb">
        MATCH (m)-[c:ConnectWeb{
        connectWebId: #{connectWebId}
        }]->(n)
        <trim prefix="SET" suffixOverrides=",">
            <if test="connectWebName != null">c.connectWebName = #{connectWebName},</if>
            <if test="connectWebInfo != null">c.connectWebInfo = #{connectWebInfo},</if>
            <if test="personWebIdAlpha != null">m.personWebId = #{personWebIdAlpha},</if>
            <if test="personWebIdBeta != null">n.personWebId = #{personWebIdBeta},</if>
        </trim>
    </update>

    <delete id="deleteConnectWeb" parameterType="String">
        MATCH ()-[c:ConnectWeb{
        connectWebId: #{connectWebId}
        }]-()
        DELETE c
    </delete>

</mapper>

1.8 maven 


        <!--手动添加-->
        <!--neo4j-jdbc-driver-->
        <dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-jdbc-driver</artifactId>
            <version>4.0.1</version>
        </dependency>

1.9 数据库配置

      #TODO 从库数据源 neo4j
            slave:
                # 从数据源开关/默认关闭
                enabled: true
                url: jdbc:neo4j:bolt://127.0.0.1:1273
                username: neo4j
                password: neo4j
                driverClassName: org.neo4j.jdbc.bolt.BoltDriver


                         #TODO NEO4J 配置检测连接是否有效
            validationQuery: match (n) return id(n) limit 2

二、vue前台

2.1

<template>
  <div class="app-container">
    <div class="echarts">
      <div class="bin" id="main"></div>
    </div>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
        >新增成员
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          icon="el-icon-edit"
          size="mini"
          :disabled="single"
          @click="handleUpdate"
        >修改成员
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          icon="el-icon-plus"
          size="mini"
          @click="handleAddConnect"
        >新增关系
        </el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="refresh"></right-toolbar>
    </el-row>
    <el-table v-loading="loading" :data="personList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center"/>
      <el-table-column label="成员昵称" align="center" prop="personWebName" :show-overflow-tooltip="true">
        <template slot-scope="scope">
          <a v-if="scope.row.personWebLink" target="_blank" :href="scope.row.personWebLink" class="link-type"
             style="margin-right: 10px;">
            <span>{{ scope.row.personWebName }}</span>
          </a>
          <span v-else>{{ scope.row.personWebName }}</span>
        </template>
      </el-table-column>
      <el-table-column label="成员简介" align="center" prop="personWebInfo" :show-overflow-tooltip="true"/>
      <el-table-column label="成员头像" align="center">
        <template slot-scope="scope">
          <img :src="person_pic_url + scope.row.personWebPic" alt="" class="pic-in-list">
        </template>
      </el-table-column>
      <el-table-column label="活跃平台" align="center" prop="personWebPlatform" :formatter="personPlatformFormat">
      </el-table-column>
      <el-table-column label="常驻领域" align="center" prop="personWebField">
        <template slot-scope="scope">
          <el-tag v-for="ikey in scope.row.personWebField" :key="ikey" type="success" style="margin: 10px;">
            {{ikey}}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="沟通要旨" align="center" prop="personWebKey" :show-overflow-tooltip="true"/>
      <el-table-column label="是否展示" align="center" width="100" prop="personWebShow" :formatter="personShowFormat">
        <template slot-scope="scope">
          <el-tag :type="scope.row.personWebShow | statusFilter">
            {{ scope.row.personWebShow | statusShowFilter}}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
          >修改
          </el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-delete"
            @click="handleDelete(scope.row)"
          >删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-dialog :visible.sync="openConnect" width="600px" append-to-body :title="titleConnect">
      <el-form ref="formConnect" :model="formConnect" :rules="rulesConnect" size="medium" label-width="100px">
        <el-row type="flex" justify="start" align="top">
          <el-col :span="12">
            <el-form-item
              label="关联上级"
              prop="personWebIdAlpha"
              :rules="requireFlag ? rulesConnect.personWebIdAlpha:[{
                required: false
               }]"
            >
              <el-select
                :disabled="!requireFlag"
                v-model="formConnect.personWebIdAlpha"
                class="filter-item"
                filterable
                remote
                reserve-keyword
                clearable
                :placeholder="formConnect.personWebIdAlphaName"
                :remote-method="remoteMethodStart"
                :loading="selectLoading" value="">
                <el-option
                  v-for="item in optionsStart"
                  :key="item.personWebId"
                  :label="item.personWebName"
                  :value="item.personWebId">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item
              label="关联下属"
              prop="personWebIdBeta"
              :rules="requireFlag ? rulesConnect.personWebIdBeta:[{
                required: false
              }]"
            >
              <el-select
                :disabled="!requireFlag"
                v-model="formConnect.personWebIdBeta"
                class="filter-item"
                filterable
                remote
                reserve-keyword
                clearable
                :placeholder="formConnect.personWebIdBetaName"
                :remote-method="remoteMethodEnd"
                :loading="selectLoading" value="">
                <el-option
                  v-for="item in optionsEnd"
                  :key="item.personWebId"
                  :label="item.personWebName"
                  :value="item.personWebId">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="关联关系" prop="connectWebName">
          <el-input v-model="formConnect.connectWebName" placeholder="请输入关联关系" clearable :style="{width: '100%'}">
          </el-input>
        </el-form-item>
        <el-form-item label="关联信息" prop="connectWebInfo">
          <el-input v-model="formConnect.connectWebInfo" type="textarea" placeholder="请输入关联信息"
                    :autosize="{minRows: 4, maxRows: 4}" :style="{width: '100%'}"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button v-if="!requireFlag" type="danger" @click="deleteConnect">删除</el-button>
        <el-button @click="cancelConnect">取消</el-button>
        <el-button type="primary" @click="handelConfirm">确定</el-button>
      </div>
    </el-dialog>

    <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="成员昵称" prop="personWebName">
          <el-input v-model="form.personWebName" placeholder="请输入成员昵称"/>
        </el-form-item>
        <el-form-item label="成员简介" prop="personWebInfo">
          <el-input v-model="form.personWebInfo" type="textarea" placeholder="请输入成员简介"/>
        </el-form-item>
        <el-form-item label="跳转链接" prop="personWebLink">
          <el-input v-model="form.personWebLink" placeholder="请输入跳转链接"/>
        </el-form-item>
        <el-form-item label="成员头像" prop="personWebPic">
          <el-button v-show="!form.personWebPic" type="primary" size="mini" @click="imageCropperShow()">
            上传图片
          </el-button>
          <el-button v-show="form.personWebPic" type="primary" size="mini" @click="imageCropperShow()">
            更新图片
          </el-button>
          <el-button v-show="form.personWebPic" type="primary" size="mini" @click="picShow(form.personWebPic)">
            预览
          </el-button>
        </el-form-item>

        <el-form-item label="活跃平台">
          <el-checkbox-group v-model="form.personWebPlatform">
            <el-checkbox
              v-for="dict in personWebPlatformOptions"
              :key="dict.dictValue"
              :label="dict.dictValue">
              {{dict.dictLabel}}
            </el-checkbox>
          </el-checkbox-group>
        </el-form-item>

        <el-form-item label="常驻领域" prop="personWebField">
          <el-tag
            :key="index"
            v-for="(tag, index) in form.personWebField"
            closable
            :disable-transitions="false"
            @close="handleClose(tag)">
            {{tag}}
          </el-tag>
          <el-input
            class="input-new-tag"
            v-if="inputVisible"
            v-model="inputValue"
            ref="saveTagInput"
            size="small"
            @keyup.enter.native="handleInputConfirm"
            @blur="handleInputConfirm"
          >
          </el-input>
          <el-button v-else class="button-new-tag" size="small" @click="showInput">+ 新标签</el-button>
        </el-form-item>

        <el-form-item label="沟通要旨" prop="personWebInfo">
          <el-input v-model="form.personWebKey" type="textarea" placeholder="请输入沟通要旨"/>
        </el-form-item>

        <el-form-item label="是否展示">
          <el-radio-group v-model="form.personWebShow">
            <el-radio
              v-for="dict in personWebShowOptions"
              :key="dict.dictValue"
              :label="dict.dictValue"
            >{{dict.dictLabel}}
            </el-radio>
          </el-radio-group>
        </el-form-item>

      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>

    <my-upload
      method="POST"
      field="file"
      v-model="upload.cropperShow"
      :headers="upload.headers"
      :width=300
      :height=300
      :url="this.upload.logo_url"
      lang-type='zh'
      img-format='jpg'
      img-bgc='#FFF'
      :no-circle=true
      @crop-upload-success="cropUploadSuccess">
    </my-upload>

    <el-dialog title="图片预览" :visible.sync="picVisible" width="500px" center>
      <div style="text-align: center">
        <img :src="answerPicImageUrl" alt="" class="pic-in-dialog">
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="picVisible = false">确定</el-button>
      </span>
    </el-dialog>

  </div>

</template>

<script>
  // import graph from '@/assets/binray/les-miserables';
  import {
    getPersonWebMap,
    getPersonWebList,
    getPersonWebSearch,
    getPersonWebInfo,
    addPersonWeb,
    editPersonWeb,
    removePersonWeb,
    getInfoConnectWeb,
    addConnectWeb,
    editConnectWeb,
    removeConnectWeb,
    getPersonWebSearchOther
  } from '@/api/person';
  import 'babel-polyfill'; // es6 shim
  import myUpload from 'vue-image-crop-upload/upload-2';

  export default {
    name: 'Echarts',
     components: {myUpload},
    filters: {
      statusShowFilter(status) {
        const statusMap = {
          0: '正常',
          1: '已下线',
        }
        return statusMap[status]
      },
      statusFilter(status) {
        const statusMap = {
          0: 'success',
          1: 'warning',
        }
        return statusMap[status]
      }
    },
    data() {
      return {
        // 新增or更新,新增为true,更新为false
        requireFlag: false,
        myChart: undefined,
        // 表单参数
        form: {},
        formConnect: {},
        // 表单校验
        rules: {
          personWebName: [{
            required: true,
            message: '成员名称为必填项',
            trigger: 'blur'
          }],
         /* personWebPic: [{
            required: true,
            message: '成员头图为必填项',
            trigger: 'change'
          }],*/
          personWebShow: [{
            required: true,
            message: '是否展示为必填项',
            trigger: 'change'
          }],
        },
        rulesConnect: {
          personWebIdAlpha: [{
            required: true,
            message: '',
            trigger: 'blur'
          }],
          personWebIdBeta: [{
            required: true,
            message: '',
            trigger: 'blur'
          }],
          connectWebName: [{
            required: true,
            message: '请输入关联关系',
            trigger: 'blur'
          }],
          connectWebInfo: [{
            required: true,
            message: '请输入关联信息',
            trigger: 'blur'
          }],
        },
        selectLoading: false,
        optionsStart: [],
        optionsEnd: [],
        personList: [],
        personMap: [],
        // 临时标签列表
        personWebPlatformTemp: undefined,
        personWebFieldTemp: undefined,
        // 路径
        person_pic_url: process.env.VUE_APP_BASE_API + "/File/upload/nosql/",
        //D:\File\upload\nosql
        // 图片预览框
        picVisible: false,
        // 拼接
        answerPicImageUrl: "",
        // 路径
        // 遮罩层
        loading: true,
        // 选中数组
        ids: [],
        // 非单个禁用
        single: true,
        // 非多个禁用
        multiple: true,
        // 显示搜索条件
        showSearch: true,
        // 总条数
        total: 0,
        upload: {
          // 显示上传图片的弹出框
          cropperShow: false,
          // 图标路径
          logo_url: process.env.VUE_APP_BASE_API + "/common/upload",
        },
        // 弹出层标题
        title: "",
        titleConnect: "",
        // 是否显示弹出层
        open: false,
        openConnect: false,
        inputVisible: false,
        // 具体内容
        inputValue: '',
        personWebShowOptions: [],
        personWebPlatformOptions: [],
        searchQueryParams: {
          // 这个一定得有
          personWebIdStart: null,
          // 这个可有可无
          personWebIdEnd: null,
        },
        graph: {
          nodes: [],
          links: []
        },
        mapCheckList: []
      }
    },
    created() {
      this.getList();
      this.personWebShowOptions = [{
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-02-21 19:29:04",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 124,
        "dictSort": 0,
        "dictLabel": "已上架",
        "dictValue": "0",
        "dictType": "material_public",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-02-21 19:29:39",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 125,
        "dictSort": 1,
        "dictLabel": "未发布",
        "dictValue": "1",
        "dictType": "material_public",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }];
      this.personWebPlatformOptions = [{
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:20:51",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 135,
        "dictSort": 0,
        "dictLabel": "哔哩哔哩",
        "dictValue": "0",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:21:03",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 136,
        "dictSort": 1,
        "dictLabel": "今日头条",
        "dictValue": "1",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:21:12",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 137,
        "dictSort": 2,
        "dictLabel": "抖音",
        "dictValue": "2",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:21:21",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 138,
        "dictSort": 3,
        "dictLabel": "西瓜视频",
        "dictValue": "3",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:21:29",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 139,
        "dictSort": 4,
        "dictLabel": "YouTube",
        "dictValue": "4",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:22:06",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 140,
        "dictSort": 5,
        "dictLabel": "知乎",
        "dictValue": "5",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:22:17",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 141,
        "dictSort": 6,
        "dictLabel": "小红书",
        "dictValue": "6",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:22:27",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 142,
        "dictSort": 7,
        "dictLabel": "快手",
        "dictValue": "7",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:22:49",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 143,
        "dictSort": 8,
        "dictLabel": "Acfun",
        "dictValue": "8",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:23:05",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 144,
        "dictSort": 9,
        "dictLabel": "网易云音乐",
        "dictValue": "9",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:23:34",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 145,
        "dictSort": 10,
        "dictLabel": "豆瓣",
        "dictValue": "10",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:23:52",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 146,
        "dictSort": 11,
        "dictLabel": "微博",
        "dictValue": "11",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:24:34",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 147,
        "dictSort": 12,
        "dictLabel": "新片场",
        "dictValue": "12",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }, {
        "searchValue": null,
        "createBy": "admin",
        "createTime": "2021-03-26 02:24:50",
        "updateBy": null,
        "updateTime": null,
        "remark": null,
        "params": {},
        "dictCode": 148,
        "dictSort": 13,
        "dictLabel": "图虫",
        "dictValue": "13",
        "dictType": "media_platform",
        "cssClass": null,
        "listClass": null,
        "isDefault": "N",
        "status": "0",
        "default": false
      }]
    },
    methods: {
      myEcharts() {
        const that = this;
        this.myChart.showLoading();

        this.graph.nodes.forEach(function (node) {
          node.label = {
            show: true
          };
        });
        const option = {
          title: {
            text: '',
            subtext: '',
            top: 'bottom',
            left: 'right'
          },
          tooltip: {
            trigger: "item",
            // textStyle: {
            //   width: 10,
            //   fontWeight: "bold",
            //   overflow: "truncate"
            // },
            confine: 'true',
            formatter: function (param) {
              if (param.dataType === 'edge') {
                // 连接
                return [
                  '关系:' + param.data["connectWebName"] + '<br/>',
                  '详情:' + param.data["connectWebInfo"] + '<br/>'
                ].join('');
              } else if (param.dataType === 'node') {
                // 处理标签
                let graphTag = '';
                const arr1 = JSON.parse(param.data["personWebField"]);
                for (let i = 0; i < arr1.length; i++) {
                  if (i === 0) {
                    graphTag = `<span style="
                      display: inline-block;
                      border-radius: 4px;
                      min-width: min-content;
                      padding: 0 10px;
                      margin: 5px;
                      background-color: #e7faf0;
                      border-color: #d0f5e0;
                      color: #13ce66;
                      border-width: 1px;
                      border-style: solid;
                    ">${arr1[i]}</span>`
                  } else {
                    graphTag = graphTag + `<span style="
                      display: inline-block;
                      border-radius: 4px;
                      min-width: min-content;
                      padding: 0 10px;
                      margin: 5px;
                      background-color: #e7faf0;
                      border-color: #d0f5e0;
                      color: #13ce66;
                      border-width: 1px;
                      border-style: solid;
                    ">${arr1[i]}</span>`;
                  }
                }
                // 处理字典
                let graphDict = '';
                const arrTemp = that.selectDictLabel(that.personWebPlatformOptions, JSON.parse(param.data["personWebPlatform"]));
                const arr2 = arrTemp.split(', ')
                for (let i = 0; i < arr2.length; i++) {
                  if (i === 0) {
                    graphDict = `<span style="
                      display: inline-block;
                      border-radius: 4px;
                      min-width: min-content;
                      padding: 0 10px;
                      margin: 5px;
                      background-color: #faece7;
                      border-color: #f5dad0;
                      color: #ff7d27;
                      border-width: 1px;
                      border-style: solid;
                    ">${arr2[i]}</span>`
                  } else {
                    graphDict = graphDict + `<span style="
                      display: inline-block;
                      border-radius: 4px;
                      min-width: min-content;
                      padding: 0 10px;
                      margin: 5px;
                      background-color: #faece7;
                      border-color: #f5dad0;
                      color: #ff7d27;
                      border-width: 1px;
                      border-style: solid;
                    ">${arr2[i]}</span>`;
                  }
                }
                // 节点
                return [
                  '<div style="text-align:left;max-width:1000px;">昵称:' + param.data["name"] + '<br/>',
                  '<div style="display:block;word-break: break-all;word-wrap: break-word;white-space: pre-line;">简介:' + param.data["personWebInfo"] + '</div>',
                  '常驻领域:' + graphTag + '<br/>',
                  '活跃平台:' + graphDict + '</div><br/>',
                ].join('');
              }

            }
          },
          legend: [],
          animationDuration: 150,
          animationEasingUpdate: 'quinticInOut',
          series: [
            {
              name: '',
              type: 'graph',
              layout: "force",
              force: {
                repulsion: 200,
                edgeLength: 100,
                gravity: 0.2
              },
              symbolSize: 50,
              data: this.graph.nodes,
              links: this.graph.links,
              // data: graph.nodes,
              // links: graph.links,
              roam: true,
              label: {
                show: true,
              },
              draggable: true,

              labelLayout: {
                hideOverlap: false
              },
              lineStyle: {
                color: 'source',
                curveness: 0.3
              },
              emphasis: {
                focus: 'adjacency',
                lineStyle: {
                  width: 10
                }
              }
            }
          ]
        };
        this.myChart.clear();
        option && this.myChart.setOption(option, true);
        // console.log(option)
        this.myChart.hideLoading();
        this.myChart.on("click", function (e) {
          if (e.dataType === 'edge') {
            that.handleUpdateConnect(e.data)
          } else if (e.dataType === 'node') {
            console.log(e)
            e.data.personWebId = e.data.id
            that.handleUpdate(e.data)
          }
        })
      },
      getList() {
        this.loading = true;
        getPersonWebList().then(response => {
          this.personList = response.rows;
          Object.keys(this.personList).forEach(key => {
            this.personList[key].personWebPlatform = JSON.parse(this.personList[key].personWebPlatform)
            this.personList[key].personWebField = JSON.parse(this.personList[key].personWebField)
          });
          this.loading = false;
        });
      },
      async getMap() {

        this.loading = true;
        await getPersonWebMap().then(response => {
          this.graph = {
            nodes: [],
            links: []
          };
          this.mapCheckList = [];
          this.personMap = response.rows;
          Object.keys(this.personMap).forEach(key => {
            // 导入节点,列表为空表示首次加入元素,反之亦然
            if (this.graph.nodes !== []) {
              // 如果导入过就不用重复导入了
              if (!this.mapCheckList.includes(this.personMap[key].PersonAlpha.personWebId)) {
                this.pushAlpha(key);
              }
              if (!this.mapCheckList.includes(this.personMap[key].PersonBeta.personWebId)) {
                this.pushBeta(key);
              }
            } else {
              this.pushAlpha(key);
              this.pushBeta(key);
            }
            // 把导入过的节点id存进checkList
            this.mapCheckList.push(this.personMap[key].PersonAlpha.personWebId)
            this.mapCheckList.push(this.personMap[key].PersonBeta.personWebId)
            // 导入关系
            this.pushConnect(key);
          });
        });
        // console.log(this.graph)
        this.loading = false;
      },
      pushAlpha(key) {

        this.graph.nodes.push({
          id: this.personMap[key].PersonAlpha.personWebId,
          name: this.personMap[key].PersonAlpha.personWebName,
          personWebPic: this.personMap[key].PersonAlpha.personWebPic,
          personWebShow: this.personMap[key].PersonAlpha.personWebShow,
          personWebLink: this.personMap[key].PersonAlpha.personWebLink,
          personWebPlatform: this.personMap[key].PersonAlpha.personWebPlatform,
          personWebField: this.personMap[key].PersonAlpha.personWebField,
          personWebInfo: this.personMap[key].PersonAlpha.personWebInfo,
          personWebKey: this.personMap[key].PersonAlpha.personWebKey,
        })
      },
      pushBeta(key) {
        this.graph.nodes.push({
          id: this.personMap[key].PersonBeta.personWebId,
          name: this.personMap[key].PersonBeta.personWebName,
          personWebPic: this.personMap[key].PersonBeta.personWebPic,
          personWebShow: this.personMap[key].PersonBeta.personWebShow,
          personWebLink: this.personMap[key].PersonBeta.personWebLink,
          personWebPlatform: this.personMap[key].PersonBeta.personWebPlatform,
          personWebField: this.personMap[key].PersonBeta.personWebField,
          personWebInfo: this.personMap[key].PersonBeta.personWebInfo,
          personWebKey: this.personMap[key].PersonBeta.personWebKey,
        })
      },
      pushConnect(key) {
        this.graph.links.push({
          source: this.personMap[key].PersonAlpha.personWebId,
          target: this.personMap[key].PersonBeta.personWebId,
          connectWebId: this.personMap[key].Connect.connectWebId,
          connectWebName: this.personMap[key].Connect.connectWebName,
          connectWebInfo: this.personMap[key].Connect.connectWebInfo,
        })
      },

      // 字典翻译
      personShowFormat(row, column) {
        return this.selectDictLabel(this.personWebShowOptions, row.personWebShow);
      },
      personPlatformFormat(row, column) {
        return this.selectDictLabel(this.personWebPlatformOptions, row.personWebPlatform);
      },
      // 取消按钮
      cancel() {
        this.open = false;
        this.reset();
      },
      // 取消按钮
      cancelConnect() {
        this.openConnect = false;
        this.resetConnect();
      },
      // 表单重置
      reset() {
        this.form = {
          personWebId: null,
          personWebName: null,
          personWebPic: null,
          personWebShow: "0",
          personWebLink: "",
          personWebPlatform: [],
          personWebField: [],
          personWebInfo: "",
          personWebKey: ""
        };
        this.answerPicImageUrl = null;
        this.resetForm("form");
      },

      resetConnect() {
        this.formConnect = {
          personWebIdAlpha: null,
          personWebIdBeta: null,
          personWebIdAlphaName: null,
          personWebIdBetaName: null,
          connectWebId: null,
          connectWebName: null,
          connectWebInfo: null,
        };
        this.resetForm("formConnect");
      },

      handleAddConnect() {
        this.optionsStart = []
        this.optionsEnd = []
        this.requireFlag = true;
        this.resetConnect();
        this.openConnect = true;
        this.titleConnect = "添加成员关系";
      },

      /** 修改按钮操作 */
      handleUpdateConnect(row) {
        this.optionsStart = []
        this.optionsEnd = []
        this.requireFlag = false;
        this.reset();
        const connectWeb = row.connectWebId;
        getInfoConnectWeb(connectWeb).then(response => {
          this.formConnect = response.data;
          // console.log(this.formConnect)
          this.formConnect.personWebIdAlpha = null;
          this.formConnect.personWebIdBeta = null;
          this.openConnect = true;
          this.titleConnect = "修改成员关系";
        });
      },

      // 多选框选中数据
      handleSelectionChange(selection) {
        this.ids = selection.map(item => item.personWebId)
        this.single = selection.length !== 1
        this.multiple = !selection.length
      },

      remoteMethodStart(keyword) {
        if (keyword.trim() === '') {
          this.optionsStart = []
          return
        }
        // 当后一个对象不为空的情况
        if (this.formConnect.personWebIdBeta) {
          let others = [];
          this.selectLoading = true;
          getPersonWebSearch(keyword).then(data => {
            getPersonWebSearchOther(this.formConnect.personWebIdBeta, keyword).then(dataOther => {
              others = dataOther.rows;
              this.optionsStart = [];
              data.rows.forEach(ma => {
                let exist = others.some(sa => {
                  return ma.personWebId === sa.personWebId
                });
                if (!exist) {
                  this.optionsStart.push(ma);
                }
              });
              this.optionsStart = this.optionsStart.filter(item => item.personWebId !== this.formConnect.personWebIdBeta)
            })
            this.selectLoading = false;
          })
        }
        // 后一个对象为空时
        else {
          this.selectLoading = true;
          getPersonWebSearch(keyword).then(data => {
            this.selectLoading = false;
            this.optionsStart = data.rows;
          })
        }
      },
      remoteMethodEnd(keyword) {
        if (keyword.trim() === '') {
          this.optionsEnd = []
          return
        }
        // 当前一个对象不为空的情况
        if (this.formConnect.personWebIdAlpha) {
          let others = [];
          this.selectLoading = true;
          getPersonWebSearch(keyword).then(data => {
            getPersonWebSearchOther(this.formConnect.personWebIdAlpha, keyword).then(dataOther => {
              others = dataOther.rows;
              this.optionsEnd = [];
              data.rows.forEach(ma => {
                let exist = others.some(sa => {
                  return ma.personWebId === sa.personWebId
                });
                if (!exist) {
                  this.optionsEnd.push(ma);
                }
              });
              this.optionsEnd = this.optionsEnd.filter(item => item.personWebId !== this.formConnect.personWebIdAlpha)
            })
            this.selectLoading = false;
          })
        }
        // 前一个对象为空时
        else {
          this.selectLoading = true;
          getPersonWebSearch(keyword).then(data => {
            this.selectLoading = false;
            this.optionsEnd = data.rows;
          })
        }
      },
      /** 新增按钮操作 */
      handleAdd() {
        this.reset();
        this.open = true;
        this.title = "添加成员管理";
      },
      /** 修改按钮操作 */
      handleUpdate(row) {
        this.reset();
        const personWeb = row.personWebId || this.ids;
        getPersonWebInfo(personWeb).then(response => {
          this.form = response.data;
          this.personWebPlatformTemp = this.form.personWebPlatform;
          this.form.personWebPlatform = JSON.parse(this.personWebPlatformTemp);
          this.personWebFieldTemp = this.form.personWebField;
          this.form.personWebField = JSON.parse(this.personWebFieldTemp);
          this.open = true;
          this.title = "修改成員管理";
        });
      },
      submitForm() {
        this.$refs["form"].validate(valid => {
          if (valid) {
            this.open = false;
            this.personWebPlatformTemp = this.form.personWebPlatform;
            this.form.personWebPlatform = JSON.stringify(this.personWebPlatformTemp);
            this.personWebFieldTemp = this.form.personWebField;
            this.form.personWebField = JSON.stringify(this.personWebFieldTemp);
            if (this.form.personWebId != null) {
              editPersonWeb(this.form).then(response => {
                if (response.code === 200) {
                  this.msgSuccess("修改成功");
                  this.refresh();
                }
              });
            } else {
              addPersonWeb(this.form).then(response => {
                if (response.code === 200) {
                  this.msgSuccess("新增成功");
                  this.refresh();
                }
              });
            }
          }
        });
      },

      handelConfirm() {
        this.$refs["formConnect"].validate(valid => {
          if (valid) {
            this.openConnect = false;
            if (this.formConnect.connectWebId != null) {
              editConnectWeb(this.formConnect).then(response => {
                if (response.code === 200) {
                  this.msgSuccess("修改成功");
                  this.refresh();
                }
              });
            } else {
              addConnectWeb(this.formConnect).then(response => {
                if (response.code === 200) {
                  this.msgSuccess("新增成功");
                  this.refresh();
                }
              });
            }
          }
        });
      },
      deleteConnect() {
        const connectWebId = this.formConnect.connectWebId
        this.$confirm('是否确认删除「' + this.formConnect.personWebIdAlphaName + '」和「' + this.formConnect.personWebIdBetaName + '」的关系?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(function () {
          return removeConnectWeb(connectWebId);
        }).then(() => {
          this.openConnect = false;
          this.refresh();
          this.msgSuccess("删除成功");
        }).catch(function (e) {
          console.log(e)
        });
      },
      /** 删除按钮操作 */
      handleDelete(row) {
        const personWebIds = row.personWebId || this.ids;
        this.$confirm('是否确认删除成员编号为"' + personWebIds + '"的数据项?', "警告", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(function () {
          return removePersonWeb(personWebIds);
        }).then(() => {
          this.refresh();
          this.msgSuccess("删除成功");
        }).catch(function () {
        });
      },
      // 显示图片上传模块
      imageCropperShow() {
        this.upload.cropperShow = !this.upload.cropperShow
      },
      // 图片上传成功后执行
      cropUploadSuccess(jsonData, field) {
        this.form.personWebPic = jsonData.fileName
        // console.log(jsonData)
      },
      picShow(pic) {
        this.picVisible = !this.picVisible;
        this.answerPicImageUrl = this.person_pic_url + pic
      },
      handleClose(tag) {
        this.form.personWebField.splice(this.form.personWebField.indexOf(tag), 1);
      },
      showInput() {
        this.inputVisible = true;
        this.$nextTick(_ => {
          this.$refs.saveTagInput.$refs.input.focus();
        });
      },
      handleInputConfirm() {
        let inputValue = this.inputValue;
        if (inputValue) {
          this.form.personWebField.push(inputValue);
        }
        this.inputVisible = false;
        this.inputValue = '';
      },
      async refresh() {
        await this.getMap();
        this.myEcharts();
        this.getList()
      },
    },

    async mounted() {
      await this.getMap();
      // 基于准备好的dom,初始化echarts实例
      let echarts = require('echarts')
      this.myChart = echarts.init(document.getElementById('main'));
      this.myEcharts();
    }
  }
</script>


<style lang="scss" scoped>

  .avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    width: 178px;
    height: 178px;
  }

  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }

  .avatar-uploader-icon {
    line-height: 140px;
  }

  .avatar {
    height: 144px;
  }

  .image-preview {
    width: 178px;
    height: 178px;
    position: relative;
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    float: left;
  }

  .image-preview .image-preview-wrapper {
    position: relative;
    width: 100%;
    height: 100%;
  }

  .image-preview .image-preview-wrapper img {
    width: 100%;
    height: 100%;
  }

  .image-preview .image-preview-action {
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
    text-align: center;
    color: #fff;
    opacity: 0;
    font-size: 20px;
    background-color: rgba(0, 0, 0, .5);
    transition: opacity .3s;
    cursor: pointer;
    line-height: 200px;
  }

  .image-preview .image-preview-action .el-icon-delete {
    font-size: 32px;
  }

  .image-preview:hover .image-preview-action {
    opacity: 1;
  }

  .el-upload--picture-card {
    display: block;
    width: 258px;
    height: 146px;
    overflow: hidden;
  }

  .input-new-tag {
    width: 90px;
    margin-left: 10px;
    vertical-align: bottom;
  }

  .el-tag + .el-tag {
    margin-left: 10px;
  }

  .button-new-tag {
    margin-left: 10px;
    height: 32px;
    line-height: 30px;
    padding-top: 0;
    padding-bottom: 0;
  }

  .echarts {
    width: 100%;
    text-align: center;
    height: 800px;
  }

  .bin {
    /*text-align: center;*/
    /*padding: 50px;*/
    width: 100%;
    height: 800px
  }

  .dashboard-editor-container {
    padding: 32px;
    background-color: rgb(240, 242, 245);
    position: relative;

    .chart-wrapper {
      background: #fff;
      padding: 16px 16px 0;
      margin-bottom: 32px;
    }
  }

  .graph-tag {
    display: inline-block;
    border-radius: 4px;
    min-width: min-content;
    padding: 5px;
    background-color: #e7faf0;
    border-color: #d0f5e0;
    color: #13ce66;
  }

  @media (max-width: 1024px) {
    .chart-wrapper {
      padding: 8px;
    }
  }

</style>

2.2 

import request from '@/utils/request'

export function getPersonWebMap() {
  return request({
    url: '/people/web/map',
    method: 'get'
  })
}

export function getPersonWebList() {
  return request({
    url: '/people/web/list',
    method: 'get'
  })
}

export function getPersonWebSearch(personName) {
  return request({
    url: '/people/web/search/' + personName,
    method: 'get'
  })
}

export function getPersonWebSearchOther(personId, personName) {
  return request({
    url: '/people/web/search/' + personId + '/' + personName,
    method: 'get'
  })
}

export function getPersonWebInfo(personId) {
  return request({
    url: '/people/web/person/' + personId,
    method: 'get'
  })
}

export function addPersonWeb(data) {
  return request({
    url: '/people/web/person',
    method: 'post',
    data: data
  })
}

export function editPersonWeb(data) {
  return request({
    url: '/people/web/person',
    method: 'put',
    data: data
  })
}

export function removePersonWeb(personId) {
  return request({
    url: '/people/web/person/' + personId,
    method: 'delete'
  })
}

export function getInfoConnectWeb(connectId) {
  return request({
    url: '/people/web/connect/' + connectId,
    method: 'get'
  })
}

export function addConnectWeb(data) {
  return request({
    url: '/people/web/connect',
    method: 'post',
    data: data
  })
}

export function editConnectWeb(data) {
  return request({
    url: '/people/web/connect',
    method: 'put',
    data: data
  })
}

export function removeConnectWeb(connectId) {
  return request({
    url: '/people/web/connect/' + connectId,
    method: 'delete'
  })
}

三、展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/558914.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

指针专题(2)

前言 上一节我们学习了指针的相关内容&#xff0c;本节我们继续学习指针专题&#xff0c;更加深入的了解指针&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 1.对数组名的深入理解 在上一节的内容中&#xff0c;我们提到了用指针来访问数组的操作&#xff0c…

昂科烧录器支持Nuvoton新唐科技的低功耗微控制器M482SIDAE

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中Nuvoton新唐科技的低功耗微控制器M482SIDAE已经被昂科的通用烧录平台AP8000所支持。 M482SIDAE以Arm Cortex-M4F为核心&#xff0c;是带有DSP指令集的高效能低功耗微控制器。其…

Mybatis的注解开发

1、概述 mybatis中也提供了注解式开发方式&#xff0c;采用注解可以减少Sql映射文件的配置。 使用注解式开发的话&#xff0c;sql语句是写在java程序中的&#xff0c;这种方式也给sql语句的维护带来成本。 使用注解来映射简单语句会使代码显得更加简洁&#xff0c;但对于稍微…

ASP.NET基于WEB的工作计划流程管理系统的设计与实现

摘 要 信息技术的飞速发展&#xff0c;尤其是网络通讯技术、数据库技术及自动化技术的日新月异&#xff0c;为单位、企业的办公带来了极大的便利。但是由于单位、企业的工作性质众多&#xff0c;工作流程各有差异&#xff0c;企业、单位、部门之间的管理机制各不相同&#xf…

OpenHarmony实战开发-Web自定义长按菜单案例。

介绍 本示例介绍了给Webview页面中可点击元素&#xff08;超链接/图片&#xff09;绑定长按/鼠标右击时的自定义菜单的方案。 效果预览图 使用说明 长按Web页面中的图片或者链接元素&#xff0c;弹出自定义的Menu菜单&#xff0c;创建自定义的操作&#xff0c;如复制图片、使…

定时器详解

定时器&#xff1a;Timer类 常用方法方法&#xff1a; 1.schedule(TimeTask timetask,long delay,(long period)): TimeTask&#xff1a;实现了Runnable类&#xff0c;实现时需要重写run方法 delay&#xff1a;表示延迟多少(decay)后开始执行任务&#xff0c;单位是毫秒&#x…

密码学 | 椭圆曲线密码学 ECC 入门(四)

目录 正文 1 曲线方程 2 点的运算 3 求解过程 4 补充&#xff1a;有限域 ⚠️ 知乎&#xff1a;【密码专栏】动手计算双线性对&#xff08;中&#xff09; - 知乎 ⚠️ 写在前面&#xff1a;本文属搬运博客&#xff0c;自己留着学习。注意&#xff0c;这篇博客与前三…

LeetCode in Python 200. Number of islands (岛屿数量)

岛屿数量既可以用深度优先搜索也可以用广度优先搜索解决&#xff0c;本文给出两种方法的代码实现。 示例&#xff1a; 图1 岛屿数量输入输出示意图 方法一&#xff1a;广度优先搜索(bfs) 代码&#xff1a; class Solution:def numIslands(self, grid):if not grid:return 0…

【WSL报错】执行:wsl --list --online;错误:0x80072ee7

【WSL报错】执行:wsl --list --online&#xff1b;错误:0x80072ee7 问题情况解决方法详细过程 问题情况 C:\Users\17569>wsl --list --online 错误: 0x80072ee7 解决方法 开系统代理&#xff0c;到外网即可修复&#xff01;&#xff01;&#xff01;&#xff01;&#x…

Yolov8项目实践——基于yolov8与OpenCV实现目标物体运动热力图

概述 在数据驱动和定位的世界中&#xff0c;对数据进行解释、可视化和决策的能力变得日益重要。这表明&#xff0c;使用正确的工具和技术可能是项目成功的关键。在计算机视觉领域&#xff0c;存在许多技术来解释从视频&#xff08;包括录像、流媒体或实时视频&#xff09;中获…

「 网络安全常用术语解读 」软件成分分析SCA详解:从发展背景到技术原理再到业界常用检测工具推荐

软件成分分析&#xff08;Software Composition Analysis&#xff0c;SCA&#xff09;是一种用于识别和分析软件内部组件及其关系的技术&#xff0c;旨在帮助开发人员更好地了解和管理其软件的构建过程&#xff0c;同时可帮助安全人员揭秘软件内部结构的神秘面纱。SCA技术的发展…

递归、搜索与回溯算法:回溯,决策树

回溯算法是⼀种经典的递归算法&#xff0c;通常⽤于解决组合问题、排列问题和搜索问题等。 回溯算法的基本思想&#xff1a;从⼀个初始状态开始&#xff0c;按照⼀定的规则向前搜索&#xff0c;当搜索到某个状态⽆法前进时&#xff0c;回退到前⼀个状态&#xff0c;再按照其他…

【计算机组成原理】运算方法和运算器

数据与文字的表示方法 1. 数据格式1.1 定点数表示方法1.1.1 定点小数1.1.2 定点整数 1.2 浮点数表示方法1.2.1 浮点数表示1.2.2 浮点数的规格化1.2.2.1 尾数为原码表示的规格化1.2.2.2 尾数为补码表示的规格化 1.2.3 IEEE754标准⭐ 1.3 十进制数串的表示方法1.3.1 字符串形式1.…

网盘——私聊

在私聊这个功能实现中&#xff0c;具体步骤如下&#xff1a; 1、实现步骤&#xff1a; A、客户端A发送私聊信息请求&#xff08;发送的信息包括双方的用户名&#xff0c;聊天信息&#xff09; B、如果双方在线则直接转发给B&#xff0c;不在线则回复私聊失败&#xff0c;对方…

ProgressFlowmon的confluence接口存在任意命令执行漏洞(CVE-2024-2389)

声明&#xff1a; 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 简介 ProgressFlowmon是一整套用于网络映射、应用程序性能…

客户端动态降级系统

本文字数&#xff1a;4576字 预计阅读时间&#xff1a;20分钟 01 背景 无论是iOS还是Android系统的设备&#xff0c;在线上运行时受硬件、网络环境、代码质量等多方面因素影响&#xff0c;可能会导致性能问题&#xff0c;这一类问题有些在开发阶段是发现不了的。如何在线上始终…

大气的免费wordpress模板

国产的wordpress模板&#xff0c;更适合中国人使用习惯&#xff0c;更符合中国老板的审美的大气wordpress企业官网建站模板。 WordPress模板&#xff0c;也称为主题&#xff0c;是用于定义WordPress网站或博客外观和功能的预设计文件集。这些模板使用HTML、CSS和PHP代码构建&a…

上传文件到HDFS

1.创建文件夹 hdfs -dfs -mkdir -p /opt/mydoc 2.查看创建的文件夹 hdfs -dfs -ls /opt 注意改文件夹是创建在hdfs中的&#xff0c;不是本地&#xff0c;查看本地/opt&#xff0c;并没有该文件夹。 3.上传文件 hdfs dfs -put -f file:///usr/local/testspark.txt hdfs://m…

【深度学习】Vision Transformer

一、Vision Transformer Vision Transformer (ViT)将Transformer应用在了CV领域。在学习它之前&#xff0c;需要了解ResNet、LayerNorm、Multi-Head Self-Attention。 ViT的结构图如下&#xff1a; 如图所示&#xff0c;ViT主要包括Embedding、Encoder、Head三大部分。Class …

Docker in Docker的原理与实战

Docker in Docker&#xff08;简称DinD&#xff09;是一种在Docker容器内部运行另一个Docker实例的技术。这种技术允许用户在一个隔离的Docker容器中创建、管理和运行其他Docker容器&#xff0c;从而提供了更灵活和可控的部署选项。以下是DinD的主要特点&#xff1a; 隔离性&am…
最新文章