修改看板

master
夜笙歌 3 weeks ago
parent 1f5f365c45
commit 3f44330b31

@ -0,0 +1,158 @@
<template>
<div class="flow-ruler-container">
<div class="ruler-x">
<canvas ref="rulerXCanvas" class="ruler-canvas"></canvas>
</div>
<div class="main-content">
<div class="ruler-y">
<canvas ref="rulerYCanvas" class="ruler-canvas"></canvas>
</div>
<slot />
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useVueFlow } from '@vue-flow/core';
const rulerXCanvas = ref(null);
const rulerYCanvas = ref(null);
const { viewport } = useVueFlow();
let animationFrameId = null;
let lastRenderTime = 0;
const FRAME_INTERVAL = 1000 / 60;
const getNiceStep = (target) => {
const steps = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000];
return steps.find(s => s * viewport.value.zoom >= target) || 1000;
};
const drawRulers = () => {
const scale = viewport.value.zoom;
const offsetX = viewport.value.x;
const offsetY = viewport.value.y;
const step = getNiceStep(10);
const bigStep = step * 10;
const leftOffset = 30;
const rulerSize = 30;
const xCanvas = rulerXCanvas.value;
const xCtx = xCanvas.getContext('2d');
xCanvas.width = xCanvas.offsetWidth * window.devicePixelRatio;
xCanvas.height = xCanvas.offsetHeight * window.devicePixelRatio;
xCtx.scale(window.devicePixelRatio, window.devicePixelRatio);
xCtx.clearRect(0, 0, xCanvas.offsetWidth, xCanvas.offsetHeight);
xCtx.fillStyle = '#999';
xCtx.font = '10px sans-serif';
const canvasWidth = xCanvas.offsetWidth;
const startWorldX = Math.floor((-offsetX - leftOffset) / scale / step) * step;
const endWorldX = (-offsetX + canvasWidth) / scale;
for (let worldX = startWorldX; worldX < endWorldX; worldX += step) {
const screenX = worldX * scale + offsetX + leftOffset;
xCtx.beginPath();
if (Math.round(worldX) % bigStep === 0) {
xCtx.strokeStyle = '#fff';
xCtx.moveTo(screenX, rulerSize - 20);
xCtx.lineTo(screenX, rulerSize);
xCtx.stroke();
xCtx.fillStyle = '#ccc';
xCtx.fillText(Math.round(worldX).toString(), screenX + 2, 10);
} else {
xCtx.strokeStyle = '#666';
xCtx.moveTo(screenX, rulerSize - 10);
xCtx.lineTo(screenX, rulerSize);
xCtx.stroke();
}
}
const yCanvas = rulerYCanvas.value;
const yCtx = yCanvas.getContext('2d');
yCanvas.width = yCanvas.offsetWidth * window.devicePixelRatio;
yCanvas.height = yCanvas.offsetHeight * window.devicePixelRatio;
yCtx.scale(window.devicePixelRatio, window.devicePixelRatio);
yCtx.clearRect(0, 0, yCanvas.offsetWidth, yCanvas.offsetHeight);
yCtx.fillStyle = '#999';
yCtx.font = '10px sans-serif';
const canvasHeight = yCanvas.offsetHeight;
const startWorldY = Math.floor((-offsetY) / scale / step) * step;
const endWorldY = (-offsetY + canvasHeight) / scale;
for (let worldY = startWorldY; worldY < endWorldY; worldY += step) {
const screenY = worldY * scale + offsetY;
yCtx.beginPath();
if (Math.round(worldY) % bigStep === 0) {
yCtx.strokeStyle = '#fff';
yCtx.save();
yCtx.translate(rulerSize - 2, screenY + 5);
yCtx.rotate(-Math.PI / 2);
yCtx.fillStyle = '#ccc';
yCtx.fillText(Math.round(worldY).toString(), 0, 0);
yCtx.restore();
yCtx.moveTo(rulerSize - 20, screenY);
yCtx.lineTo(rulerSize, screenY);
yCtx.stroke();
} else {
yCtx.strokeStyle = '#666';
yCtx.moveTo(rulerSize - 10, screenY);
yCtx.lineTo(rulerSize, screenY);
yCtx.stroke();
}
}
};
const renderLoop = (time) => {
if (time - lastRenderTime >= FRAME_INTERVAL) {
drawRulers();
lastRenderTime = time;
}
animationFrameId = requestAnimationFrame(renderLoop);
};
onMounted(() => {
animationFrameId = requestAnimationFrame(renderLoop);
});
</script>
<style scoped>
.flow-ruler-container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.ruler-x {
height: 30px;
background: #1F2122;
border-bottom: 1px solid #444;
overflow: hidden;
}
.ruler-y {
width: 30px;
background: #1F2122;
border-right: 1px solid #444;
height: 100%;
overflow: hidden;
}
.main-content {
display: flex;
height: calc(100% - 30px);
}
.ruler-canvas {
width: 100%;
height: 100%;
display: block;
}
</style>

@ -964,7 +964,6 @@ onMounted(async () => {
});
customBoard.value = JSON.parse(localStorage.getItem('BOARDNODE') || '[]');
await nextTick();
getBoardApi(router.currentRoute.value.query.id)
.then((res) => {
let data = res.data;
@ -1027,7 +1026,6 @@ onMounted(async () => {
loading.value = false
})
// pageData.value = JSON.parse(localStorage.getItem('PAGEDATA'));
});
const customDataForm = ref({});
const nodeAttrForm = ref({});

@ -3,6 +3,7 @@
<div class="top">
<div class="componentMenu">
<el-popover
:width="620"
trigger="click"
placement="bottom-start">
<template #reference>
@ -17,13 +18,98 @@
</el-icon>
</div>
</template>
<el-table>
<el-table-column width="150" property="date" label="date" />
<el-table-column width="100" property="name" label="name" />
<el-table-column width="300" property="address" label="address" />
</el-table>
<div>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'line')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">折线</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'multiLines')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">多折线</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'curve')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">曲线</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'multiCurves')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">多曲线
</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'bar')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">柱状图</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'backgroundBar')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">背景柱状图</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'multiBars')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">多柱状图
</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'pie')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">饼图</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'nightingaleRoseDiagram')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">南丁格尔玫瑰图</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'carousel')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">轮播图</div>
</el-card>
</div>
</el-popover>
<el-popover
:width="620"
trigger="click"
placement="bottom-start">
<template #reference>
@ -38,13 +124,48 @@
</el-icon>
</div>
</template>
<el-table>
<el-table-column width="150" property="date" label="date" />
<el-table-column width="100" property="name" label="name" />
<el-table-column width="300" property="address" label="address" />
</el-table>
<div>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'map')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">映射</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'staticData')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">静态数据</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'data')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">设备数据</div>
</el-card>
<template v-for="i in customData">
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'customData',i)"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">{{ i.name }}</div>
</el-card>
</template>
</div>
</el-popover>
<el-popover
:width="620"
trigger="click"
placement="bottom-start"
>
@ -60,11 +181,92 @@
</el-icon>
</div>
</template>
<el-table>
<el-table-column width="150" property="date" label="date" />
<el-table-column width="100" property="name" label="name" />
<el-table-column width="300" property="address" label="address" />
</el-table>
<div>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'text')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">文字</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'inputNode')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">输入框</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'time')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">时间</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'img')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">图片</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'icon')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">图标</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'video')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">视频</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'timeline')" :style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">时间线</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'digitalFlop')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">数字翻牌器</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'table')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">普通表格</div>
</el-card>
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'scrollTable')"
:style="{display:'inline-block',margin:'0 4px 4px 0'}"
:body-style="{padding:'4px 0'}">
<template #header>
<StarFilled />
</template>
<div class="moduleText">滚动表格</div>
</el-card>
</div>
</el-popover>
</div>
<div class="optionsMenu"></div>
@ -73,7 +275,27 @@
<div class="title">
图层
</div>
<div class="level" v-for="i in 10">
<div v-if="else">
<el-dropdown trigger="click" @command="nodeOperate">
<span class="el-dropdown-link" @click.stop>
<el-icon class="settingIcon">
<Setting />
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="{type:'toTop',node:i}">置顶</el-dropdown-item>
<el-dropdown-item :command="{type:'moveUp',node:i}">上移一层</el-dropdown-item>
<el-dropdown-item :command="{type:'moveDown',node:i}">下移一层</el-dropdown-item>
<el-dropdown-item :command="{type:'copy',node:i}">复制</el-dropdown-item>
<el-dropdown-item :command="{type:'del',node:i}">删除</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<div class="level" v-for="i in nodes.filter(e=>e.type!=='area').reverse()">
<div class="isShow">
<el-icon style="cursor: pointer" color="#fff" :size="16">
<View />
@ -88,18 +310,370 @@
</svg>
</div>
<div class="boardName">
<span style=" display: inline-block;">图表名称</span>
<span style=" display: inline-block;">{{ i.name }}</span>
</div>
</div>
</div>
<div class="center"></div>
<div class="right"></div>
<div class="center" @drop="onDrop" v-loading="loading">
<FlowRuler>
<VueFlow :min-zoom="0.01" ref="flowRef" v-model:nodes="nodes" v-model:edges="edges" fit-view-on-init
default-marker-color="#409EFF"
@connect="logEvent('connect', $event)"
@node-click="logEvent('click', $event)"
@pane-click="logEvent('paneClick', $event)"
@node-drag-start="logEvent('nodeDrag', $event)"
@node-contextMenu="logEvent('contextmenu', $event)"
@dragover="onDragOver"
>
<Background :size="1" :gap="20" pattern-color="#BDBDBD" style="background-color: #000" />
<template #node-area="areaNodeProps">
<AreaNode v-bind="areaNodeProps" :pageData="pageData"></AreaNode>
</template>
<template #node-customBoard="customBoardNodeProps">
<CustomBoardNode :inputData=getInputData(customBoardNodeProps.id) v-bind="customBoardNodeProps"
@resize="resize"></CustomBoardNode>
</template>
<template #node-customData="customDataNodeProps">
<CustomDataNode :inputData=getInputData(customDataNodeProps.id) v-bind="customDataNodeProps"
@resize="resize"></CustomDataNode>
</template>
<template #node-line="lineNodeProps">
<LineNode :inputData=getInputData(lineNodeProps.id) v-bind="lineNodeProps"
@resize="resize"></LineNode>
</template>
<template #node-multiLines="multiLinesNodeProps">
<MultiLinesNode :inputData=getInputData(multiLinesNodeProps.id) v-bind="multiLinesNodeProps"
@resize="resize"></MultiLinesNode>
</template>
<template #node-curve="curveNodeProps">
<CurveNode :inputData=getInputData(curveNodeProps.id) v-bind="curveNodeProps"
@resize="resize"></CurveNode>
</template>
<template #node-multiCurves="multiCurvesNodeProps">
<MultiCurvesNode :inputData=getInputData(multiCurvesNodeProps.id) v-bind="multiCurvesNodeProps"
@resize="resize"></MultiCurvesNode>
</template>
<template #node-bar="barNodeProps">
<BarNode :inputData=getInputData(barNodeProps.id) v-bind="barNodeProps"
@resize="resize"></BarNode>
</template>
<template #node-backgroundBar="backgroundBarNodeProps">
<BackgroundBarNode :inputData=getInputData(backgroundBarNodeProps.id) v-bind="backgroundBarNodeProps"
@resize="resize"></BackgroundBarNode>
</template>
<template #node-multiBars="multiBarsNodeProps">
<MultiBarsNode :inputData=getInputData(multiBarsNodeProps.id) v-bind="multiBarsNodeProps"
@resize="resize"></MultiBarsNode>
</template>
<template #node-pie="pieNodeProps">
<PieNode :inputData=getInputData(pieNodeProps.id) v-bind="pieNodeProps"
@resize="resize"></PieNode>
</template>
<template #node-nightingaleRoseDiagram="nightingaleRoseDiagramNodeProps">
<NightingaleRoseDiagramNode :inputData=getInputData(nightingaleRoseDiagramNodeProps.id)
v-bind="nightingaleRoseDiagramNodeProps"
@resize="resize"></NightingaleRoseDiagramNode>
</template>
<template #node-carousel="carouselNodeProps">
<CarouselNode :inputData=getInputData(carouselNodeProps.id) v-bind="carouselNodeProps"
@resize="resize"></CarouselNode>
</template>
<template #node-data="dataNodeProps">
<DataNode :inputData=getInputData(dataNodeProps.id) v-bind="dataNodeProps"
@resize="resize"></DataNode>
</template>
<template #node-text="textNodeProps">
<TextNode :inputData=getInputData(textNodeProps.id) v-bind="textNodeProps"
@resize="resize"></TextNode>
</template>
<template #node-img="imgNodeProps">
<ImgNode :inputData=getInputData(imgNodeProps.id) v-bind="imgNodeProps"
@resize="resize"></ImgNode>
</template>
<template #node-icon="iconNodeProps">
<IconNode :inputData=getInputData(iconNodeProps.id) v-bind="iconNodeProps"
@resize="resize"></IconNode>
</template>
<template #node-video="videoNodeProps">
<VideoNode :inputData=getInputData(videoNodeProps.id) v-bind="videoNodeProps"
@resize="resize"></VideoNode>
</template>
<template #node-timeline="timelineNodeProps">
<TimelineNode :inputData=getInputData(timelineNodeProps.id) v-bind="timelineNodeProps"
@resize="resize"></TimelineNode>
</template>
<template #node-digitalFlop="digitalFlopNodeProps">
<DigitalFlopNode :inputData=getInputData(digitalFlopNodeProps.id) v-bind="digitalFlopNodeProps"
@resize="resize"></DigitalFlopNode>
</template>
<template #node-inputNode="inputNodeProps">
<InputNode :inputData=getInputData(inputNodeProps.id) v-bind="inputNodeProps"
@resize="resize"></InputNode>
</template>
<template #node-time="timeNodeProps">
<TimeNode :inputData=getInputData(timeNodeProps.id) v-bind="timeNodeProps"
@resize="resize"></TimeNode>
</template>
<template #node-map="mapNodeProps">
<MapNode :inputData=getInputData(mapNodeProps.id) v-bind="mapNodeProps"
@resize="resize"></MapNode>
</template>
<template #node-staticData="staticDataNodeProps">
<StaticDataNode :inputData=getInputData(staticDataNodeProps.id) v-bind="staticDataNodeProps"
@resize="resize"></StaticDataNode>
</template>
<template #node-table="tableNodeProps">
<TableNode :inputData=getInputData(tableNodeProps.id) v-bind="tableNodeProps"
@resize="resize"></TableNode>
</template>
<template #node-scrollTable="scrollTableNodeProps">
<ScrollTableNode :inputData=getInputData(scrollTableNodeProps.id) v-bind="scrollTableNodeProps"
@resize="resize"></ScrollTableNode>
</template>
</VueFlow>
</FlowRuler>
</div>
<div class="right">
<div class="tabs">
<div class="tab" :class="{active : tabs === 0}" @click="selectTabs(0)">
属性设置
</div>
<div class="tab" :class="{active : tabs === 1}" @click="selectTabs(1)">
样式设置
</div>
</div>
<div class="tabsItem"></div>
</div>
</div>
</template>
<script setup>
import FlowRuler from './FlowRuler.vue';
import { ArrowDown, View } from '@element-plus/icons-vue';
import * as icon from '@element-plus/icons-vue';
import { MarkerType, useVueFlow, VueFlow } from '@vue-flow/core';
import tool from '@/views/boardGenerate/tool.js';
import { v4 as uuidv4 } from 'uuid';
import { Background } from '@vue-flow/background';
import CarouselNode from '@/views/boardGenerate/nodes/board/carouselNode.vue';
import CustomBoardNode from '@/views/boardGenerate/nodes/board/customBoardNode.vue';
import DataNode from '@/views/boardGenerate/nodes/data/dataNode.vue';
import ImgNode from '@/views/boardGenerate/nodes/form/imgNode.vue';
import TimelineNode from '@/views/boardGenerate/nodes/form/timelineNode.vue';
import ScrollTableNode from '@/views/boardGenerate/nodes/form/scrollTableNode.vue';
import TextNode from '@/views/boardGenerate/nodes/form/textNode.vue';
import CurveNode from '@/views/boardGenerate/nodes/board/curveNode.vue';
import PieNode from '@/views/boardGenerate/nodes/board/pieNode.vue';
import LineNode from '@/views/boardGenerate/nodes/board/lineNode.vue';
import MultiLinesNode from '@/views/boardGenerate/nodes/board/multiLinesNode.vue';
import BackgroundBarNode from '@/views/boardGenerate/nodes/board/backgroundBarNode.vue';
import MultiCurvesNode from '@/views/boardGenerate/nodes/board/multiCurvesNode.vue';
import DigitalFlopNode from '@/views/boardGenerate/nodes/form/digitalFlopNode.vue';
import NightingaleRoseDiagramNode from '@/views/boardGenerate/nodes/board/nightingaleRoseDiagramNode.vue';
import IconNode from '@/views/boardGenerate/nodes/form/iconNode.vue';
import InputNode from '@/views/boardGenerate/nodes/form/inputNode.vue';
import TimeNode from '@/views/boardGenerate/nodes/form/timeNode.vue';
import TableNode from '@/views/boardGenerate/nodes/form/tableNode.vue';
import MultiBarsNode from '@/views/boardGenerate/nodes/board/multiBarsNode.vue';
import VideoNode from '@/views/boardGenerate/nodes/form/videoNode.vue';
import BarNode from '@/views/boardGenerate/nodes/board/barNode.vue';
import CustomDataNode from '@/views/boardGenerate/nodes/data/customDataNode.vue';
import AreaNode from '@/views/boardGenerate/nodes/other/areaNode.vue';
import StaticDataNode from '@/views/boardGenerate/nodes/data/staticDataNode.vue';
import MapNode from '@/views/boardGenerate/nodes/form/mapNode.vue';
import { getDataSourceList } from '@/views/boardGenerate/api/dataSource.js';
import { getBoardApi } from '@/views/boardGenerate/api/boardList.js';
const { onDragStart, onDrop, onDragOver } = tool();
const router = useRouter();
const {
addEdges,
updateNode,
removeNodes,
addNodes
} = useVueFlow();
onMounted(async () => {
icons.value = Object.keys(icon);
loading.value = true;
getDataSourceList({
pageNum: 1,
pageSize: 9999999
})
.then((res) => {
customData.value = res.rows.map(e => {
return {
name: e.dataSourceName,
url: e.requestUrl,
method: e.requestMethod,
outputData: e.designDataFieldList
};
});
});
customBoard.value = JSON.parse(localStorage.getItem('BOARDNODE') || '[]');
await nextTick();
getBoardApi(router.currentRoute.value.query.id)
.then((res) => {
let data = res.data;
boardData.value = data;
nodes.value = data.designPagePointList?.length !== 0 ? data.designPagePointList.sort((a, b) => a.fieldOne - b.fieldOne).map(e => {
let data = {};
let savaField = ['customData', 'options'];
let dataContent = JSON.parse(e.dataContent) || {};
Object.keys(dataContent).forEach((key) => {
if (savaField.includes(key)) {
data[key] = dataContent[key];
} else {
if (Array.isArray(dataContent[key])) {
data[key] = [];
} else if (dataContent[key] && typeof dataContent[key] === 'object' && !Array.isArray(dataContent[key])) {
data[key] = {};
} else {
data[key] = null;
}
}
});
return {
id: e.pagePointId,
name: e.pagePointName,
dimensions: {
width: e.width,
height: e.height
},
position: {
x: e.posX,
y: e.posY
},
type: e.pointType,
data: JSON.parse(e.dataContent)
};
}) : [{
id: `area_${uuidv4().replaceAll('-', '_')}`,
name: 'area',
type: 'area',
position: {
x: 0,
y: 0
},
data: {}
}];
edges.value = data.designPageEdgesList.map(e => {
return {
id: e.pageEdgesId,
source: e.sourceNodeId,
target: e.targetNodeId,
type: e.edgeType,
targetHandle: e.targetHandleId,
sourceHandle: e.sourceHandleId
};
}) || [];
pageData.value = JSON.parse(data.customContent) || {};
})
.finally(() => {
loading.value = false;
});
});
const icons = ref([]);
const loading = ref(false);
const nodes = ref([{
id: `area_${uuidv4().replaceAll('-', '_')}`,
name: 'area',
type: 'area',
position: {
x: 0,
y: 0
},
data: {}
}]);
const edges = ref([]);
const customData = ref([]);
const customBoard = ref([]);
const boardData = ref({});
const pageData = ref({});
const tabs = ref(0);
const logEvent = async (eventname, event) => {
switch (eventname) {
case 'connect':
if (!edges.value.some(r => r.id === `${event.source}---${event.target}`)) {
addEdges({
id: `${event.source}---${event.target}`,
source: event.source,
target: event.target,
type: 'bezier',
animated: true,
markerEnd: MarkerType.ArrowClosed,
sourceHandle: event.sourceHandle,
style: { stroke: '#409EFF' }
});
}
break;
case 'paneClick':
nodeAttrForm.value = {};
nodeDataForm.value = {};
customDataForm.value = {};
break;
case 'click':
nodeAttrForm.value = event.node.data.options;
nodeDataForm.value = event.node;
customDataForm.value = event.node.data.customData;
break;
case 'nodeDrag':
console.log(event.nodes);
if (event.nodes.length === 1) {
nodeAttrForm.value = event.node.data.options;
nodeDataForm.value = event.node;
customDataForm.value = event.node.data.customData;
} else {
nodeAttrForm.value = {};
nodeDataForm.value = {};
customDataForm.value = {};
}
break;
case 'contextmenu':
console.log('contextmenu', event);
}
};
const resize = (e, id) => {
nodes.value.forEach((item) => {
if (item.selected && item.id !== id) {
item.dimensions = {
width: e.params.width,
height: e.params.height
};
}
});
};
const getInputData = (e) => {
let outputData = {};
let nodeIds = edges.value.map(v => {
if (v.target === e) {
return v.source;
}
});
nodes.value.forEach(v => {
if (nodeIds.includes(v.id)) {
outputData = {
...outputData,
...v.data.outputData
};
}
});
return outputData;
};
const selectTabs = (e) => {
tabs.value = e;
};
</script>
<style scoped lang="less">
:deep(.vue-flow__node-area) {
z-index: -1 !important;
pointer-events: none !important;
}
.boardGenerate {
width: 100%;
height: 100%;
@ -109,7 +683,7 @@ import { ArrowDown, View } from '@element-plus/icons-vue';
.top {
width: 100%;
height: var(--boardGenerateTopHeight);
background-color: #1F2224;
background-color: #1C1F20;
border-bottom: 1px solid #000;
}
@ -118,7 +692,7 @@ import { ArrowDown, View } from '@element-plus/icons-vue';
display: inline-block;
height: calc(100vh - var(--boardGenerateTopHeight));
overflow: auto;
background-color: #1F2224;
background-color: #1C1F20;
border-right: 1px solid #000;
.title {
@ -160,21 +734,73 @@ import { ArrowDown, View } from '@element-plus/icons-vue';
}
.center {
width: calc(100% - 400px);
width: calc(100% - 500px);
display: inline-block;
background-color: #1F2224;
background-color: #1C1F20;
height: calc(100vh - var(--boardGenerateTopHeight));
overflow: auto;
}
.right {
width: 200px;
width: 300px;
display: inline-block;
height: calc(100vh - var(--boardGenerateTopHeight));
overflow: auto;
background-color: #1F2224;
background-color: #1C1F20;
border-left: 1px solid #000;
.tabs {
display: flex;
border-bottom: 1px solid black;
background-color: #1C1F20;
.tab {
padding: 8px 16px;
font-size: 14px;
background: transparent;
cursor: pointer;
color: #ccc;
}
.tab.active {
background: #222;
color: #fff;
border-bottom: none;
border-radius: 4px 4px 0 0;
position: relative;
top: 1px;
z-index: 1;
}
}
.tabsItem {
width: 100%;
height: calc(100% - 50px);
background-color: #222;
}
}
}
.moduleCard {
width: 80px;
vertical-align: top;
:deep(.el-card__body) {
height: 40px;
padding: 0 !important;
}
.moduleText {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
text-align: center;
font-size: 12px;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
</style>

Loading…
Cancel
Save