mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 15:30:25 +08:00
refactor: 数据同步编辑页调整、echarts组件重构
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
"countup.js": "^2.7.0",
|
||||
"cropperjs": "^1.5.11",
|
||||
"echarts": "^5.4.3",
|
||||
"element-plus": "^2.4.4",
|
||||
"element-plus": "^2.5.0",
|
||||
"js-base64": "^3.7.5",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -33,7 +33,7 @@
|
||||
"splitpanes": "^3.1.5",
|
||||
"sql-formatter": "^14.0.0",
|
||||
"uuid": "^9.0.1",
|
||||
"vue": "^3.4.6",
|
||||
"vue": "^3.4.7",
|
||||
"vue-router": "^4.2.5",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0",
|
||||
@@ -48,7 +48,7 @@
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
||||
"@typescript-eslint/parser": "^6.7.4",
|
||||
"@vitejs/plugin-vue": "^5.0.2",
|
||||
"@vue/compiler-sfc": "^3.4.6",
|
||||
"@vue/compiler-sfc": "^3.4.7",
|
||||
"dotenv": "^16.3.1",
|
||||
"eslint": "^8.35.0",
|
||||
"eslint-plugin-vue": "^9.19.2",
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
{
|
||||
"seriesCnt": "4",
|
||||
"backgroundColor": "rgba(0,0,0,0)",
|
||||
"titleColor": "#008acd",
|
||||
"subtitleColor": "#aaaaaa",
|
||||
"textColorShow": false,
|
||||
"textColor": "#333",
|
||||
"markTextColor": "#eeeeee",
|
||||
"color": [
|
||||
"#2ec7c9",
|
||||
"#b6a2de",
|
||||
"#5ab1ef",
|
||||
"#ffb980",
|
||||
"#d87a80",
|
||||
"#8d98b3",
|
||||
"#e5cf0d",
|
||||
"#97b552",
|
||||
"#95706d",
|
||||
"#dc69aa",
|
||||
"#07a2a4",
|
||||
"#9a7fd1",
|
||||
"#588dd5",
|
||||
"#f5994e",
|
||||
"#c05050",
|
||||
"#59678c",
|
||||
"#c9ab00",
|
||||
"#7eb00a",
|
||||
"#6f5553",
|
||||
"#c14089"
|
||||
],
|
||||
"borderColor": "#ccc",
|
||||
"borderWidth": 0,
|
||||
"visualMapColor": [
|
||||
"#5ab1ef",
|
||||
"#e0ffff"
|
||||
],
|
||||
"legendTextColor": "#333333",
|
||||
"kColor": "#d87a80",
|
||||
"kColor0": "#2ec7c9",
|
||||
"kBorderColor": "#d87a80",
|
||||
"kBorderColor0": "#2ec7c9",
|
||||
"kBorderWidth": 1,
|
||||
"lineWidth": 2,
|
||||
"symbolSize": 3,
|
||||
"symbol": "emptyCircle",
|
||||
"symbolBorderWidth": 1,
|
||||
"lineSmooth": true,
|
||||
"graphLineWidth": 1,
|
||||
"graphLineColor": "#aaaaaa",
|
||||
"mapLabelColor": "#d87a80",
|
||||
"mapLabelColorE": "rgb(100,0,0)",
|
||||
"mapBorderColor": "#eeeeee",
|
||||
"mapBorderColorE": "#444",
|
||||
"mapBorderWidth": 0.5,
|
||||
"mapBorderWidthE": 1,
|
||||
"mapAreaColor": "#dddddd",
|
||||
"mapAreaColorE": "rgba(254,153,78,1)",
|
||||
"axes": [
|
||||
{
|
||||
"type": "all",
|
||||
"name": "通用坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#eeeeee",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#eeeeee",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#eeeeee",
|
||||
"splitLineShow": true,
|
||||
"splitLineColor": [
|
||||
"#aaaaaa"
|
||||
],
|
||||
"splitAreaShow": false,
|
||||
"splitAreaColor": [
|
||||
"#eeeeee"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "category",
|
||||
"name": "类目坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#008acd",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#333",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#333",
|
||||
"splitLineShow": false,
|
||||
"splitLineColor": [
|
||||
"#eee"
|
||||
],
|
||||
"splitAreaShow": false,
|
||||
"splitAreaColor": [
|
||||
"rgba(250,250,250,0.3)",
|
||||
"rgba(200,200,200,0.3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "value",
|
||||
"name": "数值坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#008acd",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#333",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#333",
|
||||
"splitLineShow": true,
|
||||
"splitLineColor": [
|
||||
"#eee"
|
||||
],
|
||||
"splitAreaShow": true,
|
||||
"splitAreaColor": [
|
||||
"rgba(250,250,250,0.3)",
|
||||
"rgba(200,200,200,0.3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "log",
|
||||
"name": "对数坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#008acd",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#333",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#333",
|
||||
"splitLineShow": true,
|
||||
"splitLineColor": [
|
||||
"#eee"
|
||||
],
|
||||
"splitAreaShow": true,
|
||||
"splitAreaColor": [
|
||||
"rgba(250,250,250,0.3)",
|
||||
"rgba(200,200,200,0.3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "time",
|
||||
"name": "时间坐标轴",
|
||||
"axisLineShow": true,
|
||||
"axisLineColor": "#008acd",
|
||||
"axisTickShow": true,
|
||||
"axisTickColor": "#333",
|
||||
"axisLabelShow": true,
|
||||
"axisLabelColor": "#333",
|
||||
"splitLineShow": true,
|
||||
"splitLineColor": [
|
||||
"#eee"
|
||||
],
|
||||
"splitAreaShow": false,
|
||||
"splitAreaColor": [
|
||||
"rgba(250,250,250,0.3)",
|
||||
"rgba(200,200,200,0.3)"
|
||||
]
|
||||
}
|
||||
],
|
||||
"axisSeperateSetting": true,
|
||||
"toolboxColor": "#2ec7c9",
|
||||
"toolboxEmphasisColor": "#18a4a6",
|
||||
"tooltipAxisColor": "#008acd",
|
||||
"tooltipAxisWidth": "1",
|
||||
"timelineLineColor": "#008acd",
|
||||
"timelineLineWidth": 1,
|
||||
"timelineItemColor": "#008acd",
|
||||
"timelineItemColorE": "#a9334c",
|
||||
"timelineCheckColor": "#2ec7c9",
|
||||
"timelineCheckBorderColor": "#2ec7c9",
|
||||
"timelineItemBorderWidth": 1,
|
||||
"timelineControlColor": "#008acd",
|
||||
"timelineControlBorderColor": "#008acd",
|
||||
"timelineControlBorderWidth": 0.5,
|
||||
"timelineLabelColor": "#008acd",
|
||||
"datazoomBackgroundColor": "rgba(47,69,84,0)",
|
||||
"datazoomDataColor": "#efefff",
|
||||
"datazoomFillColor": "rgba(182,162,222,0.2)",
|
||||
"datazoomHandleColor": "#008acd",
|
||||
"datazoomHandleWidth": "100",
|
||||
"datazoomLabelColor": "#333333"
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// import * as echarts from 'echarts'
|
||||
|
||||
// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
|
||||
import * as echarts from 'echarts/core';
|
||||
|
||||
/** 图表后缀都为 Chart */
|
||||
import { PieChart } from 'echarts/charts';
|
||||
|
||||
// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
|
||||
import { TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, LegendComponent } from 'echarts/components';
|
||||
|
||||
// 标签自动布局,全局过渡动画等特性
|
||||
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||
|
||||
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
|
||||
// 注册必须的组件
|
||||
echarts.use([
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
DatasetComponent,
|
||||
TransformComponent,
|
||||
LegendComponent,
|
||||
// BarChart,
|
||||
LabelLayout,
|
||||
UniversalTransition,
|
||||
CanvasRenderer,
|
||||
// LineChart,
|
||||
PieChart,
|
||||
]);
|
||||
|
||||
export default function (dom: any, theme: any = null, option: any) {
|
||||
let chart = echarts.init(dom, theme);
|
||||
chart.setOption(option);
|
||||
return chart;
|
||||
}
|
||||
86
mayfly_go_web/src/components/echarts/ECharts.vue
Normal file
86
mayfly_go_web/src/components/echarts/ECharts.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div id="echarts" ref="chartRef" :style="echartsStyle" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ECharts">
|
||||
import { ref, onMounted, onBeforeUnmount, watch, computed, markRaw, nextTick } from 'vue';
|
||||
import { EChartsType, ECElementEvent } from 'echarts/core';
|
||||
import echarts, { ECOption } from './config';
|
||||
import { useDebounceFn, useEventListener } from '@vueuse/core';
|
||||
import { light } from './config/theme';
|
||||
// import { useThemeConfig } from '@/store/themeConfig';
|
||||
// import { storeToRefs } from 'pinia';
|
||||
|
||||
interface Props {
|
||||
option: ECOption;
|
||||
renderer?: 'canvas' | 'svg';
|
||||
resize?: boolean;
|
||||
theme?: Object | string;
|
||||
width?: number | string;
|
||||
height?: number | string;
|
||||
onClick?: (event: ECElementEvent) => any;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
renderer: 'canvas',
|
||||
theme: light as any,
|
||||
resize: true,
|
||||
});
|
||||
|
||||
const echartsStyle = computed(() => {
|
||||
return props.width || props.height ? { height: props.height + 'px', width: props.width + 'px' } : { height: '100%', width: '100%' };
|
||||
});
|
||||
|
||||
const chartRef = ref<HTMLDivElement | HTMLCanvasElement>();
|
||||
const chartInstance = ref<EChartsType>();
|
||||
|
||||
const draw = () => {
|
||||
if (chartInstance.value) {
|
||||
chartInstance.value.setOption(props.option, { notMerge: true });
|
||||
}
|
||||
};
|
||||
|
||||
watch(props, () => {
|
||||
draw();
|
||||
});
|
||||
|
||||
const handleClick = (event: ECElementEvent) => props.onClick && props.onClick(event);
|
||||
|
||||
const init = () => {
|
||||
if (!chartRef.value) return;
|
||||
chartInstance.value = echarts.getInstanceByDom(chartRef.value);
|
||||
|
||||
if (!chartInstance.value) {
|
||||
chartInstance.value = markRaw(
|
||||
echarts.init(chartRef.value, props.theme, {
|
||||
renderer: props.renderer,
|
||||
})
|
||||
);
|
||||
chartInstance.value.on('click', handleClick);
|
||||
draw();
|
||||
}
|
||||
};
|
||||
|
||||
const resize = () => {
|
||||
if (chartInstance.value && props.resize) {
|
||||
chartInstance.value.resize({ animation: { duration: 300 } });
|
||||
}
|
||||
};
|
||||
|
||||
const debouncedResize = useDebounceFn(resize, 300, { maxWait: 800 });
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => init());
|
||||
useEventListener('resize', debouncedResize);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
chartInstance.value?.dispose();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
getInstance: () => chartInstance.value,
|
||||
resize,
|
||||
draw,
|
||||
});
|
||||
</script>
|
||||
67
mayfly_go_web/src/components/echarts/config/index.ts
Normal file
67
mayfly_go_web/src/components/echarts/config/index.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import * as echarts from 'echarts/core';
|
||||
import { BarChart, LineChart, LinesChart, PieChart, ScatterChart, RadarChart, GaugeChart } from 'echarts/charts';
|
||||
import {
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
DatasetComponent,
|
||||
TransformComponent,
|
||||
LegendComponent,
|
||||
PolarComponent,
|
||||
GeoComponent,
|
||||
ToolboxComponent,
|
||||
DataZoomComponent,
|
||||
} from 'echarts/components';
|
||||
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||
import { CanvasRenderer } from 'echarts/renderers';
|
||||
import type {
|
||||
BarSeriesOption,
|
||||
LineSeriesOption,
|
||||
LinesSeriesOption,
|
||||
PieSeriesOption,
|
||||
ScatterSeriesOption,
|
||||
RadarSeriesOption,
|
||||
GaugeSeriesOption,
|
||||
} from 'echarts/charts';
|
||||
import type { TitleComponentOption, TooltipComponentOption, GridComponentOption, DatasetComponentOption } from 'echarts/components';
|
||||
import type { ComposeOption } from 'echarts/core';
|
||||
// import 'echarts-liquidfill';
|
||||
|
||||
export type ECOption = ComposeOption<
|
||||
| BarSeriesOption
|
||||
| LineSeriesOption
|
||||
| LinesSeriesOption
|
||||
| PieSeriesOption
|
||||
| RadarSeriesOption
|
||||
| GaugeSeriesOption
|
||||
| TitleComponentOption
|
||||
| TooltipComponentOption
|
||||
| GridComponentOption
|
||||
| DatasetComponentOption
|
||||
| ScatterSeriesOption
|
||||
>;
|
||||
|
||||
echarts.use([
|
||||
TitleComponent,
|
||||
TooltipComponent,
|
||||
GridComponent,
|
||||
DatasetComponent,
|
||||
TransformComponent,
|
||||
LegendComponent,
|
||||
PolarComponent,
|
||||
GeoComponent,
|
||||
ToolboxComponent,
|
||||
DataZoomComponent,
|
||||
BarChart,
|
||||
LineChart,
|
||||
LinesChart,
|
||||
PieChart,
|
||||
ScatterChart,
|
||||
RadarChart,
|
||||
GaugeChart,
|
||||
LabelLayout,
|
||||
UniversalTransition,
|
||||
CanvasRenderer,
|
||||
]);
|
||||
|
||||
export default echarts;
|
||||
151
mayfly_go_web/src/components/echarts/config/theme.js
Normal file
151
mayfly_go_web/src/components/echarts/config/theme.js
Normal file
@@ -0,0 +1,151 @@
|
||||
const light = {
|
||||
seriesCnt: '4',
|
||||
backgroundColor: 'rgba(0,0,0,0)',
|
||||
titleColor: '#008acd',
|
||||
subtitleColor: '#aaaaaa',
|
||||
textColorShow: false,
|
||||
textColor: '#333',
|
||||
markTextColor: '#eeeeee',
|
||||
color: [
|
||||
'#2ec7c9',
|
||||
'#b6a2de',
|
||||
'#5ab1ef',
|
||||
'#ffb980',
|
||||
'#d87a80',
|
||||
'#8d98b3',
|
||||
'#e5cf0d',
|
||||
'#97b552',
|
||||
'#95706d',
|
||||
'#dc69aa',
|
||||
'#07a2a4',
|
||||
'#9a7fd1',
|
||||
'#588dd5',
|
||||
'#f5994e',
|
||||
'#c05050',
|
||||
'#59678c',
|
||||
'#c9ab00',
|
||||
'#7eb00a',
|
||||
'#6f5553',
|
||||
'#c14089',
|
||||
],
|
||||
borderColor: '#ccc',
|
||||
borderWidth: 0,
|
||||
visualMapColor: ['#5ab1ef', '#e0ffff'],
|
||||
legendTextColor: '#333333',
|
||||
kColor: '#d87a80',
|
||||
kColor0: '#2ec7c9',
|
||||
kBorderColor: '#d87a80',
|
||||
kBorderColor0: '#2ec7c9',
|
||||
kBorderWidth: 1,
|
||||
lineWidth: 2,
|
||||
symbolSize: 3,
|
||||
symbol: 'emptyCircle',
|
||||
symbolBorderWidth: 1,
|
||||
lineSmooth: true,
|
||||
graphLineWidth: 1,
|
||||
graphLineColor: '#aaaaaa',
|
||||
mapLabelColor: '#d87a80',
|
||||
mapLabelColorE: 'rgb(100,0,0)',
|
||||
mapBorderColor: '#eeeeee',
|
||||
mapBorderColorE: '#444',
|
||||
mapBorderWidth: 0.5,
|
||||
mapBorderWidthE: 1,
|
||||
mapAreaColor: '#dddddd',
|
||||
mapAreaColorE: 'rgba(254,153,78,1)',
|
||||
axes: [
|
||||
{
|
||||
type: 'all',
|
||||
name: '通用坐标轴',
|
||||
axisLineShow: true,
|
||||
axisLineColor: '#eeeeee',
|
||||
axisTickShow: true,
|
||||
axisTickColor: '#eeeeee',
|
||||
axisLabelShow: true,
|
||||
axisLabelColor: '#eeeeee',
|
||||
splitLineShow: true,
|
||||
splitLineColor: ['#aaaaaa'],
|
||||
splitAreaShow: false,
|
||||
splitAreaColor: ['#eeeeee'],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
name: '类目坐标轴',
|
||||
axisLineShow: true,
|
||||
axisLineColor: '#008acd',
|
||||
axisTickShow: true,
|
||||
axisTickColor: '#333',
|
||||
axisLabelShow: true,
|
||||
axisLabelColor: '#333',
|
||||
splitLineShow: false,
|
||||
splitLineColor: ['#eee'],
|
||||
splitAreaShow: false,
|
||||
splitAreaColor: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'],
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: '数值坐标轴',
|
||||
axisLineShow: true,
|
||||
axisLineColor: '#008acd',
|
||||
axisTickShow: true,
|
||||
axisTickColor: '#333',
|
||||
axisLabelShow: true,
|
||||
axisLabelColor: '#333',
|
||||
splitLineShow: true,
|
||||
splitLineColor: ['#eee'],
|
||||
splitAreaShow: true,
|
||||
splitAreaColor: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'],
|
||||
},
|
||||
{
|
||||
type: 'log',
|
||||
name: '对数坐标轴',
|
||||
axisLineShow: true,
|
||||
axisLineColor: '#008acd',
|
||||
axisTickShow: true,
|
||||
axisTickColor: '#333',
|
||||
axisLabelShow: true,
|
||||
axisLabelColor: '#333',
|
||||
splitLineShow: true,
|
||||
splitLineColor: ['#eee'],
|
||||
splitAreaShow: true,
|
||||
splitAreaColor: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'],
|
||||
},
|
||||
{
|
||||
type: 'time',
|
||||
name: '时间坐标轴',
|
||||
axisLineShow: true,
|
||||
axisLineColor: '#008acd',
|
||||
axisTickShow: true,
|
||||
axisTickColor: '#333',
|
||||
axisLabelShow: true,
|
||||
axisLabelColor: '#333',
|
||||
splitLineShow: true,
|
||||
splitLineColor: ['#eee'],
|
||||
splitAreaShow: false,
|
||||
splitAreaColor: ['rgba(250,250,250,0.3)', 'rgba(200,200,200,0.3)'],
|
||||
},
|
||||
],
|
||||
axisSeperateSetting: true,
|
||||
toolboxColor: '#2ec7c9',
|
||||
toolboxEmphasisColor: '#18a4a6',
|
||||
tooltipAxisColor: '#008acd',
|
||||
tooltipAxisWidth: '1',
|
||||
timelineLineColor: '#008acd',
|
||||
timelineLineWidth: 1,
|
||||
timelineItemColor: '#008acd',
|
||||
timelineItemColorE: '#a9334c',
|
||||
timelineCheckColor: '#2ec7c9',
|
||||
timelineCheckBorderColor: '#2ec7c9',
|
||||
timelineItemBorderWidth: 1,
|
||||
timelineControlColor: '#008acd',
|
||||
timelineControlBorderColor: '#008acd',
|
||||
timelineControlBorderWidth: 0.5,
|
||||
timelineLabelColor: '#008acd',
|
||||
datazoomBackgroundColor: 'rgba(47,69,84,0)',
|
||||
datazoomDataColor: '#efefff',
|
||||
datazoomFillColor: 'rgba(182,162,222,0.2)',
|
||||
datazoomHandleColor: '#008acd',
|
||||
datazoomHandleWidth: '100',
|
||||
datazoomLabelColor: '#333333',
|
||||
};
|
||||
|
||||
export { light };
|
||||
135
mayfly_go_web/src/views/ops/component/TagTreeResourceSelect.vue
Normal file
135
mayfly_go_web/src/views/ops/component/TagTreeResourceSelect.vue
Normal file
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<el-tree-select
|
||||
v-bind="$attrs"
|
||||
ref="treeRef"
|
||||
:highlight-current="true"
|
||||
:indent="10"
|
||||
:load="loadNode"
|
||||
:props="treeProps"
|
||||
lazy
|
||||
node-key="key"
|
||||
:expand-on-click-node="true"
|
||||
filterable
|
||||
:filter-node-method="filterNode"
|
||||
v-model="modelValue"
|
||||
@change="changeNode"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span>
|
||||
<span v-if="data.type.value == TagTreeNode.TagPath">
|
||||
<tag-info :tag-path="data.label" />
|
||||
</span>
|
||||
|
||||
<slot v-else :node="node" :data="data" name="prefix"></slot>
|
||||
|
||||
<span class="ml3" :title="data.labelRemark">
|
||||
<slot name="label" :data="data"> {{ data.label }}</slot>
|
||||
</span>
|
||||
|
||||
<slot :node="node" :data="data" name="suffix"></slot>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, reactive, ref, watch, toRefs } from 'vue';
|
||||
import { NodeType, TagTreeNode } from './tag';
|
||||
import TagInfo from './TagInfo.vue';
|
||||
import { tagApi } from '../tag/api';
|
||||
|
||||
const props = defineProps({
|
||||
resourceType: {
|
||||
type: [Number],
|
||||
required: true,
|
||||
},
|
||||
tagPathNodeType: {
|
||||
type: [NodeType],
|
||||
required: true,
|
||||
},
|
||||
load: {
|
||||
type: Function,
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
|
||||
const treeProps = {
|
||||
label: 'name',
|
||||
children: 'zones',
|
||||
isLeaf: 'isLeaf',
|
||||
};
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
const treeRef: any = ref(null);
|
||||
|
||||
const modelValue = defineModel('modelValue');
|
||||
|
||||
const state = reactive({
|
||||
height: 600 as any,
|
||||
filterText: '',
|
||||
opend: {},
|
||||
});
|
||||
const { filterText } = toRefs(state);
|
||||
|
||||
onMounted(async () => {});
|
||||
|
||||
watch(filterText, (val) => {
|
||||
treeRef.value?.filter(val);
|
||||
});
|
||||
|
||||
const filterNode = (value: string, data: any) => {
|
||||
if (!value) return true;
|
||||
return data.label.includes(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* 加载标签树节点
|
||||
*/
|
||||
const loadTags = async () => {
|
||||
const tags = await tagApi.getResourceTagPaths.request({ resourceType: props.resourceType });
|
||||
const tagNodes = [];
|
||||
for (let tagPath of tags) {
|
||||
tagNodes.push(new TagTreeNode(tagPath, tagPath, props.tagPathNodeType));
|
||||
}
|
||||
return tagNodes;
|
||||
};
|
||||
|
||||
/**
|
||||
* 加载树节点
|
||||
* @param { Object } node
|
||||
* @param { Object } resolve
|
||||
*/
|
||||
const loadNode = async (node: any, resolve: any) => {
|
||||
if (typeof resolve !== 'function') {
|
||||
return;
|
||||
}
|
||||
let nodes = [];
|
||||
try {
|
||||
if (node.level == 0) {
|
||||
nodes = await loadTags();
|
||||
} else if (props.load) {
|
||||
nodes = await props.load(node);
|
||||
} else {
|
||||
nodes = await node.data.loadChildren();
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.error(e);
|
||||
}
|
||||
return resolve(nodes);
|
||||
};
|
||||
|
||||
const getNode = (nodeKey: any) => {
|
||||
let node = treeRef.value.getNode(nodeKey);
|
||||
if (!node) {
|
||||
throw new Error('未找到节点: ' + nodeKey);
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
const changeNode = (val: any) => {
|
||||
// 触发改变时间,并传递节点数据
|
||||
emit('change', getNode(val)?.data);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -7,47 +7,62 @@
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
:destroy-on-close="true"
|
||||
width="700px"
|
||||
width="850px"
|
||||
>
|
||||
<el-form :model="form" ref="dbForm" :rules="rules" label-width="auto">
|
||||
<el-tabs v-model="tabActiveName" style="height: 450px">
|
||||
<el-tab-pane label="基本信息" name="basic">
|
||||
<el-form-item prop="taskName" label="任务名" required>
|
||||
<el-input v-model.trim="form.taskName" placeholder="请输入数据库别名" auto-complete="off" />
|
||||
<el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="11">
|
||||
<el-form-item prop="taskName" label="任务名" required>
|
||||
<el-input v-model.trim="form.taskName" placeholder="请输入数据库别名" auto-complete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="11">
|
||||
<el-form-item prop="taskCron" label="cron" required>
|
||||
<template #label>
|
||||
cron
|
||||
<el-tooltip effect="dark" content="只支持5位表达式,不支持秒级.如 0/2 * * * * 表示每两分钟执行" placement="top">
|
||||
<el-icon>
|
||||
<question-filled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<el-input v-model="form.taskCron" placeholder="支持5位表达式,不支持秒级" auto-complete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="2">
|
||||
<el-form-item prop="status" label="状态" label-width="60" required>
|
||||
<el-switch
|
||||
v-model="form.status"
|
||||
inline-prompt
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
:active-value="1"
|
||||
:inactive-value="-1"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item prop="taskCron" label="cron" required>
|
||||
<el-input v-model="form.taskCron" placeholder="只支持5位表达式,不支持秒级.如 0/2 * * * * 表示每两分钟执行" auto-complete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="pageSize" label="分页大小" required>
|
||||
<el-input-number v-model.trim="form.pageSize" placeholder="同步数据时查询的每页数据大小" auto-complete="off" size="small" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="updField" label="更新字段" required>
|
||||
<el-input v-model.trim="form.updField" placeholder="查询数据源的时候会带上这个字段当前最大值" auto-complete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="updFieldVal" label="更新值">
|
||||
<el-input v-model.trim="form.updFieldVal" placeholder="更新字段当前最大值" auto-complete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="status" label="状态" required>
|
||||
<el-switch v-model="form.status" inline-prompt active-text="启用" inactive-text="禁用" :active-value="1" :inactive-value="-1" />
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="源数据库配置" name="srcDb">
|
||||
<el-form-item prop="srcDbId" label="数据源" required>
|
||||
|
||||
<el-form-item prop="srcDbId" label="源数据库" required>
|
||||
<db-select-tree
|
||||
placeholder="请选择源数据库"
|
||||
v-model:db-id="form.srcDbId"
|
||||
v-model:db-name="form.srcDbName"
|
||||
v-model:tag-path="form.srcTagPath"
|
||||
@select-db="onSelectSrcDb"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item prop="dataSql" label="数据sql" required>
|
||||
<monaco-editor height="200px" class="task-sql" language="sql" v-model="form.dataSql" />
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="目标数据库配置" name="targetDb">
|
||||
<el-form-item prop="targetDbId" label="数据源" required>
|
||||
<el-form-item prop="targetDbId" label="目标数据库" required>
|
||||
<db-select-tree
|
||||
placeholder="请选择目标数据库"
|
||||
v-model:db-id="form.targetDbId"
|
||||
v-model:db-name="form.targetDbName"
|
||||
v-model:tag-path="form.targetTagPath"
|
||||
@@ -55,7 +70,11 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="targetTableName" label="目标表" required>
|
||||
<el-form-item prop="dataSql" label="源数据sql" required>
|
||||
<monaco-editor height="150px" class="task-sql" language="sql" v-model="form.dataSql" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="targetTableName" label="目标库表" required>
|
||||
<el-select v-model="form.targetTableName" filterable placeholder="请选择目标数据库表">
|
||||
<el-option
|
||||
v-for="item in state.targetTableList"
|
||||
@@ -65,7 +84,30 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item prop="pageSize" label="分页大小" required>
|
||||
<el-input type="number" v-model.trim="form.pageSize" placeholder="同步数据时查询的每页数据大小" auto-complete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item prop="updField" label="更新字段" required>
|
||||
<el-input v-model.trim="form.updField" placeholder="查询数据源的时候会带上这个字段当前最大值" auto-complete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-form-item prop="updFieldVal" label="更新值">
|
||||
<el-input v-model.trim="form.updFieldVal" placeholder="更新字段当前最大值" auto-complete="off" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="字段映射" name="field">
|
||||
<el-form-item prop="fieldMap" label="字段映射" required>
|
||||
<el-table :data="form.fieldMap" :max-height="400" size="small">
|
||||
@@ -85,6 +127,7 @@
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="sql预览" name="sqlPreview">
|
||||
<el-form-item prop="fieldMap" label="查询sql">
|
||||
<el-input type="textarea" v-model="state.previewDataSql" readonly :input-style="{ height: '190px' }" />
|
||||
@@ -226,48 +269,43 @@ watch(dialogVisible, async (newValue: boolean) => {
|
||||
}
|
||||
state.tabActiveName = 'basic';
|
||||
const propsData = props.data as any;
|
||||
if (propsData?.id) {
|
||||
let data = await dbApi.getDatasyncTask.request({ taskId: propsData?.id });
|
||||
state.form = data;
|
||||
try {
|
||||
state.form.fieldMap = JSON.parse(data.fieldMap);
|
||||
} catch (e) {
|
||||
state.form.fieldMap = [];
|
||||
}
|
||||
let { srcDbId, srcTagPath, srcDbName, targetTagPath, targetDbId } = state.form;
|
||||
|
||||
// 初始化src数据源
|
||||
if (srcTagPath && srcDbId) {
|
||||
// 通过tagPath查询实例列表
|
||||
const dbInfoRes = await dbApi.dbs.request({ tagPath: srcTagPath });
|
||||
dbInfoRes.list.forEach((a: any) => {
|
||||
if (a.id === srcDbId) {
|
||||
// 初始化实例
|
||||
a.databases = a.database?.split(' ').sort() || [];
|
||||
state.srcDbInst = DbInst.getOrNewInst(a);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化target数据源
|
||||
if (targetTagPath && targetDbId) {
|
||||
// 通过tagPath查询实例列表
|
||||
const dbInfoRes = await dbApi.dbs.request({ tagPath: targetTagPath });
|
||||
dbInfoRes.list.forEach((a: any) => {
|
||||
if (a.id === targetDbId) {
|
||||
// 初始化实例
|
||||
a.databases = a.database?.split(' ').sort() || [];
|
||||
state.targetDbInst = DbInst.getOrNewInst(a);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 注册sql代码提示
|
||||
if (srcDbId && srcDbName) {
|
||||
registerDbCompletionItemProvider(srcDbId, srcDbName, state.srcDbInst.databases, state.srcDbInst.type);
|
||||
}
|
||||
} else {
|
||||
if (!propsData?.id) {
|
||||
state.form = basicFormData;
|
||||
return;
|
||||
}
|
||||
|
||||
let data = await dbApi.getDatasyncTask.request({ taskId: propsData?.id });
|
||||
state.form = data;
|
||||
try {
|
||||
state.form.fieldMap = JSON.parse(data.fieldMap);
|
||||
} catch (e) {
|
||||
state.form.fieldMap = [];
|
||||
}
|
||||
let { srcDbId, srcDbName, targetDbId } = state.form;
|
||||
|
||||
// 初始化src数据源
|
||||
if (srcDbId) {
|
||||
// 通过tagPath查询实例列表
|
||||
const dbInfoRes = await dbApi.dbs.request({ id: srcDbId });
|
||||
const db = dbInfoRes.list[0];
|
||||
// 初始化实例
|
||||
db.databases = db.database?.split(' ').sort() || [];
|
||||
state.srcDbInst = DbInst.getOrNewInst(db);
|
||||
}
|
||||
|
||||
// 初始化target数据源
|
||||
if (targetDbId) {
|
||||
// 通过tagPath查询实例列表
|
||||
const dbInfoRes = await dbApi.dbs.request({ id: targetDbId });
|
||||
const db = dbInfoRes.list[0];
|
||||
// 初始化实例
|
||||
db.databases = db.database?.split(' ').sort() || [];
|
||||
state.targetDbInst = DbInst.getOrNewInst(db);
|
||||
}
|
||||
|
||||
// 注册sql代码提示
|
||||
if (srcDbId && srcDbName) {
|
||||
registerDbCompletionItemProvider(srcDbId, srcDbName, state.srcDbInst.databases, state.srcDbInst.type);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -277,7 +315,7 @@ watch(tabActiveName, async (newValue: string) => {
|
||||
await handleGetSrcFields();
|
||||
await handleGetTargetFields();
|
||||
break;
|
||||
case 'targetDb':
|
||||
case 'dbConf':
|
||||
await handleGetTargetFields();
|
||||
if (state.form.targetDbId && state.form.targetDbName) {
|
||||
await loadDbTables(state.form.targetDbId, state.form.targetDbName);
|
||||
@@ -418,8 +456,12 @@ const cancel = () => {
|
||||
<style lang="scss">
|
||||
.sync-task-edit {
|
||||
.el-select {
|
||||
width: 360px;
|
||||
// width: 360px;
|
||||
width: 100%;
|
||||
}
|
||||
// .el-input__inner {
|
||||
// width: 100%; /* 将el-select内部输入框的宽度设置为100% */
|
||||
// }
|
||||
.task-sql {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
<template>
|
||||
<div class="db-select-tree">
|
||||
<div style="color: gray">{{ (tagPath || '') + ' - ' + (dbName || '请选择数据源schema') }}</div>
|
||||
<tag-tree :resource-type="TagResourceTypeEnum.Db.value" :tag-path-node-type="NodeTypeTagPath" ref="tagTreeRef">
|
||||
<template #prefix="{ data }">
|
||||
<SvgIcon v-if="data.type.value == SqlExecNodeType.DbInst" :name="getDbDialect(data.params.type).getInfo().icon" :size="18" />
|
||||
<SvgIcon v-if="data.icon" :name="data.icon.name" :color="data.icon.color" />
|
||||
</template>
|
||||
</tag-tree>
|
||||
</div>
|
||||
<TagTreeResourceSelect
|
||||
v-bind="$attrs"
|
||||
v-model="selectNode"
|
||||
@change="changeNode"
|
||||
:resource-type="TagResourceTypeEnum.Db.value"
|
||||
:tag-path-node-type="NodeTypeTagPath"
|
||||
>
|
||||
<template #prefix="{ data }">
|
||||
<SvgIcon v-if="data.type.value == SqlExecNodeType.DbInst" :name="getDbDialect(data.params.type).getInfo().icon" :size="18" />
|
||||
<SvgIcon v-if="data.icon" :name="data.icon.name" :color="data.icon.color" />
|
||||
</template>
|
||||
</TagTreeResourceSelect>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { TagResourceTypeEnum } from '@/common/commonEnum';
|
||||
import TagTree from '@/views/ops/component/TagTree.vue';
|
||||
import { NodeType, TagTreeNode } from '@/views/ops/component/tag';
|
||||
import { dbApi } from '@/views/ops/db/api';
|
||||
import { sleep } from '@/common/utils/loading';
|
||||
import SvgIcon from '@/components/svgIcon/index.vue';
|
||||
import { DbType, getDbDialect } from '@/views/ops/db/dialect';
|
||||
import TagTreeResourceSelect from '../../component/TagTreeResourceSelect.vue';
|
||||
import { computed } from 'vue';
|
||||
|
||||
defineProps({
|
||||
const props = defineProps({
|
||||
dbId: {
|
||||
type: Number,
|
||||
},
|
||||
@@ -47,6 +51,15 @@ class SqlExecNodeType {
|
||||
static PgSchema = 8;
|
||||
}
|
||||
|
||||
const selectNode = computed({
|
||||
get: () => {
|
||||
return props.dbName ? `${props.tagPath} - ${props.dbId} - ${props.dbName}` : '';
|
||||
},
|
||||
set: () => {
|
||||
//
|
||||
},
|
||||
});
|
||||
|
||||
const DbIcon = {
|
||||
name: 'Coin',
|
||||
color: '#67c23a',
|
||||
@@ -89,7 +102,7 @@ const NodeTypeDbInst = new NodeType(SqlExecNodeType.DbInst).withLoadNodesFunc((p
|
||||
fn = PgNodeTypes;
|
||||
}
|
||||
return dbs.map((x: any) => {
|
||||
let tagTreeNode = new TagTreeNode(`${parentNode.key}.${x}`, x, fn)
|
||||
let tagTreeNode = new TagTreeNode(`${parentNode.key}.${x}`, `${x}`, fn)
|
||||
.withParams({
|
||||
tagPath: params.tagPath,
|
||||
id: params.id,
|
||||
@@ -108,17 +121,6 @@ const NodeTypeDbInst = new NodeType(SqlExecNodeType.DbInst).withLoadNodesFunc((p
|
||||
});
|
||||
});
|
||||
|
||||
const nodeClickChangeDb = (nodeData: TagTreeNode) => {
|
||||
const params = nodeData.params;
|
||||
// postgres
|
||||
emits('update:dbName', params.db);
|
||||
emits('update:dbId', params.id);
|
||||
emits('update:tagPath', params.tagPath);
|
||||
emits('selectDb', params);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// 数据库节点
|
||||
const PgNodeTypes = new NodeType(SqlExecNodeType.Db).withLoadNodesFunc(async (parentNode: TagTreeNode) => {
|
||||
// pg类数据库会多一层schema
|
||||
@@ -137,23 +139,19 @@ const PgNodeTypes = new NodeType(SqlExecNodeType.Db).withLoadNodesFunc(async (pa
|
||||
});
|
||||
});
|
||||
|
||||
const MysqlNodeTypes = new NodeType(SqlExecNodeType.Db).withNodeClickFunc(nodeClickChangeDb);
|
||||
const MysqlNodeTypes = new NodeType(SqlExecNodeType.Db);
|
||||
|
||||
// postgres schema模式
|
||||
const NodeTypePostgresSchema = new NodeType(SqlExecNodeType.PgSchema).withNodeClickFunc(nodeClickChangeDb);
|
||||
const NodeTypePostgresSchema = new NodeType(SqlExecNodeType.PgSchema);
|
||||
|
||||
const changeNode = (nodeData: TagTreeNode) => {
|
||||
const params = nodeData.params;
|
||||
// postgres
|
||||
emits('update:dbName', params.db);
|
||||
emits('update:dbId', params.id);
|
||||
emits('update:tagPath', params.tagPath);
|
||||
emits('selectDb', params);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.db-select-tree {
|
||||
.tag-tree {
|
||||
height: auto !important;
|
||||
overflow-x: hidden;
|
||||
width: 560px;
|
||||
.el-tree {
|
||||
height: 150px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss"></style>
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
</el-col>
|
||||
|
||||
<el-col :lg="6" :md="6">
|
||||
<div class="card-item-chart" ref="memRef"></div>
|
||||
<ECharts height="200" :option="state.memOption" />
|
||||
</el-col>
|
||||
|
||||
<el-col :lg="6" :md="6">
|
||||
<div class="card-item-chart" ref="cpuRef"></div>
|
||||
<ECharts height="200" :option="state.cpuOption" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -74,11 +74,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRefs, reactive, watch, ref, nextTick } from 'vue';
|
||||
import useEcharts from '@/common/echarts/useEcharts';
|
||||
import tdTheme from '@/common/echarts/theme.json';
|
||||
import { toRefs, reactive, watch, nextTick } from 'vue';
|
||||
import { formatByteSize } from '@/common/utils/format';
|
||||
import { machineApi } from './api';
|
||||
import ECharts from '@/components/echarts/ECharts.vue';
|
||||
import { ECOption } from '@/components/echarts/config';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
@@ -94,22 +94,16 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['update:visible', 'cancel', 'update:machineId']);
|
||||
|
||||
const cpuRef: any = ref();
|
||||
const memRef: any = ref();
|
||||
|
||||
let cpuChart: any = null;
|
||||
let memChart: any = null;
|
||||
|
||||
const state = reactive({
|
||||
dialogVisible: false,
|
||||
stats: {} as any,
|
||||
netInter: [] as any,
|
||||
memOption: {},
|
||||
cpuOption: {},
|
||||
});
|
||||
|
||||
const { dialogVisible, stats, netInter } = toRefs(state);
|
||||
|
||||
let charts = [] as any;
|
||||
|
||||
watch(props, async (newValue: any) => {
|
||||
const visible = newValue.visible;
|
||||
if (visible) {
|
||||
@@ -139,15 +133,15 @@ const initMemStats = () => {
|
||||
value: mem.total - mem.available,
|
||||
},
|
||||
];
|
||||
const option = {
|
||||
|
||||
const option: ECOption = {
|
||||
title: {
|
||||
text: '内存',
|
||||
x: 'left',
|
||||
textStyle: { fontSize: 15 },
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
valueFormatter: formatByteSize,
|
||||
valueFormatter: (val: any) => formatByteSize(val),
|
||||
},
|
||||
legend: {
|
||||
top: '15%',
|
||||
@@ -180,13 +174,7 @@ const initMemStats = () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
if (memChart) {
|
||||
memChart.setOption(option, true);
|
||||
return;
|
||||
}
|
||||
const chart: any = useEcharts(memRef.value, tdTheme, option);
|
||||
memChart = chart;
|
||||
charts.push(chart);
|
||||
state.memOption = option;
|
||||
};
|
||||
|
||||
const initCpuStats = () => {
|
||||
@@ -206,10 +194,10 @@ const initCpuStats = () => {
|
||||
value: cpu.user,
|
||||
},
|
||||
];
|
||||
const option = {
|
||||
|
||||
const option: ECOption = {
|
||||
title: {
|
||||
text: 'CPU使用率',
|
||||
x: 'left',
|
||||
textStyle: { fontSize: 15 },
|
||||
},
|
||||
tooltip: {
|
||||
@@ -247,13 +235,7 @@ const initCpuStats = () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
if (cpuChart) {
|
||||
cpuChart.setOption(option, true);
|
||||
return;
|
||||
}
|
||||
const chart: any = useEcharts(cpuRef.value, tdTheme, option);
|
||||
cpuChart = chart;
|
||||
charts.push(chart);
|
||||
state.cpuOption = option;
|
||||
};
|
||||
|
||||
const initCharts = () => {
|
||||
@@ -262,21 +244,6 @@ const initCharts = () => {
|
||||
initCpuStats();
|
||||
});
|
||||
parseNetInter();
|
||||
initEchartsResize();
|
||||
};
|
||||
|
||||
const initEchartResizeFun = () => {
|
||||
nextTick(() => {
|
||||
for (let i = 0; i < charts.length; i++) {
|
||||
setTimeout(() => {
|
||||
charts[i].resize();
|
||||
}, i * 1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const initEchartsResize = () => {
|
||||
window.addEventListener('resize', initEchartResizeFun);
|
||||
};
|
||||
|
||||
const parseNetInter = () => {
|
||||
@@ -295,16 +262,6 @@ const parseNetInter = () => {
|
||||
const cancel = () => {
|
||||
emit('update:visible', false);
|
||||
emit('cancel');
|
||||
|
||||
setTimeout(() => {
|
||||
cpuChart = null;
|
||||
memChart = null;
|
||||
}, 200);
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.card-item-chart {
|
||||
height: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss"></style>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</el-descriptions>
|
||||
</el-col>
|
||||
<el-col :lg="8" :md="8" class="redis-info">
|
||||
<div class="info-memory-chart" ref="memRef"></div>
|
||||
<ECharts height="150" width="360" :option="state.memOption" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, watch, toRefs, ref, nextTick } from 'vue';
|
||||
import { reactive, watch, toRefs, nextTick } from 'vue';
|
||||
import { formatByteSize } from '@/common/utils/format';
|
||||
import useEcharts from '@/common/echarts/useEcharts';
|
||||
import tdTheme from '@/common/echarts/theme.json';
|
||||
import ECharts from '@/components/echarts/ECharts.vue';
|
||||
import { ECOption } from '@/components/echarts/config';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
@@ -86,6 +86,7 @@ const props = defineProps({
|
||||
},
|
||||
info: {
|
||||
type: [Boolean, Object],
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -95,11 +96,9 @@ const state = reactive({
|
||||
dialogVisible: false,
|
||||
memInfo: {} as any,
|
||||
Keyspace: [] as any[],
|
||||
memOption: {},
|
||||
});
|
||||
|
||||
let memChart: any = null;
|
||||
let memRef = ref(null);
|
||||
|
||||
const { dialogVisible, Keyspace } = toRefs(state);
|
||||
|
||||
watch(
|
||||
@@ -146,15 +145,14 @@ const initMemStats = () => {
|
||||
value: state.memInfo.used_memory,
|
||||
},
|
||||
];
|
||||
const option = {
|
||||
const option: ECOption = {
|
||||
title: {
|
||||
text: '内存',
|
||||
x: 'left',
|
||||
textStyle: { fontSize: 14 },
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
valueFormatter: formatByteSize,
|
||||
valueFormatter: (val: any) => formatByteSize(val),
|
||||
},
|
||||
legend: {
|
||||
top: '15%',
|
||||
@@ -186,11 +184,8 @@ const initMemStats = () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
if (memChart) {
|
||||
memChart.setOption(option, true);
|
||||
return;
|
||||
}
|
||||
memChart = useEcharts(memRef.value, tdTheme, option);
|
||||
|
||||
state.memOption = option;
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
@@ -202,11 +197,6 @@ const close = () => {
|
||||
<style lang="scss">
|
||||
.redis-info {
|
||||
margin-top: 12px;
|
||||
|
||||
.info-memory-chart {
|
||||
width: 360px;
|
||||
height: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.row .title {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package entity
|
||||
|
||||
import "mayfly-go/pkg/model"
|
||||
|
||||
// InstanceQuery 数据库实例查询
|
||||
type InstanceQuery struct {
|
||||
Id uint64 `json:"id" form:"id"`
|
||||
@@ -19,7 +17,7 @@ type DataSyncLogQuery struct {
|
||||
|
||||
// 数据库查询实体,不与数据库表字段一一对应
|
||||
type DbQuery struct {
|
||||
model.Model
|
||||
Id uint64 `form:"id"`
|
||||
|
||||
Name string `orm:"column(name)" json:"name"`
|
||||
Database string `orm:"column(database)" json:"database"`
|
||||
|
||||
@@ -22,6 +22,7 @@ func (d *dbRepoImpl) GetDbList(condition *entity.DbQuery, pageParam *model.PageP
|
||||
Select("db.*, inst.name instance_name, inst.type instance_type, inst.host, inst.port, inst.username ").
|
||||
Joins("JOIN t_db_instance inst ON db.instance_id = inst.id").
|
||||
Eq("db.instance_id", condition.InstanceId).
|
||||
Eq("db.id", condition.Id).
|
||||
Like("db.database", condition.Database).
|
||||
In("db.code", condition.Codes).
|
||||
Eq0("db."+model.DeletedColumn, model.ModelUndeleted).
|
||||
|
||||
Reference in New Issue
Block a user