|
|
@@ -0,0 +1,97 @@
|
|
|
+# 数字票(Digital Ticket)— 设计文档
|
|
|
+
|
|
|
+> 日期:2026-07-23 | 优先级:P0
|
|
|
+
|
|
|
+## 1. 目标
|
|
|
+
|
|
|
+引入数字票作为停车业务的统一抽象模型。所有进场方式(RFID/车牌识别/手动)最终创建数字票,以票的状态驱动计费、支付和放行。
|
|
|
+
|
|
|
+## 2. 状态机
|
|
|
+
|
|
|
+```
|
|
|
+ ┌──────────┐
|
|
|
+ ┌──→ │ 已过期 │ ←──┐
|
|
|
+ │ └──────────┘ │
|
|
|
+ │ 超时未支付 │ 超时未离场
|
|
|
+ │ │
|
|
|
+ ┌────────┐ │ ┌───────────┐ ┌──┴───┐ ┌────────┐
|
|
|
+ │ 已创建 │─→│ │ 待支付 │─→│ 已支付 │─→│ 已离场 │
|
|
|
+ └────────┘ └───────────┘ └──────┘ └────────┘
|
|
|
+ 车辆入场 自动转换 支付成功 验证放行
|
|
|
+```
|
|
|
+
|
|
|
+| 状态 | 描述 | 触发条件 |
|
|
|
+|------|------|---------|
|
|
|
+| created | 车辆入场,数字票生成 | 入场事件触发 |
|
|
|
+| pending_payment | 待支付 | 创建完成后自动进入 |
|
|
|
+| paid | 已支付,费用结清 | 支付成功回调 |
|
|
|
+| exited | 已离场,流程结束 | 验证通过后开闸 |
|
|
|
+| expired | 超时未支付或未离场 | 定时任务/超时逻辑 |
|
|
|
+
|
|
|
+## 3. 数据模型
|
|
|
+
|
|
|
+### digital_ticket 表
|
|
|
+
|
|
|
+| 字段 | 类型 | 说明 |
|
|
|
+|------|------|------|
|
|
|
+| id | uint | 主键 |
|
|
|
+| ticket_no | string | 票号(UUID,二维码凭证) |
|
|
|
+| plate_number | string | 车牌 |
|
|
|
+| trigger_mode | string | rfid / plate_recognition / manual |
|
|
|
+| state | string | created / pending_payment / paid / exited / expired |
|
|
|
+| vehicle_record_id | uint | 关联 vehicle_record |
|
|
|
+| entry_time | datetime | 入场时间 |
|
|
|
+| exit_time | datetime | 出场时间 |
|
|
|
+| fee | float64 | 计费金额 |
|
|
|
+| payment_method | string | cash / free / wechat / alipay |
|
|
|
+| payment_order_no | string | 支付单号(关联 payment_record) |
|
|
|
+| paid_at | datetime | 支付时间 |
|
|
|
+| expire_at | datetime | 超时过期时间 |
|
|
|
+| event_log | text(JSON) | 事件日志数组 |
|
|
|
+
|
|
|
+### event_log 格式
|
|
|
+
|
|
|
+```json
|
|
|
+[
|
|
|
+ {"at": "2026-07-23 10:30", "event": "created", "trigger": "manual"},
|
|
|
+ {"at": "2026-07-23 12:30", "event": "fee_calculated", "fee": 15.0},
|
|
|
+ {"at": "2026-07-23 12:31", "event": "paid", "method": "cash", "amount": 20}
|
|
|
+]
|
|
|
+```
|
|
|
+
|
|
|
+## 4. API
|
|
|
+
|
|
|
+| 方法 | 路径 | 说明 |
|
|
|
+|------|------|------|
|
|
|
+| POST | /digital-ticket/create | 创建票(入场时) |
|
|
|
+| GET | /digital-ticket/:ticketNo | 查询票(扫码用) |
|
|
|
+| POST | /digital-ticket/:ticketNo/calculate | 计费 |
|
|
|
+| POST | /digital-ticket/:ticketNo/pay | 支付 |
|
|
|
+| POST | /digital-ticket/:ticketNo/exit | 离场验证 |
|
|
|
+| GET | /digital-ticket/list | 列表 |
|
|
|
+
|
|
|
+## 5. 与现有流程关系
|
|
|
+
|
|
|
+```
|
|
|
+任何进场方式 → DigitalTicket.Create() + VehicleEntry()
|
|
|
+ │
|
|
|
+ 状态: created → pending_payment
|
|
|
+ │
|
|
|
+ ExitPreview / ExitConfirm
|
|
|
+ │
|
|
|
+ 状态: paid → exited
|
|
|
+```
|
|
|
+
|
|
|
+数字票作为业务状态层,位于 `internal/modules/digital-ticket/`,不替代 vehicle_record。
|
|
|
+
|
|
|
+## 6. 文件变更
|
|
|
+
|
|
|
+| 文件 | 操作 |
|
|
|
+|------|------|
|
|
|
+| `internal/dao/digital_ticket.go` | 新建 |
|
|
|
+| `internal/modules/digital-ticket/api.go` | 新建 |
|
|
|
+| `internal/modules/digital-ticket/service/service.go` | 新建 |
|
|
|
+| `internal/modules/digital-ticket/repository/repo.go` | 新建 |
|
|
|
+| `internal/service/vehicle/vehicle.go` | 修改(VehicleEntry 创建 digital_ticket) |
|
|
|
+| `internal/initialize/gorm.go` | 修改(AutoMigrate) |
|
|
|
+| `internal/initialize/router.go` | 修改(路由注册) |
|