针对 **Wails v2 (Go) + Vue3** 的技术栈,建议采用**“按业务功能切片”**的架构设计。 相较于传统的“把所有 handler 放一个目录,所有 service 放一个目录”,按功能切片(每个模块内部自带 handler/service/repo)能更好地隔离业务逻辑,非常适合这种模块边界清晰的停车系统。 以下是完整的项目代码模块结构规划: ### 顶层目录结构 ```text parking-system/ ├── build/ # Wails 构建配置 (图标、安装包脚本) ├── frontend/ # Vue3 前端源码 (Vite) ├── internal/ # 核心业务代码 (不可被外部引用) ├── pkg/ # 通用工具包 ├── app.go # Wails 应用主结构体 (统一绑定前端方法) ├── main.go # Wails 程序入口 ├── go.mod └── wails.json ``` ### `internal/` 详细拆解 (核心) 这是整个后端的灵魂。我们将基础架构、硬件代理、边缘端通信和业务模块分开管理。 ```text internal/ ├── core/ # 基础设施与共享内核 │ ├── config/ # 全局配置加载 (解析 config.yaml) │ ├── database/ # SQLite/GORM 初始化、连接池、自动迁移 │ ├── logger/ # Zap 日志封装 │ └── response/ # 统一的 API 返回结构封装 │ ├── hardware/ # [P0] 本地硬件交互层 (Go直接控制物理设备) │ ├── pos/ │ │ ├── pos_driver.go # 串口底层管理 (打开/关闭/重连) │ │ └── ingenico.go # POS 机协议解析与指令收发 │ └── printer/ │ ├── escpos.go # ESC/POS 指令生成 │ └── ticket_template.go # 小票排版模板渲染 │ ├── edge/ # [P0] 边缘端(RK3568)通信层 │ ├── tcp_server.go # 监听 RK3568 的 TCP 连接与心跳 │ ├── protocol.go # 定义与 RK3568 的上下行报文协议 │ └── event_bus.go # 将底层硬件事件分发到业务模块 │ ├── modules/ # ★ 业务功能模块 (按功能切片划分) ★ │ ├── system/ # [P1] 系统与权限管理模块 │ ├── parking/ # [P0] 车场与设备管理模块 │ ├── vehicle/ # [P0] 车辆与车流管理模块 │ ├── billing/ # [P0] 计费规则引擎模块 │ ├── order/ # [P0] 收费与订单管理模块 │ ├── monitor/ # [P2] 监控与大屏展示模块 │ └── report/ # [P2] 数据统计与报表模块 │ └── wails_bindings/ # Wails 前端绑定注册中心 └── register.go # 集中实例化所有模块的 Service,并返回给 app.go 用于 Bind ``` ### `internal/modules/` 业务模块内部结构 每一个业务模块内部保持一致的“微型三层架构”。以最核心的 `order` (订单收费) 和 `billing` (计费) 模块为例: ```text modules/ ├── billing/ # [P0] 计费规则引擎 │ ├── model/ │ │ └── billing_rule.go # 计费规则表结构体 (GORM Model) │ ├── repository/ │ │ └── rule_repo.go # 规则的 CRUD 操作 │ ├── service/ │ │ ├── calculator.go # ★ 核心计费算法 (按时长、阶梯、封顶计算) │ │ └── rule_service.go # 规则的增删改查逻辑 │ └── handler.go # (可选) 如果有 REST API 路由则放这里 │ ├── order/ # [P0] 收费与订单管理 (前端交互最频繁) │ ├── model/ │ │ ├── order.go # 订单主表 (入场时间、金额、状态) │ │ └── shift_record.go # 交接班记录表 │ ├── repository/ │ │ ├── order_repo.go # 订单流水查询 │ │ └── shift_repo.go # 交接班统计查询 │ ├── service/ │ │ ├── checkout_service.go # ★ 出场结算逻辑 (调用 billing 计算费用) │ │ ├── payment_service.go # ★ 支付执行 (联动 hardware/pos 和 printer) │ │ └── shift_service.go # 当班对账逻辑 │ └── api.go # ★ 暴露给 Wails 前端的方法 (如 ProcessCheckout, PayByCash) │ ├── vehicle/ # [P0] 车辆管理 │ ├── model/ │ │ ├── whitelist.go # 白名单/内部车 │ │ └── monthly_card.go # 月卡车及续费记录 │ ├── repository/ │ │ └── vehicle_repo.go │ ├── service/ │ │ ├── whitelist_service.go# 白名单校验逻辑 │ │ └── monthly_service.go # 月卡办理与有效期校验 │ └── api.go # 暴露给前端的车辆管理方法 │ ├── parking/ # [P0] 车场与设备配置 │ ├── model/ │ │ ├── lane.go # 车道配置 │ │ └── device.go # RK3568节点与本地外设参数 │ ├── repository/ │ │ └── config_repo.go │ ├── service/ │ │ └── device_service.go # 设备状态监控、参数下发 │ └── api.go │ ├── system/ # [P1] 基础权限 │ ├── model/ │ │ └── user.go │ ├── service/ │ │ └── auth_service.go # 登录验证、密码修改 │ └── api.go │ ├── monitor/ # [P2] 监控大屏 │ ├── service/ │ │ └── realtime_service.go # 聚合设备状态与实时过车数据 │ └── api.go │ └── report/ # [P2] 报表 ├── service/ │ ├── finance_service.go # 财务收入统计 │ └── traffic_service.go # 车流量分析 └── api.go ``` ### 如何在 Wails 中将这些模块暴露给前端? 在 `app.go` 中,我们不需要把所有的逻辑都塞进去,而是通过 `internal/wails_bindings/register.go` 统一管理依赖注入。 **1. `internal/wails_bindings/register.go`** ```go package wails_bindings import ( "parking-system/internal/core/database" "parking-system/internal/hardware/pos" "parking-system/internal/modules/order" "parking-system/internal/modules/billing" // ... 其他模块 ) // Register 初始化所有依赖并返回需要绑定给前端的结构体实例 func Register(db *gorm.DB) []interface{} { // 1. 初始化底层硬件 posDriver := pos.NewDriver("COM3", 9600) // 2. 初始化各模块的 Repository orderRepo := order.NewOrderRepo(db) billingRepo := billing.NewRuleRepo(db) // 3. 初始化各模块的 Service (注入 Repo 和硬件依赖) billingSvc := billing.NewService(billingRepo) orderSvc := order.NewService(orderRepo, billingSvc, posDriver) // 4. 初始化各模块的 API (注入 Service) orderAPI := order.NewAPI(orderSvc) // billingAPI := billing.NewAPI(billingSvc) // 返回所有需要暴露给前端的 API 实例 return []interface{}{ orderAPI, // billingAPI, } } ``` **2. `main.go` (Wails 入口)** ```go package main import ( "context" "parking-system/internal/core/database" "parking-system/internal/wails_bindings" "github.com/wailsapp/wails/v2/pkg/options" ) func main() { // 1. 初始化数据库 db := database.Init("%APPDATA%/smart-parking/lc_garage.db") // 2. 获取所有前端绑定实例 binds := wails_bindings.Register(db) // 3. 启动 Wails err := wails.Run(&options.App{ Title: "智慧停车收费系统", Width: 1280, Height: 800, Bind: binds, // ★ 将所有模块的 API 绑定给前端 }) if err != nil { panic(err) } } ``` ### 这种架构的优势 1. **按需开发与裁剪**:如果要先开发 P0,你只需要关注 `billing`、`order`、`parking` 和 `hardware` 目录,其他的 `monitor` 和 `report` 目录甚至可以先不建,互不干扰。 2. **清晰的调用链路**: - 前端按钮点击 -> `order/api.go` -> `order/service/checkout_service.go` (计算费) -> `billing/service/calculator.go` -> 返回金额 -> `order/service/payment_service.go` (调硬件) -> `hardware/pos/pos_driver.go` -> 返回结果给前端。 3. **Wails 绑定解耦**:通过 `wails_bindings` 统一做依赖注入,避免了业务代码与 Wails 框架强耦合,方便未来做单元测试。