This commit is contained in:
likun 2025-06-11 14:53:27 +08:00
parent ab94e78123
commit c01c90ec32
14 changed files with 393 additions and 8 deletions

12
ui/package-lock.json generated
View File

@ -12,6 +12,7 @@
"element-plus": "^2.9.7",
"pinia": "^3.0.1",
"pinia-plugin-persistedstate": "^4.2.0",
"splitpanes": "^4.0.4",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
},
@ -4766,6 +4767,17 @@
"node": ">=0.10.0"
}
},
"node_modules/splitpanes": {
"version": "4.0.4",
"resolved": "https://registry.npmmirror.com/splitpanes/-/splitpanes-4.0.4.tgz",
"integrity": "sha512-RbysugZhjbCw5fgplvk3hOXr41stahQDtZhHVkhnnJI6H4wlGDhM2kIpbehy7v92duy9GnMa8zIhHigIV1TWtg==",
"funding": {
"url": "https://github.com/sponsors/antoniandre"
},
"peerDependencies": {
"vue": "^3.2.0"
}
},
"node_modules/std-env": {
"version": "3.9.0",
"resolved": "https://registry.npmmirror.com/std-env/-/std-env-3.9.0.tgz",

View File

@ -13,6 +13,7 @@
"element-plus": "^2.9.7",
"pinia": "^3.0.1",
"pinia-plugin-persistedstate": "^4.2.0",
"splitpanes": "^4.0.4",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
},

View File

@ -137,7 +137,7 @@ const userStore = defineStore(
meta: {
desc: "事件分析"
},
component: () => import('@/views/bi/components/event.vue'),
component: () => import('@/views/bi/analyse/event.vue'),
},
{
path: biAnalyseRoutePath + "/analyse/retention",
@ -145,7 +145,63 @@ const userStore = defineStore(
meta: {
desc: "留存分析"
},
component: () => import('@/views/bi/components/retention.vue'),
component: () => import('@/views/bi/analyse/retention.vue'),
},
{
path: biAnalyseRoutePath + "/analyse/retention",
name: biAnalyseRoutePath + "/analyse/retention",
meta: {
desc: "漏斗分析"
},
component: () => import('@/views/bi/analyse/retention.vue'),
},
{
path: biAnalyseRoutePath + "/analyse/retention",
name: biAnalyseRoutePath + "/analyse/retention",
meta: {
desc: "间隔分析"
},
component: () => import('@/views/bi/analyse/retention.vue'),
},
{
path: biAnalyseRoutePath + "/analyse/retention",
name: biAnalyseRoutePath + "/analyse/retention",
meta: {
desc: "分布分析"
},
component: () => import('@/views/bi/analyse/retention.vue'),
},
{
path: biAnalyseRoutePath + "/analyse/retention",
name: biAnalyseRoutePath + "/analyse/retention",
meta: {
desc: "路径分析"
},
component: () => import('@/views/bi/analyse/retention.vue'),
},
{
path: biAnalyseRoutePath + "/analyse/retention",
name: biAnalyseRoutePath + "/analyse/retention",
meta: {
desc: "属性分析"
},
component: () => import('@/views/bi/analyse/retention.vue'),
},
{
path: biAnalyseRoutePath + "/analyse/retention",
name: biAnalyseRoutePath + "/analyse/retention",
meta: {
desc: "归因分析"
},
component: () => import('@/views/bi/analyse/retention.vue'),
},
{
path: biAnalyseRoutePath + "/analyse/retention",
name: biAnalyseRoutePath + "/analyse/retention",
meta: {
desc: "行为序列"
},
component: () => import('@/views/bi/analyse/retention.vue'),
},
],
},
@ -162,7 +218,7 @@ const userStore = defineStore(
meta: {
desc: "事件分析"
},
component: () => import('@/views/bi/components/event.vue'),
component: () => import('@/views/bi/analyse/event.vue'),
},
{
path: biAnalyseRoutePath + "/bi_user/retention",
@ -170,7 +226,7 @@ const userStore = defineStore(
meta: {
desc: "留存分析"
},
component: () => import('@/views/bi/components/retention.vue'),
component: () => import('@/views/bi/analyse/retention.vue'),
},
],
},
@ -187,7 +243,7 @@ const userStore = defineStore(
meta: {
desc: "事件分析"
},
component: () => import('@/views/bi/components/event.vue'),
component: () => import('@/views/bi/analyse/event.vue'),
},
{
path: biAnalyseRoutePath + "/bi_data/retention",
@ -195,7 +251,7 @@ const userStore = defineStore(
meta: {
desc: "留存分析"
},
component: () => import('@/views/bi/components/retention.vue'),
component: () => import('@/views/bi/analyse/retention.vue'),
},
],
},

View File

@ -0,0 +1,52 @@
<script setup>
const timeDivideSelect = [
{
name: "按分钟",
children: [
{name: "1分钟"},
{name: "5分钟"},
{name: "10分钟"},
]
},
{
name: "按小时"
},
{
name: "按天"
},
{
name: "按周"
},
{
name: "按月"
},
{
name: "按季度"
},
{
name: "按年"
},
{
name: "合计"
}
]
</script>
<template>
<div>
<el-select>
<template v-for="item in timeDivideSelect">
<el-option :key="item.name" :label="item.name" :value="item.value" v-if="item.children !== undefined">
<
</el-option>
</template>
</el-select>
</div>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,16 @@
<script setup>
import {defineAsyncComponent} from "vue";
const analyseMainIndex = defineAsyncComponent(() => import('./layout/analyseMainIndex.vue'))
</script>
<template>
<div style="height: 100%">
<analyseMainIndex/>
</div>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,80 @@
<script setup>
import {Splitpanes, Pane} from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
import {defineAsyncComponent} from 'vue';
const contentLeft = defineAsyncComponent(() => import("./analyseMainContentLeft.vue"))
const contentRight = defineAsyncComponent(() => import("./analyseMainContentRight.vue"))
</script>
<template>
<Splitpanes>
<Pane size="25" min-size="20" max-size="30">
<contentLeft/>
</Pane>
<Pane size="75" min-size="70" max-size="80">
<contentRight/>
</Pane>
</Splitpanes>
</template>
<style scoped lang="scss">
:deep(.splitpanes__pane) {
display: flex;
justify-content: center;
align-items: center;
background: white;
box-shadow: 0 0 2px rgba(30, 118, 240, .2) inset;
}
:deep(.splitpanes__splitter) {
position: relative;
background-color: #f0f0f0; /* 拖动线背景色 */
box-sizing: border-box;
/* 为了确保悬停时变粗不会导致布局跳动,可以设置一个透明的边框,悬停时改为实色边框也是一种思路,但这里我们使用伪元素 */
}
:deep(.splitpanes__splitter:before) {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background-color: #ddd;
transition: all 0.3s ease; /* 添加过渡效果 */
}
/* 横向的情况 */
:deep(.splitpanes--horizontal > .splitpanes__splitter:before) {
width: 3px; /* 垂直分割线宽度 */
height: 100%; /* 线的长度,可以根据需要调整 */
}
/* 纵向的情况 */
:deep(.splitpanes--vertical > .splitpanes__splitter:before) {
width: 5px; /* 线的长度 */
height: 100%; /* 水平分割线高度 */
}
/* 鼠标悬停在拖动线上时的样式 */
:deep(.splitpanes__splitter:hover:before) {
width: 4px;
background-color: #3498db; /* 变为蓝色 */
}
/* 对于横向分割线,悬停时变粗 */
:deep(.splitpanes--horizontal > .splitpanes__splitter:hover:before) {
width: 3px; /* 加粗 */
height: 100%; /* 也可以加长 */
}
/* 对于纵向分割线,悬停时变粗 */
:deep(.splitpanes--vertical > .splitpanes__splitter:hover:before) {
width: 5px;
height: 100%;
}
</style>

View File

@ -0,0 +1,13 @@
<script setup>
</script>
<template>
<div class="content pane-left">
左边部分
</div>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,36 @@
<script setup>
import {defineAsyncComponent} from 'vue';
const layoutToolbar = defineAsyncComponent(() => import("./analyseMainContentRightToolbar.vue"))
const layoutResult = defineAsyncComponent(() => import("./analyseMainContentRightResult.vue"))
</script>
<template>
<div class="result">
<div class="resultToolbar">
<layoutToolbar/>
</div>
<div class="resultContent">
<layoutResult/>
</div>
</div>
</template>
<style scoped lang="scss">
.result {
height: 100%;
width: 100%;
}
.resultToolbar {
height: 60px;
width: 100%;
border-bottom: 1px solid #f0f2f5;
}
.resultContent {
height: calc(100% - 60px);
}
</style>

View File

@ -3,7 +3,7 @@
</script>
<template>
事件分析
结果
</template>
<style scoped>

View File

@ -0,0 +1,11 @@
<script setup>
</script>
<template>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,64 @@
<script setup>
</script>
<template>
<el-col :span="6">
<div class="headerAnalyseDesc">
<p style="margin-right: 6px;font-weight: bold">事件分析</p>
<el-icon size="20">
<Warning/>
</el-icon>
</div>
</el-col>
<el-col :span="10" :offset="8">
<div class="headerAnalyseToolbar" style="display: flex;float:right">
<span class="toolbarSpan">
<p>近似计算</p>
</span>
<span class="toolbarSpan">
<el-switch></el-switch>
</span>
<span class="toolbarSpan">
<el-dropdown>
<el-button>
UTC +8
</el-button>
</el-dropdown>
</span>
<span class="toolbarSpan">
<el-icon size="20">
<Refresh/>
</el-icon>
</span>
<span class="toolbarSpan">
<el-icon size="20">
<Download/>
</el-icon>
</span>
<span class="toolbarSpan">
<el-button>已存报表</el-button>
</span>
</div>
</el-col>
</template>
<style scoped lang="scss">
.headerAnalyseDesc {
display: flex;
float: left;
justify-content: center;
align-items: center;
}
.headerAnalyseToolbar {
display: flex;
float: right;
justify-content: center;
align-items: center;
.toolbarSpan {
margin-left: 10px;
}
}
</style>

View File

@ -0,0 +1,38 @@
<script setup>
import {defineAsyncComponent} from 'vue';
const layoutHeader = defineAsyncComponent(() => import("./analyseMainHeader.vue"))
const layoutContent = defineAsyncComponent(() => import("./analyseMainContent.vue"))
</script>
<template>
<div class="analyseMain">
<el-row class="analyseMainHeader">
<layoutHeader/>
</el-row>
<el-row class="analyseMainContent">
<layoutContent/>
</el-row>
</div>
</template>
<style scoped lang="scss">
.analyseMain {
height: 100%;
//border: 1px solid black;
}
.analyseMainHeader {
height: 60px;
background-color: #f0f2f5;
}
.analyseMainContent {
height: calc(100% - 60px);
display: flex;
}
</style>

View File

@ -8,17 +8,23 @@ const route = useRoute()
<template>
<el-main class="bi_main">
<router-view :key="$route.fullPath"></router-view>
<router-view :key="$route.fullPath"
style="display: inline-block;height: 100%;width: 100%;"></router-view>
</el-main>
</template>
<style scoped lang="scss">
.bi_main {
display: flex;
min-height: 500px;
margin: 0;
margin-top: 10px;
padding: 0;
background-color: white;
height: calc(100vh - 110px);
//height: 100%;
//border: 1px solid gray;
}
</style>