feat: 拓扑编辑分组功能

This commit is contained in:
TsMask
2023-12-29 10:17:31 +08:00
parent a53fd939e1
commit aa0c92a8d1
5 changed files with 690 additions and 106 deletions

View File

@@ -0,0 +1,156 @@
import { message, Form } from 'ant-design-vue/lib';
import { reactive, watch } from 'vue';
import { graphG6 } from './useGraph';
import { number } from 'echarts';
/**图分组内置类型 */
export const comboTypeOptions = [
{
value: 'circle',
label: '圆形',
},
{
value: 'rect',
label: '矩形',
},
];
/**图分组标签文本位置 */
export const comboPositionOptions = [
{
value: 'top',
label: '上',
},
{
value: 'left',
label: '左',
},
{
value: 'right',
label: '右',
},
{
value: 'bottom',
label: '下',
},
{
value: 'center',
label: '居中',
},
];
/**图分组信息状态类型 */
type ComboStateType = {
/**图分组原始数据 */
origin: Record<string, any>;
/**图分组表单数据 */
form: Record<string, any>;
};
/**图分组信息状态 */
export let comboState: ComboStateType = reactive({
origin: {},
form: {
id: '',
type: 'rect',
parentId: '',
size: [40, 40],
padding: [30, 30, 30, 30],
style: {
fill: '#ffffff',
stroke: '#ffffff',
lineWidth: 1,
},
label: '',
labelCfg: {
refX: 10,
refY: 10,
position: 'top',
style: {
fill: '#000000',
fontSize: 12,
fontWeight: 500,
},
},
},
});
/**图分组对话分组内表单属性和校验规则 */
export const comboStateForm = Form.useForm(
comboState.form,
reactive({
id: [{ required: true, message: '分组唯一标识 ID' }],
})
);
/**图分组编辑监听更新视图 */
watch(comboState.form, combo => {
const info = JSON.parse(JSON.stringify(combo));
const comboId = info.id;
if (comboId) {
graphG6.value.clearItemStates(comboId, 'selected');
console.log(info);
const data = graphG6.value.save();
const item = data.combos.find((item: any) => item.id === combo.id);
Object.assign(item, combo);
// 无父组id时不要设置避免导致绘制失败
if (!combo.parentId) {
Reflect.deleteProperty(item, 'parentId');
}
graphG6.value.read(data);
}
});
/**图分组类型输入限制 */
export function handleComboTypeChange(type: any) {
// 类型尺寸和边距
if (type === 'circle') {
comboState.form.size = 30;
comboState.form.padding = 30;
}
if (type === 'rect') {
comboState.form.size = [30, 20];
comboState.form.padding = [10, 20, 10, 20];
}
}
/**图分组新增或更新 */
export function handleOkcombo() {
const combo = JSON.parse(JSON.stringify(comboState.form));
if (!combo.id) {
message.warn({
content: `分组元素ID错误`,
duration: 2,
});
return false;
}
const item = graphG6.value.findById(combo.id);
if (item) {
const data = graphG6.value.save();
const item = data.combos.find((item: any) => item.id === combo.id);
Object.assign(item, combo);
if (!combo.parentId) {
Reflect.deleteProperty(item, 'parentId');
}
graphG6.value.read(data);
} else {
graphG6.value.createCombo(combo, []);
}
comboStateForm.resetFields();
comboState.origin = {};
return true;
}
/**图分组取消还原 */
export function handleCancelcombo() {
const origin = JSON.parse(JSON.stringify(comboState.origin));
if (origin.id) {
const data = graphG6.value.save();
const item = data.combos.find((combo: any) => combo.id === origin.id);
Object.assign(item, origin);
graphG6.value.read(data);
comboStateForm.resetFields();
comboState.origin = {};
}
}

View File

@@ -54,7 +54,7 @@ export const edgePositionOptions = [
},
];
/**边信息状态类型 */
/**边信息状态类型 */
type EdgeStateType = {
/**图边原始数据 */
origin: Record<string, any>;
@@ -62,7 +62,7 @@ type EdgeStateType = {
form: Record<string, any>;
};
/**边信息状态 */
/**边信息状态 */
export let edgeState: EdgeStateType = reactive({
origin: {},
form: {

View File

@@ -57,6 +57,52 @@ const graphCanvasMenu = new Menu({
graphG6.value.refreshItem(edge);
}
});
// 显示框
graphG6.value.getCombos().forEach((combo: any) => {
if (!combo.isVisible()) {
graphG6.value.showItem(combo);
graphG6.value.updateCombo(combo);
}
});
break;
}
},
});
/**图分组Combo 右击菜单 */
const graphComboMenu = new Menu({
offsetX: 6,
offseY: 10,
itemTypes: ['combo'],
getContent(evt) {
console.log(evt);
return `
<div
style="
display: flex;
flex-direction: column;
width: 140px;
background: #e6f7ff;
"
>
<div id="edit" style="cursor: pointer; margin-bottom: 2px">
1. 编辑
</div>
<div id="hide" style="cursor: pointer; margin-bottom: 2px">
2. 隐藏
</div>
</div>
`;
},
handleMenuClick(target, item) {
console.log(target, item);
const targetId = target.id;
switch (targetId) {
case 'edit':
graphEvent.value = { type: `combo-${targetId}`, target, item };
break;
case 'hide':
graphG6.value.hideItem(item);
break;
}
},
@@ -92,7 +138,7 @@ const graphNodeMenu = new Menu({
const targetId = target.id;
switch (targetId) {
case 'edit':
graphEvent.value = { type: `nodeMenu-${targetId}`, target, item };
graphEvent.value = { type: `node-${targetId}`, target, item };
break;
case 'hide':
graphG6.value.hideItem(item);
@@ -148,7 +194,7 @@ const graphEdgeMenu = new Menu({
const targetId = target.id;
switch (targetId) {
case 'edit':
graphEvent.value = { type: `edgeMenu-${targetId}`, target, item };
graphEvent.value = { type: `edge-${targetId}`, target, item };
break;
case 'hide':
graphG6.value.hideItem(item);
@@ -235,11 +281,15 @@ function fnGraphEvent(graph: Graph) {
/**图元素选择开始结束点 */
export const selectSourceTargetOptions = ref<Record<string, any>[]>([]);
/**图元素选择嵌入框 */
export const selectComboOptions = ref<Record<string, any>[]>([]);
/**
* 图元素选择开始结束点数据获取
*/
function fnSelectSourceTargetOptionsData() {
// 节点
selectSourceTargetOptions.value = [];
graphG6.value.getNodes().forEach((node: any) => {
const info = JSON.parse(JSON.stringify(node.getModel()));
selectSourceTargetOptions.value.push({
@@ -249,13 +299,21 @@ function fnSelectSourceTargetOptionsData() {
});
});
// 框
graphG6.value.getCombos().forEach((combo1: any) => {
const info = JSON.parse(JSON.stringify(combo1.getModel()));
selectSourceTargetOptions.value.push({
selectComboOptions.value = [
{
value: '',
label: '未分配',
},
];
graphG6.value.getCombos().forEach((combo: any) => {
const info = JSON.parse(JSON.stringify(combo.getModel()));
const comboInfo = {
value: info.id,
label: info.label,
info,
});
};
selectSourceTargetOptions.value.push(comboInfo);
selectComboOptions.value.push(comboInfo);
});
}
@@ -271,12 +329,6 @@ export function handleRanderGraph(container: HTMLElement, data: GraphData) {
animate: true,
fitCenter: true,
modes: {
// default: [
// // 允许拖拽画布、放缩画布、拖拽节点
// 'drag-canvas',
// 'zoom-canvas',
// 'drag-node',
// ],
default: [
{
type: 'click-select',
@@ -315,7 +367,7 @@ export function handleRanderGraph(container: HTMLElement, data: GraphData) {
// ranksep: 10,
// nodesep: 10,
// },
// 全局节点 矩形
// 全局节点
defaultNode: {
type: 'rect',
size: [80, 40],
@@ -344,7 +396,7 @@ export function handleRanderGraph(container: HTMLElement, data: GraphData) {
},
direction: 'up', // triangle 三角形的方向
},
// 全局边 三次贝塞尔曲线
// 全局边
defaultEdge: {
type: 'polyline',
style: {
@@ -366,19 +418,33 @@ export function handleRanderGraph(container: HTMLElement, data: GraphData) {
},
},
},
// defaultEdge: {
// type: 'line',
// },
// 全局框节点 矩形
// 全局框节点
defaultCombo: {
type: 'rect', // Combo 类型
size: [40, 40],
padding: [30, 30, 30, 30],
style: {
fillOpacity: 0.1,
radius: 2,
fill: '#ffffff',
stroke: '#ffffff',
lineWidth: 1,
cursor: 'grab',
fillOpacity: 0.5,
},
labelCfg: {
refX: 10,
refY: 10,
position: 'top',
style: {
fill: '#000000',
fontSize: 12,
fontWeight: 500,
},
},
},
plugins: [
graphCanvasMenu,
graphComboMenu,
graphNodeMenu,
graphNodeTooltip,
graphEdgeMenu,

View File

@@ -98,10 +98,11 @@ export let nodeState: NodeStateType = reactive({
origin: {},
form: {
id: '',
comboId: '',
x: 0,
y: 0,
type: 'circle',
size: [0],
size: 30,
anchorPoints: false,
style: {
fill: '#ffffff',
@@ -133,6 +134,7 @@ export const nodeStateForm = Form.useForm(
/**图节点编辑监听更新视图 */
watch(nodeState.form, node => {
const info = JSON.parse(JSON.stringify(node));
console.log(info);
const nodeId = info.id;
if (nodeId) {
// 图片类型需要移除style属性避免填充
@@ -142,23 +144,33 @@ watch(nodeState.form, node => {
graphG6.value.clearItemStates(nodeId, 'selected');
graphG6.value.updateItem(nodeId, info);
// 三角和图片的样式变更需要重绘才生效
if (info.type === 'triangle' || info.type === 'image') {
if (
info.type === 'triangle' ||
info.type === 'image' ||
info.comboId !== nodeState.origin.comboId
) {
graphG6.value.read(graphG6.value.save());
}
}
});
/**图节点类型输入限制 */
export function handleTypeChange(type: any) {
export function handleNodeTypeChange(type: any) {
// 设置图标属性
if (['circle', 'ellipse', 'diamond', 'star', 'donut'].includes(type)) {
const origin = nodeState.origin;
if (origin.icon) {
nodeState.form = Object.assign(nodeState.form, {
size: origin.size,
icon: origin.icon,
});
} else {
let size: number[] | number = [30];
if (['circle', 'star', 'donut'].includes(type)) {
size = 30;
}
nodeState.form = Object.assign(nodeState.form, {
size,
icon: {
show: false,
img: '',
@@ -172,11 +184,13 @@ export function handleTypeChange(type: any) {
const origin = nodeState.origin;
if (origin.icon) {
nodeState.form = Object.assign(nodeState.form, {
size: 40,
direction: origin.direction || 'up', // triangle 三角形的方向
icon: Object.assign({ offset: 20 }, origin.icon),
});
} else {
nodeState.form = Object.assign(nodeState.form, {
size: 30,
direction: 'up', // triangle 三角形的方向
icon: {
show: false,
@@ -193,11 +207,13 @@ export function handleTypeChange(type: any) {
const origin = nodeState.origin;
if (origin.img) {
nodeState.form = Object.assign(nodeState.form, {
size: [30, 30],
img: origin.img,
clipCfg: origin.clipCfg,
});
} else {
nodeState.form = Object.assign(nodeState.form, {
size: [30, 30],
img: '/svg/service.svg',
clipCfg: {
show: false,
@@ -222,35 +238,6 @@ export function handleTypeChange(type: any) {
}
}
/**图节点大小输入限制 */
export function handleSizeChange(value: any) {
// 处理格式
let intArr: number[] = [];
for (const v of value) {
const intV = parseInt(v);
if (!isNaN(intV)) {
intArr.push(intV);
}
}
// 节点类型限制size
const nodeType = nodeState.form.type;
switch (nodeType) {
case 'circle':
case 'star':
case 'donut':
intArr = intArr.slice(0, 1);
break;
case 'rect':
case 'ellipse':
case 'diamond':
case 'triangle':
case 'image':
intArr = intArr.slice(0, 2);
break;
}
nodeState.form.size = intArr;
}
/**图节点新增或更新 */
export function handleOkNode() {
const node = JSON.parse(JSON.stringify(nodeState.form));
@@ -270,7 +257,11 @@ export function handleOkNode() {
graphG6.value.addItem('node', node);
}
// 三角和图片的样式变更需要重绘才生效
if (node.type === 'triangle' || node.type === 'image') {
if (
node.type === 'triangle' ||
node.type === 'image' ||
node.comboId !== nodeState.origin.comboId
) {
graphG6.value.read(graphG6.value.save());
}
nodeStateForm.resetFields();
@@ -284,10 +275,13 @@ export function handleCancelNode() {
if (origin.id) {
graphG6.value.updateItem(origin.id, origin);
// 三角和图片的样式变更需要重绘才生效
if (origin.type === 'triangle' || origin.type === 'image') {
if (
origin.type === 'triangle' ||
origin.type === 'image' ||
origin.comboId !== nodeState.form.comboId
) {
graphG6.value.read(graphG6.value.save());
}
console.log(JSON.parse(JSON.stringify(nodeState.form)));
nodeStateForm.resetFields();
nodeState.origin = {};
}

View File

@@ -4,12 +4,13 @@ import { PageContainer } from 'antdv-pro-layout';
import useI18n from '@/hooks/useI18n';
import {
handleRanderGraph,
handleChangeMode,
graphEvent,
graphG6,
selectSourceTargetOptions,
selectComboOptions,
graphMode,
graphModeOptions,
handleChangeMode,
} from './hooks/useGraph';
import {
edgeTypeOptions,
@@ -25,13 +26,21 @@ import {
nodeDirectionOptions,
nodeImageClipCfgOptions,
nodeImageOptions,
handleTypeChange,
handleSizeChange,
handleNodeTypeChange,
handleOkNode,
handleCancelNode,
nodeState,
nodeStateForm,
} from './hooks/useNode';
import {
comboState,
comboStateForm,
comboTypeOptions,
comboPositionOptions,
handleComboTypeChange,
handleOkcombo,
handleCancelcombo,
} from './hooks/useCombo';
const { t } = useI18n();
@@ -44,7 +53,8 @@ watch(graphEvent, v => {
const { type, target, item } = v;
console.log(type, target, item);
if (type === 'edgeMenu-edit' && item) {
// 边
if (type === 'edge-edit' && item) {
const edge = item.getModel();
edgeState.origin = JSON.parse(JSON.stringify(edge));
edgeState.form = Object.assign(edgeState.form, edge);
@@ -52,18 +62,30 @@ watch(graphEvent, v => {
modalState.formType = 'edge';
modalState.visible = true;
}
if (type === 'nodeMenu-edit' && item) {
// 节点
if (type === 'node-edit' && item) {
const node = item.getModel();
console.log(node.comboId);
nodeState.origin = JSON.parse(JSON.stringify(node));
nodeState.form = Object.assign(nodeState.form, node);
modalState.title = '节点信息编辑';
modalState.formType = 'node';
modalState.visible = true;
}
// 分组
if (type === 'combo-edit' && item) {
const combo = item.getModel();
console.log(JSON.parse(JSON.stringify(combo)));
comboState.origin = JSON.parse(JSON.stringify(combo));
comboState.form = Object.assign(comboState.form, combo);
modalState.title = '框信息编辑';
modalState.formType = 'combo';
modalState.visible = true;
}
});
/**图数据 */
const graphG6Data2 = reactive<Record<string, any>>({
const graphG6Data = reactive<Record<string, any>>({
nodes: [
// 0 基站
{
@@ -116,6 +138,7 @@ const graphG6Data2 = reactive<Record<string, any>>({
id: '2',
x: 50,
y: 450,
size: 23,
label: 'O&M',
type: 'triangle',
icon: {
@@ -360,7 +383,7 @@ const graphG6Data2 = reactive<Record<string, any>>({
],
});
const graphG6Data = reactive<Record<string, any>>({
const graphG6Data2 = reactive<Record<string, any>>({
nodes: [
{
id: '0',
@@ -2730,7 +2753,7 @@ type ModalStateType = {
/**标题 */
title: string;
/**图元素表单类型 */
formType: 'edge' | 'node';
formType: 'edge' | 'node' | 'combo';
/**确定按钮 loading */
confirmLoading: boolean;
};
@@ -2750,20 +2773,22 @@ let modalState: ModalStateType = reactive({
function fnModalOk() {
modalState.confirmLoading = true;
const type = modalState.formType;
let result = false;
// 边编辑确认
if (type === 'edge') {
const result = handleOkEdge();
console.log(type, result);
modalState.visible = !result;
modalState.confirmLoading = !result;
result = handleOkEdge();
}
// 节点编辑确认
if (type === 'node') {
const result = handleOkNode();
console.log(type, result);
modalState.visible = !result;
modalState.confirmLoading = !result;
result = handleOkNode();
}
// 分租编辑确认
if (type === 'combo') {
result = handleOkcombo();
}
console.log(type, result);
modalState.visible = !result;
modalState.confirmLoading = !result;
}
/**
@@ -2781,6 +2806,10 @@ function fnModalCancel() {
if (type === 'node') {
handleCancelNode();
}
// 分租编辑还原
if (type === 'combo') {
handleCancelcombo();
}
}
/**保存图数据 */
@@ -2863,14 +2892,273 @@ function fnGraphLoad() {
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<!-- 节点排版 -->
<!-- 排版 -->
<a-form
v-if="modalState.formType === 'node'"
name="modalStateFromEdge"
v-if="modalState.formType === 'combo'"
name="modalStateFromCombo"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-form-item
label="父节点分组"
name="parentId"
help="将当前分组点放入到另一个分组框中"
:label-col="{ span: 3 }"
>
<a-select
v-model:value="comboState.form.parentId"
:options="selectComboOptions"
:placeholder="t('common.selectPlease')"
>
</a-select>
</a-form-item>
<a-form-item
label="分组ID"
name="type"
:label-col="{ span: 3 }"
v-bind="comboStateForm.validateInfos.id"
>
<a-input
v-model:value="comboState.form.id"
allow-clear
:placeholder="t('common.inputPlease')"
:disabled="comboState.form.id !== ''"
></a-input>
</a-form-item>
<a-form-item
label="节点类型"
name="type"
:label-col="{ span: 3 }"
v-bind="comboStateForm.validateInfos.type"
>
<a-select
v-model:value="comboState.form.type"
:options="comboTypeOptions"
@change="handleComboTypeChange"
:placeholder="t('common.selectPlease')"
>
</a-select>
</a-form-item>
<!-- 圆形尺寸 -->
<a-row :gutter="16" v-if="comboState.form.type === 'circle'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="最小尺寸" name="size" help="半径">
<a-input-number
:min="0"
:max="99"
v-model:value="comboState.form.size"
></a-input-number>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="内边距" name="padding">
<a-input-number
:min="0"
:max="99"
v-model:value="comboState.form.padding"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<!-- 矩形尺寸 -->
<a-row :gutter="16" v-if="comboState.form.type === 'rect'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="最小尺寸"
name="size"
:help="['长', '高'].join('、')"
>
<a-input-group compact>
<a-input-number
v-for="(_, i) in comboState.form.size"
:key="i"
:title="['长', '高'][i]"
style="width: calc(100% / 2)"
:min="0"
:max="99"
v-model:value="comboState.form.size[i]"
></a-input-number>
</a-input-group>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="内边距"
name="padding"
:help="['上', '左', '下', '右'].join('、')"
>
<a-input-group compact>
<a-input-number
v-for="(_, i) in comboState.form.padding"
:key="i"
:title="['上', '左', '下', '右'][i]"
style="width: calc(100% / 4)"
:min="0"
:max="99"
v-model:value="comboState.form.padding[i]"
></a-input-number>
</a-input-group>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="节点填充色" name="fill">
<a-input
v-model:value="comboState.form.style.fill"
type="color"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="透明值" name="fillOpacity">
<a-input-number
v-model:value="comboState.form.style.fillOpacity"
style="width: 100%"
:min="0.1"
:max="1"
:step="0.1"
placeholder="<=100"
></a-input-number>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="描边颜色" name="stroke">
<a-input
v-model:value="comboState.form.style.stroke"
type="color"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="描边宽度" name="lineWidth">
<a-input-number
v-model:value="comboState.form.style.lineWidth"
style="width: 100%"
:min="1"
:max="100"
placeholder="<=100"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<a-divider orientation="left"> 标签文本及其配置 </a-divider>
<a-form-item
label="标签文本"
name="label"
:label-col="{ span: 3 }"
help="文本文字,如果没有则不会显示"
>
<a-input
v-model:value="comboState.form.label"
allow-clear
:placeholder="t('common.inputPlease')"
>
</a-input>
</a-form-item>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本颜色" name="fill">
<a-input
v-model:value="comboState.form.labelCfg.style.fill"
type="color"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本大小" name="fontSize">
<a-input-number
v-model:value="comboState.form.labelCfg.style.fontSize"
style="width: 100%"
:min="10"
:max="100"
placeholder="<=100"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="x偏移"
name="labelCfg.refX"
help="标签在 x 方向的偏移量"
>
<a-input-number
v-model:value="comboState.form.labelCfg.refX"
style="width: 100%"
:min="-100"
:max="100"
placeholder="<=100"
></a-input-number>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="y偏移"
name="labelCfg.refY"
help="标签在 y 方向的偏移量"
>
<a-input-number
v-model:value="comboState.form.labelCfg.refY"
style="width: 100%"
:min="-100"
:max="100"
placeholder="<=100"
></a-input-number>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="位置"
name="labelCfg.position"
help="标签文本相对于边的位置"
>
<a-select
v-model:value="comboState.form.labelCfg.position"
:options="comboPositionOptions"
>
</a-select>
</a-form-item>
</a-col>
</a-row>
</a-form>
<!-- 节点排版 -->
<a-form
v-if="modalState.formType === 'node'"
name="modalStateFromNode"
layout="horizontal"
:label-col="{ span: 6 }"
:labelWrap="true"
>
<a-form-item
label="节点分组"
name="comboId"
help="将节点放入到分组框中"
:label-col="{ span: 3 }"
>
<a-select
v-model:value="nodeState.form.comboId"
:options="selectComboOptions"
:placeholder="t('common.selectPlease')"
>
</a-select>
</a-form-item>
<a-form-item
label="节点ID"
name="type"
@@ -2894,7 +3182,7 @@ function fnGraphLoad() {
<a-select
v-model:value="nodeState.form.type"
:options="nodeTypeOptions"
@change="handleTypeChange"
@change="handleNodeTypeChange"
:placeholder="t('common.selectPlease')"
>
</a-select>
@@ -2921,32 +3209,110 @@ function fnGraphLoad() {
</a-col>
</a-row>
<a-form-item
label="节点大小"
name="size"
help="根据节点类型区分大小是否是数组"
:label-col="{ span: 3 }"
>
<a-select
v-model:value="nodeState.form.size"
mode="tags"
style="width: 100%"
:token-separators="[',']"
@change="handleSizeChange"
:placeholder="t('common.inputPlease')"
></a-select>
</a-form-item>
<a-row :gutter="16">
<a-col
:lg="12"
:md="12"
:xs="24"
v-if="nodeState.form.type === 'circle'"
>
<a-form-item
label="节点大小"
name="size"
help="直径, 圆心位置对应节点的位置"
>
<a-input-number
v-model:value="nodeState.form.size"
style="width: 100%"
:placeholder="t('common.inputPlease')"
></a-input-number>
</a-form-item>
</a-col>
<a-col
:lg="12"
:md="12"
:xs="24"
v-else-if="nodeState.form.type === 'star'"
>
<a-form-item
label="节点大小"
name="size"
help="星形的大小, 星星的中心位置是节点的位置"
>
<a-input-number
v-model:value="nodeState.form.size"
style="width: 100%"
:placeholder="t('common.inputPlease')"
></a-input-number>
</a-form-item>
</a-col>
<a-col
:lg="12"
:md="12"
:xs="24"
v-else-if="nodeState.form.type === 'donut'"
>
<a-form-item
label="节点大小"
name="size"
help="直径, 圆心位置对应节点的位置"
>
<a-input-number
v-model:value="nodeState.form.size"
style="width: 100%"
:placeholder="t('common.inputPlease')"
></a-input-number>
</a-form-item>
</a-col>
<a-col
:lg="12"
:md="12"
:xs="24"
v-else-if="nodeState.form.type === 'triangle'"
>
<a-form-item
label="节点大小"
name="size"
help="边长, 三角形的中心位置是节点的位置"
>
<a-input-number
v-model:value="nodeState.form.size"
style="width: 100%"
:placeholder="t('common.inputPlease')"
></a-input-number>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24" v-else>
<a-form-item
label="节点大小"
name="size"
:help="
nodeState.form.type === 'ellipse'
? ['长轴直径', '短轴直径'].join('、')
: ['宽', '高'].join('、')
"
>
<a-input-group compact>
<a-input-number
v-for="(_, i) in nodeState.form.size"
:key="i"
:title="
nodeState.form.type === 'ellipse'
? ['长轴直径', '短轴直径'][i]
: ['宽', '高'][i]
"
style="width: calc(100% / 2)"
:min="0"
:max="99"
v-model:value="nodeState.form.size[i]"
></a-input-number>
</a-input-group>
</a-form-item>
</a-col>
</a-row>
<template v-if="nodeState.form.type !== 'image'">
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="节点填充色" name="fill">
<a-input
v-model:value="nodeState.form.style.fill"
type="color"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="描边颜色" name="stroke">
<a-input
@@ -2966,6 +3332,14 @@ function fnGraphLoad() {
></a-input-number>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="节点填充色" name="fill">
<a-input
v-model:value="nodeState.form.style.fill"
type="color"
></a-input>
</a-form-item>
</a-col>
<a-col
:lg="12"
:md="12"
@@ -3086,7 +3460,7 @@ function fnGraphLoad() {
:custom-request="(v: any) => console.log(v)"
:disabled="true"
>
<a-button type="primary" :loading="true">
<a-button type="primary" :loading="false">
<template #icon>
<UploadOutlined />
</template>
@@ -3231,12 +3605,6 @@ function fnGraphLoad() {
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="图标来源" name="icon.img">
<a-input
v-model:value="nodeState.form.icon.img"
allow-clear
:placeholder="t('common.inputPlease')"
>
</a-input>
<a-auto-complete
v-model:value="nodeState.form.icon.img"
:options="nodeImageOptions"