From b9fa2c53e0fb86718d976ee825102e43f3825a26 Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期一, 06 一月 2025 09:51:58 +0800 Subject: [PATCH] 大模型管理修改 --- src/views/project/yw/systemManage/metricMgr/MetricDetail.vue | 377 ++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 253 insertions(+), 124 deletions(-) diff --git a/src/views/project/yw/systemManage/metricMgr/MetricDetail.vue b/src/views/project/yw/systemManage/metricMgr/MetricDetail.vue index 4bedfd8..152d9d8 100644 --- a/src/views/project/yw/systemManage/metricMgr/MetricDetail.vue +++ b/src/views/project/yw/systemManage/metricMgr/MetricDetail.vue @@ -1,130 +1,111 @@ <template> <div class="flex flex-col h100"> <el-row class="w100 h100"> - <el-col :span="17"> + <el-col :span="17" class="h-full"> <div class="h100 relative"> <div class="ml-6 h100"> <el-tabs v-model="state.activeMetricName" @tab-change="handleClick" class="h100"> - <el-tab-pane label="鍩虹淇℃伅" name="basicInformation"> - <div class="h100"> - <el-descriptions title="鎸囨爣淇℃伅"> - <el-descriptions-item label="鎸囨爣鍚嶇О:" :span="2">{{ - state.metricBasicInfo.descriptionQuotaItems.title ? state.metricBasicInfo.descriptionQuotaItems.title : '-' - }}</el-descriptions-item> - <el-descriptions-item label="鎸囨爣鍏ㄧО:" :span="2">{{ - state.metricBasicInfo.descriptionQuotaItems.full_name - ? state.metricBasicInfo.descriptionQuotaItems.full_name - : '-' - }}</el-descriptions-item> - <el-descriptions-item label="鎸囨爣瀹氫箟:" :span="3">{{ - state.metricBasicInfo.descriptionQuotaItems.metrics_define - ? state.metricBasicInfo.descriptionQuotaItems.metrics_define - : '-' - }}</el-descriptions-item> - <el-descriptions-item label="绫诲埆:" :span="2"> - {{ - state.metricBasicInfo.descriptionQuotaItems.metrics_type - ? state.metricBasicInfo.descriptionQuotaItems.metrics_type + <el-tab-pane label="鍩虹淇℃伅" name="basicInformation" class="h-full"> + <div class="h100 flex flex-col"> + <div class="flex-0"> + <el-descriptions title="鎸囨爣淇℃伅"> + <el-descriptions-item label="鎸囨爣缂栧彿:" :span="2">{{ + state.metricBasicInfo.descriptionQuotaItems.id ? state.metricBasicInfo.descriptionQuotaItems.id : '-' + }}</el-descriptions-item> + <el-descriptions-item label="鎸囨爣鍚嶇О:" :span="2">{{ + state.metricBasicInfo.descriptionQuotaItems.title ? state.metricBasicInfo.descriptionQuotaItems.title : '-' + }}</el-descriptions-item> + <el-descriptions-item label="涓婚鍩�:" :span="2">{{ + state.metricBasicInfo.descriptionQuotaItems?.metrics_group + ? themeDomainMap?.[state.metricBasicInfo.descriptionQuotaItems?.metrics_group]?.group_name : '-' - }}</el-descriptions-item - > - <el-descriptions-item label="閲嶈鎬�:" :span="2"> - {{ eMetrics_Ops[state.metricBasicInfo.descriptionQuotaItems.metrics_important] }} - </el-descriptions-item> - <el-descriptions-item label="璁$畻鏂规硶:" :span="3"> - {{ - state.metricBasicInfo.descriptionQuotaItems.calcu_method - ? state.metricBasicInfo.descriptionQuotaItems.calcu_method + }}</el-descriptions-item> + <el-descriptions-item label="鍗曚綅:" :span="2">{{ + state.metricBasicInfo.descriptionQuotaItems.metrics_unit + ? state.metricBasicInfo.descriptionQuotaItems.metrics_unit : '-' - }} - </el-descriptions-item> - </el-descriptions> - <el-divider /> - </div> - </el-tab-pane> - <el-tab-pane label="鎸囨爣鎺㈢储" name="indicatorExploration"> - <div class="h100"> - <div class="set_explore"> - <div class="set_explore_pad"> - <el-form ref="exploreFormRef" :model="state.exploreForm" label-width="80px" label-position="left"> - <el-form-item label="鏃ユ湡鍖洪棿:"> - <div style="width: 300px"> - <el-date-picker - v-model="state.exploreForm.dateRangeExplore" - type="daterange" - range-separator="~" - value-format="YYYY-MM-DD HH:mm:ss" - :default-time="defaultTime" - @change="getDateTime" - :disabled-date="disablesDate" - /> - </div> - </el-form-item> - <el-form-item label="缁村害涓嬮捇:"> - <el-select v-model="state.exploreForm.dimensionDrilling" autocomplete="off" style="width: 226.4px" clearable> - <el-option - v-for="item in Object.keys(eDrilling_Ops)" - :key="item" - :value="parseInt(item)" - :label="eDrilling_Ops[item]" - > - </el-option> - </el-select> - </el-form-item> - <el-form-item label="缁村害绛涢��:"> - <el-select - v-model="state.exploreForm.dimensionFiltering.user" - autocomplete="off" - style="width: 186.4px" - clearable - @change="handleDimensionFilteringChange" - > - <el-option - v-for="item in Object.keys(eDrilling_Ops)" - :key="item" - :value="parseInt(item)" - :label="eDrilling_Ops[item]" - > - </el-option> - </el-select> - <el-select - v-model="state.exploreForm.dimensionFiltering.unit" - autocomplete="off" - style="width: 126.4px; margin: 0 5px" - clearable - > - <el-option - v-for="item in Object.keys(eDimensionFilter_Ops)" - :key="item" - :value="parseInt(item)" - :label="eDimensionFilter_Ops[item]" - > - </el-option> - </el-select> - <el-select - v-model="state.exploreForm.dimensionFiltering.someone" - autocomplete="off" - style="width: 126.4px; margin-right: 5px" - clearable - > - <el-option - v-for="(item, index) in state.resultList" - :key="index" - :value="item.id" - :label="item.department" - > - </el-option> - </el-select> - <el-button type="primary" @click="handleExplore" icon="ele-Search">鏌ヨ</el-button> - </el-form-item> - </el-form> - </div> - <div class="w100 h-[550px]"> - <div ref="chartExplorationRef" class="w100 h100"></div> - </div> + }}</el-descriptions-item> + <el-descriptions-item label="鎸囨爣鍏ㄧО:" :span="2">{{ + state.metricBasicInfo.descriptionQuotaItems.full_name + ? state.metricBasicInfo.descriptionQuotaItems.full_name + : '-' + }}</el-descriptions-item> + <el-descriptions-item label="鎸囨爣瀹氫箟:" :span="3">{{ + state.metricBasicInfo.descriptionQuotaItems.metrics_define + ? state.metricBasicInfo.descriptionQuotaItems.metrics_define + : '-' + }}</el-descriptions-item> + <el-descriptions-item label="绫诲埆:" :span="2"> + {{ + state.metricBasicInfo.descriptionQuotaItems.metrics_type + ? state.metricBasicInfo.descriptionQuotaItems.metrics_type + : '-' + }}</el-descriptions-item + > + <el-descriptions-item label="閲嶈鎬�:" :span="2"> + {{ eMetrics_Ops[state.metricBasicInfo.descriptionQuotaItems.metrics_important] }} + </el-descriptions-item> + <el-descriptions-item label="璁$畻鏂规硶:" :span="3"> + {{ + state.metricBasicInfo.descriptionQuotaItems.calcu_method + ? state.metricBasicInfo.descriptionQuotaItems.calcu_method + : '-' + }} + </el-descriptions-item> + </el-descriptions> + <el-divider /> + </div> + <div class="flex-auto flex flex-col"> + <span class="flex-0 text-[16px] font-bold mb-[4px]">鎸囨爣鍥捐氨</span> + <TreeGraph v-if="graphData" class="flex-auto" :data="graphData" :maxCount="maxCount" /> </div> </div> </el-tab-pane> + <el-tab-pane label="鎸囨爣鎺㈢储" name="indicatorExploration" class="h-full"> + <div class="h-full flex-column"> + <el-form :model="dialogFormValue" class="flex-0" ref="dialogFormRef" :rules="dialogFormRules"> + <el-form-item label="鏃ユ湡鍖洪棿锛�" prop="rangValue" v-if="currentMetrics?.is_time_values ?? true"> + <TimeRange v-model="dialogFormValue.rangValue" @change="query(false)" /> + </el-form-item> + <el-row :gutter="35"> + <el-col :span="12" class="mb20"> + <el-form-item label="鍒嗙粍缁村害锛�" prop="rangValue"> + <el-select v-model="dialogFormValue.groupDimList" multiple @change="query(false)"> + <el-option + v-for="item in currentMetrics?.dimensions ?? []" + :key="item.id" + :label="item.title" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12" class="mb20" v-for="item in filterDimList" :key="item.id" + ><el-form-item :label="`${item.title}锛歚" :prop="`${item.id}`"> + <el-input v-model="dialogFormValue[item.id]" @input="(val) => filterDimInput(val, item)"> </el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="flex-auto mt-4"> + <SummaryCom + v-loading="queryLoading" + ref="summaryComRef" + :data="querySummaryData" + :origin-data="{ + content: { + origin: { + summary: querySummaryData, + }, + }, + }" + /> + <!-- <RecordSet v-bind="recordSetProps" class="h-full" /> --> + <!-- <RecordSetTable v-bind="recordSetTableProps" class="h-full"/> --> + </div> + </div> + </el-tab-pane> + <!-- <el-tab-pane label="鎸囨爣鍥捐氨" name="metricGraph" class="h-full"> <div class="h-full"></div></el-tab-pane> --> </el-tabs> </div> <div class="list_btn" @click="handleExitFlow"> @@ -142,12 +123,17 @@ <div class="mb-[5px]"> <div class="set-visit"> <i class="ywifont ywicon-fenshu_an w-[18px] h-[18px] text-yellow-300 !text-[20px]"></i> - <div>璁块棶娆℃暟</div> + <div>鍏抽敭淇℃伅</div> </div> </div> <div class="set-detail"> <el-divider /> <div class="section___vePzi"> + + <div class="item___txXyB"> + <div class="item_name">鎸囨爣鍚嶇О:</div> + <div class="item_value">{{state.metricBasicInfo.descriptionQuotaItems.title ? state.metricBasicInfo.descriptionQuotaItems.title : '-'}}</div> + </div> <div class="item___txXyB"> <div class="item_name">閲嶈鎬�:</div> <div class="item_value">{{ eMetrics_Ops[state.metricBasicInfo.descriptionQuotaItems.metrics_important] }}</div> @@ -212,7 +198,7 @@ <div class="subTitle___zya5g">涓嬮捇缁村害</div> <div class="ml-0 mt-[20px]"> <div class="flex flex-wrap gap-[5px] items-center"> - <div v-for="item in state.metricBasicInfo.applicationInformation" :key="item.id"> + <div v-for="item in currentMetrics?.dimensions ?? []" :key="item.id"> <el-tag :style="{ backgroundColor: 'e6f4ff', color: '#0958d9', borderColor: '#91caff' }">{{ item.title }}</el-tag> @@ -235,12 +221,32 @@ import { nextTick, onMounted, reactive, ref } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import * as metricApi from '/@/api/metrics'; +import TimeRange from '/@/components/chat/chatComponents/summaryCom/components/recordSet/components/TimeRange.vue'; +import TreeGraph from '/@/components/graph/treeGraph/TreeGraph.vue'; import { formatTime, getDefaultPeriod } from '/@/utils/istation/common.js'; -import { eDimensionFilter_Ops, eDrilling_Ops, eMetrics_Ops } from '/@/views/types/metrics'; +import { eMetrics_Ops } from '/@/views/types/metrics'; + +import type { FormRules } from 'element-plus/es/components/form/src/types'; +import _, { debounce } from 'lodash'; +import { computed } from 'vue'; +import type { OrgTreeItem } from '../agentGraph/types'; +import SummaryCom from './components/SummaryCom.vue'; +import { chatMetricsJsonByPost } from '/@/api/metrics'; +import { getSceneGroupTreeByPost } from '/@/api/scene'; +import { useCompRef } from '/@/utils/types'; +import { getItemMap } from '/@/utils/util'; const defaultTime = ref<[Date, Date]>([new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]); const router = useRouter(); const route = useRoute(); // 瀹氫箟鍙橀噺鍐呭 +const themeDomainData = ref([]); +const initThemeDomainData = async () => { + const res = await getSceneGroupTreeByPost(); + themeDomainData.value = res.groups || []; +}; +const themeDomainMap = computed(() => { + return getItemMap(themeDomainData.value, 'group_id'); +}); const state = reactive({ metricInfo: { name: '', @@ -249,7 +255,6 @@ activeMetricName: 'basicInformation', metricBasicInfo: { descriptionQuotaItems: {}, - applicationInformation: [], } as any, exploreForm: { dateRangeExplore: '' as any, @@ -289,16 +294,23 @@ //#endregion //#region ====================== 鍩虹淇℃伅 ====================== +const currentMetrics = ref(null); const tableData = ref([]); const getTableData = async (id) => { const res = await metricApi.getMetricNameListByPost(); const data = res?.values ?? []; const filterData = data.filter((item) => item.id == id); state.metricBasicInfo.descriptionQuotaItems = filterData[0]; //宸︿晶鎻忚堪鍐呭 - state.metricBasicInfo.applicationInformation = filterData[0].dimensions ?? []; + currentMetrics.value = filterData[0]; + filterDimList.value.forEach((item) => { + if (!dialogFormValue.value) { + dialogFormValue.value = {} as any; + } + dialogFormValue.value[item.id] = ''; + }); }; //#endregion -//#region ====================== 鎸囨爣鎺㈢储鏌ヨ ====================== +//#region ====================== 鎸囨爣鍥捐氨鏌ヨ ====================== // 鏃堕棿闄愬埗 const disablesDate = (time) => { return time.getTime() > new Date().getTime(); @@ -432,12 +444,129 @@ state.chartStatus = true; }); } + state.activeMetricName = val; }; //#endregion -onMounted(() => { + +//#region ====================== 鎸囨爣鍥捐氨 ====================== + +const filterDimList = computed( + () => currentMetrics?.value?.dimensions ?? [].filter((item) => item.filter_type === 'str_eq' && item.type === '瀛楃涓�') +); +const dialogFormRules = ref<FormRules>({ + title: [{ required: true, message: '璇疯緭鍏ユ爣棰�', trigger: 'blur' }], + prompt: [{ required: true, message: '璇疯緭鍏ユ彁绀鸿瘝', trigger: 'blur' }], +}); + +const summaryComRef = useCompRef(SummaryCom); +const dialogFormValue = ref({ + rangValue: ['2024-10-21 00:00:00', '2024-10-23 23:59:59'], + groupDimList: [], +}); + +const currentMetricsId = computed(() => router.currentRoute.value.query.id as string); +const querySummaryData = ref([]); +const queryLoading = ref(false); +/** + * 鎸夋煡璇㈡潯浠舵煡鎵� + */ +const query = async (isFirst: boolean) => { + if (!currentMetricsId.value) return; + const groupDimStr = dialogFormValue.value.groupDimList.join(','); + const sendGroupDims = groupDimStr || undefined; + queryLoading.value = true; + const res = await chatMetricsJsonByPost( + { + metrics_id: currentMetricsId.value, + start_time: dialogFormValue.value.rangValue[0], + end_time: dialogFormValue.value.rangValue[1], + group_dims: sendGroupDims, + filter_dims: JSON.stringify(_.omit(dialogFormValue.value, ['groupDimList', 'rangValue'])), + }, + { + loading: false, + } + ).finally(() => { + queryLoading.value = false; + }); + querySummaryData.value = res?.summary ?? []; + if (!isFirst) { + nextTick(() => { + nextTick(() => { + summaryComRef.value.updateSummary(); + }); + }); + } +}; +const debounceQuery = debounce(query, 600); +const filterDimInput = (val, dim) => { + debounceQuery(false); +}; + +//#endregion + +//#region ====================== 鎸囨爣鍥捐氨 ====================== + +const maxCount = ref(null); +const graphData = ref(null); +const convertOrgTreeToTreeNode = (orgTreeData: OrgTreeItem) => { + const treeData = { + id: orgTreeData.treeId, + label: orgTreeData.label, + data: orgTreeData, + children: orgTreeData.children?.length > 0 ? orgTreeData.children.map((item) => convertOrgTreeToTreeNode(item)) : [], + }; + return treeData; +}; +const getGraphTreeData = () => { + if (!currentMetricsId.value) return; + /** @description 缁村害鏁伴噺 */ + let dimensionCount = 0; + /** @description 鎸囨爣鏁伴噺 */ + let metricsCount = 1; + + const metricsTreeId = `metrics-${currentMetricsId.value}`; + const dimensionList = currentMetrics.value.dimensions ?? []; + dimensionCount = dimensionList.length; + let logicTree: OrgTreeItem = { + treeId: metricsTreeId, + logicId: currentMetricsId.value, + type: 'metrics', + + model: currentMetrics.value, + get label() { + return this.model.title; + }, + level: 0, + children: dimensionList.map((item) => { + const dimensionTreeId = `${metricsTreeId}-dimension-${item.id}`; + return { + treeId: dimensionTreeId, + logicId: item.id, + type: 'dimension', + model: item, + get label() { + return this.model.title; + }, + level: 1, + }; + }), + }; + const resData = logicTree; + maxCount.value = Math.max(dimensionCount, metricsCount); + graphData.value = convertOrgTreeToTreeNode(resData); +}; +//#endregion + +onMounted(async () => { const { id } = route.query; - getTableData(id); + query(true); + initThemeDomainData(); + await getTableData(id); + if (!graphData.value) { + getGraphTreeData(); + } }); </script> <style scoped lang="scss"> -- Gitblit v1.9.3