针对 Wails v2 (Go) + Vue3 的技术栈,建议采用“按业务功能切片”的架构设计。 相较于传统的“把所有 handler 放一个目录,所有 service 放一个目录”,按功能切片(每个模块内部自带 handler/service/repo)能更好地隔离业务逻辑,非常适合这种模块边界清晰的停车系统。 以下是完整的项目代码模块结构规划:
parking-system/
├── build/ # Wails 构建配置 (图标、安装包脚本)
├── frontend/ # Vue3 前端源码 (Vite)
├── internal/ # 核心业务代码 (不可被外部引用)
├── pkg/ # 通用工具包
├── app.go # Wails 应用主结构体 (统一绑定前端方法)
├── main.go # Wails 程序入口
├── go.mod
└── wails.json
internal/ 详细拆解 (核心)这是整个后端的灵魂。我们将基础架构、硬件代理、边缘端通信和业务模块分开管理。
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 (计费) 模块为例:
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
在 app.go 中,我们不需要把所有的逻辑都塞进去,而是通过 internal/wails_bindings/register.go 统一管理依赖注入。
1. internal/wails_bindings/register.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 入口)
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)
}
}
billing、order、parking 和 hardware 目录,其他的 monitor 和 report 目录甚至可以先不建,互不干扰。order/api.go -> order/service/checkout_service.go (计算费) -> billing/service/calculator.go -> 返回金额 -> order/service/payment_service.go (调硬件) -> hardware/pos/pos_driver.go -> 返回结果给前端。wails_bindings 统一做依赖注入,避免了业务代码与 Wails 框架强耦合,方便未来做单元测试。