From 6f4c46999ea691f1adec5c38fe0333fd7f066f86 Mon Sep 17 00:00:00 2001 From: songjie Date: Sat, 24 Jan 2026 13:47:26 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=90=84=E5=9C=B0=E5=8C=BA?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E6=B4=BB=E8=B7=83=E6=9F=B1=E7=8A=B6=E5=9B=BE?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=8E=A5=E5=8F=A3=E5=AF=B9=E6=8E=A5=E5=AE=8C?= =?UTF-8?q?=E6=88=90=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/platformData.js | 22 +++++ src/views/PlatformData/UserLoginStats.vue | 130 +++++++++++++++++++++++++++++- 2 files changed, 150 insertions(+), 2 deletions(-) diff --git a/src/api/platformData.js b/src/api/platformData.js index 1968c17..7721f2f 100644 --- a/src/api/platformData.js +++ b/src/api/platformData.js @@ -132,3 +132,25 @@ export function getRegionActiveData(params) { data: formData }) } + +// 获取各地区登录活跃柱状图数据 +export function getRegionActiveDataHistogram(params) { + const formData = new FormData(); + formData.append('token', localStorage.getItem('token')); + if (params) { + if (params.start_time) formData.append('start_time', params.start_time); + if (params.end_time) formData.append('end_time', params.end_time); + } + + return request({ + url: 'http://d9a962ee.natappfree.cc/admin/user/login/statistics/regionActiveDataHistogram', + method: 'post', + headers: { + 'token': localStorage.getItem('token'), + 'client': 'ios', + 'version': '1', + 'Content-Type': 'multipart/form-data' + }, + data: formData + }) +} diff --git a/src/views/PlatformData/UserLoginStats.vue b/src/views/PlatformData/UserLoginStats.vue index da633f7..5504e3e 100644 --- a/src/views/PlatformData/UserLoginStats.vue +++ b/src/views/PlatformData/UserLoginStats.vue @@ -193,7 +193,7 @@
各地区日活跃用户 - 切换 + 切换
@@ -223,7 +223,7 @@ import { ref, onMounted, nextTick, watch } from 'vue'; import { useRoute, useRouter } from 'vue-router'; import * as echarts from 'echarts'; -import { getUserLoginList, getUserLoginTrend, getRegionActiveData } from '../../api/platformData'; +import { getUserLoginList, getUserLoginTrend, getRegionActiveData, getRegionActiveDataHistogram } from '../../api/platformData'; const route = useRoute(); const router = useRouter(); @@ -237,10 +237,14 @@ const dateRangeRegion = ref(''); const chartTrendRef = ref(null); let chartTrendInstance = null; const chartRegionBarRef = ref(null); +let chartRegionBarInstance = null; const chartRegionPieRef = ref(null); const chartRegionMemberPieRef = ref(null); const chartRegionNonMemberPieRef = ref(null); +// 柱状图显示模式:'all' (全部用户), 'detail' (分身份用户) +const barChartMode = ref('all'); + // 响应式数据:地区活跃数据 const regionalTableData1 = ref([]); const regionalTableData2 = ref([]); @@ -486,6 +490,125 @@ const fetchRegionActiveData = async () => { } }; +const fetchRegionHistogramData = async () => { + let params = {}; + if (dateRangeRegion.value && dateRangeRegion.value.length === 2) { + params.start_time = formatDate(dateRangeRegion.value[0]); + params.end_time = formatDate(dateRangeRegion.value[1]); + } + + try { + const res = await getRegionActiveDataHistogram(params); + console.log("获取地区活跃柱状图数据响应:", res); + + // 兼容处理拦截器 + const data = res.region_active_data_histogram ? res : (res.data && res.data.region_active_data_histogram ? res.data : null); + + if (data && data.region_active_data_histogram) { + updateRegionBarChart(data.region_active_data_histogram); + } + } catch (e) { + console.error('获取地区活跃柱状图数据失败:', e); + } +}; + +const updateRegionBarChart = (list) => { + if (!chartRegionBarRef.value) return; + + if (!chartRegionBarInstance) { + chartRegionBarInstance = echarts.init(chartRegionBarRef.value); + } + + const regions = list.map(item => item.region); + const series = []; + const legendData = []; + + if (barChartMode.value === 'all') { + legendData.push('日活跃用户', '周活跃用户', '月活跃用户'); + series.push( + { name: '日活跃用户', type: 'bar', data: list.map(item => item.daily_active_user), itemStyle: { color: '#40a9ff' } }, + { name: '周活跃用户', type: 'bar', data: list.map(item => item.weekly_active_user), itemStyle: { color: '#52c41a' } }, + { name: '月活跃用户', type: 'bar', data: list.map(item => item.monthly_active_user), itemStyle: { color: '#BC943D' } } + ); + } else { + legendData.push('日活跃会员', '日活跃非网', '周活跃会员', '周活跃非网', '月活跃会员', '月活跃非网'); + + // 使用 stack 属性将会员和非会员数据堆叠在一起 + // 日活跃 + series.push( + { + name: '日活跃会员', + type: 'bar', + stack: 'daily', + data: list.map(item => item.member_daily_active), + itemStyle: { color: '#91D5FF' } // 浅蓝 + }, + { + name: '日活跃非网', + type: 'bar', + stack: 'daily', + data: list.map(item => item.no_member_daily_active), + itemStyle: { color: '#40a9ff' } // 深蓝 + } + ); + + // 周活跃 + series.push( + { + name: '周活跃会员', + type: 'bar', + stack: 'weekly', + data: list.map(item => item.member_weekly_active), + itemStyle: { color: '#95de64' } // 浅绿 + }, + { + name: '周活跃非网', + type: 'bar', + stack: 'weekly', + data: list.map(item => item.no_member_weekly_active), + itemStyle: { color: '#52c41a' } // 深绿 + } + ); + + // 月活跃 + series.push( + { + name: '月活跃会员', + type: 'bar', + stack: 'monthly', + data: list.map(item => item.member_monthly_active), + itemStyle: { color: '#FFC53D' } // 浅橙 + }, + { + name: '月活跃非网', + type: 'bar', + stack: 'monthly', + data: list.map(item => item.no_member_monthly_active), + itemStyle: { color: '#BC943D' } // 深棕 + } + ); + } + + const option = { + tooltip: { trigger: 'item' }, // 之前需求:取消十字线显示,改为item + legend: { data: legendData, top: 'top' }, + xAxis: { + type: 'category', + data: regions, + axisLabel: { interval: 0, rotate: 30 } // 防止标签重叠 + }, + yAxis: { type: 'value' }, + series: series + }; + + chartRegionBarInstance.setOption(option, true); // true: not merge, reset +}; + +const toggleBarChartMode = () => { + barChartMode.value = barChartMode.value === 'all' ? 'detail' : 'all'; + fetchRegionHistogramData(); +}; + const handleSearchRegion = () => { // 更新 URL 参数 const query = { ...route.query }; @@ -507,6 +630,7 @@ const handleSearchRegion = () => { router.replace({ query }); fetchRegionActiveData(); + fetchRegionHistogramData(); }; const handleResetRegion = () => { @@ -521,6 +645,7 @@ const handleResetRegion = () => { router.replace({ query }); fetchRegionActiveData(); + fetchRegionHistogramData(); }; // Tab 1 数据 @@ -566,6 +691,7 @@ const initCharts = () => { fetchLoginData(); } else if (activeTab.value === 'regionalData') { fetchRegionActiveData(); + fetchRegionHistogramData(); // 柱状图 if (chartRegionBarRef.value) { const chart = echarts.init(chartRegionBarRef.value);