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);