feat: 拓扑编辑页面多语言翻译

This commit is contained in:
TsMask
2024-01-05 10:22:17 +08:00
parent 7e2f404ba7
commit 6936355ed9
8 changed files with 922 additions and 406 deletions

View File

@@ -1024,6 +1024,158 @@ export default {
kbps: "Network entry/exit",
commandstats: "Command Statistics",
},
topologyBuild: {
graphMode: "Graph Model",
graphGroup: "Graph Group name",
graphGroupTip: "Graph data is updated when a graph group name already exists, and a new graph group is added when it does not.",
graphSave: "Save",
graphDelete: "Delete",
noData: "There is no group data at the moment, you can add a new group using [Graph Model - Edit].",
groupPlease: "Groups cannot be empty",
saveTtite: "Group Information Saving",
saveOk: "Saved group [{group}] successfully.",
saveFail: "Failed to save group [{group}].",
delTip: "Are you sure you want to delete the chart group named [{group}]?",
edgeTitleAdd: "Add Edge Info",
edgeTitleEdit: "Edit Edge Info",
nodeTitleAdd: "Add Node Info",
nodeTitleEdit: "Edit Node Info",
comboTitleAdd: "Add Combo Info",
comboTitleEdit: "Edit Combo Info",
comboFormParentId: "Parent Combo",
comboFormParentIdTip: "Place the current combo point into another combo box",
comboFormId: "Combo ID",
comboFormIdPlease: "Combo Unique ID",
comboFormIdNot: "Combo Element ID Error",
comboFormType: "Combo Type",
comboFormSize: "Minimum Size",
comboFormSizeCircle: "Radius",
comboFormSizeRect: "Length, height",
comboFormPadding: "Inner Margin",
comboFormPaddingRect: "Up, Left, Down, Right",
formStyleFill: "Filler Color",
formStyleFillOpacity: "Transparent Value",
formStyleStroke: "Trim Color",
formStyleLineWidth: "Trim Width",
comboFormChildren: "Element within Combo",
comboFormChildrenTip: "Elements include nodes and combo",
label: "Markup text and its configuration",
formLabel: "Label Text",
formLabelTip: "Text text, if there is none it will not be displayed",
formLabelStyleFill: "Text Color",
formLabelStyleFontSize: "Text Size",
formLabelRefX: "X Offset",
formLabelRefXTip: "The offset of the label in the x-direction",
formLabelRefY: "Y Offset",
formLabelRefYTip: "The offset of the label in the y-direction",
formLabelPosition: "Position",
comboFormLabelPosition: "Position of the label text relative to the position within the grouping",
nodeFormLabelPosition: "Position of the label text relative to the node",
edgeFormLabelPosition: "Position of label text relative to edge",
nodeFormLabelOffset: "Text Offset",
edgeFormLabelAutoRotate: "Follow the side rotation",
edgeFormLabelAutoRotateTip: "Whether the label text follows the side rotation",
edgeFormType: "Edge Type",
edgeFormTypePlease: "The edge type cannot be null",
edgeFormSource: "Start Element",
edgeFormSourcePlease: "Edge start element cannot be empty",
edgeFormTarget: "End Element",
edgeFormTargetPlease: "Edge end element cannot be empty",
edgeFormStartArrow: "Starting Arrow",
edgeFormStartArrowTip: "Default arrows are drawn at the beginning of edges",
edgeFormEndArrow: "Closing Arrow",
edgeFormEndArrowTip: "Default arrows are drawn at the end of edges",
nodeFormComboId: "Node Combo",
nodeFormComboIdTip: "Putting nodes into the combo box",
nodeFormId: "Node ID",
nodeFormIdPlease: "Node Unique ID",
nodeFormIdNot: "Node Element ID Error",
nodeFormType: "Node Type",
nodeFormX: "x Coordinate",
nodeFormY: "Y Coordinate",
nodeFormSize: "Node Size",
nodeFormSizeCircle: "Diameter, position of the center of the circle corresponding to the position of the node",
nodeFormSizeStar: "The size of the star, the center of the star is the position of the node.",
nodeFormSizeDonut: "Diameter, position of the center of the circle corresponding to the position of the node",
nodeFormSizeTriangle: "Side lengths, the center of the triangle is the position of the nodes.",
nodeFormSizeEllipse: "Long shaft diameter, short shaft diameter",
nodeFormSizeOhter: "Width, Height",
nodeFormDirection: "Direction",
nodeFormTypeImage: "Image",
nodeFormImg: "Image Source",
nodeFormClipShow: "Crop Feature",
nodeFormClipType: "Crop Image Shape",
nodeFormClipTypeCircle: "Radius of the clipped circle",
nodeFormClipTypeRectWidth: "Width of the clipping rectangle",
nodeFormClipTypeRectHeight: "Length of the clipping rectangle",
nodeFormClipTypeEllipseRx: "Radius of the long axis of the clipping ellipse",
nodeFormClipTypeEllipseRy: "Radius of the short axis of the clipped ellipse",
nodeFormClipX: "The x-coordinate of the cropped figure",
nodeFormClipY: "The y-coordinate of the cropped figure",
nodeFormIcon: "Icon",
nodeFormIconShow: "Does It Show",
nodeFormIconImg: "Icon Source",
nodeFormIconWidth: "Width",
nodeFormIconHeight: "Height",
nodeFormIconOffset: "Offset",
comboTypeCircle: "Circle",
comboTypeRect: "Rect",
comboLabelPositionTop: "Top",
comboLabelPositionLeft: "Left",
comboLabelPositionRight: "Right",
comboLabelPositionBottom: "Bottom",
comboLabelPositionCenter: "Center",
edgeFormIdPlease: "Edge Unique ID",
edgeFormIdNot: "Edge Element ID Error",
edgeTypeLine: "Straight line, a line connecting two nodes",
edgeTypePolyline: "Folding line, a line formed by multiple line segments connecting two endpoints",
edgeTypeArc: "Circular arc, a segment of a circular arc connecting two nodes",
edgeTypeQuadratic: "Second-order Bessel curves, curves with only one control point",
edgeTypeCubic: "Third-order Bessel curve with two control points",
edgeTypeCubicV: "Vertical third-order Bessel curve",
edgeTypeCubicH: "Horizontal third-order Bessel curve",
edgeTypeLoop: "Self-Loop",
edgeLabelPositionStart: "Start",
edgeLabelPositionMiddle: "Middle",
edgeLabelPositionEnd: "End",
nodeTypeCircle: "Circle",
nodeTypeRect: "Rect",
nodeTypeEllipse: "Ellipse",
nodeTypeDiamond: "Diamond",
nodeTypeTriangle: "Triangle",
nodeTypeStar: "Star",
nodeTypeImage: "Image",
nodeLabelPositionTop: "Top",
nodeLabelPositionLeft: "Left",
nodeLabelPositionRight: "Right",
nodeLabelPositionBottom: "Bottom",
nodeLabelPositionCenter: "Center",
nodeDirectionUp: "Up",
nodeDirectionDown: "Down",
nodeDirectionLeft: "Left",
nodeDirectionRight: "Right",
nodeImageClipCircle: "Circle",
nodeImageClipRect: "Rect",
nodeImageClipEllipse: "Ellipse",
nodeImageBase: "Base Stations",
nodeImageCloud: "Cloud",
nodeImageService: "Server",
nodeImageServiceDB: "Server Data",
graphModeDefault: "Default",
graphModeEdit: "Edit",
graphNotInfo: "no information",
graphMenuHide: "Hide",
graphMenuHideAllShow: "Show all hidden items",
graphMenuEdit: "Edit",
graphMenuDel: "Delete",
graphMenuAddEdge: "New Edge",
graphMenuAddNode: "New Node",
graphMenuAddCombo: "New Combo",
graphCanvas: "Canvas",
graphCombo: "Combo",
graphNode: "Node",
graphEdge: "Edge",
},
},
system:{
user: {

View File

@@ -1024,6 +1024,158 @@ export default {
kbps: "网络入口/出口",
commandstats: "命令统计",
},
topologyBuild: {
graphMode: "图模式",
graphGroup: "图组名",
graphGroupTip: "已存在图组名会更新图数据,不存在则新增图组",
graphSave: "保存",
graphDelete: "删除",
noData: "暂无图组数据,可使用【图模式-编辑】进行新增图组",
groupPlease: "图组不能为空",
saveTtite: "图组信息保存",
saveOk: "保存图组【{group}】成功",
saveFail: "保存图组【{group}】失败",
delTip: "确认要删除图组名为【{group}】的数据吗?",
edgeTitleAdd: "新增边信息编辑",
edgeTitleEdit: "边信息编辑",
nodeTitleAdd: "新增节点信息编辑",
nodeTitleEdit: "节点信息编辑",
comboTitleAdd: "新增分组信息编辑",
comboTitleEdit: "分组信息编辑",
comboFormParentId: "父分组",
comboFormParentIdTip: "将当前分组点放入到另一个分组框中",
comboFormId: "分组ID",
comboFormIdPlease: "分组唯一标识 ID",
comboFormIdNot: "分组元素ID错误",
comboFormType: "分组类型",
comboFormSize: "最小尺寸",
comboFormSizeCircle: "半径",
comboFormSizeRect: "长、高",
comboFormPadding: "内边距",
comboFormPaddingRect: "上、左、下、右",
formStyleFill: "填充色",
formStyleFillOpacity: "透明值",
formStyleStroke: "边颜色",
formStyleLineWidth: "边宽度",
comboFormChildren: "分组内元素",
comboFormChildrenTip: "元素包括节点和分组",
label: "标签文本及其配置",
formLabel: "标签文本",
formLabelTip: "文本文字,如果没有则不会显示",
formLabelStyleFill: "文本颜色",
formLabelStyleFontSize: "文本大小",
formLabelRefX: "x偏移",
formLabelRefXTip: "标签在 x 方向的偏移量",
formLabelRefY: "y偏移",
formLabelRefYTip: "标签在 y 方向的偏移量",
formLabelPosition: "位置",
comboFormLabelPosition: "标签文本相对于分组内的位置",
nodeFormLabelPosition: "标签文本相对于节点的位置",
edgeFormLabelPosition: "标签文本相对于边的位置",
nodeFormLabelOffset: "文本偏移",
edgeFormLabelAutoRotate: "跟随边旋转",
edgeFormLabelAutoRotateTip: "标签文字是否跟随边旋转",
edgeFormType: "边类型",
edgeFormTypePlease: "边类型不能为空",
edgeFormSource: "起始元素",
edgeFormSourcePlease: "边起始元素不能为空",
edgeFormTarget: "结束元素",
edgeFormTargetPlease: "边结束元素不能为空",
edgeFormStartArrow: "开始端箭头",
edgeFormStartArrowTip: "边的开始端绘制默认箭头",
edgeFormEndArrow: "结束端箭头",
edgeFormEndArrowTip: "边的结束端绘制默认箭头",
nodeFormComboId: "节点分组",
nodeFormComboIdTip: "将节点放入到分组框中",
nodeFormId: "节点ID",
nodeFormIdPlease: "节点唯一 ID",
nodeFormIdNot: "节点元素ID错误",
nodeFormType: "节点类型",
nodeFormX: "x 坐标",
nodeFormY: "Y 坐标",
nodeFormSize: "节点大小",
nodeFormSizeCircle: "直径, 圆心位置对应节点的位置",
nodeFormSizeStar: "星形的大小, 星星的中心位置是节点的位置",
nodeFormSizeDonut: "直径, 圆心位置对应节点的位置",
nodeFormSizeTriangle: "边长, 三角形的中心位置是节点的位置",
nodeFormSizeEllipse: "长轴直径、短轴直径",
nodeFormSizeOhter: "宽、高",
nodeFormDirection: "方向",
nodeFormTypeImage: "图片",
nodeFormImg: "图片来源",
nodeFormClipShow: "裁剪功能",
nodeFormClipType: "裁剪的图片形状",
nodeFormClipTypeCircle: "剪裁圆形的半径",
nodeFormClipTypeRectWidth: "剪裁矩形的宽度",
nodeFormClipTypeRectHeight: "剪裁矩形的长度",
nodeFormClipTypeEllipseRx: "剪裁椭圆的长轴半径",
nodeFormClipTypeEllipseRy: "剪裁椭圆的短轴半径",
nodeFormClipX: "裁剪图形的 x 坐标",
nodeFormClipY: "裁剪图形的 y 坐标",
nodeFormIcon: "图标",
nodeFormIconShow: "是否显示",
nodeFormIconImg: "图标来源",
nodeFormIconWidth: "宽度",
nodeFormIconHeight: "高度",
nodeFormIconOffset: "偏移",
comboTypeCircle: "圆形",
comboTypeRect: "矩形",
comboLabelPositionTop: "上",
comboLabelPositionLeft: "左",
comboLabelPositionRight: "右",
comboLabelPositionBottom: "下",
comboLabelPositionCenter: "居中",
edgeFormIdPlease: "边唯一 ID",
edgeFormIdNot: "边元素ID错误",
edgeTypeLine: "直线,连接两个节点的直线",
edgeTypePolyline: "折线,多段线段构成的折线,连接两个端点",
edgeTypeArc: "圆弧线,连接两个节点的一段圆弧",
edgeTypeQuadratic: "二阶贝塞尔曲线,只有一个控制点的曲线",
edgeTypeCubic: "三阶贝塞尔曲线,有两个控制点的曲线",
edgeTypeCubicV: "垂直方向的三阶贝塞尔曲线",
edgeTypeCubicH: "水平方向的三阶贝塞尔曲线",
edgeTypeLoop: "自环",
edgeLabelPositionStart: "开头",
edgeLabelPositionMiddle: "中间",
edgeLabelPositionEnd: "末尾",
nodeTypeCircle: "圆形",
nodeTypeRect: "矩形",
nodeTypeEllipse: "椭圆",
nodeTypeDiamond: "菱形",
nodeTypeTriangle: "三角形",
nodeTypeStar: "星形",
nodeTypeImage: "图片",
nodeLabelPositionTop: "上",
nodeLabelPositionLeft: "左",
nodeLabelPositionRight: "右",
nodeLabelPositionBottom: "下",
nodeLabelPositionCenter: "居中",
nodeDirectionUp: "向上",
nodeDirectionDown: "向下",
nodeDirectionLeft: "向左",
nodeDirectionRight: "向右",
nodeImageClipCircle: "圆形",
nodeImageClipRect: "矩形",
nodeImageClipEllipse: "椭圆",
nodeImageBase: "基站",
nodeImageCloud: "云",
nodeImageService: "服务器",
nodeImageServiceDB: "数据服务器",
graphModeDefault: "默认",
graphModeEdit: "编辑",
graphNotInfo: "无信息",
graphMenuHide: "隐藏",
graphMenuHideAllShow: "显示所有隐藏项",
graphMenuEdit: "编辑",
graphMenuDel: "删除",
graphMenuAddEdge: "新增边",
graphMenuAddNode: "新增节点",
graphMenuAddCombo: "新增分组",
graphCanvas: "画布",
graphCombo: "分组",
graphNode: "节点",
graphEdge: "边",
},
},
system:{
user:{

View File

@@ -1,37 +1,39 @@
<script setup lang="ts">
import { reactive, ref, watch } from 'vue';
import { reactive, watch } from 'vue';
import useI18n from '@/hooks/useI18n';
import {
graphEvent,
selectSourceTargetOptions,
selectComboOptions,
} from '../hooks/useGraph';
import useEdge, {
edgeTypeOptions,
edgePositionOptions,
} from '../hooks/useEdge';
import useNode, {
nodeTypeOptions,
nodePositionOptions,
nodeDirectionOptions,
nodeImageClipCfgOptions,
nodeImageOptions,
} from '../hooks/useNode';
import useCombo, {
comboTypeOptions,
comboPositionOptions,
} from '../hooks/useCombo';
import useEdge from '../hooks/useEdge';
import useNode from '../hooks/useNode';
import useCombo from '../hooks/useCombo';
const { t } = useI18n();
const {
comboTypeOptions,
comboLabelPositionOptions,
comboState,
comboStateForm,
handleComboTypeChange,
handleOkcombo,
handleCancelcombo,
} = useCombo();
const { edgeState, edgeStateForm, handleOkEdge, handleCancelEdge } = useEdge();
const {
edgeTypeOptions,
edgeLabelPositionOptions,
edgeState,
edgeStateForm,
handleOkEdge,
handleCancelEdge,
} = useEdge();
const {
nodeTypeOptions,
nodeLabelPositionOptions,
nodeDirectionOptions,
nodeImageClipCfgOptions,
nodeImageOptions,
nodeState,
nodeStateForm,
handleNodeTypeChange,
@@ -49,21 +51,21 @@ watch(graphEvent, v => {
if (type === 'canvas-create-edge') {
edgeState.origin = {};
edgeState.form.id = '#';
modalState.title = '新增边信息编辑';
modalState.title = t('views.monitor.topologyBuild.edgeTitleAdd');
modalState.formType = 'edge';
modalState.visible = true;
}
if (type === 'canvas-create-node') {
nodeState.origin = {};
nodeState.form.id = '';
modalState.title = '新增节点信息编辑';
modalState.title = t('views.monitor.topologyBuild.nodeTitleAdd');
modalState.formType = 'node';
modalState.visible = true;
}
if (type === 'canvas-create-combo') {
comboState.origin = {};
comboState.form.id = '';
modalState.title = '新增分组信息编辑';
modalState.title = t('views.monitor.topologyBuild.comboTitleAdd');
modalState.formType = 'combo';
modalState.visible = true;
}
@@ -72,7 +74,7 @@ watch(graphEvent, v => {
const edge = item.getModel();
edgeState.origin = JSON.parse(JSON.stringify(edge));
edgeState.form = Object.assign(edgeState.form, edge);
modalState.title = '边信息编辑';
modalState.title = t('views.monitor.topologyBuild.edgeTitleEdit');
modalState.formType = 'edge';
modalState.visible = true;
}
@@ -81,7 +83,7 @@ watch(graphEvent, v => {
const node = item.getModel();
nodeState.origin = JSON.parse(JSON.stringify(node));
nodeState.form = Object.assign(nodeState.form, node);
modalState.title = '节点信息编辑';
modalState.title = t('views.monitor.topologyBuild.nodeTitleEdit');
modalState.formType = 'node';
modalState.visible = true;
}
@@ -94,7 +96,7 @@ watch(graphEvent, v => {
if (Array.isArray(combo.children)) {
comboState.form.children = combo.children.map(item => item.id);
}
modalState.title = '分组信息编辑';
modalState.title = t('views.monitor.topologyBuild.comboTitleEdit');
modalState.formType = 'combo';
modalState.visible = true;
}
@@ -184,7 +186,7 @@ function fnModalCancel() {
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<!-- 排版 -->
<!-- 分组排版 -->
<a-form
v-if="modalState.formType === 'combo'"
name="modalStateFromCombo"
@@ -193,9 +195,9 @@ function fnModalCancel() {
:labelWrap="true"
>
<a-form-item
label="父节点分组"
:label="t('views.monitor.topologyBuild.comboFormParentId')"
name="parentId"
help="将当前分组点放入到另一个分组框中"
:help="t('views.monitor.topologyBuild.comboFormParentIdTip')"
:label-col="{ span: 3 }"
>
<a-select
@@ -207,7 +209,7 @@ function fnModalCancel() {
</a-form-item>
<a-form-item
label="分组ID"
:label="t('views.monitor.topologyBuild.comboFormId')"
name="type"
:label-col="{ span: 3 }"
v-bind="comboStateForm.validateInfos.id"
@@ -221,7 +223,7 @@ function fnModalCancel() {
</a-form-item>
<a-form-item
label="节点类型"
:label="t('views.monitor.topologyBuild.comboFormType')"
name="type"
:label-col="{ span: 3 }"
v-bind="comboStateForm.validateInfos.type"
@@ -238,19 +240,26 @@ function fnModalCancel() {
<!-- 圆形尺寸 -->
<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-form-item
:label="t('views.monitor.topologyBuild.comboFormSize')"
name="size"
:help="t('views.monitor.topologyBuild.comboFormSizeCircle')"
>
<a-input-number
:min="0"
:max="99"
:max="300"
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-form-item
:label="t('views.monitor.topologyBuild.comboFormPadding')"
name="padding"
>
<a-input-number
:min="0"
:max="99"
:max="300"
v-model:value="comboState.form.padding"
></a-input-number>
</a-form-item>
@@ -261,15 +270,14 @@ function fnModalCancel() {
<a-row :gutter="16" v-if="comboState.form.type === 'rect'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="最小尺寸"
:label="t('views.monitor.topologyBuild.comboFormSize')"
name="size"
:help="['长', '高'].join('、')"
:help="t('views.monitor.topologyBuild.comboFormSizeRect')"
>
<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"
@@ -280,15 +288,14 @@ function fnModalCancel() {
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="内边距"
:label="t('views.monitor.topologyBuild.comboFormPadding')"
name="padding"
:help="['上', '左', '下', '右'].join('、')"
:help="t('views.monitor.topologyBuild.comboFormPaddingRect')"
>
<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"
@@ -301,7 +308,10 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="节点填充色" name="fill">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleFill')"
name="fill"
>
<a-input
v-model:value="comboState.form.style.fill"
type="color"
@@ -309,7 +319,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="透明值" name="fillOpacity">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleFillOpacity')"
name="fillOpacity"
>
<a-input-number
v-model:value="comboState.form.style.fillOpacity"
style="width: 100%"
@@ -321,7 +334,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="描边颜色" name="stroke">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleStroke')"
name="stroke"
>
<a-input
v-model:value="comboState.form.style.stroke"
type="color"
@@ -329,7 +345,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="描边宽度" name="lineWidth">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleLineWidth')"
name="lineWidth"
>
<a-input-number
v-model:value="comboState.form.style.lineWidth"
style="width: 100%"
@@ -342,9 +361,9 @@ function fnModalCancel() {
</a-row>
<a-form-item
label="分组内元素"
:label="t('views.monitor.topologyBuild.comboFormChildren')"
name="children"
help="元素包括节点和分组"
:help="t('views.monitor.topologyBuild.comboFormChildrenTip')"
:label-col="{ span: 3 }"
v-if="comboState.form.id !== comboState.origin.id"
>
@@ -357,13 +376,15 @@ function fnModalCancel() {
></a-select>
</a-form-item>
<a-divider orientation="left"> 标签文本及其配置 </a-divider>
<a-divider orientation="left">
{{ t('views.monitor.topologyBuild.label') }}
</a-divider>
<a-form-item
label="标签文本"
:label="t('views.monitor.topologyBuild.formLabel')"
name="label"
:label-col="{ span: 3 }"
help="文本文字,如果没有则不会显示"
:help="t('views.monitor.topologyBuild.formLabelTip')"
>
<a-input
v-model:value="comboState.form.label"
@@ -375,7 +396,10 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本颜色" name="fill">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFill')"
name="fill"
>
<a-input
v-model:value="comboState.form.labelCfg.style.fill"
type="color"
@@ -383,7 +407,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本大小" name="fontSize">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFontSize')"
name="fontSize"
>
<a-input-number
v-model:value="comboState.form.labelCfg.style.fontSize"
style="width: 100%"
@@ -398,9 +425,9 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="x偏移"
:label="t('views.monitor.topologyBuild.formLabelRefX')"
name="labelCfg.refX"
help="标签在 x 方向的偏移量"
:help="t('views.monitor.topologyBuild.formLabelRefXTip')"
>
<a-input-number
v-model:value="comboState.form.labelCfg.refX"
@@ -413,9 +440,9 @@ function fnModalCancel() {
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="y偏移"
:label="t('views.monitor.topologyBuild.formLabelRefY')"
name="labelCfg.refY"
help="标签在 y 方向的偏移量"
:help="t('views.monitor.topologyBuild.formLabelRefYTip')"
>
<a-input-number
v-model:value="comboState.form.labelCfg.refY"
@@ -431,13 +458,13 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="位置"
:label="t('views.monitor.topologyBuild.formLabelPosition')"
name="labelCfg.position"
help="标签文本相对于边的位置"
:help="t('views.monitor.topologyBuild.comboFormLabelPosition')"
>
<a-select
v-model:value="comboState.form.labelCfg.position"
:options="comboPositionOptions"
:options="comboLabelPositionOptions"
>
</a-select>
</a-form-item>
@@ -454,9 +481,9 @@ function fnModalCancel() {
:labelWrap="true"
>
<a-form-item
label="节点分组"
:label="t('views.monitor.topologyBuild.nodeFormComboId')"
name="comboId"
help="将节点放入到分组框中"
:help="t('views.monitor.topologyBuild.nodeFormComboIdTip')"
:label-col="{ span: 3 }"
>
<a-select
@@ -468,7 +495,7 @@ function fnModalCancel() {
</a-form-item>
<a-form-item
label="节点ID"
:label="t('views.monitor.topologyBuild.nodeFormId')"
name="type"
:label-col="{ span: 3 }"
v-bind="nodeStateForm.validateInfos.id"
@@ -482,7 +509,7 @@ function fnModalCancel() {
</a-form-item>
<a-form-item
label="节点类型"
:label="t('views.monitor.topologyBuild.nodeFormType')"
name="type"
:label-col="{ span: 3 }"
v-bind="nodeStateForm.validateInfos.type"
@@ -498,7 +525,10 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="x 坐标" name="x">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormX')"
name="x"
>
<a-input-number
v-model:value="nodeState.form.x"
style="width: 100%"
@@ -507,7 +537,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="y 坐标" name="y">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormY')"
name="y"
>
<a-input-number
v-model:value="nodeState.form.y"
style="width: 100%"
@@ -525,9 +558,9 @@ function fnModalCancel() {
v-if="nodeState.form.type === 'circle'"
>
<a-form-item
label="节点大小"
:label="t('views.monitor.topologyBuild.nodeFormSize')"
name="size"
help="直径, 圆心位置对应节点的位置"
:help="t('views.monitor.topologyBuild.nodeFormSizeCircle')"
>
<a-input-number
v-model:value="nodeState.form.size"
@@ -543,9 +576,9 @@ function fnModalCancel() {
v-else-if="nodeState.form.type === 'star'"
>
<a-form-item
label="节点大小"
:label="t('views.monitor.topologyBuild.nodeFormSize')"
name="size"
help="星形的大小, 星星的中心位置是节点的位置"
:help="t('views.monitor.topologyBuild.nodeFormSizeStar')"
>
<a-input-number
v-model:value="nodeState.form.size"
@@ -561,9 +594,9 @@ function fnModalCancel() {
v-else-if="nodeState.form.type === 'donut'"
>
<a-form-item
label="节点大小"
:label="t('views.monitor.topologyBuild.nodeFormSize')"
name="size"
help="直径, 圆心位置对应节点的位置"
:help="t('views.monitor.topologyBuild.nodeFormSizeDonut')"
>
<a-input-number
v-model:value="nodeState.form.size"
@@ -579,9 +612,9 @@ function fnModalCancel() {
v-else-if="nodeState.form.type === 'triangle'"
>
<a-form-item
label="节点大小"
:label="t('views.monitor.topologyBuild.nodeFormSize')"
name="size"
help="边长, 三角形的中心位置是节点的位置"
:help="t('views.monitor.topologyBuild.nodeFormSizeTriangle')"
>
<a-input-number
:min="0"
@@ -594,23 +627,18 @@ function fnModalCancel() {
</a-col>
<a-col :lg="12" :md="12" :xs="24" v-else>
<a-form-item
label="节点大小"
:label="t('views.monitor.topologyBuild.nodeFormSize')"
name="size"
:help="
nodeState.form.type === 'ellipse'
? ['长轴直径', '短轴直径'].join('、')
: ['宽', '高'].join('、')
? t('views.monitor.topologyBuild.nodeFormSizeEllipse')
: t('views.monitor.topologyBuild.nodeFormSizeOhter')
"
>
<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="1000"
@@ -625,7 +653,10 @@ function fnModalCancel() {
<template v-if="nodeState.form.type !== 'image'">
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="描边颜色" name="stroke">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleStroke')"
name="stroke"
>
<a-input
v-model:value="nodeState.form.style.stroke"
type="color"
@@ -633,7 +664,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="描边宽度" name="lineWidth">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleLineWidth')"
name="lineWidth"
>
<a-input-number
v-model:value="nodeState.form.style.lineWidth"
style="width: 100%"
@@ -644,7 +678,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="节点填充色" name="fill">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleFill')"
name="fill"
>
<a-input
v-model:value="nodeState.form.style.fill"
type="color"
@@ -657,7 +694,10 @@ function fnModalCancel() {
:xs="24"
v-if="nodeState.form.type === 'triangle'"
>
<a-form-item label="方向" name="direction">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormDirection')"
name="direction"
>
<a-select
v-model:value="nodeState.form.direction"
:options="nodeDirectionOptions"
@@ -668,13 +708,15 @@ function fnModalCancel() {
</a-row>
</template>
<a-divider orientation="left"> 标签文本及其配置 </a-divider>
<a-divider orientation="left">
{{ t('views.monitor.topologyBuild.label') }}
</a-divider>
<a-form-item
label="标签文本"
:label="t('views.monitor.topologyBuild.formLabel')"
name="label"
:label-col="{ span: 3 }"
help="文本文字,如果没有则不会显示"
:help="t('views.monitor.topologyBuild.formLabelTip')"
>
<a-input
v-model:value="nodeState.form.label"
@@ -686,7 +728,10 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本颜色" name="fill">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFill')"
name="fill"
>
<a-input
v-model:value="nodeState.form.labelCfg.style.fill"
type="color"
@@ -694,7 +739,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本大小" name="fontSize">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFontSize')"
name="fontSize"
>
<a-input-number
v-model:value="nodeState.form.labelCfg.style.fontSize"
style="width: 100%"
@@ -709,19 +757,22 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="位置"
:label="t('views.monitor.topologyBuild.formLabelPosition')"
name="labelCfg.position"
help="文本相对于节点的位置"
:help="t('views.monitor.topologyBuild.nodeFormLabelPosition')"
>
<a-select
v-model:value="nodeState.form.labelCfg.position"
:options="nodePositionOptions"
:options="nodeLabelPositionOptions"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本偏移" name="labelCfg.offset">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormLabelOffset')"
name="labelCfg.offset"
>
<a-input-number
v-model:value="nodeState.form.labelCfg.offset"
style="width: 100%"
@@ -734,20 +785,24 @@ function fnModalCancel() {
</a-row>
<template v-if="nodeState.form.type === 'image'">
<a-divider orientation="left"> 图片 </a-divider>
<a-divider orientation="left">
{{ t('views.monitor.topologyBuild.nodeFormTypeImage') }}
</a-divider>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="裁剪功能" name="clipCfg.show">
<a-switch
v-model:checked="nodeState.form.clipCfg.show"
checked-children=""
un-checked-children=""
/>
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipShow')"
name="clipCfg.show"
>
<a-switch v-model:checked="nodeState.form.clipCfg.show" />
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="图片来源" name="img">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormImg')"
name="img"
>
<a-input-group compact>
<a-auto-complete
v-model:value="nodeState.form.img"
@@ -780,7 +835,10 @@ function fnModalCancel() {
<template v-if="nodeState.form.clipCfg.show">
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="裁剪的图片形状" name="direction">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipType')"
name="clipCfg.type"
>
<a-select
v-model:value="nodeState.form.clipCfg.type"
:options="nodeImageClipCfgOptions"
@@ -793,7 +851,10 @@ function fnModalCancel() {
<!-- 剪裁圆形 -->
<a-row :gutter="16" v-if="nodeState.form.clipCfg.type === 'circle'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="剪裁圆形的半径" name="clipCfg.r">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipTypeCircle')"
name="clipCfg.r"
>
<a-input-number
v-model:value="nodeState.form.clipCfg.r"
style="width: 100%"
@@ -808,7 +869,12 @@ function fnModalCancel() {
<!-- 剪裁矩形 -->
<a-row :gutter="16" v-if="nodeState.form.clipCfg.type === 'rect'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="剪裁矩形的宽度" name="clipCfg.width">
<a-form-item
:label="
t('views.monitor.topologyBuild.nodeFormClipTypeRectWidth')
"
name="clipCfg.width"
>
<a-input-number
v-model:value="nodeState.form.clipCfg.width"
style="width: 100%"
@@ -819,7 +885,12 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="剪裁矩形的长度" name="clipCfg.height">
<a-form-item
:label="
t('views.monitor.topologyBuild.nodeFormClipTypeRectHeight')
"
name="clipCfg.height"
>
<a-input-number
v-model:value="nodeState.form.clipCfg.height"
style="width: 100%"
@@ -834,7 +905,12 @@ function fnModalCancel() {
<!-- 剪裁椭圆 -->
<a-row :gutter="16" v-if="nodeState.form.clipCfg.type === 'ellipse'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="剪裁椭圆的长轴半径" name="clipCfg.rx">
<a-form-item
:label="
t('views.monitor.topologyBuild.nodeFormClipTypeEllipseRx')
"
name="clipCfg.rx"
>
<a-input-number
v-model:value="nodeState.form.clipCfg.rx"
style="width: 100%"
@@ -845,7 +921,12 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="剪裁椭圆的短轴半径" name="clipCfg.ry">
<a-form-item
:label="
t('views.monitor.topologyBuild.nodeFormClipTypeEllipseRy')
"
name="clipCfg.ry"
>
<a-input-number
v-model:value="nodeState.form.clipCfg.ry"
style="width: 100%"
@@ -860,7 +941,10 @@ function fnModalCancel() {
<!-- 裁剪图形坐标 -->
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="裁剪图形的 x 坐标" name="clipCfg.x">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipX')"
name="clipCfg.x"
>
<a-input-number
v-model:value="nodeState.form.clipCfg.x"
style="width: 100%"
@@ -871,7 +955,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="裁剪图形的 y 坐标" name="clipCfg.y">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormClipY')"
name="clipCfg.y"
>
<a-input-number
v-model:value="nodeState.form.clipCfg.y"
style="width: 100%"
@@ -893,20 +980,24 @@ function fnModalCancel() {
nodeState.form.type !== 'image'
"
>
<a-divider orientation="left"> 图标 </a-divider>
<a-divider orientation="left">
{{ t('views.monitor.topologyBuild.nodeFormIcon') }}
</a-divider>
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="是否显示" name="icon.show">
<a-switch
v-model:checked="nodeState.form.icon.show"
checked-children=""
un-checked-children=""
/>
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormIconShow')"
name="icon.show"
>
<a-switch v-model:checked="nodeState.form.icon.show" />
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="图标来源" name="icon.img">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormIconImg')"
name="icon.img"
>
<a-auto-complete
v-model:value="nodeState.form.icon.img"
:options="nodeImageOptions"
@@ -919,7 +1010,10 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="宽度" name="icon.width">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormIconWidth')"
name="icon.width"
>
<a-input-number
v-model:value="nodeState.form.icon.width"
style="width: 100%"
@@ -930,7 +1024,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="高度" name="icon.height">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormIconHeight')"
name="icon.height"
>
<a-input-number
v-model:value="nodeState.form.icon.height"
style="width: 100%"
@@ -944,7 +1041,10 @@ function fnModalCancel() {
<a-row :gutter="16" v-if="nodeState.form.type === 'triangle'">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="偏移" name="icon.offset">
<a-form-item
:label="t('views.monitor.topologyBuild.nodeFormIconOffset')"
name="icon.offset"
>
<a-input-number
v-model:value="nodeState.form.icon.offset"
style="width: 100%"
@@ -967,7 +1067,7 @@ function fnModalCancel() {
:labelWrap="true"
>
<a-form-item
label="边类型"
:label="t('views.monitor.topologyBuild.edgeFormType')"
name="type"
:label-col="{ span: 3 }"
v-bind="edgeStateForm.validateInfos.type"
@@ -982,7 +1082,7 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="起始元素"
:label="t('views.monitor.topologyBuild.edgeFormSource')"
name="source"
v-bind="edgeStateForm.validateInfos.source"
>
@@ -996,7 +1096,7 @@ function fnModalCancel() {
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="结束元素"
:label="t('views.monitor.topologyBuild.edgeFormTarget')"
name="target"
v-bind="edgeStateForm.validateInfos.target"
>
@@ -1012,7 +1112,10 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="边的颜色" name="stroke">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleStroke')"
name="stroke"
>
<a-input
v-model:value="edgeState.form.style.stroke"
type="color"
@@ -1020,7 +1123,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="边宽度" name="lineWidth">
<a-form-item
:label="t('views.monitor.topologyBuild.formStyleLineWidth')"
name="lineWidth"
>
<a-input-number
v-model:value="edgeState.form.style.lineWidth"
style="width: 100%"
@@ -1035,39 +1141,33 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="开始端箭头"
:label="t('views.monitor.topologyBuild.edgeFormStartArrow')"
name="startArrow"
help="边的开始端绘制默认箭头"
:help="t('views.monitor.topologyBuild.edgeFormStartArrowTip')"
>
<a-switch
v-model:checked="edgeState.form.style.startArrow"
checked-children=""
un-checked-children=""
/>
<a-switch v-model:checked="edgeState.form.style.startArrow" />
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="结束端箭头"
:label="t('views.monitor.topologyBuild.edgeFormEndArrow')"
name="endArrow"
help="边的结束端绘制默认箭头"
:help="t('views.monitor.topologyBuild.edgeFormEndArrowTip')"
>
<a-switch
v-model:checked="edgeState.form.style.endArrow"
checked-children=""
un-checked-children=""
/>
<a-switch v-model:checked="edgeState.form.style.endArrow" />
</a-form-item>
</a-col>
</a-row>
<a-divider orientation="left"> 标签文本及其配置 </a-divider>
<a-divider orientation="left">
{{ t('views.monitor.topologyBuild.label') }}
</a-divider>
<a-form-item
label="标签文本"
:label="t('views.monitor.topologyBuild.formLabel')"
name="label"
:label-col="{ span: 3 }"
help="文本文字如果没有则不会显示"
:help="t('views.monitor.topologyBuild.formLabelTip')"
>
<a-input
v-model:value="edgeState.form.label"
@@ -1079,7 +1179,10 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本颜色" name="fill">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFill')"
name="fill"
>
<a-input
v-model:value="edgeState.form.labelCfg.style.fill"
type="color"
@@ -1087,7 +1190,10 @@ function fnModalCancel() {
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="文本大小" name="fontSize">
<a-form-item
:label="t('views.monitor.topologyBuild.formLabelStyleFontSize')"
name="fontSize"
>
<a-input-number
v-model:value="edgeState.form.labelCfg.style.fontSize"
style="width: 100%"
@@ -1102,9 +1208,9 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="x偏移"
:label="t('views.monitor.topologyBuild.formLabelRefX')"
name="labelCfg.refX"
help="标签在 x 方向的偏移量"
:help="t('views.monitor.topologyBuild.formLabelRefXTip')"
>
<a-input-number
v-model:value="edgeState.form.labelCfg.refX"
@@ -1117,9 +1223,9 @@ function fnModalCancel() {
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="y偏移"
:label="t('views.monitor.topologyBuild.formLabelRefY')"
name="labelCfg.refY"
help="标签在 y 方向的偏移量"
:help="t('views.monitor.topologyBuild.formLabelRefYTip')"
>
<a-input-number
v-model:value="edgeState.form.labelCfg.refY"
@@ -1135,28 +1241,24 @@ function fnModalCancel() {
<a-row :gutter="16">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="位置"
:label="t('views.monitor.topologyBuild.formLabelPosition')"
name="labelCfg.position"
help="标签文本相对于边的位置"
:help="t('views.monitor.topologyBuild.edgeFormLabelPosition')"
>
<a-select
v-model:value="edgeState.form.labelCfg.position"
:options="edgePositionOptions"
:options="edgeLabelPositionOptions"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item
label="跟随边旋转"
:label="t('views.monitor.topologyBuild.edgeFormLabelAutoRotate')"
name="labelCfg.autoRotate"
help="标签文字是否跟随边旋转"
:help="t('views.monitor.topologyBuild.edgeFormLabelAutoRotateTip')"
>
<a-switch
v-model:checked="edgeState.form.labelCfg.autoRotate"
checked-children=""
un-checked-children=""
/>
<a-switch v-model:checked="edgeState.form.labelCfg.autoRotate" />
</a-form-item>
</a-col>
</a-row>

View File

@@ -3,45 +3,45 @@ import { reactive, toRaw, watch } from 'vue';
import { graphG6, selectSourceTargetOptions } from './useGraph';
import useI18n from '@/hooks/useI18n';
/**图分组内置类型 */
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: '居中',
},
];
export default function useCombo() {
const { t } = useI18n();
/**图分组内置类型 */
const comboTypeOptions = [
{
value: 'circle',
label: t('views.monitor.topologyBuild.comboTypeCircle'),
},
{
value: 'rect',
label: t('views.monitor.topologyBuild.comboTypeRect'),
},
];
/**图分组标签文本位置 */
const comboLabelPositionOptions = [
{
value: 'top',
label: t('views.monitor.topologyBuild.comboLabelPositionTop'),
},
{
value: 'left',
label: t('views.monitor.topologyBuild.comboLabelPositionLeft'),
},
{
value: 'right',
label: t('views.monitor.topologyBuild.comboLabelPositionRight'),
},
{
value: 'bottom',
label: t('views.monitor.topologyBuild.comboLabelPositionBottom'),
},
{
value: 'center',
label: t('views.monitor.topologyBuild.comboLabelPositionCenter'),
},
];
/**图分组信息状态类型 */
type ComboStateType = {
/**图分组原始数据 */
@@ -86,7 +86,12 @@ export default function useCombo() {
const comboStateForm = Form.useForm(
comboState.form,
reactive({
id: [{ required: true, message: '分组唯一标识 ID' }],
id: [
{
required: true,
message: t('views.monitor.topologyBuild.comboFormIdPlease'),
},
],
})
);
@@ -130,8 +135,8 @@ export default function useCombo() {
const combo = JSON.parse(JSON.stringify(comboState.form));
if (!combo.id) {
message.warn({
content: `分组元素ID错误`,
duration: 2,
content: t('views.monitor.topologyBuild.comboFormIdNot'),
duration: 3,
});
return false;
}
@@ -178,6 +183,8 @@ export default function useCombo() {
}
return {
comboTypeOptions,
comboLabelPositionOptions,
comboState,
comboStateForm,
handleComboTypeChange,

View File

@@ -3,61 +3,61 @@ import { reactive, watch } from 'vue';
import useI18n from '@/hooks/useI18n';
import { graphG6 } from './useGraph';
/**图边内置边类型 */
export const edgeTypeOptions = [
{
value: 'line',
label: '直线,连接两个节点的直线',
},
{
value: 'polyline',
label: '折线,多段线段构成的折线,连接两个端点',
},
{
value: 'arc',
label: '圆弧线,连接两个节点的一段圆弧',
},
{
value: 'quadratic',
label: '二阶贝塞尔曲线,只有一个控制点的曲线',
},
{
value: 'cubic',
label: '三阶贝塞尔曲线,有两个控制点的曲线',
},
{
value: 'cubic-vertical',
label: '垂直方向的三阶贝塞尔曲线',
},
{
value: 'cubic-horizontal',
label: '水平方向的三阶贝塞尔曲线',
},
{
value: 'loop',
label: '自环',
},
];
/**图边标签文本位置 */
export const edgePositionOptions = [
{
value: 'start',
label: '开头',
},
{
value: 'middle',
label: '中间',
},
{
value: 'end',
label: '末尾',
},
];
export default function useEdge() {
const { t } = useI18n();
/**图边内置边类型 */
const edgeTypeOptions = [
{
value: 'line',
label: t('views.monitor.topologyBuild.edgeTypeLine'),
},
{
value: 'polyline',
label: t('views.monitor.topologyBuild.edgeTypePolyline'),
},
{
value: 'arc',
label: t('views.monitor.topologyBuild.edgeTypeArc'),
},
{
value: 'quadratic',
label: t('views.monitor.topologyBuild.edgeTypeQuadratic'),
},
{
value: 'cubic',
label: t('views.monitor.topologyBuild.edgeTypeCubic'),
},
{
value: 'cubic-vertical',
label: t('views.monitor.topologyBuild.edgeTypeCubicV'),
},
{
value: 'cubic-horizontal',
label: t('views.monitor.topologyBuild.edgeTypeCubicH'),
},
{
value: 'loop',
label: t('views.monitor.topologyBuild.edgeTypeLoop'),
},
];
/**图边标签文本位置 */
const edgeLabelPositionOptions = [
{
value: 'start',
label: t('views.monitor.topologyBuild.edgeLabelPositionStart'),
},
{
value: 'middle',
label: t('views.monitor.topologyBuild.edgeLabelPositionMiddle'),
},
{
value: 'end',
label: t('views.monitor.topologyBuild.edgeLabelPositionEnd'),
},
];
/**图边信息状态类型 */
type EdgeStateType = {
/**图边原始数据 */
@@ -71,8 +71,8 @@ export default function useEdge() {
origin: {},
form: {
id: '',
source: '',
target: '',
source: undefined,
target: undefined,
type: 'polyline',
style: {
offset: 20,
@@ -100,10 +100,30 @@ export default function useEdge() {
const edgeStateForm = Form.useForm(
edgeState.form,
reactive({
id: [{ required: true, message: '边唯一 ID' }],
source: [{ required: true, message: '起始点 id' }],
target: [{ required: true, message: '结束点 id' }],
type: [{ required: true, message: 'line' }],
id: [
{
required: true,
message: t('views.monitor.topologyBuild.edgeFormIdPlease'),
},
],
source: [
{
required: true,
message: t('views.monitor.topologyBuild.edgeFormSourcePlease'),
},
],
target: [
{
required: true,
message: t('views.monitor.topologyBuild.edgeFormTargetPlease'),
},
],
type: [
{
required: true,
message: t('views.monitor.topologyBuild.edgeFormTypePlease'),
},
],
})
);
@@ -113,6 +133,10 @@ export default function useEdge() {
// 新增id是#不监听变化
const edgeId = info.id;
if (edgeId && edgeId !== '#') {
// 开始结束一样就自环
if (info.source === info.target) {
info.type = 'loop';
}
graphG6.value.clearItemStates(edgeId, 'selected');
graphG6.value.updateItem(edgeId, info);
}
@@ -126,12 +150,16 @@ export default function useEdge() {
const edge = JSON.parse(JSON.stringify(edgeState.form));
if (!edge.id) {
message.warn({
content: `边元素ID错误`,
duration: 2,
content: t('views.monitor.topologyBuild.edgeFormIdNot'),
duration: 3,
});
return false;
}
// 开始结束一样就自环
if (edge.source === edge.target) {
edge.type = 'loop';
}
// 存在更新新增id是#不监听变化
const item = graphG6.value.findById(edge.id);
if (item) {
@@ -165,5 +193,12 @@ export default function useEdge() {
edgeState.origin = {};
}
return { edgeState, edgeStateForm, handleOkEdge, handleCancelEdge };
return {
edgeTypeOptions,
edgeLabelPositionOptions,
edgeState,
edgeStateForm,
handleOkEdge,
handleCancelEdge,
};
}

View File

@@ -10,18 +10,6 @@ import {
} from '@antv/g6';
import { ref } from 'vue';
/**图模式选择项 */
export const graphModeOptions = [
{
value: 'default',
label: '默认',
},
{
value: 'edit',
label: '编辑',
},
];
/**图实例对象 */
export const graphG6 = ref<any>(null);
@@ -38,20 +26,32 @@ export const selectSourceTargetOptions = ref<Record<string, any>[]>([]);
/**图元素选择嵌入分组 */
export const selectComboOptions = ref<Record<string, any>[]>([]);
/**图模式选择项 */
export const graphMode = ref<'default' | 'edit'>('default');
export default function useGraph() {
//实例化i18n
const { t } = useI18n();
/**图模式选择项 */
const graphMode = ref<'default' | 'edit'>('default');
/**图模式选择项 */
const graphModeOptions = [
{
value: 'default',
label: t('views.monitor.topologyBuild.graphModeDefault'),
},
{
value: 'edit',
label: t('views.monitor.topologyBuild.graphModeEdit'),
},
];
/**图画布右击菜单 */
const graphCanvasMenu = new Menu({
offsetX: 6,
offseY: 10,
itemTypes: ['canvas'],
getContent(evt) {
if (!evt) return '无';
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
const edit = graphMode.value === 'edit';
return `
<div
@@ -61,24 +61,24 @@ export default function useGraph() {
width: 140px;
"
>
<h3>画布</h3>
<h3>${t('views.monitor.topologyBuild.graphCanvas')}</h3>
<div id="show" style="cursor: pointer; margin-bottom: 2px">
显示所有隐藏项
${t('views.monitor.topologyBuild.graphMenuHideAllShow')}
</div>
<div id="create-edge" style="cursor: pointer; margin-bottom: 2px; display: ${
edit ? 'black' : 'none'
}">
新增边
${t('views.monitor.topologyBuild.graphMenuAddEdge')}
</div>
<div id="create-node" style="cursor: pointer; margin-bottom: 2px; display: ${
edit ? 'black' : 'none'
}">
新增节点
${t('views.monitor.topologyBuild.graphMenuAddNode')}
</div>
<div id="create-combo" style="cursor: pointer; margin-bottom: 2px; display: ${
edit ? 'black' : 'none'
}">
新增分组
${t('views.monitor.topologyBuild.graphMenuAddCombo')}
</div>
</div>`;
},
@@ -124,7 +124,7 @@ export default function useGraph() {
offseY: 10,
itemTypes: ['combo'],
getContent(evt) {
if (!evt) return '无';
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
const item = evt.item?.getModel();
const edit = graphMode.value === 'edit';
return `
@@ -135,26 +135,28 @@ export default function useGraph() {
width: 140px;
"
>
<h3 style="margin-bottom: 8px">分组:${item?.label || item?.id}</h3>
<h3 style="margin-bottom: 8px">
${t('views.monitor.topologyBuild.graphCombo')}:
${item?.label || item?.id}
</h3>
<div id="hide" style="cursor: pointer; margin-bottom: 2px">
隐藏
${t('views.monitor.topologyBuild.graphMenuHide')}
</div>
<div id="edit" style="cursor: pointer; margin-bottom: 2px;display: ${
edit ? 'black' : 'none'
}">
编辑
${t('views.monitor.topologyBuild.graphMenuEdit')}
</div>
<div id="delete" style="cursor: pointer; margin-bottom: 2px; display: ${
edit ? 'black' : 'none'
}">
删除
${t('views.monitor.topologyBuild.graphMenuDel')}
</div>
</div>
`;
},
handleMenuClick(target, item) {
console.log(target, item);
const targetId = target.id;
switch (targetId) {
case 'edit':
@@ -177,7 +179,7 @@ export default function useGraph() {
offseY: 10,
itemTypes: ['node'],
getContent(evt) {
if (!evt) return '无';
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
const item = evt.item?.getModel();
const edit = graphMode.value === 'edit';
return `
@@ -188,19 +190,22 @@ export default function useGraph() {
width: 140px;
"
>
<h3 style="margin-bottom: 8px">节点:${item?.label || item?.id}</h3>
<h3 style="margin-bottom: 8px">
${t('views.monitor.topologyBuild.graphNode')}:
${item?.label || item?.id}
</h3>
<div id="hide" style="cursor: pointer; margin-bottom: 4px">
隐藏
${t('views.monitor.topologyBuild.graphMenuHide')}
</div>
<div id="edit" style="cursor: pointer; margin-bottom: 4px; display: ${
edit ? 'black' : 'none'
}">
编辑
${t('views.monitor.topologyBuild.graphMenuEdit')}
</div>
<div id="delete" style="cursor: pointer; margin-bottom: 4px; display: ${
edit ? 'black' : 'none'
}">
删除
${t('views.monitor.topologyBuild.graphMenuDel')}
</div>
</div>
@@ -228,7 +233,7 @@ export default function useGraph() {
offsetX: 10,
offsetY: 20,
getContent(evt) {
if (!evt) return '无';
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
const item = evt.item?.getModel();
return `
<div
@@ -238,7 +243,10 @@ export default function useGraph() {
width: 140px;
"
>
<h3>节点:${item?.label || item?.id}</h3>
<h3>
${t('views.monitor.topologyBuild.graphNode')}:
${item?.label || item?.id}
</h3>
</div>
`;
},
@@ -251,7 +259,7 @@ export default function useGraph() {
offseY: 10,
itemTypes: ['edge'],
getContent(evt) {
if (!evt) return '无';
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
const item = evt.item?.getModel();
const edit = graphMode.value === 'edit';
return `
@@ -262,19 +270,22 @@ export default function useGraph() {
width: 140px;
"
>
<h3 style="margin-bottom: 8px">边:${item?.label || '无标签'}</h3>
<h3 style="margin-bottom: 8px">
${t('views.monitor.topologyBuild.graphEdge')}
${item?.label && `:${item?.label}`}
</h3>
<div id="hide" style="cursor: pointer; margin-bottom: 4px">
隐藏
${t('views.monitor.topologyBuild.graphMenuHide')}
</div>
<div id="edit" style="cursor: pointer; margin-bottom: 4px; display: ${
edit ? 'black' : 'none'
}">
编辑
${t('views.monitor.topologyBuild.graphMenuEdit')}
</div>
<div id="delete" style="cursor: pointer; margin-bottom: 4px; display: ${
edit ? 'black' : 'none'
}">
删除
${t('views.monitor.topologyBuild.graphMenuDel')}
</div>
</div>
`;
@@ -301,7 +312,7 @@ export default function useGraph() {
offsetX: 10,
offsetY: 20,
getContent(evt) {
if (!evt) return '无';
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
const item = evt.item?.getModel();
return `
<div
@@ -311,7 +322,10 @@ export default function useGraph() {
width: 140px;
"
>
<h3>边: ${item?.label || '无标签'}</h3>
<h3>
${t('views.monitor.topologyBuild.graphEdge')}
${item?.label && `:${item?.label}`}
</h3>
</div>
`;
},
@@ -568,6 +582,8 @@ export default function useGraph() {
}
return {
graphMode,
graphModeOptions,
handleRanderGraph,
handleChangeMode,
};

View File

@@ -3,92 +3,122 @@ import { reactive, watch } from 'vue';
import { graphG6 } from './useGraph';
import useI18n from '@/hooks/useI18n';
/**图节点内置边类型 */
export const nodeTypeOptions = [
{
value: 'circle',
label: '圆形',
},
{
value: 'rect',
label: '矩形',
},
{
value: 'ellipse',
label: '椭圆',
},
{
value: 'diamond',
label: '菱形',
},
{
value: 'triangle',
label: '三角形',
},
{
value: 'star',
label: '星形',
},
{
value: 'image',
label: '图片',
},
// {
// value: 'donut',
// label: '面包圈',
// },
];
/**图节点标签文本位置 */
export const nodePositionOptions = [
{
value: 'top',
label: '上',
},
{
value: 'left',
label: '左',
},
{
value: 'right',
label: '右',
},
{
value: 'bottom',
label: '下',
},
{
value: 'center',
label: '居中',
},
];
/**图节点三角形方向 */
export const nodeDirectionOptions = [
{ value: 'up', label: '向上' },
{ value: 'down', label: '向下' },
{ value: 'left', label: '向左' },
{ value: 'right', label: '向右' },
];
/**图节点图片裁剪的形状 */
export const nodeImageClipCfgOptions = [
{ value: 'circle', label: '圆形' },
{ value: 'rect', label: '矩形' },
{ value: 'ellipse', label: '椭圆' },
];
/**图节点图片来源 */
export const nodeImageOptions = [
{ value: '/svg/base.svg', label: '基站' },
{ value: '/svg/cloud.svg', label: '云' },
{ value: '/svg/service.svg', label: '服务器' },
{ value: '/svg/service_db.svg', label: '数据服务器' },
];
export default function useNode() {
const { t } = useI18n();
/**图节点内置边类型 */
const nodeTypeOptions = [
{
value: 'circle',
label: t('views.monitor.topologyBuild.nodeTypeCircle'),
},
{
value: 'rect',
label: t('views.monitor.topologyBuild.nodeTypeRect'),
},
{
value: 'ellipse',
label: t('views.monitor.topologyBuild.nodeTypeEllipse'),
},
{
value: 'diamond',
label: t('views.monitor.topologyBuild.nodeTypeDiamond'),
},
{
value: 'triangle',
label: t('views.monitor.topologyBuild.nodeTypeTriangle'),
},
{
value: 'star',
label: t('views.monitor.topologyBuild.nodeTypeStar'),
},
{
value: 'image',
label: t('views.monitor.topologyBuild.nodeTypeImage'),
},
// {
// value: 'donut',
// label: '面包圈',
// },
];
/**图节点标签文本位置 */
const nodeLabelPositionOptions = [
{
value: 'top',
label: t('views.monitor.topologyBuild.nodeLabelPositionTop'),
},
{
value: 'left',
label: t('views.monitor.topologyBuild.nodeLabelPositionLeft'),
},
{
value: 'right',
label: t('views.monitor.topologyBuild.nodeLabelPositionRight'),
},
{
value: 'bottom',
label: t('views.monitor.topologyBuild.nodeLabelPositionBottom'),
},
{
value: 'center',
label: t('views.monitor.topologyBuild.nodeLabelPositionCenter'),
},
];
/**图节点三角形方向 */
const nodeDirectionOptions = [
{ value: 'up', label: t('views.monitor.topologyBuild.nodeDirectionUp') },
{
value: 'down',
label: t('views.monitor.topologyBuild.nodeDirectionDown'),
},
{
value: 'left',
label: t('views.monitor.topologyBuild.nodeDirectionLeft'),
},
{
value: 'right',
label: t('views.monitor.topologyBuild.nodeDirectionRight'),
},
];
/**图节点图片裁剪的形状 */
const nodeImageClipCfgOptions = [
{
value: 'circle',
label: t('views.monitor.topologyBuild.nodeImageClipCircle'),
},
{
value: 'rect',
label: t('views.monitor.topologyBuild.nodeImageClipRect'),
},
{
value: 'ellipse',
label: t('views.monitor.topologyBuild.nodeImageClipEllipse'),
},
];
/**图节点图片来源 */
const nodeImageOptions = [
{
value: '/svg/base.svg',
label: t('views.monitor.topologyBuild.nodeImageBase'),
},
{
value: '/svg/cloud.svg',
label: t('views.monitor.topologyBuild.nodeImageCloud'),
},
{
value: '/svg/service.svg',
label: t('views.monitor.topologyBuild.nodeImageService'),
},
{
value: '/svg/service_db.svg',
label: t('views.monitor.topologyBuild.nodeImageServiceDB'),
},
];
/**图节点信息状态类型 */
type NodeStateType = {
/**图节点原始数据 */
@@ -130,7 +160,12 @@ export default function useNode() {
const nodeStateForm = Form.useForm(
nodeState.form,
reactive({
id: [{ required: true, message: '节点唯一 ID' }],
id: [
{
required: true,
message: t('views.monitor.topologyBuild.nodeFormIdPlease'),
},
],
type: [{ required: true, message: 'line' }],
})
);
@@ -257,8 +292,8 @@ export default function useNode() {
const node = JSON.parse(JSON.stringify(nodeState.form));
if (!node.id) {
message.warn({
content: `节点元素ID错误`,
duration: 2,
content: t('views.monitor.topologyBuild.nodeFormIdNot'),
duration: 3,
});
return false;
}
@@ -314,6 +349,11 @@ export default function useNode() {
}
return {
nodeTypeOptions,
nodeLabelPositionOptions,
nodeDirectionOptions,
nodeImageClipCfgOptions,
nodeImageOptions,
nodeState,
nodeStateForm,
handleNodeTypeChange,

View File

@@ -3,11 +3,7 @@ import { reactive, onMounted, ref, toRaw } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import useI18n from '@/hooks/useI18n';
import GraphEditModal from './components/GraphEditModal.vue';
import useGraph, {
graphG6,
graphMode,
graphModeOptions,
} from './/hooks/useGraph';
import useGraph, { graphG6 } from './/hooks/useGraph';
import {
delGraphData,
getGraphData,
@@ -17,7 +13,8 @@ import {
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { Form, Modal, message } from 'ant-design-vue/lib';
const { t } = useI18n();
const { handleRanderGraph, handleChangeMode } = useGraph();
const { graphMode, graphModeOptions, handleRanderGraph, handleChangeMode } =
useGraph();
/**图DOM节点实例对象 */
const graphG6Dom = ref<HTMLElement | undefined>(undefined);
@@ -67,7 +64,7 @@ function fnGraphDataGroups(reload: boolean = false) {
if (!graphState.group) {
handleRanderGraph(graphG6Dom.value, graphState.data);
message.warning({
content: '暂无图组数据,可使用【图模式-编辑】进行新增图组',
content: t('views.monitor.topologyBuild.noData'),
duration: 5,
});
}
@@ -127,7 +124,7 @@ const modalStateFrom = Form.useForm(
group: [
{
required: true,
message: '图组不能为空',
message: t('views.monitor.topologyBuild.groupPlease'),
},
],
})
@@ -149,14 +146,18 @@ function fnModalOk() {
.then((res: any) => {
if (res.code === RESULT_CODE_SUCCESS) {
message.success({
content: `保存图组【${from.group}】成功`,
content: t('views.monitor.topologyBuild.saveOk', {
group: from.group,
}),
duration: 3,
});
fnGraphDataGroups(true);
graphState.group = from.group;
} else {
message.error({
content: `保存图组【${from.group}】失败`,
content: t('views.monitor.topologyBuild.saveFail', {
group: from.group,
}),
duration: 3,
});
}
@@ -186,8 +187,8 @@ function fnModalCancel() {
function fnGraphDataSave() {
modalState.form.group = graphState.group;
modalState.type = 'save';
modalState.title = '图组信息保存';
modalState.visible = true;
(modalState.title = t('views.monitor.topologyBuild.saveTtite')),
(modalState.visible = true);
}
/**图组数据删除 */
@@ -195,13 +196,15 @@ function fnGraphDataDelete() {
if (!graphState.group) {
handleRanderGraph(graphG6Dom.value, graphState.data);
message.warning({
content: '暂无图组数据,可使用【图模式-编辑】进行新增图组',
content: t('views.monitor.topologyBuild.noData'),
duration: 5,
});
}
Modal.confirm({
title: t('common.tipTitle'),
content: `确认要删除图组名为【${graphState.group}】的数据吗?`,
content: t('views.monitor.topologyBuild.delTip', {
group: graphState.group,
}),
onOk() {
const hide = message.loading({ content: t('common.loading') });
delGraphData(graphState.group)
@@ -248,7 +251,10 @@ onMounted(() => {
<a-form :model="graphState" name="graphState" layout="horizontal">
<a-row :gutter="16">
<a-col :lg="4" :md="12" :xs="24">
<a-form-item label="图模式" name="graphMode">
<a-form-item
:label="t('views.monitor.topologyBuild.graphMode')"
name="graphMode"
>
<a-select
:value="graphMode"
:options="graphModeOptions"
@@ -258,7 +264,10 @@ onMounted(() => {
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item label="图组" name="group ">
<a-form-item
:label="t('views.monitor.topologyBuild.graphGroup')"
name="group "
>
<a-select
v-model:value="graphState.group"
:options="graphState.groupOptions"
@@ -275,7 +284,10 @@ onMounted(() => {
<!-- 插槽-卡片左侧侧 -->
<template #title>
<div class="button-container" style="margin-bottom: -12px">
<span>图组名{{ graphState.group }}</span>
<span>
{{ t('views.monitor.topologyBuild.graphGroup') }}
{{ graphState.group }}
</span>
</div>
</template>
@@ -287,7 +299,7 @@ onMounted(() => {
<template #icon>
<SaveOutlined />
</template>
保存
{{ t('views.monitor.topologyBuild.graphSave') }}
</a-button>
<a-button
@@ -299,7 +311,7 @@ onMounted(() => {
<template #icon>
<DeleteOutlined />
</template>
删除
{{ t('views.monitor.topologyBuild.graphDelete') }}
</a-button>
</template>
</div>
@@ -331,16 +343,16 @@ onMounted(() => {
<a-row :gutter="16">
<a-col :lg="24" :md="24" :xs="24">
<a-form-item
label="图组名"
:label="t('views.monitor.topologyBuild.graphGroup')"
name="group"
v-bind="modalStateFrom.validateInfos.group"
help="已存在图组名会更新图数据,不存在则新增图组"
:help="t('views.monitor.topologyBuild.graphGroupTip')"
>
<a-auto-complete
v-model:value="modalState.form.group"
:options="graphState.groupOptions"
allow-clear
placeholder="图组名"
:placeholder="t('views.monitor.topologyBuild.graphGroup')"
/>
</a-form-item>
</a-col>
@@ -353,7 +365,7 @@ onMounted(() => {
<style lang="less" scoped>
.chart {
width: 100%;
height: calc(100vh - 300px);
height: calc(100vh - 380px);
background-color: rgb(43, 47, 51);
}
</style>