# 监控仪表盘 — 实现计划 > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans. **Goal:** 升级仪表盘为停车监控大屏,4统计卡片+设备状态,10秒轮询 **Architecture:** 后端 `GET /dashboard/monitor`(system 模块,SQL 聚合)。前端替换 `dashboard/index.vue`,`el-statistic` + `setInterval`。 --- ## 文件结构 | 文件 | 操作 | |------|------| | `internal/service/system/sys_dashboard.go` | 新建 | | `internal/api/v1/system/sys_dashboard.go` | 新建 | | `internal/router/system/sys_dashboard.go` | 新建 | | `internal/router/enter.go` | 修改 | | `internal/initialize/router.go` | 修改 | | `frontend/src/view/dashboard/index.vue` | 修改 | | `frontend/src/api/dashboard.js` | 修改 | --- ### Task 1: 后端 API - [ ] **Step 1: Service** Write `internal/service/system/sys_dashboard.go`: ```go package system import ( "time" "wails-app/internal/global" ) type DeviceStatus struct { ChannelName string `json:"channel_name"` Direction string `json:"direction"` DeviceName string `json:"device_name"` DeviceStatus string `json:"device_status"` } type MonitorData struct { TotalSpaces int64 `json:"total_spaces"` UsedSpaces int64 `json:"used_spaces"` InPark int64 `json:"in_park"` TodayIncome float64 `json:"today_income"` TodayEntry int64 `json:"today_entry"` TodayExit int64 `json:"today_exit"` Devices []DeviceStatus `json:"devices"` } type DashboardService struct{} func (s *DashboardService) GetMonitorData() (MonitorData, error) { var d MonitorData today := time.Now().Format("2006-01-02") global.GVA_DB.Raw("SELECT COALESCE(SUM(capacity), 0) FROM parking_lot").Scan(&d.TotalSpaces) global.GVA_DB.Raw("SELECT COUNT(*) FROM vehicle_record WHERE exit_time IS NULL").Scan(&d.InPark) d.UsedSpaces = d.InPark global.GVA_DB.Raw("SELECT COALESCE(SUM(amount), 0) FROM payment_record WHERE paid_at >= ? AND paid_at < ?", today, today+" 23:59:59").Scan(&d.TodayIncome) global.GVA_DB.Raw("SELECT COUNT(*) FROM vehicle_record WHERE entry_time >= ? AND entry_time < ?", today, today+" 23:59:59").Scan(&d.TodayEntry) global.GVA_DB.Raw("SELECT COUNT(*) FROM vehicle_record WHERE exit_time >= ? AND exit_time < ?", today, today+" 23:59:59").Scan(&d.TodayExit) global.GVA_DB.Raw(`SELECT ch.channel_name, ch.direction, COALESCE(uhf.device_name, '-') as device_name, COALESCE(uhf.status, 'offline') as device_status FROM channel ch LEFT JOIN uhf_reader uhf ON uhf.channel_id = ch.id WHERE ch.deleted_at IS NULL ORDER BY ch.id`).Scan(&d.Devices) return d, nil } ``` - [ ] **Step 2: Handler** Write `internal/api/v1/system/sys_dashboard.go`: ```go package system import ( "github.com/gin-gonic/gin" "wails-app/internal/model/common/response" systemService "wails-app/internal/service/system" ) var dashboardSvc = systemService.DashboardService{} func GetMonitor(c *gin.Context) { data, err := dashboardSvc.GetMonitorData() if err != nil { response.FailWithMessage(err.Error(), c) return } response.OkWithData(data, c) } ``` - [ ] **Step 3: Router** Write `internal/router/system/sys_dashboard.go`: ```go package system import ( "wails-app/internal/api/v1/system" "github.com/gin-gonic/gin" ) type DashboardRouter struct{} func (s *DashboardRouter) InitDashboardRouter(Router *gin.RouterGroup) { dashboardRouter := Router.Group("dashboard") { dashboardRouter.GET("monitor", system.GetMonitor) } } ``` - [ ] **Step 4: 注册路由** Edit `internal/router/enter.go`, add DashboardRouter to RouterGroup: ```go type RouterGroup struct { System system.RouterGroup Example example.RouterGroup Vehicle vehicle.RouterGroup Dashboard system.DashboardRouter // add this line } ``` Edit `internal/initialize/router.go`, register in PrivateGroup block: ```go systemRouter.InitDashboardRouter(PrivateGroup) // add this line ``` - [ ] **Step 5: Casbin** ```bash sqlite3 "$APPDATA/smart-parking/lc_garage.db" "INSERT INTO casbin_rule (ptype, v0, v1, v2) VALUES ('p', '888', '/dashboard/monitor', 'GET'), ('p', '618', '/dashboard/monitor', 'GET');" ``` - [ ] **Step 6: 编译+提交** ```bash go build -o build/bin/smart-parking.exe . git add internal/service/system/sys_dashboard.go internal/api/v1/system/sys_dashboard.go internal/router/system/sys_dashboard.go internal/router/enter.go internal/initialize/router.go git commit -m "feat: 新增监控仪表盘API——GET /dashboard/monitor" ``` --- ### Task 2: 前端监控大屏 - [ ] **Step 1: API** Edit `frontend/src/api/dashboard.js` (add to existing or create): ```js import service from '@/utils/request' export const getMonitor = () => { return service({ url: '/dashboard/monitor', method: 'get' }) } ``` - [ ] **Step 2: 页面** Write `frontend/src/view/dashboard/index.vue` (replace existing): ```vue 智慧停车监控 {{ now }} 车位 台 / {{ data.today_exit }} 进 / 出 设备状态 {{ d.device_status === 'online' ? '在线' : '离线' }} {{ d.channel_name }} {{ d.device_name }} ({{ d.direction === 'in' ? '入口' : '出口' }}) ``` - [ ] **Step 3: 编译+提交** ```bash cd frontend && npm run build && cd .. git add frontend/src/view/dashboard/index.vue frontend/src/api/dashboard.js git commit -m "feat: 升级仪表盘为停车监控大屏——4统计卡片+设备状态+10秒轮询" ```