| | |
| | | <el-card class="box-card"> |
| | | <!-- KPI 汇总 --> |
| | | <el-row :gutter="20" class="stats-row"> |
| | | <el-col :span="6"> |
| | | <el-col :span="8"> |
| | | <div class="stat-card"> |
| | | <div class="stat-icon" style="background: #ecf5ff;"> |
| | | <el-icon :size="30" color="#409eff"><Document /></el-icon> |
| | |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-col :span="8"> |
| | | <div class="stat-card"> |
| | | <div class="stat-icon" style="background: #f0f9ff;"> |
| | | <el-icon :size="30" color="#67c23a"><Tickets /></el-icon> |
| | |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <el-col :span="8"> |
| | | <div class="stat-card"> |
| | | <div class="stat-icon" style="background: #fef0f0;"> |
| | | <el-icon :size="30" color="#e6a23c"><Van /></el-icon> |
| | |
| | | <div class="stat-content"> |
| | | <div class="stat-value">{{ indicatorKpis.shipmentRate }}%</div> |
| | | <div class="stat-label">发货率</div> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | <el-col :span="6"> |
| | | <div class="stat-card"> |
| | | <div class="stat-icon" style="background: #f4f4f5;"> |
| | | <el-icon :size="30" color="#f56c6c"><Wallet /></el-icon> |
| | | </div> |
| | | <div class="stat-content"> |
| | | <div class="stat-value">{{ indicatorKpis.collectionRate }}%</div> |
| | | <div class="stat-label">回款率</div> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | |
| | | </div> |
| | | |
| | | <!-- 业绩统计(团队维度,无个人姓名) --> |
| | | <el-table :data="teamPerformanceList" border stripe style="margin-top: 20px;"> |
| | | <el-table v-if="showTeamPerformance" :data="teamPerformanceList" border stripe style="margin-top: 20px;"> |
| | | <el-table-column prop="team" label="销售团队"/> |
| | | <el-table-column prop="orderCount" label="订单数"/> |
| | | <el-table-column prop="salesAmount" label="销售额"> |
| | |
| | | </el-table-column> |
| | | <el-table-column prop="shipmentRate" label="发货率"> |
| | | <template #default="scope">{{ scope.row.shipmentRate }}%</template> |
| | | </el-table-column> |
| | | <el-table-column prop="collectionRate" label="回款率"> |
| | | <template #default="scope">{{ scope.row.collectionRate }}%</template> |
| | | </el-table-column> |
| | | <el-table-column prop="attainment" label="目标达成率"> |
| | | <template #default="scope"> |
| | |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, nextTick } from 'vue' |
| | | import { Document, Van, Tickets, Wallet } from '@element-plus/icons-vue' |
| | | import { Document, Van, Tickets } from '@element-plus/icons-vue' |
| | | import * as echarts from 'echarts' |
| | | |
| | | const indicatorKpis = reactive({ |
| | | orderCount: 1280, |
| | | salesAmount: 9650000, |
| | | shipmentRate: 89.2, |
| | | collectionRate: 76.4 |
| | | shipmentRate: 89.2 |
| | | }) |
| | | |
| | | // 是否展示销售团队明细表,按需开启 |
| | | const showTeamPerformance = ref(false) |
| | | |
| | | const indicatorFilter = reactive({ |
| | | product: '', |
| | |
| | | let indicatorChart = null |
| | | |
| | | const teamPerformanceList = ref([ |
| | | { team: '华东大区', orderCount: 320, salesAmount: 2850000, shipmentRate: 90, collectionRate: 80, attainment: 105 }, |
| | | { team: '华北大区', orderCount: 280, salesAmount: 2150000, shipmentRate: 86, collectionRate: 73, attainment: 92 }, |
| | | { team: '华南大区', orderCount: 210, salesAmount: 1850000, shipmentRate: 88, collectionRate: 70, attainment: 78 }, |
| | | { team: '西南大区', orderCount: 180, salesAmount: 1500000, shipmentRate: 83, collectionRate: 68, attainment: 74 } |
| | | { team: '华东大区', orderCount: 320, salesAmount: 2850000, shipmentRate: 90, attainment: 105 }, |
| | | { team: '华北大区', orderCount: 280, salesAmount: 2150000, shipmentRate: 86, attainment: 92 }, |
| | | { team: '华南大区', orderCount: 210, salesAmount: 1850000, shipmentRate: 88, attainment: 78 }, |
| | | { team: '西南大区', orderCount: 180, salesAmount: 1500000, shipmentRate: 83, attainment: 74 } |
| | | ]) |
| | | |
| | | const initIndicatorChart = () => { |
| | |
| | | const option = { |
| | | title: { text: '多维度销售指标趋势', left: 'center' }, |
| | | tooltip: { trigger: 'axis' }, |
| | | legend: { data: ['订单数', '销售额', '发货率', '回款率'], top: 30 }, |
| | | legend: { data: ['订单数', '销售额', '发货率'], top: 30 }, |
| | | grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, |
| | | xAxis: { type: 'category', data: ['2024-12', '2025-01', '2025-02', '2025-03', '2025-04', '2025-05'] }, |
| | | yAxis: [ |
| | |
| | | series: [ |
| | | { name: '订单数', type: 'bar', data: [180, 220, 210, 260, 205, 225], itemStyle: { color: '#409eff' } }, |
| | | { name: '销售额', type: 'bar', data: [820, 950, 910, 1080, 980, 1020], itemStyle: { color: '#67c23a' } }, |
| | | { name: '发货率', type: 'line', yAxisIndex: 1, data: [86, 89, 88, 91, 87, 90], itemStyle: { color: '#e6a23c' } }, |
| | | { name: '回款率', type: 'line', yAxisIndex: 1, data: [72, 76, 74, 79, 75, 78], itemStyle: { color: '#f56c6c' } } |
| | | { name: '发货率', type: 'line', yAxisIndex: 1, data: [86, 89, 88, 91, 87, 90], itemStyle: { color: '#e6a23c' } } |
| | | ] |
| | | } |
| | | indicatorChart.setOption(option) |
| | |
| | | indicatorKpis.orderCount = random(1280, 120) |
| | | indicatorKpis.salesAmount = random(9650000, 350000) |
| | | indicatorKpis.shipmentRate = (85 + Math.random() * 10).toFixed(1) * 1 |
| | | indicatorKpis.collectionRate = (70 + Math.random() * 12).toFixed(1) * 1 |
| | | setTimeout(() => initIndicatorChart(), 200) |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | const exportIndicatorTable = () => { |
| | | const header = ['销售团队', '订单数', '销售额', '发货率(%)', '回款率(%)', '目标达成率(%)'] |
| | | const header = ['销售团队', '订单数', '销售额', '发货率(%)', '目标达成率(%)'] |
| | | const rows = teamPerformanceList.value.map(r => [ |
| | | r.team, |
| | | r.orderCount, |
| | | r.salesAmount, |
| | | r.shipmentRate, |
| | | r.collectionRate, |
| | | r.attainment |
| | | ]) |
| | | const csv = [header, ...rows].map(r => r.join(',')).join('\n') |