refactor(manager): 优化团队成员详情和预警处理逻辑
- 移除硬编码的团队成员数据,改为从API获取 - 添加可选链操作符处理可能为空的成员数据 - 重构异常预警处理逻辑,动态生成预警消息 - 调整UI组件间距和样式 - 清理无用注释和代码
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="member-details">
|
||||
<div class="details-header" @click="toggleDetailsCollapse">
|
||||
<h2>{{ selectedMember.user_name || selectedMember.name }} 的详细数据</h2>
|
||||
<h2>{{ selectedMember?.user_name || selectedMember?.name||'张三' }} 的详细数据</h2>
|
||||
<div class="collapse-toggle" :class="{ 'collapsed': isDetailsCollapsed }">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
|
||||
<path d="M8 4l4 4H4l4-4z"/>
|
||||
@@ -15,35 +15,35 @@
|
||||
总通话次数
|
||||
<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 class="detail-card">
|
||||
<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 class="detail-card">
|
||||
<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 class="detail-card">
|
||||
<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 class="detail-card">
|
||||
<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>
|
||||
@@ -115,7 +115,7 @@
|
||||
<div class="no-recordings" v-else>
|
||||
<div class="no-data-icon">📞</div>
|
||||
<h4>暂无录音</h4>
|
||||
<p>{{ selectedMember.user_name || selectedMember.name }} 还没有通话录音记录</p>
|
||||
<p>{{ selectedMember?.user_name || selectedMember?.name || '张三' }} 还没有通话录音记录</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -259,7 +259,7 @@ const getRecordingsForMember = (member) => {
|
||||
]
|
||||
|
||||
// 根据成员ID返回对应的录音,这里简化处理
|
||||
return recordings.slice(0, Math.min(3, member.calls || 0))
|
||||
return recordings.slice(0, Math.min(3, member?.calls || 0))
|
||||
}
|
||||
|
||||
// 下载录音文件
|
||||
|
||||
@@ -62,7 +62,6 @@ const aggregatedAlerts = computed(() => {
|
||||
.alert-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
max-height: 270px;
|
||||
overflow-y: auto;
|
||||
|
||||
@@ -85,12 +84,11 @@ const aggregatedAlerts = computed(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alert-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.75rem;
|
||||
gap: 0.2rem;
|
||||
padding: 0.25rem;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
|
||||
|
||||
@@ -95,54 +95,6 @@ const teamMembers = [
|
||||
newClients: 12,
|
||||
deals: 5,
|
||||
avgDealValue: 24000,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "张明",
|
||||
rank: 2,
|
||||
performance: 85000,
|
||||
conversion: 5.0,
|
||||
calls: 142,
|
||||
callTime: 6.2,
|
||||
newClients: 8,
|
||||
deals: 3,
|
||||
avgDealValue: 28333,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "王强",
|
||||
rank: 3,
|
||||
performance: 65000,
|
||||
conversion: 4.0,
|
||||
calls: 128,
|
||||
callTime: 5.8,
|
||||
newClients: 6,
|
||||
deals: 2,
|
||||
avgDealValue: 32500,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "赵静",
|
||||
rank: 4,
|
||||
performance: 0,
|
||||
conversion: 0.0,
|
||||
calls: 89,
|
||||
callTime: 3.2,
|
||||
newClients: 2,
|
||||
deals: 0,
|
||||
avgDealValue: 0,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "刘洋",
|
||||
rank: 5,
|
||||
performance: 0,
|
||||
conversion: 0.0,
|
||||
calls: 76,
|
||||
callTime: 2.8,
|
||||
newClients: 1,
|
||||
deals: 0,
|
||||
avgDealValue: 0,
|
||||
}
|
||||
];
|
||||
|
||||
@@ -199,10 +151,46 @@ const groupAbnormalResponse = ref({})
|
||||
async function TeamGetGroupAbnormalResponse() {
|
||||
const params = getRequestParams()
|
||||
const hasParams = params.user_name
|
||||
const res = await getGroupAbnormalResponse(hasParams ? params : undefined)
|
||||
console.log(res)
|
||||
if (res.code === 200) {
|
||||
groupAbnormalResponse.value = res.data
|
||||
try {
|
||||
const response = await getGroupAbnormalResponse(hasParams ? params : undefined)
|
||||
const rawData = response.data
|
||||
|
||||
// 转换数据格式,生成预警消息
|
||||
const processedAlerts = []
|
||||
let alertId = 1
|
||||
|
||||
// 处理严重超时异常人员
|
||||
const timeoutPersons = rawData.erious_timeout_rate_abnorma || []
|
||||
// 处理表格填写异常人员
|
||||
const fillingPersons = rawData.table_filling_abnormal || []
|
||||
|
||||
// 为每个异常人员生成独立的预警消息
|
||||
|
||||
// 处理严重超时率异常人员
|
||||
timeoutPersons.forEach(person => {
|
||||
processedAlerts.push({
|
||||
id: `timeout-${alertId++}`,
|
||||
type: 'warning',
|
||||
icon: '⚠',
|
||||
message: `${person}严重超时率过高`
|
||||
})
|
||||
})
|
||||
|
||||
// 处理表格填写率异常人员
|
||||
fillingPersons.forEach(person => {
|
||||
processedAlerts.push({
|
||||
id: `filling-${alertId++}`,
|
||||
type: 'warning',
|
||||
icon: '⚠',
|
||||
message: `${person}表格填写率过低`
|
||||
})
|
||||
})
|
||||
|
||||
// 设置处理后的数据
|
||||
groupAbnormalResponse.value = { processedAlerts }
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取团队异常预警失败:', error)
|
||||
}
|
||||
}
|
||||
// 团队总通话
|
||||
@@ -281,57 +269,22 @@ async function TeamGetGroupRanking() {
|
||||
console.log(res)
|
||||
if (res.code === 200) {
|
||||
groupRanking.value = res.data
|
||||
/**
|
||||
* "data": {
|
||||
"user_name": "马然",
|
||||
"user_level": 2,
|
||||
"team_data": {
|
||||
"group_list": [
|
||||
{
|
||||
"user_name": "马然",
|
||||
"week_amount": 0,
|
||||
"conversion_rate": "0%",
|
||||
"plus_v_rate": "0%",
|
||||
"group_rate": "0%"
|
||||
},
|
||||
{
|
||||
"user_name": "程慧仟",
|
||||
"week_amount": 7100.0,
|
||||
"conversion_rate": "0.00%",
|
||||
"plus_v_rate": "0.00%",
|
||||
"group_rate": "0.00%"
|
||||
},
|
||||
{
|
||||
"user_name": "常琳",
|
||||
"week_amount": 14500.0,
|
||||
"conversion_rate": "3.51%",
|
||||
"plus_v_rate": "54.39%",
|
||||
"group_rate": "49.12%"
|
||||
},
|
||||
{
|
||||
"user_name": "王娟娟",
|
||||
"week_amount": 600.0,
|
||||
"conversion_rate": "0.00%",
|
||||
"plus_v_rate": "3.08%",
|
||||
"group_rate": "0.00%"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
// 成员详细数据
|
||||
const memberDetails = ref({})
|
||||
|
||||
|
||||
// 当前选中的成员,默认为第一名
|
||||
const selectedMember = ref(teamMembers[0]);
|
||||
// 当前选中的成员,默认为空
|
||||
const selectedMember = ref(null);
|
||||
|
||||
// 选择成员函数
|
||||
const selectMember = (member) => {
|
||||
selectedMember.value = member;
|
||||
};
|
||||
|
||||
// 团队异常预警
|
||||
|
||||
onMounted(async () => {
|
||||
await TeamGetGroupAbnormalResponse()
|
||||
await TeamGetWeekTotalCall()
|
||||
@@ -340,7 +293,6 @@ onMounted(async () => {
|
||||
await TeamGetWeekAddFeeTotal()
|
||||
await TeamGetGroupFunnel()
|
||||
await TeamGetGroupRanking()
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user