diff --git a/src/api/platformData.js b/src/api/platformData.js index 8e88642..acab3b7 100644 --- a/src/api/platformData.js +++ b/src/api/platformData.js @@ -224,6 +224,30 @@ export function getRegionActiveDataHistogram(params) { }) } +// 获取各地区用户分布(饼图) +export function getRegionUserDistribution(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); + // identity: 0:全部 1:会员 2:非网 (可不传,默认全部) + if (params.identity !== undefined) formData.append('identity', params.identity); + } + + return request({ + url: 'http://d9a962ee.natappfree.cc/admin/user/login/statistics/regionUserDistribution', + method: 'post', + headers: { + 'token': localStorage.getItem('token'), + 'client': 'ios', + 'version': '1', + 'Content-Type': 'multipart/form-data' + }, + data: formData + }) +} + // 获取DeepChart用户活跃度趋势 export function getUserDeepChartTrend(params) { const formData = new FormData(); diff --git a/src/views/PlatformData/UserLoginStats.vue b/src/views/PlatformData/UserLoginStats.vue index 8a23928..7b2b0a0 100644 --- a/src/views/PlatformData/UserLoginStats.vue +++ b/src/views/PlatformData/UserLoginStats.vue @@ -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, getRegionActiveDataHistogram, getUserLoginChannel, getUserLoginChannelMember, getUserLoginChannelNoMember } from '../../api/platformData'; +import { getUserLoginList, getUserLoginTrend, getRegionActiveData, getRegionActiveDataHistogram, getUserLoginChannel, getUserLoginChannelMember, getUserLoginChannelNoMember, getRegionUserDistribution } from '../../api/platformData'; const route = useRoute(); const router = useRouter(); @@ -562,7 +562,8 @@ const fetchAllRegionData = async () => { try { await Promise.all([ fetchRegionActiveData(), - fetchRegionHistogramData() + fetchRegionHistogramData(), + fetchRegionDistributionData() ]); } catch (error) { console.error('获取地区数据失败:', error); @@ -736,6 +737,81 @@ const toggleBarChartMode = () => { fetchRegionHistogramData(); }; +const fetchRegionDistributionData = 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 [resAll, resMember, resNormal] = await Promise.all([ + getRegionUserDistribution({ ...params, identity: 0 }), + getRegionUserDistribution({ ...params, identity: 1 }), + getRegionUserDistribution({ ...params, identity: 2 }) + ]); + + console.log("获取地区分布数据响应:", { resAll, resMember, resNormal }); + + const processData = (res) => { + const data = res.region_user_distribution ? res : (res.data && res.data.region_user_distribution ? res.data : null); + if (data && data.region_user_distribution) { + return data.region_user_distribution.map(item => ({ + name: item.region, + value: item.total + })).filter(item => item.value > 0); // 过滤掉值为0的项,使饼图更美观 + } + return []; + }; + + updatePieChart(chartRegionPieRef, chartRegionPieInstance, processData(resAll)); + updatePieChart(chartRegionMemberPieRef, chartRegionMemberPieInstance, processData(resMember)); + updatePieChart(chartRegionNonMemberPieRef, chartRegionNonMemberPieInstance, processData(resNormal)); + + } catch (e) { + console.error('获取地区分布数据失败:', e); + } +}; + +let chartRegionPieInstance = null; +let chartRegionMemberPieInstance = null; +let chartRegionNonMemberPieInstance = null; + +const updatePieChart = (chartRef, chartInstance, data) => { + if (!chartRef.value) return; + + let instance = chartInstance; + if (!instance) { + // 如果没有传入实例,尝试获取或初始化 (注意:这里需要正确维护全局实例变量) + // 简单起见,这里总是重新获取echarts实例,或者通过DOM属性判断 + instance = echarts.getInstanceByDom(chartRef.value); + if (!instance) { + instance = echarts.init(chartRef.value); + } + } + + const option = { + color: regionColors, + tooltip: { trigger: 'item' }, + legend: { orient: 'vertical', right: '0%', top: 'center', itemWidth: 10, itemHeight: 10, textStyle: { fontSize: 10 } }, + series: [ + { + type: 'pie', + radius: '70%', + center: ['30%', '50%'], + data: data, + label: { show: false }, + itemStyle: { + borderRadius: 0, + borderColor: '#fff', + borderWidth: 2 + }, + } + ] + }; + instance.setOption(option); +}; + const handleSearchRegion = () => { // 更新 URL 参数 const query = { ...route.query };