# 收费结算模块 — 设计文档

> 日期：2026-07-17 | 优先级：P0-3

## 1. 目标

在出场环节增加收费结算流程。临时车人工收费（现金），月租/VIP 车自动免密放行。架构上预留 POS 机、扫码支付的扩展入口。

## 2. 核心改造

### 出场流程

```
输入车牌 → 查询车辆
  ├─ 月租/VIP（is_system=false）→ 点"确认出场" → 免密 → 自动放行
  └─ 临时车（is_system=true）→ 显示费用
       ├─ 应付金额
       ├─ 支付方式：[现金] [扫码(预留)] [POS(预留)]
       └─ 现金模式：
            ├─ 收费员输入实收金额
            ├─ 系统自动计算找零
            └─ "确认收款" → 创建支付记录 → 出场+开闸
```

### 扩展性设计

- 后端定义 `PaymentMethod` 常量（cash / free / pos / wechat / alipay）
- 新增支付方式：加常量 + 前端加支付按钮 → 调同一接口传不同 `payment_method`
- 前端支付按钮按 `paymentMethodList` 渲染，新增只需加数组项

## 3. 数据结构

### 新增表：`payment_record`

| 字段 | 类型 | 说明 |
|------|------|------|
| id | uint | 主键 |
| record_id | uint | 关联 vehicle_record.id |
| payment_method | string | cash / free / pos / wechat / alipay |
| amount | float64 | 应收金额 |
| paid_amount | float64 | 实收金额（现金时由收费员输入）|
| change_amount | float64 | 找零 |
| operator_id | uint | 收费员用户ID |
| paid_at | datetime | 支付时间 |
| remark | string | 备注 |

### vehicle_record 表新增字段

| 字段 | 类型 | 说明 |
|------|------|------|
| payment_method | string | 支付方式 |

## 4. API 设计

### 4.1 费用预览

`POST /vehicle/exit/preview`

```
Request:  { plate_number, rfid_tag }
Response: { plate_number, entry_time, stay_time, fee, vehicle_type, is_temp }
```

不修改数据库，仅查询进场记录 + 计算费用。

### 4.2 确认出场（+支付）

`POST /vehicle/exit/confirm`

```
Request:  { plate_number, rfid_tag, payment_method, paid_amount }
Response: { plate_number, entry_time, exit_time, stay_time, fee, change_amount, payment_method }
```

1. 更新 vehicle_record（exit_time, stay_time, fee, payment_status, payment_method）
2. 创建 payment_record
3. 更新车辆统计

**payment_method=free 时**：`paid_amount=0`，直接放行。

## 5. 前端改造（entryExit.vue 出场 Tab）

查询到车辆后，根据 `is_temp` 分两路：

### 月租/VIP（非临时车）

直接显示"确认出场"按钮 → 调 `/vehicle/exit/confirm`（payment_method=free）

### 临时车

显示费用信息 + 支付方式选择 + 现金输入（选现金时） + "确认收款"按钮

```
┌───────────────────────────────────┐
│ 出场信息                          │
│ 车牌: 粤A12345  进场: 10:30       │
│ 停留: 2小时15分  应收: ¥15.00     │
│                                   │
│ 支付方式: [现金] [扫码] [POS]     │
│                                   │
│ 实收金额: [______] 元             │
│ 找零: ¥5.00                       │
│                                   │
│ [确认收款并放行]                   │
└───────────────────────────────────┘
```

## 6. 文件变更清单

| 文件 | 操作 | 说明 |
|------|------|------|
| `internal/dao/payment_record.go` | 新增 | 支付记录 DAO |
| `internal/dao/vehicle_record.go` | 修改 | 加 payment_method 字段 |
| `internal/model/vehicle/request/vehicle.go` | 修改 | 新增 ExitPreview / ExitConfirm 请求 |
| `internal/service/vehicle/vehicle.go` | 修改 | 拆出 Preview / Confirm 方法 |
| `internal/api/v1/vehicle/vehicle.go` | 修改 | 新增路由 handler |
| `internal/router/vehicle/vehicle.go` | 修改 | 注册新路由 |
| `frontend/src/view/parking/entryExit.vue` | 修改 | 出场 Tab 增加收费 UI |
| `frontend/src/api/vehicle.js` | 修改 | 新增 preview / confirm API |

## 7. 边界情况

| 场景 | 处理 |
|------|------|
| 现金收不够 | 前端校验：实收 < 应收，提示"金额不足" |
| 金额输入非数字 | 前端过滤，仅允许数字和点 |
| 已出场的车再次点出场 | 后端 preview 返回错误 |
| 免密车类型不对 | confirm 时二次校验 is_system |
