diff --git a/apps/web-antd/src/api/ops/order-center/index.ts b/apps/web-antd/src/api/ops/order-center/index.ts index c1c17ac42..8fe3bc25c 100644 --- a/apps/web-antd/src/api/ops/order-center/index.ts +++ b/apps/web-antd/src/api/ops/order-center/index.ts @@ -200,13 +200,22 @@ export interface DashboardStatsResp { }; funnelData: Array<{ name: string; value: number }>; heatmapData: { days: string[]; hours: string[]; data: number[][] }; - areaRanking: Array<{ - area: string; + functionTypeRanking: Array<{ + functionType: string; count: number; completed: number; rate: number; }>; - durationStats: Array<{ type: string; avgDuration: number }>; +} + +/** 近7天客流趋势响应 */ +export interface TrafficTrendResp { + dates: string[]; + inData: number[]; + outData: number[]; + netData: number[]; + totalIn: number; + totalOut: number; } /** 实时客流响应 */ @@ -268,6 +277,13 @@ export function getWorkspaceStats() { ); } +/** 获取近7天客流趋势统计 */ +export function getTrafficTrend() { + return requestClient.get( + '/ops/order-center/traffic-trend', + ); +} + // ==================== 工单操作接口 ==================== /** 重新分配/派单 */ diff --git a/apps/web-antd/src/views/ops/cleaning/work-order/dashboard/index.vue b/apps/web-antd/src/views/ops/cleaning/work-order/dashboard/index.vue index 36811f4cf..1890226ab 100644 --- a/apps/web-antd/src/views/ops/cleaning/work-order/dashboard/index.vue +++ b/apps/web-antd/src/views/ops/cleaning/work-order/dashboard/index.vue @@ -58,28 +58,20 @@ interface DashboardStats { // 工单处理漏斗 funnelData: Array<{ name: string; value: number }>; - // 时段热力图数据(7天 x 24小时) + // 时段热力图数据(近7天 x 24小时) heatmapData: { data: number[][]; // 7x24的二维数组 days: string[]; // 周一到周日 hours: string[]; // 0-23小时 }; - // 区域工单排行 - areaRanking: Array<{ - area: string; + // 功能类型工单排行 + functionTypeRanking: Array<{ + functionType: string; completed: number; count: number; rate: number; }>; - - // 工单作业时长统计 - durationStats: Array<{ - avgDuration: number; // 分钟 - color: string; - icon: string; - type: string; - }>; } // ========== 响应式数据 ========== @@ -92,17 +84,15 @@ const hourlyChartRef = ref(); const timeTrendChartRef = ref(); const funnelChartRef = ref(); const heatmapChartRef = ref(); -const areaRankingChartRef = ref(); -const durationChartRef = ref(); +const functionTypeRankingChartRef = ref(); const { renderEcharts: renderTrendChart } = useEcharts(trendChartRef); const { renderEcharts: renderHourlyChart } = useEcharts(hourlyChartRef); const { renderEcharts: renderTimeTrendChart } = useEcharts(timeTrendChartRef); const { renderEcharts: renderFunnelChart } = useEcharts(funnelChartRef); const { renderEcharts: renderHeatmapChart } = useEcharts(heatmapChartRef); -const { renderEcharts: renderAreaRankingChart } = - useEcharts(areaRankingChartRef); -const { renderEcharts: renderDurationChart } = useEcharts(durationChartRef); +const { renderEcharts: renderFunctionTypeRankingChart } = + useEcharts(functionTypeRankingChartRef); const statsData = ref({ pendingCount: 0, @@ -129,8 +119,7 @@ const statsData = ref({ hours: [], data: [], }, - areaRanking: [], - durationStats: [], + functionTypeRanking: [], }); // ========== 空数据(API失败时的fallback) ========== @@ -144,8 +133,7 @@ const EMPTY_STATS: DashboardStats = { timeTrendData: { dates: [], responseTimeData: [], completionTimeData: [] }, funnelData: [], heatmapData: { days: [], hours: [], data: [] }, - areaRanking: [], - durationStats: [], + functionTypeRanking: [], }; // ========== 图表配置 ========== @@ -674,10 +662,10 @@ function getHeatmapChartOptions(): ECOption { } /** - * 区域工单排行图表配置 + * 功能类型排行图表配置 */ -function getAreaRankingChartOptions(): ECOption { - const { areaRanking } = statsData.value; +function getFunctionTypeRankingChartOptions(): ECOption { + const { functionTypeRanking } = statsData.value; return { grid: { left: '3%', @@ -698,7 +686,7 @@ function getAreaRankingChartOptions(): ECOption { }, yAxis: { type: 'category', - data: areaRanking.map((item) => item.area), + data: functionTypeRanking.map((item) => item.functionType), axisLabel: { fontSize: 13, color: '#595959', @@ -713,7 +701,7 @@ function getAreaRankingChartOptions(): ECOption { series: [ { type: 'bar', - data: areaRanking.map((item) => ({ + data: functionTypeRanking.map((item) => ({ value: item.count, itemStyle: { color: getCompletionRateColor(item.rate), @@ -743,67 +731,6 @@ function getAreaRankingChartOptions(): ECOption { } } -/** - * 工单作业时长统计图表配置 - */ -function getDurationChartOptions(): ECOption { - const { durationStats } = statsData.value; - return { - grid: { - left: '3%', - right: '18%', - top: '5%', - bottom: '3%', - containLabel: true, - }, - xAxis: { - type: 'value', - max: 'dataMax', - splitLine: { - show: false, - }, - axisLabel: { - show: false, - }, - }, - yAxis: { - type: 'category', - data: durationStats.map((item) => item.type), - axisLabel: { - fontSize: 13, - color: '#595959', - }, - axisLine: { - show: false, - }, - axisTick: { - show: false, - }, - }, - series: [ - { - type: 'bar', - data: durationStats.map((item) => ({ - value: item.avgDuration, - itemStyle: { - color: item.color, - borderRadius: [0, 6, 6, 0], - }, - })), - barWidth: 18, - label: { - show: true, - position: 'right', - fontSize: 13, - color: '#262626', - fontWeight: 500, - formatter: (params: any) => `${params.value}分钟`, - }, - }, - ], - }; -} - // ========== 数据加载 ========== /** 加载统计数据 */ @@ -811,20 +738,6 @@ async function loadStats() { loading.value = true; try { const resp = await getDashboardStats(); - // 映射 durationStats: 后端返回 type(枚举key) + avgDuration,前端补充显示名、图标、颜色 - const mappedDurationStats = (resp.durationStats || []).map((item) => { - const mapping = CLEANING_TYPE_MAP[item.type] || { - type: item.type, - icon: 'solar:broom-bold', - color: '#8c8c8c', - }; - return { - type: mapping.type, - icon: mapping.icon, - color: mapping.color, - avgDuration: item.avgDuration, - }; - }); statsData.value = { pendingCount: resp.pendingCount, @@ -836,8 +749,7 @@ async function loadStats() { timeTrendData: resp.timeTrendData, funnelData: resp.funnelData, heatmapData: resp.heatmapData, - areaRanking: resp.areaRanking, - durationStats: mappedDurationStats, + functionTypeRanking: resp.functionTypeRanking, }; // 渲染图表 @@ -848,8 +760,7 @@ async function loadStats() { renderTimeTrendChart(getTimeTrendChartOptions()); renderFunnelChart(getFunnelChartOptions()); renderHeatmapChart(getHeatmapChartOptions()); - renderAreaRankingChart(getAreaRankingChartOptions()); - renderDurationChart(getDurationChartOptions()); + renderFunctionTypeRankingChart(getFunctionTypeRankingChartOptions()); } catch { // API失败时使用空数据作为fallback statsData.value = { ...EMPTY_STATS }; @@ -983,9 +894,9 @@ onUnmounted(() => { - +