6 天以前 65ea825eb3e8547f0222224835554dabaec5a7ad
feat(vehicle): 添加车辆管理模块及归还里程功能

- 新增车辆管理模块API接口文档,包含车辆基础信息和借出记录管理
- 添加归还时公里数字段到车辆借用记录实体和数据库表
- 实现归还车辆时同步更新车辆里程数的功能
- 修复车辆借用记录服务中的审批流程处理逻辑
- 添加车辆管理相关枚举类型和数据传输对象
- 配置开发环境数据库连接字符串指向新的产品库存管理系统数据库
已添加1个文件
已修改4个文件
793 ■■■■■ 文件已修改
doc/车辆管理模块API接口文档.md 765 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/VehicleBorrowRecord.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/VehicleBorrowRecordServiceImpl.java 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/³µÁ¾¹ÜÀíÄ£¿éAPI½Ó¿ÚÎĵµ.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,765 @@
# è½¦è¾†ç®¡ç†æ¨¡å— API æŽ¥å£æ–‡æ¡£
## æ¨¡å—概述
车辆管理模块包含两个子模块:
1. **车辆管理** - è½¦è¾†åŸºç¡€ä¿¡æ¯çš„增删改查
2. **借出记录管理** - è½¦è¾†å€Ÿå‡ºç”³è¯·ã€å®¡æ‰¹ã€å½’还、延期等功能
**基础路径**: `/approve/vehicle`
---
## ä¸€ã€è½¦è¾†ç®¡ç†æŽ¥å£
### 1.1 åˆ†é¡µæŸ¥è¯¢è½¦è¾†åˆ—表
**请求**
```
GET /approve/vehicle/listPage
```
**请求参数**
| å‚数名 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|--------|------|------|------|
| current | Long | å¦ | å½“前页码,默认1 |
| size | Long | å¦ | æ¯é¡µæ¡æ•°ï¼Œé»˜è®¤10 |
| plateNumber | String | å¦ | è½¦ç‰Œå·ï¼Œæ¨¡ç³ŠæŸ¥è¯¢ |
| status | String | å¦ | ä½¿ç”¨çŠ¶æ€ï¼šIDLE-空闲,IN_USE-使用中 |
| createTimeStart | String | å¦ | åˆ›å»ºæ—¶é—´èµ·å§‹ |
| createTimeEnd | String | å¦ | åˆ›å»ºæ—¶é—´ç»“束 |
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "records": [
      {
        "id": 1,
        "plateNumber": "京A12345",
        "mileage": 15000.50,
        "status": "IDLE",
        "deleted": 0,
        "createUser": 1,
        "createTime": "2026-05-29 10:00:00",
        "updateUser": 1,
        "updateTime": "2026-05-29 10:00:00",
        "deptId": 100
      }
    ],
    "total": 1,
    "size": 10,
    "current": 1
  }
}
```
---
### 1.2 æ–°å¢žè½¦è¾†
**请求**
```
POST /approve/vehicle/save
Content-Type: application/json
```
**请求体**
```json
{
  "plateNumber": "京A12345",
  "mileage": 15000.50,
  "status": "IDLE"
}
```
**请求参数说明**
| å‚数名 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|--------|------|------|------|
| plateNumber | String | æ˜¯ | è½¦ç‰Œå· |
| mileage | BigDecimal | å¦ | è½¦è¾†å…¬é‡Œæ•° |
| status | String | å¦ | ä½¿ç”¨çŠ¶æ€ï¼Œé»˜è®¤IDLE |
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功"
}
```
---
### 1.3 è½¦è¾†è¯¦æƒ…
**请求**
```
GET /approve/vehicle/detail?id=1
```
**请求参数**
| å‚数名 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|--------|------|------|------|
| id | Long | æ˜¯ | è½¦è¾†ID |
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "id": 1,
    "plateNumber": "京A12345",
    "mileage": 15000.50,
    "status": "IDLE",
    "deleted": 0,
    "createTime": "2026-05-29 10:00:00"
  }
}
```
---
### 1.4 ä¿®æ”¹è½¦è¾†
**请求**
```
PUT /approve/vehicle/update
Content-Type: application/json
```
**请求体**
```json
{
  "id": 1,
  "plateNumber": "京A12346",
  "mileage": 16000.00,
  "status": "IN_USE"
}
```
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功"
}
```
---
### 1.5 åˆ é™¤è½¦è¾†
**请求**
```
DELETE /approve/vehicle/delete
Content-Type: application/json
```
**请求体**
```json
[1, 2, 3]
```
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功"
}
```
---
## äºŒã€å€Ÿå‡ºè®°å½•接口
### 2.1 åˆ†é¡µæŸ¥è¯¢å€Ÿå‡ºè®°å½•
**请求**
```
GET /approve/vehicle/borrow/listPage
```
**请求参数**
| å‚数名 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|--------|------|------|------|
| current | Long | å¦ | å½“前页码 |
| size | Long | å¦ | æ¯é¡µæ¡æ•° |
| borrowNo | String | å¦ | å€Ÿå‡ºå•号,模糊查询 |
| vehiclePlateNumber | String | å¦ | è½¦ç‰Œå·ï¼Œæ¨¡ç³ŠæŸ¥è¯¢ |
| applicantName | String | å¦ | ç”³è¯·äººå§“名,模糊查询 |
| borrowStatus | String | å¦ | å€Ÿå‡ºçŠ¶æ€ |
| extendStatus | String | å¦ | å»¶æœŸçŠ¶æ€ |
| vehicleId | Long | å¦ | è½¦è¾†ID |
| createTimeStart | String | å¦ | åˆ›å»ºæ—¶é—´èµ·å§‹ |
| createTimeEnd | String | å¦ | åˆ›å»ºæ—¶é—´ç»“束 |
**借出状态枚举**
| å€¼ | è¯´æ˜Ž |
|-----|------|
| DRAFT | è‰ç¨¿ |
| IN_APPROVAL | å®¡æ‰¹ä¸­ |
| BORROWING | å€Ÿå‡ºä¸­ |
| RETURNED | å·²å½’还 |
| REJECTED | å·²é©³å›ž |
**延期状态枚举**
| å€¼ | è¯´æ˜Ž |
|-----|------|
| NONE | æœªç”³è¯· |
| PENDING | å®¡æ‰¹ä¸­ |
| APPROVED | å·²é€šè¿‡ |
| REJECTED | å·²é©³å›ž |
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "records": [
      {
        "id": 1,
        "borrowNo": "CLJC202605290001",
        "vehicleId": 1,
        "vehiclePlateNumber": "京A12345",
        "applicantId": 10,
        "applicantName": "张三",
        "applicantDeptId": 100,
        "applicantDeptName": "研发部",
        "borrowReason": "外出办事",
        "borrowStartTime": "2026-05-29 09:00:00",
        "plannedReturnTime": "2026-05-29 18:00:00",
        "actualReturnTime": null,
        "borrowStatus": "IN_APPROVAL",
        "approvalInstanceId": 100,
        "approvedTime": null,
        "returnedTime": null,
        "extendStatus": "NONE",
        "extendTargetReturnTime": null,
        "extendReason": null,
        "extendApprovedTime": null,
        "borrowStorageBlobVOList": [],
        "returnStorageBlobVOList": []
      }
    ],
    "total": 1
  }
}
```
---
### 2.2 æ–°å¢žå€Ÿå‡ºè®°å½•(发起借车申请)
**请求**
```
POST /approve/vehicle/borrow/save
Content-Type: application/json
```
**请求体**
```json
{
  "vehicleId": 1,
  "borrowReason": "外出办事",
  "borrowStartTime": "2026-05-29 09:00:00",
  "plannedReturnTime": "2026-05-29 18:00:00",
  "borrowStatus": "IN_APPROVAL",
  "approvalTemplateId": 1,
  "borrowStorageBlobDTOs": [
    {
      "fileName": "申请单.pdf",
      "filePath": "/upload/2026/05/xxx.pdf",
      "fileSize": 1024
    }
  ]
}
```
**请求参数说明**
| å‚数名 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|--------|------|------|------|
| vehicleId | Long | æ˜¯ | è½¦è¾†ID |
| borrowReason | String | æ˜¯ | å€Ÿå‡ºåŽŸå›  |
| borrowStartTime | DateTime | æ˜¯ | å€Ÿå‡ºå¼€å§‹æ—¶é—´ï¼Œæ ¼å¼ï¼šyyyy-MM-dd HH:mm:ss |
| plannedReturnTime | DateTime | æ˜¯ | è®¡åˆ’归还时间,必须晚于借出开始时间 |
| borrowStatus | String | æ˜¯ | DRAFT(存草稿) æˆ– IN_APPROVAL(提交审批) |
| approvalTemplateId | Long | å¦ | å®¡æ‰¹æ¨¡æ¿ID,不传则使用默认模板 |
| borrowStorageBlobDTOs | Array | å¦ | å€Ÿå‡ºé™„件列表 |
| formConfig | String | å¦ | è‡ªå®šä¹‰è¡¨å•配置(JSON字符串) |
**业务规则**
- å¿…须选择状态为 IDLE(空闲) çš„车辆
- åŒä¸€è½¦è¾†ä¸èƒ½æœ‰é‡å¤çš„借出申请(审批中或借出中)
- `borrowStatus=IN_APPROVAL` æ—¶ä¼šè‡ªåŠ¨å‘èµ·å®¡æ‰¹æµç¨‹
- `borrowStatus=DRAFT` æ—¶ä»…保存草稿,不发起审批
- ç”³è¯·äººä¿¡æ¯è‡ªåŠ¨ä»Žå½“å‰ç™»å½•ç”¨æˆ·èŽ·å–
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功"
}
```
**错误响应**
```json
{
  "code": 500,
  "msg": "当前车辆已有借出记录,不能重复借出"
}
```
---
### 2.3 å€Ÿå‡ºè®°å½•详情
**请求**
```
GET /approve/vehicle/borrow/detail?id=1
```
**请求参数**
| å‚数名 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|--------|------|------|------|
| id | Long | æ˜¯ | å€Ÿå‡ºè®°å½•ID |
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "id": 1,
    "borrowNo": "CLJC202605290001",
    "vehicleId": 1,
    "vehiclePlateNumber": "京A12345",
    "applicantId": 10,
    "applicantName": "张三",
    "applicantDeptId": 100,
    "applicantDeptName": "研发部",
    "borrowReason": "外出办事",
    "borrowStartTime": "2026-05-29 09:00:00",
    "plannedReturnTime": "2026-05-29 18:00:00",
    "actualReturnTime": null,
    "borrowStatus": "BORROWING",
    "approvalInstanceId": 100,
    "approvedTime": "2026-05-29 09:30:00",
    "returnedTime": null,
    "extendStatus": "NONE",
    "extendTargetReturnTime": null,
    "extendReason": null,
    "extendApprovedTime": null,
    "extendApprovalInstanceId": null,
    "deleted": 0,
    "createUser": 10,
    "createTime": "2026-05-29 09:00:00",
    "updateUser": 10,
    "updateTime": "2026-05-29 09:30:00",
    "deptId": 100
  }
}
```
---
### 2.4 ä¿®æ”¹å€Ÿå‡ºè®°å½•
**请求**
```
PUT /approve/vehicle/borrow/update
Content-Type: application/json
```
**请求体**
```json
{
  "id": 1,
  "vehicleId": 1,
  "borrowReason": "外出办事(修改)",
  "borrowStartTime": "2026-05-29 10:00:00",
  "plannedReturnTime": "2026-05-29 18:00:00",
  "borrowStatus": "IN_APPROVAL",
  "approvalTemplateId": 2,
  "borrowStorageBlobDTOs": []
}
```
**业务规则**
- ä»… DRAFT(草稿) æˆ– REJECTED(已驳回) çŠ¶æ€å¯ä¿®æ”¹
- ä¿®æ”¹åŽæäº¤å®¡æ‰¹ä¼šåˆ é™¤åŽŸå®¡æ‰¹å®žä¾‹å¹¶é‡æ–°å‘èµ·
- é™„件列表传入时会覆盖原有附件
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功"
}
```
**错误响应**
```json
{
  "code": 500,
  "msg": "当前状态的借出记录不允许修改"
}
```
---
### 2.5 åˆ é™¤å€Ÿå‡ºè®°å½•
**请求**
```
DELETE /approve/vehicle/borrow/delete
Content-Type: application/json
```
**请求体**
```json
[1, 2]
```
**业务规则**
- å®¡æ‰¹ä¸­(IN_APPROVAL) æˆ– å€Ÿå‡ºä¸­(BORROWING) çš„记录不可删除
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功"
}
```
**错误响应**
```json
{
  "code": 500,
  "msg": "审批中或借出中的记录不允许删除"
}
```
---
### 2.6 å½’还车辆
**请求**
```
POST /approve/vehicle/borrow/return
Content-Type: application/json
```
**请求体**
```json
{
  "id": 1,
  "actualReturnTime": "2026-05-29 17:30:00",
  "returnMileage": 16500.50,
  "returnStorageBlobDTOs": [
    {
      "fileName": "归还确认单.pdf",
      "filePath": "/upload/2026/05/xxx.pdf",
      "fileSize": 2048
    }
  ]
}
```
**请求参数说明**
| å‚数名 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|--------|------|------|------|
| id | Long | æ˜¯ | å€Ÿå‡ºè®°å½•ID |
| actualReturnTime | DateTime | å¦ | å®žé™…归还时间,不传则使用当前时间 |
| returnMileage | BigDecimal | å¦ | å½’还时公里数,会同步更新到车辆信息 |
| returnStorageBlobDTOs | Array | å¦ | å½’还附件列表 |
**业务规则**
- ä»… BORROWING(借出中) çŠ¶æ€å¯å½’è¿˜
- å»¶æœŸå®¡æ‰¹ä¸­(PENDING) çš„记录不可直接归还,需先处理延期审批
- å½’还后车辆状态自动变为 IDLE(空闲)
- å€Ÿå‡ºè®°å½•状态变为 RETURNED(已归还)
- è‹¥ä¼ å…¥ returnMileage,会同步更新车辆的公里数
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功"
}
```
**错误响应**
```json
{
  "code": 500,
  "msg": "只有借出中的车辆才能归还"
}
```
---
### 2.7 å‘起延期申请
**请求**
```
POST /approve/vehicle/borrow/delay
Content-Type: application/json
```
**请求体**
```json
{
  "id": 1,
  "extendTargetReturnTime": "2026-05-30 18:00:00",
  "extendReason": "业务需要延长一天"
}
```
**请求参数说明**
| å‚数名 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|--------|------|------|------|
| id | Long | æ˜¯ | å€Ÿå‡ºè®°å½•ID |
| extendTargetReturnTime | DateTime | æ˜¯ | å»¶æœŸåŽçš„归还时间,必须晚于当前计划归还时间 |
| extendReason | String | å¦ | å»¶æœŸåŽŸå›  |
**业务规则**
- ä»… BORROWING(借出中) çŠ¶æ€å¯ç”³è¯·å»¶æœŸ
- å»¶æœŸå½’还时间必须晚于当前计划归还时间
- å·²æœ‰å»¶æœŸå®¡æ‰¹ä¸­çš„申请不可重复提交
- ç”³è¯·åŽä¼šè‡ªåŠ¨å‘èµ·å»¶æœŸå®¡æ‰¹æµç¨‹(业务类型=20)
**响应示例**
```json
{
  "code": 200,
  "msg": "操作成功"
}
```
**错误响应**
```json
{
  "code": 500,
  "msg": "已有延期审批中的申请,请勿重复提交"
}
```
---
## ä¸‰ã€çŠ¶æ€æµè½¬è¯´æ˜Ž
### 3.1 å€Ÿå‡ºçŠ¶æ€æµè½¬å›¾
```
                    â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”
                    â”‚                                      â”‚
                    â”‚                                      â†“
┌─────────┐    â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”    â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”    â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”
│  æ–°å»º   â”‚───→│    DRAFT      â”‚───→│ IN_APPROVAL â”‚───→│ BORROWING â”‚
└─────────┘    â”‚   (草稿)      â”‚    â”‚  (审批中)   â”‚    â”‚ (借出中)  â”‚
               â””───────┬───────┘    â””──────┬───────┘    â””─────┬─────┘
                       â”‚                   â”‚                  â”‚
                       â”‚                   â†“                  â”‚
                       â”‚            â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”            â”‚
                       â”‚            â”‚  REJECTED  â”‚            â”‚
                       â”‚            â”‚  (已驳回)  â”‚            â”‚
                       â”‚            â””──────┬─────┘            â”‚
                       â”‚                   â”‚                  â”‚
                       â””───────────────────┘                  â”‚
                                                              â”‚
                                                              â”‚ å½’还
                                                              â†“
                                                       â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”
                                                       â”‚ RETURNED  â”‚
                                                       â”‚ (已归还)  â”‚
                                                       â””───────────┘
```
### 3.2 å»¶æœŸçŠ¶æ€æµè½¬å›¾
```
┌─────────┐    â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”    â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”
│  NONE   â”‚───→│  PENDING  â”‚───→│ APPROVED  â”‚
│(未申请) â”‚    â”‚ (审批中)  â”‚    â”‚ (已通过)  â”‚
└─────────┘    â””─────┬─────┘    â””───────────┘
                     â”‚
                     â†“
              â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”
              â”‚  REJECTED â”‚
              â”‚ (已驳回)  â”‚
              â””───────────┘
```
### 3.3 è½¦è¾†çŠ¶æ€è¯´æ˜Ž
| çŠ¶æ€ | å€¼ | è¯´æ˜Ž | è§¦å‘条件 |
|------|-----|------|----------|
| ç©ºé—² | IDLE | è½¦è¾†å¯å€Ÿå‡º | æ–°å¢žè½¦è¾†ã€å€Ÿå‡ºå½’还后 |
| ä½¿ç”¨ä¸­ | IN_USE | è½¦è¾†å·²è¢«å€Ÿå‡º | å€Ÿå‡ºå®¡æ‰¹é€šè¿‡åŽ |
---
## å››ã€é™„件说明
### 4.1 é™„件类型
| ç±»åž‹ | recordType | ä½¿ç”¨åœºæ™¯ |
|------|------------|----------|
| å€Ÿå‡ºé™„ä»¶ | vehicle_borrow_record | å€Ÿè½¦ç”³è¯·æ—¶ä¸Šä¼  |
| å½’还附件 | vehicle_return_record | å½’还时上传 |
### 4.2 é™„件上传流程
1. å…ˆè°ƒç”¨æ–‡ä»¶ä¸Šä¼ æŽ¥å£èŽ·å–æ–‡ä»¶ä¿¡æ¯
2. å°†æ–‡ä»¶ä¿¡æ¯æ”¾å…¥ `borrowStorageBlobDTOs` æˆ– `returnStorageBlobDTOs`
3. æäº¤ä¸šåŠ¡æŽ¥å£æ—¶ä¸€å¹¶ä¿å­˜
**附件对象结构**
```json
{
  "fileName": "文件名称.pdf",
  "filePath": "/upload/2026/05/xxx.pdf",
  "fileSize": 1024,
  "fileType": "application/pdf"
}
```
---
## äº”、审批配置说明
### 5.1 å®¡æ‰¹æ¨¡æ¿é…ç½®
需在审批模板管理中配置以下业务类型的模板:
| ä¸šåŠ¡ç±»åž‹ | ç±»åž‹å€¼ | è¯´æ˜Ž |
|----------|--------|------|
| è½¦è¾†å€Ÿå‡ºå®¡æ‰¹ | 19 | è½¦è¾†å€Ÿå‡ºç”³è¯·çš„审批流程 |
| è½Šè¾†å»¶æœŸå®¡æ‰¹ | 20 | è½¦è¾†å»¶æœŸç”³è¯·çš„审批流程 |
### 5.2 å®¡æ‰¹å›žè°ƒæœºåˆ¶
审批结果会自动同步到业务状态:
| å®¡æ‰¹ç±»åž‹ | å®¡æ‰¹é€šè¿‡ | å®¡æ‰¹é©³å›ž |
|----------|----------|----------|
| è½¦è¾†å€Ÿå‡ºå®¡æ‰¹(19) | borrowStatus â†’ BORROWING<br>车辆status â†’ IN_USE | borrowStatus â†’ REJECTED |
| è½¦è¾†å»¶æœŸå®¡æ‰¹(20) | extendStatus â†’ APPROVED<br>更新plannedReturnTime为extendTargetReturnTime | extendStatus â†’ REJECTED |
---
## å…­ã€é”™è¯¯ç è¯´æ˜Ž
| é”™è¯¯ä¿¡æ¯ | åŽŸå›  | è§£å†³æ–¹æ¡ˆ |
|----------|------|----------|
| è½¦è¾†ä¸å­˜åœ¨ | è½¦è¾†ID无效或已删除 | æ£€æŸ¥è½¦è¾†ID是否正确 |
| å½“前车辆不在可借出状态 | è½¦è¾†çŠ¶æ€ä¸º IN_USE | é€‰æ‹©å…¶ä»–空闲车辆 |
| å½“前车辆已有借出记录,不能重复借出 | è¯¥è½¦å·²æœ‰å®¡æ‰¹ä¸­æˆ–借出中的记录 | ç­‰å¾…该车辆归还后再申请 |
| è¯·å…ˆé…ç½®è½¦è¾†å®¡æ‰¹æ¨¡æ¿ | æœªé…ç½®è½¦è¾†å€Ÿå‡ºå®¡æ‰¹æ¨¡æ¿ | åœ¨å®¡æ‰¹æ¨¡æ¿ç®¡ç†ä¸­é…ç½® |
| å€Ÿå‡ºè®°å½•不存在 | å€Ÿå‡ºè®°å½•ID无效或已删除 | æ£€æŸ¥è®°å½•ID是否正确 |
| å½“前状态的借出记录不允许修改 | éžè‰ç¨¿æˆ–驳回状态 | ä»…草稿和驳回状态可修改 |
| å®¡æ‰¹ä¸­æˆ–借出中的记录不允许删除 | è®°å½•状态为审批中或借出中 | ä¸èƒ½åˆ é™¤è¿›è¡Œä¸­çš„记录 |
| åªæœ‰å€Ÿå‡ºä¸­çš„车辆才能归还 | éž BORROWING çŠ¶æ€ | ä»…借出中状态可归还 |
| å»¶æœŸå®¡æ‰¹ä¸­çš„记录不允许直接归还 | å­˜åœ¨è¿›è¡Œä¸­çš„延期审批 | å…ˆå¤„理延期审批再归还 |
| å€Ÿå‡ºè®°å½•ID不能为空 | è¯·æ±‚缺少记录ID | ä¼ å…¥æ­£ç¡®çš„记录ID |
| è®¡åˆ’归还时间不能为空 | ç¼ºå°‘计划归还时间 | å¡«å†™è®¡åˆ’归还时间 |
| è®¡åˆ’归还时间必须晚于借出开始时间 | æ—¶é—´é¡ºåºé”™è¯¯ | è°ƒæ•´æ—¶é—´é¡ºåº |
| å»¶æœŸåŽçš„归还时间不能为空 | ç¼ºå°‘延期目标时间 | å¡«å†™å»¶æœŸåŽçš„归还时间 |
| å»¶æœŸåŽçš„归还时间必须晚于当前计划归还时间 | å»¶æœŸæ—¶é—´ä¸åˆç† | å»¶æœŸæ—¶é—´éœ€æ™šäºŽå½“前计划时间 |
| åªæœ‰å€Ÿå‡ºä¸­çš„车辆才能申请延期 | éž BORROWING çŠ¶æ€ | ä»…借出中状态可延期 |
| å·²æœ‰å»¶æœŸå®¡æ‰¹ä¸­çš„申请,请勿重复提交 | é‡å¤ç”³è¯·å»¶æœŸ | ç­‰å¾…当前延期审批完成 |
| è¯·å…ˆç™»å½• | æœªç™»å½•或登录失效 | é‡æ–°ç™»å½• |
---
## ä¸ƒã€æ•°æ®ç»“æž„
### 7.1 è½¦è¾†å®žä½“ (Vehicle)
| å­—段名 | ç±»åž‹ | è¯´æ˜Ž |
|--------|------|------|
| id | Long | è½¦è¾†ID |
| plateNumber | String | è½¦ç‰Œå· |
| mileage | BigDecimal | è½¦è¾†å…¬é‡Œæ•° |
| status | String | ä½¿ç”¨çŠ¶æ€ï¼šIDLE/IN_USE |
| deleted | Integer | åˆ é™¤æ ‡è®°ï¼š0未删除,1已删除 |
| createUser | Long | åˆ›å»ºäººID |
| createTime | DateTime | åˆ›å»ºæ—¶é—´ |
| updateUser | Long | æ›´æ–°äººID |
| updateTime | DateTime | æ›´æ–°æ—¶é—´ |
| deptId | Long | éƒ¨é—¨ID |
### 7.2 å€Ÿå‡ºè®°å½•实体 (VehicleBorrowRecord)
| å­—段名 | ç±»åž‹ | è¯´æ˜Ž |
|--------|------|------|
| id | Long | è®°å½•ID |
| borrowNo | String | å€Ÿå‡ºå•号,格式:CLJC+日期+序号 |
| vehicleId | Long | è½¦è¾†ID |
| vehiclePlateNumber | String | è½¦ç‰Œå· |
| applicantId | Long | ç”³è¯·äººID |
| applicantName | String | ç”³è¯·äººå§“名 |
| applicantDeptId | Long | ç”³è¯·éƒ¨é—¨ID |
| applicantDeptName | String | ç”³è¯·éƒ¨é—¨åç§° |
| borrowReason | String | å€Ÿå‡ºåŽŸå›  |
| borrowStartTime | DateTime | å€Ÿå‡ºå¼€å§‹æ—¶é—´ |
| plannedReturnTime | DateTime | è®¡åˆ’归还时间 |
| actualReturnTime | DateTime | å®žé™…归还时间 |
| borrowStatus | String | å€Ÿå‡ºçŠ¶æ€ |
| approvalInstanceId | Long | å€Ÿå‡ºå®¡æ‰¹å®žä¾‹ID |
| approvedTime | DateTime | å€Ÿå‡ºå®¡æ‰¹é€šè¿‡æ—¶é—´ |
| returnedTime | DateTime | å½’还时间 |
| returnMileage | BigDecimal | å½’还时公里数 |
| extendApprovalInstanceId | Long | å»¶æœŸå®¡æ‰¹å®žä¾‹ID |
| extendStatus | String | å»¶æœŸçŠ¶æ€ |
| extendTargetReturnTime | DateTime | å»¶æœŸç›®æ ‡å½’还时间 |
| extendReason | String | å»¶æœŸåŽŸå›  |
| extendApprovedTime | DateTime | å»¶æœŸå®¡æ‰¹é€šè¿‡æ—¶é—´ |
| deleted | Integer | åˆ é™¤æ ‡è®° |
| createUser | Long | åˆ›å»ºäººID |
| createTime | DateTime | åˆ›å»ºæ—¶é—´ |
| updateUser | Long | æ›´æ–°äººID |
| updateTime | DateTime | æ›´æ–°æ—¶é—´ |
| deptId | Long | éƒ¨é—¨ID |
---
## å…«ã€å‰ç«¯å¼€å‘建议
### 8.1 è½¦è¾†ç®¡ç†é¡µé¢
- æ–°å¢žè½¦è¾†æ—¶è½¦ç‰Œå·å»ºè®®åšå”¯ä¸€æ€§æ ¡éªŒ
- è½¦è¾†çŠ¶æ€ä½¿ç”¨æ ‡ç­¾å±•ç¤ºï¼šç©ºé—²(绿色)、使用中(红色/橙色)
- åˆ é™¤è½¦è¾†å‰æ£€æŸ¥æ˜¯å¦æœ‰è¿›è¡Œä¸­çš„借出记录
### 8.2 å€Ÿå‡ºè®°å½•页面
- åˆ—表页建议按状态筛选:草稿、审批中、借出中、已归还、已驳回
- æ–°å¢žç”³è¯·æ—¶ï¼Œè½¦è¾†é€‰æ‹©ä¸‹æ‹‰æ¡†ä»…显示IDLE状态的车辆
- å®¡æ‰¹ä¸­å’Œå€Ÿå‡ºä¸­çš„记录不允许删除,建议隐藏删除按钮
- å»¶æœŸç”³è¯·æŒ‰é’®ä»…在BORROWING状态且无进行中延期申请时显示
- å½’还按钮仅在BORROWING状态且无进行中延期申请时显示
- é©³å›žçŠ¶æ€çš„è®°å½•å…è®¸ä¿®æ”¹åŽé‡æ–°æäº¤
### 8.3 çŠ¶æ€å±•ç¤ºå»ºè®®
| çŠ¶æ€ | å»ºè®®é¢œè‰² | å»ºè®®æ“ä½œæŒ‰é’® |
|------|----------|--------------|
| DRAFT | ç°è‰² | ç¼–辑、删除、提交审批 |
| IN_APPROVAL | è“è‰² | æŸ¥çœ‹ã€æ’¤å›ž(需配置) |
| BORROWING | ç»¿è‰² | ç”³è¯·å»¶æœŸã€å½’还 |
| RETURNED | é»˜è®¤è‰² | æŸ¥çœ‹ |
| REJECTED | çº¢è‰² | ç¼–辑、删除、重新提交 |
---
## ä¹ã€ç‰ˆæœ¬ä¿¡æ¯
- **模块版本**: 1.0.0
- **更新日期**: 2026-05-29
- **作者**: èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
src/main/java/com/ruoyi/approve/pojo/VehicleBorrowRecord.java
@@ -11,6 +11,7 @@
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
@@ -82,6 +83,9 @@
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime returnedTime;
    @Schema(description = "归还时公里数")
    private BigDecimal returnMileage;
    @Schema(description = "延期审批实例ID")
    private Long extendApprovalInstanceId;
src/main/java/com/ruoyi/approve/service/impl/VehicleBorrowRecordServiceImpl.java
@@ -1,5 +1,6 @@
package com.ruoyi.approve.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -197,6 +198,7 @@
        update.setActualReturnTime(now);
        update.setReturnedTime(now);
        update.setBorrowStatus(BORROW_STATUS_RETURNED);
        update.setReturnMileage(record.getReturnMileage());
        update.setUpdateUser(SecurityUtils.getUserId());
        update.setUpdateTime(now);
        update.setExtendStatus(existing.getExtendStatus());
@@ -208,6 +210,9 @@
        Vehicle vehicle = new Vehicle();
        vehicle.setId(existing.getVehicleId());
        vehicle.setStatus("IDLE");
        if (record.getReturnMileage() != null) {
            vehicle.setMileage(record.getReturnMileage());
        }
        vehicleMapper.updateById(vehicle);
        return true;
    }
@@ -247,7 +252,10 @@
            throw new ServiceException("保存延期申请失败");
        }
        VehicleBorrowRecord refreshed = detail(existing.getId());
        startApproval(refreshed, TypeEnums.VEHICLE_DELAY_APPROVAL.getCode());
        VehicleBorrowRecordDto recordDto = new VehicleBorrowRecordDto();
        BeanUtil.copyProperties(refreshed, recordDto);
        recordDto.setFormConfig(record.getFormConfig());
        startApproval(recordDto, TypeEnums.VEHICLE_DELAY_APPROVAL.getCode());
        return true;
    }
@@ -329,11 +337,12 @@
        }
    }
    private void startApproval(VehicleBorrowRecord record, Long businessType) {
    private void startApproval(VehicleBorrowRecordDto record, Long businessType) {
        Long templateId = null;
        if (record instanceof VehicleBorrowRecordDto) {
            templateId = ((VehicleBorrowRecordDto) record).getApprovalTemplateId();
        if (record == null) {
            return;
        }
        templateId = record.getApprovalTemplateId();
        ApprovalTemplate approvalTemplate = resolveApprovalTemplate(templateId, businessType);
        ApprovalInstanceDto approvalInstanceDto = new ApprovalInstanceDto();
        approvalInstanceDto.setTemplateId(approvalTemplate.getId());
@@ -346,6 +355,7 @@
        approvalInstanceDto.setApplyTime(LocalDateTime.now());
        approvalInstanceDto.setStatus("PENDING");
        approvalInstanceDto.setCurrentLevel(1);
        approvalInstanceDto.setFormConfig(record.getFormConfig());
        boolean saved = approvalInstanceService.add(approvalInstanceDto);
        if (!saved || approvalInstanceDto.getId() == null) {
src/main/java/com/ruoyi/basic/enums/RecordTypeEnum.java
@@ -202,9 +202,7 @@
    APPROVAL_INSTANCE("approval_instance"),
    ACCOUNT_INVOICE_APPLICATION("account_invoice_application"),
    ACCOUNT_PURCHASE_INVOICE("account_purchase_invoice"),
    APPROVAL_TEMPLATE("approval_template");
    ACCOUNT_PURCHASE_INVOICE("account_purchase_invoice"),
    // Vehicle
    APPROVAL_TEMPLATE("approval_template"),
    VEHICLE("vehicle"),
    VEHICLE_BORROW_RECORD("vehicle_borrow_record"),
    VEHICLE_RETURN_RECORD("vehicle_return_record");
src/main/resources/application-dev.yml
@@ -74,7 +74,7 @@
    druid:
      # ä¸»åº“数据源
      master:
        url: jdbc:mysql://localhost:3306/product-inventory-management-new-pro?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        url: jdbc:mysql://localhost:3306/product-inventory-management-yzfx?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: 123456
      # ä»Žåº“数据源