diff --git a/package-lock.json b/package-lock.json index 217941fd..59d7203e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,8 +22,7 @@ "vue-grid-layout": "^3.0.0-beta1", "vue-i18n": "^9.1.9", "vue-router": "^4.0.0-0", - "vue-types": "^4.1.1", - "vuex": "^4.0.0-0" + "vue-types": "^4.1.1" }, "devDependencies": { "@types/d3": "^7.1.0", @@ -27338,17 +27337,6 @@ "vue": "^2.0.0 || ^3.0.0" } }, - "node_modules/vuex": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", - "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==", - "dependencies": { - "@vue/devtools-api": "^6.0.0-beta.11" - }, - "peerDependencies": { - "vue": "^3.0.2" - } - }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -50552,14 +50540,6 @@ "is-plain-object": "5.0.0" } }, - "vuex": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz", - "integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==", - "requires": { - "@vue/devtools-api": "^6.0.0-beta.11" - } - }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/package.json b/package.json index 040092aa..2877874e 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,7 @@ "vue-grid-layout": "^3.0.0-beta1", "vue-i18n": "^9.1.9", "vue-router": "^4.0.0-0", - "vue-types": "^4.1.1", - "vuex": "^4.0.0-0" + "vue-types": "^4.1.1" }, "devDependencies": { "@types/d3": "^7.1.0", diff --git a/src/components/Graph.vue b/src/components/Graph.vue index 85638baa..0222dca1 100644 --- a/src/components/Graph.vue +++ b/src/components/Graph.vue @@ -46,8 +46,12 @@ const props = defineProps({ }, filters: { type: Object as PropType<{ - value: number | string; - dataIndex: number; + duration: { + startTime: string; + endTime: string; + }; + isRange: boolean; + dataIndex?: number; sourceId: string; }>, }, @@ -73,7 +77,7 @@ onMounted(async () => { }); document.addEventListener( "click", - () => { + (event: Event) => { if (instance.isDisposed()) { return; } @@ -84,6 +88,27 @@ onMounted(async () => { type: "updateAxisPointer", currTrigger: "leave", }); + if ( + ["vis-item-overflow", "vis-item-content"].includes( + (event.target as HTMLDivElement).className + ) + ) { + return; + } + const series = (window as any).structuredClone(props.option.series); + for (const temp of series) { + if (temp.markArea) { + delete temp.markArea; + } + } + const options = { + ...props.option, + series, + }; + if (JSON.stringify(options) === JSON.stringify(props.option)) { + return; + } + setOptions(options); }, true ); @@ -110,6 +135,39 @@ watch( return; } if (props.filters) { + if (props.filters.isRange) { + const markArea = { + silent: true, + itemStyle: { + opacity: 0.3, + }, + data: [ + [ + { + xAxis: props.filters.duration.startTime, + }, + { + xAxis: props.filters.duration.endTime, + }, + ], + ], + }; + const series = (window as any).structuredClone(props.option.series); + for (const [key, temp] of series.entries()) { + if (key === 0) { + temp.markArea = markArea; + } + } + const options = { + ...props.option, + series, + }; + if (JSON.stringify(options) === JSON.stringify(props.option)) { + return; + } + setOptions(options); + return; + } instance.dispatchAction({ type: "showTip", dataIndex: props.filters.dataIndex, diff --git a/src/hooks/useEcharts.ts b/src/hooks/useEcharts.ts index 01f7d7ed..24698653 100644 --- a/src/hooks/useEcharts.ts +++ b/src/hooks/useEcharts.ts @@ -18,7 +18,6 @@ import { BarSeriesOption, LineSeriesOption, HeatmapSeriesOption, - PieSeriesOption, SankeySeriesOption, } from "echarts/charts"; import { @@ -46,7 +45,6 @@ export type ECOption = echarts.ComposeOption< | DatasetComponentOption | LegendComponentOption | HeatmapSeriesOption - | PieSeriesOption | SankeySeriesOption >; diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts index f2a90370..3b4af093 100644 --- a/src/locales/lang/en.ts +++ b/src/locales/lang/en.ts @@ -147,6 +147,7 @@ const msg = { nameTip: "The name only supports Chinese and English, horizontal lines and underscores. The length of the name is limited to 300 characters", duplicateName: "Duplicate name", + enableAssociate: "Enable association", seconds: "Seconds", hourTip: "Select Hour", minuteTip: "Select Minute", diff --git a/src/locales/lang/es.ts b/src/locales/lang/es.ts index 2da52839..d65c1e41 100644 --- a/src/locales/lang/es.ts +++ b/src/locales/lang/es.ts @@ -147,6 +147,7 @@ const msg = { duplicateName: "Nombre duplicado", nameTip: "El nombre sólo admite chino e inglés, líneas horizontales y subrayado, y la longitud del nombre no excederá de 300 caracteres", + enableAssociate: "Activar asociación", seconds: "Segundos", hourTip: "Seleccione Hora", minuteTip: "Seleccione Minuto", diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts index 7a636263..6c05e548 100644 --- a/src/locales/lang/zh.ts +++ b/src/locales/lang/zh.ts @@ -142,6 +142,7 @@ const msg = { begin: "开始", associateOptions: "关联选项", widget: "部件", + enableAssociate: "启用关联", nameTip: "该名称仅支持中文和英文、横线和下划线, 并且限制长度为300个字符", duplicateName: "重复的名称", seconds: "秒", diff --git a/src/store/modules/event.ts b/src/store/modules/event.ts index fed1fa74..82c8a829 100644 --- a/src/store/modules/event.ts +++ b/src/store/modules/event.ts @@ -104,6 +104,9 @@ export const eventStore = defineStore({ scope = "Endpoint"; } item.scope = scope; + if (!item.endTime || item.endTime === item.startTime) { + item.endTime = Number(item.startTime) + 60000; + } return item; } ); diff --git a/src/types/dashboard.d.ts b/src/types/dashboard.d.ts index 4bb9aa33..1f3ecac9 100644 --- a/src/types/dashboard.d.ts +++ b/src/types/dashboard.d.ts @@ -38,7 +38,16 @@ export interface LayoutConfig { metricConfig?: MetricConfigOpt[]; id?: string; associate?: { widgetId: string }[]; - filters?: { dataIndex: number; sourceId: string }; + eventAssociate?: boolean; + filters?: { + dataIndex: number; + sourceId: string; + isRange?: boolean; + duration?: { + startTime: string; + endTime: string; + }; + }; } export type MetricConfigOpt = { diff --git a/src/utils/echarts.ts b/src/utils/echarts.ts index 9103f912..db786a00 100644 --- a/src/utils/echarts.ts +++ b/src/utils/echarts.ts @@ -16,13 +16,7 @@ */ import * as echarts from "echarts/core"; -import { - BarChart, - LineChart, - PieChart, - HeatmapChart, - SankeyChart, -} from "echarts/charts"; +import { BarChart, LineChart, HeatmapChart, SankeyChart } from "echarts/charts"; import { TitleComponent, @@ -32,6 +26,7 @@ import { DataZoomComponent, VisualMapComponent, TimelineComponent, + MarkAreaComponent, } from "echarts/components"; import { SVGRenderer } from "echarts/renderers"; @@ -43,13 +38,13 @@ echarts.use([ GridComponent, BarChart, LineChart, - PieChart, HeatmapChart, SankeyChart, SVGRenderer, DataZoomComponent, VisualMapComponent, TimelineComponent, + MarkAreaComponent, ]); export default echarts; diff --git a/src/views/dashboard/configuration/Event.vue b/src/views/dashboard/configuration/Event.vue new file mode 100644 index 00000000..a5d9b661 --- /dev/null +++ b/src/views/dashboard/configuration/Event.vue @@ -0,0 +1,82 @@ + + + + diff --git a/src/views/dashboard/configuration/index.ts b/src/views/dashboard/configuration/index.ts index a1359eec..6d39f192 100644 --- a/src/views/dashboard/configuration/index.ts +++ b/src/views/dashboard/configuration/index.ts @@ -18,9 +18,11 @@ import Text from "./Text.vue"; import Widget from "./Widget.vue"; import Topology from "./Topology.vue"; +import Event from "./Event.vue"; export default { Text, Widget, Topology, + Event, }; diff --git a/src/views/dashboard/configuration/widget/AssociateOptions.vue b/src/views/dashboard/configuration/widget/AssociateOptions.vue index 0e7aab97..feae7703 100644 --- a/src/views/dashboard/configuration/widget/AssociateOptions.vue +++ b/src/views/dashboard/configuration/widget/AssociateOptions.vue @@ -41,32 +41,16 @@ const widgetIds = ref( associate.map((d: { widgetId: string }) => d.widgetId) ); const widgets = computed(() => { - const isLinear = ["Bar", "Line", "Area"].includes( - dashboardStore.selectedGrid.graph && dashboardStore.selectedGrid.graph.type - ); - // const isRank = ["TopList"].includes( - // dashboardStore.selectedGrid.graph && dashboardStore.selectedGrid.graph.type - // ); - const { widgets } = getDashboard(dashboardStore.currentDashboard); - const items = widgets.filter( + const all = getDashboard(dashboardStore.currentDashboard).widgets; + const items = all.filter( (d: { value: string; label: string } & LayoutConfig) => { - if (dashboardStore.selectedGrid.id !== d.id) { - if ( - isLinear && - d.type === "Widget" && - d.widget && - d.widget.name && - d.id - ) { - d.value = d.id; - d.label = d.widget.name; - return d; - } - // if (isRank && d.type !== "Widget" && d.widget && d.id) { - // d.value = d.id; - // d.label = d.widget.name || d.id; - // return d; - // } + const isLinear = ["Bar", "Line", "Area"].includes( + (d.graph && d.graph.type) || "" + ); + if (isLinear && d.id && dashboardStore.selectedGrid.id !== d.id) { + d.value = d.id; + d.label = (d.widget && d.widget.name) || d.id; + return d; } } ); @@ -84,6 +68,7 @@ function updateWidgetConfig(options: Option[]) { associate: opt, }; dashboardStore.selectWidget({ ...widget }); + // remove unuse association widget option for (const id of widgetIds.value) { if (!newVal.includes(id)) { diff --git a/src/views/dashboard/controls/Event.vue b/src/views/dashboard/controls/Event.vue index e510a138..c4cc16ac 100644 --- a/src/views/dashboard/controls/Event.vue +++ b/src/views/dashboard/controls/Event.vue @@ -25,6 +25,9 @@ limitations under the License. --> +
+ {{ t("edit") }} +
{{ t("delete") }}
@@ -58,6 +61,10 @@ const dashboardStore = useDashboardStore(); function removeWidget() { dashboardStore.removeControls(props.data); } +function editConfig() { + dashboardStore.setConfigPanel(true); + dashboardStore.selectWidget(props.data); +}