feat(views): 添加双击跳转功能并优化样式

- 在DetailedDataTable.vue中添加双击人员跳转功能
- 优化表格和卡片头部样式
- 移除模拟数据并启用初始化API调用
- 修复performance显示格式问题
This commit is contained in:
2025-08-18 15:36:34 +08:00
parent 0a50d2fa37
commit 68ba83ca81
4 changed files with 75 additions and 238 deletions

View File

@@ -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;

View File

@@ -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; }

View File

@@ -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>

View File

@@ -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()
});