feat: 拓扑编辑多语言函数处理
This commit is contained in:
1150
src/views/monitor/topology-build/components/GraphEditModal.vue
Normal file
1150
src/views/monitor/topology-build/components/GraphEditModal.vue
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
import { message, Form } from 'ant-design-vue/lib';
|
import { message, Form } from 'ant-design-vue/lib';
|
||||||
import { reactive, watch } from 'vue';
|
import { reactive, watch } from 'vue';
|
||||||
import { graphG6 } from './useGraph';
|
import { graphG6 } from './useGraph';
|
||||||
import { number } from 'echarts';
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
|
||||||
/**图分组内置类型 */
|
/**图分组内置类型 */
|
||||||
export const comboTypeOptions = [
|
export const comboTypeOptions = [
|
||||||
@@ -39,118 +39,130 @@ export const comboPositionOptions = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**图分组信息状态类型 */
|
export default function useCombo() {
|
||||||
type ComboStateType = {
|
const { t } = useI18n();
|
||||||
/**图分组原始数据 */
|
|
||||||
origin: Record<string, any>;
|
|
||||||
/**图分组表单数据 */
|
|
||||||
form: Record<string, any>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**图分组信息状态 */
|
/**图分组信息状态类型 */
|
||||||
export let comboState: ComboStateType = reactive({
|
type ComboStateType = {
|
||||||
origin: {},
|
/**图分组原始数据 */
|
||||||
form: {
|
origin: Record<string, any>;
|
||||||
id: '',
|
/**图分组表单数据 */
|
||||||
type: 'rect',
|
form: Record<string, any>;
|
||||||
parentId: '',
|
};
|
||||||
size: [40, 40],
|
|
||||||
padding: [30, 30, 30, 30],
|
/**图分组信息状态 */
|
||||||
style: {
|
let comboState: ComboStateType = reactive({
|
||||||
fill: '#ffffff',
|
origin: {},
|
||||||
stroke: '#ffffff',
|
form: {
|
||||||
lineWidth: 1,
|
id: '',
|
||||||
},
|
type: 'rect',
|
||||||
label: '',
|
parentId: '',
|
||||||
labelCfg: {
|
size: [40, 40],
|
||||||
refX: 10,
|
padding: [30, 30, 30, 30],
|
||||||
refY: 10,
|
|
||||||
position: 'top',
|
|
||||||
style: {
|
style: {
|
||||||
fill: '#000000',
|
fill: '#ffffff',
|
||||||
fontSize: 12,
|
stroke: '#ffffff',
|
||||||
fontWeight: 500,
|
lineWidth: 1,
|
||||||
|
},
|
||||||
|
label: '',
|
||||||
|
labelCfg: {
|
||||||
|
refX: 10,
|
||||||
|
refY: 10,
|
||||||
|
position: 'top',
|
||||||
|
style: {
|
||||||
|
fill: '#000000',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
|
|
||||||
/**图分组对话分组内表单属性和校验规则 */
|
/**图分组对话分组内表单属性和校验规则 */
|
||||||
export const comboStateForm = Form.useForm(
|
const comboStateForm = Form.useForm(
|
||||||
comboState.form,
|
comboState.form,
|
||||||
reactive({
|
reactive({
|
||||||
id: [{ required: true, message: '分组唯一标识 ID' }],
|
id: [{ required: true, message: '分组唯一标识 ID' }],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
/**图分组编辑监听更新视图 */
|
/**图分组编辑监听更新视图 */
|
||||||
watch(comboState.form, combo => {
|
watch(comboState.form, combo => {
|
||||||
const info = JSON.parse(JSON.stringify(combo));
|
const info = JSON.parse(JSON.stringify(combo));
|
||||||
const comboId = info.id;
|
const comboId = info.id;
|
||||||
if (comboId) {
|
if (comboId) {
|
||||||
graphG6.value.clearItemStates(comboId, 'selected');
|
graphG6.value.clearItemStates(comboId, 'selected');
|
||||||
console.log(info);
|
console.log(info);
|
||||||
const data = graphG6.value.save();
|
const data = graphG6.value.save();
|
||||||
const item = data.combos.find((item: any) => item.id === combo.id);
|
const item = data.combos.find((item: any) => item.id === combo.id);
|
||||||
Object.assign(item, combo);
|
Object.assign(item, combo);
|
||||||
// 无父组id时不要设置,避免导致绘制失败
|
// 无父组id时不要设置,避免导致绘制失败
|
||||||
if (!combo.parentId) {
|
if (!combo.parentId) {
|
||||||
Reflect.deleteProperty(item, 'parentId');
|
Reflect.deleteProperty(item, 'parentId');
|
||||||
|
}
|
||||||
|
graphG6.value.read(data);
|
||||||
}
|
}
|
||||||
graphG6.value.read(data);
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图分组类型输入限制 */
|
/**图分组类型输入限制 */
|
||||||
export function handleComboTypeChange(type: any) {
|
function handleComboTypeChange(type: any) {
|
||||||
// 类型尺寸和边距
|
// 类型尺寸和边距
|
||||||
if (type === 'circle') {
|
if (type === 'circle') {
|
||||||
comboState.form.size = 30;
|
comboState.form.size = 30;
|
||||||
comboState.form.padding = 30;
|
comboState.form.padding = 30;
|
||||||
}
|
}
|
||||||
if (type === 'rect') {
|
if (type === 'rect') {
|
||||||
comboState.form.size = [30, 20];
|
comboState.form.size = [30, 20];
|
||||||
comboState.form.padding = [10, 20, 10, 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() {
|
function handleOkcombo() {
|
||||||
const origin = JSON.parse(JSON.stringify(comboState.origin));
|
const combo = JSON.parse(JSON.stringify(comboState.form));
|
||||||
if (origin.id) {
|
if (!combo.id) {
|
||||||
const data = graphG6.value.save();
|
message.warn({
|
||||||
const item = data.combos.find((combo: any) => combo.id === origin.id);
|
content: `分组元素ID错误`,
|
||||||
Object.assign(item, origin);
|
duration: 2,
|
||||||
graphG6.value.read(data);
|
});
|
||||||
|
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();
|
comboStateForm.resetFields();
|
||||||
comboState.origin = {};
|
comboState.origin = {};
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**图分组取消还原 */
|
||||||
|
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 = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
comboState,
|
||||||
|
comboStateForm,
|
||||||
|
handleComboTypeChange,
|
||||||
|
handleOkcombo,
|
||||||
|
handleCancelcombo,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { message, Form } from 'ant-design-vue/lib';
|
import { message, Form } from 'ant-design-vue/lib';
|
||||||
import { reactive, watch } from 'vue';
|
import { reactive, watch } from 'vue';
|
||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
import { graphG6 } from './useGraph';
|
import { graphG6 } from './useGraph';
|
||||||
|
|
||||||
/**图边内置边类型 */
|
/**图边内置边类型 */
|
||||||
@@ -54,98 +55,117 @@ export const edgePositionOptions = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
/**图边信息状态类型 */
|
export default function useEdge() {
|
||||||
type EdgeStateType = {
|
const { t } = useI18n();
|
||||||
/**图边原始数据 */
|
|
||||||
origin: Record<string, any>;
|
|
||||||
/**图边表单数据 */
|
|
||||||
form: Record<string, any>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**图边信息状态 */
|
/**图边信息状态类型 */
|
||||||
export let edgeState: EdgeStateType = reactive({
|
type EdgeStateType = {
|
||||||
origin: {},
|
/**图边原始数据 */
|
||||||
form: {
|
origin: Record<string, any>;
|
||||||
id: '',
|
/**图边表单数据 */
|
||||||
source: '',
|
form: Record<string, any>;
|
||||||
target: '',
|
};
|
||||||
type: 'polyline',
|
|
||||||
style: {
|
/**图边信息状态 */
|
||||||
offset: 20,
|
let edgeState: EdgeStateType = reactive({
|
||||||
radius: 2,
|
origin: {},
|
||||||
stroke: '#ffffff',
|
form: {
|
||||||
lineWidth: 1,
|
id: '',
|
||||||
cursor: 'pointer',
|
source: '',
|
||||||
},
|
target: '',
|
||||||
label: '',
|
type: 'polyline',
|
||||||
labelCfg: {
|
|
||||||
refX: 0,
|
|
||||||
refY: 0,
|
|
||||||
position: 'middle',
|
|
||||||
autoRotate: false,
|
|
||||||
style: {
|
style: {
|
||||||
fill: '#ffffff',
|
offset: 20,
|
||||||
fontSize: 12,
|
radius: 2,
|
||||||
fontWeight: 500,
|
stroke: '#ffffff',
|
||||||
|
lineWidth: 1,
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
label: '',
|
||||||
|
labelCfg: {
|
||||||
|
refX: 0,
|
||||||
|
refY: 0,
|
||||||
|
position: 'middle',
|
||||||
|
autoRotate: false,
|
||||||
|
style: {
|
||||||
|
fill: '#ffffff',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
|
|
||||||
/**图边对话框内表单属性和校验规则 */
|
/**图边对话框内表单属性和校验规则 */
|
||||||
export const edgeStateForm = Form.useForm(
|
const edgeStateForm = Form.useForm(
|
||||||
edgeState.form,
|
edgeState.form,
|
||||||
reactive({
|
reactive({
|
||||||
id: [{ required: true, message: '边唯一 ID' }],
|
id: [{ required: true, message: '边唯一 ID' }],
|
||||||
source: [{ required: true, message: '起始点 id' }],
|
source: [{ required: true, message: '起始点 id' }],
|
||||||
target: [{ required: true, message: '结束点 id' }],
|
target: [{ required: true, message: '结束点 id' }],
|
||||||
type: [{ required: true, message: 'line' }],
|
type: [{ required: true, message: 'line' }],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
/**图边编辑监听更新视图 */
|
/**图边编辑监听更新视图 */
|
||||||
watch(edgeState.form, edge => {
|
watch(edgeState.form, edge => {
|
||||||
const info = JSON.parse(JSON.stringify(edge));
|
const info = JSON.parse(JSON.stringify(edge));
|
||||||
const edgeId = info.id;
|
const edgeId = info.id;
|
||||||
if (edgeId) {
|
if (edgeId && edgeId !== '#') {
|
||||||
graphG6.value.clearItemStates(edgeId, 'selected');
|
graphG6.value.clearItemStates(edgeId, 'selected');
|
||||||
graphG6.value.updateItem(edgeId, info);
|
graphG6.value.updateItem(edgeId, info);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**图边新增或更新 */
|
/**图边新增或更新 */
|
||||||
export function handleOkEdge() {
|
function handleOkEdge() {
|
||||||
const edge = JSON.parse(JSON.stringify(edgeState.form));
|
return edgeStateForm
|
||||||
if (!edge.id) {
|
.validate()
|
||||||
message.warn({
|
.then(e => {
|
||||||
content: `边元素ID错误`,
|
const edge = JSON.parse(JSON.stringify(edgeState.form));
|
||||||
duration: 2,
|
if (!edge.id) {
|
||||||
});
|
message.warn({
|
||||||
return false;
|
content: `边元素ID错误`,
|
||||||
|
duration: 2,
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugger;
|
||||||
|
// graphG6.value.removeItem(edge.id);
|
||||||
|
// edge.id = `${edge.source}~${Date.now()}~${edge.target}`;
|
||||||
|
// graphG6.value.addItem('edge', edge);
|
||||||
|
const item = graphG6.value.findById(edge.id);
|
||||||
|
if (item) {
|
||||||
|
graphG6.value.updateItem(item, edge);
|
||||||
|
} else {
|
||||||
|
edge.id = `${edge.source}~${Date.now()}~${edge.target}`;
|
||||||
|
graphG6.value.addItem('edge', edge);
|
||||||
|
}
|
||||||
|
edgeStateForm.resetFields();
|
||||||
|
edgeState.origin = {};
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
message.error(
|
||||||
|
t('common.errorFields', { num: e.errorFields.length }),
|
||||||
|
3
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// graphG6.value.removeItem(edge.id);
|
|
||||||
// edge.id = `${edge.source}~${Date.now()}~${edge.target}`;
|
/**图边取消还原 */
|
||||||
// graphG6.value.addItem('edge', edge);
|
function handleCancelEdge() {
|
||||||
const item = graphG6.value.findById(edge.id);
|
const origin = JSON.parse(JSON.stringify(edgeState.origin));
|
||||||
if (item) {
|
if (origin.id) {
|
||||||
graphG6.value.updateItem(item, edge);
|
graphG6.value.updateItem(origin.id, origin);
|
||||||
} else {
|
// graphG6.value.removeItem(edgeOrigin.id);
|
||||||
edge.id = `${edge.source}~${Date.now()}~${edge.target}`;
|
// graphG6.value.addItem('edge', edgeOrigin);
|
||||||
graphG6.value.addItem('edge', edge);
|
edgeStateForm.resetFields();
|
||||||
}
|
edgeState.origin = {};
|
||||||
edgeStateForm.resetFields();
|
}
|
||||||
edgeState.origin = {};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图边取消还原 */
|
|
||||||
export function handleCancelEdge() {
|
|
||||||
const origin = JSON.parse(JSON.stringify(edgeState.origin));
|
|
||||||
if (origin.id) {
|
|
||||||
graphG6.value.updateItem(origin.id, origin);
|
|
||||||
// graphG6.value.removeItem(edgeOrigin.id);
|
|
||||||
// graphG6.value.addItem('edge', edgeOrigin);
|
|
||||||
edgeStateForm.resetFields();
|
|
||||||
edgeState.origin = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return { edgeState, edgeStateForm, handleOkEdge, handleCancelEdge };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
import {
|
import {
|
||||||
Graph,
|
Graph,
|
||||||
GraphData,
|
GraphData,
|
||||||
@@ -9,462 +10,6 @@ import {
|
|||||||
} from '@antv/g6';
|
} from '@antv/g6';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
/**图实例对象 */
|
|
||||||
export const graphG6 = ref<any>(null);
|
|
||||||
|
|
||||||
/**图事件变更 */
|
|
||||||
export const graphEvent = ref<{
|
|
||||||
type: string;
|
|
||||||
target: HTMLElement | (IShapeBase & ICanvas);
|
|
||||||
item: Item | null;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
/**图画布右击菜单 */
|
|
||||||
const graphCanvasMenu = new Menu({
|
|
||||||
offsetX: 6,
|
|
||||||
offseY: 10,
|
|
||||||
itemTypes: ['canvas'],
|
|
||||||
getContent(evt) {
|
|
||||||
return `
|
|
||||||
<div
|
|
||||||
style="
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 140px;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div id="show" style="cursor: pointer; margin-bottom: 2px">
|
|
||||||
1. 显示所有隐藏项
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
},
|
|
||||||
handleMenuClick(target, item) {
|
|
||||||
console.log(target, item);
|
|
||||||
const targetId = target.id;
|
|
||||||
switch (targetId) {
|
|
||||||
case 'show':
|
|
||||||
// 显示节点
|
|
||||||
graphG6.value.getNodes().forEach((node: any) => {
|
|
||||||
if (!node.isVisible()) {
|
|
||||||
graphG6.value.showItem(node);
|
|
||||||
graphG6.value.refreshItem(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 显示边
|
|
||||||
graphG6.value.getEdges().forEach((edge: any) => {
|
|
||||||
if (!edge.isVisible()) {
|
|
||||||
graphG6.value.showItem(edge);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图节点右击菜单 */
|
|
||||||
const graphNodeMenu = new Menu({
|
|
||||||
offsetX: 6,
|
|
||||||
offseY: 10,
|
|
||||||
itemTypes: ['node'],
|
|
||||||
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: `node-${targetId}`, target, item };
|
|
||||||
break;
|
|
||||||
case 'hide':
|
|
||||||
graphG6.value.hideItem(item);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图节点展示 */
|
|
||||||
const graphNodeTooltip = new Tooltip({
|
|
||||||
offsetX: 10,
|
|
||||||
offsetY: 20,
|
|
||||||
getContent(e: any) {
|
|
||||||
const outDiv = document.createElement('div');
|
|
||||||
outDiv.style.width = '180px';
|
|
||||||
outDiv.innerHTML = `
|
|
||||||
<h4>自定义tooltip</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Label: ${e.item.getModel().label || e.item.getModel().id}</li>
|
|
||||||
</ul>`;
|
|
||||||
return outDiv;
|
|
||||||
},
|
|
||||||
itemTypes: ['node'],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图边右击菜单 */
|
|
||||||
const graphEdgeMenu = new Menu({
|
|
||||||
offsetX: 6,
|
|
||||||
offseY: 10,
|
|
||||||
itemTypes: ['edge'],
|
|
||||||
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: `edge-${targetId}`, target, item };
|
|
||||||
break;
|
|
||||||
case 'hide':
|
|
||||||
graphG6.value.hideItem(item);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图边展示 */
|
|
||||||
const graphEdgeTooltip = new Tooltip({
|
|
||||||
offsetX: 10,
|
|
||||||
offsetY: 20,
|
|
||||||
getContent(e: any) {
|
|
||||||
const outDiv = document.createElement('div');
|
|
||||||
outDiv.style.width = '180px';
|
|
||||||
outDiv.innerHTML = `
|
|
||||||
<h4>graphEdgeTooltip</h4>
|
|
||||||
<ul>
|
|
||||||
<li>Label: ${e.item.getModel().label || e.item.getModel().id}</li>
|
|
||||||
</ul>`;
|
|
||||||
return outDiv;
|
|
||||||
},
|
|
||||||
itemTypes: ['edge'],
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图绑定事件 */
|
|
||||||
function fnGraphEvent(graph: Graph) {
|
|
||||||
// 调用 graph.add / graph.addItem 方法之后触发
|
|
||||||
graph.on('afteradditem', evt => {
|
|
||||||
fnSelectSourceTargetOptionsData();
|
|
||||||
});
|
|
||||||
|
|
||||||
// 鼠标进入节点事件
|
|
||||||
graph.on('edge:mouseenter', (ev: any) => {
|
|
||||||
// 获得鼠标当前目标边
|
|
||||||
const edge = ev.item;
|
|
||||||
// 该边的起始点
|
|
||||||
const source = edge.getSource();
|
|
||||||
// 该边的结束点
|
|
||||||
const target = edge.getTarget();
|
|
||||||
// 先将边提前,再将端点提前。这样该边两个端点还是在该边上层,较符合常规。
|
|
||||||
// edge.toFront();
|
|
||||||
// source.toFront();
|
|
||||||
// target.toFront();
|
|
||||||
});
|
|
||||||
|
|
||||||
graph.on('edge:mouseleave', (ev: any) => {
|
|
||||||
// 获得图上所有边实例
|
|
||||||
const edges = graph.getEdges();
|
|
||||||
// 遍历边,将所有边的层级放置在后方,以恢复原样
|
|
||||||
// edges.forEach(edge => {
|
|
||||||
// edge.toBack();
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
|
|
||||||
graph.on('node:mouseenter', evt => {
|
|
||||||
// 获得鼠标当前目标节点
|
|
||||||
const node = evt.item;
|
|
||||||
// 获取该节点的所有相关边
|
|
||||||
const edges = node && graph.getEdges();
|
|
||||||
// 遍历相关边,将所有相关边提前,再将相关边的两个端点提前,以保证相关边的端点在边的上方常规效果
|
|
||||||
// edges.forEach((edge: any) => {
|
|
||||||
// edge.toFront();
|
|
||||||
// edge.getSource().toFront();
|
|
||||||
// edge.getTarget().toFront();
|
|
||||||
// });
|
|
||||||
// graphEvent.value = {
|
|
||||||
// type: 'node:mouseenter',
|
|
||||||
// target: evt.target,
|
|
||||||
// item: evt.item,
|
|
||||||
// };
|
|
||||||
});
|
|
||||||
|
|
||||||
graph.on('node:mouseleave', (ev: any) => {
|
|
||||||
// 获得图上所有边实例
|
|
||||||
const edges = graph.getEdges();
|
|
||||||
// 遍历边,将所有边的层级放置在后方,以恢复原样
|
|
||||||
// edges.forEach(edge => {
|
|
||||||
// edge.toBack();
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图元素选择开始结束点 */
|
|
||||||
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({
|
|
||||||
value: info.id,
|
|
||||||
label: info.label,
|
|
||||||
info,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// 框
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图数据渲染 */
|
|
||||||
export function handleRanderGraph(container: HTMLElement, data: GraphData) {
|
|
||||||
if (!container) return;
|
|
||||||
const { clientHeight, clientWidth } = container;
|
|
||||||
|
|
||||||
const graph = new Graph({
|
|
||||||
container: container,
|
|
||||||
width: clientWidth,
|
|
||||||
height: clientHeight,
|
|
||||||
animate: true,
|
|
||||||
fitCenter: true,
|
|
||||||
modes: {
|
|
||||||
default: [
|
|
||||||
{
|
|
||||||
type: 'click-select',
|
|
||||||
selectEdge: true,
|
|
||||||
},
|
|
||||||
'drag-combo',
|
|
||||||
{
|
|
||||||
type: 'drag-node',
|
|
||||||
onlyChangeComboSize: true,
|
|
||||||
},
|
|
||||||
'drag-canvas',
|
|
||||||
'zoom-canvas',
|
|
||||||
'collapse-expand-combo',
|
|
||||||
],
|
|
||||||
edit: [
|
|
||||||
{
|
|
||||||
type: 'click-select',
|
|
||||||
selectEdge: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'drag-node',
|
|
||||||
shouldEnd: (e: any) => {
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ type: 'drag-combo' },
|
|
||||||
'drag-canvas',
|
|
||||||
'zoom-canvas',
|
|
||||||
{ type: 'create-edge', key: 'alt' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
groupByTypes: false,
|
|
||||||
// layout: {
|
|
||||||
// type: 'dagre',
|
|
||||||
// sortByCombo: false,
|
|
||||||
// ranksep: 10,
|
|
||||||
// nodesep: 10,
|
|
||||||
// },
|
|
||||||
// 全局节点
|
|
||||||
defaultNode: {
|
|
||||||
type: 'rect',
|
|
||||||
size: [80, 40],
|
|
||||||
style: {
|
|
||||||
radius: 8,
|
|
||||||
// fill: '#ffffff',
|
|
||||||
stroke: '#ffffff',
|
|
||||||
lineWidth: 1,
|
|
||||||
cursor: 'pointer',
|
|
||||||
},
|
|
||||||
labelCfg: {
|
|
||||||
position: 'center',
|
|
||||||
offset: 0,
|
|
||||||
style: {
|
|
||||||
fill: '#000000',
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: 500,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
show: false,
|
|
||||||
img: '/svg/service.svg',
|
|
||||||
width: 25,
|
|
||||||
height: 25,
|
|
||||||
offset: 20, // triangle 特有
|
|
||||||
},
|
|
||||||
direction: 'up', // triangle 三角形的方向
|
|
||||||
},
|
|
||||||
// 全局边
|
|
||||||
defaultEdge: {
|
|
||||||
type: 'polyline',
|
|
||||||
style: {
|
|
||||||
offset: 20, // 拐弯处距离节点最小距离
|
|
||||||
radius: 2, // 拐弯处的圆角弧度,若不设置则为直角
|
|
||||||
stroke: '#ffffff',
|
|
||||||
lineWidth: 1,
|
|
||||||
cursor: 'pointer',
|
|
||||||
},
|
|
||||||
labelCfg: {
|
|
||||||
refX: 0,
|
|
||||||
refY: 0,
|
|
||||||
position: 'middle',
|
|
||||||
autoRotate: false,
|
|
||||||
style: {
|
|
||||||
fill: '#ffffff',
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: 500,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// 全局框节点
|
|
||||||
defaultCombo: {
|
|
||||||
type: 'rect', // Combo 类型
|
|
||||||
size: [40, 40],
|
|
||||||
padding: [30, 30, 30, 30],
|
|
||||||
style: {
|
|
||||||
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,
|
|
||||||
graphEdgeTooltip,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
graph.data(data);
|
|
||||||
graph.render();
|
|
||||||
|
|
||||||
// 图绑定事件
|
|
||||||
fnGraphEvent(graph);
|
|
||||||
|
|
||||||
graphG6.value = graph;
|
|
||||||
|
|
||||||
// 图元素选择开始结束点数据
|
|
||||||
fnSelectSourceTargetOptionsData();
|
|
||||||
|
|
||||||
return graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图模式选择项 */
|
/**图模式选择项 */
|
||||||
export const graphModeOptions = [
|
export const graphModeOptions = [
|
||||||
{
|
{
|
||||||
@@ -477,12 +22,494 @@ export const graphModeOptions = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**图实例对象 */
|
||||||
|
export const graphG6 = ref<any>(null);
|
||||||
|
|
||||||
|
/**图事件变更 */
|
||||||
|
export const graphEvent = ref<{
|
||||||
|
type: string;
|
||||||
|
target: HTMLElement | (IShapeBase & ICanvas);
|
||||||
|
item: Item | null;
|
||||||
|
}>();
|
||||||
|
|
||||||
/**图模式选择项 */
|
/**图模式选择项 */
|
||||||
export const graphMode = ref<string>('default');
|
export const graphMode = ref<string>('default');
|
||||||
|
|
||||||
/**图模式改变 default | edit */
|
export default function useGraph() {
|
||||||
export function handleChangeMode(value: any) {
|
//实例化i18n
|
||||||
console.log(value, JSON.parse(JSON.stringify(graphG6.value.save())));
|
const { t } = useI18n();
|
||||||
graphG6.value.setMode(value);
|
|
||||||
graphMode.value = graphG6.value.getCurrentMode();
|
/**图画布右击菜单 */
|
||||||
|
const graphCanvasMenu = new Menu({
|
||||||
|
offsetX: 6,
|
||||||
|
offseY: 10,
|
||||||
|
itemTypes: ['canvas'],
|
||||||
|
getContent(evt) {
|
||||||
|
return `
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 140px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div id="show" style="cursor: pointer; margin-bottom: 2px">
|
||||||
|
1. 显示所有隐藏项
|
||||||
|
</div>
|
||||||
|
<div id="create-node" style="cursor: pointer; margin-bottom: 2px">
|
||||||
|
2. 新增节点
|
||||||
|
</div>
|
||||||
|
<div id="create-edge" style="cursor: pointer; margin-bottom: 2px">
|
||||||
|
3. 新增边
|
||||||
|
</div>
|
||||||
|
<div id="create-combo" style="cursor: pointer; margin-bottom: 2px">
|
||||||
|
4. 新增分组
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
},
|
||||||
|
handleMenuClick(target, item) {
|
||||||
|
console.log(target, item);
|
||||||
|
const targetId = target.id;
|
||||||
|
switch (targetId) {
|
||||||
|
case 'create-node':
|
||||||
|
case 'create-edge':
|
||||||
|
case 'create-combo':
|
||||||
|
graphEvent.value = { type: `canvas-${targetId}`, target, item };
|
||||||
|
break;
|
||||||
|
case 'show':
|
||||||
|
// 显示节点
|
||||||
|
graphG6.value.getNodes().forEach((node: any) => {
|
||||||
|
if (!node.isVisible()) {
|
||||||
|
graphG6.value.showItem(node);
|
||||||
|
graphG6.value.refreshItem(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 显示边
|
||||||
|
graphG6.value.getEdges().forEach((edge: any) => {
|
||||||
|
if (!edge.isVisible()) {
|
||||||
|
graphG6.value.showItem(edge);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**图节点右击菜单 */
|
||||||
|
const graphNodeMenu = new Menu({
|
||||||
|
offsetX: 6,
|
||||||
|
offseY: 10,
|
||||||
|
itemTypes: ['node'],
|
||||||
|
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: `node-${targetId}`, target, item };
|
||||||
|
break;
|
||||||
|
case 'hide':
|
||||||
|
graphG6.value.hideItem(item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**图节点展示 */
|
||||||
|
const graphNodeTooltip = new Tooltip({
|
||||||
|
offsetX: 10,
|
||||||
|
offsetY: 20,
|
||||||
|
getContent(e: any) {
|
||||||
|
const outDiv = document.createElement('div');
|
||||||
|
outDiv.style.width = '180px';
|
||||||
|
outDiv.innerHTML = `
|
||||||
|
<h4>自定义tooltip</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Label: ${e.item.getModel().label || e.item.getModel().id}</li>
|
||||||
|
</ul>`;
|
||||||
|
return outDiv;
|
||||||
|
},
|
||||||
|
itemTypes: ['node'],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**图边右击菜单 */
|
||||||
|
const graphEdgeMenu = new Menu({
|
||||||
|
offsetX: 6,
|
||||||
|
offseY: 10,
|
||||||
|
itemTypes: ['edge'],
|
||||||
|
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: `edge-${targetId}`, target, item };
|
||||||
|
break;
|
||||||
|
case 'hide':
|
||||||
|
graphG6.value.hideItem(item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**图边展示 */
|
||||||
|
const graphEdgeTooltip = new Tooltip({
|
||||||
|
offsetX: 10,
|
||||||
|
offsetY: 20,
|
||||||
|
getContent(e: any) {
|
||||||
|
const outDiv = document.createElement('div');
|
||||||
|
outDiv.style.width = '180px';
|
||||||
|
outDiv.innerHTML = `
|
||||||
|
<h4>graphEdgeTooltip</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Label: ${e.item.getModel().label || e.item.getModel().id}</li>
|
||||||
|
</ul>`;
|
||||||
|
return outDiv;
|
||||||
|
},
|
||||||
|
itemTypes: ['edge'],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**图绑定事件 */
|
||||||
|
function fnGraphEvent(graph: Graph) {
|
||||||
|
// 调用 graph.add / graph.addItem 方法之后触发
|
||||||
|
graph.on('afteradditem', evt => {
|
||||||
|
fnSelectSourceTargetOptionsData();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 鼠标进入节点事件
|
||||||
|
graph.on('edge:mouseenter', (ev: any) => {
|
||||||
|
// 获得鼠标当前目标边
|
||||||
|
const edge = ev.item;
|
||||||
|
// 该边的起始点
|
||||||
|
const source = edge.getSource();
|
||||||
|
// 该边的结束点
|
||||||
|
const target = edge.getTarget();
|
||||||
|
// 先将边提前,再将端点提前。这样该边两个端点还是在该边上层,较符合常规。
|
||||||
|
// edge.toFront();
|
||||||
|
// source.toFront();
|
||||||
|
// target.toFront();
|
||||||
|
});
|
||||||
|
|
||||||
|
graph.on('edge:mouseleave', (ev: any) => {
|
||||||
|
// 获得图上所有边实例
|
||||||
|
const edges = graph.getEdges();
|
||||||
|
// 遍历边,将所有边的层级放置在后方,以恢复原样
|
||||||
|
// edges.forEach(edge => {
|
||||||
|
// edge.toBack();
|
||||||
|
// });
|
||||||
|
});
|
||||||
|
|
||||||
|
graph.on('node:mouseenter', evt => {
|
||||||
|
// 获得鼠标当前目标节点
|
||||||
|
const node = evt.item;
|
||||||
|
// 获取该节点的所有相关边
|
||||||
|
const edges = node && graph.getEdges();
|
||||||
|
// 遍历相关边,将所有相关边提前,再将相关边的两个端点提前,以保证相关边的端点在边的上方常规效果
|
||||||
|
// edges.forEach((edge: any) => {
|
||||||
|
// edge.toFront();
|
||||||
|
// edge.getSource().toFront();
|
||||||
|
// edge.getTarget().toFront();
|
||||||
|
// });
|
||||||
|
// graphEvent.value = {
|
||||||
|
// type: 'node:mouseenter',
|
||||||
|
// target: evt.target,
|
||||||
|
// item: evt.item,
|
||||||
|
// };
|
||||||
|
});
|
||||||
|
|
||||||
|
graph.on('node:mouseleave', (ev: any) => {
|
||||||
|
// 获得图上所有边实例
|
||||||
|
const edges = graph.getEdges();
|
||||||
|
// 遍历边,将所有边的层级放置在后方,以恢复原样
|
||||||
|
// edges.forEach(edge => {
|
||||||
|
// edge.toBack();
|
||||||
|
// });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**图元素选择开始结束点 */
|
||||||
|
const selectSourceTargetOptions = ref<Record<string, any>[]>([]);
|
||||||
|
|
||||||
|
/**图元素选择嵌入分组 */
|
||||||
|
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({
|
||||||
|
value: info.id,
|
||||||
|
label: info.label,
|
||||||
|
info,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// 分组
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**图数据渲染 */
|
||||||
|
function handleRanderGraph(container: HTMLElement, data: GraphData) {
|
||||||
|
if (!container) return;
|
||||||
|
const { clientHeight, clientWidth } = container;
|
||||||
|
|
||||||
|
const graph = new Graph({
|
||||||
|
container: container,
|
||||||
|
width: clientWidth,
|
||||||
|
height: clientHeight,
|
||||||
|
animate: true,
|
||||||
|
fitCenter: true,
|
||||||
|
modes: {
|
||||||
|
default: [
|
||||||
|
{
|
||||||
|
type: 'click-select',
|
||||||
|
selectEdge: true,
|
||||||
|
},
|
||||||
|
'drag-combo',
|
||||||
|
{
|
||||||
|
type: 'drag-node',
|
||||||
|
onlyChangeComboSize: true,
|
||||||
|
},
|
||||||
|
'drag-canvas',
|
||||||
|
'zoom-canvas',
|
||||||
|
'collapse-expand-combo',
|
||||||
|
],
|
||||||
|
edit: [
|
||||||
|
{
|
||||||
|
type: 'click-select',
|
||||||
|
selectEdge: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'drag-node',
|
||||||
|
shouldEnd: (e: any) => {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ type: 'drag-combo' },
|
||||||
|
'drag-canvas',
|
||||||
|
'zoom-canvas',
|
||||||
|
{ type: 'create-edge', key: 'alt' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
groupByTypes: false,
|
||||||
|
// layout: {
|
||||||
|
// type: 'dagre',
|
||||||
|
// sortByCombo: false,
|
||||||
|
// ranksep: 10,
|
||||||
|
// nodesep: 10,
|
||||||
|
// },
|
||||||
|
// 全局节点
|
||||||
|
defaultNode: {
|
||||||
|
type: 'rect',
|
||||||
|
size: [80, 40],
|
||||||
|
style: {
|
||||||
|
radius: 8,
|
||||||
|
// fill: '#ffffff',
|
||||||
|
stroke: '#ffffff',
|
||||||
|
lineWidth: 1,
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
labelCfg: {
|
||||||
|
position: 'center',
|
||||||
|
offset: 0,
|
||||||
|
style: {
|
||||||
|
fill: '#000000',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
show: false,
|
||||||
|
img: '/svg/service.svg',
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
|
offset: 20, // triangle 特有
|
||||||
|
},
|
||||||
|
direction: 'up', // triangle 三角形的方向
|
||||||
|
},
|
||||||
|
// 全局边
|
||||||
|
defaultEdge: {
|
||||||
|
type: 'polyline',
|
||||||
|
style: {
|
||||||
|
offset: 20, // 拐弯处距离节点最小距离
|
||||||
|
radius: 2, // 拐弯处的圆角弧度,若不设置则为直角
|
||||||
|
stroke: '#ffffff',
|
||||||
|
lineWidth: 1,
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
labelCfg: {
|
||||||
|
refX: 0,
|
||||||
|
refY: 0,
|
||||||
|
position: 'middle',
|
||||||
|
autoRotate: false,
|
||||||
|
style: {
|
||||||
|
fill: '#ffffff',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 全局分组节点
|
||||||
|
defaultCombo: {
|
||||||
|
type: 'rect', // Combo 类型
|
||||||
|
size: [40, 40],
|
||||||
|
padding: [30, 30, 30, 30],
|
||||||
|
style: {
|
||||||
|
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,
|
||||||
|
graphEdgeTooltip,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
graph.data(data);
|
||||||
|
graph.render();
|
||||||
|
|
||||||
|
// 图绑定事件
|
||||||
|
fnGraphEvent(graph);
|
||||||
|
|
||||||
|
graphG6.value = graph;
|
||||||
|
|
||||||
|
// 图元素选择开始结束点数据
|
||||||
|
fnSelectSourceTargetOptionsData();
|
||||||
|
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**图模式改变 default | edit */
|
||||||
|
function handleChangeMode(value: any) {
|
||||||
|
console.log(value, JSON.parse(JSON.stringify(graphG6.value.save())));
|
||||||
|
graphG6.value.setMode(value);
|
||||||
|
graphMode.value = graphG6.value.getCurrentMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectSourceTargetOptions,
|
||||||
|
selectComboOptions,
|
||||||
|
handleRanderGraph,
|
||||||
|
handleChangeMode,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { message, Form } from 'ant-design-vue/lib';
|
import { message, Form } from 'ant-design-vue/lib';
|
||||||
import { reactive, watch } from 'vue';
|
import { reactive, watch } from 'vue';
|
||||||
import { graphG6 } from './useGraph';
|
import { graphG6 } from './useGraph';
|
||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
|
||||||
/**图节点内置边类型 */
|
/**图节点内置边类型 */
|
||||||
export const nodeTypeOptions = [
|
export const nodeTypeOptions = [
|
||||||
@@ -85,204 +86,216 @@ export const nodeImageOptions = [
|
|||||||
{ value: '/svg/service_db.svg', label: '数据服务器' },
|
{ value: '/svg/service_db.svg', label: '数据服务器' },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**图节点信息状态类型 */
|
export default function useNode() {
|
||||||
type NodeStateType = {
|
const { t } = useI18n();
|
||||||
/**图节点原始数据 */
|
|
||||||
origin: Record<string, any>;
|
|
||||||
/**图节点表单数据 */
|
|
||||||
form: Record<string, any>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**图节点信息状态 */
|
/**图节点信息状态类型 */
|
||||||
export let nodeState: NodeStateType = reactive({
|
type NodeStateType = {
|
||||||
origin: {},
|
/**图节点原始数据 */
|
||||||
form: {
|
origin: Record<string, any>;
|
||||||
id: '',
|
/**图节点表单数据 */
|
||||||
comboId: '',
|
form: Record<string, any>;
|
||||||
x: 0,
|
};
|
||||||
y: 0,
|
|
||||||
type: 'circle',
|
/**图节点信息状态 */
|
||||||
size: 30,
|
let nodeState: NodeStateType = reactive({
|
||||||
anchorPoints: false,
|
origin: {},
|
||||||
style: {
|
form: {
|
||||||
fill: '#ffffff',
|
id: '',
|
||||||
stroke: '#ffffff',
|
comboId: '',
|
||||||
lineWidth: 1,
|
x: 0,
|
||||||
},
|
y: 0,
|
||||||
label: '',
|
type: 'circle',
|
||||||
labelCfg: {
|
size: 30,
|
||||||
position: 'center',
|
anchorPoints: false,
|
||||||
offset: 0,
|
|
||||||
style: {
|
style: {
|
||||||
fill: '#000000',
|
fill: '#ffffff',
|
||||||
fontSize: 12,
|
stroke: '#ffffff',
|
||||||
fontWeight: 500,
|
lineWidth: 1,
|
||||||
|
},
|
||||||
|
label: '',
|
||||||
|
labelCfg: {
|
||||||
|
position: 'center',
|
||||||
|
offset: 0,
|
||||||
|
style: {
|
||||||
|
fill: '#000000',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
|
|
||||||
/**图节点对话框内表单属性和校验规则 */
|
/**图节点对话框内表单属性和校验规则 */
|
||||||
export const nodeStateForm = Form.useForm(
|
const nodeStateForm = Form.useForm(
|
||||||
nodeState.form,
|
nodeState.form,
|
||||||
reactive({
|
reactive({
|
||||||
id: [{ required: true, message: '节点唯一 ID' }],
|
id: [{ required: true, message: '节点唯一 ID' }],
|
||||||
type: [{ required: true, message: 'line' }],
|
type: [{ required: true, message: 'line' }],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
/**图节点编辑监听更新视图 */
|
/**图节点编辑监听更新视图 */
|
||||||
watch(nodeState.form, node => {
|
watch(nodeState.form, node => {
|
||||||
const info = JSON.parse(JSON.stringify(node));
|
const info = JSON.parse(JSON.stringify(node));
|
||||||
console.log(info);
|
console.log(info);
|
||||||
const nodeId = info.id;
|
const nodeId = info.id;
|
||||||
if (nodeId) {
|
if (nodeId) {
|
||||||
// 图片类型需要移除style属性,避免填充
|
// 图片类型需要移除style属性,避免填充
|
||||||
if (info.type === 'image') {
|
if (info.type === 'image') {
|
||||||
Reflect.deleteProperty(info, 'style');
|
Reflect.deleteProperty(info, 'style');
|
||||||
}
|
}
|
||||||
graphG6.value.clearItemStates(nodeId, 'selected');
|
graphG6.value.clearItemStates(nodeId, 'selected');
|
||||||
graphG6.value.updateItem(nodeId, info);
|
graphG6.value.updateItem(nodeId, info);
|
||||||
// 三角和图片的样式变更需要重绘才生效
|
// 三角和图片的样式变更需要重绘才生效
|
||||||
if (
|
if (
|
||||||
info.type === 'triangle' ||
|
info.type === 'triangle' ||
|
||||||
info.type === 'image' ||
|
info.type === 'image' ||
|
||||||
info.comboId !== nodeState.origin.comboId
|
info.comboId !== nodeState.origin.comboId
|
||||||
) {
|
) {
|
||||||
graphG6.value.read(graphG6.value.save());
|
graphG6.value.read(graphG6.value.save());
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/**图节点类型输入限制 */
|
|
||||||
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: '',
|
|
||||||
width: 25,
|
|
||||||
height: 25,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else if (type === 'triangle') {
|
});
|
||||||
// 三角
|
|
||||||
const origin = nodeState.origin;
|
/**图节点类型输入限制 */
|
||||||
if (origin.icon) {
|
function handleNodeTypeChange(type: any) {
|
||||||
nodeState.form = Object.assign(nodeState.form, {
|
// 设置图标属性
|
||||||
size: 40,
|
if (['circle', 'ellipse', 'diamond', 'star', 'donut'].includes(type)) {
|
||||||
direction: origin.direction || 'up', // triangle 三角形的方向
|
const origin = nodeState.origin;
|
||||||
icon: Object.assign({ offset: 20 }, origin.icon),
|
if (origin.icon) {
|
||||||
});
|
nodeState.form = Object.assign(nodeState.form, {
|
||||||
} else {
|
size: origin.size,
|
||||||
nodeState.form = Object.assign(nodeState.form, {
|
icon: origin.icon,
|
||||||
size: 30,
|
});
|
||||||
direction: 'up', // triangle 三角形的方向
|
} else {
|
||||||
icon: {
|
let size: number[] | number = [30];
|
||||||
show: false,
|
if (['circle', 'star', 'donut'].includes(type)) {
|
||||||
|
size = 30;
|
||||||
|
}
|
||||||
|
nodeState.form = Object.assign(nodeState.form, {
|
||||||
|
size,
|
||||||
|
icon: {
|
||||||
|
show: false,
|
||||||
|
img: '',
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (type === 'triangle') {
|
||||||
|
// 三角
|
||||||
|
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,
|
||||||
|
img: '/svg/service.svg',
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
|
offset: 20, // triangle 特有
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 设置图片属性
|
||||||
|
if (type === 'image') {
|
||||||
|
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',
|
img: '/svg/service.svg',
|
||||||
width: 25,
|
clipCfg: {
|
||||||
height: 25,
|
show: false,
|
||||||
offset: 20, // triangle 特有
|
width: 0,
|
||||||
},
|
height: 0,
|
||||||
});
|
type: 'circle',
|
||||||
}
|
},
|
||||||
}
|
});
|
||||||
// 设置图片属性
|
}
|
||||||
if (type === 'image') {
|
Reflect.deleteProperty(nodeState.form, 'style');
|
||||||
const origin = nodeState.origin;
|
|
||||||
if (origin.img) {
|
|
||||||
nodeState.form = Object.assign(nodeState.form, {
|
|
||||||
size: [30, 30],
|
|
||||||
img: origin.img,
|
|
||||||
clipCfg: origin.clipCfg,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
nodeState.form = Object.assign(nodeState.form, {
|
// 当切换非图片时补充style属性
|
||||||
size: [30, 30],
|
if (!Reflect.has(nodeState.form, 'style')) {
|
||||||
img: '/svg/service.svg',
|
nodeState.form = Object.assign(nodeState.form, {
|
||||||
clipCfg: {
|
style: {
|
||||||
show: false,
|
fill: '#ffffff',
|
||||||
width: 0,
|
stroke: '#ffffff',
|
||||||
height: 0,
|
lineWidth: 1,
|
||||||
type: 'circle',
|
},
|
||||||
},
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
Reflect.deleteProperty(nodeState.form, 'style');
|
|
||||||
} else {
|
|
||||||
// 当切换非图片时补充style属性
|
|
||||||
if (!Reflect.has(nodeState.form, 'style')) {
|
|
||||||
nodeState.form = Object.assign(nodeState.form, {
|
|
||||||
style: {
|
|
||||||
fill: '#ffffff',
|
|
||||||
stroke: '#ffffff',
|
|
||||||
lineWidth: 1,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**图节点新增或更新 */
|
/**图节点新增或更新 */
|
||||||
export function handleOkNode() {
|
function handleOkNode() {
|
||||||
const node = JSON.parse(JSON.stringify(nodeState.form));
|
const node = JSON.parse(JSON.stringify(nodeState.form));
|
||||||
if (!node.id) {
|
if (!node.id) {
|
||||||
message.warn({
|
message.warn({
|
||||||
content: `节点元素ID错误`,
|
content: `节点元素ID错误`,
|
||||||
duration: 2,
|
duration: 2,
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// graphG6.value.removeItem(node.id);
|
// graphG6.value.removeItem(node.id);
|
||||||
// graphG6.value.addItem('node', node);
|
// graphG6.value.addItem('node', node);
|
||||||
const item = graphG6.value.findById(node.id);
|
const item = graphG6.value.findById(node.id);
|
||||||
if (item) {
|
if (item) {
|
||||||
graphG6.value.updateItem(item, node);
|
graphG6.value.updateItem(item, node);
|
||||||
} else {
|
} else {
|
||||||
graphG6.value.addItem('node', node);
|
graphG6.value.addItem('node', node);
|
||||||
}
|
}
|
||||||
// 三角和图片的样式变更需要重绘才生效
|
|
||||||
if (
|
|
||||||
node.type === 'triangle' ||
|
|
||||||
node.type === 'image' ||
|
|
||||||
node.comboId !== nodeState.origin.comboId
|
|
||||||
) {
|
|
||||||
graphG6.value.read(graphG6.value.save());
|
|
||||||
}
|
|
||||||
nodeStateForm.resetFields();
|
|
||||||
nodeState.origin = {};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**图节点取消还原 */
|
|
||||||
export function handleCancelNode() {
|
|
||||||
const origin = JSON.parse(JSON.stringify(nodeState.origin));
|
|
||||||
if (origin.id) {
|
|
||||||
graphG6.value.updateItem(origin.id, origin);
|
|
||||||
// 三角和图片的样式变更需要重绘才生效
|
// 三角和图片的样式变更需要重绘才生效
|
||||||
if (
|
if (
|
||||||
origin.type === 'triangle' ||
|
node.type === 'triangle' ||
|
||||||
origin.type === 'image' ||
|
node.type === 'image' ||
|
||||||
origin.comboId !== nodeState.form.comboId
|
node.comboId !== nodeState.origin.comboId
|
||||||
) {
|
) {
|
||||||
graphG6.value.read(graphG6.value.save());
|
graphG6.value.read(graphG6.value.save());
|
||||||
}
|
}
|
||||||
nodeStateForm.resetFields();
|
nodeStateForm.resetFields();
|
||||||
nodeState.origin = {};
|
nodeState.origin = {};
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**图节点取消还原 */
|
||||||
|
function handleCancelNode() {
|
||||||
|
const origin = JSON.parse(JSON.stringify(nodeState.origin));
|
||||||
|
if (origin.id) {
|
||||||
|
graphG6.value.updateItem(origin.id, origin);
|
||||||
|
// 三角和图片的样式变更需要重绘才生效
|
||||||
|
if (
|
||||||
|
origin.type === 'triangle' ||
|
||||||
|
origin.type === 'image' ||
|
||||||
|
origin.comboId !== nodeState.form.comboId
|
||||||
|
) {
|
||||||
|
graphG6.value.read(graphG6.value.save());
|
||||||
|
}
|
||||||
|
nodeStateForm.resetFields();
|
||||||
|
nodeState.origin = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
nodeState,
|
||||||
|
nodeStateForm,
|
||||||
|
handleNodeTypeChange,
|
||||||
|
handleOkNode,
|
||||||
|
handleCancelNode,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user