修改组态化

master
夜笙歌 2 months ago
parent 7ad9739095
commit 8588bd27ab

File diff suppressed because one or more lines are too long

@ -52,6 +52,14 @@
<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>
<template v-for="i in customBoard">
<el-card class="moduleCard" shadow="never" :draggable="true"
@dragstart="onDragStart($event, 'customBoard',i)"
@ -143,6 +151,8 @@
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"
>
@ -183,6 +193,10 @@
<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-data="dataNodeProps">
<DataNode :inputData=getInputData(dataNodeProps.id) v-bind="dataNodeProps"
@resize="resize"></DataNode>
@ -212,6 +226,22 @@
</div>
<div class="rightPanel">
<el-form :model="nodeAttrForm" label-width="auto" style="max-width: 600px" v-if="nodeAttrForm">
<el-form-item label="默认内容" v-if="Object.keys(nodeAttrForm).includes('defaultInput')">
<el-input v-model="nodeAttrForm.defaultInput" style="width: 100%" />
</el-form-item>
<el-form-item label="默认日期" v-if="Object.keys(nodeAttrForm).includes('defaultTime')">
<el-date-picker
v-model="nodeAttrForm.defaultTime"
type="datetimerange"
range-separator="到"
start-placeholder="开始时间"
end-placeholder="结束时间"
style="width: 100%;height: 100%"
/>
</el-form-item>
<el-form-item label="日期格式" v-if="Object.keys(nodeAttrForm).includes('format')">
<el-input v-model="nodeAttrForm.format" style="width: 100%" />
</el-form-item>
<el-form-item label="输出字段名" v-if="Object.keys(nodeAttrForm).includes('field')">
<el-input v-model="nodeAttrForm.field" />
</el-form-item>
@ -332,6 +362,7 @@ import MultiCurvesNode from './nodes/board/multiCurvesNode.vue';
import BarNode from './nodes/board/barNode.vue';
import MultiBarsNode from './nodes/board/multiBarsNode.vue';
import CustomBoardNode from './nodes/board/customBoardNode.vue';
import PieNode from './nodes/board/pieNode.vue';
import DataNode from './nodes/data/dataNode.vue';
import CustomDataNode from './nodes/data/customDataNode.vue';
import MapNode from './nodes/form/mapNode.vue';
@ -381,7 +412,6 @@ const nodeAttrForm = ref({});
const logEvent = async (eventname, event) => {
switch (eventname) {
case 'connect':
console.log('connect');
if (!edges.value.some(r => r.id === `${event.source}---${event.target}`)) {
addEdges({
id: `${event.source}---${event.target}`,
@ -395,10 +425,19 @@ const logEvent = async (eventname, event) => {
});
}
break;
case 'paneClick':
nodeAttrForm.value = {};
break;
case 'click':
console.log('click', event);
nodeAttrForm.value = event.node.data.options;
break;
case 'nodeDrag':
if (event.nodes.length === 1) {
nodeAttrForm.value = event.node.data.options;
} else {
nodeAttrForm.value = {};
}
break;
case 'contextmenu':
console.log('contextmenu', event);
}
@ -435,7 +474,6 @@ const pageSetting = () => {
pageSettingForm.value = JSON.parse(localStorage.getItem('PAGEDATA'));
};
const save = () => {
console.log(nodes.value);
localStorage.setItem('NODES', JSON.stringify(nodes.value.map(e => {
let data = {};
let savaField = ['customData', 'options'];
@ -462,7 +500,19 @@ const save = () => {
data: data
};
})));
localStorage.setItem('EDGES', JSON.stringify(edges.value));
localStorage.setItem('EDGES', JSON.stringify(edges.value.map(e => {
return {
id: e.id,
source: e.source,
target: e.target,
type: e.type,
animated: e.animated,
markerEnd: e.markerEnd,
targetHandle: e.targetHandle,
sourceHandle: e.sourceHandle,
style: e.style
};
})));
};
const clear = () => {
nodes.value = [{
@ -603,4 +653,9 @@ const setPageData = () => {
border-left: 1px solid #409EFF;
overflow: auto;
}
.avatar {
width: 384px;
height: 216px
}
</style>

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">
@ -90,6 +90,7 @@ onMounted(() => {
});
watch(() => [JSON.parse(JSON.stringify(props.inputData)), JSON.parse(JSON.stringify(props.data.options))], (obj1, obj2) => {
if (JSON.stringify(obj1) !== JSON.stringify(obj2)) {
console.log(getOption());
chart && chart.setOption(getOption(), true);
}
}, { deep: true, immediate: true });

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -0,0 +1,154 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">
<div style="width: 100%;height: 100%" ref="chartRef" />
</div>
<Handle v-if="!props.isView" :id="`${props.id}.-t`" type="target" :position="Position.Left" />
</div>
</template>
<script setup>
import { defineEmits, defineProps, ref } from 'vue';
import { NodeResizer } from '@vue-flow/node-resizer';
import { Handle, Position } from '@vue-flow/core';
import * as echarts from 'echarts';
const props = defineProps({
isView: {
type: Boolean,
required: false
},
inputData: {
type: Object,
required: false
},
id: {
type: String,
required: true
},
isHideHandle: {
type: Boolean,
required: false
},
selected: {
type: Boolean,
required: false
},
data: {
type: Object,
required: true
},
dimensions: {
type: Object,
required: true
}
});
const chartRef = ref();
let chart = null;
const colorList = ['#9E87FF', '#73DDFF', '#fe9a8b', '#F56948', '#9E87FF'];
const getOption = () => {
const chartOption = {
title: {
text: props.data.options.title || '设备运行数量',
textStyle: {
fontSize: 12,
fontWeight: 400,
color: '#fff'
},
left: '0',
top: '5%'
},
legend: {
icon: 'circle',
top: '5%',
right: '5%',
itemWidth: 6,
itemGap: 20,
textStyle: {
color: '#fff'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
label: {
show: true,
backgroundColor: '#fff',
color: '#000',
borderColor: 'rgba(0,0,0,0)',
shadowColor: 'rgba(0,0,0,0)',
shadowOffsetY: 0
},
lineStyle: {
width: 0
}
},
backgroundColor: '#fff',
textStyle: {
color: '#000'
},
padding: [10, 10],
extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5)'
},
grid: {
top: '30%',
bottom: '10%'
},
series: [
{
type: 'pie',
radius: '50%',
label: {
formatter: '{b}: {d}%'
},
}
]
};
let xData = [props.inputData?.x1 || []];
let yData = [props.inputData?.y1 || []];
let length = Math.min(...xData.map(e => e.length), ...yData.map(e => e.length));
let source = [['product', ...[props.data.options?.yNames?.[0] || '数量']]];
Array(length).fill(0).forEach((_, i) => {
let item = [];
xData.forEach(e => {
item.push(e[i]);
});
yData.forEach(e => {
item.push(e[i]);
});
source.push(item);
});
return {
...chartOption,
dataset: {
source
}
};
};
onMounted(() => {
chart = echarts.init(chartRef.value, 'macarons', {
renderer: 'svg' // 使 SVG
});
chart.setOption(getOption(), true);
});
watch(() => [JSON.parse(JSON.stringify(props.inputData)), JSON.parse(JSON.stringify(props.data.options))], (obj1, obj2) => {
if (JSON.stringify(obj1) !== JSON.stringify(obj2)) {
chart && chart.setOption(getOption(), true);
}
}, { deep: true, immediate: true });
const emit = defineEmits(['resize']);
const resize = (e) => {
chart.resize();
emit('resize', e, props.id);
};
</script>
<style scoped>
.custom-node {
width: 100%;
height: 100%;
}
</style>

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -1,9 +1,10 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node" :style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">
<el-input v-model="input" placeholder="输入值" style="width: 100%;height: 100%" />
</div>
<Handle v-if="!props.isView" :id="`${props.id}.-t`" type="target" :position="Position.Left" />
@ -47,11 +48,21 @@ const props = defineProps({
}
});
watch(() => JSON.parse(JSON.stringify(input.value)), () => {
if (props.data?.options?.field) {
props.data.outputData[props.data.options.field] = input.value;
watch(() => [JSON.parse(JSON.stringify(input.value || '')), JSON.parse(JSON.stringify(props.data.options.field))], (obj1, obj2) => {
if (JSON.stringify(obj1) !== JSON.stringify(obj2)) {
if (props.data?.options?.field) {
props.data.outputData[props.data.options.field] = input.value;
}
}
}, { deep: true });
}, { deep: true, immediate: true });
watch(() => JSON.parse(JSON.stringify(props.data.options?.defaultInput || '')), (obj1, obj2) => {
if (JSON.stringify(obj1) !== JSON.stringify(obj2)) {
input.value = props.data.options.defaultInput;
if (props.data?.options?.field) {
props.data.outputData[props.data.options.field] = input.value;
}
}
}, { deep: true, immediate: true });
const emit = defineEmits(['resize']);
const resize = (e) => {
emit('resize', e, props.id);

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected" @resize="resize" />
<div class="custom-node"
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px',pointerEvents:props.isView?'auto': 'none'}">

@ -1,7 +1,7 @@
<template>
<div
:style="{width:props.dimensions.width+'px',height:props.dimensions.height+'px'}">
<NodeResizer color="#000" v-if="!props.isView && !props.isHideHandle && props.selected"
<NodeResizer color="#fff" v-if="!props.isView && !props.isHideHandle && props.selected"
@resize="resize" />
<div class="custom-node"
@ -13,6 +13,7 @@
start-placeholder="开始时间"
end-placeholder="结束时间"
style="width: 100%;height: 100%"
:format="props.data.options.format||'YYYY/MM/DD HH:mm:ss'"
/>
</div>
<Handle v-if="!props.isView" :id="`${props.id}.-t`" type="target" :position="Position.Left" />
@ -56,14 +57,27 @@ const props = defineProps({
}
});
watch(() => JSON.parse(JSON.stringify(value.value)), () => {
if (props.data?.options?.startTimeId) {
props.data.outputData[props.data.options.startTimeId || 'startTime'] = value.value?.[0];
watch(() => [JSON.parse(JSON.stringify(value.value || '[]')), JSON.parse(JSON.stringify(props.data?.options?.startTimeId)), JSON.parse(JSON.stringify(props.data?.options?.endTimeId))], (obj1, obj2) => {
if (JSON.stringify(obj1) !== JSON.stringify(obj2)) {
if (props.data?.options?.startTimeId) {
props.data.outputData[props.data.options.startTimeId || 'startTime'] = value.value?.[0];
}
if (props.data?.options?.endTimeId) {
props.data.outputData[props.data.options.endTimeId || 'endTime'] = value.value?.[1];
}
}
if (props.data?.options?.endTimeId) {
props.data.outputData[props.data.options.endTimeId || 'endTime'] = value.value?.[1];
}, { deep: true, immediate: true });
watch(() => JSON.parse(JSON.stringify(props.data.options?.defaultTime || '')), (obj1, obj2) => {
if (JSON.stringify(obj1) !== JSON.stringify(obj2)) {
value.value = props.data.options.defaultTime;
if (props.data?.options?.startTimeId) {
props.data.outputData[props.data.options.startTimeId || 'startTime'] = value.value?.[0];
}
if (props.data?.options?.endTimeId) {
props.data.outputData[props.data.options.endTimeId || 'endTime'] = value.value?.[1];
}
}
}, { deep: true });
}, { deep: true, immediate: true });
const emit = defineEmits(['resize']);
const resize = (e) => {
emit('resize', e, props.id);

File diff suppressed because one or more lines are too long

@ -15,6 +15,8 @@ const getOption = (e) => {
return { title: '', yNames: [] };
} else if (e === 'curve' || e === 'multiCurves') {
return { title: '', yNames: [] };
} else if (e === 'pie' ) {
return { title: '', yNames: [] };
} else if (e === 'customBoard') {
return { title: '', yNames: [] };
} else if (e === 'data') {
@ -22,9 +24,9 @@ const getOption = (e) => {
} else if (e === 'map') {
return { dataMap: [] };
} else if (e === 'inputNode') {
return { field: '' };
return { field: '', defaultInput: '' };
} else if (e === 'time') {
return { startTimeId: 'startTime', endTimeId: 'endTime' };
return { startTimeId: 'startTime', endTimeId: 'endTime', defaultTime: [], format: '' };
} else if (e === 'text') {
return { text: '文字', align: '', color: '#fff' };
} else if (e === 'img') {
@ -34,12 +36,18 @@ const getOption = (e) => {
}
};
const getNodeSize = (e) => {
if (e === 'line') {
if (e === 'line' || e === 'multiLines' || e === 'bar' || e === 'multiBars' || e === 'curve' || e === 'multiCurves' || e === 'customBoard'|| e === 'pie') {
return { width: 300, height: 150 };
} else if (e === 'data') {
return { width: 200, height: 50 };
} else if (e === 'data' || e === 'customData') {
return { width: 150, height: 50 };
} else if (e === 'inputNode') {
return { width: 100, height: 30 };
} else if (e === 'text') {
return { width: 100, height: 30 };
} else if (e === 'time') {
return { width: 200, height: 30 };
} else if (e === 'img') {
return { width: 300, height: 300 };
} else if (e === 'map') {
return { width: 100, height: 30 };
} else {

@ -44,6 +44,9 @@
<template v-if="i.type === 'img'">
<ImgNode :isView="true" :inputData=getInputData(i.id) v-bind="i"></ImgNode>
</template>
<template v-if="i.type === 'pie'">
<PieNode :isView="true" :inputData=getInputData(i.id) v-bind="i"></PieNode>
</template>
</div>
</div>
@ -64,6 +67,7 @@ import CustomBoardNode from './nodes/board/customBoardNode.vue';
import CustomDataNode from './nodes/data/customDataNode.vue';
import TextNode from './nodes/form/textNode.vue';
import ImgNode from './nodes/form/imgNode.vue';
import PieNode from '@/views/boardGenerate/nodes/board/pieNode.vue';
const nodes = ref([]);
const edges = ref([]);
@ -97,6 +101,7 @@ onMounted(() => {
<style lang="less" scoped>
.content {
position: absolute;
overflow: hidden;
background-color: #000000;
background-repeat: no-repeat;
background-size: 100% 100%;

Loading…
Cancel
Save