feat: 拓扑编辑demo
This commit is contained in:
@@ -4,9 +4,9 @@ import { PageContainer } from 'antdv-pro-layout';
|
||||
import useI18n from '@/hooks/useI18n';
|
||||
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
|
||||
import { listNe, stateNe } from '@/api/ne/ne';
|
||||
import message from 'ant-design-vue/lib/message';
|
||||
import { parseDateToStr } from '@/utils/date-utils';
|
||||
import { Graph, Util } from '@antv/g6';
|
||||
import { Graph, Menu, Tooltip, Util, registerBehavior } from '@antv/g6';
|
||||
import { message, Modal, Form, notification } from 'ant-design-vue/lib';
|
||||
const { t } = useI18n();
|
||||
|
||||
/**图DOM节点实例对象 */
|
||||
@@ -15,6 +15,12 @@ const graphG6Dom = ref<HTMLElement | undefined>(undefined);
|
||||
/**图实例对象 */
|
||||
const graphG6 = ref<any>(null);
|
||||
|
||||
/**图实例状态 */
|
||||
const graphG6State = reactive<Record<string, any>>({
|
||||
mode: 'default',
|
||||
editEdge: {},
|
||||
});
|
||||
|
||||
/**图数据 */
|
||||
const graphG6Data = reactive<Record<string, any>>({
|
||||
nodes: [
|
||||
@@ -309,18 +315,18 @@ function graphEvent(graph: Graph) {
|
||||
// 该边的结束点
|
||||
const target = edge.getTarget();
|
||||
// 先将边提前,再将端点提前。这样该边两个端点还是在该边上层,较符合常规。
|
||||
edge.toFront();
|
||||
source.toFront();
|
||||
target.toFront();
|
||||
// edge.toFront();
|
||||
// source.toFront();
|
||||
// target.toFront();
|
||||
});
|
||||
|
||||
graph.on('edge:mouseleave', (ev: any) => {
|
||||
// 获得图上所有边实例
|
||||
const edges = graph.getEdges();
|
||||
// 遍历边,将所有边的层级放置在后方,以恢复原样
|
||||
edges.forEach(edge => {
|
||||
edge.toBack();
|
||||
});
|
||||
// edges.forEach(edge => {
|
||||
// edge.toBack();
|
||||
// });
|
||||
});
|
||||
|
||||
graph.on('node:mouseenter', (ev: any) => {
|
||||
@@ -329,36 +335,122 @@ function graphEvent(graph: Graph) {
|
||||
// 获取该节点的所有相关边
|
||||
const edges = node.getEdges();
|
||||
// 遍历相关边,将所有相关边提前,再将相关边的两个端点提前,以保证相关边的端点在边的上方常规效果
|
||||
edges.forEach((edge: any) => {
|
||||
edge.toFront();
|
||||
edge.getSource().toFront();
|
||||
edge.getTarget().toFront();
|
||||
});
|
||||
// edges.forEach((edge: any) => {
|
||||
// edge.toFront();
|
||||
// edge.getSource().toFront();
|
||||
// edge.getTarget().toFront();
|
||||
// });
|
||||
});
|
||||
|
||||
graph.on('node:mouseleave', (ev: any) => {
|
||||
// 获得图上所有边实例
|
||||
const edges = graph.getEdges();
|
||||
// 遍历边,将所有边的层级放置在后方,以恢复原样
|
||||
edges.forEach(edge => {
|
||||
edge.toBack();
|
||||
});
|
||||
});
|
||||
|
||||
// 使用内置交互 create-edge,创建边之后触发
|
||||
graph.on('aftercreateedge', e => {
|
||||
console.log(JSON.parse(JSON.stringify(graph.save())));
|
||||
const edges = graph.save().edges as any;
|
||||
// Util.processParallelEdges(edges);
|
||||
graph.getEdges().forEach((edge, i) => {
|
||||
graph.updateItem(edge, {
|
||||
curveOffset: edges[i].curveOffset,
|
||||
curvePosition: edges[i].curvePosition,
|
||||
});
|
||||
});
|
||||
// edges.forEach(edge => {
|
||||
// edge.toBack();
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
/**图节点右击菜单 */
|
||||
const graphNodeMenu = new Menu({
|
||||
offsetX: 6,
|
||||
offseY: 10,
|
||||
itemTypes: ['node'],
|
||||
getContent(e) {
|
||||
const outDiv = document.createElement('div');
|
||||
outDiv.style.width = '180px';
|
||||
outDiv.innerHTML = `<ul>
|
||||
<li>测试01</li>
|
||||
<li>测试01</li>
|
||||
<li>测试01</li>
|
||||
<li>测试01</li>
|
||||
<li>测试01</li>
|
||||
</ul>`;
|
||||
return outDiv;
|
||||
},
|
||||
handleMenuClick(target, item) {
|
||||
console.log(target, item);
|
||||
},
|
||||
});
|
||||
|
||||
/**图节点展示 */
|
||||
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) {
|
||||
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':
|
||||
const info = item.getModel();
|
||||
console.log(Object.assign({}, info));
|
||||
|
||||
modalState.title = '边信息编辑';
|
||||
modalState.formEdge = Object.assign(modalState.formEdge, info);
|
||||
modalState.visibleByEdge = true;
|
||||
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 fnRanderGraph() {
|
||||
if (!graphG6Dom.value) return;
|
||||
@@ -390,16 +482,20 @@ function fnRanderGraph() {
|
||||
'drag-canvas',
|
||||
'zoom-canvas',
|
||||
'collapse-expand-combo',
|
||||
{
|
||||
type: 'create-edge',
|
||||
trigger: 'click', // 'click' by default. options: 'drag', 'click'
|
||||
},
|
||||
],
|
||||
edit: [
|
||||
{
|
||||
type: 'create-edge',
|
||||
trigger: 'click', // 'click' by default. options: 'drag', 'click'
|
||||
type: 'click-select',
|
||||
selectEdge: true,
|
||||
},
|
||||
{
|
||||
type: 'drag-node',
|
||||
onlyChangeComboSize: true,
|
||||
shouldEnd: (e: any) => {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
{ type: 'create-edge', key: 'alt' },
|
||||
],
|
||||
},
|
||||
groupByTypes: false,
|
||||
@@ -426,6 +522,9 @@ function fnRanderGraph() {
|
||||
lineWidth: 1,
|
||||
},
|
||||
},
|
||||
// defaultEdge: {
|
||||
// type: 'line',
|
||||
// },
|
||||
// 全局框节点 矩形
|
||||
defaultCombo: {
|
||||
type: 'rect', // Combo 类型
|
||||
@@ -434,10 +533,12 @@ function fnRanderGraph() {
|
||||
fillOpacity: 0.1,
|
||||
},
|
||||
},
|
||||
plugins: [graphNodeMenu, graphNodeTooltip, graphEdgeMenu, graphEdgeTooltip],
|
||||
});
|
||||
graph.data(graphG6Data);
|
||||
graph.render();
|
||||
|
||||
// 图绑定事件
|
||||
graphEvent(graph);
|
||||
|
||||
graphG6.value = graph;
|
||||
@@ -568,6 +669,185 @@ onMounted(() => {
|
||||
// fnGetList();
|
||||
fnRanderGraph();
|
||||
});
|
||||
|
||||
/**改变图模式 */
|
||||
function fnChangeMode(value: any) {
|
||||
console.log(value, JSON.parse(JSON.stringify(graphG6.value.save())));
|
||||
graphG6.value.setMode(value);
|
||||
}
|
||||
|
||||
/**对话框对象信息状态类型 */
|
||||
type ModalStateType = {
|
||||
/**图边框是否显示 */
|
||||
visibleByEdge: boolean;
|
||||
/**标题 */
|
||||
title: string;
|
||||
/**表单数据 */
|
||||
form: Record<string, any>;
|
||||
/**图边表单数据 */
|
||||
formEdge: Record<string, any>;
|
||||
/**确定按钮 loading */
|
||||
confirmLoading: boolean;
|
||||
};
|
||||
|
||||
/**对话框对象信息状态 */
|
||||
let modalState: ModalStateType = reactive({
|
||||
visibleByEdge: false,
|
||||
title: '图信息',
|
||||
form: {
|
||||
id: '',
|
||||
msisdn: '',
|
||||
},
|
||||
formEdge: {
|
||||
id: '',
|
||||
source: '',
|
||||
target: '',
|
||||
type: '',
|
||||
style: {},
|
||||
label: '',
|
||||
labelCfg: {
|
||||
refX: 0,
|
||||
refY: 0,
|
||||
position: 'middle',
|
||||
autoRotate: false,
|
||||
style: {},
|
||||
},
|
||||
},
|
||||
confirmLoading: false,
|
||||
});
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateForm = Form.useForm(
|
||||
modalState.form,
|
||||
reactive({
|
||||
imsi: [{ required: true, message: 'IMSI' + t('common.unableNull') }],
|
||||
msisdn: [{ required: true, message: 'MSISDN' + t('common.unableNull') }],
|
||||
staticIp: [
|
||||
{ required: true, message: 'static ip' + t('common.unableNull') },
|
||||
],
|
||||
smData: [
|
||||
{
|
||||
required: true,
|
||||
message: 'Subscribed SM Data' + t('common.unableNull'),
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/**对话框内表单属性和校验规则 */
|
||||
const modalStateFormEdge = Form.useForm(
|
||||
modalState.formEdge,
|
||||
reactive({
|
||||
id: [{ required: true, message: '边唯一 ID' }],
|
||||
source: [{ required: true, message: '起始点 id' }],
|
||||
target: [{ required: true, message: '结束点 id' }],
|
||||
type: [{ required: true, message: 'line' }],
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* 对话框弹出关闭执行函数
|
||||
* 进行表达规则校验
|
||||
*/
|
||||
function fnModalCancel() {
|
||||
modalState.visibleByEdge = false;
|
||||
modalStateForm.resetFields();
|
||||
modalStateFormEdge.resetFields();
|
||||
}
|
||||
|
||||
/**内置边类型 */
|
||||
const edgeType = [
|
||||
{
|
||||
type: 'line',
|
||||
description: '连接两个节点的直线',
|
||||
},
|
||||
{
|
||||
type: 'polyline',
|
||||
description: '多段线段构成的折线,连接两个端点',
|
||||
},
|
||||
{
|
||||
type: 'arc',
|
||||
description: '连接两个节点的一段圆弧',
|
||||
},
|
||||
{
|
||||
type: 'quadratic',
|
||||
description: '只有一个控制点的曲线',
|
||||
},
|
||||
{
|
||||
type: 'cubic',
|
||||
description: '有两个控制点的曲线',
|
||||
},
|
||||
{
|
||||
type: 'cubic-vertical',
|
||||
description: '垂直方向的三阶贝塞尔曲线',
|
||||
},
|
||||
{
|
||||
type: 'cubic-horizontal',
|
||||
description: '水平方向的三阶贝塞尔曲线',
|
||||
},
|
||||
{
|
||||
type: 'loop',
|
||||
description: '自环',
|
||||
},
|
||||
];
|
||||
|
||||
/**边新增 */
|
||||
function fnModalOkEdge() {
|
||||
const model = {
|
||||
id: '2-190',
|
||||
source: '2',
|
||||
target: '190',
|
||||
type: 'line',
|
||||
style: {
|
||||
stroke: 'steelblue',
|
||||
lineWidth: 5,
|
||||
},
|
||||
label: '边新增',
|
||||
labelCfg: {
|
||||
position: 'end',
|
||||
refY: 20,
|
||||
},
|
||||
};
|
||||
graphG6.value.addItem('edge', model);
|
||||
|
||||
console.log(JSON.parse(JSON.stringify(graphG6.value.save())));
|
||||
}
|
||||
|
||||
/**边新增 */
|
||||
function fnAddEdge() {
|
||||
const model = {
|
||||
id: '2-190',
|
||||
source: '2',
|
||||
target: '190',
|
||||
type: 'line',
|
||||
style: {
|
||||
stroke: 'steelblue',
|
||||
lineWidth: 5,
|
||||
},
|
||||
label: '边新增',
|
||||
labelCfg: {
|
||||
position: 'end',
|
||||
refY: 20,
|
||||
},
|
||||
};
|
||||
graphG6.value.addItem('edge', model);
|
||||
|
||||
console.log(JSON.parse(JSON.stringify(graphG6.value.save())));
|
||||
}
|
||||
|
||||
/**保存图数据 */
|
||||
function fnGraphSave() {
|
||||
sessionStorage.setItem('graph', JSON.stringify(graphG6.value.save()));
|
||||
|
||||
console.log(JSON.parse(JSON.stringify(graphG6.value.save())));
|
||||
}
|
||||
|
||||
/**保存图数据 */
|
||||
function fnGraphLoad() {
|
||||
const data = sessionStorage.getItem('graph') || '{}';
|
||||
graphG6.value.read(JSON.parse(data));
|
||||
console.log(JSON.parse(JSON.stringify(graphG6.value.save())));
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -580,56 +860,37 @@ onMounted(() => {
|
||||
<!-- 插槽-卡片左侧侧 -->
|
||||
<template #title>
|
||||
<div class="button-container" style="margin-bottom: -12px">
|
||||
<a-select size="small" value="view">
|
||||
<a-select-option value="view" key="view"> 查看 </a-select-option>
|
||||
<a-select
|
||||
size="small"
|
||||
v-model:value="graphG6State.mode"
|
||||
@change="fnChangeMode"
|
||||
>
|
||||
<a-select-option value="default" key="default">
|
||||
查看
|
||||
</a-select-option>
|
||||
<a-select-option value="edit" key="edit"> 编辑 </a-select-option>
|
||||
</a-select>
|
||||
|
||||
<a-button type="primary">
|
||||
<a-button type="primary" @click="fnAddEdge">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
{{ t('common.addText') }}
|
||||
fnAddEdge
|
||||
</a-button>
|
||||
|
||||
<a-button type="primary" danger ghost>
|
||||
<a-button type="primary" ghost @click="fnGraphLoad">
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.auth.batchDelText') }}
|
||||
fnGraphLoad
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.loadDataConfirm')"
|
||||
:ok-text="t('common.ok')"
|
||||
:cancel-text="t('common.cancel')"
|
||||
>
|
||||
<a-button type="dashed" danger>
|
||||
<template #icon>
|
||||
<SyncOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.sub.loadData') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
|
||||
<a-button type="dashed">
|
||||
<a-button type="dashed" @click="fnGraphSave">
|
||||
<template #icon>
|
||||
<ImportOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.sub.import') }}
|
||||
fnGraphSave
|
||||
</a-button>
|
||||
|
||||
<a-popconfirm
|
||||
:title="t('views.neUser.sub.exportConfirm')"
|
||||
ok-text="TXT"
|
||||
ok-type="default"
|
||||
>
|
||||
<a-button type="dashed">
|
||||
<template #icon>
|
||||
<ExportOutlined />
|
||||
</template>
|
||||
{{ t('views.neUser.sub.export') }}
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 插槽-卡片右侧 -->
|
||||
@@ -644,6 +905,162 @@ onMounted(() => {
|
||||
|
||||
<div ref="graphG6Dom" class="chart"></div>
|
||||
</a-card>
|
||||
|
||||
<!-- 批量增加框 -->
|
||||
<DraggableModal
|
||||
width="800px"
|
||||
:body-style="{ maxHeight: '650px', 'overflow-y': 'auto' }"
|
||||
:keyboard="false"
|
||||
:mask-closable="false"
|
||||
:visible="modalState.visibleByEdge"
|
||||
:title="modalState.title"
|
||||
:confirm-loading="modalState.confirmLoading"
|
||||
@ok="fnModalOkEdge"
|
||||
@cancel="fnModalCancel"
|
||||
>
|
||||
<a-form
|
||||
name="modalStateFromEdge"
|
||||
layout="horizontal"
|
||||
:label-col="{ span: 6 }"
|
||||
:labelWrap="true"
|
||||
>
|
||||
<a-form-item
|
||||
label="type"
|
||||
name="type"
|
||||
:label-col="{ span: 3 }"
|
||||
v-bind="modalStateFormEdge.validateInfos.type"
|
||||
>
|
||||
<a-select v-model:value="modalState.formEdge.type">
|
||||
<a-select-option
|
||||
v-for="opt in edgeType"
|
||||
:key="opt.type"
|
||||
:value="opt.type"
|
||||
>
|
||||
{{ opt.type }} : {{ opt.description }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="source"
|
||||
name="source"
|
||||
v-bind="modalStateFormEdge.validateInfos.source"
|
||||
>
|
||||
<a-input v-model:value="modalState.formEdge.source" allow-clear>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 起始点 id </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item
|
||||
label="target"
|
||||
name="target"
|
||||
v-bind="modalStateFormEdge.validateInfos.target"
|
||||
>
|
||||
<a-input v-model:value="modalState.formEdge.target" allow-clear>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 结束点 id </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="label" name="label">
|
||||
<a-input v-model:value="modalState.formEdge.label" allow-clear>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 文本文字,如果没有则不会显示 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg" name="labelCfg">
|
||||
{{ modalState.form.labelCfg }}
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg.refX" name="labelCfg.refX">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.labelCfg.refX"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 标签在 x 方向的偏移量 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg.refY" name="labelCfg.refY">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.labelCfg.refY"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 标签在 x 方向的偏移量 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="16">
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg.refX" name="labelCfg.refX">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.labelCfg.refX"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 标签在 x 方向的偏移量 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="12" :md="12" :xs="24">
|
||||
<a-form-item label="labelCfg.refY" name="labelCfg.refY">
|
||||
<a-input
|
||||
v-model:value="modalState.formEdge.labelCfg.refY"
|
||||
allow-clear
|
||||
>
|
||||
<template #prefix>
|
||||
<a-tooltip placement="topLeft">
|
||||
<template #title> 标签在 x 方向的偏移量 </template>
|
||||
<InfoCircleOutlined style="color: rgba(0, 0, 0, 0.45)" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</DraggableModal>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user