Files
DJKB/my-vue-app/src/views/senorManger/components/CenterOverview.vue
lbw_9527443 9d52b99414 refactor: 移除调试用的console.log语句
清理多个组件和工具文件中用于调试的console.log语句,保持代码整洁
2025-11-25 15:31:40 +08:00

474 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="center-overview">
<div class="overview-header">
<h2>整体概览</h2>
<div class="stats-toggle">
<button
:class="['toggle-btn', { active: statsMode === 'monthly' }]"
@click="switchStatsMode('monthly')"
>
按月统计
</button>
<button
:class="['toggle-btn', { active: statsMode === 'period' }]"
@click="switchStatsMode('period')"
>
按期统计
</button>
</div>
</div>
<div class="overview-grid">
<div class="overview-card primary">
<div class="card-header">
<span class="card-title">
团队总业绩
<span class="info-icon" @mouseenter="showTooltip($event, 'teamPerformance')" @mouseleave="hideTooltip"></span>
</span>
<span class="card-trend positive">{{ totalPerformance.team_current_vs_previous_period_deals_comparison }} vs 上期</span>
</div>
<div class="card-value">{{ totalPerformance.current_team_odd_numbers||0 }}</div>
<div class="card-subtitle">月目标完成率: {{ totalPerformance.team_monthly_target_completion_rate }}</div>
</div>
<div class="overview-card">
<div class="card-header">
<span class="card-title">
活跃组数
<span class="info-icon" @mouseenter="showTooltip($event, 'activeGroups')" @mouseleave="hideTooltip"></span>
</span>
<span class="card-trend stable">{{ activeGroups.total_group_count }}/{{ activeGroups.total_group_count }} </span>
</div>
<div class="card-value">{{ activeGroups.total_group_count }} </div>
<div class="card-subtitle">总人数: {{ activeGroups.total_user_count }}</div>
</div>
<div class="overview-card">
<div class="card-header">
<span class="card-title">
团队转化率
<span class="info-icon" @mouseenter="showTooltip($event, 'conversionRate')" @mouseleave="hideTooltip"></span>
</span>
<span class="card-trend positive">{{ conversionRate.team_current_vs_previous_conversion_rate }} vs 上期</span>
</div>
<div class="card-value">{{ conversionRate.center_conversion_rate }}</div>
<div class="card-subtitle">团队平均转化率: {{ conversionRate.average_conversion_rate }}</div>
</div>
<div class="overview-card">
<div class="card-header">
<span class="card-title">
总通话次数
<span class="info-icon" @mouseenter="showTooltip($event, 'totalCalls')" @mouseleave="hideTooltip"></span>
</span>
<span class="card-trend positive">{{ totalCalls.total_call_count_vs_yesterday }} vs 上期</span>
</div>
<div class="card-value">{{ totalCalls.total_call_count }}</div>
<div class="card-subtitle">有效通话: {{ totalCalls.effective_call_count }}</div>
</div>
<div class="overview-card">
<div class="card-header">
<span class="card-title">
新增客户
<span class="info-icon" @mouseenter="showTooltip($event, 'newCustomers')" @mouseleave="hideTooltip"></span>
</span>
<span class="card-trend positive">{{ newCustomers.new_customer_vs_yesterday }} vs 上期</span>
</div>
<div class="card-value">{{ newCustomers.new_customer }} </div>
<div class="card-subtitle">意向客户: {{ newCustomers.new_v_customer }}</div>
</div>
<div class="overview-card">
<div class="card-header">
<span class="card-title">
定金转化
<span class="info-icon" @mouseenter="showTooltip($event, 'depositConversion')" @mouseleave="hideTooltip"></span>
</span>
<span class="card-trend positive">{{ depositConversions.deposit_conversion_vs_previous }} vs 上期</span>
</div>
<div class="card-value">{{ depositConversions.current_deposit_conversion_rate }}</div>
<div class="card-subtitle">本月定金转化率: {{ depositConversions.monthly_deposit_conversion_rate }}</div>
</div>
</div>
<!-- Tooltip 组件 -->
<Tooltip
:visible="tooltip.visible"
:x="tooltip.x"
:y="tooltip.y"
:title="tooltip.title"
:description="tooltip.description"
/>
</div>
</template>
<script setup>
import { computed, reactive, ref } from 'vue'
import Tooltip from '@/components/Tooltip.vue'
// 统计模式状态
const statsMode = ref('monthly') // 默认按月统计
// 定义emit事件
const emit = defineEmits(['update-check-type'])
// 切换统计模式
const switchStatsMode = (mode) => {
statsMode.value = mode
// 向父组件发送事件修改CheckType的值
const checkTypeValue = mode === 'monthly' ? 'month' : 'period'
emit('update-check-type', checkTypeValue)
console.log('切换统计模式:', mode, '发送CheckType值:', checkTypeValue)
}
// 中心整体概览组件
const props = defineProps({
overallTeamPerformance: {
type: Object,
default: () => ({
totalPerformance: {},
activeGroups: {},
conversionRate: {},
totalCalls: {},
newCustomers: {},
depositConversions: {}
})
}
})
// 计算属性
const totalPerformance = computed(() => {
return props.overallTeamPerformance.totalPerformance
})
const activeGroups = computed(() => {
return props.overallTeamPerformance.activeGroups
})
const conversionRate = computed(() => {
return props.overallTeamPerformance.conversionRate
})
const totalCalls = computed(() => {
return props.overallTeamPerformance.totalCalls
})
const newCustomers = computed(() => {
return props.overallTeamPerformance.newCustomers
})
const depositConversions = computed(() => {
return props.overallTeamPerformance.depositConversions
})
// 工具提示状态
const tooltip = reactive({
visible: false,
x: 0,
y: 0,
title: '',
description: ''
})
// 指标描述
const metricDescriptions = {
teamPerformance: {
title: '团队总业绩计算方式',
description: '所有团队成员在选定时间范围内的成交金额总和,包括全款订单和定金订单的累计业绩。'
},
activeGroups: {
title: '活跃组数计算方式',
description: '当前有成员在线且有业务活动的团队组数,以及各组的总人数统计。'
},
conversionRate: {
title: '团队转化率计算方式',
description: '团队总成交单数 ÷ 团队总新增客户数 × 100%'
},
totalCalls: {
title: '总通话次数计算方式',
description: '所有团队成员在选定时间范围内的通话总次数,包括外呼、接听等所有通话记录。'
},
newCustomers: {
title: '新增客户计算方式',
description: '所有团队成员在选定时间范围内新建档的客户总数,包括意向客户和潜在客户。'
},
depositConversion: {
title: '定金转化计算方式',
description: '定金订单数 ÷ 总成交单数 × 100%'
}
}
// 显示工具提示
const showTooltip = (event, metricType) => {
const metric = metricDescriptions[metricType]
if (metric) {
tooltip.title = metric.title
tooltip.description = metric.description
tooltip.x = event.clientX
tooltip.y = event.clientY
tooltip.visible = true
}
}
// 隐藏工具提示
const hideTooltip = () => {
tooltip.visible = false
}
</script>
<style lang="scss" scoped>
.center-overview {
background: white;
border-radius: 12px;
padding: 0.5rem;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
.overview-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
.stats-toggle {
display: flex;
background: #f8fafc;
border-radius: 8px;
padding: 4px;
gap: 2px;
.toggle-btn {
padding: 8px 16px;
border: none;
background: transparent;
border-radius: 6px;
font-size: 0.875rem;
font-weight: 500;
color: #64748b;
cursor: pointer;
transition: all 0.2s ease;
&:hover {
background: #e2e8f0;
color: #475569;
}
&.active {
background: #3b82f6;
color: white;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
}
}
}
h2 {
font-size: 1.3rem;
font-weight: 600;
color: #1e293b;
margin: 0 0 1.5rem 0;
}
.overview-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin-bottom: 0;
}
.overview-card {
padding: 0.5rem;
border: 1px solid #e2e8f0;
border-radius: 10px;
transition: all 0.3s ease;
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transform: translateY(-2px);
}
&.primary {
background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
color: white;
border: none;
.card-title, .card-subtitle {
color: rgba(255, 255, 255, 0.9);
}
.card-title .info-icon {
color: rgba(255, 255, 255, 0.7);
&:hover {
color: rgba(255, 255, 255, 1);
opacity: 1;
}
}
.card-trend {
color: rgba(255, 255, 255, 0.8);
}
.card-value {
color: white;
}
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
}
.card-title {
color: #64748b;
font-size: 0.9rem;
font-weight: 500;
display: flex;
align-items: center;
gap: 0.25rem;
.info-icon {
color: #94a3b8;
font-size: 0.75rem;
cursor: pointer;
opacity: 0.7;
transition: all 0.2s ease;
margin-left: 0.25rem;
&:hover {
opacity: 1;
color: #3b82f6;
transform: scale(1.1);
}
}
}
.card-trend {
font-size: 0.75rem;
font-weight: 600;
&.positive {
color: #059669;
}
&.negative {
color: #dc2626;
}
&.stable {
color: #7c3aed;
}
}
.card-value {
font-size: 1.8rem;
font-weight: bold;
color: #1e293b;
margin-bottom: 0.25rem;
}
.card-subtitle {
color: #94a3b8;
font-size: 0.8rem;
}
}
.trend-section {
h3 {
font-size: 1.1rem;
font-weight: 600;
color: #1e293b;
margin: 0 0 1rem 0;
}
.trend-charts {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
.trend-item {
display: flex;
align-items: center;
gap: 1rem;
padding: 0.75rem;
background: #f8fafc;
border-radius: 8px;
.trend-label {
font-size: 0.85rem;
color: #64748b;
min-width: 80px;
}
.trend-bar {
flex: 1;
height: 6px;
background: #e2e8f0;
border-radius: 3px;
overflow: hidden;
.trend-fill {
height: 100%;
background: linear-gradient(90deg, #10b981, #059669);
border-radius: 3px;
transition: width 0.3s ease;
}
}
.trend-value {
font-size: 0.8rem;
font-weight: 600;
color: #059669;
min-width: 40px;
text-align: right;
}
}
}
}
// 移动端适配
@media (max-width: 768px) {
.center-overview {
padding: 1rem;
.overview-header {
flex-direction: column;
align-items: flex-start;
gap: 1rem;
.stats-toggle {
.toggle-btn {
padding: 6px 12px;
font-size: 0.8rem;
}
}
}
.overview-grid {
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
}
.overview-card {
padding: 1rem;
.card-value {
font-size: 1.5rem;
}
}
.trend-charts {
grid-template-columns: 1fr;
}
}
}
@media (max-width: 480px) {
.center-overview {
.overview-grid {
grid-template-columns: 1fr;
}
}
}
</style>