feat(views): 添加双击跳转功能并优化样式
- 在DetailedDataTable.vue中添加双击人员跳转功能 - 优化表格和卡片头部样式 - 移除模拟数据并启用初始化API调用 - 修复performance显示格式问题
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="dashboard-card detail-section">
|
||||
<div class="card-header">
|
||||
<div class="card-header custom-header">
|
||||
<h3>数据详情</h3>
|
||||
</div>
|
||||
<div class="detail-content">
|
||||
@@ -38,6 +38,10 @@ defineProps({
|
||||
grid-column: 3 / 4;
|
||||
}
|
||||
|
||||
.custom-header {
|
||||
margin-left: 1rem !important;
|
||||
}
|
||||
|
||||
.detail-content .no-selection {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="dashboard-card table-section">
|
||||
<div class="card-header">
|
||||
<div class="card-header" style="margin-left: 1rem;">
|
||||
|
||||
<h3>详细数据表格</h3>
|
||||
</div>
|
||||
<div class="data-table-container">
|
||||
@@ -49,7 +50,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(person, index) in displayTableData" :key="index" @click="$emit('update:selectedPerson', person)" :class="{ selected: selectedPerson && (selectedPerson.sale_name === person.sale_name || selectedPerson.leader_name === person.leader_name) }">
|
||||
<tr v-for="(person, index) in displayTableData" :key="index" @click="$emit('update:selectedPerson', person)" @dblclick="handlePersonDoubleClick(person)" :class="{ selected: selectedPerson && (selectedPerson.sale_name === person.sale_name || selectedPerson.leader_name === person.leader_name) }">
|
||||
<td>
|
||||
<div class="person-info">
|
||||
<div class="person-avatar">{{ (person.sale_name || person.leader_name).charAt(0) }}</div>
|
||||
@@ -78,6 +79,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const props = defineProps({
|
||||
tableData: { type: Array, required: true },
|
||||
@@ -85,6 +87,7 @@ const props = defineProps({
|
||||
levelTree: { type: Object, default: () => ({}) }
|
||||
});
|
||||
const emit = defineEmits(['update:selectedPerson', 'filter-change']);
|
||||
const router = useRouter();
|
||||
|
||||
const filters = ref({ centerLeader: '', advancedManager: '', manager: '', dealStatus: '' });
|
||||
const sortField = ref('conversion_rate');
|
||||
@@ -165,12 +168,57 @@ const getRateClass = (rate) => {
|
||||
const getRateColor = (rate) => {
|
||||
if (rate >= 80) return '#4CAF50'; if (rate >= 60) return '#FF9800'; return '#f44336';
|
||||
};
|
||||
|
||||
// 处理人员双击事件
|
||||
const handlePersonDoubleClick = (person) => {
|
||||
let userLevel = 4; // 默认级别
|
||||
const userName = person.sale_name || person.leader_name;
|
||||
|
||||
// 根据筛选器选择状态确定user_level
|
||||
if (filters.value.manager) {
|
||||
userLevel = 1; // 选中经理
|
||||
} else if (filters.value.advancedManager) {
|
||||
userLevel = 2; // 选中高级经理
|
||||
} else if (filters.value.centerLeader) {
|
||||
userLevel = 3; // 选中中心领导
|
||||
}
|
||||
// 如果什么都没选,userLevel保持为4
|
||||
|
||||
// 根据user_level确定跳转路径
|
||||
let targetPath = '';
|
||||
switch (userLevel) {
|
||||
case 4:
|
||||
targetPath = '/second-top';
|
||||
break;
|
||||
case 3:
|
||||
targetPath = '/senior-manager';
|
||||
break;
|
||||
case 2:
|
||||
targetPath = '/manager';
|
||||
break;
|
||||
case 1:
|
||||
targetPath = '/sale';
|
||||
break;
|
||||
default:
|
||||
targetPath = '/second-top';
|
||||
}
|
||||
|
||||
// 路由跳转
|
||||
router.push({
|
||||
path: targetPath,
|
||||
query: {
|
||||
user_name: userName,
|
||||
user_level: userLevel
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 移除formatDuration函数,不再需要
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.table-section { height: 600px; }
|
||||
.data-table-container { height: calc(100% - 60px); overflow-y: auto; padding: 24px; }
|
||||
.data-table-container { height: calc(100% - 60px); overflow-y: auto; padding: 0.5rem; }
|
||||
.table-filters { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; margin-bottom: 24px; padding: 16px; background: #f8fafc; border-radius: 8px; }
|
||||
.filter-group { display: flex; flex-direction: column; gap: 4px; }
|
||||
.filter-group label { font-size: 12px; font-weight: 600; color: #4a5568; }
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
<div class="ranking-toggle">
|
||||
<button
|
||||
:class="['toggle-btn', { active: rankingType === 'red' }]"
|
||||
@click="rankingType = 'red'"
|
||||
@click="handleRankingTypeChange('red')"
|
||||
>
|
||||
红榜
|
||||
</button>
|
||||
<button
|
||||
:class="['toggle-btn', { active: rankingType === 'black' }]"
|
||||
@click="rankingType = 'black'"
|
||||
@click="handleRankingTypeChange('black')"
|
||||
>
|
||||
黑榜
|
||||
</button>
|
||||
@@ -34,7 +34,7 @@
|
||||
</div>
|
||||
<div class="performance-section">
|
||||
<div class="performance-value">
|
||||
¥{{ formatNumber(item.performance) }}
|
||||
{{ item.performance }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -73,234 +73,13 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['period-change']);
|
||||
const emit = defineEmits(['period-change', 'ranking-type-change']);
|
||||
|
||||
const rankingPeriod = ref('month');
|
||||
const rankingType = ref('red'); // 'red' 为红榜,'black' 为黑榜
|
||||
|
||||
// 模拟数据
|
||||
const mockData = [
|
||||
{
|
||||
id: 1,
|
||||
name: '张明',
|
||||
department: '华东区',
|
||||
performance: 156800,
|
||||
deals: 28,
|
||||
conversionRate: 85.2,
|
||||
trend: 'up',
|
||||
growth: 12.5,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '李娜',
|
||||
department: '华南区',
|
||||
performance: 142300,
|
||||
deals: 25,
|
||||
conversionRate: 78.9,
|
||||
trend: 'up',
|
||||
growth: 8.3,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '王强',
|
||||
department: '华北区',
|
||||
performance: 138900,
|
||||
deals: 23,
|
||||
conversionRate: 82.1,
|
||||
trend: 'down',
|
||||
growth: -2.1,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '赵丽',
|
||||
department: '西南区',
|
||||
performance: 125600,
|
||||
deals: 21,
|
||||
conversionRate: 75.4,
|
||||
trend: 'up',
|
||||
growth: 15.2,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '陈伟',
|
||||
department: '华中区',
|
||||
performance: 118700,
|
||||
deals: 19,
|
||||
conversionRate: 71.8,
|
||||
trend: 'stable',
|
||||
growth: 0.5,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: '刘芳',
|
||||
department: '东北区',
|
||||
performance: 112400,
|
||||
deals: 18,
|
||||
conversionRate: 69.3,
|
||||
trend: 'up',
|
||||
growth: 6.7,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: '杨磊',
|
||||
department: '西北区',
|
||||
performance: 98500,
|
||||
deals: 16,
|
||||
conversionRate: 65.2,
|
||||
trend: 'down',
|
||||
growth: -5.3,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: '周敏',
|
||||
department: '华东区',
|
||||
performance: 89300,
|
||||
deals: 14,
|
||||
conversionRate: 62.1,
|
||||
trend: 'up',
|
||||
growth: 3.8,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: '吴刚',
|
||||
department: '华南区',
|
||||
performance: 82100,
|
||||
deals: 13,
|
||||
conversionRate: 58.7,
|
||||
trend: 'down',
|
||||
growth: -3.2,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: '孙丽',
|
||||
department: '西南区',
|
||||
performance: 76800,
|
||||
deals: 12,
|
||||
conversionRate: 55.4,
|
||||
trend: 'stable',
|
||||
growth: 1.1,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: '马强',
|
||||
department: '华北区',
|
||||
performance: 71200,
|
||||
deals: 11,
|
||||
conversionRate: 52.3,
|
||||
trend: 'down',
|
||||
growth: -6.8,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: '朱敏',
|
||||
department: '东北区',
|
||||
performance: 65900,
|
||||
deals: 10,
|
||||
conversionRate: 49.1,
|
||||
trend: 'down',
|
||||
growth: -8.5,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: '胡伟',
|
||||
department: '西北区',
|
||||
performance: 58700,
|
||||
deals: 9,
|
||||
conversionRate: 45.8,
|
||||
trend: 'down',
|
||||
growth: -12.3,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
name: '郭芳',
|
||||
department: '华中区',
|
||||
performance: 52400,
|
||||
deals: 8,
|
||||
conversionRate: 42.6,
|
||||
trend: 'down',
|
||||
growth: -15.7,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: '林磊',
|
||||
department: '华东区',
|
||||
performance: 45300,
|
||||
deals: 7,
|
||||
conversionRate: 38.9,
|
||||
trend: 'down',
|
||||
growth: -18.2,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: '何敏',
|
||||
department: '华南区',
|
||||
performance: 38100,
|
||||
deals: 6,
|
||||
conversionRate: 35.4,
|
||||
trend: 'down',
|
||||
growth: -22.1,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
name: '罗强',
|
||||
department: '西南区',
|
||||
performance: 31800,
|
||||
deals: 5,
|
||||
conversionRate: 31.7,
|
||||
trend: 'down',
|
||||
growth: -25.6,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
name: '高丽',
|
||||
department: '华北区',
|
||||
performance: 25200,
|
||||
deals: 4,
|
||||
conversionRate: 28.3,
|
||||
trend: 'down',
|
||||
growth: -28.9,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
name: '宋伟',
|
||||
department: '东北区',
|
||||
performance: 18900,
|
||||
deals: 3,
|
||||
conversionRate: 24.1,
|
||||
trend: 'down',
|
||||
growth: -32.4,
|
||||
avatar: '/default-avatar.svg'
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
name: '谢芳',
|
||||
department: '西北区',
|
||||
performance: 12600,
|
||||
deals: 2,
|
||||
conversionRate: 19.8,
|
||||
trend: 'down',
|
||||
growth: -36.7,
|
||||
avatar: '/default-avatar.svg'
|
||||
}
|
||||
];
|
||||
const mockData = [];
|
||||
|
||||
const displayData = computed(() => {
|
||||
const data = props.rankingData.length > 0 ? props.rankingData : mockData;
|
||||
@@ -317,6 +96,11 @@ const displayData = computed(() => {
|
||||
const handlePeriodChange = () => {
|
||||
emit('period-change', rankingPeriod.value);
|
||||
};
|
||||
|
||||
const handleRankingTypeChange = (type) => {
|
||||
rankingType.value = type;
|
||||
emit('ranking-type-change', type);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
:format-number="formatNumber"
|
||||
:get-rank-class="getRankClass"
|
||||
@period-change="handleRankingPeriodChange"
|
||||
@ranking-type-change="getCompanySalesRank"
|
||||
/>
|
||||
<!-- 优质通话 -->
|
||||
<quality-calls
|
||||
@@ -704,7 +705,7 @@ const formattedSalesRankingData = computed(() => {
|
||||
id: index + 1,
|
||||
name: item.name,
|
||||
department: item.department,
|
||||
performance: item.deal_count * 10000, // 假设每单10000元,可根据实际情况调整
|
||||
performance: item.deal_count, // 假设每单10000元,可根据实际情况调整
|
||||
deals: item.deal_count,
|
||||
conversionRate: parseFloat(item.conversion_rate.replace('%', '')),
|
||||
trend: rankType === 'red' ? 'up' : 'down', // 红榜为上升趋势,黑榜为下降趋势
|
||||
@@ -1038,13 +1039,13 @@ const handleFilterChange = (filterParams) => {
|
||||
|
||||
onMounted(async() => {
|
||||
// 页面初始化逻辑
|
||||
// await getRealTimeProgress()
|
||||
// await getTotalDeals()
|
||||
// await getConversionComparison('month')
|
||||
// await getCompanySalesRank('red')
|
||||
// await getCenterSalesRank('periods')
|
||||
// await getCustomerTypeRatio('child_education')
|
||||
// await getCustomerUrgency()
|
||||
await getRealTimeProgress()
|
||||
await getTotalDeals()
|
||||
await getConversionComparison('month')
|
||||
await getCompanySalesRank('red')
|
||||
await getCenterSalesRank('periods')
|
||||
await getCustomerTypeRatio('child_education')
|
||||
await getCustomerUrgency()
|
||||
await CusotomGetLevelTree()
|
||||
await getDetailData()
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user