feat(数据分析): 重构客户问题排行榜和客户类型图表数据处理

- 将客户问题排行榜数据从静态数据改为基于API响应的计算属性
- 重构客户类型图表数据处理逻辑,支持按省份聚合地域数据
- 将客户类型图表从柱状图改为饼图,优化数据显示效果
This commit is contained in:
2025-08-18 12:00:11 +08:00
parent ca3df35ff9
commit 80f4d82a75
2 changed files with 215 additions and 36 deletions

View File

@@ -40,10 +40,133 @@ const chartData = computed(() => {
return [] return []
} }
return props.customerData.customer_type_distribution.map(item => ({ let processedData = props.customerData.customer_type_distribution.map(item => ({
name: item.category, name: item.category,
value: parseFloat(item.ratio.replace('%', '')) || 0 value: parseFloat(item.ratio.replace('%', '')) || 0
})) }))
// 如果是地域类型,需要按省份进行数据整理
if (customerTypeCategory.value === 'region') {
const provinceMap = new Map()
processedData.forEach(item => {
// 提取省份名称,处理"山东省 临沂市 莒南县"这种空格分隔的格式
let provinceName = item.name
// 处理空格分隔的地域数据格式(如:"山东省 临沂市 莒南县"
if (item.name.includes(' ')) {
const parts = item.name.split(' ')
provinceName = parts[0] // 取第一部分作为省份
}
// 处理横线分隔的格式
else if (item.name.includes('-')) {
provinceName = item.name.split('-')[0]
}
// 处理包含省字的格式
else if (item.name.includes('省') || item.name.includes('市') || item.name.includes('区')) {
// 如果已经包含省份标识,直接使用
if (item.name.includes('省') || item.name.includes('自治区') || item.name.endsWith('市')) {
provinceName = item.name
} else {
// 根据城市名推断省份
const cityToProvince = {
'北京': '北京市',
'上海': '上海市',
'天津': '天津市',
'重庆': '重庆市',
'广州': '广东省',
'深圳': '广东省',
'珠海': '广东省',
'佛山': '广东省',
'东莞': '广东省',
'中山': '广东省',
'杭州': '浙江省',
'宁波': '浙江省',
'温州': '浙江省',
'南京': '江苏省',
'苏州': '江苏省',
'无锡': '江苏省',
'常州': '江苏省',
'成都': '四川省',
'绵阳': '四川省',
'武汉': '湖北省',
'宜昌': '湖北省',
'西安': '陕西省',
'郑州': '河南省',
'洛阳': '河南省',
'济南': '山东省',
'青岛': '山东省',
'烟台': '山东省',
'潍坊': '山东省',
'临沂': '山东省',
'大连': '辽宁省',
'沈阳': '辽宁省',
'长春': '吉林省',
'哈尔滨': '黑龙江省',
'石家庄': '河北省',
'唐山': '河北省',
'太原': '山西省',
'呼和浩特': '内蒙古自治区',
'南宁': '广西壮族自治区',
'桂林': '广西壮族自治区',
'海口': '海南省',
'三亚': '海南省',
'昆明': '云南省',
'贵阳': '贵州省',
'拉萨': '西藏自治区',
'兰州': '甘肃省',
'西宁': '青海省',
'银川': '宁夏回族自治区',
'乌鲁木齐': '新疆维吾尔自治区',
'合肥': '安徽省',
'芜湖': '安徽省',
'福州': '福建省',
'厦门': '福建省',
'泉州': '福建省',
'南昌': '江西省',
'长沙': '湖南省',
'株洲': '湖南省',
// 港澳台地区
'香港': '香港特别行政区',
'澳门': '澳门特别行政区',
'台北': '台湾省',
'高雄': '台湾省',
'台中': '台湾省',
'台南': '台湾省',
'桃园': '台湾省',
'新竹': '台湾省',
'基隆': '台湾省',
'嘉义': '台湾省',
'台东': '台湾省',
'花莲': '台湾省',
'宜兰': '台湾省',
'屏东': '台湾省',
'彰化': '台湾省',
'南投': '台湾省',
'云林': '台湾省',
'苗栗': '台湾省',
'澎湖': '台湾省'
}
provinceName = cityToProvince[item.name] || item.name
}
}
// 聚合同一省份的数据
if (provinceMap.has(provinceName)) {
provinceMap.set(provinceName, provinceMap.get(provinceName) + item.value)
} else {
provinceMap.set(provinceName, item.value)
}
})
// 转换为数组格式
processedData = Array.from(provinceMap.entries()).map(([name, value]) => ({
name,
value
}))
}
return processedData
}) })
const updateChart = () => { const updateChart = () => {
@@ -70,37 +193,47 @@ const updateChart = () => {
} }
const option = { const option = {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'item',
axisPointer: { type: 'shadow' },
formatter: function(params) { formatter: function(params) {
return params[0].name + '<br/>' + params[0].seriesName + ': ' + params[0].value + '%' return params.name + '<br/>' + '占比: ' + params.value + '%' + ' (' + params.percent + '%)'
} }
}, },
grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, legend: {
xAxis: { orient: 'vertical',
type: 'category', left: 'left',
data: currentData.map(item => item.name), top: 'center',
axisTick: { alignWithLabel: true }, textStyle: {
axisLabel: { fontSize: 12
interval: 0,
rotate: currentData.length > 5 ? 45 : 0
}
},
yAxis: {
type: 'value',
axisLabel: {
formatter: '{value}%'
} }
}, },
series: [{ series: [{
name: '占比', name: '客户类型占比',
type: 'bar', type: 'pie',
barWidth: '60%', radius: ['40%', '70%'],
data: currentData.map(item => item.value), center: ['65%', '50%'],
itemStyle: { avoidLabelOverlap: false,
color: (params) => ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de'][params.dataIndex % 5] label: {
} show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '16',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: currentData.map((item, index) => ({
name: item.name,
value: item.value,
itemStyle: {
color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#fc8452', '#9a60b4'][index % 7]
}
}))
}] }]
}; };
customerTypeChart.setOption(option, true); customerTypeChart.setOption(option, true);

View File

@@ -280,16 +280,18 @@ const customerTypeData = ref([
{ name: "55岁以上", value: 50 }, { name: "55岁以上", value: 50 },
]); ]);
// 客户问题排行榜数据 // 客户问题排行榜数据 - 计算属性将API数据转换为组件所需格式
const problemRankingData = ref([ const problemRankingData = computed(() => {
{ name: "提高学习成绩", value: "65%" }, if (!customerUrgency.value || !customerUrgency.value.company_urgent_issue_ratio) {
{ name: "课程费用咨询", value: "58%" }, return []
{ name: "师资力量了解", value: "52%" }, }
{ name: "时间安排问题", value: "48%" },
{ name: "学习兴趣培养", value: "42%" }, const ratioData = customerUrgency.value.company_urgent_issue_ratio
{ name: "学习方法指导", value: "38%" }, return Object.entries(ratioData).map(([name, value]) => ({
{ name: "课程内容详情", value: "35%" }, name,
]); value
}))
})
// 表格数据和筛选 // 表格数据和筛选
const tableData = ref([ const tableData = ref([
@@ -1027,6 +1029,50 @@ async function getCustomerUrgency() {
const res = await getUrgentNeedToAddress() const res = await getUrgentNeedToAddress()
console.log(1222222,res) console.log(1222222,res)
customerUrgency.value = res.data customerUrgency.value = res.data
/**
* data
:
company_urgent_issue_counts
:
回归学校
:
2
少玩手机
:
6
心理健康
:
0
成绩提升
:
8
[[Prototype]]
:
Object
company_urgent_issue_ratio
:
回归学校
:
"12.50%"
少玩手机
:
"37.50%"
心理健康
:
"0.00%"
成绩提升
:
"50.00%"
[[Prototype]]
:
Object
user_level
:
5
user_name
:
"赵世敬"
*/
} catch (error) { } catch (error) {
console.error("获取客户迫切解决的问题排行榜失败:", error); console.error("获取客户迫切解决的问题排行榜失败:", error);
} }