From 9bf042f8173ae060bc51d15b0cbcb5af97dee14f Mon Sep 17 00:00:00 2001 From: lzh Date: Thu, 26 Feb 2026 16:52:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(project):=20=E6=96=B0=E5=A2=9E=E5=AE=A2?= =?UTF-8?q?=E6=B5=81=E7=BB=9F=E8=AE=A1=E7=8B=AC=E7=AB=8B=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新建 /ops/traffic 路由和客流统计页面 - 新建客流 API 模块(全局/设备/区域维度的实时和趋势接口) - 新建 AreaTree 组件(区域树选择、搜索过滤保留祖先节点、递归获取子孙ID) - 支持全局总览和按区域查看客流数据 - 今日/昨日小时客流趋势对比曲线图、近7天客流趋势折线图 - 核心指标卡片 + 客流态势分析面板 - 更新旧 API 路径适配新后端接口 Co-Authored-By: Claude Opus 4.6 --- .../src/api/ops/order-center/index.ts | 34 +- apps/web-antd/src/api/ops/traffic/index.ts | 117 ++ .../web-antd/src/router/routes/modules/ops.ts | 10 + .../src/views/ops/components/AreaTree.vue | 159 +++ apps/web-antd/src/views/ops/traffic/index.vue | 1231 +++++++++-------- 5 files changed, 969 insertions(+), 582 deletions(-) create mode 100644 apps/web-antd/src/api/ops/traffic/index.ts create mode 100644 apps/web-antd/src/views/ops/components/AreaTree.vue 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 8fe3bc25c..125b1369a 100644 --- a/apps/web-antd/src/api/ops/order-center/index.ts +++ b/apps/web-antd/src/api/ops/order-center/index.ts @@ -188,22 +188,22 @@ export interface DashboardStatsResp { completedTodayCount: number; completedTotalCount: number; trendData: { - dates: string[]; - createdData: number[]; completedData: number[]; + createdData: number[]; + dates: string[]; }; - hourlyDistribution: { hours: string[]; data: number[] }; + hourlyDistribution: { data: number[]; hours: string[] }; timeTrendData: { + completionTimeData: number[]; dates: string[]; responseTimeData: number[]; - completionTimeData: number[]; }; funnelData: Array<{ name: string; value: number }>; - heatmapData: { days: string[]; hours: string[]; data: number[][] }; + heatmapData: { data: number[][]; days: string[]; hours: string[] }; functionTypeRanking: Array<{ - functionType: string; - count: number; completed: number; + count: number; + functionType: string; rate: number; }>; } @@ -226,10 +226,10 @@ export interface TrafficRealtimeResp { areas: Array<{ areaId: number; areaName: string; - todayIn: number; - todayOut: number; currentOccupancy: number; deviceCount: number; + todayIn: number; + todayOut: number; }>; hourlyTrend: { hours: string[]; inData: number[]; outData: number[] }; } @@ -244,15 +244,15 @@ export interface WorkspaceStatsResp { todayOrderCount: number; newOrderCount: number; urgentTasks: Array<{ + assigneeName: string; + createTime: string; id: number; - title: string; location: string; priority: number; status: string; - createTime: string; - assigneeName: string; + title: string; }>; - workOrderTrend: { hours: string[]; data: number[] }; + workOrderTrend: { data: number[]; hours: string[] }; } /** 获取看板完整统计 */ @@ -265,9 +265,7 @@ export function getDashboardStats(params?: DashboardStatsQuery) { /** 获取实时客流数据 */ export function getTrafficRealtime() { - return requestClient.get( - '/ops/order-center/traffic-realtime', - ); + return requestClient.get('/ops/traffic/realtime'); } /** 获取工作台统计数据 */ @@ -279,9 +277,7 @@ export function getWorkspaceStats() { /** 获取近7天客流趋势统计 */ export function getTrafficTrend() { - return requestClient.get( - '/ops/order-center/traffic-trend', - ); + return requestClient.get('/ops/traffic/trend'); } // ==================== 工单操作接口 ==================== diff --git a/apps/web-antd/src/api/ops/traffic/index.ts b/apps/web-antd/src/api/ops/traffic/index.ts new file mode 100644 index 000000000..06f8b2d0a --- /dev/null +++ b/apps/web-antd/src/api/ops/traffic/index.ts @@ -0,0 +1,117 @@ +import { requestClient } from '#/api/request'; + +// ==================== 类型定义 ==================== + +/** 实时客流区域信息 */ +export interface TrafficAreaItem { + areaId: number; + areaName: string; + todayIn: number; + todayOut: number; + currentOccupancy: number; + deviceCount: number; +} + +/** 全局实时客流响应 */ +export interface TrafficRealtimeResp { + totalIn: number; + totalOut: number; + currentOccupancy: number; + areas: TrafficAreaItem[]; + hourlyTrend: { + hours: string[]; + inData: number[]; + outData: number[]; + }; + yesterdayHourlyTrend?: { + hours: string[]; + inData: number[]; + outData: number[]; + }; + message?: string; // 提示信息,如"该区域暂未配置客流设备" +} + +/** 客流趋势响应(全局/设备/区域通用) */ +export interface TrafficTrendResp { + deviceId?: null | number; + areaId?: null | number; + dates: string[]; + inData: number[]; + outData: number[]; + netData: number[]; + totalIn: number; + totalOut: number; +} + +/** 设备/区域实时客流响应(单条) */ +export interface DeviceTrafficRealtimeResp { + deviceId: number; + deviceName: null | string; + areaId: null | number; + areaName: null | string; + todayIn: number; + todayOut: number; + currentOccupancy: number; + hourlyTrend: { + hours: string[]; + inData: number[]; + outData: number[]; + }; + yesterdayHourlyTrend?: { + hours: string[]; + inData: number[]; + outData: number[]; + }; +} + +/** 趋势查询参数 */ +export interface TrafficTrendQuery { + deviceId?: number; + areaId?: number; + areaIds?: string; // 逗号分隔的区域ID列表 + startDate?: string; // yyyy-MM-dd + endDate?: string; // yyyy-MM-dd +} + +// ==================== 迁移接口(路径变更) ==================== + +/** 获取全局实时客流数据 */ +export function getTrafficRealtime() { + return requestClient.get('/ops/traffic/realtime'); +} + +/** 获取全局近7天客流趋势 */ +export function getTrafficTrend() { + return requestClient.get('/ops/traffic/trend'); +} + +// ==================== 新增接口 ==================== + +/** 获取单设备实时客流 */ +export function getDeviceRealtime(deviceId: number) { + return requestClient.get( + '/ops/traffic/device/realtime', + { params: { deviceId } }, + ); +} + +/** 获取区域实时客流(汇总,返回与全局一致的结构) */ +export function getAreaRealtime(areaIds: number[]) { + return requestClient.get('/ops/traffic/area/realtime', { + params: { areaIds: areaIds.join(',') }, + }); +} + +/** 获取单设备客流趋势 */ +export function getDeviceTrend(params: TrafficTrendQuery) { + return requestClient.get('/ops/traffic/device/trend', { + params, + }); +} + +/** 获取区域客流趋势(汇总) */ +export function getAreaTrend(params: TrafficTrendQuery) { + return requestClient.get('/ops/traffic/area/trend', { + params, + }); +} diff --git a/apps/web-antd/src/router/routes/modules/ops.ts b/apps/web-antd/src/router/routes/modules/ops.ts index b724ae5d8..fb2ff4ab2 100644 --- a/apps/web-antd/src/router/routes/modules/ops.ts +++ b/apps/web-antd/src/router/routes/modules/ops.ts @@ -21,6 +21,16 @@ const routes: RouteRecordRaw[] = [ }, component: () => import('#/views/ops/area/index.vue'), }, + // 客流统计 + { + path: 'traffic', + name: 'OpsTraffic', + meta: { + title: '客流统计', + activePath: '/ops/traffic', + }, + component: () => import('#/views/ops/traffic/index.vue'), + }, // 保洁工单详情 { path: 'cleaning/work-order/detail/:id', diff --git a/apps/web-antd/src/views/ops/components/AreaTree.vue b/apps/web-antd/src/views/ops/components/AreaTree.vue new file mode 100644 index 000000000..0e67733a9 --- /dev/null +++ b/apps/web-antd/src/views/ops/components/AreaTree.vue @@ -0,0 +1,159 @@ + + + diff --git a/apps/web-antd/src/views/ops/traffic/index.vue b/apps/web-antd/src/views/ops/traffic/index.vue index f0cd5a28f..395614e2b 100644 --- a/apps/web-antd/src/views/ops/traffic/index.vue +++ b/apps/web-antd/src/views/ops/traffic/index.vue @@ -1,66 +1,79 @@