| | |
| | | window.route = [ |
| | | { |
| | | name: 'DataMonitor', |
| | | isKeepAlive: true, |
| | | isAffix: false, |
| | | path: '/dataMonitor', |
| | | component: '/project/yw/systemManage/DataMonitor/index.vue', |
| | | }, |
| | | { |
| | | name: 'AgentGraph', |
| | | isKeepAlive: true, |
| | | isAffix: false, |
¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from '/@/utils/request'; |
| | | |
| | | export const getAttachTableList = () => { |
| | | return request({ |
| | | url: '/attach/get_attach_table_list', |
| | | method: 'POST', |
| | | }); |
| | | }; |
| | | |
| | | export const queryAttachTableRecords = (params: any) => { |
| | | return request({ |
| | | url: '/attach/query_attach_table_records', |
| | | method: 'POST', |
| | | data: params, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * @description è·åéä»¶ææ å®ä¹å表 |
| | | **/ |
| | | export const getAttachMetricListByPost = () => |
| | | request({ |
| | | url: `/attach/get_attach_metric_list`, |
| | | method: 'post', |
| | | params: {}, |
| | | data: {}, |
| | | }); |
| | | /** |
| | | * @description æ¥è¯¢éä»¶ææ å¼ |
| | | * @param {FormData} params |
| | | **/ |
| | | export const queryAttachMetricValuesByPost = (params) => |
| | | request({ |
| | | url: `/attach/query_attach_metric_values`, |
| | | method: 'post', |
| | | params: {}, |
| | | data: params, |
| | | }); |
| | | /** |
| | | * @description æ¥è¯¢éä»¶ææ åç§° |
| | | * @param {FormData} params |
| | | **/ |
| | | export const queryAttachMetricNamesByPost = (params) => |
| | | request({ |
| | | url: `/attach/query_attach_metric_names`, |
| | | method: 'post', |
| | | params: {}, |
| | | data: params, |
| | | }); |
| | |
| | | }, |
| | | { |
| | | Children: [], |
| | | ID: '1121', |
| | | ParentID: '1742436890822447104', |
| | | Type: 2, |
| | | Name: 'æ°æ®çæµ', |
| | | Path: '/dataMonitor', |
| | | Permission: '', |
| | | Icon: 'ywifont ywicon-tubiao-zhexiantu', |
| | | IsIframe: false, |
| | | OutLink: '', |
| | | IsHide: false, |
| | | Weight: 0, |
| | | SortCode: 2, |
| | | Description: '', |
| | | }, |
| | | { |
| | | Children: [], |
| | | ID: '1122', |
| | | ParentID: '1742436890822447104', |
| | | Type: 2, |
| | |
| | | :value-format="valueFormat" |
| | | :format="DEFAULT_FORMATS_DATE" |
| | | :disabled-date="disabledDate" |
| | | :clearable="false" |
| | | :clearable="true" |
| | | :disabled="disabled" |
| | | @change="datePickerChange" |
| | | > |
| | |
| | | <div class="ml-2 inline-flex items-center space-x-2 text-[14px]"> |
| | | <div |
| | | @click="quickPickRangeClick(parseInt(item))" |
| | | class="border border-solid rounded-md px-2 cursor-pointer" |
| | | :class="{ 'bg-[#1677ff]': parseInt(item) === quickPickValue, 'text-white': parseInt(item) === quickPickValue }" |
| | | v-for="item in Object.keys(timeRangeEnumMapTitle)" |
| | | class="border border-solid rounded-md px-2 py-1 cursor-pointer" |
| | | :class="{ |
| | | 'bg-[#1677ff]': parseInt(item) === quickPickValue, |
| | | 'text-white': parseInt(item) === quickPickValue, |
| | | 'bg-[#f5f7fa]': disabled, |
| | | 'text-[#a9acb3]': disabled, |
| | | 'border-[#dcdfe6]': disabled, |
| | | '!cursor-not-allowed': disabled, |
| | | }" |
| | | v-for="item in Object.keys(timeRangeMapTitle)" |
| | | :key="item" |
| | | > |
| | | {{ timeRangeEnumMapTitle[item] }} |
| | | {{ timeRangeMapTitle[item] }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <script setup lang="ts"> |
| | | import { ElDatePicker } from 'element-plus'; |
| | | import { definePropType } from 'element-plus/es/utils/vue/props/runtime'; |
| | | import { ref, type PropType, computed, watch, nextTick, onMounted } from 'vue'; |
| | | import moment from 'moment'; |
| | | import { computed, nextTick, onMounted, ref, type PropType } from 'vue'; |
| | | import type { TimeRangeParam } from '../types'; |
| | | import type { TimeRangeEnum } from './types'; |
| | | import { timeRangeEnumMapTitle, timeRangeEnumMapValue } from './types'; |
| | | import { dayTimeRangeEnumMapTitle, monthTimeRangeEnumMapTitle, timeRangeEnumMapValue, TimeStepValue } from './types'; |
| | | import { |
| | | CURRENT_DAY, |
| | | DEFAULT_FORMATS_DATE, |
| | | DEFAULT_FORMATS_TIME, |
| | | END_PLACEHOLDER, |
| | | RANGE_SEPARATOR, |
| | | START_PLACEHOLDER, |
| | | } from '/@/components/form/datepicker/constants'; |
| | | import { formatDate } from '/@/utils/formatTime'; |
| | | import moment from 'moment'; |
| | | |
| | | const valueFormat = DEFAULT_FORMATS_DATE + ' ' + DEFAULT_FORMATS_TIME; |
| | | const props = defineProps({ |
| | | data: { |
| | |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | |
| | | quickActive: { |
| | | type: Number as PropType<TimeRangeEnum>, |
| | | required: false, |
| | | }, |
| | | }); |
| | | |
| | | const getRangeMapTitle = (timeStep: TimeStepValue) => { |
| | | switch (timeStep) { |
| | | case TimeStepValue.Day: |
| | | return dayTimeRangeEnumMapTitle; |
| | | case TimeStepValue.Month: |
| | | return monthTimeRangeEnumMapTitle; |
| | | default: |
| | | return dayTimeRangeEnumMapTitle; |
| | | } |
| | | }; |
| | | |
| | | const timeRangeMapTitle = getRangeMapTitle(props.data?.origin?.time_step); |
| | | const dateValue = defineModel({ |
| | | type: definePropType<[string, string]>(Array), |
| | | }); |
| | |
| | | |
| | | const dateChange = () => { |
| | | nextTick(() => { |
| | | if (dateValue.value?.[1]) { |
| | | dateValue.value[1] = dateValue.value[1].slice(0, 10) + ' 23:59:59'; |
| | | } |
| | | emit('change', dateValue.value); |
| | | }); |
| | | }; |
| | |
| | | const quickPickValue = ref<TimeRangeEnum>(null); |
| | | |
| | | const pickQuickRange = (val: TimeRangeEnum) => { |
| | | if(val==undefined) return; |
| | | // if(val==undefined) return; |
| | | quickPickValue.value = val; |
| | | dateValue.value = timeRangeEnumMapValue[val]().map((item) => formatDate(item)) as [string, string]; |
| | | }; |
| | | const quickPickRangeClick = (val: TimeRangeEnum) => { |
| | | if (props.disabled) return; |
| | | if (quickPickValue.value === val) return; |
| | | pickQuickRange(val); |
| | | |
| | | pickQuickRange(val); |
| | | dateChange(); |
| | | }; |
| | | |
| | | const offsetClickIsAllow = computed(() => !!dateValue.value && !props.disabled); |
| | | const preDayClick = () => { |
| | | if (props.disabled) return; |
| | | |
| | | if (!dateValue.value) return; |
| | | dateValue.value[0] = moment(dateValue.value[0]).subtract(1, 'day').format('YYYY-MM-DD HH:mm:ss'); |
| | | dateChange(); |
| | |
| | | }; |
| | | |
| | | const nextDayClick = () => { |
| | | if (props.disabled) return; |
| | | |
| | | if (!dateValue.value) return; |
| | | dateValue.value[1] = moment(dateValue.value[1]).add(1, 'day').format('YYYY-MM-DD HH:mm:ss'); |
| | | dateChange(); |
| | |
| | | resetQuickPickValue(); |
| | | dateChange(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | if(props.quickActive !=null){ |
| | | if (props.quickActive != null) { |
| | | pickQuickRange(props.quickActive); |
| | | } |
| | | }); |
| | | |
| | | defineExpose({ |
| | | formatDateValue: dateValue, |
| | | resetQuickPickValue: resetQuickPickValue, |
| | | }); |
| | | </script> |
| | | <style scoped lang="scss"> |
| | |
| | | CurrentDay, |
| | | ThreeDay, |
| | | SevenDay, |
| | | ThreeMonth, |
| | | HalfYear, |
| | | OneYear, |
| | | } |
| | | |
| | | export const timeRangeEnumMapTitle = { |
| | |
| | | [TimeRangeEnum.CurrentDay]: () => getRecentDateRange(1), |
| | | [TimeRangeEnum.ThreeDay]: () => getRecentDateRange(3), |
| | | [TimeRangeEnum.SevenDay]: () => getRecentDateRange(7), |
| | | |
| | | [TimeRangeEnum.ThreeMonth]: () => getRecentDateRange(90), |
| | | [TimeRangeEnum.HalfYear]: () => getRecentDateRange(180), |
| | | [TimeRangeEnum.OneYear]: () => getRecentDateRange(365), |
| | | }; |
| | | |
| | | export const enum DisplayModeType { |
| | |
| | | [DisplayModeType.Chart]: 'å¾è¡¨', |
| | | [DisplayModeType.List]: 'å表', |
| | | }; |
| | | |
| | | export const enum TimeStepValue { |
| | | Day = 'day', |
| | | Month = 'month', |
| | | } |
| | | /** |
| | | * ææ¥å¿«æ·è¾å
¥ |
| | | */ |
| | | export const dayTimeRangeEnumMapTitle = { |
| | | [TimeRangeEnum.CurrentDay]: '彿¥', |
| | | [TimeRangeEnum.ThreeDay]: 'è¿ä¸æ¥', |
| | | [TimeRangeEnum.SevenDay]: 'è¿ä¸æ¥', |
| | | }; |
| | | |
| | | /** |
| | | * ææå¿«æ·è¾å
¥ |
| | | */ |
| | | export const monthTimeRangeEnumMapTitle = { |
| | | [TimeRangeEnum.ThreeMonth]: 'è¿ä¸æ', |
| | | [TimeRangeEnum.HalfYear]: 'è¿åå¹´', |
| | | [TimeRangeEnum.OneYear]: 'è¿ä¸å¹´', |
| | | }; |
| | |
| | | } |
| | | ); |
| | | |
| | | |
| | | //#region ====================== æç´¢æ¡æä½ ====================== |
| | | const handleCommand = async (command: string | number | object) => { |
| | | if ('expandAll' == command) { |
| | |
| | | for (let i = 0; i < listTreeRef.value!.store._getAllNodes().length; i++) { |
| | | listTreeRef.value!.store._getAllNodes()[i].expanded = false; |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | //#endregion |
| | | |
| | |
| | | //#region ====================== å表æ èç¹åç¼å¾æ ====================== |
| | | suffixIconFun, |
| | | //#endregion |
| | | handleCommand |
| | | handleCommand, |
| | | }; |
| | | }; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | <div class="h-full" v-loading="chartLoading" v-resize="chartContainerResize"> |
| | | <div ref="chartRef"></div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts" name="ChartDisplay"> |
| | | import { defaultsDeep } from 'lodash-es'; |
| | | import type { PropType } from 'vue'; |
| | | import { computed, ref, watch } from 'vue'; |
| | | import { getChatChartOption, SCATTER_SYMBOL_SIZE } from '/@/components/chat/chatComponents/common'; |
| | | import { useDrawChatChart } from '/@/components/chat/chatComponents/hooks/useDrawChatChart'; |
| | | import { ChartTypeEnum } from '/@/components/chat/chatComponents/types'; |
| | | import type { SeriesOption } from 'echarts'; |
| | | import { axisLabelFormatter } from '/@/utils/chart'; |
| | | const props = defineProps({ |
| | | displayList: { |
| | | type: Array as PropType<any[]>, |
| | | default: () => [], |
| | | }, |
| | | }); |
| | | |
| | | const chartRef = ref<HTMLDivElement>(); |
| | | |
| | | const getYColumnIndexMap = () => { |
| | | const displayList = props?.displayList ?? []; |
| | | if (displayList.length === 0) return [{}, []]; |
| | | const yColumnList = displayList.map((item) => { |
| | | return item.values?.columns[1]; |
| | | }); |
| | | const yColumnIndexMap = {}; |
| | | |
| | | // Remove duplicates from yColumnList |
| | | const uniqueYColumns = Array.from(new Set(yColumnList.filter(Boolean))); |
| | | for (const item of displayList) { |
| | | uniqueYColumns.forEach((yColumn, index) => { |
| | | if (item.values?.columns[1] === yColumn) { |
| | | yColumnIndexMap[item.logicalId] = { index, name: yColumn }; |
| | | } |
| | | }); |
| | | } |
| | | |
| | | return [yColumnIndexMap, uniqueYColumns] as any; |
| | | }; |
| | | |
| | | const drawChart = () => { |
| | | const displayList = props?.displayList ?? []; |
| | | if (displayList.length === 0) { |
| | | chartInstance.value.clear(); |
| | | return; |
| | | } |
| | | const xRowTitle = displayList[0]?.values?.columns?.[0] ?? 'æ¶é´'; |
| | | const [yColumnIndexMap, uniqueYColumns] = getYColumnIndexMap(); |
| | | const chartOption = getChatChartOption(); |
| | | Reflect.deleteProperty(chartOption, 'yAxis'); |
| | | const combineOption = defaultsDeep( |
| | | { |
| | | grid: { |
| | | bottom: 50, |
| | | right: 65, |
| | | }, |
| | | legend: { |
| | | top: 19, |
| | | show: true, |
| | | type: 'scroll', |
| | | }, |
| | | tooltip: { |
| | | // valueFormatter: tooltipValueFormatter, |
| | | }, |
| | | toolbox: { |
| | | show: true, |
| | | feature: { |
| | | myBar: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Bar; |
| | | chartInstance.value.setOption({ |
| | | series: seriesInfo.value.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | |
| | | myScatter: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Scatter; |
| | | |
| | | chartInstance.value.setOption({ |
| | | series: seriesInfo.value.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | myLine: { |
| | | onclick: () => { |
| | | activeChartType = ChartTypeEnum.Line; |
| | | chartInstance.value.setOption({ |
| | | series: seriesInfo.value.map((item) => ({ |
| | | ...item, |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | })), |
| | | }); |
| | | }, |
| | | }, |
| | | }, |
| | | }, |
| | | |
| | | // title: { |
| | | // text: props.mapRow?.title, |
| | | // }, |
| | | xAxis: { |
| | | name: xRowTitle, |
| | | nameLocation: 'middle', |
| | | nameGap: 32, |
| | | }, |
| | | // yAxis: displayList.map((item) => { |
| | | // return { |
| | | // name: item.values?.columns[1], |
| | | |
| | | // /** @description ä¸å¼ºå¶ä¿ç */ |
| | | // scale: true, |
| | | // }; |
| | | // }), |
| | | yAxis: uniqueYColumns.map((item) => { |
| | | return { |
| | | name: item, |
| | | |
| | | /** @description ä¸å¼ºå¶ä¿ç */ |
| | | scale: true, |
| | | |
| | | // æ¾ç¤ºy轴线 |
| | | axisLine: { |
| | | show: true, |
| | | }, |
| | | // æ¾ç¤ºå»åº¦çº¿ |
| | | axisTick: { |
| | | show: true, |
| | | }, |
| | | type: 'value', |
| | | axisLabel: { |
| | | formatter: axisLabelFormatter, |
| | | }, |
| | | }; |
| | | }), |
| | | series: seriesInfo.value, |
| | | } as echarts.EChartsOption, |
| | | chartOption |
| | | ); |
| | | chartInstance.value?.setOption(combineOption, { |
| | | notMerge: true, |
| | | }); |
| | | }; |
| | | |
| | | const getChartTypeSeriesOption = (type: ChartTypeEnum) => { |
| | | let result = {}; |
| | | switch (type) { |
| | | case ChartTypeEnum.Bar: |
| | | result = { |
| | | type: 'bar', |
| | | symbol: 'none', |
| | | }; |
| | | |
| | | break; |
| | | case ChartTypeEnum.Line: |
| | | result = { |
| | | type: 'line', |
| | | symbol: 'none', |
| | | smooth: true, |
| | | }; |
| | | |
| | | break; |
| | | |
| | | case ChartTypeEnum.Scatter: |
| | | result = { |
| | | type: 'scatter', |
| | | symbol: 'circle', |
| | | symbolSize: SCATTER_SYMBOL_SIZE, |
| | | }; |
| | | |
| | | break; |
| | | case ChartTypeEnum.Score: |
| | | result = { |
| | | type: 'bar', |
| | | symbol: 'none', |
| | | }; |
| | | |
| | | break; |
| | | |
| | | default: |
| | | break; |
| | | } |
| | | |
| | | return result; |
| | | }; |
| | | let activeChartType: ChartTypeEnum = ChartTypeEnum.Line; |
| | | |
| | | const seriesInfo = computed(() => { |
| | | const displayList = props.displayList ?? []; |
| | | if (displayList.length === 0) return []; |
| | | const xProp = 0; |
| | | const yProp = 1; |
| | | const [yColumnIndexMap, uniqueYColumns] = getYColumnIndexMap(); |
| | | const series = props.displayList.map((item) => { |
| | | return { |
| | | name: item.title, |
| | | data: item.values?.records.toSorted((b, a) => { |
| | | return b[xProp]?.localeCompare(a[xProp]); |
| | | }), |
| | | ...getChartTypeSeriesOption(activeChartType), |
| | | yAxisIndex: yColumnIndexMap[item.logicalId]?.index, |
| | | } as SeriesOption; |
| | | }); |
| | | return series; |
| | | }); |
| | | |
| | | const chartLoading = ref(false); |
| | | const { chartContainerResize, chartInstance } = useDrawChatChart({ chartRef, drawChart }); |
| | | |
| | | watch( |
| | | () => props.displayList, |
| | | (val) => { |
| | | drawChart(); |
| | | } |
| | | ); |
| | | </script> |
| | | <style scoped lang="scss"></style> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <AMContainer class="flex-auto" type="card"> |
| | | <template #aside> |
| | | <!-- ç®å½æ --> |
| | | <LeftTreeByMgr |
| | | v-loading="treeLoading" |
| | | class="h100" |
| | | ref="leftTreeRef" |
| | | :defaultProps="{ |
| | | id: 'logicalId', |
| | | label: 'title', |
| | | children: 'children', |
| | | }" |
| | | :titleName="'ææ å表'" |
| | | @check="handleCheck" |
| | | showCheckbox |
| | | defaultExpandAll |
| | | :treedata="listTreeData" |
| | | :show-more-operate="false" |
| | | :show-add="false" |
| | | :current-node-key="currentListID" |
| | | :folder-icon="(_, data) => data.type !== 'metric'" |
| | | @click="handleClickNode" |
| | | > |
| | | </LeftTreeByMgr> |
| | | </template> |
| | | |
| | | <template #main> |
| | | <div class="w100 h100"> |
| | | <div class="h-full"> |
| | | <div class="h-full flex-column gap-2"> |
| | | <div class="flex-0 flex items-center"> |
| | | <TimeRange |
| | | class="flex-0" |
| | | ref="timeRangeRef" |
| | | v-if="dateRange" |
| | | v-model="dateRange" |
| | | @change="handleSearchInput" |
| | | :data="{ |
| | | origin: { |
| | | time_step: TimeStepValue.Month, |
| | | }, |
| | | }" |
| | | :quickActive="TimeRangeEnum.ThreeMonth" |
| | | /> |
| | | </div> |
| | | |
| | | <ChartDisplay v-loading="chartLoading" class="flex-auto" :displayList="checkedList" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </AMContainer> |
| | | </template> |
| | | |
| | | <script setup lang="ts" name="DataMonitor"> |
| | | import type { TableInstance } from 'element-plus'; |
| | | import { ElMessage } from 'element-plus'; |
| | | import { computed, nextTick, onMounted, ref, watch } from 'vue'; |
| | | import { useCompRef } from '/@/utils/types'; |
| | | import * as attachApi from '/@/api/attach'; |
| | | import { convertListToTree, getRecentDateRange, travelTree } from '/@/utils/util'; |
| | | import { formatDate } from '/@/utils/formatTime'; |
| | | import TimeRange from '/@/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue'; |
| | | import LeftTreeByMgr from '/@/components/tree/leftTreeByMgr.vue'; |
| | | import ChartDisplay from './ChartDisplay.vue'; |
| | | import AMContainer from '/@/components/layout/AMContainer.vue'; |
| | | import { TimeStepValue } from '/@/components/chat/chatComponents/summaryCom/components/recordSet/components/types'; |
| | | import { TimeRangeEnum } from '/@/components/chat/chatComponents/summaryCom/components/recordSet/components/types'; |
| | | const timeRangeRef = useCompRef(TimeRange); |
| | | |
| | | const checkedList = ref([]); |
| | | |
| | | const handleCheck = async (currentNode, checkedInfo) => { |
| | | const checkedNodes = checkedInfo.checkedNodes.filter((item) => item.type === 'metric'); |
| | | await getUnGetData(checkedNodes); |
| | | checkedList.value = checkedNodes; |
| | | }; |
| | | |
| | | //#region ====================== å·¦ä¾§æ æ°æ®ï¼tree init ====================== |
| | | const leftTreeRef = useCompRef(LeftTreeByMgr); |
| | | const treeLoading = ref(false); |
| | | const currentListID = computed(() => currentNode.value?.id); |
| | | |
| | | const listTreeData = ref([]); |
| | | const currentNode = ref(null); |
| | | |
| | | const requestListTreeData = async (listData: any[]) => { |
| | | const listDataWithType = listData.map((item) => ({ |
| | | id: item.id, |
| | | logicalId: `item-${item.id}`, |
| | | logicalParentId: `group-${item.group}`, |
| | | ...item, |
| | | type: 'item', |
| | | })); |
| | | |
| | | const groupList = Array.from(new Set(listDataWithType.filter((item) => item.group).map((item) => item.group))).map((item) => ({ |
| | | id: item, |
| | | title: item, |
| | | logicalId: `group-${item}`, |
| | | type: 'group', |
| | | })); |
| | | const treeData = convertListToTree(listDataWithType.concat(groupList), { |
| | | ID: 'logicalId', |
| | | ParentID: 'logicalParentId', |
| | | Children: 'children', |
| | | }); |
| | | |
| | | const requestParams = listData.map((item) => { |
| | | return { |
| | | id: item.id, |
| | | name: item.title, |
| | | }; |
| | | }); |
| | | |
| | | const p = Promise.all( |
| | | requestParams.map((item) => { |
| | | return attachApi.queryAttachMetricNamesByPost(item); |
| | | }) |
| | | ); |
| | | |
| | | const res = await p; |
| | | |
| | | const idMapMetricName = new Map( |
| | | requestParams.map((item, index) => { |
| | | return [item.id, res[index].values ?? []]; |
| | | }) |
| | | ); |
| | | |
| | | for (const metricItem of listDataWithType) { |
| | | const metricId = metricItem.id; |
| | | if (idMapMetricName.has(metricId)) { |
| | | const metricNames = idMapMetricName.get(metricId); |
| | | metricItem.children = metricNames.map((item) => { |
| | | const id = `${item.OTYPE}-${item.ONAME}`; |
| | | return { |
| | | metric: metricItem, |
| | | id, |
| | | logicalId: `metric-${id}`, |
| | | logicalParentId: metricItem.logicalId, |
| | | title: item.TITLE, |
| | | type: 'metric', |
| | | model: item, |
| | | }; |
| | | }); |
| | | } |
| | | } |
| | | return treeData; |
| | | }; |
| | | |
| | | const handleClickNode = (data) => { |
| | | return; |
| | | if (data.type === 'group' || data.type === 'item') { |
| | | ElMessage.warning('è¯·éæ©ææ '); |
| | | return; |
| | | } |
| | | nextTick(() => { |
| | | leftTreeRef.value?.treeRef.setCurrentKey(data.logicalId); |
| | | }); |
| | | |
| | | currentNode.value = data; |
| | | handleChartQuery(data); |
| | | }; |
| | | const getListTreeData = async () => { |
| | | treeLoading.value = true; |
| | | const res = await attachApi.getAttachMetricListByPost().finally(() => { |
| | | treeLoading.value = false; |
| | | }); |
| | | const listData = res.metrics || []; |
| | | |
| | | listTreeData.value = await requestListTreeData(listData); |
| | | let firstListTreeNode; |
| | | travelTree(listTreeData.value, (value, index, array, parent) => { |
| | | if (value.type === 'metric') { |
| | | firstListTreeNode = value; |
| | | return true; |
| | | } |
| | | }); |
| | | if (firstListTreeNode) { |
| | | await handleChartQuery(firstListTreeNode); |
| | | leftTreeRef.value?.treeRef.setCheckedKeys([firstListTreeNode.logicalId]); |
| | | checkedList.value = [firstListTreeNode]; |
| | | } else { |
| | | currentNode.value = null; |
| | | } |
| | | }; |
| | | //#endregion |
| | | const getUnGetData = async (checkedList: any[]) => { |
| | | const getDataPromiseList = []; |
| | | for (const item of checkedList) { |
| | | if (!item.values) { |
| | | getDataPromiseList.push(handleSearchItem(item)); |
| | | } |
| | | } |
| | | // çå¾
æææ°æ®è·å宿 |
| | | await Promise.all(getDataPromiseList); |
| | | }; |
| | | //#region ====================== ææ ç®¡çè¡¨æ ¼æ°æ®ï¼table init ====================== |
| | | const chartLoading = ref(false); |
| | | |
| | | const handleChartQuery = async (row) => { |
| | | if (!row.values) { |
| | | await handleSearchItem(row); |
| | | } |
| | | }; |
| | | |
| | | //#endregion |
| | | |
| | | //#region ====================== æ¥è¯¢ ====================== |
| | | |
| | | const dateRange = ref(getRecentDateRange(90).map((item) => formatDate(item))); |
| | | |
| | | const getSearchParams = (node) => { |
| | | const metricsNameModel = JSON.stringify(node.model); |
| | | |
| | | const params = { |
| | | id: node.metric?.id, |
| | | start_time: dateRange.value[0], |
| | | end_time: dateRange.value[1], |
| | | quota_keys: metricsNameModel, |
| | | limit: 100, |
| | | } as any; |
| | | |
| | | return params; |
| | | }; |
| | | |
| | | const handleSearchItem = async (node) => { |
| | | const params = getSearchParams(node); |
| | | |
| | | chartLoading.value = true; |
| | | const res = await attachApi.queryAttachMetricValuesByPost(params).finally(() => { |
| | | chartLoading.value = false; |
| | | }); |
| | | node.values = res ?? {}; |
| | | }; |
| | | |
| | | const handleSearchInput = async () => { |
| | | const allPromiseList = []; |
| | | for (const item of checkedList.value) { |
| | | allPromiseList.push(handleSearchItem(item)); |
| | | } |
| | | await Promise.all(allPromiseList); |
| | | checkedList.value = checkedList.value.concat([]) |
| | | }; |
| | | |
| | | //#endregion |
| | | |
| | | onMounted(() => { |
| | | getListTreeData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| | |
| | | host: '0.0.0.0', |
| | | port: env.VITE_PORT as unknown as number, |
| | | open: JSON.parse(env.VITE_OPEN), |
| | | hmr: false, |
| | | hmr: true, |
| | | proxy: { |
| | | '/gitee': { |
| | | target: 'https://gitee.com', |