# 快充管理平台 API 契约文档

> **版本**: v1.5  
> **最后更新**: 2026-07-29  
> **访问地址**: https://k-xx.cn/docs/api（密码: kxx-admin-2026）  
> **用途**: 前端（小程序 / 管理后台）与后端之间的接口协议  
> **原则**: 本文档是前后端之间的「合同」——接口定义一旦确认，双方按文档各自开发，互不阻塞  
> **给新人**: 拿到这份文档 + Mock Server 示例数据 = 可以独立开发小程序和后台，不需要碰协议网关

---

## 目录

- [1. 约定与规范](#1-约定与规范)
- [2. 用户模块](#2-用户模块)
  - [2.1 微信登录](#21-微信登录)
  - [2.2 获取个人信息](#22-获取个人信息)
  - [2.3 充值](#23-充值)
  - [2.4 VIN车架号绑定](#24-vin车架号绑定)
  - [2.5 VIN绑定列表](#25-vin绑定列表)
  - [2.6 解绑车架号](#26-解绑车架号)
  - [2.7 设置支付模式](#27-设置支付模式)
  - [2.8 开通信用支付](#28-开通信用支付)
  - [2.9 查询信用支付状态](#29-查询信用支付状态)
  - [2.10 用户注册](#210-用户注册)
  - [2.11 绑定手机号](#211-绑定手机号)
  - [2.12 用户退出登录](#212-用户退出登录)
  - [2.13 积分与等级](#213-积分与等级)
  - [2.14 签到与邀请](#214-签到与邀请)
  - [2.15 提现](#215-提现)
- [3. 充电站模块](#3-充电站模块)
  - [3.1 附近充电站列表](#31-附近充电站列表)
  - [3.2 充电站详情+桩列表](#32-充电站详情--桩列表)
  - [3.3 桩实时状态查询](#33-桩实时状态查询)
- [4. 充电流程模块](#4-充电流程模块)
  - [4.1 启动充电（扫码充电）](#41-启动充电扫码充电)
  - [4.1d VIN充电启动](#41d-vin充电启动-⭐-v12-更新)
  - [4.1e 密码充电启动](#41e-密码充电启动)
  - [4.1f 账号登录充电](#41f-账号登录充电-⭐-v14-新增)
  - [4.2 充电中实时数据](#42-充电中实时数据轮询)
  - [4.3 结束充电](#43-结束充电)
  - [4.4 充电账单](#44-充电账单)
- [5. 订单模块](#5-订单模块)
  - [5.1 订单列表](#51-订单列表)
  - [5.2 订单详情](#52-订单详情充电中账单)
- [6. 管理后台模块](#6-管理后台模块)
  - [6.1 管理员登录](#61-管理员登录)
  - [6.1b 获取管理员信息](#61b-获取管理员信息)
  - [6.2 充电桩管理列表](#62-充电桩管理列表)
  - [6.3 添加充电桩](#63-添加充电桩)
  - [6.4 编辑充电桩](#64-编辑充电桩)
  - [6.5 删除充电桩](#65-删除充电桩)
  - [6.6 远程重启充电桩](#66-远程重启充电桩)
  - [6.7 远程升级固件](#67-远程升级固件)
  - [6.8 费率管理列表](#68-费率管理列表)
  - [6.9 创建费率](#69-创建费率)
  - [6.10 编辑费率](#610-编辑费率)
  - [6.11 桩-费率绑定](#611-桩-费率绑定)
  - [6.12 交易流水](#612-交易流水)
  - [6.13 营收日报](#613-营收日报)
  - [6.14 营收月报](#614-营收月报)
  - [6.15 充电站管理列表](#615-充电站管理列表)
  - [6.16 创建充电站](#616-创建充电站)
  - [6.17 编辑充电站](#617-编辑充电站)
  - [6.18 VIN批量导入](#618-vin批量导入车队管理-⭐-v12)
  - [6.19 VIN批量批次列表](#619-vin批量批次列表)
  - [6.20 批次详情](#620-批次详情)
  - [6.21 充电密码预设管理](#621-充电密码预设管理-⭐-v12)
  - [6.22 站点服务费规格管理](#622-站点服务费规格管理-⭐-v11-新增)
  - [6.23 运营看板](#623-运营看板-⭐-v11-新增)
  - [6.24 费用单位约定](#624-费用单位约定-⭐-v11-新增)
  - [6.25 企业管理](#625-企业管理-⭐-v13-新增)
  - [6.26 车队/组织机构管理](#626-车队组织机构管理-⭐-v13-新增)
  - [6.27 群组定价活动](#627-群组定价活动-⭐-v13-新增)
  - [6.28 线下清分结算](#628-线下清分结算-⭐-v13-新增)
  - [6.29 国网基准电价](#629-国网基准电价-⭐-v14-新增)
  - [6.30 远程启机](#630-远程启机-⭐-v14-新增)
  - [6.31 即插即充](#631-即插即充-⭐-v14-新增)
  - [6.32 BMS电池诊断](#632-bms电池诊断-⭐-v14-新增)
  - [6.33 用户管理](#633-用户管理-⭐-v14-新增)
  - [6.34 提现审核](#634-提现审核-⭐-v14-新增)
  - [6.35 移动充电设备管理](#635-移动充电设备管理-⭐-v14-新增)
  - [6.36 车队VIN批操作](#636-车队vin批操作-⭐-v14-新增)
  - [6.37 车队停止码设置](#637-车队停止码设置-⭐-v14-新增)
- [7. 支付模块](#7-支付模块)
  - [7.1 统一下单](#71-统一下单)
  - [7.2 支付回调](#72-支付回调)
  - [7.3 信用支付回调](#73-信用支付回调)
- [附录A: 通用数据字典](#附录a-通用数据字典)
- [附录B: Mock Server 搭建指南](#附录b-mock-server-搭建指南)

---

## 1. 约定与规范

### 1.1 基础信息

| 项 | 值 |
|----|-----|
| 协议 | HTTPS |
| 域名 | `https://api.lkc.com` (开发期用 `http://localhost:3000`) |
| 请求格式 | `application/json` |
| 响应格式 | `application/json` |
| 字符编码 | UTF-8 |

### 1.2 统一响应结构

```json
{
  "code": 0,
  "message": "ok",
  "data": { ... },
  "timestamp": 1717200000
}
```

| 字段 | 类型 | 说明 |
|------|------|------|
| code | int | 0=成功, 非0=错误（见错误码表） |
| message | string | 提示信息 |
| data | object/array/null | 业务数据 |
| timestamp | int | 响应时间戳(秒) |

### 1.3 通用错误码

| code | 说明 |
|------|------|
| 0 | 成功 |
| 1001 | 参数错误 |
| 1002 | 签名校验失败 |
| 1003 | Token 过期 |
| 1004 | Token 无效 |
| 2001 | 用户不存在 |
| 2002 | 余额不足 |
| 3001 | 充电桩不在线 |
| 3002 | 充电桩已占用 |
| 3003 | 充电桩故障 |
| 3004 | 充电订单不存在 |
| 4001 | 费率不存在 |
| 5000 | 服务器内部错误 |

### 1.4 分页结构

```json
// 请求参数（Query String）
?page=1&pageSize=20

// 响应格式
{
  "code": 0,
  "message": "ok",
  "data": {
    "list": [ ... ],
    "total": 156,
    "page": 1,
    "pageSize": 20,
    "totalPages": 8
  }
}
```

### 1.5 认证方式

- **小程序端**: 微信 `wx.login()` 获取 code → 调登录接口换取 `token`
- **管理后台**: 用户名+密码登录 → 换取 `token`
- 后续请求在 Header 中携带: `Authorization: Bearer <token>`

---

## 2. 用户模块

### 2.1 微信登录

```
POST /api/auth/login
```

> 或 `POST /api/users/login`（完全等价，均支持 code 登录）

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| code | string | code/userId 二选一 | wx.login() 返回的临时 code（微信登录） |
| userId | int | code/userId 二选一 | 用户ID（管理后台/测试用，无需微信授权） |
| nickName | string | 否 | 微信昵称（code 模式下新用户自动存入） |
| avatarUrl | string | 否 | 微信头像URL（code 模式下新用户自动存入） |

**请求示例（微信登录）**:
```json
{
  "code": "0a3XyY0w1kabcDeFGH",
  "nickName": "孔师傅",
  "avatarUrl": "https://thirdwx.qlogo.cn/xxx"
}
```

> 💡 `wx.getUserProfile` 已废弃（基础库 2.27.1+ 返回默认值）。新方案：`<button open-type="chooseAvatar">` + `<input type="nickname">` 获取头像昵称后传入。两种路由 `/api/auth/login` 和 `/api/users/login` 完全等价。

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "expiresIn": 86400,
    "user": {
      "id": 1001,
      "nickname": "孔师傅",
      "avatar": "https://example.com/avatar.png",
      "phone": "137****0417",
      "balance": 12850,
      "createdAt": "2026-03-15T10:30:00Z"
    }
  }
}
```

> `balance` 单位为分（12850 = ¥128.50），前端自行除100显示

---

### 2.2 获取个人信息

```
GET /api/users/me
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "id": 1001,
    "nickname": "孔师傅",
    "avatar": "https://example.com/avatar.png",
    "phone": "137****0417",
    "balance": 12850,
    "totalCharged": 320500,
    "chargeCount": 48,
    "createdAt": "2026-03-15T10:30:00Z"
  }
}
```

| 字段 | 说明 |
|------|------|
| balance | 余额(分) |
| totalCharged | 累计充电金额(分) |
| chargeCount | 累计充电次数 |

---

### 2.3 充值

```
POST /api/users/recharge
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| amount | int | 是 | 充值金额(分)，如 5000 = ¥50 |
| payMethod | string | 是 | 固定值 `"wechat"` |

**请求示例**:
```json
{
  "amount": 5000,
  "payMethod": "wechat"
}
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "rechargeNo": "R20260601123456001",
    "amount": 5000,
    "payInfo": {
      "appId": "wx1234567890",
      "timeStamp": "1717200000",
      "nonceStr": "abc123",
      "package": "prepay_id=wx123456789",
      "signType": "RSA",
      "paySign": "xxx"
    }
  }
}
```

> 前端拿到 `payInfo` 后调用 `wx.requestPayment()` 拉起微信支付。  
> 支付结果前端不要自行判断——需调 `GET /api/users/me` 刷新余额确认。

---

### 2.4 VIN车架号绑定

> **三种录入方式**：
> 1. **手动输入** — 用户在小程序「我的车辆」手动输入VIN码
> 2. **行驶证OCR** — 扫描上传行驶证，自动识别VIN及车辆信息
> 3. **首次充电触发** — 桩读取VIN后平台通知用户确认绑定

---

#### 2.4.1 手动输入绑定

```
POST /api/users/vin/bind
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| vin | string | 是 | 车架号(17位) |
| vehicleBrand | string | 否 | 车辆品牌，如 "比亚迪" |
| vehicleModel | string | 否 | 车辆型号，如 "汉EV" |
| plateNo | string | 否 | 车牌号 |
| isDefault | bool | 否 | 设为默认车辆，默认 true |
| bindSource | string | 否 | 绑定来源，默认 `"manual"`。可选 `"car_app_authorize"` |

**请求**:
```json
{
  "vin": "LSVAU2A38J2150114",
  "vehicleBrand": "比亚迪",
  "vehicleModel": "汉EV",
  "plateNo": "京A12345",
  "bindSource": "manual"
}
```

**响应**:
```json
{ "code": 0, "data": { "id": 1, "vin": "LSVAU2A38J2150114", "vehicleBrand": "比亚迪", "vehicleModel": "汉EV", "plateNo": "京A12345", "isDefault": true, "bindSource": "manual" } }
```

---

#### 2.4.2 行驶证OCR上传

```
POST /api/users/vin/ocr
```

> ⚠️ 生产环境需接入腾讯云OCR/百度OCR API识别行驶证。开发模式下，前端调用此接口提交OCR识别结果（JSON），平台自动绑定。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| ocrResult.vin | string | 是 | OCR识别的车架号 |
| ocrResult.brand | string | 否 | 识别的品牌 |
| ocrResult.model | string | 否 | 识别的型号 |
| ocrResult.plateNo | string | 否 | 识别的车牌号 |
| imageUrl | string | 否 | 行驶证原图URL(存证) |
| autoBind | bool | 否 | 是否自动绑定，默认 true |
| isDefault | bool | 否 | 是否设为默认车辆，默认 true |

**请求**:
```json
{
  "ocrResult": {
    "vin": "LSVAU2A38J2150114",
    "brand": "比亚迪",
    "model": "汉EV",
    "plateNo": "京A12345"
  },
  "imageUrl": "https://cdn.lkc.com/ocr/driving_license_123.jpg",
  "autoBind": true
}
```

**响应（自动绑定）**:
```json
{ "code": 0, "data": { "id": 2, "vin": "LSVAU2A38J2150114", "brand": "比亚迪", "model": "汉EV", "plateNo": "京A12345", "autoBound": true, "bindSource": "ocr" }, "message": "行驶证识别成功，车架号已自动绑定" }
```

**响应（需确认）** — 传 `autoBind: false`:
```json
{ "code": 0, "data": { "vin": "...", "brand": "...", "model": "...", "plateNo": "...", "autoBound": false }, "message": "OCR识别成功，请确认后绑定" }
```

---

#### 2.4.3 首次充电触发采集

```
POST /api/users/vin/confirm-from-charge
```

> **场景**：用户在充电桩首次充电后，小程序推送 VIN 绑定确认弹窗。  
> 此 API 返回待确认的 VIN 信息，用户确认后还需调 `POST /api/users/vin/bind` 完成绑定。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| vin | string | 是 | 桩读取到的车架号 |
| pileSn | string | 否 | 充电桩编号（前端展示） |
| gunNo | int | 否 | 枪号 |

**请求**:
```json
{ "vin": "LSVAU2A38J2150114", "pileSn": "LKC-P001-001", "gunNo": 1 }
```

**响应**:
```json
{
  "code": 0,
  "data": {
    "vin": "LSVAU2A38J2150114",
    "chargingAt": { "pileSn": "LKC-P001-001", "gunNo": 1 },
    "status": "pending_confirm",
    "message": "检测到新车辆，请在弹窗中确认是否绑定此车架号并开通即插即充",
    "action": "请调用 POST /api/users/vin/bind 完成绑定"
  }
}
```

---

#### 2.4.4 车企App授权（bindSource）

> 部分车企（比亚迪、蔚来等）与充电平台合作支持授权同步。用户在车企 App 内授权后，车企回调至平台，调用 `POST /api/users/vin/bind` 并传 `bindSource: "car_app_authorize"`。

---

### 2.5 VIN绑定列表

```
GET /api/users/vin/list
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

**响应**:
```json
{
  "code": 0,
  "data": {
    "list": [
      { "id": 1, "vin": "LSVAU2A38J2150114", "vehicleBrand": "比亚迪", "vehicleModel": "汉EV", "plateNo": "京A12345", "isDefault": true, "status": "active" }
    ],
    "total": 1
  }
}
```

---

### 2.6 解绑车架号

```
DELETE /api/users/vin/:id
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

**响应**: `{ "code": 0, "data": { "vin": "LSVAU2A38J2150114" } }`

---

### 2.7 设置支付模式

```
POST /api/users/pay-mode
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| payMode | string | 是 | `"prepaid"` 预付费 / `"postpaid"` 后付费（信用支付） |

**请求**:
```json
{ "payMode": "prepaid" }
```

**响应**:
```json
{ "code": 0, "data": { "payMode": "prepaid" }, "message": "支付模式已切换为: 预付费（先充值后充电）" }
```

---

### 2.8 开通信用支付

```
POST /api/users/credit/authorize
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| provider | string | 是 | `"wechat_pay_score"` 微信支付分 / `"sesame_credit"` 芝麻信用 |
| authCode | string | 是 | 微信/支付宝返回的信用授权码 |

**请求**:
```json
{
  "provider": "wechat_pay_score",
  "authCode": "abc123def456"
}
```

**响应**:
```json
{
  "code": 0,
  "data": { "creditEnabled": true, "provider": "wechat_pay_score", "payMode": "postpaid" },
  "message": "信用支付已开通"
}
```

---

### 2.9 查询信用支付状态

```
GET /api/users/credit/status
```

**响应**:
```json
{ "code": 0, "data": { "creditEnabled": true, "payMode": "postpaid" } }
```

---

### 2.10 用户注册

```
POST /api/users/register
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| username | string | 是 | 用户名/充电账号 |
| password | string | 是 | 密码 |
| nickname | string | 否 | 昵称 |

**响应**: 返回 `{ token, user }`，与登录接口结构一致。

---

### 2.11 绑定手机号

```
POST /api/users/bind-phone
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| phone | string | 是 | 手机号 |
| code | string | 否 | 短信验证码 |

---

### 2.12 用户退出登录

```
POST /api/users/logout
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

---

### 2.13 积分与等级

```
GET /api/users/points      — 查询积分
GET /api/users/levels      — 获取等级配置
```

|---

### 2.14 签到与邀请

```
POST /api/users/checkin    — 每日签到
POST /api/users/invite     — 邀请好友
```

---

### 2.15 提现

```
POST /api/users/withdraw   — 申请提现
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| amount | int | 是 | 提现金额（分） |

---

## 3. 充电站模块

### 3.1 附近充电站列表

```
GET /api/stations
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| lng | float | 是 | 当前经度 |
| lat | float | 是 | 当前纬度 |
| radius | int | 否 | 搜索半径(米)，默认5000 |
| keyword | string | 否 | 站名模糊搜索 |

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "list": [
      {
        "id": 1,
        "name": "望京充电站",
        "address": "北京市朝阳区望京SOHO B1停车场",
        "lng": 116.4809,
        "lat": 40.0015,
        "distance": 1200,
        "image": "https://cdn.lkc.com/station/1.jpg",
        "openTime": "00:00-24:00",
        "totalPiles": 4,
        "idlePiles": 2,
        "minFee": 80,
        "tags": ["24小时", "有地锁"]
      }
    ],
    "total": 3
  }
}
```

| 字段 | 说明 |
|------|------|
| distance | 距离(米) |
| totalPiles | 总桩数 |
| idlePiles | 空闲枪数 |
| minFee | 计费参考最低价(分/度) |

---

### 3.2 充电站详情 + 桩列表

```
GET /api/stations/:id
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "id": 1,
    "name": "望京充电站",
    "address": "北京市朝阳区望京SOHO B1停车场",
    "lng": 116.4809,
    "lat": 40.0015,
    "openTime": "00:00-24:00",
    "phone": "400-xxx-xxxx",
    "images": ["https://cdn.lkc.com/station/1_1.jpg"],
    "piles": [
      {
        "id": 101,
        "sn": "LKC-P001-001",
        "gunCount": 2,
        "guns": [
          {
            "no": 1,
            "status": "idle",
            "power": 60,
            "voltage": 380,
            "rateFee": 80,
            "rateService": 50
          },
          {
            "no": 2,
            "status": "charging",
            "power": 60,
            "voltage": 380,
            "rateFee": 80,
            "rateService": 50
          }
        ]
      }
    ]
  }
}
```

**枪状态枚举**:

| status | 说明 | 小程序行为 |
|--------|------|------------|
| `idle` | 空闲 | 显示绿色，"可充电"，可扫码 |
| `charging` | 充电中 | 显示红色，不可选 |
| `offline` | 离线 | 显示灰色，"维护中" |
| `fault` | 故障 | 显示灰色，"故障" |
| `reserved` | 已预约 | 显示橙色 |

**费率说明**:
| 字段 | 含义 | 单位 |
|------|------|------|
| rateFee | 电费单价 | 分/度 (80 = 0.80元/度) |
| rateService | 服务费单价 | 分/度 (50 = 0.50元/度) |
| **合计** | rateFee + rateService | 用户看到的单价 |

---

### 3.3 桩实时状态查询

```
GET /api/piles/:sn
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "sn": "LKC-P001-001",
    "status": "charging",
    "gunStatus": {
      "gun1": "charging",
      "gun2": "idle"
    },
    "currentOrder": {
      "orderNo": "LC202606011200001",
      "gunNo": 1,
      "startTime": "2026-06-01T11:55:00Z",
      "duration": 300,
      "energy": 2.35,
      "fee": 306
    },
    "lastOnline": "2026-06-01T12:00:05Z"
  }
}
```

> 小程序扫码后可以用这个接口轮询获取桩最新状态，配合扫码页展示。

---

## 4. 充电流程模块

> 充电桩支持三种启动方式：**扫码充电**、**VIN充电**、**密码充电**。
> 扣款逻辑分两种：**预付费**（先充值后充电）、**后付费**（信用支付，先充后付）。

### 4.1 启动充电（扫码充电）

> **扫码充电两种入口路径**：
>
> **路径A — 小程序内扫码（已登录态）**  
> 用户已在 APP/小程序内保持登录态 → 点击扫码 → 识别桩编号 → 调用 `POST /api/charge/start` → 进入充电页。  
> ⚠️ 如果 Token 已过期（Bearer 头存在但验证失败），返回 `401 needLogin: true`，前端应弹出重新授权弹窗。
>
> **路径B — 微信「扫一扫」扫描桩码（跳转场景）**  
> 用户用系统相机或微信扫一扫扫描充电桩二维码 → 自动跳转小程序 → 弹出微信授权登录弹窗 → 用户点击「允许」→ 小程序拿到 `code` → 调用 `POST /api/charge/start-with-auth` → **一次请求完成：授权登录 + 自动注册 + 创建订单**。  
> 新用户无感注册（自动分配 openid、账号密码、注册积分），老用户静默登录，无需额外跳转应用商店。

---

#### 4.1a 已登录扫码（路径A）

```
POST /api/charge/start
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| pileSn | string | 是 | 充电桩编号 |
| gunNo | int | 是 | 枪号(1或2) |
| payMode | string | 否 | `"prepaid"` / `"postpaid"`，不传则使用用户偏好 |

**请求示例**:
```json
{
  "pileSn": "LKC-P001-001",
  "gunNo": 1
}
```

**响应**:
```json
{
  "code": 0,
  "data": {
    "orderNo": "LClz2k3fWxP9",
    "pileSn": "LKC-P001-001",
    "gunNo": 1,
    "startTime": "2026-07-14T09:10:00Z",
    "rateFee": 80,
    "rateService": 50,
    "totalFeeRate": 130,
    "status": "pending",
    "mode": "scan",
    "user": { "id": 1001, "nickname": "孔师傅", "balance": 12850, "payMode": "prepaid", "creditEnabled": false },
    "message": "订单已创建，请在桩上启动充电"
  }
}
```

**Token 过期错误**（Header 有 Authorization 但 Token 失效）:
```json
{
  "code": 401,
  "message": "登录已过期，请重新授权登录",
  "data": {
    "needLogin": true,
    "action": "请在弹窗中重新授权登录，或使用微信扫一扫重新进入"
  }
}
```

---

#### 4.1b 微信扫一扫新用户入口（路径B）⭐ 推荐新用户首次入口

```
POST /api/charge/start-with-auth
```

> **一体式接口**：一次请求完成「微信授权 → 自动登录/注册 → 创建订单」。  
> 前端无需先调 `/api/auth/login`，本接口内部走完全流程。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| code | string | 是 | `wx.login()` 返回的 code 凭证 |
| pileSn | string | 是 | 充电桩编号（扫码解析） |
| gunNo | int | 是 | 枪号 |
| userInfo.nickname | string | 否 | 微信头像昵称（新用户注册用） |
| userInfo.avatar | string | 否 | 微信头像URL |

**请求示例**:
```json
{
  "code": "0b1cZf000xyz123abc",
  "pileSn": "LKC-P001-001",
  "gunNo": 1,
  "userInfo": { "nickname": "孔师傅", "avatar": "https://thirdwx.xxx/avatar.jpg" }
}
```

**响应（老用户/静默登录）**:
```json
{
  "code": 0,
  "data": {
    "token": "eyJhbG...",
    "user": {
      "id": 1001, "nickname": "孔师傅", "avatar": "https://...", "phone": "137****0417",
      "balance": 12850, "payMode": "prepaid", "creditEnabled": false, "isNew": false
    },
    "order": {
      "orderNo": "LClz2khWxQ1", "pileSn": "LKC-P001-001", "gunNo": 1,
      "startTime": "2026-07-14T09:11:00Z", "rateFee": 80, "rateService": 50,
      "totalFeeRate": 130, "status": "pending", "mode": "scan"
    },
    "message": "欢迎回来 孔师傅，请在桩上启动充电"
  }
}
```

**响应（新用户/无感注册）**:
```json
{
  "code": 0,
  "data": {
    "token": "eyJhbG...",
    "user": {
      "id": 1002, "nickname": "新用户9527", "avatar": null, "phone": null,
      "balance": 0, "points": 20, "payMode": "prepaid", "creditEnabled": false, "isNew": true
    },
    "order": { "orderNo": "LClz2kkWxQ2", "pileSn": "LKC-P001-001", "gunNo": 1, "status": "pending", "mode": "scan" },
    "message": "欢迎 新用户9527！账户已自动创建，请在桩上启动充电"
  }
}
```

> **注册逻辑**：首次扫码自动创建 `charge_user` → 分配充电账号 `CK0001` → 密码同账号 → 奖励 20 积分 → 下发 Token → 创建订单。全程无需用户手动填表单。

---

#### 4.1c 桩实时状态查询（轮询）

> 小程序扫码后可以用这个接口轮询获取桩最新状态，配合扫码页展示。

---

### 4.1d VIN充电启动

```
POST /api/charge/start-by-vin
```

> **两种鉴权模式**：
> - **mode=default（旧版明文）**：平台侧匹配 VIN 绑定 → 创建订单 → 发远程启机帧。适用于不支持 ISO 15118 的旧桩。
> - **mode=challenge（ISO 15118 挑战-应答）**：平台下发挑战码给桩 → 桩结合车端 VIN 回传 → 平台校验后返回认证结果。安全等级更高。
> 
> **完整流程**：充电桩显示屏点击 VIN 充电模式 → 插枪 → 桩通过 CAN/BMS 读取 VIN → 上报平台（0xA9 明文或 0xAD 安全上报） → 平台匹配绑定信息 → 自动启机充电扣款。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| vin | string | mode=default 时必填 | 车架号(17位)，mode=challenge 时桩自动读取 |
| pileSn | string | 是 | 充电桩编号 |
| gunNo | int | 否 | 枪号，默认 1 |
| mode | string | 否 | `"default"` 直接匹配 / `"challenge"` 下发挑战码 / `"status"` 查询挑战码状态 |

**请求示例（default 模式）**:
```json
{
  "vin": "LSVAU2A38J2150114",
  "pileSn": "LKC-P001-001",
  "gunNo": 1,
  "mode": "default"
}
```

**请求示例（challenge 模式 — 下发挑战码）**:
```json
{
  "pileSn": "LKC-P001-001",
  "gunNo": 1,
  "mode": "challenge"
}
```

**请求示例（status 模式 — 查询挑战码）**:
```json
{
  "pileSn": "LKC-P001-001",
  "mode": "status"
}
```

**响应（default 模式 — VIN 匹配成功）**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "orderNo": "VIly2k3fWxP7",
    "pileSn": "LKC-P001-001",
    "gunNo": 1,
    "vin": "LSVAU2A38J2150114",
    "startTime": "2026-07-20T08:45:00Z",
    "rateFee": 76,
    "rateService": 500,
    "status": "pending",
    "mode": "VIN",
    "user": {
      "id": 1001,
      "nickname": "孔师傅",
      "balance": 12850,
      "vehicle": "比亚迪 汉EV",
      "plateNo": "京A12345",
      "payMode": "prepaid",
      "creditEnabled": false
    },
    "message": "VIN匹配成功: 孔师傅，请在桩上启动充电"
  }
}
```

**响应（challenge 模式 — 挑战码已下发）**:
```json
{
  "code": 0,
  "data": {
    "pileSn": "LKC-P001-001",
    "challenge": "a1b2c3d4e5f6...",
    "operatorId": "CN-TH-001",
    "ttl": 60,
    "message": "挑战码已下发，等待桩端安全上报（60秒有效）"
  }
}
```

**响应（status 模式 — 挑战码有效）**:
```json
{
  "code": 0,
  "data": {
    "pileSn": "LKC-P001-001",
    "challengeExists": true,
    "message": "挑战码有效，等待桩端上报"
  }
}
```

**错误场景**:
```json
{ "code": 4008, "message": "该车架号未绑定用户，请先在小程序中绑定" }
{ "code": 2002, "message": "余额不足（当前1.28元），请先充值" }
{ "code": 3001, "message": "充电桩不在线" }
{ "code": 1001, "message": "缺少车架号 VIN（mode=default时必填）" }
```

---

### 4.1e 密码充电启动

```
POST /api/charge/start-by-password
```

> **流程**：商家预设充电密码 → 用户在桩显示屏输入密码 → 验证通过后直接启动 → **跳过账户验证和计费逻辑**。
> ⚠️ 密码充电为商家内部使用，不扣费。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| password | string | 是 | 充电密码 |
| pileSn | string | 是 | 充电桩编号 |
| gunNo | int | 是 | 枪号 |

**请求示例**:
```json
{
  "password": "admin123",
  "pileSn": "LKC-P001-001",
  "gunNo": 2
}
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "orderNo": "PWly2k3fWxP8",
    "pileSn": "LKC-P001-001",
    "gunNo": 2,
    "startTime": "2026-07-14T08:46:00Z",
    "rateFee": 80,
    "rateService": 50,
    "status": "pending",
    "mode": "password",
    "message": "密码验证通过，请在桩上启动充电"
  }
}
```

**错误场景**:
```json
{ "code": 4000, "message": "未配置充电密码，请联系管理员" }
{ "code": 4003, "message": "密码错误" }
```

---

### 4.1f 账号登录充电 ⭐ v1.4 新增

```
POST /api/charge/start-by-account
```

> **场景**：用户在充电桩屏幕上输入充电账号+密码登录启动充电，跳过小程序扫码流程。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| account | string | 是 | 充电账号（手机号或账号ID） |
| password | string | 是 | 账号密码 |
| pileSn | string | 是 | 充电桩编号 |
| gunNo | int | 是 | 枪号 |

**响应**:
```json
{
  "code": 0,
  "data": {
    "orderNo": "ACly2k3fWxP0",
    "pileSn": "LKC-P001-001",
    "gunNo": 1,
    "startTime": "2026-07-29T08:30:00Z",
    "status": "pending",
    "mode": "account",
    "user": { "id": 1001, "nickname": "孔师傅", "balance": 12850 },
    "message": "账号验证通过，请在桩上启动充电"
  }
}
```

---

### 4.2 充电中实时数据（轮询）

```
GET /api/charge/:orderNo
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "orderNo": "LC202606011200001",
    "status": "charging",
    "pileSn": "LKC-P001-001",
    "gunNo": 1,
    "startTime": "2026-06-01T12:00:00Z",
    "duration": 480,
    "energy": 3.85,
    "fee": 501,
    "realTime": {
      "voltage": 385.2,
      "current": 28.6,
      "power": 11.02,
      "soc": 62,
      "temperature": 35
    }
  }
}
```

| 字段 | 类型 | 单位 | 说明 |
|------|------|------|------|
| duration | int | 秒 | 已充时长 |
| energy | float | kWh | 已充电量 |
| fee | int | 分 | 累计费用 |
| voltage | float | V | 实时电压 |
| current | float | A | 实时电流 |
| power | float | kW | 实时功率 |
| soc | int | % | 当前电池SOC |
| temperature | int | ℃ | 电池温度 |

> **轮询建议**: 小程序每 5 秒轮询一次。充电中页面用这些数据画实时曲线和进度条。

**status 状态流**:
```
charging → finished (正常结束)
charging → stopped  (用户主动停止)
charging → error    (异常中断)
```

---

### 4.3 结束充电

```
POST /api/charge/stop
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderNo | string | 是 | 订单编号 |

**请求示例**:
```json
{
  "orderNo": "LC202606011200001"
}
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "orderNo": "LC202606011200001",
    "stopTime": "2026-06-01T12:45:00Z",
    "status": "finished"
  }
}
```

> 前端收到此响应后，跳转到充电账单页。

---

### 4.4 充电账单

```
GET /api/charge/:orderNo/bill
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "orderNo": "LC202606011200001",
    "pileSn": "LKC-P001-001",
    "gunNo": 1,
    "stationName": "望京充电站",
    "startTime": "2026-06-01T12:00:00Z",
    "endTime": "2026-06-01T12:45:00Z",
    "duration": 2700,
    "startSoc": 20,
    "endSoc": 85,
    "energy": 19.50,
    "feeDetail": {
      "elecFee": 1560,
      "serviceFee": 975,
      "totalFee": 2535
    },
    "payStatus": "paid",
    "payTime": "2026-06-01T12:45:05Z",
    "balanceBefore": 12850,
    "balanceAfter": 10315
  }
}
```

| 字段 | 类型 | 说明 |
|------|------|------|
| duration | int | 充电时长(秒)，前端显示 "45分00秒" |
| energy | float | 充电度数(kWh) |
| elecFee | int | 电费(分) |
| serviceFee | int | 服务费(分) |
| totalFee | int | 合计(分) |
| payStatus | string | `paid` / `unpaid` |
| balanceBefore | int | 扣款前余额(分) |
| balanceAfter | int | 扣款后余额(分) |

---

## 5. 订单模块

### 5.1 订单列表

```
GET /api/admin/users/orders?userId={userId}
```

| Header | 值 |
|--------|-----|
| Authorization | Bearer {token} |

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| userId | int | 是 | 用户ID |
| page | int | 否 | 默认1 |
| pageSize | int | 否 | 默认20 |

**响应**: 返回标准分页结构，含订单列表。

---

### 5.2 订单详情（充电中/账单）

```
GET /api/charge/:orderNo
```

> 此接口对应 4.2 充电中实时轮询 和 4.4 充电账单，同一路由按订单状态返回不同数据。

---

## 6. 管理后台模块

> **认证方式**: 后台使用独立的用户名+密码登录，与小程序用户体系分开。  
> Token 同样放在 Header: `Authorization: Bearer {token}`  
> 所有管理后台接口路径前缀为 `/api/admin/`

### 6.1 管理员登录

```
POST /api/admin/login
```
> ⚡ **v1.1 更新**: 响应增加 `stationId`、`permission`、`realName` 字段，支持站长角色。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| username | string | 是 | 账号 |
| password | string | 是 | 密码 |

**请求**:
```json
{
  "username": "admin",
  "password": "123456"
}
```

**响应**:
```json
{
  "code": 0,
  "message": "登录成功",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "admin": {
      "id": 1,
      "username": "admin",
      "role": "super",
      "stationId": null,
      "realName": "超级管理员"
    },
    "permission": "all_stations"
  }
}
```

**角色与权限**:

| role | stationId | permission | 说明 |
|------|-----------|------------|------|
| `super` | null | `all_stations` | 超级管理员，全平台 |
| `admin` | null | `all_stations` | 管理员，全平台 |
| `station_master` | 具体站点ID | `single_station` | 站长，仅归属站点 |
| `operator` | null | 无管理后台权限 | 运营人员 |

### 6.1b 获取管理员信息

```
GET /api/admin/me
```

**响应**:
```json
{
  "code": 0,
  "data": {
    "id": 2,
    "username": "yt_station",
    "role": "station_master",
    "stationId": 1,
    "realName": "盐田站长",
    "permission": "single_station"
  }
}
```

> 前端用 `permission` 字段决定是否显示全站数据选择器；`station_master` 角色应隐藏站点切换功能。

---

### 6.2 充电桩管理列表

```
GET /api/admin/piles
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | int | 否 | 默认1 |
| pageSize | int | 否 | 默认20 |
| status | string | 否 | `online` / `offline` / `fault` / `all` |
| keyword | string | 否 | 桩编号/站名模糊搜索 |

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "list": [
      {
        "id": 1,
        "sn": "LKC-P001-001",
        "imei": "860123456789012",
        "model": "LKC-AC60-D",
        "stationName": "望京充电站",
        "status": "online",
        "gunCount": 2,
        "firmwareVer": "v2.1.3",
        "lastOnline": "2026-06-01T12:00:05Z",
        "todayEnergy": 156.8,
        "todayFee": 20384,
        "totalEnergy": 15230.5,
        "totalFee": 1980065
      }
    ],
    "total": 12,
    "page": 1,
    "pageSize": 20,
    "totalPages": 1
  }
}
```

---

### 6.3 添加充电桩

```
POST /api/admin/piles
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| sn | string | 是 | 桩编号 |
| imei | string | 是 | IMEI |
| model | string | 是 | 型号 |
| stationId | int | 是 | 所属充电站ID |
| gunCount | int | 是 | 枪数(1或2) |

**请求**:
```json
{
  "sn": "LKC-P002-001",
  "imei": "860123456789013",
  "model": "LKC-AC60-D",
  "stationId": 1,
  "gunCount": 2
}
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "id": 13,
    "sn": "LKC-P002-001"
  }
}
```

---

### 6.4 编辑充电桩

```
PUT /api/admin/piles/:id
```

| 参数 | 类型 | 说明 |
|------|------|------|
| stationId | int | 更换所属电站 |
| model | string | 型号 |
| gunCount | int | 枪数 |
| firmwareVer | string | 固件版本(手动更新记录) |

**请求**:
```json
{
  "stationId": 2,
  "firmwareVer": "v2.2.0"
}
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": null
}
```

---

### 6.5 删除充电桩

```
DELETE /api/admin/piles/:id
```

**响应**:
```json
{
  "code": 0,
  "message": "充电桩已删除",
  "data": null
}
```

---

### 6.6 远程重启充电桩

```
POST /api/admin/pile/restart
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| pileId | int | 是 | 桩ID |

**请求**:
```json
{
  "pileId": 1
}
```

**响应**:
```json
{
  "code": 0,
  "message": "重启指令已下发",
  "data": {
    "commandId": "cmd-abc123"
  }
}
```

> 对应协议帧: `0x92 远程重启`  
> 下发后桩会返回 `0x91 远程重启应答`，后台通过 WebSocket 推送执行结果。

---

### 6.7 远程升级固件

```
POST /api/admin/pile/update
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| pileId | int | 是 | 桩ID |
| firmwareUrl | string | 是 | 固件下载地址 |
| firmwareVer | string | 是 | 新版本号 |
| md5 | string | 是 | 固件包MD5 |

**请求**:
```json
{
  "pileId": 1,
  "firmwareUrl": "https://cdn.lkc.com/firmware/v2.2.0.bin",
  "firmwareVer": "v2.2.0",
  "md5": "d41d8cd98f00b204e9800998ecf8427e"
}
```

**响应**:
```json
{
  "code": 0,
  "message": "升级指令已下发",
  "data": {
    "commandId": "cmd-abc456"
  }
}
```

> 对应协议帧: `0x94 远程更新`

---

### 6.8 费率管理列表

```
GET /api/admin/rates
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "list": [
      {
        "id": 1,
        "name": "标准费率",
        "elecFee": 80,
        "serviceFee": 50,
        "desc": "全天统一",
        "isDefault": true,
        "pileCount": 8
      },
      {
        "id": 2,
        "name": "峰谷费率-峰时",
        "elecFee": 120,
        "serviceFee": 50,
        "timeRange": "08:00-22:00",
        "pileCount": 4
      },
      {
        "id": 3,
        "name": "峰谷费率-谷时",
        "elecFee": 40,
        "serviceFee": 50,
        "timeRange": "22:00-08:00",
        "pileCount": 4
      }
    ]
  }
}
```

---

### 6.9 创建费率

```
POST /api/admin/rates
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | string | 是 | 费率名称 |
| elecFee | int | 是 | 电费单价(分/度) |
| serviceFee | int | 是 | 服务费单价(分/度) |
| timeRange | string | 否 | 时段范围 "08:00-22:00"，不填=全天 |
| isDefault | bool | 否 | 是否默认费率 |

**请求**:
```json
{
  "name": "标准费率",
  "elecFee": 80,
  "serviceFee": 50,
  "isDefault": true
}
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "id": 34
  }
}
```

---

### 6.10 编辑费率

```
PUT /api/admin/rates/:id
```

参数同创建。已有交易记录的费率不可删除，只能停用或修改。

---

### 6.11 桩-费率绑定

```
POST /api/admin/piles/:id/bind-rate
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| rateId | int | 是 | 费率ID |

**请求**:
```json
{
  "rateId": 2
}
```

**响应**:
```json
{
  "code": 0,
  "message": "费率已绑定，将在下一个心跳周期同步到充电桩",
  "data": null
}
```

> 对应协议帧: `0x58 计费模型设置`。绑定后系统通过心跳应答自动下发最新费率到桩。

---

### 6.12 交易流水

```
GET /api/admin/transactions
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| page | int | 否 | 默认1 |
| pageSize | int | 否 | 默认20 |
| startDate | string | 否 | 开始日期 "2026-06-01" |
| endDate | string | 否 | 结束日期 |
| type | string | 否 | `recharge` / `charge` / `refund` |
| userId | int | 否 | 按用户筛选 |

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "list": [
      {
        "id": 1,
        "userId": 1001,
        "userName": "孔师傅",
        "type": "charge",
        "orderNo": "LC202606011200001",
        "amount": -2535,
        "balanceBefore": 12850,
        "balanceAfter": 10315,
        "createdAt": "2026-06-01T12:45:05Z"
      }
    ],
    "total": 562,
    "page": 1,
    "pageSize": 20,
    "totalPages": 29
  }
}
```

---

### 6.13 营收日报

```
GET /api/admin/report/daily
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| date | string | 否 | 日期 "2026-06-01"，不填=今天 |
| stationId | int | 否 | 按电站筛选 |

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "date": "2026-06-01",
    "totalOrders": 42,
    "totalEnergy": 680.5,
    "totalElecFee": 54440,
    "totalServiceFee": 34025,
    "totalFee": 88465,
    "rechargeTotal": 50000,
    "hourlyBreakdown": [
      { "hour": 0, "orders": 2, "energy": 30.2, "fee": 3926 },
      { "hour": 1, "orders": 1, "energy": 15.0, "fee": 1950 }
    ],
    "pileBreakdown": [
      { "pileSn": "LKC-P001-001", "orders": 8, "energy": 120.5, "fee": 15665 }
    ]
  }
}
```

---

### 6.14 营收月报

```
GET /api/admin/report/monthly
```

| 参数 | 类型 | 说明 |
|------|------|------|
| month | string | "2026-06" |

**响应**: 结构同日，多一个 `dailyTrend` 数组用于折线图。

```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "month": "2026-06",
    "totalOrders": 1200,
    "totalEnergy": 18500,
    "totalFee": 2405000,
    "dailyTrend": [
      { "date": "2026-06-01", "orders": 42, "fee": 88465 },
      { "date": "2026-06-02", "orders": 38, "fee": 79200 }
    ]
  }
}
```

---

### 6.15 充电站管理列表

```
GET /api/admin/stations
```

**响应**:
```json
{
  "code": 0,
  "message": "ok",
  "data": {
    "list": [
      {
        "id": 1,
        "name": "望京充电站",
        "address": "北京市朝阳区望京SOHO B1停车场",
        "lng": 116.4809,
        "lat": 40.0015,
        "pileCount": 4,
        "totalGuns": 8,
        "onlineCount": 3,
        "status": "open",
        "createdAt": "2026-03-01T00:00:00Z"
      }
    ]
  }
}
```

---

### 6.16 创建充电站

```
POST /api/admin/stations
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | string | 是 | 站名 |
| address | string | 是 | 地址 |
| lng | float | 是 | 经度 |
| lat | float | 是 | 纬度 |
| openTime | string | 否 | 营业时间，默认 "00:00-24:00" |
| phone | string | 否 | 联系电话 |
| images | array | 否 | 图片URL数组 |

---

### 6.17 编辑充电站

```
PUT /api/admin/stations/:id
```
参数同创建，全部可选填。

---

### 6.18 VIN批量导入（车队管理）

```
POST /api/admin/vin/batch
```

> **场景**：企业车队管理员批量导入车辆VIN码。支持同时指定用户账号关联。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| batchName | string | 是 | 批次名称，如"盐田港2026Q3车队" |
| vehicles | array | 是 | 车辆列表 |
| vehicles[].vin | string | 是 | 车架号(17位) |
| vehicles[].brand | string | 否 | 品牌 |
| vehicles[].model | string | 否 | 型号 |
| vehicles[].plateNo | string | 否 | 车牌 |
| vehicles[].userAccount | string | 否 | 用户手机号/充电账号，存在则直接绑定 |
| overwriteExisting | bool | 否 | 是否覆盖已存在的VIN绑定，默认 false |

**请求示例**:
```json
{
  "batchName": "盐田港2026Q3车队",
  "vehicles": [
    { "vin": "LSVAU2A38J2150114", "brand": "比亚迪", "model": "汉EV", "plateNo": "京A12345", "userAccount": "13712345678" },
    { "vin": "LNBMDBAH4FU055511", "brand": "北汽", "model": "EU5", "plateNo": "京B56789", "userAccount": "qc001" }
  ],
  "overwriteExisting": false
}
```

**响应**:
```json
{
  "code": 0,
  "data": {
    "batchId": 1,
    "batchName": "盐田港2026Q3车队",
    "total": 2,
    "success": 1,
    "fail": 1,
    "failDetail": [
      { "row": 3, "vin": "LNBMDBAH4FU055511", "reason": "VIN已被绑定，跳过" }
    ],
    "status": "partial_ok"
  }
}
```

---

### 6.19 批量导入批次列表

```
GET /api/admin/vin/batch/list
```

**响应**:
```json
{
  "code": 0,
  "data": {
    "list": [
      { "id": 1, "batch_name": "盐田港2026Q3车队", "total_count": 100, "success_count": 97, "fail_count": 3, "status": "partial_ok", "operator_name": "admin", "created_at": "2026-07-14T00:30:00Z" }
    ]
  }
}
```

---

### 6.20 批次详情（含失败明细）

```
GET /api/admin/vin/batch/:id
```

**响应**: 完整批次对象 + `failDetail` 数组（每笔失败的 row/vin/reason）。

---

### 6.21 充电密码预设管理

```
POST   /api/admin/password-preset      创建密码预设
PUT    /api/admin/password-preset/:id  更新密码预设
DELETE /api/admin/password-preset/:id  删除密码预设
GET    /api/admin/password-presets     密码预设列表
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| password | string | 是（创建/更新时） | 明文密码，服务端bcrypt加密 |
| stationId | int | 否 | 站点ID，NULL=全局密码 |
| remark | string | 否 | 备注说明 |
| status | string | 否（更新时） | active / disabled |

---

### 6.22 站点服务费规格管理 ⭐ v1.1 新增

> 每个站点的服务费由站长/管理通过规格词条独立设置，支持分时段差异化定价。  
> 充电计费链路：`rate-selector` 根据当前时段从 `station_service_fee_spec` 匹配对应服务费。

#### 6.22.1 创建服务费规格

```
POST /api/stations/service-fee
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| stationId | int | 是 | 站点ID |
| specName | string | 否 | 规格名称，默认"标准服务费" |
| serviceFee | int | 是 | 服务费(分/度) |
| timeStart | string | 否 | 时段开始 HH:MM，如"22:00"，null=全天 |
| timeEnd | string | 否 | 时段结束 HH:MM，如"06:00"，null=全天 |
| isDefault | bool | 否 | 是否默认规格，默认true |

> 创建默认规格时自动清除该站点旧默认。  
> 站长只能操作自己归属站点，跨站操作返回 403。

**请求**:
```json
{
  "stationId": 2,
  "specName": "龙华夜间特惠",
  "serviceFee": 30,
  "timeStart": "22:00",
  "timeEnd": "06:00",
  "isDefault": false
}
```

**响应**:
```json
{
  "code": 0,
  "data": {
    "id": 3,
    "station_id": 2,
    "spec_name": "龙华夜间特惠",
    "service_fee": 30,
    "service_feeYuan": "0.30",
    "time_start": "22:00",
    "time_end": "06:00",
    "is_default": 0,
    "status": "active"
  }
}
```

#### 6.22.2 查询站点服务费规格列表

```
GET /api/stations/service-fee/list?stationId=1
```

**响应**:
```json
{
  "code": 0,
  "data": {
    "stationId": 1,
    "specs": [
      {
        "id": 1,
        "spec_name": "标准服务费",
        "service_fee": 50,
        "service_feeYuan": "0.50",
        "time_start": null,
        "time_end": null,
        "is_default": 1,
        "status": "active"
      }
    ]
  }
}
```

#### 6.22.3 删除服务费规格

```
DELETE /api/stations/service-fee/:id
```

> 软禁用（status=disabled），不会物理删除。需 admin token。

---

### 6.23 运营看板 ⭐ v1.1 新增

> 按站点+按天汇总订单、电量、电费、服务费。  
> 管理员看全站，站长仅看归属站点数据（自动隔离）。

#### 6.23.1 看板汇总

```
GET /api/dashboard
GET /api/stats
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| date | string | 否 | 指定日期 YYYY-MM-DD |
| from | string | 否 | 开始日期 YYYY-MM-DD |
| to | string | 否 | 结束日期 YYYY-MM-DD |
| month | string | 否 | 整月 YYYY-MM（自动计算月初到月末） |
| stationId | int | 否 | 站点ID（管理员可用，站长忽略此参数自动限定归属站） |

> `date` / `from+to` / `month` 三选一。  
> 不带任何日期参数默认查当天。

**响应** (`/api/dashboard`):
```json
{
  "code": 0,
  "data": {
    "dateFrom": "2026-07-14",
    "dateTo": "2026-07-14",
    "stationFilter": "all",
    "summary": {
      "orderCnt": 2,
      "energy": 46.2,
      "totalFee": 8963,
      "totalFeeYuan": "89.63",
      "elecFee": 5960,
      "elecFeeYuan": "59.60",
      "serviceFee": 3003,
      "serviceFeeYuan": "30.03",
      "paidFee": 8963,
      "paidFeeYuan": "89.63",
      "finishedCnt": 2
    },
    "daily": [
      {
        "date": "2026-07-14",
        "orderCnt": 2,
        "energy": 46.2,
        "totalFee": 8963,
        "totalFeeYuan": "89.63",
        "elecFee": 5960,
        "elecFeeYuan": "59.60",
        "serviceFee": 3003,
        "serviceFeeYuan": "30.03",
        "paidFee": 8963,
        "paidFeeYuan": "89.63",
        "vinCnt": 1,
        "pwdCnt": 0,
        "scanCnt": 1
      }
    ],
    "byStation": [
      {
        "stationId": 2,
        "stationName": "龙华工业园充电站",
        "orderCnt": 1,
        "energy": 23.1,
        "totalFee": 4828,
        "totalFeeYuan": "48.28",
        "serviceFee": 1848,
        "serviceFeeYuan": "18.48"
      },
      {
        "stationId": 1,
        "stationName": "盐田港充电站",
        "orderCnt": 1,
        "energy": 23.1,
        "totalFee": 4135,
        "totalFeeYuan": "41.35",
        "serviceFee": 1155,
        "serviceFeeYuan": "11.55"
      }
    ]
  }
}
```

**响应** (`/api/stats`):
```json
{
  "code": 0,
  "data": {
    "from": "2026-07-01",
    "to": "2026-07-14",
    "stationFilter": "1",
    "monthly": { "orderCnt": 45, "energy": 1024.5, "totalFee": 183200, "totalFeeYuan": "1832.00", "elecFee": 124800, "elecFeeYuan": "1248.00", "serviceFee": 58400, "serviceFeeYuan": "584.00", "finishedCnt": 42, "paidFee": 180000, "paidFeeYuan": "1800.00" },
    "daily": [ { "date": "2026-07-14", "cnt": 2, "energy": 46.2, "totalFee": 8963, "totalFeeYuan": "89.63", "elecFee": 5960, "elecFeeYuan": "59.60", "serviceFee": 3003, "serviceFeeYuan": "30.03", "paidFee": 8963, "paidFeeYuan": "89.63" } ],
    "byStation": [ { "id": 1, "name": "盐田港充电站", "cnt": 45, "energy": 1024.5, "totalFee": 183200, "totalFeeYuan": "1832.00", "serviceFee": 58400, "serviceFeeYuan": "584.00" } ],
    "byPile": [ { "sn": "YT-P001-001", "model": "LKC-AC60-D", "cnt": 22, "energy": 512.3, "totalFee": 91600, "totalFeeYuan": "916.00", "serviceFee": 29200, "serviceFeeYuan": "292.00" } ],
    "total": { "orderCnt": 1560, "energy": 32000.5, "totalFee": 5769000, "totalFeeYuan": "57690.00", "elecFee": 3920000, "elecFeeYuan": "39200.00", "serviceFee": 1849000, "serviceFeeYuan": "18490.00", "paidFee": 5705000, "paidFeeYuan": "57050.00" }
  }
}
```

### 6.24 费用单位约定 ⭐ v1.1 新增

> 数据库全量以**分**（BIGINT 整数）存储，API 响应同时提供分字段和元字段。

| 分字段 | 对应元字段 | 示例 |
|--------|-----------|------|
| `totalFee` | `totalFeeYuan` | `8963` → `"89.63"` |
| `elecFee` | `elecFeeYuan` | `5960` → `"59.60"` |
| `serviceFee` | `serviceFeeYuan` | `3003` → `"30.03"` |
| `balance` | `balanceYuan` | `12850` → `"128.50"` |
| `amount` | `amountYuan` | `-4135` → `"-41.35"` |
| `paidFee` | `paidFeeYuan` | `5705000` → `"57050.00"` |

> 前端展示统一用 `*Yuan` 字段，分字段仅用于精度计算。  
> 费率（电费/服务费单价）同样是分/度存储 + `*Yuan` 元/度显示。

---

## 附录A: 通用数据字典

### A.1 充电桩状态

| 值 | 含义 |
|----|------|
| `online` | 在线（TCP连接正常） |
| `offline` | 离线（心跳超时） |
| `fault` | 故障（桩主动上报错误） |
| `maintenance` | 维护中（管理员手动标记） |

### A.2 枪状态

| 值 | 含义 |
|----|------|
| `idle` | 空闲 |
| `charging` | 充电中 |
| `reserved` | 已预约 |
| `offline` | 离线 |
| `fault` | 故障 |

### A.3 订单状态

| 值 | 含义 |
|----|------|
| `pending` | 等待充电桩确认启机 |
| `charging` | 充电中 |
| `finished` | 正常结束 |
| `stopped` | 用户主动停止 |
| `error` | 异常中断 |

### A.4 支付状态

| 值 | 含义 |
|----|------|
| `paid` | 已扣费 |
| `unpaid` | 未扣费（预付费余额不足或后付费待扣款） |
| `overdue` | 欠费（预付费余额不足，已记录欠费流水） |
| `failed` | 后付费扣款失败 |
| `pending` | 后付费等待回调确认 |

### A.5 启动方式 (start_mode)

| 值 | 含义 |
|----|------|
| `scan` | 扫码充电 |
| `VIN` | VIN码充电（插枪自动识别） |
| `password` | 密码充电 |
| `account` | 账号登录充电 |
| `card` | 刷卡充电 |

### A.6 支付模式 (pay_mode)

| 值 | 含义 |
|----|------|
| `prepaid` | 预付费（余额实时扣款） |
| `postpaid` | 后付费（信用支付，充电后异步扣款） |

### A.7 交易类型

| 值 | 含义 |
|----|------|
| `recharge` | 充值 |
| `charge` | 充电扣费 |
| `refund` | 退款 |

### A.8 管理员角色

| role | stationId | permission | 说明 |
|------|-----------|------------|------|
| `super` | null | `all_stations` | 超级管理员，全平台数据 |
| `admin` | null | `all_stations` | 管理员，全平台 |
| `station_master` | 站点ID | `single_station` | 站长，仅归属站点 |
| `operator` | null | — | 运营人员（无管理后台权限） |

---

### 6.19 企业管理 ⭐ v1.3 新增

> **场景**：平台管理员创建和管理充电服务的企业客户（物流公司、运输公司等）。

#### 6.19.1 企业列表

```
GET /api/admin/enterprise/list
```

**响应 data**:

```json
{
  "list": [
    {
      "id": 1,
      "name": "深圳天策物流有限公司",
      "credit_code": "91440300MA5XXXXXXXX",
      "contact_name": "张总",
      "contact_phone": "13800138000",
      "address": null,
      "remark": null,
      "created_at": "2026-07-17T00:00:00Z"
    }
  ]
}
```

#### 6.19.2 创建企业

```
POST /api/admin/enterprise
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| name | string | 是 | 企业名称 |
| creditCode | string | 否 | 统一社会信用代码 |
| contactName | string | 否 | 联系人 |
| contactPhone | string | 否 | 联系电话 |
| address | string | 否 | 地址 |
| remark | string | 否 | 备注 |

#### 6.19.3 企业详情

```
GET /api/admin/enterprise/:id
```

#### 6.19.4 编辑企业

```
PUT /api/admin/enterprise/:id
```

参数同创建，所有字段可选。

#### 6.19.5 删除企业

```
DELETE /api/admin/enterprise/:id
```

---

### 6.20 车队/组织机构管理 ⭐ v1.3 新增

> **场景**：每个企业下挂多个车队（或部门），车队可设置独立停止码和专用站标记。
> 
> **设计参考**：国网智慧车联网平台的重卡场站方案——企业下挂车队，车队可设置群组定价。

#### 6.20.1 车队列表

```
GET /api/admin/org/list?enterpriseId=1
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| enterpriseId | number | 否 | 筛选企业ID |

**响应 data** — 数组：

```json
[
  {
    "id": 1,
    "enterprise_id": 1,
    "name": "盐田港罐车车队",
    "short_name": "罐车队",
    "org_type": "fleet",
    "stop_code": "4396",
    "is_dedicated_station": 1,
    "memberCount": 12,
    "created_at": "2026-07-17T00:00:00Z"
  }
]
```

**字段说明**:

| 字段 | 说明 |
|------|------|
| org_type | `fleet`（车队）或 `department`（部门） |
| stop_code | 专用站停止码，BMS 报文匹配 |
| is_dedicated_station | `1`=专用站（满电自停），`0`=普通站 |

#### 6.20.2 创建车队

```
POST /api/admin/org
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| enterpriseId | number | 是 | 所属企业ID |
| name | string | 是 | 车队名称 |
| shortName | string | 否 | 简称 |
| orgType | string | 否 | `fleet`/`department`，默认 `fleet` |
| stopCode | string | 否 | 停止码（1-8位） |
| isDedicatedStation | number | 否 | `0`/`1`，默认 `0` |

#### 6.20.3 车队详情

```
GET /api/admin/org/:id
```

#### 6.20.4 编辑车队

```
PUT /api/admin/org/:id
```

参数同创建。

#### 6.20.5 删除车队

```
DELETE /api/admin/org/:id
```

#### 6.20.6 车队成员列表

```
GET /api/admin/org/members?orgId=1
```

**响应 data** — 数组：

```json
[
  {
    "id": 16,
    "nickname": "南城旧梦",
    "phone": "13800138000",
    "balance": 200082052,
    "charge_count": 42,
    "vins": [
      { "vin": "LB3781NZ4SH131205", "is_default": true }
    ]
  }
]
```

#### 6.20.7 添加成员到车队

```
POST /api/admin/org/member
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| orgId | number | 是 | 车队ID |
| userId | number | 是 | 用户ID |

#### 6.20.8 移出车队成员

```
DELETE /api/admin/org/member/:userId
```

---

### 6.21 群组定价活动 ⭐ v1.3 新增

> **场景**：为车队设置专属电价/服务费，覆盖站点默认费率。
> 
> **设计参考**：国网"立减活动"模型——一个车队同时只有一个活跃定价活动，启用新活动时自动停用旧的。

#### 6.21.1 定价活动列表

```
GET /api/admin/pricing-activity/list?orgId=1&status=active
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| orgId | number | 否 | 筛选车队ID |
| status | string | 否 | `active`/`pending`/`stopped` |

**响应 data** — 数组：

```json
[
  {
    "id": 1,
    "org_id": 1,
    "org_name": "盐田港罐车车队",
    "activity_name": "罐车队VIP专属价",
    "discount_mode": "replace",
    "elec_fee": 76,
    "service_fee": 50,
    "reduce_amount": null,
    "reduce_pct": null,
    "charge_methods": "vin,scan",
    "is_offline_settle": 1,
    "offline_settle_period": "weekly",
    "status": "active",
    "start_time": "2026-07-01T00:00:00Z",
    "end_time": "2026-12-31T23:59:59Z"
  }
]
```

**字段说明**:

| 字段 | 类型 | 说明 |
|------|------|------|
| discount_mode | string | `replace`（替换费率）/ `reduce`（减固定值） / `reduce_pct`（折扣百分比） |
| elec_fee | number\|null | 电费（分/度），`null`=用站点默认 |
| service_fee | number\|null | 服务费（分/度），`null`=用站点默认 |
| reduce_amount | number\|null | reduce 模式：减去服务费金额（分） |
| reduce_pct | number\|null | reduce_pct 模式：折扣百分比（如 85 表示 85%） |
| charge_methods | string | 适用充电方式：`vin,scan,password` 组合 |
| is_offline_settle | number | `1`=线下结算（不扣平台余额），`0`=平台扣款 |
| offline_settle_period | string | 线下结算周期：`weekly`/`monthly`/`quarterly` |

#### 6.21.2 创建定价活动

```
POST /api/admin/pricing-activity
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| orgId | number | 是 | 车队ID |
| activityName | string | 是 | 活动名称 |
| discountMode | string | 是 | `replace`/`reduce`/`reduce_pct` |
| elecFee | number\|null | 否 | 电费（分/度） |
| serviceFee | number\|null | 否 | 服务费（分/度） |
| reduceAmount | number\|null | 否 | reduce 模式专用 |
| reducePct | number\|null | 否 | reduce_pct 模式专用 |
| chargeMethods | string | 否 | 默认 `vin,scan,password` |
| isOfflineSettle | boolean | 否 | 默认 `false` |
| offlineSettlePeriod | string | 否 | 默认 `weekly` |
| startTime | string | 是 | ISO 8601 时间 |
| endTime | string | 是 | ISO 8601 时间 |

#### 6.21.3 定价活动详情

```
GET /api/admin/pricing-activity/:id
```

#### 6.21.4 编辑定价活动

```
PUT /api/admin/pricing-activity/:id
```

#### 6.21.5 删除（停用）定价活动

```
DELETE /api/admin/pricing-activity/:id
```

> 注意：删除操作实际是停用（status→stopped），不会物理删除记录。

#### 6.21.6 启用定价活动

```
POST /api/admin/pricing-activity/activate
Content-Type: application/json

{ "id": 1 }
```

> 启用后自动停用同车队的其他活跃活动（互斥）。

#### 6.21.7 停用定价活动

```
POST /api/admin/pricing-activity/stop
Content-Type: application/json

{ "id": 1 }
```

---

### 6.22 线下清分结算 ⭐ v1.3 新增

> **场景**：企业对账——车队定价中 `isOfflineSettle=1` 的订单不扣平台余额，由企业与车队线下结算。平台定期生成结算报表供双方对账。
> 
> **结算流程**：选择车队+周期 → 生成结算记录 → 线下打款 → 标记已结算

#### 6.22.1 结算记录列表

```
GET /api/admin/settle/list?orgId=1
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| orgId | number | 否 | 筛选车队 |

**响应 data** — 数组：

```json
[
  {
    "id": 1,
    "org_id": 1,
    "org_name": "盐田港罐车车队",
    "settle_period": "2026-W30",
    "start_date": "2026-07-20T00:00:00Z",
    "end_date": "2026-07-26T23:59:59Z",
    "total_orders": 48,
    "total_energy": "326.50",
    "total_fee": 41139,
    "settled_amount": 41139,
    "status": "settled",
    "created_at": "2026-07-20T10:00:00Z",
    "settled_at": "2026-07-21T09:30:00Z"
  }
]
```

**字段说明**:

| 字段 | 说明 |
|------|------|
| total_fee | 应付金额（分） |
| settled_amount | 实收金额（分） |
| status | `pending`（待结算）/ `settled`（已结算） |

#### 6.22.2 生成结算记录

```
POST /api/admin/settle/generate
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| orgId | number | 是 | 车队ID |
| settlePeriod | string | 是 | 结算周期标识（如 `2026-W30`） |
| startDate | string | 否 | 开始日期（ISO 8601，默认结算周期起始） |
| endDate | string | 否 | 结束日期（ISO 8601，默认结算周期结束） |

> 系统自动统计该车队在时间范围内 `is_offline_settle=1` 的所有已结束订单，汇总生成结算记录。同一周期重复生成会更新原记录。

#### 6.22.3 结算详情

```
GET /api/admin/settle/:id
```

**响应 data** 包含结算记录 + orders 数组（该结算周期内的订单明细）。

#### 6.22.4 标记已结算

```
POST /api/admin/settle/mark
```

| 参数 | 类型 | 必需 | 说明 |
|------|------|------|------|
| id | number | 是 | 结算记录ID |
| settledAmount | number | 是 | 实际结算金额（分） |

#### 6.22.5 CSV 导出

```
GET /api/admin/settle/export?id=1
```

响应 `Content-Type: text/csv; charset=utf-8`，可直接下载或在 Excel 中打开。

#### 6.22.6 发票预览（HTML）

```
GET /api/admin/settle/invoice-preview?id=1
```

> 返回格式化的 HTML 页面，样式参照标准企业对账发票。仅供预览和对账参考，非税务发票。

---

### 6.29 国网基准电价 ⭐ v1.4 新增

```
POST /api/admin/guowang-rate    — 设置国网基准电价
GET  /api/admin/guowang-rate    — 查询国网基准电价列表
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| stationId | int | 是 | 站点ID |
| peakRate | int | 否 | 峰时电价（分/度） |
| flatRate | int | 否 | 平时电价（分/度） |
| valleyRate | int | 否 | 谷时电价（分/度） |

---

### 6.30 远程启机 ⭐ v1.4 新增

```
POST /api/admin/remote-start
```

> 管理员手动下发远程启机指令给充电桩。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| sn | string | 是 | 充电桩编号 |
| gunNo | int | 是 | 枪号 |

---

### 6.31 即插即充 ⭐ v1.4 新增

```
POST /api/admin/enable-plug-charge
```

> 为指定充电桩启用即插即充功能。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| sn | string | 是 | 充电桩编号 |
| enabled | bool | 是 | true=启用 / false=停用 |

---

### 6.32 BMS电池诊断 ⭐ v1.4 新增

```
GET /api/admin/bms/diagnose?sn={pileSn}   — AI 电池诊断
GET /api/admin/bms/logs?sn={pileSn}       — BMS 日志查询
```

> 分析充电桩上报的 BMS 数据，输出电池健康评估报告。

---

### 6.33 用户管理 ⭐ v1.4 新增

```
GET /api/users                  — 用户列表（管理后台用）
GET /api/users/:id              — 用户详情
GET /api/admin/users/orders     — 按用户查询订单
GET /api/admin/user/transactions — 用户交易流水
GET /api/admin/user/vin/list    — 管理员查看用户VIN绑定列表
POST /api/admin/user/vin/bind   — 管理员代绑VIN
DELETE /api/admin/user/vin/:id   — 管理员解绑VIN
```

---

### 6.34 提现审核 ⭐ v1.4 新增

```
GET  /api/admin/withdraw/list            — 提现申请列表
POST /api/admin/withdraw/review          — 审核通过/拒绝
```

| 参数（审核） | 类型 | 必填 | 说明 |
|-------------|------|------|------|
| id | int | 是 | 提现申请ID |
| action | string | 是 | approve / reject |
| reason | string | 否 | 拒绝原因 |

---

### 6.35 移动充电设备管理 ⭐ v1.4 新增

> 移动充电小车/地牛式拉杆车的设备管理、借用归还、锁定解锁。

```
管理端：
POST   /api/admin/mobile/device                 — 创建设备
PUT    /api/admin/mobile/device/:id              — 编辑设备
DELETE /api/admin/mobile/device/:id              — 删除设备
GET    /api/admin/mobile/device/:id              — 设备详情
GET    /api/admin/mobile/device/map             — 设备地图
POST   /api/admin/mobile/device/emergency-stop  — 紧急停机
POST   /api/admin/mobile/device/lock            — 锁定设备
POST   /api/admin/mobile/device/unlock          — 解锁设备
POST   /api/admin/mobile/station                — 创建移动充电站点
PUT    /api/admin/mobile/station/:id            — 编辑站点
DELETE /api/admin/mobile/station/:id            — 删除站点
GET    /api/admin/mobile/order/list             — 订单列表
GET    /api/admin/mobile/stats                  — 移动设备统计

用户端：
GET    /api/mobile/device/list                  — 可借设备列表
POST   /api/mobile/device/borrow                — 借用设备
POST   /api/mobile/device/return                — 归还设备
GET    /api/mobile/order/:id                    — 订单状态
POST   /api/mobile/charge/stop                  — 停止充电
GET    /api/mobile/station/list                 — 站点列表
GET    /api/mobile/rate                         — 费率查询
```

---

### 6.36 车队VIN批操作 ⭐ v1.4 新增

```
POST /api/admin/org/vin-bind    — 车队批量VIN绑定
POST /api/admin/org/vin-batch   — 车队批量VIN导入
```

> 功能类似 6.18 VIN批量导入，但绑定到具体车队（org），用于车队级别的车辆管理。

---

### 6.37 车队停止码设置 ⭐ v1.4 新增

```
PUT /api/admin/org/stop-code/:id
```

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| stopCode | string | 是 | 停止码（1-8位数字） |

> 配合停止码验证：`POST /api/charge/verify-stop-code`

---

## 7. 支付模块

### 7.1 统一下单

```
POST /api/pay/unified-order
```

> 小程序端发起微信支付时调用此接口生成预支付订单。

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| amount | int | 是 | 支付金额（分） |
| type | string | 是 | recharge / charge |
| orderNo | string | 否 | 关联订单号（充电扣费时） |

---

### 7.2 支付回调

```
POST /api/pay/notify
```

> 微信支付异步通知回调，由微信服务器调用，无需认证。

---

### 7.3 信用支付回调

```
POST /api/callback/credit-pay
```

> 微信支付分/芝麻信用异步扣款结果回调，无需认证。

---

## 附录A: 通用数据字典

> **给新人**: 建议用 Express + JSON 文件搭建 Mock Server，整个搭建不超过半天。

### B.1 项目结构

```
mock-server/
├── package.json
├── server.js              # 主入口
├── routes/
│   ├── user.js            # 用户模块 mock
│   ├── station.js         # 充电站模块 mock
│   ├── charge.js          # 充电流程 mock
│   ├── order.js           # 订单模块 mock
│   └── admin.js           # 管理后台 mock
└── data/                  # Mock 数据文件
    ├── user.json
    ├── stations.json
    ├── piles.json
    ├── orders.json
    └── rates.json
```

### B.2 server.js 骨架

```javascript
const express = require('express');
const app = express();
app.use(express.json());

// 注入mock token校验（真实开发时删掉这行，接真实auth）
app.use((req, res, next) => {
  if (req.path === '/api/user/login' || req.path === '/api/admin/login') return next();
  if (!req.headers.authorization) return res.status(401).json({ code: 1004, message: 'Token无效' });
  next();
});

// 统一响应包装
const ok = (data) => ({ code: 0, message: 'ok', data, timestamp: Math.floor(Date.now()/1000) });
const fail = (code, msg) => ({ code, message: msg, data: null, timestamp: Math.floor(Date.now()/1000) });

app.use('/api/user', require('./routes/user'));
app.use('/api/stations', require('./routes/station'));
app.use('/api/charge', require('./routes/charge'));
app.use('/api/orders', require('./routes/order'));
app.use('/api/admin', require('./routes/admin'));

app.listen(3000, () => console.log('Mock Server running on :3000'));
```

### B.3 模拟充电中动态数据（关键）

充电中页面的 `GET /api/charge/:orderNo` 需要返回**每5秒变化的数据**，让老板看起来像"真的在充电"。Mock 实现：

```javascript
// routes/charge.js
const chargingOrders = {}; // 内存存储充电中订单

router.post('/start', (req, res) => {
  const orderNo = 'LC' + Date.now().toString(36).toUpperCase();
  chargingOrders[orderNo] = {
    orderNo,
    pileSn: req.body.pileSn,
    gunNo: req.body.gunNo,
    status: 'charging',
    startTime: new Date().toISOString(),
    startSoc: 20,
    energy: 0,
    fee: 0,
    voltage: 380,
    current: 32,
    power: 12.1,
    soc: 20,
    temperature: 30
  };
  res.json(ok({ orderNo, ...chargingOrders[orderNo] }));
});

router.get('/:orderNo', (req, res) => {
  const order = chargingOrders[req.params.orderNo];
  if (!order) return res.json(fail(3004, '订单不存在'));

  // 模拟递增 —— 每次调用都增长，页面看起来像真的在充电
  order.energy += 0.15;
  order.fee = Math.round(order.energy * 130); // 1.3元/度
  order.soc = Math.min(order.soc + 1, 99);
  order.voltage = 380 + Math.random() * 5;
  order.current = 28 + Math.random() * 8;
  order.power = (order.voltage * order.current / 1000);
  order.temperature = 30 + Math.random() * 10;
  order.duration = Math.floor((Date.now() - new Date(order.startTime).getTime()) / 1000);

  const resp = { ...order, realTime: {
    voltage: +order.voltage.toFixed(1),
    current: +order.current.toFixed(1),
    power: +order.power.toFixed(2),
    soc: order.soc,
    temperature: Math.round(order.temperature)
  }};
  res.json(ok(resp));
});
```

> 这段 Mock 代码的效果：小程序充电中页面打开后，电量、费用、电流电压持续跳动——**非技术人员看就是"真的在充"**。第2周演示的核心就是这一段。

---

> **文档版本**: v1.5  
> **最后更新**: 2026-07-29  
> **v1.5 变更摘要**:
> - 🔧 `/api/auth/login` 新增 `nickName`、`avatarUrl` 参数（新用户自动存昵称/头像）
> - 🔧 `/api/users/login` 升级支持 code + userId 双模式，与 `/api/auth/login` 完全等价
> - 🔧 文档下载文件名 v1.2→v1.5 修正
> 
> **v1.4 变更**:
> - 🔧 修复路由不一致：`/api/user/login`→`/api/users/login`，`/api/user/profile`→`/api/users/me`，`/api/user/recharge`→`/api/users/recharge`
> - 🔧 修复订单模块路由：`/api/orders`→`/api/admin/users/orders`，`/api/orders/:orderNo`→`/api/charge/:orderNo`
> - ⭐ 新增账号登录充电接口（4.1f）：`POST /api/charge/start-by-account`
> - ⭐ 新增用户模块接口（2.10-2.15）：注册、绑定手机、登出、积分/等级、签到/邀请、提现
> - ⭐ 新增支付模块（7.1-7.3）：统一下单、支付回调、信用支付回调
> - ⭐ 新增管理后台接口（6.29-6.37）：国网电价、远程启机、即插即充、BMS诊断、用户管理、提现审核、移动充电设备管理、车队VIN批操作、车队停止码
> - 📋 目录全面重构，补全所有节编号，去重重复项
> 
> **v1.3 变更摘要**:
> - ⭐ 新增企业客户管理 CRUD（6.19）
> - ⭐ 新增车队/组织机构管理 CRUD（6.20）——企业下挂车队，支持停止码+专用站
> - ⭐ 新增群组定价活动 CRUD（6.21）——三种定价模式(replace/reduce/reduce_pct) + 线下结算标记
> - ⭐ 新增线下清分结算（6.22）——生成/列表/详情/标记已结算/CSV导出/发票预览
> - 修复费率时区双偏移（系统已是CST不再+8h） + 车队定价大小写匹配
> - VIN充电（HTTP兼容 + 0xAD安全认证）全部接入车队定价覆盖
> 
> **v1.2 变更摘要**:
> - ⭐ VIN充电启动接口新增 `mode` 参数（支持 challenge/default/status 三种模式）
> - ⭐ 新增 ISO 15118 挑战-应答安全认证流程说明
> - 新增 VIN 批量导入（车队管理）+ 批次列表/详情
> - 新增充电密码预设管理 CRUD（商家内部免账户充电）
> - 新增 VIN 绑定：手动绑定/行驶证OCR/首次充电触发采集
> - 新增支付模式切换（预付费/后付费信用支付）
> - 新增信用支付开通与状态查询
> - 补充数据库访问说明：前端通过 API 访问，不直连 MySQL
> 
> **v1.1 变更摘要**:
> - 新增管理员角色体系（super/admin/station_master/operator）与站长站点隔离
> - 新增 `POST /api/stations/service-fee` 站点服务费规格管理 CRUD
> - 新增 `GET /api/dashboard` + `GET /api/stats` 按站+按天看板
> - 新增 `GET /api/admin/me` 管理员信息接口
> - 全部费用字段增加 `*Yuan` 元格式
> - 新增 `start_mode` / `pay_mode` 数据字典
> - 新增信用支付回调 `POST /api/callback/credit-pay`
> - 补充支付状态 `overdue` / `failed` / `pending`
> **维护者**: 克里斯提娜
