代码规划.md 8.5 KB

针对 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

如何在 Wails 中将这些模块暴露给前端?

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)
	}
}

这种架构的优势

  1. 按需开发与裁剪:如果要先开发 P0,你只需要关注 billingorderparkinghardware 目录,其他的 monitorreport 目录甚至可以先不建,互不干扰。
  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 框架强耦合,方便未来做单元测试。