<template>
|
<div class="flex flex-col h100">
|
<el-row class="w100 h100">
|
<el-col :span="17">
|
<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="指标信息" :column="2">
|
<el-descriptions-item label="指标ID">kooriookami</el-descriptions-item>
|
<el-descriptions-item label="中文名">18100000000</el-descriptions-item>
|
<el-descriptions-item label="英文名">Suzhou</el-descriptions-item>
|
<el-descriptions-item label="别名"> </el-descriptions-item>
|
<el-descriptions-item label="分类">
|
<el-tag size="small">School</el-tag>
|
</el-descriptions-item>
|
</el-descriptions>
|
<el-divider />
|
<el-descriptions title="模型信息" :column="2">
|
<el-descriptions-item label="模型名">kooriookami</el-descriptions-item>
|
<el-descriptions-item label="模型ID">18100000000</el-descriptions-item>
|
<el-descriptions-item label="模型英文名">Suzhou</el-descriptions-item>
|
</el-descriptions>
|
<el-divider />
|
<el-descriptions title="定义信息" :column="2">
|
<el-descriptions-item label="定义类型">kooriookami</el-descriptions-item>
|
<el-descriptions-item label="表达式">18100000000</el-descriptions-item>
|
<el-descriptions-item label="度量列表">
|
<template #default>
|
<el-table :data="state.measurementList" style="width: 100%">
|
<el-table-column prop="date" label="度量名称" width="180" />
|
<el-table-column prop="name" label="限定条件" width="180" />
|
<el-table-column prop="address" label="聚合函数" />
|
</el-table>
|
</template>
|
</el-descriptions-item>
|
</el-descriptions>
|
</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="100px">
|
<el-form-item label="日期区间:">
|
<div style="width: 300px">
|
<el-date-picker
|
v-model="state.exploreForm.dateRangeExplore"
|
type="daterange"
|
range-separator="~"
|
:shortcuts="shortcuts"
|
/>
|
</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
|
>
|
<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.resultList" autocomplete="off" style="width: 126.4px; margin-right: 5px" clearable>
|
<el-option
|
v-for="(item, index) in state.resultList"
|
:key="index"
|
:value="item.department"
|
: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 h100">
|
<div ref="chartExplorationRef" class=""></div>
|
</div>
|
</div>
|
</div>
|
</el-tab-pane>
|
</el-tabs>
|
</div>
|
<div class="list_btn">
|
<el-button style="width: 40px" link @click="handleExitFlow">
|
<el-icon style="font-size: 16px !important; color: #1677ff">
|
<ArrowLeft />
|
</el-icon>
|
</el-button>
|
<span class="text-[14px] text-[#1677ff] font-[400] mr-2">返回列表页</span>
|
</div>
|
</div>
|
</el-col>
|
<el-col :span="7">
|
<div class="set-right-height ml-[10px]">
|
<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 class="set-detail">
|
<el-divider />
|
<div class="section___vePzi">
|
<div class="item___txXyB" v-for="(item, index) in state.metricBasicInfo.visitNumData" :key="index">
|
<div class="item_name">{{ item.name }}:</div>
|
<div class="item_value">
|
{{ item.value }}
|
</div>
|
</div>
|
</div>
|
<el-divider />
|
<div class="section___vePzi">
|
<div class="item___title">
|
<i class="ywifont ywicon-gongzuozongjie w-[18px] h-[18px] !text-[18px]"></i>
|
<span>创建信息</span>
|
</div>
|
<div class="item___txXyB" v-for="(item, index) in state.metricBasicInfo.createInformation" :key="index">
|
<div class="item_name">{{ item.name }}:</div>
|
<div class="item_value">
|
{{ item.value }}
|
</div>
|
</div>
|
</div>
|
<el-divider />
|
<div class="section___vePzi">
|
<div class="item___title">
|
<i class="ywifont ywicon-jiankong w-[18px] h-[18px] !text-[20px]"></i>
|
<span>应用信息 </span>
|
</div>
|
<div class="item___txXyB" v-for="(item, index) in state.metricBasicInfo.applicationInformation" :key="index">
|
<div class="item_name">{{ item.name }}:</div>
|
<div class="item_value">
|
{{ item.value }}
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import * as echarts from 'echarts';
|
import { onMounted, reactive, ref } from 'vue';
|
import { useRoute, useRouter } from 'vue-router';
|
import { eDimensionFilter_Ops, eDrilling_Ops } from '/@/views/types/metrics/index';
|
const router = useRouter();
|
const route = useRoute();
|
// 定义变量内容
|
const state = reactive({
|
metricInfo: {
|
name: '',
|
id: '',
|
} as any,
|
activeMetricName: 'indicatorExploration',
|
measurementList: [],
|
metricBasicInfo: {
|
visitNumData: [
|
{
|
name: '敏感度',
|
value: '普通',
|
},
|
{
|
name: '所属模型',
|
value: 'PVUV统计',
|
},
|
{
|
name: '描述',
|
value: '一段时间内用户的访问次数',
|
},
|
],
|
createInformation: [
|
{
|
name: '创建人',
|
value: 'admin',
|
},
|
{
|
name: '创建时间',
|
value: '2024-10-08 10:03:39',
|
},
|
{
|
name: '更新时间',
|
value: '2024-10-08 14:12:11',
|
},
|
],
|
applicationInformation: [
|
{
|
name: '分类',
|
value: '核心指标',
|
},
|
],
|
},
|
exploreForm: {
|
dateRangeExplore: [] as any,
|
dimensionDrilling: 0,
|
dimensionFiltering: {
|
user: '',
|
unit: '',
|
someone: '',
|
},
|
},
|
resultList: [
|
{
|
department: 'HR',
|
},
|
{
|
department: 'marketing',
|
},
|
{
|
department: 'sales',
|
},
|
{
|
department: 'strategy',
|
},
|
],
|
});
|
const shortcuts = [
|
{
|
text: '最近一周',
|
value: () => {
|
const end = new Date();
|
const start = new Date();
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
|
return [start, end];
|
},
|
},
|
{
|
text: '最近一月',
|
value: () => {
|
const end = new Date();
|
const start = new Date();
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
return [start, end];
|
},
|
},
|
{
|
text: '最近三月',
|
value: () => {
|
const end = new Date();
|
const start = new Date();
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
|
return [start, end];
|
},
|
},
|
];
|
|
//返回到知识库列表
|
const handleExitFlow = () => {
|
//是否显示返回
|
router.back();
|
};
|
const handleClick = (val) => {
|
state.activeMetricName = val;
|
};
|
//#endregion
|
//#region ====================== 查询 ======================
|
const handleExplore = () => {
|
console.log(state.exploreForm);
|
};
|
//#endregion
|
//#region ====================== init 图表 ======================
|
const chartExplorationRef = ref(null);
|
|
const initChartExploration = () => {
|
const chartExploration = echarts.init(chartExplorationRef.value);
|
chartExploration.setOption({
|
tooltip: {
|
trigger: 'axis',
|
axisPointer: {
|
type: 'cross',
|
crossStyle: {
|
color: '#999',
|
},
|
},
|
},
|
legend: {
|
data: ['PV', 'UV'],
|
},
|
grid: {
|
left: '3%',
|
right: '4%',
|
bottom: '3%',
|
containLabel: true,
|
},
|
xAxis: [
|
{
|
type: 'category',
|
boundaryGap: false,
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
},
|
],
|
yAxis: [
|
{
|
type: 'value',
|
},
|
],
|
series: [
|
{
|
name: 'PV',
|
type: 'line',
|
stack: '总量',
|
areaStyle: {},
|
data: [120, 132, 101, 134, 90, 230, 210],
|
},
|
{
|
name: 'UV',
|
type: 'line',
|
stack: '总量',
|
areaStyle: {},
|
data: [220, 182, 191, 234, 290, 330, 310],
|
},
|
],
|
});
|
};
|
//#endregion
|
onMounted(() => {
|
const { id, name } = route.query;
|
state.metricInfo.name = name;
|
state.metricInfo.id = id;
|
});
|
</script>
|
<style scoped lang="scss">
|
:deep(.el-tabs__header) {
|
background-color: #fff;
|
border-radius: 8px;
|
}
|
:deep(.el-tabs__content) {
|
height: 100%;
|
background-color: #fff;
|
border-radius: 16px;
|
overflow-y: auto;
|
padding: 10px 20px;
|
box-sizing: border-box;
|
}
|
.set-right-height {
|
padding: 20px;
|
color: #344767;
|
background-color: #fff;
|
height: 100%;
|
border-radius: 6px;
|
.set-visit {
|
box-sizing: border-box;
|
column-gap: 8px;
|
row-gap: 8px;
|
align-items: center;
|
display: inline-flex;
|
font-weight: 600;
|
font-size: 18px;
|
}
|
.set-detail {
|
width: 100%;
|
height: calc(100% - 92px);
|
position: relative;
|
display: flex;
|
flex-direction: column;
|
overflow: scroll;
|
overflow: hidden;
|
background-image: none;
|
border-radius: 6px;
|
.section___vePzi {
|
padding: 0px 16px;
|
color: #344767;
|
line-height: 1.25;
|
background: transparent;
|
box-shadow: none;
|
opacity: 1;
|
.item___title {
|
padding: unset;
|
color: #344767;
|
background: transparent;
|
box-shadow: none;
|
opacity: 1;
|
span {
|
margin-left: 8px;
|
color: #344767;
|
font-weight: 600;
|
font-size: 16px;
|
line-height: 1.625;
|
letter-spacing: 0.0075em;
|
text-transform: capitalize;
|
text-decoration: none;
|
vertical-align: unset;
|
opacity: 1;
|
}
|
}
|
.item___txXyB {
|
display: flex;
|
padding-top: 8px;
|
padding-right: 16px;
|
padding-bottom: 8px;
|
color: #344767;
|
background: transparent;
|
box-shadow: none;
|
opacity: 1;
|
.item_name {
|
min-width: fit-content;
|
margin: 0 10px 0 0;
|
color: #344767;
|
font-weight: 700;
|
font-size: 14px;
|
line-height: 1.5;
|
letter-spacing: 0.02857em;
|
text-transform: capitalize;
|
text-decoration: none;
|
vertical-align: unset;
|
opacity: 1;
|
}
|
.item_value {
|
margin: 0;
|
color: #7b809a;
|
font-weight: 400;
|
font-size: 14px;
|
line-height: 1.5;
|
letter-spacing: 0.02857em;
|
text-transform: none;
|
text-decoration: none;
|
vertical-align: unset;
|
opacity: 1;
|
}
|
}
|
}
|
}
|
}
|
.activeColor {
|
border-color: #0062be;
|
background-color: #f6f5ff;
|
}
|
.list_btn {
|
outline: none;
|
position: absolute;
|
top: 0;
|
right: 0;
|
display: inline-block;
|
font-weight: 400;
|
white-space: nowrap;
|
text-align: center;
|
background-image: none;
|
background-color: transparent;
|
border: 1px solid transparent;
|
cursor: pointer;
|
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
|
user-select: none;
|
touch-action: manipulation;
|
line-height: 1.5714285714285714;
|
margin-top: 5px;
|
margin-right: 6px;
|
}
|
.set_explore {
|
position: relative;
|
overflow: hidden;
|
background-color: #fff;
|
background-image: none;
|
border-radius: 6px;
|
// box-shadow: #888 0 0 1px, #1d293914 0 1px 3px;
|
transition: box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1) 0ms;
|
&_pad {
|
padding: 10px 10px 0px;
|
}
|
}
|
</style>
|