feat: 拓扑编辑多语言函数处理

This commit is contained in:
TsMask
2023-12-29 11:56:52 +08:00
parent e4c829a46d
commit d9c561e677
6 changed files with 2053 additions and 1946 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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,16 +39,19 @@ export const comboPositionOptions = [
}, },
]; ];
/**图分组信息状态类型 */ export default function useCombo() {
type ComboStateType = { const { t } = useI18n();
/**图分组信息状态类型 */
type ComboStateType = {
/**图分组原始数据 */ /**图分组原始数据 */
origin: Record<string, any>; origin: Record<string, any>;
/**图分组表单数据 */ /**图分组表单数据 */
form: Record<string, any>; form: Record<string, any>;
}; };
/**图分组信息状态 */ /**图分组信息状态 */
export let comboState: ComboStateType = reactive({ let comboState: ComboStateType = reactive({
origin: {}, origin: {},
form: { form: {
id: '', id: '',
@@ -73,18 +76,18 @@ export let comboState: ComboStateType = reactive({
}, },
}, },
}, },
}); });
/**图分组对话分组内表单属性和校验规则 */ /**图分组对话分组内表单属性和校验规则 */
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) {
@@ -99,10 +102,10 @@ watch(comboState.form, combo => {
} }
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;
@@ -112,10 +115,10 @@ export function handleComboTypeChange(type: any) {
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() { function handleOkcombo() {
const combo = JSON.parse(JSON.stringify(comboState.form)); const combo = JSON.parse(JSON.stringify(comboState.form));
if (!combo.id) { if (!combo.id) {
message.warn({ message.warn({
@@ -140,10 +143,10 @@ export function handleOkcombo() {
comboStateForm.resetFields(); comboStateForm.resetFields();
comboState.origin = {}; comboState.origin = {};
return true; return true;
} }
/**图分组取消还原 */ /**图分组取消还原 */
export function handleCancelcombo() { function handleCancelcombo() {
const origin = JSON.parse(JSON.stringify(comboState.origin)); const origin = JSON.parse(JSON.stringify(comboState.origin));
if (origin.id) { if (origin.id) {
const data = graphG6.value.save(); const data = graphG6.value.save();
@@ -153,4 +156,13 @@ export function handleCancelcombo() {
comboStateForm.resetFields(); comboStateForm.resetFields();
comboState.origin = {}; comboState.origin = {};
} }
}
return {
comboState,
comboStateForm,
handleComboTypeChange,
handleOkcombo,
handleCancelcombo,
};
} }

View File

@@ -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,16 +55,19 @@ export const edgePositionOptions = [
}, },
]; ];
/**图边信息状态类型 */ export default function useEdge() {
type EdgeStateType = { const { t } = useI18n();
/**图边信息状态类型 */
type EdgeStateType = {
/**图边原始数据 */ /**图边原始数据 */
origin: Record<string, any>; origin: Record<string, any>;
/**图边表单数据 */ /**图边表单数据 */
form: Record<string, any>; form: Record<string, any>;
}; };
/**图边信息状态 */ /**图边信息状态 */
export let edgeState: EdgeStateType = reactive({ let edgeState: EdgeStateType = reactive({
origin: {}, origin: {},
form: { form: {
id: '', id: '',
@@ -90,10 +94,10 @@ export let edgeState: EdgeStateType = reactive({
}, },
}, },
}, },
}); });
/**图边对话框内表单属性和校验规则 */ /**图边对话框内表单属性和校验规则 */
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' }],
@@ -101,20 +105,23 @@ export const edgeStateForm = Form.useForm(
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() {
return edgeStateForm
.validate()
.then(e => {
const edge = JSON.parse(JSON.stringify(edgeState.form)); const edge = JSON.parse(JSON.stringify(edgeState.form));
if (!edge.id) { if (!edge.id) {
message.warn({ message.warn({
@@ -123,6 +130,8 @@ export function handleOkEdge() {
}); });
return false; return false;
} }
debugger;
// graphG6.value.removeItem(edge.id); // graphG6.value.removeItem(edge.id);
// edge.id = `${edge.source}~${Date.now()}~${edge.target}`; // edge.id = `${edge.source}~${Date.now()}~${edge.target}`;
// graphG6.value.addItem('edge', edge); // graphG6.value.addItem('edge', edge);
@@ -136,10 +145,18 @@ export function handleOkEdge() {
edgeStateForm.resetFields(); edgeStateForm.resetFields();
edgeState.origin = {}; edgeState.origin = {};
return true; return true;
} })
.catch(e => {
message.error(
t('common.errorFields', { num: e.errorFields.length }),
3
);
return false;
});
}
/**图边取消还原 */ /**图边取消还原 */
export function handleCancelEdge() { function handleCancelEdge() {
const origin = JSON.parse(JSON.stringify(edgeState.origin)); const origin = JSON.parse(JSON.stringify(edgeState.origin));
if (origin.id) { if (origin.id) {
graphG6.value.updateItem(origin.id, origin); graphG6.value.updateItem(origin.id, origin);
@@ -148,4 +165,7 @@ export function handleCancelEdge() {
edgeStateForm.resetFields(); edgeStateForm.resetFields();
edgeState.origin = {}; edgeState.origin = {};
} }
}
return { edgeState, edgeStateForm, handleOkEdge, handleCancelEdge };
} }

View File

@@ -1,3 +1,4 @@
import useI18n from '@/hooks/useI18n';
import { import {
Graph, Graph,
GraphData, GraphData,
@@ -9,6 +10,18 @@ import {
} from '@antv/g6'; } from '@antv/g6';
import { ref } from 'vue'; import { ref } from 'vue';
/**图模式选择项 */
export const graphModeOptions = [
{
value: 'default',
label: '默认',
},
{
value: 'edit',
label: '编辑',
},
];
/**图实例对象 */ /**图实例对象 */
export const graphG6 = ref<any>(null); export const graphG6 = ref<any>(null);
@@ -19,8 +32,15 @@ export const graphEvent = ref<{
item: Item | null; item: Item | null;
}>(); }>();
/**图画布右击菜单 */ /**图模式选择项 */
const graphCanvasMenu = new Menu({ export const graphMode = ref<string>('default');
export default function useGraph() {
//实例化i18n
const { t } = useI18n();
/**图画布右击菜单 */
const graphCanvasMenu = new Menu({
offsetX: 6, offsetX: 6,
offseY: 10, offseY: 10,
itemTypes: ['canvas'], itemTypes: ['canvas'],
@@ -36,12 +56,26 @@ const graphCanvasMenu = new Menu({
<div id="show" style="cursor: pointer; margin-bottom: 2px"> <div id="show" style="cursor: pointer; margin-bottom: 2px">
1. 显示所有隐藏项 1. 显示所有隐藏项
</div> </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>`; </div>`;
}, },
handleMenuClick(target, item) { handleMenuClick(target, item) {
console.log(target, item); console.log(target, item);
const targetId = target.id; const targetId = target.id;
switch (targetId) { switch (targetId) {
case 'create-node':
case 'create-edge':
case 'create-combo':
graphEvent.value = { type: `canvas-${targetId}`, target, item };
break;
case 'show': case 'show':
// 显示节点 // 显示节点
graphG6.value.getNodes().forEach((node: any) => { graphG6.value.getNodes().forEach((node: any) => {
@@ -57,7 +91,7 @@ const graphCanvasMenu = new Menu({
graphG6.value.refreshItem(edge); graphG6.value.refreshItem(edge);
} }
}); });
// 显示 // 显示分组
graphG6.value.getCombos().forEach((combo: any) => { graphG6.value.getCombos().forEach((combo: any) => {
if (!combo.isVisible()) { if (!combo.isVisible()) {
graphG6.value.showItem(combo); graphG6.value.showItem(combo);
@@ -67,10 +101,10 @@ const graphCanvasMenu = new Menu({
break; break;
} }
}, },
}); });
/**图分组Combo 右击菜单 */ /**图分组Combo 右击菜单 */
const graphComboMenu = new Menu({ const graphComboMenu = new Menu({
offsetX: 6, offsetX: 6,
offseY: 10, offseY: 10,
itemTypes: ['combo'], itemTypes: ['combo'],
@@ -106,10 +140,10 @@ const graphComboMenu = new Menu({
break; break;
} }
}, },
}); });
/**图节点右击菜单 */ /**图节点右击菜单 */
const graphNodeMenu = new Menu({ const graphNodeMenu = new Menu({
offsetX: 6, offsetX: 6,
offseY: 10, offseY: 10,
itemTypes: ['node'], itemTypes: ['node'],
@@ -145,10 +179,10 @@ const graphNodeMenu = new Menu({
break; break;
} }
}, },
}); });
/**图节点展示 */ /**图节点展示 */
const graphNodeTooltip = new Tooltip({ const graphNodeTooltip = new Tooltip({
offsetX: 10, offsetX: 10,
offsetY: 20, offsetY: 20,
getContent(e: any) { getContent(e: any) {
@@ -162,10 +196,10 @@ const graphNodeTooltip = new Tooltip({
return outDiv; return outDiv;
}, },
itemTypes: ['node'], itemTypes: ['node'],
}); });
/**图边右击菜单 */ /**图边右击菜单 */
const graphEdgeMenu = new Menu({ const graphEdgeMenu = new Menu({
offsetX: 6, offsetX: 6,
offseY: 10, offseY: 10,
itemTypes: ['edge'], itemTypes: ['edge'],
@@ -201,10 +235,10 @@ const graphEdgeMenu = new Menu({
break; break;
} }
}, },
}); });
/**图边展示 */ /**图边展示 */
const graphEdgeTooltip = new Tooltip({ const graphEdgeTooltip = new Tooltip({
offsetX: 10, offsetX: 10,
offsetY: 20, offsetY: 20,
getContent(e: any) { getContent(e: any) {
@@ -218,10 +252,10 @@ const graphEdgeTooltip = new Tooltip({
return outDiv; return outDiv;
}, },
itemTypes: ['edge'], itemTypes: ['edge'],
}); });
/**图绑定事件 */ /**图绑定事件 */
function fnGraphEvent(graph: Graph) { function fnGraphEvent(graph: Graph) {
// 调用 graph.add / graph.addItem 方法之后触发 // 调用 graph.add / graph.addItem 方法之后触发
graph.on('afteradditem', evt => { graph.on('afteradditem', evt => {
fnSelectSourceTargetOptionsData(); fnSelectSourceTargetOptionsData();
@@ -276,18 +310,18 @@ function fnGraphEvent(graph: Graph) {
// edge.toBack(); // edge.toBack();
// }); // });
}); });
} }
/**图元素选择开始结束点 */ /**图元素选择开始结束点 */
export const selectSourceTargetOptions = ref<Record<string, any>[]>([]); const selectSourceTargetOptions = ref<Record<string, any>[]>([]);
/**图元素选择嵌入 */ /**图元素选择嵌入分组 */
export const selectComboOptions = ref<Record<string, any>[]>([]); const selectComboOptions = ref<Record<string, any>[]>([]);
/** /**
* 图元素选择开始结束点数据获取 * 图元素选择开始结束点数据获取
*/ */
function fnSelectSourceTargetOptionsData() { function fnSelectSourceTargetOptionsData() {
// 节点 // 节点
selectSourceTargetOptions.value = []; selectSourceTargetOptions.value = [];
graphG6.value.getNodes().forEach((node: any) => { graphG6.value.getNodes().forEach((node: any) => {
@@ -298,7 +332,7 @@ function fnSelectSourceTargetOptionsData() {
info, info,
}); });
}); });
// // 分组
selectComboOptions.value = [ selectComboOptions.value = [
{ {
value: '', value: '',
@@ -315,10 +349,10 @@ function fnSelectSourceTargetOptionsData() {
selectSourceTargetOptions.value.push(comboInfo); selectSourceTargetOptions.value.push(comboInfo);
selectComboOptions.value.push(comboInfo); selectComboOptions.value.push(comboInfo);
}); });
} }
/**图数据渲染 */ /**图数据渲染 */
export function handleRanderGraph(container: HTMLElement, data: GraphData) { function handleRanderGraph(container: HTMLElement, data: GraphData) {
if (!container) return; if (!container) return;
const { clientHeight, clientWidth } = container; const { clientHeight, clientWidth } = container;
@@ -418,7 +452,7 @@ export function handleRanderGraph(container: HTMLElement, data: GraphData) {
}, },
}, },
}, },
// 全局节点 // 全局分组节点
defaultCombo: { defaultCombo: {
type: 'rect', // Combo 类型 type: 'rect', // Combo 类型
size: [40, 40], size: [40, 40],
@@ -463,26 +497,19 @@ export function handleRanderGraph(container: HTMLElement, data: GraphData) {
fnSelectSourceTargetOptionsData(); fnSelectSourceTargetOptionsData();
return graph; return graph;
} }
/**图模式选择项 */ /**图模式改变 default | edit */
export const graphModeOptions = [ function handleChangeMode(value: any) {
{
value: 'default',
label: '默认',
},
{
value: 'edit',
label: '编辑',
},
];
/**图模式选择项 */
export const graphMode = ref<string>('default');
/**图模式改变 default | edit */
export function handleChangeMode(value: any) {
console.log(value, JSON.parse(JSON.stringify(graphG6.value.save()))); console.log(value, JSON.parse(JSON.stringify(graphG6.value.save())));
graphG6.value.setMode(value); graphG6.value.setMode(value);
graphMode.value = graphG6.value.getCurrentMode(); graphMode.value = graphG6.value.getCurrentMode();
}
return {
selectSourceTargetOptions,
selectComboOptions,
handleRanderGraph,
handleChangeMode,
};
} }

View File

@@ -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,16 +86,19 @@ export const nodeImageOptions = [
{ value: '/svg/service_db.svg', label: '数据服务器' }, { value: '/svg/service_db.svg', label: '数据服务器' },
]; ];
/**图节点信息状态类型 */ export default function useNode() {
type NodeStateType = { const { t } = useI18n();
/**图节点信息状态类型 */
type NodeStateType = {
/**图节点原始数据 */ /**图节点原始数据 */
origin: Record<string, any>; origin: Record<string, any>;
/**图节点表单数据 */ /**图节点表单数据 */
form: Record<string, any>; form: Record<string, any>;
}; };
/**图节点信息状态 */ /**图节点信息状态 */
export let nodeState: NodeStateType = reactive({ let nodeState: NodeStateType = reactive({
origin: {}, origin: {},
form: { form: {
id: '', id: '',
@@ -120,19 +124,19 @@ export let nodeState: NodeStateType = reactive({
}, },
}, },
}, },
}); });
/**图节点对话框内表单属性和校验规则 */ /**图节点对话框内表单属性和校验规则 */
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;
@@ -152,10 +156,10 @@ watch(nodeState.form, node => {
graphG6.value.read(graphG6.value.save()); graphG6.value.read(graphG6.value.save());
} }
} }
}); });
/**图节点类型输入限制 */ /**图节点类型输入限制 */
export function handleNodeTypeChange(type: any) { function handleNodeTypeChange(type: any) {
// 设置图标属性 // 设置图标属性
if (['circle', 'ellipse', 'diamond', 'star', 'donut'].includes(type)) { if (['circle', 'ellipse', 'diamond', 'star', 'donut'].includes(type)) {
const origin = nodeState.origin; const origin = nodeState.origin;
@@ -236,10 +240,10 @@ export function handleNodeTypeChange(type: any) {
}); });
} }
} }
} }
/**图节点新增或更新 */ /**图节点新增或更新 */
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({
@@ -267,10 +271,10 @@ export function handleOkNode() {
nodeStateForm.resetFields(); nodeStateForm.resetFields();
nodeState.origin = {}; nodeState.origin = {};
return true; return true;
} }
/**图节点取消还原 */ /**图节点取消还原 */
export function handleCancelNode() { function handleCancelNode() {
const origin = JSON.parse(JSON.stringify(nodeState.origin)); const origin = JSON.parse(JSON.stringify(nodeState.origin));
if (origin.id) { if (origin.id) {
graphG6.value.updateItem(origin.id, origin); graphG6.value.updateItem(origin.id, origin);
@@ -285,4 +289,13 @@ export function handleCancelNode() {
nodeStateForm.resetFields(); nodeStateForm.resetFields();
nodeState.origin = {}; nodeState.origin = {};
} }
}
return {
nodeState,
nodeStateForm,
handleNodeTypeChange,
handleOkNode,
handleCancelNode,
};
} }

File diff suppressed because it is too large Load Diff