feat(会员详情): 添加指标说明工具提示功能

为会员详情页面的各项指标添加信息图标和工具提示功能,当用户悬停在ⓘ图标上时显示该指标的计算方式和说明。包含总通话次数、通话时长、新增客户、成交单数和转化率五个指标的详细说明。

新增Tooltip组件用于显示提示信息,并实现鼠标跟随定位功能。调整了样式以适配新的信息图标布局。
This commit is contained in:
2025-08-22 18:20:02 +08:00
parent 9b61620b86
commit d53dd95c4e

View File

@@ -11,23 +11,38 @@
<div class="details-content"> <div class="details-content">
<div class="details-grid" v-show="!isDetailsCollapsed" :class="{ 'collapsing': isDetailsCollapsed }"> <div class="details-grid" v-show="!isDetailsCollapsed" :class="{ 'collapsing': isDetailsCollapsed }">
<div class="detail-card"> <div class="detail-card">
<div class="detail-label">总通话次数</div> <div class="detail-label">
总通话次数
<span class="info-icon" @mouseenter="showTooltip($event, 'totalCalls')" @mouseleave="hideTooltip"></span>
</div>
<div class="detail-value">{{ selectedMember.calls || 0 }} </div> <div class="detail-value">{{ selectedMember.calls || 0 }} </div>
</div> </div>
<div class="detail-card"> <div class="detail-card">
<div class="detail-label">通话时长</div> <div class="detail-label">
通话时长
<span class="info-icon" @mouseenter="showTooltip($event, 'callTime')" @mouseleave="hideTooltip"></span>
</div>
<div class="detail-value">{{ selectedMember.callTime || 0 }} 小时</div> <div class="detail-value">{{ selectedMember.callTime || 0 }} 小时</div>
</div> </div>
<div class="detail-card"> <div class="detail-card">
<div class="detail-label">新增客户</div> <div class="detail-label">
新增客户
<span class="info-icon" @mouseenter="showTooltip($event, 'newClients')" @mouseleave="hideTooltip"></span>
</div>
<div class="detail-value">{{ selectedMember.newClients || 0 }} </div> <div class="detail-value">{{ selectedMember.newClients || 0 }} </div>
</div> </div>
<div class="detail-card"> <div class="detail-card">
<div class="detail-label">成交单数</div> <div class="detail-label">
成交单数
<span class="info-icon" @mouseenter="showTooltip($event, 'deals')" @mouseleave="hideTooltip"></span>
</div>
<div class="detail-value">{{ selectedMember.deals || 0 }} </div> <div class="detail-value">{{ selectedMember.deals || 0 }} </div>
</div> </div>
<div class="detail-card"> <div class="detail-card">
<div class="detail-label">转化率</div> <div class="detail-label">
转化率
<span class="info-icon" @mouseenter="showTooltip($event, 'conversionRate')" @mouseleave="hideTooltip"></span>
</div>
<div class="detail-value">{{ selectedMember.conversion_rate || selectedMember.conversion || '0%' }}</div> <div class="detail-value">{{ selectedMember.conversion_rate || selectedMember.conversion || '0%' }}</div>
</div> </div>
</div> </div>
@@ -104,11 +119,21 @@
</div> </div>
</div> </div>
</div> </div>
<!-- Tooltip 组件 -->
<Tooltip
:visible="tooltip.visible"
:x="tooltip.x"
:y="tooltip.y"
:title="tooltip.title"
:description="tooltip.description"
/>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, defineProps, watch, nextTick } from 'vue' import { ref, defineProps, watch, nextTick, reactive } from 'vue'
import Tooltip from '@/components/Tooltip.vue'
// 定义props // 定义props
const props = defineProps({ const props = defineProps({
@@ -127,6 +152,39 @@ const isGuidanceCollapsed = ref(false)
// 录音列表折叠状态(默认展开) // 录音列表折叠状态(默认展开)
const isRecordingsCollapsed = ref(false) const isRecordingsCollapsed = ref(false)
// 工具提示状态
const tooltip = reactive({
visible: false,
x: 0,
y: 0,
title: '',
description: ''
})
// 指标描述
const metricDescriptions = {
totalCalls: {
title: '总通话次数计算方式',
description: '统计该成员在选定时间范围内的所有外呼和接听通话的总次数,包括有效通话和无效通话。'
},
callTime: {
title: '通话时长计算方式',
description: '累计该成员所有有效通话的时长,以小时为单位显示,精确到小数点后一位。'
},
newClients: {
title: '新增客户计算方式',
description: '统计该成员在选定时间范围内新建档的客户数量,不包括重复录入的客户。'
},
deals: {
title: '成交单数计算方式',
description: '统计该成员在选定时间范围内成功签约的订单数量,包括全款和定金订单。'
},
conversionRate: {
title: '转化率计算方式',
description: '成交单数 ÷ 新增客户数 × 100%,反映该成员将潜在客户转化为成交客户的能力。'
}
}
// 切换详细数据折叠状态 // 切换详细数据折叠状态
const toggleDetailsCollapse = () => { const toggleDetailsCollapse = () => {
isDetailsCollapsed.value = !isDetailsCollapsed.value isDetailsCollapsed.value = !isDetailsCollapsed.value
@@ -142,6 +200,23 @@ const toggleRecordingsCollapse = () => {
isRecordingsCollapsed.value = !isRecordingsCollapsed.value isRecordingsCollapsed.value = !isRecordingsCollapsed.value
} }
// 显示工具提示
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
}
// 格式化金额 // 格式化金额
const formatAmount = (amount) => { const formatAmount = (amount) => {
if (typeof amount === 'number') { if (typeof amount === 'number') {
@@ -349,6 +424,25 @@ watch(() => props.selectedMember, () => {
color: #64748b; color: #64748b;
font-size: 0.85rem; font-size: 0.85rem;
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
display: flex;
align-items: center;
justify-content: 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);
}
}
} }
.detail-value { .detail-value {