|
|
|
@ -193,7 +193,7 @@ |
|
|
|
<!-- 图表: 各地区日活跃用户 --> |
|
|
|
<div class="chart-section"> |
|
|
|
<div class="section-title"><el-icon><BarChart /></el-icon> 各地区日活跃用户 |
|
|
|
<el-button size="small" style="margin-left: auto;">切换</el-button> |
|
|
|
<el-button size="small" style="margin-left: auto;" @click="toggleBarChartMode">切换</el-button> |
|
|
|
</div> |
|
|
|
<div ref="chartRegionBarRef" class="chart-box-large"></div> |
|
|
|
</div> |
|
|
|
@ -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); |
|
|
|
|