vue手写多对多关联图,连线用leader-line

效果如图

 鼠标滑动效果

关联性效果

 

 

<template ><div class="main" ref="predecessor"><div class="search"><div class="search-item"><div class="search-item-label">部门</div><Treeselect v-model="dept":options="deptOptions"show-countplaceholder="请选择部门"@change="changeDept()"/><!-- <el-cascader v-model="dept" clearable placeholder="请选择部门" ><el-option v-for="item in deptOptions" :key="item.id" :label="item.label" :value="item.id"></el-option></el-cascader> --></div><div class="search-item"><div class="search-item-label">周期</div><el-cascader v-model="TypeSelectValue" :options="cycleTypeSelect" :props="{checkStrictly: true,expandTrigger: 'hover'}" @change="handleChange" /></div></div><div class="main-predecessor"><div v-for="(item, index) in predecessorList" :key="'father' + index" class="father-predecessor"><div v-for="(itm, idx) in item" :key="itm.id"><div v-if="itm.status === 0 && itm.display === true" :id="itm.id" class="children-predecessor-big"@mouseenter="enter(index, idx)" @mouseleave="leave()":style="changeCardList.indexOf(itm.id) === -1 ? '' : 'background:rgba(206, 210, 232, 0.87)'"@click="clickDownsize(index, idx)"><div class="caption">{{ itm.okrUserOrDept }}</div><Vptip :content="itm.okrOContent" :width="'100%'" style="max-width: 500px;margin-bottom: 10px;"><span class="O-list" :style="changeOList.indexOf(itm.id) === -1 ? '' : 'color:#8198fe;font-weight: 700;'">O:{{`${itm.okrOContent}` }}</span></Vptip><div v-for="(im, indx) in itm.okrKrConfigList"><Vptip :content="im.okrKrContent" :width="'100%'" style="max-width: 500px;"><span class="kr-list":style="changeKrList.indexOf(im.id) === -1 ? '' : 'color:#8198fe;font-weight: 700;'">KR{{ indx + 1 }}: {{ `${im.okrKrContent}` }}</span></Vptip></div><div class="button"><el-button type="text" class="open" v-if="itm.isHeader && !itm.buttonDisplay" :disabled="timeout !== 0"@click.stop="commencementAll(index, itm.id, idx)" icon="el-icon-caret-bottom" /><el-button type="text" class="open" v-if="itm.isHeader && itm.buttonDisplay" :disabled="timeout !== 0"@click.stop="implicitAll(index, itm.id, idx)" icon="el-icon-caret-top" /></div></div><div v-if="itm.status === 1 && itm.display === true" :id="itm.id" class="children-predecessor-middle"@mouseenter="enter(index, idx)" @mouseleave="leave()":style="changeCardList.indexOf(itm.id) === -1 ? '' : 'background:rgba(206, 210, 232, 0.87)'"@click="clickDownsize(index, idx)"><div class="caption">{{ itm.okrUserOrDept }}</div><Vptip :content="itm.okrOContent" :width="'100%'" style="max-width: 500px;"><span class="O-list" :style="changeOList.indexOf(itm.id) === -1 ? '' : 'color:#8198fe;font-weight: 700;'">O:{{`${itm.okrOContent}` }}</span></Vptip><div class="button"><el-button type="text" class="open" v-if="itm.isHeader && !itm.buttonDisplay" :disabled="timeout !== 0"@click.stop="commencementAll(index, itm.id, idx)" icon="el-icon-caret-bottom" /><el-button type="text" class="open" v-if="itm.isHeader && itm.buttonDisplay" :disabled="timeout !== 0"@click.stop="implicitAll(index, itm.id, idx)" icon="el-icon-caret-top" /></div></div><div v-if="itm.status === 2 && itm.display === true" :id="itm.id" class="children-predecessor-small"@mouseenter="enter(index, idx)" @mouseleave="leave()":style="changeCardList.indexOf(itm.id) === -1 ? '' : 'background:rgba(206, 210, 232, 0.87)'"@click="clickDownsize(index, idx)"><div class="caption">{{ itm.okrUserOrDept }}</div><div class="button"><el-button type="text" class="open" v-if="itm.isHeader && !itm.buttonDisplay" :disabled="timeout !== 0"@click.stop="commencementAll(index, itm.id, idx)" icon="el-icon-caret-bottom" /><el-button type="text" class="open" v-if="itm.isHeader && itm.buttonDisplay" :disabled="timeout !== 0"@click.stop="implicitAll(index, itm.id, idx)" icon="el-icon-caret-top" /></div></div></div></div></div></div>
</template><script >
import { deptTreeSelect } from '@/api/system/user'
import okrConstant from '@/utils/okr/okrConstant'
import { getOkrPredecessor } from '@/api/okr/okrPredecessor'
import LeaderLine from 'leader-line'
import Vptip from "@/components/vptip" // 自定义Tooltip 文字提示
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
export default {name: 'okrPredecessor',components: {Vptip,Treeselect},data() {return {// 级联选择器下拉框selectOKrForm: {// 年份搜索值okrCycleYear: okrConstant.yearDecade()[0].value,// 季度搜索值okrCycleQuarter: okrConstant.currentMonthIsQuarter(),// 月份搜索值okrCycleMonth: '',},TypeSelectValue: okrConstant.currentMonthIsQuarter(),cycleTypeSelect: okrConstant.yearDecade(),// 部门列表deptOptions: [],// 部门数据dept: undefined,// 控制按钮的倒计时timeout: 0,// 线条的数组lineList: {},// 接口返回的循环数据predecessorListAll: [],// 继承的渲染数据predecessorList: [// [//   {//     id: 0,//     // 展开还是缩小状态//     status: 0,//     // 能否展开或者缩小下一级//     isHeader: true,//     // 目前在显示还是隐藏//     display: true,//     // 当前按钮是展开还是隐藏//     buttonDisplay: true,//     // 父级相关的id合集//     fatherUserId: []//   }// ]],// 所有的线条allLineList: [],// 应该画出来的线drawLineList: [],// 隐藏的数组listdisplayList: [],// 变色的卡片IDchangeCardList: [],// 变色的KRIDchangeKrList: [],// 变色的OIDchangeOList: [],// 变色的线段changeDrawLineList: []}},watch:{dept(){this.search()}},// 注册监听mounted() {// 获取部门列表this.getDept()window.addEventListener('resize', this.getScroll)// 监听div滚动事件let scrollView = this.$refs.predecessorscrollView.addEventListener("scroll", this.positionLine);document.body.style.overflow = 'hidden'this.search()},// 销毁前beforeDestroy() {document.body.style.overflow = ''// 销毁线条this.removeLines()},// 销毁监听,防止内存泄露destroyed() {window.removeEventListener('resize', this.getScroll)},methods: {// 获取部门列表getDept() {deptTreeSelect().then(response => {this.deptOptions = response.data[0].children})},// 鼠标移出事件(将O和KR两个数组归0)leave() {// 变色的KRIDthis.changeKrList = []// 变色的OIDthis.changeOList = []// 变色的卡片IDthis.changeCardList = []// 线段颜色恢复this.resumption()// 特殊线段归0this.changeDrawLineList = []},// 鼠标移入事件enter(index, idx) {// 变色的KRIDthis.changeKrList = []// 变色的OIDthis.changeOList = []// 变色的卡片IDthis.changeCardList = []// 获取到第一层DIV之后首先对上下紧挨的关系层进行循环// 寻找相关的父级this.findFatherList(index, idx)// 寻找相关的子集this.findChildrenList(index, idx)// 先将他本身的数据push进去if (this.predecessorList[index][idx].okrKrConfigList) {for (let i = 0; i < this.predecessorList[index][idx].okrKrConfigList.length; i++) {this.changeKrList.push(this.predecessorList[index][idx].okrKrConfigList[i].id)}}this.changeOList.push(this.predecessorList[index][idx].id)this.changeCardList.push(this.predecessorList[index][idx].id)// 获取线段变化线段this.getChangeLine()// 更改相关线段this.changeLineColor()},// 获取相关需要更改线段getChangeLine() {this.changeDrawLineList = []// 判断开头结尾都在变色的卡片之中for (let j = 0; j < this.drawLineList.length; j++) {if (this.changeCardList.indexOf(Number(this.drawLineList[j].start)) !== -1 && this.changeCardList.indexOf(Number(this.drawLineList[j].end)) !== -1) {this.changeDrawLineList.push(this.drawLineList[j])}}},// 恢复相关线段颜色resumption() {for (let i = 0; i < this.changeDrawLineList.length; i++) {this.twiceGetLine(this.changeDrawLineList[i].start, this.changeDrawLineList[i].end, i)}},// 更改相关线段颜色changeLineColor() {for (let i = 0; i < this.changeDrawLineList.length; i++) {this.changeGetLine(this.changeDrawLineList[i].start, this.changeDrawLineList[i].end, i)}},// 寻找相关的子集findChildrenList(index, idx) {// 对所有的线段进行遍历(因为只有O能够继承,所以子集直接往下找,只要有就是要变色)for (let i = 0; i < this.drawLineList.length; i++) {// 寻找到以此为开头的数据if (this.drawLineList[i].start === String(this.predecessorList[index][idx].id)) {// 对页面数据进行遍历寻找出此ID的位置,为后续获取KR做准备for (let x = 0; x < this.predecessorList.length; x++) {if (this.predecessorList[x]) {for (let y = 0; y < this.predecessorList[x].length; y++) {// 寻找到线段结束点位的内容if (String(this.predecessorList[x][y].id) === this.drawLineList[i].end) {// 变色的OIDthis.changeOList.push(this.predecessorList[x][y].id)// 变色的卡片IDthis.changeCardList.push(this.predecessorList[x][y].id)//  对KRLIST进行遍历,渲染KRLISTfor (let z = 0; z < this.predecessorList[x][y].okrKrConfigList.length; z++) {// 将所有相关kr进行pushthis.changeKrList.push(this.predecessorList[x][y].okrKrConfigList[z].id)}// 删除递归根节点功能// this.findChildrenList(x, y)}}}}}}},// 寻找相关的父级findFatherList(index, idx) {let fatherList = this.predecessorList[index][idx].extendsKrs// 对FATHERlIST进行遍历for (let i = 0; i < fatherList.length; i++) {// 只要是存在的Oid卡片就跟随变色(需要两点之间还存在连线关系)for (let j = 0; j < this.drawLineList.length; j++) {if (this.drawLineList[j].start === String(fatherList[i].okrId) && this.drawLineList[j].end === String(this.predecessorList[index][idx].id)) {this.changeCardList.push(fatherList[i].okrId)// 如果继承的是KR(O不变色,但是KR需要变色)if (fatherList[i].krId !== null) {this.changeKrList.push(fatherList[i].krId)} else {// 如果继承的是O,那么OKR全部变色,并且继续寻找上一层的OKR// 将变色Opush进入O的数组this.changeOList.push(fatherList[i].okrId)// 将变色O所对应的KR全部push进入数组(遍历寻找对应O)for (let x = 0; x < this.predecessorList.length; x++) {if (this.predecessorList[x]) {for (let y = 0; y < this.predecessorList[x].length; y++) {// 找出对应的IDif (fatherList[i].okrId === this.predecessorList[x][y].id) {// 对ID中的OKR进行循环pushfor (let z = 0; z < this.predecessorList[x][y].okrKrConfigList.length; z++) {// 将所有相关kr进行pushthis.changeKrList.push(this.predecessorList[x][y].okrKrConfigList[z].id)}// 寻找完O之后,将后生成的O继续进行上层寻找循环// 删除递归根节点功能// this.findFatherList(x, y)}}}}}}}}},// 级联改变方法handleChange(value) {this.selectOKrForm.okrCycleYear = ''this.selectOKrForm.okrCycleQuarter = ''this.selectOKrForm.okrCycleMonth = ''value.forEach((element, index) => {switch (index) {case 0: this.selectOKrForm.okrCycleYear = element; breakcase 1: this.selectOKrForm.okrCycleQuarter = element; breakcase 2: this.selectOKrForm.okrCycleMonth = element; break}})this.search()},// 搜索search() {let params = {okrUserDept: this.dept,okrCycleYear: this.selectOKrForm.okrCycleYear,okrCycleQuarter: this.selectOKrForm.okrCycleQuarter,okrCycleMonth: this.selectOKrForm.okrCycleMonth}// 跑接口之前销毁所有线条this.removeLines()// 获取继承关系详细数据getOkrPredecessor(params).then(res => {// 所有的线条this.allLineList = []// 应该画出来的线this.drawLineList = []// 页面渲染数据this.predecessorList = []this.predecessorListAll = res.data// 递归逻辑for (let i = 0; i < this.predecessorListAll.length; i++) {for (let j = 0; j < this.predecessorListAll[i].inheritedToOkrId.length; j++) {let level = this.predecessorListAll[i].levellet fatherUserId = []// 获取fatherListfor (let x = 0; x < this.predecessorListAll[i].inheritedToOkrId[j].extendsKrs.length; x++) {if (fatherUserId.indexOf(this.predecessorListAll[i].inheritedToOkrId[j].extendsKrs[x].okrId) === -1) {fatherUserId.push(this.predecessorListAll[i].inheritedToOkrId[j].extendsKrs[x].okrId)}}// 如果此层级还不存在先重置层级if (!this.predecessorList[level]) {this.predecessorList[level] = []}this.predecessorList[level].push(this.predecessorListAll[i].inheritedToOkrId[j])this.predecessorList[level][this.predecessorList[level].length - 1].fatherUserId = fatherUserIdthis.predecessorList[level][this.predecessorList[level].length - 1].status = 2this.predecessorList[level][this.predecessorList[level].length - 1].isHeader = falsethis.predecessorList[level][this.predecessorList[level].length - 1].display = truethis.predecessorList[level][this.predecessorList[level].length - 1].buttonDisplay = true}}// 寻找父子关系的连线this.findLineList()// 更改header属性判断是否可以当标头this.whetherIsHeader()// 刷新数组变化导致的数据更改this.$forceUpdate()// 画线(页面加载有一个动画,需要等动画完毕再开始加载线条保证线条的稳定性)setTimeout(() => { this.drawLine() }, 500)})},// 判断是否可以当标头,是否含有展开收起属性whetherIsHeader() {// 对二维数组进行遍历for (let x = 0; x < this.predecessorList.length; x++) {// 判断此层级中是否有内容if (this.predecessorList[x]) {for (let y = 0; y < this.predecessorList[x].length; y++) {// 对当前所有连线进行遍历for (let i = 0; i < this.allLineList.length; i++) {// 如果存在以此ID为开头的线段,证明为header,isHeader属性为trueif (String(this.predecessorList[x][y].id) === this.allLineList[i].start) {this.predecessorList[x][y].isHeader = true}}}}}},// 寻找父子关系的连线findLineList() {// 对二维数组进行循环for (let i = 0; i < this.predecessorList.length; i++) {if (this.predecessorList[i]) {for (let j = 0; j < this.predecessorList[i].length; j++) {// 对父级进行循环if (this.predecessorList[i][j].fatherUserId) {for (let x = 0; x < this.predecessorList[i][j].fatherUserId.length; x++) {if (this.existent(this.predecessorList[i][j].fatherUserId[x], this.predecessorList[i][j].id)) {this.allLineList.push({start: String(this.predecessorList[i][j].fatherUserId[x]),end: String(this.predecessorList[i][j].id)})}}}}}}// 将数据同步到渲染的线段中,默认全部显示this.drawLineList = JSON.parse(JSON.stringify(this.allLineList))},// 验证是否存在该条数据existent(start, end) {// 对二维数组进行遍历for (let i = 0; i < this.predecessorList.length; i++) {if (this.predecessorList[i]) {for (let j = 0; j < this.predecessorList[i].length; j++) {if (this.predecessorList[i][j].id === start) {// 如果开始符合,看结束是否存在for (let x = 0; x < this.predecessorList.length; x++) {if (this.predecessorList[x]) {for (let y = 0; y < this.predecessorList[x].length; y++) {if (this.predecessorList[x][y].id === end) {return true}}}}}}}}return false},// 点击展开// 准备开始展开递归将所有关联的数据进行处理commencementAll(index, id, idx) {this.timeout = 1// 防抖setTimeout(() => {this.timeout = 0}, 500)// 更改按钮let changeIndexfor (let i = 0; i < this.predecessorList[index].length; i++) {if (this.predecessorList[index][i].id === id) {changeIndex = i}}// 更改按钮状态this.predecessorList[index][changeIndex].buttonDisplay = true// 目前已经确认隐藏的id标题// 把跟原标题有关的数据全都找出来再进行删除let oldIdList = this.displayList//  所有可以改回状态的IDlet deleteIdList = [id]// 新的ID集合let newIdList = []// 进行遍历寻找不需要删除的数组for (let i = index; i < this.predecessorList.length; i++) {if (this.predecessorList[i]) {for (let j = 0; j < this.predecessorList[i].length; j++) {if (this.arbitrarily(deleteIdList, this.predecessorList[i][j].fatherUserId)) {deleteIdList.push(this.predecessorList[i][j].id)}}}}//  生成新数组for (let i = 0; i < oldIdList.length; i++) {let haveId = truefor (let j = 0; j < deleteIdList.length; j++) {if (deleteIdList[j] === oldIdList[i]) {haveId = false}}if (haveId) {newIdList.push(oldIdList[i])}}// 当前禁止当头的数据 this.displayListthis.displayList = [...newIdList]// 更改页面this.commencement(index, id)// 更改页面显示this.enter(index, idx)},// 点击收起implicitAll(index, id, idx) {this.timeout = 1// 防抖setTimeout(() => {this.timeout = 0}, 1000)// 更改按钮let changeIndexfor (let i = 0; i < this.predecessorList[index].length; i++) {if (this.predecessorList[index][i].id === id) {changeIndex = i}}// 更改按钮状态this.predecessorList[index][changeIndex].buttonDisplay = false// 寻找子集this.findImplicit(index, id)// 更改页面this.implicit(index, id)// 更改页面显示this.enter(index, idx)},// 展开隐藏后续内容commencement(index, id) {// 操作线条// 销毁线条this.removeLines()// 线条数组清零let newDrawLineList = []// 对目前所有线条进行循环for (let i = 0; i < this.allLineList.length; i++) {let remain = falsefor (let j = 0; j < this.displayList.length; j++) {if (this.allLineList[i].start === String(this.displayList[j])) {remain = true}}if (remain === false) {newDrawLineList.push(this.allLineList[i])}}// 操作卡片// 寻找各个子集,并且观察子集是不是只有这一个fatherUserIdfor (let i = index; i < this.predecessorList.length; i++) {if (this.predecessorList[i]) {for (let j = 0; j < this.predecessorList[i].length; j++) {// 如果先前的隐藏那么展开后按钮状态为打开if (this.predecessorList[i][j].display === false) {this.predecessorList[i][j].buttonDisplay = true}// 只有从无到有的才进行回显this.predecessorList[i][j].display = trueif (this.including(this.displayList, this.predecessorList[i][j].fatherUserId)) {this.predecessorList[i][j].display = false}}}}// 验证画线数据结尾是否实际存在let trueLineList = []for (let i = 0; i < newDrawLineList.length; i++) {if (this.trueDiv(newDrawLineList[i].end)) {trueLineList.push(newDrawLineList[i])}}// 新的画线数据this.drawLineList = trueLineList// 重新画线setTimeout(() => { this.drawLine() }, 50)},// 隐藏后续内容implicit(index, id) {// 操作线条// 销毁线条this.removeLines()// 线条数组清零let newDrawLineList = []// 对目前所有线条进行循环for (let i = 0; i < this.allLineList.length; i++) {let remain = falsefor (let j = 0; j < this.displayList.length; j++) {if (this.allLineList[i].start === String(this.displayList[j])) {remain = true}}if (remain === false) {newDrawLineList.push(this.allLineList[i])}}// 操作卡片// 寻找各个子集,并且观察子集是不是只有这一个fatherUserIdfor (let i = index; i < this.predecessorList.length; i++) {if (this.predecessorList[i]) {for (let j = 0; j < this.predecessorList[i].length; j++) {if (this.including(this.displayList, this.predecessorList[i][j].fatherUserId)) {this.predecessorList[i][j].display = false}}}}// 验证画线数据结尾是否实际存在let trueLineList = []for (let i = 0; i < newDrawLineList.length; i++) {if (this.trueDiv(newDrawLineList[i].end)) {trueLineList.push(newDrawLineList[i])}}// 新的画线数据this.drawLineList = trueLineList// 重新画线setTimeout(() => { this.drawLine() }, 50)},// div节点是否是实际存在的trueDiv(id) {for (let i = 0; i < this.predecessorList.length; i++) {if (this.predecessorList[i]) {for (let j = 0; j < this.predecessorList[i].length; j++) {if (String(this.predecessorList[i][j].id) === id && this.predecessorList[i][j].display === true) {return true}}}}return false},// 寻找子集findImplicit(index, id) {// 目前已经确认隐藏的id标题this.displayList.push(id)// 进行遍历寻找for (let i = index; i < this.predecessorList.length; i++) {if (this.predecessorList[i]) {for (let j = 0; j < this.predecessorList[i].length; j++) {if (this.including(this.displayList, this.predecessorList[i][j].fatherUserId)) {this.displayList.push(this.predecessorList[i][j].id)}}}}let newArr = [];for (let i = 0; i < this.displayList.length; i++) {if (!newArr.includes(this.displayList[i])) {newArr.push(this.displayList[i])}}// 隐藏的数组数据: this.displayListthis.displayList = [...newArr]},// 判断子数组中是否存在任意包含关系,不需要全等,只要有一个就行arbitrarily(list, fatherUserId) {let x = 0for (let i = 0; i < list.length; i++) {for (let j = 0; j < fatherUserId.length; j++) {if (list[i] === fatherUserId[j]) {x++}}}if (x !== 0) {return true}return false},// 判断子数组中是否存在包含关系including(list, fatherUserId) {let x = 0for (let i = 0; i < list.length; i++) {for (let j = 0; j < fatherUserId.length; j++) {if (list[i] === fatherUserId[j]) {x++}}}if (x === fatherUserId.length && fatherUserId.length !== 0) {return true}return false},// 重新定位各线positionLine() {for (let i = 0; i < this.drawLineList.length; i++) {let nameLine = this.drawLineList[i].start + '' + this.drawLineList[i].end// 判断线段是否真实存在if (this.lineList[nameLine] !== undefined) {this.lineList[nameLine].position()}}},// 开始画线drawLine() {for (let i = 0; i < this.drawLineList.length; i++) {this.getLine(this.drawLineList[i].start, this.drawLineList[i].end, i)}},// 点击展开缩小重新定位线条hideLines() {for (let i = 0; i < this.drawLineList.length; i++) {let nameLine = this.drawLineList[i].start + '' + this.drawLineList[i].endthis.lineList[nameLine].position()}},// 隐藏线条hideLine(start, end) {let nameLine = start + endthis.lineList[nameLine].hide()},// 销毁线条removeLines() {for (let i = 0; i < this.drawLineList.length; i++) {let nameLine = this.drawLineList[i].start + '' + this.drawLineList[i].endthis.lineList[nameLine].remove()}},// 点击展开clickDownsize(index, idx) {// 卡片三种状态互相切换if (this.predecessorList[index][idx].status === 0) {this.predecessorList[index][idx].status = 1} else if (this.predecessorList[index][idx].status === 1) {this.predecessorList[index][idx].status = 2} else {this.predecessorList[index][idx].status = 0}let predecessor = JSON.parse(JSON.stringify(this.predecessorList))this.predecessorList = []this.predecessorList = JSON.parse(JSON.stringify(predecessor))setTimeout(() => { this.positionLine() }, 50)},// 画线changeGetLine(start, end, i) {let lineStart = document.getElementById(start)let lineEnd = document.getElementById(end)let styleOption = {color: 'red', // 指引线颜色endPlug: '', // 指引线结束点的样式 hand,discsize: 2, // 线条尺寸startSocket: 'bottom', //在指引线开始的地方从元素左侧开始endSocket: 'top', //在指引线开始的地方从元素右侧结束// hide: true, // 绘制时隐藏,默认为false,在初始化时可能会出现闪烁的线条// startPlugColor: '#ff3792', // 渐变色开始色// endPlugColor: '#fff386', // 渐变色结束色gradient: false, // 使用渐变色outLineColor: 'blue',path: 'fluid', // straight,arc,fluid,magnet,grid// dash: {//   // 虚线样式//   animation: true // 让线条滚动起来// },hide: true,}let nameLine = start + endthis.lineList[nameLine].setOptions(styleOption)/** 显示效果*  draw 绘制线条*  fade 淡入*  none 无效果,即直接显示*/// let showEffectName = 'draw'// // 动画参数// let animOptions = {//   // duration: 1000, //持续时长//   // timing: 'ease-in' // 动画函数// }// this.lineList[nameLine].show()// this.lineList[nameLine].position()},// 恢复线段twiceGetLine(start, end, i) {let lineStart = document.getElementById(start)let lineEnd = document.getElementById(end)let styleOption = {color: '#6a6a6a', // 指引线颜色endPlug: '', // 指引线结束点的样式 hand,discsize: 2, // 线条尺寸startSocket: 'bottom', //在指引线开始的地方从元素左侧开始endSocket: 'top', //在指引线开始的地方从元素右侧结束// hide: true, // 绘制时隐藏,默认为false,在初始化时可能会出现闪烁的线条// startPlugColor: '#ff3792', // 渐变色开始色// endPlugColor: '#fff386', // 渐变色结束色gradient: false, // 使用渐变色outLineColor: '#6a6a6a',path: 'fluid', // straight,arc,fluid,magnet,grid// dash: {//   // 虚线样式//   animation: true // 让线条滚动起来// },hide: true,}let nameLine = start + endthis.lineList[nameLine].setOptions(styleOption)},// 画线getLine(start, end, i) {let lineStart = document.getElementById(start)let lineEnd = document.getElementById(end)let styleOption = {color: '#6a6a6a', // 指引线颜色endPlug: '', // 指引线结束点的样式 hand,discsize: 2, // 线条尺寸startSocket: 'bottom', //在指引线开始的地方从元素左侧开始endSocket: 'top', //在指引线开始的地方从元素右侧结束// hide: true, // 绘制时隐藏,默认为false,在初始化时可能会出现闪烁的线条// startPlugColor: '#ff3792', // 渐变色开始色// endPlugColor: '#fff386', // 渐变色结束色gradient: false, // 使用渐变色outLineColor: '#6a6a6a',path: 'fluid', // straight,arc,fluid,magnet,grid// dash: {//   // 虚线样式//   animation: true // 让线条滚动起来// },hide: true,}let nameLine = start + endthis.$set(this.lineList, `${nameLine}`, null)this.lineList[nameLine] = new LeaderLine(lineStart, lineEnd, styleOption)/** 显示效果*  draw 绘制线条*  fade 淡入*  none 无效果,即直接显示*/// let showEffectName = 'draw'// // 动画参数// let animOptions = {//   // duration: 1000, //持续时长//   // timing: 'ease-in' // 动画函数// }this.lineList[nameLine].show()this.lineList[nameLine].position()},}
}
</script>
<style>
.leader-line {z-index: -1
}
</style>
<style lang="scss" scoped >
.search-item-label {width: 30%;font-size: 14px;color: #333;font-weight: 600;
}.search-item {width: 40%;display: flex;align-items: center;margin-right: 5%;
}
.vue-treeselect{width: 80%;
}
.search {margin-left: 20px;margin-top: 20px;width: 500px;display: flex;justify-content: space-between;.el-button+.el-button {margin-left: 0px;}
}.main {height: calc(100vh - 84px);overflow-x: scroll;overflow-y: scroll;
}.main-predecessor {min-width: 1100px;width: fit-content;min-height: calc(100vh - 94px);}.father-predecessor {display: flex;justify-content: space-around;align-items: flex-start;
}.children-predecessor-big {width: 250px;height: 200px;border: 1px solid #f8f8f8;margin: 60px 10px;border-radius: 6px;box-shadow: rgba(136, 165, 191, 0.48) 6px 2px 16px 0px, rgba(255, 255, 255, 0.8) -6px -2px 16px 0px;background-color: rgba(255, 255, 255, 0.95);position: relative;}.children-predecessor-middle {width: 200px;height: 80px;border: 1px solid #f8f8f8;margin: 60px 10px;border-radius: 6px;box-shadow: rgba(136, 165, 191, 0.48) 6px 2px 16px 0px, rgba(255, 255, 255, 0.8) -6px -2px 16px 0px;background-color: rgba(255, 255, 255, 0.95);position: relative;
}.children-predecessor-small {width: 130px;height: 50px;border: 1px solid #f8f8f8;margin: 60px 10px;border-radius: 6px;box-shadow: rgba(136, 165, 191, 0.48) 6px 2px 16px 0px, rgba(255, 255, 255, 0.8) -6px -2px 16px 0px;background-color: rgba(255, 255, 255, 0.95);position: relative;
}.button {position: absolute;text-align: center;bottom: -10px;left: 0;width: 100%;height: 20px;}.caption {text-align: center;line-height: 30px;
}.icon {cursor: pointer;float: right;font-size: 20px;line-height: 30px;color: #158BBB;margin-right: 10px;
}::v-deep .open {padding: 0 !important;border: 1px solid #b4b4b4;box-shadow: rgba(135, 138, 141, 0.48) 6px 2px 16px 0px, rgba(255, 255, 255, 0.8) -6px -2px 16px 0px;background-color: rgba(255, 255, 255, 0.95);border-radius: 50%;
}.O-list {margin-left: 10px;font-size: 18px;
}.kr-list {margin-left: 10px;font-size: 16px;
}::v-deep .small-select {.el-input__inner {width: 120px;}
}
</style>

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dinput8.dll导致游戏打不开的解决方法,快速修复dinput8.dll文件

当你尝试启动某个游戏时&#xff0c;如果遇到dinput8.dll文件缺失或损坏的错误提示&#xff0c;可能会导致游戏无法正常运行。dinput8.dll是DirectInput API的一部分&#xff0c;它提供了游戏手柄、键盘和鼠标等输入设备的支持。本文将详细介绍dinput8.dll的作用、导致游戏无法…

2023下半年软考改成机考,对考生有哪些影响?

软考改革成无纸化考试已经实锤。根据陕西软考办官网的消息&#xff0c;从2023年11月起&#xff0c;软考的所有科目都将改为机器考试形式。详情请参阅&#xff1a; 那么软考考试改为机考后&#xff0c;对我们会有哪些影响呢&#xff1f;我来简单概括一下。 1、复习的方法可以根…

AMD高保真超分算法1.0解密

FSR 1.0是空间滤波算法&#xff0c;分成EASU和RCAS两部分。EASU是边缘适配的空间上采样(Edge Adaptive Spatial Upsampling)&#xff0c;RCAS是健壮对比度适配锐化(Robust Contrast Adaptive Sharpening)&#xff0c;从CAS发展而来。 Lanczos 采样及多项式拟合 FSR 1.0 使用了 …

Nginx的优化和防盗链(面试高频!!!)

Nginx的优化和防盗链 全篇高能&#xff01;&#xff01;&#xff01;&#xff01;干货较多&#xff01;&#xff01;&#xff01;&#xff01;本篇含面试高频题&#xff1a; 修改配置文件时&#xff0c;先备份&#xff01;&#xff01;&#xff01;以便回滚&#xff01;&…

Oracle数据迁移

问题描述&#xff1a; oracle数据库的所有表结构、数据、索引等需要需从测试库迁移到正式库。 解决步骤&#xff1a; oracle数据库迁移&#xff0c;主要通过expdp从测试库所在的源服务器将指定的数据表或数据源导出为一个或多个数据文件&#xff08;.dmp文件&#xff09;&…

3.6 Spring MVC文件上传

1. 文件上传到本地 实现方式 Spring MVC使用commons-fileupload实现文件上传&#xff0c;注意事项如下&#xff1a; l HTTP请求方法是POST。 l HTTP请求头的Content-Type是multipart/form-data。 SpringMVC配置 配置commons-fileupload插件的文件上传解析器CommonsMultip…

【JAVA基础】- 同步非阻塞模式NIO详解

【JAVA基础】- 同步非阻塞模式NIO详解 文章目录 【JAVA基础】- 同步非阻塞模式NIO详解一、概述二、常用概念三、NIO的实现原理四、NIO代码实现客户端实现服务端实现 五、同步非阻塞NIO总结 一、概述 NIO&#xff08;Non-Blocking IO&#xff09;是同步非阻塞方式来处理IO数据。…

Qt通过QSS设置QPushButton的样式

同时设置QPushButton的文字样式和图标的方法 为了美化界面&#xff0c;有时候需要修改QPushButton的样式&#xff0c;让一个QPushButton上面既要显示图标&#xff0c;又要显示文字内容 起初我的做法是重写QPushButton&#xff0c;这样做可以实现&#xff0c;但是有几个问题 实现…

亚信科技AntDB数据库与库瀚存储方案完成兼容性互认证,联合方案带来约20%性能提升

近日&#xff0c;亚信科技AntDB数据库与苏州库瀚信息科技有限公司自主研发的RISC-V数据库存储解决方案进行了产品兼容测试。经过双方团队的严格测试&#xff0c;亚信科技AntDB数据库与库瀚数据库存储解决方案完全兼容、运行稳定。除高可用性测试外&#xff0c;双方进一步开展TP…

SpringBoot整合、SpringBoot与异步任务

目录 一、背景描述二、简单使用方法三、原理五、使用自定义线程池六、Async失效情况 一、背景描述 java 的代码是同步顺序执行&#xff0c;当我们需要执行异步操作时我们通常会去创建一个新线程去执行。比如new Thread()。start()&#xff0c;或者使用线程池线程池 new Thread…

jackson库收发json格式数据和ajax发送json格式的数据

一、jackson库收发json格式数据 jackson库是maven仓库中用来实现组织json数据功能的库。 json格式  json格式一个组织数据的字符文本格式&#xff0c;它用键值对的方式存贮数据&#xff0c;json数据都是有一对对键值对组成的&#xff0c;键只能是字符串&#xff0c;用双引号包…

C++模板初阶

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析2 目录 &#x1f449;&#x1f3fb;泛型编程&#x1f449;&#x1f3fb;模板函数模板函数…