fix: 修复表单数据处理和API端点问题

修复RawDataCards和CustomerDetail组件中表单数据的默认值和类型定义
更新getTodayCall API端点路径为current_camp_call
调整sale.vue中表单数据处理逻辑以适应新API响应格式
优化PerformanceComparison组件的数据处理逻辑
修改开发环境API基础路径为本地测试地址
This commit is contained in:
2025-10-22 14:57:28 +08:00
parent 10c8c7b796
commit 094f655634
8 changed files with 111 additions and 126 deletions

View File

@@ -60,42 +60,41 @@ import { ref, computed, onMounted, watch } from 'vue';
// 假设你有一个API服务来获取对比数据
// import { getPerformanceComparisonData } from '@/api/senorManger.js';
// 模拟API调用
// **MODIFIED**: 更新模拟API以返回新的数据结构
const getPerformanceComparisonData = async (params) => {
console.log('模拟API请求:', params);
console.log('模拟API请求 (新数据结构):', params);
return new Promise(resolve => {
setTimeout(() => {
// 模拟不同周期返回不同数据
let mockData;
if (params.period === 'last_week') {
mockData = {
assignedLeads: 480,
wechatAdds: 390,
calls: 1450,
callDuration: 11500,
deposits: 38,
deals: 50,
conversionRate: 10.4,
"allocated_data_volume": 650,
"wechat_added_volume": 410,
"call_volume_after_classification": { "加微通话": 10, "20分钟通话": 50, "未分类": 150, "无效通话": 100, "促到课": 40 },
"call_avg_duration_after_classification": { "加微通话": 4.5, "20分钟通话": 15.0, "未分类": 1.5, "无效通话": 1.0, "促到课": 2.0 },
"deposit_volume": 40,
"transaction_volume": 52,
"conversion_rate": "8.00%"
};
} else if (params.period === 'last_month') {
mockData = {
assignedLeads: 2000,
wechatAdds: 1500,
calls: 5800,
callDuration: 48000,
deposits: 150,
deals: 210,
conversionRate: 10.5,
"allocated_data_volume": 2800,
"wechat_added_volume": 1800,
"call_volume_after_classification": { "加微通话": 40, "20分钟通话": 220, "未分类": 600, "视频通话": 50, "无效通话": 450, "促到课": 180 },
"call_avg_duration_after_classification": { "加微通话": 5.0, "20分钟通话": 16.0, "未分类": 1.8, "视频通话": 6.0, "无效通话": 1.1, "促到课": 1.5 },
"deposit_volume": 180,
"transaction_volume": 230,
"conversion_rate": "8.21%"
};
} else {
} else { // last_quarter
mockData = {
assignedLeads: 6500,
wechatAdds: 5200,
calls: 18000,
callDuration: 150000,
deposits: 450,
deals: 600,
conversionRate: 9.2,
"allocated_data_volume": 8500,
"wechat_added_volume": 5500,
"call_volume_after_classification": { "加微通话": 120, "20分钟通话": 650, "未分类": 1800, "视频通话": 150, "无效通话": 1200, "促到课": 500 },
"call_avg_duration_after_classification": { "加微通话": 4.8, "20分钟通话": 16.5, "未分类": 1.7, "视频通话": 5.5, "无效通话": 1.0, "促到课": 1.8 },
"deposit_volume": 550,
"transaction_volume": 700,
"conversion_rate": "8.24%"
};
}
resolve({ code: 200, data: mockData });
@@ -125,12 +124,11 @@ const selectedPeriodLabel = computed(() => periodLabels[selectedPeriod.value]);
const fetchComparisonData = async () => {
isLoading.value = true;
try {
// 真实场景中这里应该调用API
const res = await getPerformanceComparisonData({ period: selectedPeriod.value });
if (res.code === 200) {
previousPeriodData.value = res.data;
} else {
previousPeriodData.value = null; // API出错或无数据
previousPeriodData.value = null;
}
} catch (error) {
console.error('获取对比数据失败:', error);
@@ -144,14 +142,54 @@ onMounted(() => {
fetchComparisonData();
});
// 如果本期数据可能变化可以监听props来刷新
watch(() => props.currentPeriodData, () => {
fetchComparisonData();
}, { deep: true });
// **NEW**: 新增一个工具函数用于处理API返回的复杂数据结构
// 并将其转换为表格渲染所需的扁平化结构
const processRawData = (rawData) => {
if (!rawData) return null;
// 1. 计算通话总量
const totalCalls = Object.values(rawData.call_volume_after_classification || {})
.reduce((sum, count) => sum + count, 0);
// 2. 计算通话总时长 (分钟)
// 逻辑: (分类通话数 * 分类平均时长) 的总和
const callVolumes = rawData.call_volume_after_classification || {};
const avgDurations = rawData.call_avg_duration_after_classification || {};
const totalDurationInMinutes = Object.keys(callVolumes).reduce((sum, key) => {
const volume = callVolumes[key] || 0;
const avgDuration = avgDurations[key] || 0;
return sum + (volume * avgDuration);
}, 0);
// 3. 将转化率字符串 "7.98%" 转为数字 7.98
const conversionRateValue = parseFloat(rawData.conversion_rate) || 0;
// 4. 返回一个与旧版组件兼容的对象结构
return {
assignedLeads: rawData.allocated_data_volume,
wechatAdds: rawData.wechat_added_volume,
calls: totalCalls,
// 组件内部格式化时会除以60因此这里需要乘以60将分钟转为秒
callDuration: totalDurationInMinutes * 60,
deposits: rawData.deposit_volume,
deals: rawData.transaction_volume,
conversionRate: conversionRateValue,
};
};
const comparedMetrics = computed(() => {
if (!props.currentPeriodData || !previousPeriodData.value) return [];
// **MODIFIED**: 在计算前,先使用 processRawData 对数据进行处理
const processedCurrentData = processRawData(props.currentPeriodData);
const processedPreviousData = processRawData(previousPeriodData.value);
if (!processedCurrentData || !processedPreviousData) return [];
// 指标配置保持不变,因为数据已经被处理成它期望的格式
const metricsConfig = [
{ key: 'assignedLeads', label: '分配数据量', unit: '个' },
{ key: 'wechatAdds', label: '加微量', unit: '个' },
@@ -163,8 +201,8 @@ const comparedMetrics = computed(() => {
];
return metricsConfig.map(metric => {
const current = props.currentPeriodData[metric.key];
const previous = previousPeriodData.value[metric.key];
const current = processedCurrentData[metric.key];
const previous = processedPreviousData[metric.key];
return {
...metric,
current,
@@ -198,6 +236,7 @@ const calculateChange = (current, previous) => {
const formatValue = (value, unit) => {
if (value === null || value === undefined) return '-';
if (unit === '分钟') {
// 假设传入的value是秒转换为分钟显示
return `${Math.round(value / 60)} 分钟`;
}
if (unit === '%') {
@@ -212,6 +251,7 @@ const formatChange = (diff, unit) => {
const absDiff = Math.abs(diff);
if (unit === '分钟') {
// 假设diff是秒转换为分钟显示
return `${prefix}${Math.round(absDiff / 60)} 分钟`;
}
if (unit === '%') {
@@ -229,12 +269,12 @@ const getChangeClass = (trend) => {
</script>
<style lang="scss" scoped>
/* 样式部分无需改动,因此省略以保持简洁 */
.performance-comparison {
background: #ffffff;
border-radius: 12px;
padding: 2rem;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
margin-top: 1.5rem;
border: 1px solid #e2e8f0;
}
@@ -242,7 +282,6 @@ const getChangeClass = (trend) => {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 1px solid #f1f5f9;

View File

@@ -64,6 +64,10 @@
:severeTimeoutRate="statisticalIndicators.severeTimeoutRate"
:formCompletionRate="statisticalIndicators.formCompletionRate"
/>
<!-- 新增业绩周期对比组件 -->
<div v-if="cardVisibility.performanceComparison" class="performance-comparison-section">
<PerformanceComparison :current-period-data="currentPeriodMetrics" />
</div>
<!-- Bottom Section -->
<div class="bottom-section">
<!-- Left Section - Group Performance Ranking -->
@@ -90,10 +94,7 @@
</div>
</div>
<!-- 新增业绩周期对比组件 -->
<div v-if="cardVisibility.performanceComparison" class="performance-comparison-section">
<PerformanceComparison :current-period-data="currentPeriodMetrics" />
</div>
<!-- Team Members Detail Section -->
<div class="team-detail-section" v-if="selectedGroup && cardVisibility.teamDetail">
@@ -996,10 +997,6 @@ const hideTooltip = () => {
overflow: auto;
}
/* 新增 */
.performance-comparison-section {
margin-top: 1rem;
}
.action-items-compact {
overflow: hidden;