import { computed, ref } from 'vue' import { metricBlueprints, trendRanges, trendSeries, spendByCategory, exceptionMix, departmentRangeOptions, bottlenecks, budgetSummary } from '../../data/metrics.js' import TrendChart from '../../components/charts/TrendChart.vue' import DonutChart from '../../components/charts/DonutChart.vue' import BarChart from '../../components/charts/BarChart.vue' import GaugeChart from '../../components/charts/GaugeChart.vue' import PersonalWorkbench from '../../components/business/PersonalWorkbench.vue' export default { name: 'OverviewView', components: { TrendChart, DonutChart, BarChart, GaugeChart, PersonalWorkbench }, props: { filteredRequests: { type: Array, required: true } }, emits: ['ask'] , setup(props, { emit }) { const activeTrendRange = ref(trendRanges[0]) const activeDepartmentRange = ref(departmentRangeOptions[0]) const demoTotals = { pendingCount: 128, pendingAmount: 361600, avgSla: 6.8, autoPassRate: 78, riskCount: 14, slaRate: 96 } const demoDepartments = [ { name: '销售部', amount: 182000, color: 'var(--theme-primary)' }, { name: '研发中心', amount: 146000, color: 'var(--chart-blue)' }, { name: '市场部', amount: 96000, color: 'var(--chart-amber)' }, { name: '运营部', amount: 68600, color: 'var(--chart-purple)' }, { name: '行政部', amount: 48300, color: 'var(--chart-blue)' } ] const formatCompact = (value) => { if (value >= 1_000_000) return `¥${(value / 1_000_000).toFixed(1)}M` if (value >= 1_000) return `¥${(value / 1_000).toFixed(1)}K` return `¥${value}` } const formatCurrency = (value) => formatCompact(value) const formatMetricValue = (metric, value) => { if (metric.key === 'pendingAmount') return formatCurrency(Math.round(value)) if (metric.key === 'avgSla') return `${value.toFixed(1)} ${metric.unit}` if (metric.unit === '%') return `${Math.round(value)} ${metric.unit}` if (metric.unit) return `${Math.round(value)} ${metric.unit}` return `${Math.round(value)}` } const kpiMetrics = computed(() => metricBlueprints.map((metric, index) => { const rawValue = demoTotals[metric.key] const displayValue = formatMetricValue(metric, rawValue) return { ...metric, displayValue, changeText: metric.change, delay: index * 55 } })) const activeTrend = computed(() => trendSeries[activeTrendRange.value]) const spendTotal = computed(() => spendByCategory.reduce((sum, item) => sum + item.value, 0)) const riskTotal = computed(() => exceptionMix.reduce((sum, item) => sum + item.value, 0)) const spendLegend = computed(() => spendByCategory.map((item) => ({ ...item, display: `${Math.round((item.value / spendTotal.value) * 100)}%` }))) const riskLegend = computed(() => exceptionMix.map((item) => ({ ...item, display: `${item.value} 单` }))) const rankedDepartments = computed(() => { const rows = demoDepartments const max = Math.max(...rows.map((item) => item.amount), 1) return rows.slice(0, 6).map((item, index) => ({ ...item, rank: index + 1, shortName: item.name, amountLabel: formatCurrency(item.amount), width: `${Math.max((item.amount / max) * 100, 18)}%`, color: item.color })) }) return { emit, activeTrendRange, activeDepartmentRange, demoTotals, demoDepartments, formatCompact, formatCurrency, formatMetricValue, kpiMetrics, activeTrend, spendTotal, riskTotal, spendLegend, riskLegend, rankedDepartments, metricBlueprints, trendRanges, trendSeries, spendByCategory, exceptionMix, departmentRangeOptions, bottlenecks, budgetSummary } } }