# 接口变更记录 — 2026-03-30 22:20

> **提交** `a59cd643` · **作者** wx · **时间** 2026-03-30 22:20:22 +0800
>
> refactor: 11个微服务合并为5个，运行时12进程降为6进程

## 变更总览

- **用户服务**
  - 🆕 MsgAuditCallback (+2 接口)
  - 🆕 WxCallback (+4 接口)
  - 🆕 File (+9 接口)
  - 🆕 InternalFile (+10 接口)
  - 🆕 MpFile (+4 接口)
  - 🆕 ApprovalLog (+2 接口)
  - 🆕 DataRetention (+1 接口)
  - 🆕 ErrorLog (+2 接口)
  - 🆕 InternalLog (+5 接口)
  - 🆕 LoginLog (+1 接口)
  - 🆕 MysqlMonitor (+3 接口)
  - 🆕 NotificationLog (+2 接口)
  - 🆕 OperationLog (+2 接口)
  - 🆕 RedisMonitor (+1 接口)
  - 🆕 RocketMqMonitor (+3 接口)
  - 🆕 ServiceMonitor (+1 接口)
  - 🆕 AdminReview (+6 接口)
  - 🆕 InternalMpReview (+10 接口)
  - 🆕 InternalReview (+8 接口)
  - 🆕 Board (+13 接口)
  - 🆕 Task (+13 接口)
  - 🆕 WebSocketDoc (+1 接口)
  - 🆕 MsgAuditCallbackTest (+0 接口)
  - 🆕 WxCallbackTest (+0 接口)
  - 🆕 FileTest (+0 接口)
  - 🆕 ApprovalLogTest (+0 接口)
  - 🆕 DataRetentionTest (+0 接口)
  - 🆕 ErrorLogTest (+0 接口)
  - 🆕 InternalLogTest (+0 接口)
  - 🆕 LoginLogTest (+0 接口)
  - 🆕 MysqlMonitorTest (+0 接口)
  - 🆕 NotificationLogTest (+0 接口)
  - 🆕 OperationLogTest (+0 接口)
  - 🆕 RedisMonitorTest (+0 接口)
  - 🆕 RocketMqMonitorTest (+0 接口)
  - 🆕 ServiceMonitorTest (+0 接口)
  - 🆕 AdminReviewTest (+0 接口)
  - 🆕 InternalMpReviewTest (+0 接口)
  - 🆕 InternalReviewTest (+0 接口)
  - 🆕 BoardTest (+0 接口)
  - 🆕 TaskTest (+0 接口)
  - 🆕 WebSocketDocTest (+0 接口)
- **订单服务**
  - 🆕 AdminClauseTemplate (+6 接口)
  - 🆕 AdminContract (+14 接口)
  - 🆕 AdminContractScheme (+7 接口)
  - 🆕 ContractCallback (+2 接口)
  - 🆕 InternalContract (+7 接口)
  - 🆕 InternalMpContract (+5 接口)
  - 🆕 AdminInsurance (+23 接口)
  - 🆕 AdminInsuranceScheme (+8 接口)
  - 🆕 InternalInsurance (+13 接口)
  - 🆕 AdminPayment (+9 接口)
  - 🆕 InternalPayment (+5 接口)
  - 🆕 PaymentCallback (+3 接口)
  - 🆕 AdminClauseTemplateTest (+0 接口)
  - 🆕 AdminContractTest (+0 接口)
  - 🆕 AdminContractSchemeTest (+0 接口)
  - 🆕 ContractCallbackTest (+0 接口)
  - 🆕 InternalContractTest (+0 接口)
  - 🆕 InternalMpContractTest (+0 接口)
  - 🆕 AdminPaymentTest (+0 接口)
  - 🆕 InternalPaymentTest (+0 接口)
  - 🆕 PaymentCallbackTest (+0 接口)
- **资源服务**
  - 🆕 AdminGuideArticle (+8 接口)
  - 🆕 AdminGuideCategory (+7 接口)
  - 🆕 AdminGuideTag (+6 接口)
  - 🆕 InternalWiki (+4 接口)
  - 🆕 DictCacheService (+0 接口)
  - 🆕 InternalMaterial (+6 接口)
  - 🆕 MaterialCategoryPermission (+2 接口)
  - 🆕 Material (+20 接口)
  - 🆕 MaterialTag (+6 接口)
  - 🆕 MpMaterial (+1 接口)
  - 🆕 AdminTransport (+7 接口)
  - 🆕 InternalTransport (+2 接口)
  - 🆕 AdminGuideArticleTest (+0 接口)
  - 🆕 AdminGuideCategoryTest (+0 接口)
  - 🆕 AdminGuideTagTest (+0 接口)
  - 🆕 InternalWikiTest (+0 接口)
  - 🆕 DictCacheServiceTest (+0 接口)

---

## 用户服务

### 🆕 新增: MsgAuditCallback

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「【回调接口】会话内容存档」**

### 📌 `GET` /callback/msg-audit — 会话内容存档回调URL验证

> 企业微信会话内容存档的回调URL验证端点。使用独立的Token/AESKey，在企微后台配置会话存档回调URL时进行验证。

**参数**

  - `msgSignature` (`String`) — 查询参数
  - `timestamp` (`String`) — 查询参数
  - `nonce` (`String`) — 查询参数
  - `echostr` (`String`) — 查询参数

**响应** `String`

### 📌 `POST` /callback/msg-audit — 接收会话内容存档事件通知

> 企业微信在有新的存档消息时推送事件通知到此端点。通知仅表示'有新消息可拉取'，收到后异步触发消息拉取任务（通过Finance SDK API主动拉取具体内容并存储）。必须5秒内返回'success'。

**参数**

  - `msgSignature` (`String`) — 查询参数
  - `timestamp` (`String`) — 查询参数
  - `nonce` (`String`) — 查询参数

**响应** `String`

### 🆕 新增: WxCallback

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「【回调接口】企业微信回调」**

### 📌 `GET` /wx/callback/app — 回调URL验证

> 企业微信自建应用的回调URL验证端点。企微在配置回调URL时发送GET请求，需解密echostr并返回明文以完成验证。无需JWT认证，使用企微自有的签名校验机制。

**参数**

  - `msgSignature` (`String`) — 查询参数
  - `timestamp` (`String`) — 查询参数
  - `nonce` (`String`) — 查询参数
  - `echostr` (`String`) — 查询参数

**响应** `String`

### 📌 `POST` /wx/callback/app — 接收回调事件

> 企业微信自建应用的事件接收端点。接收加密XML格式的事件通知（审批变更、消息等），解密后按事件类型分发：change_contact→通讯录变更，change_external_contact→外部联系人变更，open_approval_change→审批状态变更。必须5秒内返回'success'。

**参数**

  - `msgSignature` (`String`) — 查询参数
  - `timestamp` (`String`) — 查询参数
  - `nonce` (`String`) — 查询参数

**响应** `String`

### 📌 `GET` /wx/callback/contacts — 联系人同步URL验证

> 企业微信通讯录同步的回调URL验证端点。使用独立的Token/AESKey（与应用回调不同），用于接收通讯录变更事件的回调URL配置验证。

**参数**

  - `msgSignature` (`String`) — 查询参数
  - `timestamp` (`String`) — 查询参数
  - `nonce` (`String`) — 查询参数
  - `echostr` (`String`) — 查询参数

**响应** `String`

### 📌 `POST` /wx/callback/contacts — 接收联系人同步事件

> 企业微信通讯录变更事件接收端点。接收员工创建/更新/删除、部门变更等事件，解密后转发给ContactChangeHandler处理，同步更新本地管理员数据。必须5秒内返回'success'。

**参数**

  - `msgSignature` (`String`) — 查询参数
  - `timestamp` (`String`) — 查询参数
  - `nonce` (`String`) — 查询参数

**响应** `String`

### 🆕 新增: File

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「文件管理」**

### 📌 `POST` /admin/file/upload/token — 请求上传凭证

> 上传流程第一步：前端请求上传凭证 → 获取OSS预签名URL和临时凭证 → 前端直传OSS → 调用确认上传接口。凭证有效期有限，过期需重新请求

**请求体** `UploadTokenRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileName` | `String` | 文件名 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件MD5哈希 |
| `forcePresigned` | `boolean` | 强制使用预签名URL（跳过STS分片模式） |

**响应** `Result<UploadTokenVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `uploadMode` | `String` | 上传模式: PRESIGNED_URL/STS_MULTIPART/INSTANT |
| `contentType` | `String` | 上传时必须使用的Content-Type（与预签名URL签名一致） |
| `presignedUrl` | `String` | 预签名上传URL |
| `ossKey` | `String` | OSS对象Key |
| `expireAt` | `LocalDateTime` | 过期时间 |
| `stsToken` | `StsTokenInfo` | STS临时凭证 |
| `bucket` | `String` | OSS Bucket名称 |
| `region` | `String` | OSS Region |
| `file` | `FileVO` | 秒传文件信息 |
| `accessKeyId` | `String` | AccessKey ID |
| `accessKeySecret` | `String` | AccessKey Secret |
| `securityToken` | `String` | 安全令牌 |
| `expiration` | `String` | 过期时间 |

### 📌 `POST` /admin/file/upload/confirm — 确认上传完成

> 上传流程第二步：前端直传OSS完成后调用此接口，系统验证文件存在性并创建文件记录。支持MD5去重，相同文件不会重复存储

**请求体** `UploadConfirmRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |

**响应** `Result<FileVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `fileName` | `String` | 文件名 |
| `fileType` | `String` | 文件类型 |
| `mimeType` | `String` | MIME类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件MD5哈希 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `previewUrl` | `String` | 预览地址 |
| `groupKey` | `String` | 业务分组 |
| `status` | `String` | 文件状态 |
| `refCount` | `Integer` | 引用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/file/list — 文件列表（分页）

> 支持按文件类型、分组、上传者等条件筛选，按上传时间倒序分页返回

**关联字典**：
- file_type：文件类型（列表筛选+显示）
- file_status：文件状态（显示）

**响应** `Result<IPage<FileVO>>`

### 📌 `GET` /admin/file/{fileId} — 文件详情

> **关联字典**：
- file_type：文件类型（显示）
- file_status：文件状态（显示）

**参数**

  - `{fileId}` (`Long`) — 路径参数：文件ID

**响应** `Result<FileVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `fileName` | `String` | 文件名 |
| `fileType` | `String` | 文件类型 |
| `mimeType` | `String` | MIME类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件MD5哈希 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `previewUrl` | `String` | 预览地址 |
| `groupKey` | `String` | 业务分组 |
| `status` | `String` | 文件状态 |
| `refCount` | `Integer` | 引用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `DELETE` /admin/file/{fileId} — 删除文件

> 软删除文件记录，如果文件存在引用关系则不允许删除。OSS上的物理文件由定时任务清理

**参数**

  - `{fileId}` (`Long`) — 路径参数：文件ID

**响应** `Result<Void>`

### 📌 `GET` /admin/file/{fileId}/refs — 文件引用列表

> 查看文件被哪些业务实体引用（如景区封面、酒店图片等），用于判断文件是否可安全删除

**参数**

  - `{fileId}` (`Long`) — 路径参数：文件ID

**响应** `Result<List<FileRefVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `refId` | `String` | 引用ID |
| `fileId` | `String` | 文件ID |
| `bizType` | `String` | 业务类型 |
| `bizId` | `String` | 业务ID |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/file/stats — 存储统计

> 返回文件总数、总存储空间、各类型文件占比等统计信息

**响应** `Result<FileStatsVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `totalCount` | `Long` | 文件总数 |
| `totalSize` | `Long` | 文件总大小(字节) |
| `countByType` | `Map<String, Long>` | 按类型统计文件数量 |
| `sizeByType` | `Map<String, Long>` | 按类型统计文件大小 |
| `countByGroup` | `Map<String, Long>` | 按分组统计文件数量 |

### 📌 `GET` /admin/file/{fileId}/preview — 文件内容流式预览

> 流式输出文件内容，设置正确的Content-Type头，支持浏览器直接预览图片和PDF等文件

**参数**

  - `{fileId}` (`Long`) — 路径参数：文件ID

**响应** `void`

### 📌 `GET` /admin/file/preview-by-url — 通过URL预览文件

> 传入完整的OSS文件URL，返回HTML预览页面（PDF用PDF.js渲染，图片直接展示）。

**响应** `void`

### 🆕 新增: InternalFile

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「【内部接口】文件（Feign调用）」**

### 📌 `POST` /internal/file/bindRefs — 绑定文件到业务实体

> 将文件与业务实体建立引用关系（如景区ID+封面图），同一文件可被多个业务实体引用

**请求体** `BindRefsRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `bizType` | `String` | 业务类型 |
| `bizId` | `Long` | 业务ID |
| `fileIds` | `List<Long>` | 文件ID列表 |

**响应** `Result<Void>`

### 📌 `POST` /internal/file/unbindRefs — 解绑业务实体的所有文件

> 删除指定业务类型+业务ID下的所有文件引用关系，常用于业务实体删除时的级联清理

**请求体** `UnbindRefsRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `bizType` | `String` | 业务类型 |
| `bizId` | `Long` | 业务ID |

**响应** `Result<Void>`

### 📌 `POST` /internal/file/byIds — 批量获取文件信息

> 内部服务间调用。根据文件ID列表批量查询文件信息（含OSS URL、文件名、类型等），用于其他服务获取关联文件的详细数据。

**请求体** `BatchFileRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileIds` | `List<Long>` | 文件ID列表 |

**响应** `Result<List<FileVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `fileName` | `String` | 文件名 |
| `fileType` | `String` | 文件类型 |
| `mimeType` | `String` | MIME类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件MD5哈希 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `previewUrl` | `String` | 预览地址 |
| `groupKey` | `String` | 业务分组 |
| `status` | `String` | 文件状态 |
| `refCount` | `Integer` | 引用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /internal/file/upload/token — 内部上传凭证（素材服务调用）

> 内部服务间调用。素材服务代理调用，为指定管理员生成OSS上传预签名URL和临时凭证，用于素材库的文件上传流程。

**参数**

  - `adminId` (`Long`) — 查询参数

**请求体** `UploadTokenRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileName` | `String` | 文件名 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件MD5哈希 |
| `forcePresigned` | `boolean` | 强制使用预签名URL（跳过STS分片模式） |

**响应** `Result<UploadTokenVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `uploadMode` | `String` | 上传模式: PRESIGNED_URL/STS_MULTIPART/INSTANT |
| `contentType` | `String` | 上传时必须使用的Content-Type（与预签名URL签名一致） |
| `presignedUrl` | `String` | 预签名上传URL |
| `ossKey` | `String` | OSS对象Key |
| `expireAt` | `LocalDateTime` | 过期时间 |
| `stsToken` | `StsTokenInfo` | STS临时凭证 |
| `bucket` | `String` | OSS Bucket名称 |
| `region` | `String` | OSS Region |
| `file` | `FileVO` | 秒传文件信息 |
| `accessKeyId` | `String` | AccessKey ID |
| `accessKeySecret` | `String` | AccessKey Secret |
| `securityToken` | `String` | 安全令牌 |
| `expiration` | `String` | 过期时间 |

### 📌 `POST` /internal/file/upload/direct — 内部直接上传文件（服务间调用）

> 服务间直接上传文件到OSS，跳过预签名流程。返回OSS公开访问URL，适用于后端生成的文件（如路线地图截图）

**参数**

  - `file` (`MultipartFile`) — 查询参数
  - `groupKey` (`String`) — 查询参数

**响应** `Result<String>`

### 📌 `POST` /internal/file/upload/confirm — 内部确认上传（素材服务调用）

> 内部服务间调用。素材服务代理调用，确认文件已上传至OSS并创建文件记录。支持MD5去重。

**参数**

  - `adminId` (`Long`) — 查询参数

**请求体** `UploadConfirmRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |

**响应** `Result<FileVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `fileName` | `String` | 文件名 |
| `fileType` | `String` | 文件类型 |
| `mimeType` | `String` | MIME类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件MD5哈希 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `previewUrl` | `String` | 预览地址 |
| `groupKey` | `String` | 业务分组 |
| `status` | `String` | 文件状态 |
| `refCount` | `Integer` | 引用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /internal/file/upload/chunk/init — 分片上传-初始化

> 大文件上传第一步：初始化分片上传任务，返回uploadId和每个分片的预签名URL。前端按分片并发上传后调用complete接口合并

**参数**

  - `adminId` (`Long`) — 查询参数

**请求体** `ChunkUploadInitRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `filename` | `String` | 文件名 |
| `fileSize` | `Long` | 文件大小（字节） |
| `contentType` | `String` | 文件MIME类型 |
| `fileHash` | `String` | 文件MD5哈希（用于去重） |

**响应** `Result<ChunkUploadInitVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `uploadId` | `String` | 上传ID（OSS multipart uploadId） |
| `chunkSize` | `int` | 推荐分片大小（字节） |
| `fileId` | `String` | 文件ID（file_info记录） |
| `ossKey` | `String` | OSS对象Key |

### 📌 `POST` /internal/file/upload/chunk — 分片上传-上传分片

> 大文件上传第二步：逐个上传分片，返回分片的ETag用于后续合并校验。支持断点续传，已上传的分片无需重传

**参数**

  - `uploadId` (`String`) — 查询参数
  - `chunkIndex` (`int`) — 查询参数
  - `chunk` (`MultipartFile`) — 查询参数

**响应** `Result<ChunkUploadPartVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `etag` | `String` | 分片ETag（用于合并时校验） |

### 📌 `POST` /internal/file/upload/chunk/complete — 分片上传-完成合并

> 大文件上传第三步：所有分片上传完成后调用，OSS端合并分片为完整文件并创建文件记录

**请求体** `ChunkUploadCompleteRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `uploadId` | `String` | 上传ID |

**响应** `Result<FileVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `fileName` | `String` | 文件名 |
| `fileType` | `String` | 文件类型 |
| `mimeType` | `String` | MIME类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件MD5哈希 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `previewUrl` | `String` | 预览地址 |
| `groupKey` | `String` | 业务分组 |
| `status` | `String` | 文件状态 |
| `refCount` | `Integer` | 引用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /internal/file/upload/chunk/cancel — 分片上传-取消

> 取消分片上传任务，清理已上传的分片数据和OSS临时文件

**请求体** `ChunkUploadCancelRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `uploadId` | `String` | 上传ID |

**响应** `Result<Void>`

### 🆕 新增: MpFile

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「C端文件上传」**

### 📌 `GET` /mp/file/mp/file

### 📌 `POST` /mp/file/upload — 上传文件（C端用户）

> 小程序端直接上传文件，支持头像、评价图片等场景。groupKey决定存储路径和文件策略，默认为avatar

**参数**

  - `file` (`MultipartFile`) — 查询参数：上传文件
  - `groupKey` (`String`) — 查询参数：文件分组标识

**响应** `Result<FileVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `fileName` | `String` | 文件名 |
| `fileType` | `String` | 文件类型 |
| `mimeType` | `String` | MIME类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件MD5哈希 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `previewUrl` | `String` | 预览地址 |
| `groupKey` | `String` | 业务分组 |
| `status` | `String` | 文件状态 |
| `refCount` | `Integer` | 引用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /mp/file/{fileId}/preview — 文件内容流式预览

> 流式输出文件内容，设置正确的Content-Type头。用于小程序端通过web-view直接预览图片和PDF等文件。

**参数**

  - `{fileId}` (`Long`) — 路径参数：文件ID

**响应** `void`

### 📌 `GET` /mp/file/preview-by-url — 文件在线预览

> 返回HTML预览页面，小程序通过web-view打开。支持PDF、图片、Office文档

**响应** `void`

### 🆕 新增: ApprovalLog

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「企微审批日志」**

### 📌 `GET` /admin/monitor/approval-logs — 审批日志分页查询

> 查询企微OA审批流程记录，支持按审批状态(1-审批中/2-已通过/3-已驳回/4-已撤销)、申请人、模板名称筛选

**关联字典**：
- approval_sp_status：审批状态（列表筛选+显示）

**参数**

  - `page` (`int`) — 查询参数：页码
  - `pageSize` (`int`) — 查询参数：每页条数
  - `spStatus` (`Integer`) — 查询参数：审批状态
  - `applyUserName` (`String`) — 查询参数：申请人姓名
  - `spName` (`String`) — 查询参数：审批模板名称
  - `startTime` (`String`) — 查询参数：开始时间
  - `endTime` (`String`) — 查询参数：结束时间

**响应** `Result<PageResult<ApprovalLog>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `approvalLogId` | `Long` | 审批日志ID |
| `thirdNo` | `String` | 审批编号 |
| `spName` | `String` | 审批模板名称 |
| `templateId` | `String` | 审批模板ID |
| `spStatus` | `Integer` | 审批状态: 1-审批中, 2-已通过, 3-已驳回, 4-已撤销, 6-通过后撤销, 7-已删除 |
| `applyUserId` | `String` | 申请人企微UserID |
| `applyUserName` | `String` | 申请人姓名 |
| `applyTime` | `LocalDateTime` | 申请时间 |
| `approvalNodes` | `String` | 审批节点详情(JSON) |
| `notifyNodes` | `String` | 抄送节点详情(JSON) |
| `applyData` | `String` | 申请表单数据(JSON) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `updatedAt` | `LocalDateTime` | 更新时间 |

### 📌 `GET` /admin/monitor/approval-logs/{id} — 审批日志详情

> **关联字典**：
- approval_sp_status：审批状态（显示）

**参数**

  - `{id}` (`Long`) — 路径参数：日志ID

**响应** `Result<ApprovalLog>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `approvalLogId` | `Long` | 审批日志ID |
| `thirdNo` | `String` | 审批编号 |
| `spName` | `String` | 审批模板名称 |
| `templateId` | `String` | 审批模板ID |
| `spStatus` | `Integer` | 审批状态: 1-审批中, 2-已通过, 3-已驳回, 4-已撤销, 6-通过后撤销, 7-已删除 |
| `applyUserId` | `String` | 申请人企微UserID |
| `applyUserName` | `String` | 申请人姓名 |
| `applyTime` | `LocalDateTime` | 申请时间 |
| `approvalNodes` | `String` | 审批节点详情(JSON) |
| `notifyNodes` | `String` | 抄送节点详情(JSON) |
| `applyData` | `String` | 申请表单数据(JSON) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `updatedAt` | `LocalDateTime` | 更新时间 |

### 🆕 新增: DataRetention

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「数据清理」**

### 📌 `POST` /admin/monitor/data-retention/cleanup — 手动触发数据清理

> 仅超级管理员可操作。按数据保留策略清理过期日志（操作日志/错误日志/通知日志等），返回各类型清理的记录数

**响应** `Result<Map<String, Integer>>`

### 🆕 新增: ErrorLog

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「错误日志」**

### 📌 `GET` /admin/monitor/error-logs — 错误日志分页查询

> 查询各微服务的异常记录，支持按服务名称、异常类名、时间范围筛选。堆栈信息仅保留com.hulalv包内的调用帧

**参数**

  - `page` (`int`) — 查询参数：页码
  - `pageSize` (`int`) — 查询参数：每页条数
  - `serviceName` (`String`) — 查询参数：服务名称
  - `exceptionClass` (`String`) — 查询参数：异常类名
  - `startTime` (`String`) — 查询参数：开始时间
  - `endTime` (`String`) — 查询参数：结束时间

**响应** `Result<PageResult<ErrorLog>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `errorLogId` | `Long` | 错误日志ID |
| `serviceName` | `String` | 服务名称 |
| `requestUrl` | `String` | 请求URL |
| `requestMethod` | `String` | 请求方法 |
| `requestParams` | `String` | 请求参数(JSON) |
| `adminId` | `Long` | 管理员ID |
| `exceptionClass` | `String` | 异常类名 |
| `exceptionMessage` | `String` | 异常消息 |
| `stackTrace` | `String` | 堆栈跟踪 |
| `ipAddress` | `String` | IP地址 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/monitor/error-logs/{id} — 错误日志详情

> 返回单条错误日志的完整信息，包含异常类名、错误消息、过滤后的堆栈信息（仅com.hulalv包内调用帧）、请求URL、请求参数等。

**参数**

  - `{id}` (`Long`) — 路径参数：日志ID

**响应** `Result<ErrorLog>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `errorLogId` | `Long` | 错误日志ID |
| `serviceName` | `String` | 服务名称 |
| `requestUrl` | `String` | 请求URL |
| `requestMethod` | `String` | 请求方法 |
| `requestParams` | `String` | 请求参数(JSON) |
| `adminId` | `Long` | 管理员ID |
| `exceptionClass` | `String` | 异常类名 |
| `exceptionMessage` | `String` | 异常消息 |
| `stackTrace` | `String` | 堆栈跟踪 |
| `ipAddress` | `String` | IP地址 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 🆕 新增: InternalLog

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「【内部接口】日志接收（Feign调用）」**

### 📌 `POST` /internal/monitor/operation-log — 接收操作日志

> 各微服务通过AOP拦截@OperationLog注解的方法，异步发送操作日志到此接口存储

**请求体** `OperationLogDTO`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `adminId` | `Long` | 管理员ID |
| `adminName` | `String` | 管理员名称 |
| `module` | `String` | 操作模块 |
| `description` | `String` | 操作描述 |
| `requestMethod` | `String` | 请求方法 |
| `requestUrl` | `String` | 请求URL |
| `requestParams` | `String` | 请求参数(JSON) |
| `responseCode` | `Integer` | 响应状态码 |
| `responseMsg` | `String` | 响应消息 |
| `ipAddress` | `String` | IP地址 |
| `duration` | `Integer` | 耗时(毫秒) |
| `status` | `Integer` | 状态: 0-成功, 1-失败 |
| `errorMsg` | `String` | 错误信息 |
| `serviceName` | `String` | 服务名称 |

**响应** `Result<Void>`

### 📌 `POST` /internal/monitor/error-log — 接收错误日志

> 各微服务的GlobalExceptionHandler捕获异常后，异步发送错误日志到此接口存储

**请求体** `ErrorLogDTO`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `serviceName` | `String` | 服务名称 |
| `requestUrl` | `String` | 请求URL |
| `requestMethod` | `String` | 请求方法 |
| `requestParams` | `String` | 请求参数(JSON) |
| `adminId` | `Long` | 管理员ID |
| `exceptionClass` | `String` | 异常类名 |
| `exceptionMessage` | `String` | 异常消息 |
| `stackTrace` | `String` | 堆栈跟踪 |
| `ipAddress` | `String` | IP地址 |

**响应** `Result<Void>`

### 📌 `POST` /internal/monitor/notification-log — 接收通知日志

> 通知服务发送消息（短信/站内信/企微等）后，记录发送结果到此接口

**请求体** `NotificationLogDTO`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `notificationType` | `String` | 通知类型: ADD_EXTERNAL_CONTACT/DEL_FOLLOW_USER/DEL_EXTERNAL_CONTACT |
| `userId` | `String` | 员工企微UserID |
| `userName` | `String` | 员工姓名 |
| `externalUserId` | `String` | 外部联系人ID |
| `externalUserName` | `String` | 外部联系人姓名 |
| `messageContent` | `String` | 消息内容 |
| `sendStatus` | `Integer` | 发送状态: 0-成功, 1-失败, 2-已过滤 |
| `failReason` | `String` | 失败原因 |
| `serviceName` | `String` | 来源服务名称 |

**响应** `Result<Void>`

### 📌 `POST` /internal/monitor/approval-log — 接收审批日志

> 企微回调服务接收审批事件后，发送审批日志到此接口。同一审批单号会更新已有记录（按thirdNo去重）

**请求体** `ApprovalLogDTO`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `thirdNo` | `String` | 审批编号 |
| `spName` | `String` | 审批模板名称 |
| `templateId` | `String` | 审批模板ID |
| `spStatus` | `Integer` | 审批状态: 1-审批中, 2-已通过, 3-已驳回, 4-已撤销 |
| `applyUserId` | `String` | 申请人企微UserID |
| `applyUserName` | `String` | 申请人姓名 |
| `applyTime` | `Long` | 申请时间(Unix时间戳秒) |
| `approvalNodes` | `String` | 审批节点详情(JSON) |
| `notifyNodes` | `String` | 抄送节点详情(JSON) |
| `applyData` | `String` | 申请表单数据(JSON) |

**响应** `Result<Void>`

### 📌 `GET` /internal/monitor/notification-log/customer-stats — 获取用户客户统计

> 统计指定用户的客户增减数据（新增客户数/流失客户数），用于客户管理看板

**参数**

  - `userId` (`String`) — 查询参数

### 🆕 新增: LoginLog

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「登录日志」**

### 📌 `GET` /admin/monitor/login-logs — 登录日志分页查询

> 查询管理员登录记录（代理到user-service），包含登录IP、设备信息、登录方式和登录结果

**关联字典**：
- login_status：登录状态（列表筛选+显示）

**参数**

  - `page` (`int`) — 查询参数：页码
  - `pageSize` (`int`) — 查询参数：每页条数
  - `adminId` (`Long`) — 查询参数：管理员ID
  - `status` (`String`) — 查询参数：状态
  - `startTime` (`String`) — 查询参数：开始时间
  - `endTime` (`String`) — 查询参数：结束时间

### 🆕 新增: MysqlMonitor

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「MySQL监控」**

### 📌 `GET` /admin/monitor/mysql — MySQL实时监控数据

> 返回MySQL实时状态：连接数、QPS、缓冲池命中率、线程状态、慢查询计数等核心指标

**响应** `Result<Map<String, Object>>`

### 📌 `GET` /admin/monitor/mysql/tables — 表空间列表

> 查询各数据库表的空间占用情况，包含数据大小、索引大小、行数等信息。可指定schema筛选，仅允许查询hl_前缀的数据库

**参数**

  - `schema` (`String`) — 查询参数：数据库名

**响应** `Result<List<Map<String, Object>>>`

### 📌 `GET` /admin/monitor/mysql/slow-queries — 慢SQL查询统计

> 仅超级管理员可操作。查询慢SQL统计信息，返回执行时间最长的SQL语句及其执行次数、平均耗时等

**参数**

  - `limit` (`int`) — 查询参数：返回条数
  - `type` (`String`) — 查询参数：查询类型

**响应** `Result<List<Map<String, Object>>>`

### 🆕 新增: NotificationLog

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「消息通知日志」**

### 📌 `GET` /admin/monitor/notification-logs — 消息通知日志分页查询

> 查询各渠道（短信/站内信/企微/公众号）的通知发送记录，支持按通知类型、用户、发送状态筛选

**关联字典**：
- notification_send_status：发送状态（列表筛选+显示，0=待发送/1=成功/2=失败）

**参数**

  - `page` (`int`) — 查询参数：页码
  - `pageSize` (`int`) — 查询参数：每页条数
  - `notificationType` (`String`) — 查询参数：通知类型
  - `userName` (`String`) — 查询参数：用户名
  - `sendStatus` (`Integer`) — 查询参数：发送状态
  - `startTime` (`String`) — 查询参数：开始时间
  - `endTime` (`String`) — 查询参数：结束时间

**响应** `Result<PageResult<NotificationLog>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `notificationLogId` | `Long` | 通知日志ID |
| `notificationType` | `String` | 通知类型: ADD_EXTERNAL_CONTACT/DEL_FOLLOW_USER/DEL_EXTERNAL_CONTACT |
| `userId` | `String` | 员工企微UserID |
| `userName` | `String` | 员工姓名 |
| `externalUserId` | `String` | 外部联系人ID |
| `externalUserName` | `String` | 外部联系人姓名 |
| `messageContent` | `String` | 消息内容 |
| `sendStatus` | `Integer` | 发送状态: 0-成功, 1-失败, 2-已过滤 |
| `failReason` | `String` | 失败原因 |
| `serviceName` | `String` | 来源服务名称 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/monitor/notification-logs/{id} — 消息通知日志详情

> 返回单条通知发送日志的完整信息，包含通知类型、接收用户、发送渠道、发送状态、失败原因（如有）、消息内容等。

**参数**

  - `{id}` (`Long`) — 路径参数：日志ID

**响应** `Result<NotificationLog>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `notificationLogId` | `Long` | 通知日志ID |
| `notificationType` | `String` | 通知类型: ADD_EXTERNAL_CONTACT/DEL_FOLLOW_USER/DEL_EXTERNAL_CONTACT |
| `userId` | `String` | 员工企微UserID |
| `userName` | `String` | 员工姓名 |
| `externalUserId` | `String` | 外部联系人ID |
| `externalUserName` | `String` | 外部联系人姓名 |
| `messageContent` | `String` | 消息内容 |
| `sendStatus` | `Integer` | 发送状态: 0-成功, 1-失败, 2-已过滤 |
| `failReason` | `String` | 失败原因 |
| `serviceName` | `String` | 来源服务名称 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 🆕 新增: OperationLog

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「操作日志」**

### 📌 `GET` /admin/monitor/operation-logs — 操作日志分页查询

> 查询管理员的操作记录，支持按模块、管理员、状态、时间范围筛选。记录包含请求参数、响应结果和耗时信息

**操作状态**：0=成功, 1=失败（非字典，代码常量）

**参数**

  - `page` (`int`) — 查询参数：页码
  - `pageSize` (`int`) — 查询参数：每页条数
  - `module` (`String`) — 查询参数：模块名称
  - `adminId` (`Long`) — 查询参数：管理员ID
  - `status` (`Integer`) — 查询参数：状态
  - `startTime` (`String`) — 查询参数：开始时间
  - `endTime` (`String`) — 查询参数：结束时间

**响应** `Result<PageResult<OperationLog>>`

### 📌 `GET` /admin/monitor/operation-logs/{id} — 操作日志详情

> 返回单条操作日志的完整信息，包含操作模块、操作描述、请求参数、响应结果、操作耗时、操作人信息、IP地址等。

**参数**

  - `{id}` (`Long`) — 路径参数：日志ID

**响应** `Result<OperationLog>`

### 🆕 新增: RedisMonitor

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「Redis监控」**

### 📌 `GET` /admin/monitor/redis — Redis实时监控数据

> 返回Redis实时状态：内存使用量、连接数、Key数量、命中率、每秒命令数等核心指标

**响应** `Result<Map<String, Object>>`

### 🆕 新增: RocketMqMonitor

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「RocketMQ监控」**

### 📌 `GET` /admin/monitor/rocketmq — RocketMQ概览

> 返回RocketMQ集群状态：Broker状态、Topic数量、消息积压量、生产者/消费者连接数等核心指标

**响应** `Result<Map<String, Object>>`

### 📌 `GET` /admin/monitor/rocketmq/topics — Topic统计

> 返回各Topic的消息量、最新偏移量和消费进度等信息

**响应** `Result<List<Map<String, Object>>>`

### 📌 `GET` /admin/monitor/rocketmq/consumer-groups — 消费者组统计

> 返回各消费者组的消费进度、积压量和在线消费者实例信息

**响应** `Result<List<Map<String, Object>>>`

### 🆕 新增: ServiceMonitor

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「服务监控」**

### 📌 `GET` /admin/monitor/services — 微服务列表和健康状态

> 从Nacos注册中心获取所有微服务的实例列表和健康状态，包含IP、端口、注册时间和健康检查结果

**响应** `Result<List<Map<String, Object>>>`

### 🆕 新增: AdminReview

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「管理端-评价审核」**

### 📌 `GET` /admin/review/list — 评价列表(支持好中差评/有图/有视频筛选)

> 分页查询全部评价（含待审核/已通过/已拒绝），支持按评价等级、是否有图/视频、目标类型筛选

**关联字典**：
- review_status：评价审核状态（列表筛选+显示）
- rating_level：评价等级（列表筛选+显示）

**响应** `Result<PageResult<ReviewListVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签 |
| `content` | `String` | 评价内容 |
| `imageCount` | `Integer` | 图片数量 |
| `videoCount` | `Integer` | 视频数量 |
| `status` | `String` | 评价状态 |
| `statusLabel` | `String` | 评价状态标签 |
| `rejectReason` | `String` | 拒绝原因 |
| `auditorName` | `String` | 审核人姓名 |
| `auditedAt` | `LocalDateTime` | 审核时间 |
| `hasReply` | `Boolean` | 是否已回复 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/review/{reviewId} — 评价详情

> **关联字典**：
- review_status：评价审核状态（显示）
- rating_level：评价等级（显示）

**参数**

  - `{reviewId}` (`Long`) — 路径参数：评价ID

**响应** `Result<ReviewVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userId` | `String` | 用户ID |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `hasImage` | `Boolean` | 是否有图片 |
| `hasVideo` | `Boolean` | 是否有视频 |
| `imageCount` | `Integer` | 图片数量 |
| `videoCount` | `Integer` | 视频数量 |
| `status` | `String` | 评价状态 |
| `statusLabel` | `String` | 评价状态标签 |
| `machineResult` | `String` | 机审结果 |
| `rejectReason` | `String` | 拒绝原因 |
| `auditorAdminId` | `String` | 审核人ID |
| `auditorName` | `String` | 审核人姓名 |
| `auditedAt` | `LocalDateTime` | 审核时间 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `images` | `List<ReviewImageVO>` | 评价图片列表 |
| `videos` | `List<ReviewVideoVO>` | 评价视频列表 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `imageId` | `String` | 图片ID |
| `imageUrl` | `String` | 图片URL |
| `fileId` | `String` | 文件ID |
| `sortOrder` | `Integer` | 排序序号 |
| `videoId` | `String` | 视频ID |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |
| `fileId` | `String` | 文件ID |
| `sortOrder` | `Integer` | 排序序号 |

### 📌 `POST` /admin/review/{reviewId}/approve — 通过评价

> 审核通过评价，通过后评价在小程序端公开展示。状态流转：PENDING_REVIEW → APPROVED

**参数**

  - `{reviewId}` (`Long`) — 路径参数：评价ID

**响应** `Result<Void>`

### 📌 `POST` /admin/review/{reviewId}/reject — 拒绝评价

> 审核拒绝评价，需填写拒绝原因。拒绝后评价不公开展示。状态流转：PENDING_REVIEW → REJECTED

**参数**

  - `{reviewId}` (`Long`) — 路径参数：评价ID

**请求体** `RejectRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `rejectReason` | `String` | 拒绝原因 |

**响应** `Result<Void>`

### 📌 `POST` /admin/review/{reviewId}/override-approve — 覆盖通过(机器拒绝的)

> 对阿里云内容审核自动拒绝的评价进行人工覆盖通过。状态流转：AUTO_REJECTED → APPROVED

**参数**

  - `{reviewId}` (`Long`) — 路径参数：评价ID

**响应** `Result<Void>`

### 📌 `POST` /admin/review/{reviewId}/reply — 回复评价(每条评价仅可回复一次)

> 管理员回复用户评价，回复内容在小程序端公开展示。每条评价仅允许回复一次，不可修改。

**权限**：需管理员登录。

**参数**

  - `{reviewId}` (`Long`) — 路径参数：评价ID

**请求体** `AdminReplyRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `replyContent` | `String` | 回复内容 |

**响应** `Result<Void>`

### 🆕 新增: InternalMpReview

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「【内部接口】小程序评价（Feign调用）」**

### 📌 `POST` /internal/mp/review/create — 创建评价(仅针对产品，每个订单仅可评价一次)

> **关联字典**：
- review_status：评价审核状态（返回字段）
- rating_level：评价等级（返回字段）

**请求体** `CreateReviewRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `ratings` | `Map<String, Integer>` | 评分数据（key为评分类别字典的dictValue，value为1-5整数）。 |
| `content` | `String` | 评价内容(10-5000字) |
| `images` | `List<ReviewImageItem>` | 评价图片列表（最多9张） |
| `videos` | `List<ReviewVideoItem>` | 评价视频列表（最多3个） |
| `imageUrl` | `String` | 图片URL |
| `fileId` | `Long` | 文件ID |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |
| `fileId` | `Long` | 文件ID |

**响应** `Result<ReviewVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userId` | `String` | 用户ID |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `hasImage` | `Boolean` | 是否有图片 |
| `hasVideo` | `Boolean` | 是否有视频 |
| `imageCount` | `Integer` | 图片数量 |
| `videoCount` | `Integer` | 视频数量 |
| `status` | `String` | 评价状态 |
| `statusLabel` | `String` | 评价状态标签 |
| `machineResult` | `String` | 机审结果 |
| `rejectReason` | `String` | 拒绝原因 |
| `auditorAdminId` | `String` | 审核人ID |
| `auditorName` | `String` | 审核人姓名 |
| `auditedAt` | `LocalDateTime` | 审核时间 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `images` | `List<ReviewImageVO>` | 评价图片列表 |
| `videos` | `List<ReviewVideoVO>` | 评价视频列表 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `imageId` | `String` | 图片ID |
| `imageUrl` | `String` | 图片URL |
| `fileId` | `String` | 文件ID |
| `sortOrder` | `Integer` | 排序序号 |
| `videoId` | `String` | 视频ID |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |
| `fileId` | `String` | 文件ID |
| `sortOrder` | `Integer` | 排序序号 |

### 📌 `GET` /internal/mp/review/order/{orderId}/reviewed — 检查订单是否已评价

> 内部服务间调用。检查指定订单是否已有评价记录，用于小程序端订单详情页控制评价入口的显示。

**参数**

  - `{orderId}` (`Long`) — 路径参数

**响应** `Result<Boolean>`

### 📌 `GET` /internal/mp/review/my — 我的评价列表

> **关联字典**：
- review_status：评价审核状态（显示）
- rating_level：评价等级（显示）

**响应** `Result<PageResult<MpReviewVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `productCoverUrl` | `String` | 产品封面URL(快照) |
| `productSnapshot` | `String` | 产品快照JSON(来自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `images` | `List<String>` | 图片URL列表 |
| `videos` | `List<MpReviewVideoVO>` | 视频列表 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `likeCount` | `Integer` | 点赞数 |
| `liked` | `Boolean` | 当前用户是否已点赞 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |

### 📌 `GET` /internal/mp/review/target — 某目标的已通过评价(公开，支持好中差评/有图/有视频筛选)

> **关联字典**：
- rating_level：评价等级（筛选+显示）

**响应** `Result<PageResult<MpReviewVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `productCoverUrl` | `String` | 产品封面URL(快照) |
| `productSnapshot` | `String` | 产品快照JSON(来自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `images` | `List<String>` | 图片URL列表 |
| `videos` | `List<MpReviewVideoVO>` | 视频列表 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `likeCount` | `Integer` | 点赞数 |
| `liked` | `Boolean` | 当前用户是否已点赞 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |

### 📌 `GET` /internal/mp/review/search — 关键词搜索评价(公开)

> **关联字典**：
- rating_level：评价等级（显示）

**参数**

  - `keyword` (`String`) — 查询参数：搜索关键词
  - `targetType` (`String`) — 查询参数：目标类型(可选)
  - `targetId` (`Long`) — 查询参数：目标ID(可选)
  - `page` (`Integer`) — 查询参数：页码
  - `pageSize` (`Integer`) — 查询参数：每页条数

**响应** `Result<PageResult<MpReviewVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `productCoverUrl` | `String` | 产品封面URL(快照) |
| `productSnapshot` | `String` | 产品快照JSON(来自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `images` | `List<String>` | 图片URL列表 |
| `videos` | `List<MpReviewVideoVO>` | 视频列表 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `likeCount` | `Integer` | 点赞数 |
| `liked` | `Boolean` | 当前用户是否已点赞 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |

### 📌 `GET` /internal/mp/review/featured — 首页精选评价

> **关联字典**：
- rating_level：评价等级（显示）

**参数**

  - `limit` (`Integer`) — 查询参数：数量限制

**响应** `Result<List<MpReviewVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `productCoverUrl` | `String` | 产品封面URL(快照) |
| `productSnapshot` | `String` | 产品快照JSON(来自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `images` | `List<String>` | 图片URL列表 |
| `videos` | `List<MpReviewVideoVO>` | 视频列表 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `likeCount` | `Integer` | 点赞数 |
| `liked` | `Boolean` | 当前用户是否已点赞 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |

### 📌 `GET` /internal/mp/review/order/{orderId}/reviewable-targets — 订单可评价目标列表

> 内部服务间调用。返回订单关联的可评价目标（产品、定制师等），用于评价页面选择评价对象。已评价的目标不会重复出现。

**参数**

  - `{orderId}` (`Long`) — 路径参数

**响应** `Result<List<Map<String, Object>>>`

### 📌 `POST` /internal/mp/review/{reviewId}/like — 点赞/取消点赞评价

> 内部服务间调用。切换当前用户对评价的点赞状态（toggle），返回最新点赞状态和点赞总数。

**参数**

  - `{reviewId}` (`Long`) — 路径参数

**响应** `Result<Map<String, Object>>`

### 📌 `GET` /internal/mp/review/{reviewId}/like/check — 检查是否已点赞

> 内部服务间调用。检查当前用户是否已对指定评价点赞，用于小程序端渲染点赞按钮状态。

**参数**

  - `{reviewId}` (`Long`) — 路径参数

**响应** `Result<Boolean>`

### 📌 `POST` /internal/mp/review/{reviewId}/sync-like-count — 同步评价点赞数（供通用点赞服务回调）

> 内部服务间调用。通用点赞服务（user-service）发生点赞变化后回调此接口，同步更新评价表的点赞计数字段。

**参数**

  - `{reviewId}` (`Long`) — 路径参数
  - `likeCount` (`int`) — 查询参数

**响应** `Result<Void>`

### 🆕 新增: InternalReview

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「【内部接口】评价统计（Feign调用）」**

### 📌 `GET` /internal/review/target-stats — 目标评价统计(平均分,数量)

> **关联字典**：
- rating_level：评价等级（统计维度）

**参数**

  - `targetType` (`String`) — 查询参数
  - `targetId` (`Long`) — 查询参数

**响应** `Result<ReviewStatsVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `targetType` | `String` | 评价目标类型 |
| `targetId` | `String` | 评价目标ID |
| `averageRating` | `BigDecimal` | 整体满意度平均分 |
| `avgItinerary` | `BigDecimal` | 行程安排平均分 |
| `avgAccommodation` | `BigDecimal` | 住宿安排平均分 |
| `avgDriver` | `BigDecimal` | 司机服务平均分 |
| `avgDining` | `BigDecimal` | 餐饮质量平均分 |
| `totalCount` | `Integer` | 评价总数 |
| `goodCount` | `Integer` | 好评数 |
| `mediumCount` | `Integer` | 中评数 |
| `badCount` | `Integer` | 差评数 |
| `withImageCount` | `Integer` | 有图评价数 |
| `withVideoCount` | `Integer` | 有视频评价数 |
| `goodRate` | `BigDecimal` | 好评率(百分比, 如 98) |

### 📌 `GET` /internal/review/target-list — 目标已通过评价列表

> **关联字典**：
- rating_level：评价等级（显示）

**参数**

  - `targetType` (`String`) — 查询参数
  - `targetId` (`Long`) — 查询参数
  - `page` (`Integer`) — 查询参数
  - `pageSize` (`Integer`) — 查询参数

**响应** `Result<PageResult<MpReviewVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `productCoverUrl` | `String` | 产品封面URL(快照) |
| `productSnapshot` | `String` | 产品快照JSON(来自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `images` | `List<String>` | 图片URL列表 |
| `videos` | `List<MpReviewVideoVO>` | 视频列表 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `likeCount` | `Integer` | 点赞数 |
| `liked` | `Boolean` | 当前用户是否已点赞 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |

### 📌 `GET` /internal/review/stats-by-targets — 批量目标评价统计(聚合多个targetId)

> **关联字典**：
- rating_level：评价等级（统计维度）

**参数**

  - `targetType` (`String`) — 查询参数
  - `targetIds` (`String`) — 查询参数

**响应** `Result<ReviewStatsVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `targetType` | `String` | 评价目标类型 |
| `targetId` | `String` | 评价目标ID |
| `averageRating` | `BigDecimal` | 整体满意度平均分 |
| `avgItinerary` | `BigDecimal` | 行程安排平均分 |
| `avgAccommodation` | `BigDecimal` | 住宿安排平均分 |
| `avgDriver` | `BigDecimal` | 司机服务平均分 |
| `avgDining` | `BigDecimal` | 餐饮质量平均分 |
| `totalCount` | `Integer` | 评价总数 |
| `goodCount` | `Integer` | 好评数 |
| `mediumCount` | `Integer` | 中评数 |
| `badCount` | `Integer` | 差评数 |
| `withImageCount` | `Integer` | 有图评价数 |
| `withVideoCount` | `Integer` | 有视频评价数 |
| `goodRate` | `BigDecimal` | 好评率(百分比, 如 98) |

### 📌 `GET` /internal/review/reviews-by-targets — 批量目标已通过评价列表(聚合多个targetId)

> **关联字典**：
- rating_level：评价等级（显示）

**参数**

  - `targetType` (`String`) — 查询参数
  - `targetIds` (`String`) — 查询参数
  - `page` (`Integer`) — 查询参数
  - `pageSize` (`Integer`) — 查询参数

**响应** `Result<PageResult<MpReviewVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `productCoverUrl` | `String` | 产品封面URL(快照) |
| `productSnapshot` | `String` | 产品快照JSON(来自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `images` | `List<String>` | 图片URL列表 |
| `videos` | `List<MpReviewVideoVO>` | 视频列表 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `likeCount` | `Integer` | 点赞数 |
| `liked` | `Boolean` | 当前用户是否已点赞 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |

### 📌 `GET` /internal/review/product-highlights — 产品精选评价(最高评分+最高点赞+统计)

> **关联字典**：
- rating_level：评价等级（显示）

**参数**

  - `productId` (`Long`) — 查询参数

**响应** `Result<Map<String, Object>>`

### 📌 `GET` /internal/review/customizer-reviews — 定制师已通过评价列表

> **关联字典**：
- rating_level：评价等级（筛选+显示）

**参数**

  - `customizerId` (`Long`) — 查询参数
  - `page` (`Integer`) — 查询参数
  - `pageSize` (`Integer`) — 查询参数
  - `ratingLevel` (`String`) — 查询参数

**响应** `Result<PageResult<MpReviewVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewId` | `String` | 评价ID |
| `orderId` | `String` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userNickname` | `String` | 用户昵称 |
| `userAvatar` | `String` | 用户头像 |
| `reviewType` | `String` | 评论类型 |
| `reviewTypeLabel` | `String` | 评论类型标签 |
| `productType` | `String` | 产品类型 |
| `productTypeLabel` | `String` | 产品类型标签 |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `productCoverUrl` | `String` | 产品封面URL(快照) |
| `productSnapshot` | `String` | 产品快照JSON(来自订单) |
| `ratingItinerary` | `Integer` | 行程安排评分(1-5) |
| `ratingAccommodation` | `Integer` | 住宿安排评分(1-5) |
| `ratingDriver` | `Integer` | 司机服务评分(1-5) |
| `ratingDining` | `Integer` | 餐饮质量评分(1-5) |
| `ratingOverall` | `Integer` | 整体满意度评分(1-5) |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `ratingLevelLabel` | `String` | 评价等级标签: 好评/中评/差评 |
| `content` | `String` | 评价内容 |
| `images` | `List<String>` | 图片URL列表 |
| `videos` | `List<MpReviewVideoVO>` | 视频列表 |
| `adminReply` | `String` | 管理员回复内容 |
| `adminReplyName` | `String` | 回复管理员姓名 |
| `adminReplyAt` | `LocalDateTime` | 回复时间 |
| `likeCount` | `Integer` | 点赞数 |
| `liked` | `Boolean` | 当前用户是否已点赞 |
| `departureDate` | `LocalDate` | 出发日期(冗余自订单) |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `videoUrl` | `String` | 视频URL |
| `coverUrl` | `String` | 视频封面URL |
| `duration` | `Integer` | 视频时长(秒) |

### 📌 `GET` /internal/review/customizer-review-stats — 定制师评价统计(总数/平均分/好评率)

> 内部服务间调用。返回指定定制师的评价汇总统计：总评价数、平均评分、好评率等。用于定制师主页展示服务评价。

**参数**

  - `customizerId` (`Long`) — 查询参数

### 📌 `GET` /internal/review/order/{orderId}/summary — 订单评价摘要(行程详情用)

> 返回订单的产品评价摘要信息，无评价返回null

**参数**

  - `{orderId}` (`Long`) — 路径参数

**响应** `Result<Map<String, Object>>`

### 🆕 新增: Board

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「任务看板管理」**

### 📌 `GET` /admin/task/boards — 获取可见看板列表

> 返回当前管理员可见的看板列表：超级管理员可见所有看板，普通管理员仅可见自己创建的或作为成员的看板

**响应** `Result<List<BoardVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `boardId` | `Long` | 看板ID |
| `boardName` | `String` | 看板名称 |
| `description` | `String` | 看板描述 |
| `boardType` | `String` | 看板类型 |
| `deptId` | `Long` | 部门ID |
| `deptName` | `String` | 部门名称 |
| `createdBy` | `Long` | 创建人ID |
| `creatorName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `statuses` | `List<BoardStatusVO>` | 状态列表 |
| `taskCount` | `int` | 任务总数 |

### 📌 `GET` /admin/task/board/{boardId} — 看板详情

> 返回看板基本信息（名称、描述、创建者），不含任务数据。查看任务请使用「获取看板任务」接口

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID

**响应** `Result<BoardVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `boardId` | `Long` | 看板ID |
| `boardName` | `String` | 看板名称 |
| `description` | `String` | 看板描述 |
| `boardType` | `String` | 看板类型 |
| `deptId` | `Long` | 部门ID |
| `deptName` | `String` | 部门名称 |
| `createdBy` | `Long` | 创建人ID |
| `creatorName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `statuses` | `List<BoardStatusVO>` | 状态列表 |
| `taskCount` | `int` | 任务总数 |

### 📌 `POST` /admin/task/board — 创建自定义看板

> 创建自定义看板，自动添加创建者为看板成员，并创建默认状态列（待办、进行中、已完成）。

**权限**：需管理员登录。

**请求体** `CreateBoardRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `boardName` | `String` | 看板名称 |
| `description` | `String` | 看板描述 |
| `deptId` | `Long` | 部门ID |
| `memberIds` | `List<Long>` | 成员ID列表 |

**响应** `Result<BoardVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `boardId` | `Long` | 看板ID |
| `boardName` | `String` | 看板名称 |
| `description` | `String` | 看板描述 |
| `boardType` | `String` | 看板类型 |
| `deptId` | `Long` | 部门ID |
| `deptName` | `String` | 部门名称 |
| `createdBy` | `Long` | 创建人ID |
| `creatorName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `statuses` | `List<BoardStatusVO>` | 状态列表 |
| `taskCount` | `int` | 任务总数 |

### 📌 `PUT` /admin/task/board/{boardId} — 更新看板

> 更新看板的名称和描述。仅看板创建者或超级管理员可操作。

**权限**：需管理员登录，且为看板创建者或超级管理员。

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID

**请求体** `UpdateBoardRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `boardName` | `String` | 看板名称 |
| `description` | `String` | 看板描述 |

**响应** `Result<BoardVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `boardId` | `Long` | 看板ID |
| `boardName` | `String` | 看板名称 |
| `description` | `String` | 看板描述 |
| `boardType` | `String` | 看板类型 |
| `deptId` | `Long` | 部门ID |
| `deptName` | `String` | 部门名称 |
| `createdBy` | `Long` | 创建人ID |
| `creatorName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `statuses` | `List<BoardStatusVO>` | 状态列表 |
| `taskCount` | `int` | 任务总数 |

### 📌 `DELETE` /admin/task/board/{boardId} — 删除看板

> 删除看板及其下所有状态列和任务（级联删除）。仅看板创建者或超级管理员可操作

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID

**响应** `Result<Void>`

### 📌 `GET` /admin/task/board/{boardId}/statuses — 获取看板状态列

> 返回看板的所有状态列（如待办、进行中、已完成），按排序字段升序排列。拖拽任务到不同状态列实现状态流转

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID

**响应** `Result<List<BoardStatusVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusId` | `Long` | 状态ID |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |
| `sortOrder` | `Integer` | 排序序号 |
| `isPreset` | `Boolean` | 是否预设状态 |
| `taskCount` | `int` | 该状态下的任务数量 |

### 📌 `POST` /admin/task/board/{boardId}/status — 创建状态列

> 在看板中创建新的状态列（如测试中、待发布等），自动排到末尾。任务通过拖拽在不同状态列间流转。

**权限**：需管理员登录且为看板成员。

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID

**请求体** `CreateStatusRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |

**响应** `Result<BoardStatusVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusId` | `Long` | 状态ID |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |
| `sortOrder` | `Integer` | 排序序号 |
| `isPreset` | `Boolean` | 是否预设状态 |
| `taskCount` | `int` | 该状态下的任务数量 |

### 📌 `PUT` /admin/task/status/{statusId} — 更新状态列

> 更新状态列的名称和颜色。

**权限**：需管理员登录且为看板成员。

**参数**

  - `{statusId}` (`Long`) — 路径参数：状态列ID

**请求体** `UpdateStatusRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |

**响应** `Result<BoardStatusVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusId` | `Long` | 状态ID |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |
| `sortOrder` | `Integer` | 排序序号 |
| `isPreset` | `Boolean` | 是否预设状态 |
| `taskCount` | `int` | 该状态下的任务数量 |

### 📌 `DELETE` /admin/task/status/{statusId} — 删除状态列

> 删除看板的状态列。如果状态列下有任务则不允许删除，需先移动或删除任务

**参数**

  - `{statusId}` (`Long`) — 路径参数：状态列ID

**响应** `Result<Void>`

### 📌 `PUT` /admin/task/board/{boardId}/status/sort — 状态列排序

> 批量更新状态列的排序顺序。传入状态列ID数组，数组下标即为新的排序值。操作完成后通过WebSocket推送STATUS_REORDERED事件

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID

**请求体** `StatusSortRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusIds` | `List<Long>` | 状态ID列表(按排序顺序) |

**响应** `Result<Void>`

### 📌 `GET` /admin/task/board/{boardId}/members — 获取看板成员

> 返回看板的所有成员列表，包含成员的管理员ID和姓名

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID

**响应** `Result<List<BoardMemberVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `adminId` | `Long` | 管理员ID |
| `username` | `String` | 用户名 |
| `avatarUrl` | `String` | 头像地址 |
| `role` | `String` | 角色: OWNER/MEMBER |
| `joinedAt` | `LocalDateTime` | 加入时间 |

### 📌 `POST` /admin/task/board/{boardId}/members — 添加成员

> 批量添加管理员为看板成员，成为成员后可以查看看板、创建和操作任务。

**权限**：需管理员登录，且为看板创建者或超级管理员。

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID

**请求体** `AddMembersRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `adminIds` | `List<Long>` | 管理员ID列表 |

**响应** `Result<Void>`

### 📌 `DELETE` /admin/task/board/{boardId}/member/{targetAdminId} — 移除成员

> 从看板中移除指定成员。仅看板创建者或超级管理员可操作，不能移除创建者自己

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID
  - `{targetAdminId}` (`Long`) — 路径参数：目标管理员ID

**响应** `Result<Void>`

### 🆕 新增: Task

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「任务管理」**

### 📌 `GET` /admin/task/board/{boardId}/tasks — 获取看板任务(按状态分组)

> 返回看板下所有任务，按状态列分组。支持按优先级(HIGH/MEDIUM/LOW)和负责人筛选，每组内按排序值升序排列

**关联字典**：
- task_priority：任务优先级（列表筛选+显示）

**参数**

  - `{boardId}` (`Long`) — 路径参数：看板ID
  - `priority` (`String`) — 查询参数：优先级
  - `assigneeId` (`Long`) — 查询参数：负责人ID

**响应** `Result<List<BoardTasksVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusId` | `Long` | 状态ID |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |
| `sortOrder` | `Integer` | 排序序号 |
| `tasks` | `List<TaskVO>` | 该状态下的任务列表 |

### 📌 `GET` /admin/task/{taskId} — 任务详情

> 返回任务完整信息，包含子任务列表、负责人信息、附件列表等

**关联字典**：
- task_priority：任务优先级（显示）

**参数**

  - `{taskId}` (`Long`) — 路径参数：任务ID

**响应** `Result<TaskVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `taskId` | `Long` | 任务ID |
| `boardId` | `Long` | 看板ID |
| `parentId` | `Long` | 父任务ID |
| `title` | `String` | 任务标题 |
| `description` | `String` | 任务描述 |
| `statusId` | `Long` | 状态ID |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |
| `priority` | `String` | 优先级: LOW/MEDIUM/HIGH/URGENT |
| `dueDate` | `LocalDate` | 截止日期 |
| `overdue` | `Boolean` | 是否逾期 |
| `sortOrder` | `Integer` | 排序序号 |
| `createdBy` | `Long` | 创建人ID |
| `creatorName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `updatedAt` | `LocalDateTime` | 更新时间 |
| `assignees` | `List<AssigneeVO>` | 负责人列表 |
| `subtaskTotal` | `int` | 子任务总数 |
| `subtaskCompleted` | `int` | 已完成子任务数 |
| `subtasks` | `List<SubtaskVO>` | 子任务列表 |

### 📌 `POST` /admin/task — 创建任务

> 在指定看板和状态列下创建任务。创建成功后通过WebSocket推送TASK_CREATED事件，并通知被分配的负责人

**关联字典**：
- task_priority：任务优先级（创建时选择）

**请求体** `CreateTaskRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `boardId` | `Long` | 看板ID |
| `title` | `String` | 任务标题 |
| `description` | `String` | 任务描述 |
| `statusId` | `Long` | 状态ID |
| `priority` | `String` | 优先级: LOW/MEDIUM/HIGH/URGENT |
| `dueDate` | `LocalDate` | 截止日期 |
| `assigneeIds` | `List<Long>` | 负责人ID列表 |

**响应** `Result<TaskVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `taskId` | `Long` | 任务ID |
| `boardId` | `Long` | 看板ID |
| `parentId` | `Long` | 父任务ID |
| `title` | `String` | 任务标题 |
| `description` | `String` | 任务描述 |
| `statusId` | `Long` | 状态ID |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |
| `priority` | `String` | 优先级: LOW/MEDIUM/HIGH/URGENT |
| `dueDate` | `LocalDate` | 截止日期 |
| `overdue` | `Boolean` | 是否逾期 |
| `sortOrder` | `Integer` | 排序序号 |
| `createdBy` | `Long` | 创建人ID |
| `creatorName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `updatedAt` | `LocalDateTime` | 更新时间 |
| `assignees` | `List<AssigneeVO>` | 负责人列表 |
| `subtaskTotal` | `int` | 子任务总数 |
| `subtaskCompleted` | `int` | 已完成子任务数 |
| `subtasks` | `List<SubtaskVO>` | 子任务列表 |

### 📌 `PUT` /admin/task/{taskId} — 更新任务

> 更新任务的标题、描述、优先级、截止日期、负责人等信息。更新后通过WebSocket推送TASK_UPDATED事件，如果修改了负责人则额外通知新负责人。

**权限**：需管理员登录且为看板成员。

**关联字典**：
- task_priority：任务优先级（编辑时选择）

**参数**

  - `{taskId}` (`Long`) — 路径参数：任务ID

**请求体** `UpdateTaskRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `title` | `String` | 任务标题 |
| `description` | `String` | 任务描述 |
| `priority` | `String` | 优先级: LOW/MEDIUM/HIGH/URGENT |
| `dueDate` | `LocalDate` | 截止日期 |
| `assigneeIds` | `List<Long>` | 负责人ID列表 |

**响应** `Result<TaskVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `taskId` | `Long` | 任务ID |
| `boardId` | `Long` | 看板ID |
| `parentId` | `Long` | 父任务ID |
| `title` | `String` | 任务标题 |
| `description` | `String` | 任务描述 |
| `statusId` | `Long` | 状态ID |
| `statusName` | `String` | 状态名称 |
| `statusColor` | `String` | 状态颜色 |
| `priority` | `String` | 优先级: LOW/MEDIUM/HIGH/URGENT |
| `dueDate` | `LocalDate` | 截止日期 |
| `overdue` | `Boolean` | 是否逾期 |
| `sortOrder` | `Integer` | 排序序号 |
| `createdBy` | `Long` | 创建人ID |
| `creatorName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `updatedAt` | `LocalDateTime` | 更新时间 |
| `assignees` | `List<AssigneeVO>` | 负责人列表 |
| `subtaskTotal` | `int` | 子任务总数 |
| `subtaskCompleted` | `int` | 已完成子任务数 |
| `subtasks` | `List<SubtaskVO>` | 子任务列表 |

### 📌 `PUT` /admin/task/{taskId}/status — 变更任务状态

> 将任务移动到指定状态列（拖拽操作），自动记录状态变更到时间线，并通过WebSocket推送TASK_STATUS_CHANGED事件

**参数**

  - `{taskId}` (`Long`) — 路径参数：任务ID

**请求体** `ChangeStatusRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusId` | `Long` | 目标状态ID |

**响应** `Result<Void>`

### 📌 `PUT` /admin/task/{taskId}/sort — 任务排序

> 更新任务在同一状态列内的排序位置，用于拖拽排序

**参数**

  - `{taskId}` (`Long`) — 路径参数：任务ID

**请求体** `TaskSortRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `statusId` | `Long` | 状态ID |
| `taskIds` | `List<Long>` | 任务ID列表(按排序顺序) |

**响应** `Result<Void>`

### 📌 `DELETE` /admin/task/{taskId} — 删除任务

> 删除任务及其所有子任务、评论和时间线记录（级联删除）。删除后通过WebSocket推送TASK_DELETED事件。

**权限**：需管理员登录且为看板成员。

**参数**

  - `{taskId}` (`Long`) — 路径参数：任务ID

**响应** `Result<Void>`

### 📌 `POST` /admin/task/{taskId}/subtask — 创建子任务

> 在指定任务下创建子任务（待办项），用于拆分任务的执行步骤。子任务默认为未完成状态。

**权限**：需管理员登录且为看板成员。

**参数**

  - `{taskId}` (`Long`) — 路径参数：任务ID

**请求体** `CreateSubtaskRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `title` | `String` | 子任务标题 |

**响应** `Result<SubtaskVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `taskId` | `Long` | 子任务ID |
| `title` | `String` | 子任务标题 |
| `completed` | `Boolean` | 是否已完成 |
| `createdBy` | `Long` | 创建人ID |
| `creatorName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/task/subtask/{subtaskId}/toggle — 切换子任务完成状态

> 切换子任务的完成/未完成状态（toggle），完成状态切换会自动记录到任务时间线

**参数**

  - `{subtaskId}` (`Long`) — 路径参数：子任务ID

**响应** `Result<Void>`

### 📌 `DELETE` /admin/task/subtask/{subtaskId} — 删除子任务

> 删除指定子任务。

**权限**：需管理员登录且为看板成员。

**参数**

  - `{subtaskId}` (`Long`) — 路径参数：子任务ID

**响应** `Result<Void>`

### 📌 `GET` /admin/task/{taskId}/timeline — 获取任务时间线

> 返回任务的完整操作记录，包含评论和系统自动记录的状态变更、人员分配等活动，按时间正序排列

**参数**

  - `{taskId}` (`Long`) — 路径参数：任务ID

**响应** `Result<List<TimelineItemVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | `Long` | 条目ID |
| `type` | `String` | 类型: COMMENT/ACTIVITY |
| `adminId` | `Long` | 管理员ID |
| `adminName` | `String` | 管理员姓名 |
| `adminAvatar` | `String` | 管理员头像 |
| `content` | `String` | 内容 |
| `action` | `String` | 操作类型 |
| `oldValue` | `String` | 旧值 |
| `newValue` | `String` | 新值 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/task/{taskId}/comment — 添加评论

> 在任务时间线中添加评论，添加后自动通知任务负责人

**参数**

  - `{taskId}` (`Long`) — 路径参数：任务ID

**请求体** `CreateCommentRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `content` | `String` | 评论内容 |

**响应** `Result<TimelineItemVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | `Long` | 条目ID |
| `type` | `String` | 类型: COMMENT/ACTIVITY |
| `adminId` | `Long` | 管理员ID |
| `adminName` | `String` | 管理员姓名 |
| `adminAvatar` | `String` | 管理员头像 |
| `content` | `String` | 内容 |
| `action` | `String` | 操作类型 |
| `oldValue` | `String` | 旧值 |
| `newValue` | `String` | 新值 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `DELETE` /admin/task/comment/{commentId} — 删除评论

> 仅评论作者本人可删除自己的评论，系统自动生成的活动记录不可删除

**参数**

  - `{commentId}` (`Long`) — 路径参数：评论ID

**响应** `Result<Void>`

### 🆕 新增: WebSocketDoc

> 📖 **接口文档**: [http://192.168.100.236:8081/doc.html](http://192.168.100.236:8081/doc.html) → 标签 **「WebSocket \u5B9E\u65F6\u63A8\u9001」**

### 📌 `GET` /admin/task/board/ws-doc/info — WebSocket \u8FDE\u63A5\u8BF4\u660E

> ## \u8FDE\u63A5\u4FE1\u606F

**响应** `Map<String, String>`

---

## 订单服务

### 🆕 新增: AdminClauseTemplate

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「补充约定模板管理」**

### 📌 `GET` /admin/contract/clause-template/list — 获取启用的补充约定模板列表（创建合同用）

> 返回所有启用状态的补充约定模板，创建合同时选择需要附加的补充约定条款。

**权限**：需管理员登录。

**响应** `Result<List<ClauseTemplateVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `templateId` | `Long` | 模板ID |
| `name` | `String` | 模板名称 |
| `content` | `String` | 模板内容 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/contract/clause-template/list-all — 获取全部补充约定模板（管理页用）

> **关联字典**：
- common_status：通用状态（列表显示，ACTIVE=启用/INACTIVE=停用）

**响应** `Result<List<ClauseTemplateVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `templateId` | `Long` | 模板ID |
| `name` | `String` | 模板名称 |
| `content` | `String` | 模板内容 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/contract/clause-template/{id}/toggle-status — 切换模板启用/停用状态

> **关联字典**：
- common_status：通用状态（状态切换，ACTIVE=启用/INACTIVE=停用）

**参数**

  - `{templateId}` (`Long`) — 路径参数：模板ID

**响应** `Result<ClauseTemplateVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `templateId` | `Long` | 模板ID |
| `name` | `String` | 模板名称 |
| `content` | `String` | 模板内容 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/contract/clause-template — 创建补充约定模板

> 创建合同补充约定的模板，支持变量占位符。创建后默认启用

**请求体** `ClauseTemplateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `name` | `String` | 模板名称 |
| `content` | `String` | 模板内容 |
| `sortOrder` | `Integer` | 排序（升序） |

**响应** `Result<ClauseTemplateVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `templateId` | `Long` | 模板ID |
| `name` | `String` | 模板名称 |
| `content` | `String` | 模板内容 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/contract/clause-template/{id} — 更新补充约定模板

> 更新模板的标题和内容。已被合同引用的模板更新不影响已创建的合同（合同记录的是快照内容）。

**权限**：需管理员登录。

**参数**

  - `{templateId}` (`Long`) — 路径参数：模板ID

**请求体** `ClauseTemplateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `name` | `String` | 模板名称 |
| `content` | `String` | 模板内容 |
| `sortOrder` | `Integer` | 排序（升序） |

**响应** `Result<ClauseTemplateVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `templateId` | `Long` | 模板ID |
| `name` | `String` | 模板名称 |
| `content` | `String` | 模板内容 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `DELETE` /admin/contract/clause-template/{id} — 删除补充约定模板

> 软删除模板。已被合同引用的模板仍可删除，不影响已创建的合同

**参数**

  - `{templateId}` (`Long`) — 路径参数：模板ID

**响应** `Result<Void>`

### 🆕 新增: AdminContract

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「合同管理」**

### 📌 `GET` /admin/contract/platforms — 可用合同平台列表

> 返回系统已对接的合同平台列表及可用状态。

**响应** `Result<List<ContractPlatformInfo>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `platformName` | `String` |  |
| `displayName` | `String` |  |
| `available` | `boolean` |  |

### 📌 `GET` /admin/contract/agencies — 可用旅行社列表

> 返回系统配置的旅行社列表，创建合同时选择签约旅行社

### 📌 `GET` /admin/contract/templates — 合同模板列表

> 返回合同平台可用的合同模板列表。可通过platform参数过滤：12301=全国旅游监管平台，FADADA=法大大

**参数**

  - `platform` (`String`) — 查询参数：合同平台(可选): 12301/FADADA

**响应** `Result<List<ContractTemplateVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `templateId` | `Long` | 模板ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `platform` | `String` | 签约平台 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 模板状态 |
| `description` | `String` | 模板描述 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/contract/create — 创建合同(标准模式)

> 标准电子签约流程：创建合同 → 平台生成合同PDF → 发送签署短信给出行人 → 出行人在线签署 → 回调更新状态。

**请求体** `CreateContractRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `contractType` | `String` | 合同类型: TOUR-旅游合同(默认), INSURANCE-保险单 |
| `platform` | `String` | 合同平台（字典：contract_platform）: 12301-全国旅游监管平台, FADADA-法大大, ESIGN-e签宝, TENCENT_ESS-腾讯电子签。不传则根据模板自动确定 |
| `templateCode` | `String` | 模板编码 |
| `agencyCode` | `String` | 旅行社编号（可选，不传则按商户号匹配，仍无则用默认值） |
| `mchId` | `String` | 微信支付商户号（用于自动匹配旅行社） |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `destination` | `String` | 目的地 |
| `routeName` | `String` | 线路名称 |
| `days` | `Integer` | 行程天数 |
| `nights` | `Integer` | 住宿晚数 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `departureCity` | `String` | 出发城市 |
| `groupId` | `String` | 团号 |
| `signatoryName` | `String` | 签署人姓名 |
| `signatoryPhone` | `String` | 签署人电话 |
| `signatoryIdNumber` | `String` | 签署人证件号码 |
| `signingPlace` | `String` | 签约地点 |
| `adultCost` | `BigDecimal` | 成人费用 |
| `childCost` | `BigDecimal` | 儿童费用 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `supplementaryClause` | `String` | 补充约定内容 |
| `vehicleModel` | `String` | 车型名称(产品快照) |
| `travelers` | `List<TravelerDTO>` | 出行人列表 |
| `name` | `String` | 姓名 |
| `gender` | `String` | 性别: male/female |
| `age` | `Integer` | 年龄 |
| `idCardNo` | `String` | 证件号码 |
| `phone` | `String` | 手机号 |
| `health` | `String` | 健康信息 |

**响应** `Result<ContractDetailVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `supplementaryClause` | `String` | 补充约定内容 |
| `travelers` | `List<TravelerVO>` | 出行人列表 |
| `statusLogs` | `List<StatusLogVO>` | 状态变更日志 |
| `travelerId` | `Long` | 出行人ID |
| `name` | `String` | 姓名 |
| `idCardType` | `String` | 证件类型 |
| `idCardNo` | `String` | 证件号码 |
| `phone` | `String` | 手机号 |
| `isSigner` | `Boolean` | 是否签署人 |
| `logId` | `Long` | 日志ID |
| `oldStatus` | `String` | 旧状态 |
| `newStatus` | `String` | 新状态 |
| `source` | `String` | 变更来源 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/contract/create-by-scheme — 按方案创建合同（简化）

> 只需传orderId和schemeId，后端自动从订单获取出行人、日期、联系人等数据，结合合同方案配置创建合同。

**响应** `Result<ContractDetailVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `supplementaryClause` | `String` | 补充约定内容 |
| `travelers` | `List<TravelerVO>` | 出行人列表 |
| `statusLogs` | `List<StatusLogVO>` | 状态变更日志 |
| `travelerId` | `Long` | 出行人ID |
| `name` | `String` | 姓名 |
| `idCardType` | `String` | 证件类型 |
| `idCardNo` | `String` | 证件号码 |
| `phone` | `String` | 手机号 |
| `isSigner` | `Boolean` | 是否签署人 |
| `logId` | `Long` | 日志ID |
| `oldStatus` | `String` | 旧状态 |
| `newStatus` | `String` | 新状态 |
| `source` | `String` | 变更来源 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/contract/report — 报备合同(同步模式)

> 线下签约模式：创建合同记录 → 管理员上传已签署的PDF → 同步到12301报备平台。

**请求体** `ReportContractRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `contractType` | `String` | 合同类型: TOUR-旅游合同(默认), INSURANCE-保险单 |
| `platform` | `String` | 合同平台（字典：contract_platform）: 12301-全国旅游监管平台, FADADA-法大大, ESIGN-e签宝, TENCENT_ESS-腾讯电子签 |
| `templateCode` | `String` | 模板编码 |
| `agencyCode` | `String` | 旅行社编号（可选，不传则按商户号匹配，仍无则用默认值） |
| `mchId` | `String` | 微信支付商户号（用于自动匹配旅行社） |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `destination` | `String` | 目的地 |
| `routeName` | `String` | 线路名称 |
| `days` | `Integer` | 行程天数 |
| `nights` | `Integer` | 住宿晚数 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `departureCity` | `String` | 出发城市 |
| `groupId` | `String` | 团号 |
| `signatoryName` | `String` | 签署人姓名 |
| `signatoryPhone` | `String` | 签署人电话 |
| `signatoryIdNumber` | `String` | 签署人证件号码 |
| `signingPlace` | `String` | 签约地点 |
| `adultCost` | `BigDecimal` | 成人费用 |
| `childCost` | `BigDecimal` | 儿童费用 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `supplementaryClause` | `String` | 补充约定内容 |

**响应** `Result<ContractDetailVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `supplementaryClause` | `String` | 补充约定内容 |
| `travelers` | `List<TravelerVO>` | 出行人列表 |
| `statusLogs` | `List<StatusLogVO>` | 状态变更日志 |
| `travelerId` | `Long` | 出行人ID |
| `name` | `String` | 姓名 |
| `idCardType` | `String` | 证件类型 |
| `idCardNo` | `String` | 证件号码 |
| `phone` | `String` | 手机号 |
| `isSigner` | `Boolean` | 是否签署人 |
| `logId` | `Long` | 日志ID |
| `oldStatus` | `String` | 旧状态 |
| `newStatus` | `String` | 新状态 |
| `source` | `String` | 变更来源 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/contract/list — 合同列表

> 分页查询合同记录，支持按订单号、合同状态、旅行社筛选

**关联字典**：
- contract_status：合同状态（列表筛选+显示）

**响应** `Result<PageResult<ContractVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/contract/{id} — 合同详情

> **关联字典**：
- contract_status：合同状态（显示）

**参数**

  - `{contractId}` (`Long`) — 路径参数：合同ID

**响应** `Result<ContractDetailVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `supplementaryClause` | `String` | 补充约定内容 |
| `travelers` | `List<TravelerVO>` | 出行人列表 |
| `statusLogs` | `List<StatusLogVO>` | 状态变更日志 |
| `travelerId` | `Long` | 出行人ID |
| `name` | `String` | 姓名 |
| `idCardType` | `String` | 证件类型 |
| `idCardNo` | `String` | 证件号码 |
| `phone` | `String` | 手机号 |
| `isSigner` | `Boolean` | 是否签署人 |
| `logId` | `Long` | 日志ID |
| `oldStatus` | `String` | 旧状态 |
| `newStatus` | `String` | 新状态 |
| `source` | `String` | 变更来源 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/contract/by-order/{orderId} — 按订单查询合同

> 查询指定订单下的所有合同记录（含已作废），按创建时间倒序排列。用于订单详情页展示合同历史。

**权限**：需管理员登录。

**关联字典**：
- contract_status：合同状态（列表显示）

**参数**

  - `{orderId}` (`Long`) — 路径参数：订单ID

**响应** `Result<List<ContractVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/contract/active-by-order/{orderId} — 获取订单有效合同

> 返回订单当前有效的合同（非作废状态的最新合同），用于检查订单是否已有签署中或已签署的合同。

**权限**：需管理员登录。

**关联字典**：
- contract_status：合同状态（显示）

**参数**

  - `{orderId}` (`Long`) — 路径参数：订单ID

**响应** `Result<ContractVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/contract/{id}/status — 刷新合同状态(从平台同步)

> 主动查询合同平台的最新签署状态并同步到本地，适用于回调未到达的场景

**参数**

  - `{contractId}` (`Long`) — 路径参数：合同ID

**响应** `Result<ContractVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/contract/{id}/invalidate — 作废合同

> 将合同标记为作废状态（不可恢复）。作废后该合同不再有效，可重新为订单创建新合同

**参数**

  - `{contractId}` (`Long`) — 路径参数：合同ID

**响应** `Result<ContractVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/contract/{id}/resend-sms — 重发签署短信

> 重新发送签署短信给出行人，用于签署短信过期或未收到的场景。仅SIGNING状态的合同可操作

**参数**

  - `{contractId}` (`Long`) — 路径参数：合同ID

**响应** `Result<Boolean>`

### 📌 `POST` /admin/contract/{id}/upload-pdf — 上传已签署PDF(同步模式)

> 同步模式专用：上传线下签署完成的合同PDF文件，上传后合同状态变为UPLOADED，可进一步报备

**参数**

  - `{contractId}` (`Long`) — 路径参数：合同ID
  - `file` (`MultipartFile`) — 查询参数：签署PDF文件

**响应** `Result<ContractVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 🆕 新增: AdminContractScheme

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「合同方案管理」**

### 📌 `GET` /admin/contract/scheme/list — 查询启用的合同方案列表

> 供产品配置时下拉选择使用，只返回启用状态的方案

**响应** `Result<List<ContractSchemeVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `String` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `contractPlatform` | `String` | 合同平台: 12301/FADADA |
| `contractTemplateCode` | `String` | 合同模板编码（与模板列表的templateCode一致） |
| `templateCode` | `String` | 合同模板编码（别名，与contractTemplateCode相同值，方便前端统一使用templateCode） |
| `contractTemplateName` | `String` | 合同模板名称（回显用） |
| `contractMode` | `String` | 签约模式: STANDARD(电子签约)/SYNC(线下报备) |
| `signatoryMode` | `Integer` | 签署模式: 1=短信签署 2=现场签署 3=线下签署 |
| `agencyCode` | `String` | 旅行社编码 |
| `agencyName` | `String` | 旅行社名称（回显用） |
| `disputeResolution` | `Integer` | 争议解决方式: 1=仲裁 2=诉讼 |
| `supplementaryClause` | `String` | 补充条款 |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/contract/scheme/list-all — 查询全部合同方案列表

> 管理页面使用，包含停用的方案

**响应** `Result<List<ContractSchemeVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `String` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `contractPlatform` | `String` | 合同平台: 12301/FADADA |
| `contractTemplateCode` | `String` | 合同模板编码（与模板列表的templateCode一致） |
| `templateCode` | `String` | 合同模板编码（别名，与contractTemplateCode相同值，方便前端统一使用templateCode） |
| `contractTemplateName` | `String` | 合同模板名称（回显用） |
| `contractMode` | `String` | 签约模式: STANDARD(电子签约)/SYNC(线下报备) |
| `signatoryMode` | `Integer` | 签署模式: 1=短信签署 2=现场签署 3=线下签署 |
| `agencyCode` | `String` | 旅行社编码 |
| `agencyName` | `String` | 旅行社名称（回显用） |
| `disputeResolution` | `Integer` | 争议解决方式: 1=仲裁 2=诉讼 |
| `supplementaryClause` | `String` | 补充条款 |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/contract/scheme/{schemeId} — 获取合同方案详情

**参数**

  - `{schemeId}` (`Long`) — 路径参数

**响应** `Result<ContractSchemeVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `String` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `contractPlatform` | `String` | 合同平台: 12301/FADADA |
| `contractTemplateCode` | `String` | 合同模板编码（与模板列表的templateCode一致） |
| `templateCode` | `String` | 合同模板编码（别名，与contractTemplateCode相同值，方便前端统一使用templateCode） |
| `contractTemplateName` | `String` | 合同模板名称（回显用） |
| `contractMode` | `String` | 签约模式: STANDARD(电子签约)/SYNC(线下报备) |
| `signatoryMode` | `Integer` | 签署模式: 1=短信签署 2=现场签署 3=线下签署 |
| `agencyCode` | `String` | 旅行社编码 |
| `agencyName` | `String` | 旅行社名称（回显用） |
| `disputeResolution` | `Integer` | 争议解决方式: 1=仲裁 2=诉讼 |
| `supplementaryClause` | `String` | 补充条款 |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/contract/scheme — 创建合同方案

**请求体** `ContractSchemeRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `contractPlatform` | `String` | 合同平台: 12301/FADADA |
| `contractTemplateCode` | `String` | 合同模板编码 |
| `contractMode` | `String` | 签约模式: STANDARD(电子签约)/SYNC(线下报备) |
| `signatoryMode` | `Integer` | 签署模式: 1=短信签署 2=现场签署 3=线下签署 |
| `agencyCode` | `String` | 旅行社编码(可选，不填则根据订单支付商户号自动匹配旅行社) |
| `disputeResolution` | `Integer` | 争议解决方式: 1=仲裁 2=诉讼 |
| `supplementaryClause` | `String` | 补充条款(可选) |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `sortOrder` | `Integer` | 排序(越小越靠前) |

**响应** `Result<ContractSchemeVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `String` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `contractPlatform` | `String` | 合同平台: 12301/FADADA |
| `contractTemplateCode` | `String` | 合同模板编码（与模板列表的templateCode一致） |
| `templateCode` | `String` | 合同模板编码（别名，与contractTemplateCode相同值，方便前端统一使用templateCode） |
| `contractTemplateName` | `String` | 合同模板名称（回显用） |
| `contractMode` | `String` | 签约模式: STANDARD(电子签约)/SYNC(线下报备) |
| `signatoryMode` | `Integer` | 签署模式: 1=短信签署 2=现场签署 3=线下签署 |
| `agencyCode` | `String` | 旅行社编码 |
| `agencyName` | `String` | 旅行社名称（回显用） |
| `disputeResolution` | `Integer` | 争议解决方式: 1=仲裁 2=诉讼 |
| `supplementaryClause` | `String` | 补充条款 |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/contract/scheme/{schemeId} — 更新合同方案

**参数**

  - `{schemeId}` (`Long`) — 路径参数

**请求体** `ContractSchemeRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `contractPlatform` | `String` | 合同平台: 12301/FADADA |
| `contractTemplateCode` | `String` | 合同模板编码 |
| `contractMode` | `String` | 签约模式: STANDARD(电子签约)/SYNC(线下报备) |
| `signatoryMode` | `Integer` | 签署模式: 1=短信签署 2=现场签署 3=线下签署 |
| `agencyCode` | `String` | 旅行社编码(可选，不填则根据订单支付商户号自动匹配旅行社) |
| `disputeResolution` | `Integer` | 争议解决方式: 1=仲裁 2=诉讼 |
| `supplementaryClause` | `String` | 补充条款(可选) |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `sortOrder` | `Integer` | 排序(越小越靠前) |

**响应** `Result<ContractSchemeVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `String` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `contractPlatform` | `String` | 合同平台: 12301/FADADA |
| `contractTemplateCode` | `String` | 合同模板编码（与模板列表的templateCode一致） |
| `templateCode` | `String` | 合同模板编码（别名，与contractTemplateCode相同值，方便前端统一使用templateCode） |
| `contractTemplateName` | `String` | 合同模板名称（回显用） |
| `contractMode` | `String` | 签约模式: STANDARD(电子签约)/SYNC(线下报备) |
| `signatoryMode` | `Integer` | 签署模式: 1=短信签署 2=现场签署 3=线下签署 |
| `agencyCode` | `String` | 旅行社编码 |
| `agencyName` | `String` | 旅行社名称（回显用） |
| `disputeResolution` | `Integer` | 争议解决方式: 1=仲裁 2=诉讼 |
| `supplementaryClause` | `String` | 补充条款 |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/contract/scheme/{schemeId}/toggle-status — 切换方案启用/停用状态

**参数**

  - `{schemeId}` (`Long`) — 路径参数

**响应** `Result<ContractSchemeVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `String` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `contractPlatform` | `String` | 合同平台: 12301/FADADA |
| `contractTemplateCode` | `String` | 合同模板编码（与模板列表的templateCode一致） |
| `templateCode` | `String` | 合同模板编码（别名，与contractTemplateCode相同值，方便前端统一使用templateCode） |
| `contractTemplateName` | `String` | 合同模板名称（回显用） |
| `contractMode` | `String` | 签约模式: STANDARD(电子签约)/SYNC(线下报备) |
| `signatoryMode` | `Integer` | 签署模式: 1=短信签署 2=现场签署 3=线下签署 |
| `agencyCode` | `String` | 旅行社编码 |
| `agencyName` | `String` | 旅行社名称（回显用） |
| `disputeResolution` | `Integer` | 争议解决方式: 1=仲裁 2=诉讼 |
| `supplementaryClause` | `String` | 补充条款 |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `String` | 状态: ACTIVE/INACTIVE |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `DELETE` /admin/contract/scheme/{schemeId} — 删除合同方案

**参数**

  - `{schemeId}` (`Long`) — 路径参数

**响应** `Result<Void>`

### 🆕 新增: ContractCallback

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「【回调接口】合同回调」**

### 📌 `POST` /contract/callback/12301 — 12301合同状态回调

> 接收12301全国旅游监管平台的合同签署状态回调。出行人签署完成后平台推送状态变更到此接口，自动更新本地合同状态

**请求体** `ContractCallbackPayload`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `apiVersion` | `String` | API版本 |
| `data` | `CallbackData` | 回调数据 |
| `sign` | `String` | 签名 |
| `signatoryPhone` | `String` | 签署人手机号 |
| `signatoryIDNumber` | `String` | 签署人证件号码 |
| `state` | `Integer` | 合同状态码 |
| `contractNumber` | `String` | 合同编号 |
| `content` | `String` | 状态描述 |
| `contractType` | `String` | 合同类型 |
| `timestamp` | `Long` | 时间戳（Unix秒） |
| `url` | `CallbackUrl` | 相关URL |
| `signingURL` | `String` | 签署URL |
| `qrCodeURL` | `String` | 二维码URL |
| `fileURL` | `String` | 合同文件URL |

**响应** `ResponseEntity<String>`

### 📌 `POST` /contract/callback/fadada — 法大大合同状态回调

> 接收法大大电子合同平台的签署状态回调。签署完成/撤销/拒签时法大大推送事件到此接口

**响应** `ResponseEntity<String>`

### 🆕 新增: InternalContract

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「【内部接口】合同（Feign调用）」**

### 📌 `GET` /internal/contract/by-order/{orderId} — 按订单查询合同(内部调用)

> **关联字典**：
- contract_status：合同状态（返回字段）

**参数**

  - `{orderId}` (`Long`) — 路径参数

**响应** `Result<List<ContractVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /internal/contract/by-orders — 按订单批量查询合同(内部调用)

> **关联字典**：
- contract_status：合同状态（返回字段）

**响应** `Result<Map<Long, List<ContractVO>>>`

### 📌 `GET` /internal/contract/has-signed/{orderId} — 检查订单是否有已签署合同(内部调用)

> 检查订单是否存在有效签署的合同（SIGNED/REPORTED/UPLOADED状态），用于订单流程中的合同校验

**参数**

  - `{orderId}` (`Long`) — 路径参数

**响应** `Result<Boolean>`

### 📌 `POST` /internal/contract/create — 创建合同（内部调用）

> 内部服务调用创建合同，adminId固定为0表示系统自动创建。返回contractId和status

**请求体** `CreateContractRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `contractType` | `String` | 合同类型: TOUR-旅游合同(默认), INSURANCE-保险单 |
| `platform` | `String` | 合同平台（字典：contract_platform）: 12301-全国旅游监管平台, FADADA-法大大, ESIGN-e签宝, TENCENT_ESS-腾讯电子签。不传则根据模板自动确定 |
| `templateCode` | `String` | 模板编码 |
| `agencyCode` | `String` | 旅行社编号（可选，不传则按商户号匹配，仍无则用默认值） |
| `mchId` | `String` | 微信支付商户号（用于自动匹配旅行社） |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `destination` | `String` | 目的地 |
| `routeName` | `String` | 线路名称 |
| `days` | `Integer` | 行程天数 |
| `nights` | `Integer` | 住宿晚数 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `departureCity` | `String` | 出发城市 |
| `groupId` | `String` | 团号 |
| `signatoryName` | `String` | 签署人姓名 |
| `signatoryPhone` | `String` | 签署人电话 |
| `signatoryIdNumber` | `String` | 签署人证件号码 |
| `signingPlace` | `String` | 签约地点 |
| `adultCost` | `BigDecimal` | 成人费用 |
| `childCost` | `BigDecimal` | 儿童费用 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `supplementaryClause` | `String` | 补充约定内容 |
| `vehicleModel` | `String` | 车型名称(产品快照) |
| `travelers` | `List<TravelerDTO>` | 出行人列表 |
| `name` | `String` | 姓名 |
| `gender` | `String` | 性别: male/female |
| `age` | `Integer` | 年龄 |
| `idCardNo` | `String` | 证件号码 |
| `phone` | `String` | 手机号 |
| `health` | `String` | 健康信息 |

**响应** `Result<Map<String, Object>>`

### 📌 `POST` /internal/contract/report — 报备合同（内部调用）

> 内部服务调用报备合同（同步模式），adminId固定为0表示系统自动创建。返回contractId和status

**请求体** `ReportContractRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `contractType` | `String` | 合同类型: TOUR-旅游合同(默认), INSURANCE-保险单 |
| `platform` | `String` | 合同平台（字典：contract_platform）: 12301-全国旅游监管平台, FADADA-法大大, ESIGN-e签宝, TENCENT_ESS-腾讯电子签 |
| `templateCode` | `String` | 模板编码 |
| `agencyCode` | `String` | 旅行社编号（可选，不传则按商户号匹配，仍无则用默认值） |
| `mchId` | `String` | 微信支付商户号（用于自动匹配旅行社） |
| `transactorName` | `String` | 经办人姓名 |
| `transactorPhone` | `String` | 经办人电话 |
| `destination` | `String` | 目的地 |
| `routeName` | `String` | 线路名称 |
| `days` | `Integer` | 行程天数 |
| `nights` | `Integer` | 住宿晚数 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `departureCity` | `String` | 出发城市 |
| `groupId` | `String` | 团号 |
| `signatoryName` | `String` | 签署人姓名 |
| `signatoryPhone` | `String` | 签署人电话 |
| `signatoryIdNumber` | `String` | 签署人证件号码 |
| `signingPlace` | `String` | 签约地点 |
| `adultCost` | `BigDecimal` | 成人费用 |
| `childCost` | `BigDecimal` | 儿童费用 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `supplementaryClause` | `String` | 补充约定内容 |

**响应** `Result<Map<String, Object>>`

### 📌 `GET` /internal/contract/scheme/{schemeId}/config — 获取合同方案配置(内部调用)

> 供 order-service 自动签约时获取方案的完整合同配置

**参数**

  - `{schemeId}` (`Long`) — 路径参数

**响应** `Result<Map<String, Object>>`

### 📌 `POST` /internal/contract/invalidate/{orderId} — 按订单作废所有有效合同(级联调用)

> 订单取消或退款时级联作废该订单下所有有效合同，reason参数记录作废原因

**参数**

  - `{orderId}` (`Long`) — 路径参数
  - `reason` (`String`) — 查询参数

**响应** `Result<Void>`

### 🆕 新增: InternalMpContract

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「【内部接口】小程序合同（Feign调用）」**

### 📌 `GET` /internal/mp/contract/list — 用户合同列表

> **关联字典**：
- contract_status：合同状态（列表筛选+显示）

**参数**

  - `userId` (`Long`) — 查询参数
  - `status` (`String`) — 查询参数
  - `page` (`int`) — 查询参数
  - `pageSize` (`int`) — 查询参数

**响应** `Result<PageResult<ContractVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /internal/mp/contract/{id} — 用户合同详情

> **关联字典**：
- contract_status：合同状态（显示）

**参数**

  - `{contractId}` (`Long`) — 路径参数
  - `userId` (`Long`) — 查询参数

**响应** `Result<ContractDetailVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `supplementaryClause` | `String` | 补充约定内容 |
| `travelers` | `List<TravelerVO>` | 出行人列表 |
| `statusLogs` | `List<StatusLogVO>` | 状态变更日志 |
| `travelerId` | `Long` | 出行人ID |
| `name` | `String` | 姓名 |
| `idCardType` | `String` | 证件类型 |
| `idCardNo` | `String` | 证件号码 |
| `phone` | `String` | 手机号 |
| `isSigner` | `Boolean` | 是否签署人 |
| `logId` | `Long` | 日志ID |
| `oldStatus` | `String` | 旧状态 |
| `newStatus` | `String` | 新状态 |
| `source` | `String` | 变更来源 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /internal/mp/contract/by-order/{orderId} — 按订单查合同（返回最新有效合同）

> **关联字典**：
- contract_status：合同状态（显示）

**参数**

  - `{orderId}` (`Long`) — 路径参数
  - `userId` (`Long`) — 查询参数

**响应** `Result<ContractVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `contractId` | `Long` | 合同ID |
| `orderId` | `Long` | 订单ID |
| `templateCode` | `String` | 模板编码 |
| `templateName` | `String` | 模板名称 |
| `contractNumber` | `String` | 合同编号 |
| `platform` | `String` | 签约平台 |
| `contractType` | `String` | 合同类型: TOUR-旅游合同, INSURANCE-保险单 |
| `mode` | `String` | 签约模式: STANDARD/SYNC |
| `status` | `String` | 合同状态 |
| `statusLabel` | `String` | 合同状态标签 |
| `signUrl` | `String` | 签署URL |
| `qrCodeUrl` | `String` | 二维码URL |
| `fileUrl` | `String` | 合同文件URL |
| `agencyCode` | `String` | 旅行社编号 |
| `travelAgencyName` | `String` | 旅行社名称 |
| `destination` | `String` | 目的地 |
| `departureDate` | `LocalDate` | 出发日期 |
| `returnDate` | `LocalDate` | 返回日期 |
| `totalAmount` | `BigDecimal` | 合同总金额 |
| `touristCount` | `Integer` | 出行人数 |
| `contactName` | `String` | 联系人姓名 |
| `contactPhone` | `String` | 联系人电话 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /internal/mp/contract/by-order/{orderId}/all — 按订单查所有有效合同（TOUR+INSURANCE各一条）

> **关联字典**：
- contract_status：合同状态（显示）

**参数**

  - `{orderId}` (`Long`) — 路径参数
  - `userId` (`Long`) — 查询参数

### 📌 `POST` /internal/mp/contract/{contractId}/resend-sms — 重新发送合同签署短信

> 内部服务间调用。小程序端用户请求重发签署短信，用于签署链接过期或短信未收到的场景。仅SIGNING状态的合同可操作。

**关联字典**：
- contract_status：合同状态（仅SIGNING可操作）

**参数**

  - `{contractId}` (`Long`) — 路径参数

**响应** `Result<Boolean>`

### 🆕 新增: AdminInsurance

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「保险管理」**

### 📌 `GET` /admin/insurance/products — 保险产品列表

> 分页查询已同步的保险产品，支持按是否境外筛选。产品数据来源于保游网同步。

**权限**：需管理员登录。

**参数**

  - `page` (`Integer`) — 查询参数：页码
  - `pageSize` (`Integer`) — 查询参数：每页条数
  - `isOverseas` (`Boolean`) — 查询参数：是否境外

**响应** `Result<PageResult<InsuranceProductVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `productId` | `Long` | 保险产品ID |
| `extProductGuid` | `String` | 保游网产品GUID |
| `productName` | `String` | 产品名称 |
| `companyName` | `String` | 保险公司名称 |
| `productType` | `String` | 产品类型 |
| `isOverseas` | `Boolean` | 是否境外产品 |
| `minDays` | `Integer` | 最短保障天数 |
| `maxDays` | `Integer` | 最长保障天数 |
| `minAge` | `Integer` | 最小投保年龄 |
| `maxAge` | `Integer` | 最大投保年龄 |
| `status` | `String` | 产品状态: ACTIVE-已上架, INACTIVE-已下架 |
| `createTime` | `LocalDateTime` | 同步时间 |

### 📌 `GET` /admin/insurance/products/{id} — 保险产品详情

> 返回保险产品完整信息，包含产品名称、保险公司、保障范围、适用地区等。

**权限**：需管理员登录。

**参数**

  - `{productId}` (`Long`) — 路径参数：保险产品ID

**响应** `Result<InsuranceProductVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `productId` | `Long` | 保险产品ID |
| `extProductGuid` | `String` | 保游网产品GUID |
| `productName` | `String` | 产品名称 |
| `companyName` | `String` | 保险公司名称 |
| `productType` | `String` | 产品类型 |
| `isOverseas` | `Boolean` | 是否境外产品 |
| `minDays` | `Integer` | 最短保障天数 |
| `maxDays` | `Integer` | 最长保障天数 |
| `minAge` | `Integer` | 最小投保年龄 |
| `maxAge` | `Integer` | 最大投保年龄 |
| `status` | `String` | 产品状态: ACTIVE-已上架, INACTIVE-已下架 |
| `createTime` | `LocalDateTime` | 同步时间 |

### 📌 `GET` /admin/insurance/products/{id}/plans — 保险产品计划及费率

> 返回指定保险产品的所有投保计划及对应费率表，包含不同天数区间的保费价格。投保下单前需选择具体计划。

**权限**：需管理员登录。

**参数**

  - `{productId}` (`Long`) — 路径参数：保险产品ID

**响应** `Result<List<InsurancePlanVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `planId` | `Long` | 计划ID |
| `productId` | `Long` | 所属产品ID |
| `extPlanGuid` | `String` | 保游网计划GUID |
| `planName` | `String` | 计划名称 |
| `securityList` | `String` | 保障内容(HTML) |
| `rates` | `List<RateVO>` | 费率列表 |
| `rateId` | `Long` | 费率ID |
| `extRateCode` | `String` | 保游网费率编码 |
| `ageRange` | `String` | 适用年龄范围 |
| `dayRange` | `String` | 适用天数范围(如 1, 2, 4-7) |
| `dayType` | `String` | 天数类型: 10-按天, 20-按月, 30-按年 |
| `premium` | `BigDecimal` | 单人保费(元) |

### 📌 `POST` /admin/insurance/sync-products — 从保游网同步产品数据

> 手动触发从保游网API拉取最新保险产品数据（含计划和费率），同步到本地数据库。返回同步的产品数量。

**权限**：需管理员登录。

**响应** `Result<Integer>`

### 📌 `GET` /admin/insurance/entities — 投保公司主体列表

> 返回系统配置的投保公司主体列表（来自Nacos配置），投保下单时选择以哪个公司主体投保。每个主体包含编码、公司名称和商户ID。

**权限**：需管理员登录。

**响应** `Result<List<Map<String, String>>>`

### 📌 `POST` /admin/insurance/purchase-by-scheme — 按方案自动投保(schemeId+orderId)

> 根据保险方案自动为订单所有出行人投保。系统自动从订单获取出行人信息和行程日期，按方案各段配置逐段投保。

**请求体** `AutoPurchaseRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 旅行订单ID |
| `schemeId` | `Long` | 保险方案ID |

**响应** `Result<AutoPurchaseResultVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `success` | `boolean` | 是否全部成功 |
| `purchasedCount` | `int` | 成功投保段数 |
| `failedCount` | `int` | 失败段数 |
| `failureReason` | `String` | 失败原因（部分失败或全部失败时返回第一个错误） |

### 📌 `POST` /admin/insurance/purchase — 投保下单(每人独立保单)

> **关联字典**：
- gender：性别（被保人信息）
- id_card_type：证件类型（被保人信息）

**请求体** `PurchaseInsuranceRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 关联旅行订单ID(可选) |
| `planId` | `Long` | 保险计划ID |
| `startDate` | `LocalDate` | 保障开始日期(传orderId时自动从订单获取) |
| `endDate` | `LocalDate` | 保障结束日期(传orderId时自动从订单获取) |
| `insuredPersons` | `List<InsuredPersonDTO>` | 被保人列表(传orderId时自动从订单出行人获取) |
| `entityCode` | `String` | 投保公司主体编码(不填则使用默认主体) |
| `remark` | `String` | 备注 |
| `name` | `String` | 姓名 |
| `idCardNo` | `String` | 证件号码 |
| `birthday` | `LocalDate` | 出生日期 |
| `gender` | `String` | 性别: MALE-男, FEMALE-女 |
| `phone` | `String` | 手机号 |

**响应** `Result<List<InsuranceOrderDetailVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `insuredPersons` | `List<InsuredPersonVO>` | 被保人列表 |
| `insuredId` | `Long` | 被保人ID |
| `name` | `String` | 姓名 |
| `idCardType` | `String` | 证件类型: ID_CARD-身份证, PASSPORT-护照, OTHER-其他 |
| `idCardNo` | `String` | 证件号码 |
| `birthday` | `LocalDate` | 出生日期 |
| `gender` | `String` | 性别: MALE-男, FEMALE-女 |
| `phone` | `String` | 手机号 |
| `isBeneficiary` | `Boolean` | 是否为受益人 |

### 📌 `POST` /admin/insurance/cancel/{id} — 退保

> 对单个保险订单发起退保，调用保游网退保API。退保成功后保险状态变为CANCELLED。

**权限**：需管理员登录。
**注意**：已生效的保单退保可能产生手续费。

**关联字典**：
- insurance_status：保险状态（状态流转）

**参数**

  - `{insuranceOrderId}` (`Long`) — 路径参数：保险订单ID

**响应** `Result<InsuranceOrderVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `insuranceOrderId` | `Long` | 保险订单ID |
| `orderId` | `Long` | 关联旅行订单ID |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `extOrderNo` | `String` | 保游网订单号 |
| `extPolicyNo` | `String` | 保单号 |
| `totalPremium` | `BigDecimal` | 总保费(元) |
| `insuredCount` | `Integer` | 被保人数量 |
| `policyHolderName` | `String` | 投保人姓名(公司名称) |
| `entityCode` | `String` | 投保公司主体编码 |
| `startDate` | `LocalDate` | 保障开始日期 |
| `endDate` | `LocalDate` | 保障结束日期 |
| `status` | `String` | 订单状态: PENDING-待出单, INSURED-已承保, CANCELLED-已退保, FAILED-投保失败 |
| `policyPdfUrl` | `String` | 保单PDF的OSS链接（.pdf结尾，可直接访问） |
| `statusLabel` | `String` | 状态中文标签 |
| `remark` | `String` | 备注 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/insurance/orders — 保险订单列表

> **关联字典**：
- insurance_status：保险状态（列表筛选+显示）

**响应** `Result<PageResult<InsuranceOrderVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `insuranceOrderId` | `Long` | 保险订单ID |
| `orderId` | `Long` | 关联旅行订单ID |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `extOrderNo` | `String` | 保游网订单号 |
| `extPolicyNo` | `String` | 保单号 |
| `totalPremium` | `BigDecimal` | 总保费(元) |
| `insuredCount` | `Integer` | 被保人数量 |
| `policyHolderName` | `String` | 投保人姓名(公司名称) |
| `entityCode` | `String` | 投保公司主体编码 |
| `startDate` | `LocalDate` | 保障开始日期 |
| `endDate` | `LocalDate` | 保障结束日期 |
| `status` | `String` | 订单状态: PENDING-待出单, INSURED-已承保, CANCELLED-已退保, FAILED-投保失败 |
| `policyPdfUrl` | `String` | 保单PDF的OSS链接（.pdf结尾，可直接访问） |
| `statusLabel` | `String` | 状态中文标签 |
| `remark` | `String` | 备注 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/insurance/orders/{id} — 保险订单详情(含被保人)

> **关联字典**：
- insurance_status：保险状态（显示）
- gender：性别（被保人信息显示）
- id_card_type：证件类型（被保人信息显示）

**参数**

  - `{insuranceOrderId}` (`Long`) — 路径参数：保险订单ID

**响应** `Result<InsuranceOrderDetailVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `insuredPersons` | `List<InsuredPersonVO>` | 被保人列表 |
| `insuredId` | `Long` | 被保人ID |
| `name` | `String` | 姓名 |
| `idCardType` | `String` | 证件类型: ID_CARD-身份证, PASSPORT-护照, OTHER-其他 |
| `idCardNo` | `String` | 证件号码 |
| `birthday` | `LocalDate` | 出生日期 |
| `gender` | `String` | 性别: MALE-男, FEMALE-女 |
| `phone` | `String` | 手机号 |
| `isBeneficiary` | `Boolean` | 是否为受益人 |

### 📌 `GET` /admin/insurance/orders/by-order/{orderId} — 按旅行订单查询保险单

> 根据旅行订单ID查询关联的所有保险订单列表。在订单详情页展示保险购买情况。

**权限**：需管理员登录。

**关联字典**：
- insurance_status：保险状态（列表显示）

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID

**响应** `Result<List<InsuranceOrderVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `insuranceOrderId` | `Long` | 保险订单ID |
| `orderId` | `Long` | 关联旅行订单ID |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `extOrderNo` | `String` | 保游网订单号 |
| `extPolicyNo` | `String` | 保单号 |
| `totalPremium` | `BigDecimal` | 总保费(元) |
| `insuredCount` | `Integer` | 被保人数量 |
| `policyHolderName` | `String` | 投保人姓名(公司名称) |
| `entityCode` | `String` | 投保公司主体编码 |
| `startDate` | `LocalDate` | 保障开始日期 |
| `endDate` | `LocalDate` | 保障结束日期 |
| `status` | `String` | 订单状态: PENDING-待出单, INSURED-已承保, CANCELLED-已退保, FAILED-投保失败 |
| `policyPdfUrl` | `String` | 保单PDF的OSS链接（.pdf结尾，可直接访问） |
| `statusLabel` | `String` | 状态中文标签 |
| `remark` | `String` | 备注 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/insurance/coverage/{orderId} — 查询订单保险保障(含被保人详情)

> 返回订单维度的保险保障汇总信息，包含覆盖人数、保障期间、每位被保人的保单明细。用于订单详情页的保险保障展示。

**权限**：需管理员登录。

**关联字典**：
- insurance_status：保险状态（显示）
- gender：性别（被保人信息显示）
- id_card_type：证件类型（被保人信息显示）

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID

**响应** `Result<InsuranceCoverageVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 旅行订单ID |
| `orderCount` | `Integer` | 保险单数量 |
| `insuranceOrders` | `List<InsuranceOrderDetailVO>` | 保险订单详情列表(含被保人) |

### 📌 `POST` /admin/insurance/trial-price — 保费试算(本地费率)

> 根据保险计划、投保天数和人数，使用本地同步的费率表试算保费。不调用保游网API，用于投保前的费用预估。

**权限**：需管理员登录。

**请求体** `TrialPriceRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `planId` | `Long` | 保险计划ID |
| `startDate` | `LocalDate` | 保障开始日期 |
| `endDate` | `LocalDate` | 保障结束日期 |
| `insuredCount` | `Integer` | 被保人数量 |

**响应** `Result<Map<String, Object>>`

### 📌 `GET` /admin/insurance/balance — 查询保游网账户余额

> 查询保游网平台的账户余额，用于管理端展示当前可用投保额度。查询失败时返回null（非关键信息，不影响业务）。

**权限**：需管理员登录。

**响应** `Result<JsonNode>`

### 📌 `GET` /admin/insurance/policy/{id}/download — 下载保单PDF(Base64)

> 从保游网下载指定保险订单的电子保单PDF，以Base64编码返回。前端可解码后展示或提供下载。

**权限**：需管理员登录。

**参数**

  - `{insuranceOrderId}` (`Long`) — 路径参数：保险订单ID

**响应** `Result<String>`

### 📌 `GET` /admin/insurance/recharge-url — 获取保游网充值链接(已废弃)

> **已废弃**：保游网充值网站已关闭。请改用 POST /admin/insurance/recharge 在线充值接口。

**权限**：需管理员登录。

**响应** `Result<String>`

### 📌 `POST` /admin/insurance/recharge — 在线充值(调用保游网支付API)

> 调用保游网在线充值API，生成充值支付链接。支持选择支付方式（支付宝/微信），充值完成后账户余额自动更新。

**权限**：需管理员登录。

**请求体** `RechargeRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `money` | `BigDecimal` | 充值金额（元） |
| `payType` | `Integer` | 支付方式：11=支付宝扫码, 33=微信扫码 |
| `backUrl` | `String` | 同步回调地址（支付宝用） |

**响应** `Result<Map<String, Object>>`

### 📌 `POST` /admin/insurance/upload-missing-pdfs — 补传旧保单PDF到OSS

> 将所有已承保但未上传PDF的保单，异步下载PDF并上传到OSS。用于历史数据迁移。

**响应** `Result<Integer>`

### 📌 `POST` /admin/insurance/share-policy — 分享保单(合并某出行人所有有效保单PDF,上传OSS返回链接)

> 合并指定出行人的所有有效保单PDF为一个文件，上传至OSS后返回公开访问链接。用于管理端分享保单给出行人。

**权限**：需管理员登录。

**请求体** `SharePolicyRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 旅游订单ID |
| `insuredName` | `String` | 被保人姓名 |
| `insuredIdCardNo` | `String` | 被保人证件号码 |

**响应** `Result<PolicyShareVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `pdfBase64` | `String` | 合并后的PDF（Base64编码） |
| `personName` | `String` | 被保人姓名 |
| `policyCount` | `int` | 包含的保单数量 |
| `failedCount` | `int` | 下载失败的保单数量（已跳过） |

### 📌 `POST` /admin/insurance/order/{orderId}/selective-purchase — 选择部分出行人投保

> 自动投保失败后，管理员可选择部分出行人手动在线投保（如排除不满1岁婴儿）。

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID

**响应** `Result<AutoPurchaseResultVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `success` | `boolean` | 是否全部成功 |
| `purchasedCount` | `int` | 成功投保段数 |
| `failedCount` | `int` | 失败段数 |
| `failureReason` | `String` | 失败原因（部分失败或全部失败时返回第一个错误） |

### 📌 `POST` /admin/insurance/order/{orderId}/traveler-note — 添加出行人保险备注

> 为不能在线投保的出行人添加备注（如不满1岁婴儿标记为线下投保）。

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID

### 📌 `DELETE` /admin/insurance/order/{orderId}/traveler-note/{noteId} — 删除出行人保险备注

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID
  - `{noteId}` (`Long`) — 路径参数：备注ID

**响应** `Result<Void>`

### 📌 `GET` /admin/insurance/order/{orderId}/traveler-coverage — 查询出行人保险覆盖状态

> 返回订单每个出行人的保险状态：

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID

### 🆕 新增: AdminInsuranceScheme

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「保险方案模板」**

### 📌 `GET` /admin/insurance/scheme/list — 活跃方案列表(下拉选择用)

> 返回所有状态为启用的保险方案模板，用于投保下单时的方案下拉选择。

**权限**：需管理员登录。

**响应** `Result<List<InsuranceSchemeVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `isOverseas` | `Boolean` | 是否境外 |
| `sortOrder` | `Integer` | 排序序号 |
| `totalDays` | `Integer` | 适用行程天数 |
| `status` | `String` | 状态: ACTIVE-启用, INACTIVE-停用 |
| `adminId` | `Long` | 创建人ID |
| `createTime` | `LocalDateTime` | 创建时间 |
| `segmentCount` | `Integer` | 段数量 |
| `segments` | `List<SegmentVO>` | 方案段列表 |
| `segmentId` | `Long` | 段ID |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 相对起始天 |
| `dayOffsetEnd` | `Integer` | 相对结束天(-1=最后一天) |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `sortOrder` | `Integer` | 段排序序号 |

### 📌 `GET` /admin/insurance/scheme/list-all — 全部方案列表(管理用)

> 返回所有保险方案模板（含启用和停用），用于方案管理页面展示和编辑。

**权限**：需管理员登录。

**响应** `Result<List<InsuranceSchemeVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `isOverseas` | `Boolean` | 是否境外 |
| `sortOrder` | `Integer` | 排序序号 |
| `totalDays` | `Integer` | 适用行程天数 |
| `status` | `String` | 状态: ACTIVE-启用, INACTIVE-停用 |
| `adminId` | `Long` | 创建人ID |
| `createTime` | `LocalDateTime` | 创建时间 |
| `segmentCount` | `Integer` | 段数量 |
| `segments` | `List<SegmentVO>` | 方案段列表 |
| `segmentId` | `Long` | 段ID |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 相对起始天 |
| `dayOffsetEnd` | `Integer` | 相对结束天(-1=最后一天) |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `sortOrder` | `Integer` | 段排序序号 |

### 📌 `GET` /admin/insurance/scheme/{id} — 方案详情

> 返回单个保险方案模板的完整信息，包含方案名称、保险产品关联、天数规则、费率配置等。

**权限**：需管理员登录。

**参数**

  - `{schemeId}` (`Long`) — 路径参数：方案ID

**响应** `Result<InsuranceSchemeVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `isOverseas` | `Boolean` | 是否境外 |
| `sortOrder` | `Integer` | 排序序号 |
| `totalDays` | `Integer` | 适用行程天数 |
| `status` | `String` | 状态: ACTIVE-启用, INACTIVE-停用 |
| `adminId` | `Long` | 创建人ID |
| `createTime` | `LocalDateTime` | 创建时间 |
| `segmentCount` | `Integer` | 段数量 |
| `segments` | `List<SegmentVO>` | 方案段列表 |
| `segmentId` | `Long` | 段ID |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 相对起始天 |
| `dayOffsetEnd` | `Integer` | 相对结束天(-1=最后一天) |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `sortOrder` | `Integer` | 段排序序号 |

### 📌 `POST` /admin/insurance/scheme — 创建方案

> 创建保险方案模板，配置关联保险产品、投保天数规则和费率。创建后默认启用。

**权限**：需管理员登录。

**请求体** `InsuranceSchemeRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `isOverseas` | `Boolean` | 是否境外: false=境内, true=境外 |
| `sortOrder` | `Integer` | 排序序号（越小越靠前） |
| `segments` | `List<SegmentDTO>` | 保险段列表 |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 相对起始天(1-based, 1=出发日) |
| `dayOffsetEnd` | `Integer` | 相对结束天(1-based, -1=行程最后一天) |
| `productId` | `Long` | 保险产品ID |
| `planId` | `Long` | 保险计划ID |
| `sortOrder` | `Integer` | 段排序序号 |

**响应** `Result<InsuranceSchemeVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `isOverseas` | `Boolean` | 是否境外 |
| `sortOrder` | `Integer` | 排序序号 |
| `totalDays` | `Integer` | 适用行程天数 |
| `status` | `String` | 状态: ACTIVE-启用, INACTIVE-停用 |
| `adminId` | `Long` | 创建人ID |
| `createTime` | `LocalDateTime` | 创建时间 |
| `segmentCount` | `Integer` | 段数量 |
| `segments` | `List<SegmentVO>` | 方案段列表 |
| `segmentId` | `Long` | 段ID |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 相对起始天 |
| `dayOffsetEnd` | `Integer` | 相对结束天(-1=最后一天) |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `sortOrder` | `Integer` | 段排序序号 |

### 📌 `PUT` /admin/insurance/scheme/{id} — 更新方案

> 更新保险方案模板的配置信息，包括方案名称、关联产品、天数规则、费率等。

**权限**：需管理员登录。

**参数**

  - `{schemeId}` (`Long`) — 路径参数：方案ID

**请求体** `InsuranceSchemeRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `isOverseas` | `Boolean` | 是否境外: false=境内, true=境外 |
| `sortOrder` | `Integer` | 排序序号（越小越靠前） |
| `segments` | `List<SegmentDTO>` | 保险段列表 |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 相对起始天(1-based, 1=出发日) |
| `dayOffsetEnd` | `Integer` | 相对结束天(1-based, -1=行程最后一天) |
| `productId` | `Long` | 保险产品ID |
| `planId` | `Long` | 保险计划ID |
| `sortOrder` | `Integer` | 段排序序号 |

**响应** `Result<InsuranceSchemeVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `isOverseas` | `Boolean` | 是否境外 |
| `sortOrder` | `Integer` | 排序序号 |
| `totalDays` | `Integer` | 适用行程天数 |
| `status` | `String` | 状态: ACTIVE-启用, INACTIVE-停用 |
| `adminId` | `Long` | 创建人ID |
| `createTime` | `LocalDateTime` | 创建时间 |
| `segmentCount` | `Integer` | 段数量 |
| `segments` | `List<SegmentVO>` | 方案段列表 |
| `segmentId` | `Long` | 段ID |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 相对起始天 |
| `dayOffsetEnd` | `Integer` | 相对结束天(-1=最后一天) |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `sortOrder` | `Integer` | 段排序序号 |

### 📌 `PUT` /admin/insurance/scheme/{id}/toggle-status — 切换方案状态(启用/停用)

> 切换保险方案模板的启用/停用状态。停用后不会出现在投保下单的方案选择列表中。

**权限**：需管理员登录。

**关联字典**：
- common_status：通用状态（ACTIVE=启用/INACTIVE=停用）

**参数**

  - `{schemeId}` (`Long`) — 路径参数：方案ID

**响应** `Result<InsuranceSchemeVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 方案ID |
| `name` | `String` | 方案名称 |
| `description` | `String` | 方案描述 |
| `isOverseas` | `Boolean` | 是否境外 |
| `sortOrder` | `Integer` | 排序序号 |
| `totalDays` | `Integer` | 适用行程天数 |
| `status` | `String` | 状态: ACTIVE-启用, INACTIVE-停用 |
| `adminId` | `Long` | 创建人ID |
| `createTime` | `LocalDateTime` | 创建时间 |
| `segmentCount` | `Integer` | 段数量 |
| `segments` | `List<SegmentVO>` | 方案段列表 |
| `segmentId` | `Long` | 段ID |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 相对起始天 |
| `dayOffsetEnd` | `Integer` | 相对结束天(-1=最后一天) |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `sortOrder` | `Integer` | 段排序序号 |

### 📌 `DELETE` /admin/insurance/scheme/{id} — 删除方案(软删除)

> 软删除保险方案模板。已使用该方案创建的保险订单不受影响。

**权限**：需管理员登录。

**参数**

  - `{schemeId}` (`Long`) — 路径参数：方案ID

**响应** `Result<Void>`

### 📌 `POST` /admin/insurance/scheme/preview-apply — 预览应用方案(解析日期+估算保费)

> 根据方案模板和行程日期预览投保效果：解析实际投保起止日期、计算每人保费和总保费。用于投保前确认费用。

**权限**：需管理员登录。

**请求体** `ApplySchemeRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 方案ID |
| `orderId` | `Long` | 旅行订单ID（用于获取出发/返回日期和出行人数） |
| `departureDate` | `LocalDate` | 出发日期（可选，不传则从订单获取） |
| `returnDate` | `LocalDate` | 返回日期（可选，不传则从订单获取） |
| `insuredCount` | `Integer` | 被保人数量（可选，不传则从订单获取出行人数） |

**响应** `Result<ApplySchemePreviewVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 方案ID |
| `schemeName` | `String` | 方案名称 |
| `departureDate` | `LocalDate` | 行程出发日期 |
| `returnDate` | `LocalDate` | 行程返回日期 |
| `tripDays` | `Integer` | 行程天数 |
| `insuredCount` | `Integer` | 被保人数量 |
| `totalEstimatedPremium` | `BigDecimal` | 预估总保费(所有段合计) |
| `segments` | `List<ResolvedSegment>` | 解析后的保险段列表 |
| `warnings` | `List<String>` | 警告信息（如日期间隙、重叠、超出行程范围等） |
| `segmentName` | `String` | 段名称 |
| `dayOffsetStart` | `Integer` | 原始起始天偏移 |
| `dayOffsetEnd` | `Integer` | 原始结束天偏移 |
| `resolvedStartDate` | `LocalDate` | 解析后的实际开始日期 |
| `resolvedEndDate` | `LocalDate` | 解析后的实际结束日期 |
| `coverageDays` | `Integer` | 覆盖天数 |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `unitPremium` | `BigDecimal` | 单人保费 |
| `estimatedPremium` | `BigDecimal` | 该段预估总保费(单人保费 x 人数) |
| `skipped` | `Boolean` | 是否被跳过(超出行程范围) |
| `skipReason` | `String` | 跳过原因 |

### 🆕 新增: InternalInsurance

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「【内部接口】保险（Feign调用）」**

### 📌 `GET` /internal/insurance/by-order/{orderId} — 按旅行订单查询保险单(内部调用)

> 内部服务间调用。根据旅行订单ID查询关联的所有保险订单，返回保险状态、保费、保障期间等信息。

**关联字典**：
- insurance_status：保险状态（返回字段）

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID

**响应** `Result<List<InsuranceOrderVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `insuranceOrderId` | `Long` | 保险订单ID |
| `orderId` | `Long` | 关联旅行订单ID |
| `productId` | `Long` | 保险产品ID |
| `productName` | `String` | 保险产品名称 |
| `planId` | `Long` | 保险计划ID |
| `planName` | `String` | 保险计划名称 |
| `extOrderNo` | `String` | 保游网订单号 |
| `extPolicyNo` | `String` | 保单号 |
| `totalPremium` | `BigDecimal` | 总保费(元) |
| `insuredCount` | `Integer` | 被保人数量 |
| `policyHolderName` | `String` | 投保人姓名(公司名称) |
| `entityCode` | `String` | 投保公司主体编码 |
| `startDate` | `LocalDate` | 保障开始日期 |
| `endDate` | `LocalDate` | 保障结束日期 |
| `status` | `String` | 订单状态: PENDING-待出单, INSURED-已承保, CANCELLED-已退保, FAILED-投保失败 |
| `policyPdfUrl` | `String` | 保单PDF的OSS链接（.pdf结尾，可直接访问） |
| `statusLabel` | `String` | 状态中文标签 |
| `remark` | `String` | 备注 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /internal/insurance/by-orders — 按订单批量查询保险单(内部调用)

> 内部服务间调用。批量查询多个旅行订单的保险订单，返回Map结构（key=订单ID，value=保险单列表），用于订单列表页展示保险状态。

**响应** `Result<Map<Long, List<InsuranceOrderVO>>>`

### 📌 `GET` /internal/insurance/coverage/{orderId} — 查询订单保险保障(含被保人详情,内部调用)

> 内部服务间调用。返回订单维度的保险保障汇总信息，包含每份保单的被保人明细。用于小程序端按出行人展示保险信息。

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID

**响应** `Result<InsuranceCoverageVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 旅行订单ID |
| `orderCount` | `Integer` | 保险单数量 |
| `insuranceOrders` | `List<InsuranceOrderDetailVO>` | 保险订单详情列表(含被保人) |

### 📌 `GET` /internal/insurance/coverage-complete/{orderId} — 检查保险是否全覆盖(内部调用)

> 内部服务间调用。根据出行人数和行程天数计算所需的人日数，与已投保的有效保单覆盖人日数对比，判断保险是否已全覆盖。

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID
  - `travelerCount` (`int`) — 查询参数：出行人数
  - `tripDays` (`int`) — 查询参数：行程天数

**响应** `Result<Boolean>`

### 📌 `GET` /internal/insurance/fully-covered/{orderId} — 检查保险是否全覆盖-含线下备注(内部调用)

> 考虑在线保单+线下投保备注，判断是否所有出行人都有保险覆盖

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID
  - `travelerCount` (`int`) — 查询参数：出行人数

**响应** `Result<Boolean>`

### 📌 `POST` /internal/insurance/invalidate/{orderId} — 按订单批量退保(级联失效调用)

> 内部服务间调用。旅行订单取消或退款时级联调用，将该订单下所有有效保险单批量退保（调用保游网退保API），记录退保原因。

**参数**

  - `{orderId}` (`Long`) — 路径参数：旅行订单ID
  - `reason` (`String`) — 查询参数：退保原因

**响应** `Result<Void>`

### 📌 `GET` /internal/insurance/policy/{id}/download — 下载单张保单PDF(内部调用)

> 内部服务间调用。从保游网下载指定保险订单的电子保单PDF，以Base64编码返回。

**参数**

  - `{insuranceOrderId}` (`Long`) — 路径参数：保险订单ID

**响应** `Result<String>`

### 📌 `POST` /internal/insurance/upload-missing-pdfs — 补传旧保单PDF到OSS(内部调用)

**响应** `Result<Integer>`

### 📌 `POST` /internal/insurance/share-policy — 分享保单PDF(内部调用,返回base64)

> 内部服务间调用。合并指定出行人的所有有效保单PDF为一个文件，上传至OSS后返回下载链接和Base64内容，用于小程序端分享保单。

**请求体** `SharePolicyRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 旅游订单ID |
| `insuredName` | `String` | 被保人姓名 |
| `insuredIdCardNo` | `String` | 被保人证件号码 |

**响应** `Result<PolicyShareVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `pdfBase64` | `String` | 合并后的PDF（Base64编码） |
| `personName` | `String` | 被保人姓名 |
| `policyCount` | `int` | 包含的保单数量 |
| `failedCount` | `int` | 下载失败的保单数量（已跳过） |

### 📌 `GET` /internal/insurance/share-policy-by-order/{orderId} — 按订单获取所有保单PDF(内部调用,合并所有出行人)

> 内部服务间调用。将指定订单下所有出行人的有效保单PDF合并为一个文件，上传至OSS后返回下载链接，用于订单维度的保单查看。

**参数**

  - `{orderId}` (`Long`) — 路径参数

**响应** `Result<PolicyShareVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `pdfBase64` | `String` | 合并后的PDF（Base64编码） |
| `personName` | `String` | 被保人姓名 |
| `policyCount` | `int` | 包含的保单数量 |
| `failedCount` | `int` | 下载失败的保单数量（已跳过） |

### 📌 `POST` /internal/insurance/auto-purchase — 按方案自动投保(内部调用)

> 内部服务间调用。根据保险方案自动为订单所有出行人投保：

**响应** `Result<AutoPurchaseResultVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `success` | `boolean` | 是否全部成功 |
| `purchasedCount` | `int` | 成功投保段数 |
| `failedCount` | `int` | 失败段数 |
| `failureReason` | `String` | 失败原因（部分失败或全部失败时返回第一个错误） |

### 📌 `GET` /internal/insurance/scheme/{schemeId}/premium — 获取保险方案信息(内部调用)

> 内部服务间调用。返回方案的适用天数和人均保费，用于产品保存时校验天数匹配并自动填充保险费。

**参数**

  - `{schemeId}` (`Long`) — 路径参数：方案ID
  - `tripDays` (`int`) — 查询参数：行程天数

**响应** `Result<Map<String, Object>>`

### 📌 `POST` /internal/insurance/sync-products — 触发保险产品同步(内部调用/定时任务)

> 内部服务间调用。从保游网API拉取最新保险产品数据（含计划和费率），同步到本地数据库。返回同步的产品数量。

**响应** `Result<Integer>`

### 🆕 新增: AdminPayment

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「支付管理」**

### 📌 `GET` /admin/payment/admin/payment

### 📌 `GET` /admin/payment/merchants

**响应** `Result<List<MerchantVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `mchId` | `String` | 商户号ID |
| `name` | `String` | 商户名称 |

### 📌 `GET` /admin/payment/list — 商户号列表

> 返回所有已配置的微信支付商户号，用于下拉选择

**响应** `Result<PageResult<PaymentVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userId` | `Long` | 用户ID |
| `mchId` | `String` | 商户号 |
| `outTradeNo` | `String` | 商户订单号 |
| `transactionIdWx` | `String` | 微信支付交易号 |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `payType` | `String` | 支付类型: FULL/DEPOSIT/BALANCE |
| `totalAmount` | `BigDecimal` | 交易金额 |
| `status` | `String` | 交易状态 |
| `payTime` | `LocalDateTime` | 支付时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/payment/{transactionId} — 支付交易列表

> 分页查询支付交易记录，支持按订单号、交易状态、交易类型筛选

**关联字典**：
- payment_mode：支付模式（列表筛选+显示）

**参数**

  - `{transactionId}` (`Long`) — 路径参数：交易ID

**响应** `Result<PaymentVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userId` | `Long` | 用户ID |
| `mchId` | `String` | 商户号 |
| `outTradeNo` | `String` | 商户订单号 |
| `transactionIdWx` | `String` | 微信支付交易号 |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `payType` | `String` | 支付类型: FULL/DEPOSIT/BALANCE |
| `totalAmount` | `BigDecimal` | 交易金额 |
| `status` | `String` | 交易状态 |
| `payTime` | `LocalDateTime` | 支付时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/payment/order/{orderId} — 交易详情

> 获取单笔交易的完整信息，包含微信支付流水号

**关联字典**：
- payment_mode：支付模式（显示）

**参数**

  - `{orderId}` (`Long`) — 路径参数：订单ID

**响应** `Result<List<PaymentVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userId` | `Long` | 用户ID |
| `mchId` | `String` | 商户号 |
| `outTradeNo` | `String` | 商户订单号 |
| `transactionIdWx` | `String` | 微信支付交易号 |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `payType` | `String` | 支付类型: FULL/DEPOSIT/BALANCE |
| `totalAmount` | `BigDecimal` | 交易金额 |
| `status` | `String` | 交易状态 |
| `payTime` | `LocalDateTime` | 支付时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/payment/{orderId}/refund — 按订单查询交易

> 查询指定订单的所有支付交易记录

**参数**

  - `{orderId}` (`Long`) — 路径参数：订单ID

**请求体** `RefundRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `amount` | `BigDecimal` | 退款金额 |
| `reason` | `String` | 退款原因 |

**响应** `Result<RefundVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `refundId` | `Long` | 退款ID |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `mchId` | `String` | 商户号 |
| `outRefundNo` | `String` | 商户退款单号 |
| `refundIdWx` | `String` | 微信退款单号 |
| `refundAmount` | `BigDecimal` | 退款金额 |
| `totalAmount` | `BigDecimal` | 订单总金额 |
| `reason` | `String` | 退款原因 |
| `status` | `String` | 退款状态 |
| `successTime` | `LocalDateTime` | 退款成功时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/payment/{transactionId}/sync — 发起退款

> 退款流程：验证订单 → 查找原支付交易 → 调用微信退款API → 记录退款单 → 等待微信回调更新状态

权限：SUPER_ADMIN、ADMIN、FINANCE

**参数**

  - `{transactionId}` (`Long`) — 路径参数：交易ID

**响应** `Result<PaymentVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userId` | `Long` | 用户ID |
| `mchId` | `String` | 商户号 |
| `outTradeNo` | `String` | 商户订单号 |
| `transactionIdWx` | `String` | 微信支付交易号 |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `payType` | `String` | 支付类型: FULL/DEPOSIT/BALANCE |
| `totalAmount` | `BigDecimal` | 交易金额 |
| `status` | `String` | 交易状态 |
| `payTime` | `LocalDateTime` | 支付时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/payment/refund/{refundId} — 同步支付状态

> 主动查询微信支付状态并同步本地数据，适用于回调未到达的场景

**参数**

  - `{refundId}` (`Long`) — 路径参数：退款ID

**响应** `Result<RefundVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `refundId` | `Long` | 退款ID |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `mchId` | `String` | 商户号 |
| `outRefundNo` | `String` | 商户退款单号 |
| `refundIdWx` | `String` | 微信退款单号 |
| `refundAmount` | `BigDecimal` | 退款金额 |
| `totalAmount` | `BigDecimal` | 订单总金额 |
| `reason` | `String` | 退款原因 |
| `status` | `String` | 退款状态 |
| `successTime` | `LocalDateTime` | 退款成功时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/payment/refund/order/{orderId} — 退款详情

> 获取单笔退款记录的完整信息，包含微信退款单号和退款状态

**参数**

  - `{orderId}` (`Long`) — 路径参数：订单ID

**响应** `Result<List<RefundVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `refundId` | `Long` | 退款ID |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `mchId` | `String` | 商户号 |
| `outRefundNo` | `String` | 商户退款单号 |
| `refundIdWx` | `String` | 微信退款单号 |
| `refundAmount` | `BigDecimal` | 退款金额 |
| `totalAmount` | `BigDecimal` | 订单总金额 |
| `reason` | `String` | 退款原因 |
| `status` | `String` | 退款状态 |
| `successTime` | `LocalDateTime` | 退款成功时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 🆕 新增: InternalPayment

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「【内部接口】支付（Feign调用）」**

### 📌 `GET` /internal/payment/internal/payment

### 📌 `POST` /internal/payment/prepay

**参数**

  - `userId` (`Long`) — 查询参数

**请求体** `PrepayRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `clientIp` | `String` | 客户端IP（H5支付必填） |

**响应** `Result<PrepayResponse>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `appId` | `String` | 小程序AppID |
| `timeStamp` | `String` | 时间戳 |
| `nonceStr` | `String` | 随机字符串 |
| `packageVal` | `String` | 预支付交易会话标识 |
| `signType` | `String` | 签名类型 |
| `paySign` | `String` | 支付签名 |
| `h5Url` | `String` | H5支付跳转URL |

### 📌 `GET` /internal/payment/status/{orderId} — 创建预支付订单

> 由BFF层调用，向微信支付API发起预支付请求，返回前端调起支付所需的参数（prepay_id等）

**参数**

  - `{orderId}` (`Long`) — 路径参数
  - `userId` (`Long`) — 查询参数

**响应** `Result<PaymentVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userId` | `Long` | 用户ID |
| `mchId` | `String` | 商户号 |
| `outTradeNo` | `String` | 商户订单号 |
| `transactionIdWx` | `String` | 微信支付交易号 |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `payType` | `String` | 支付类型: FULL/DEPOSIT/BALANCE |
| `totalAmount` | `BigDecimal` | 交易金额 |
| `status` | `String` | 交易状态 |
| `payTime` | `LocalDateTime` | 支付时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /internal/payment/transactions/{orderId} — 查询支付状态

> 查询订单的支付状态，含用户权限校验（userId不匹配时拒绝访问）

**支付状态**：PENDING=待支付, SUCCESS=成功, CLOSED=已关闭, FAILED=失败（非字典，代码常量）

**参数**

  - `{orderId}` (`Long`) — 路径参数
  - `userId` (`Long`) — 查询参数

**响应** `Result<List<PaymentVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `userId` | `Long` | 用户ID |
| `mchId` | `String` | 商户号 |
| `outTradeNo` | `String` | 商户订单号 |
| `transactionIdWx` | `String` | 微信支付交易号 |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `payType` | `String` | 支付类型: FULL/DEPOSIT/BALANCE |
| `totalAmount` | `BigDecimal` | 交易金额 |
| `status` | `String` | 交易状态 |
| `payTime` | `LocalDateTime` | 支付时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /internal/payment/refund — 订单交易记录列表

> 查询指定订单的所有支付交易记录（含支付和退款），含用户权限校验

**支付状态**：PENDING=待支付, SUCCESS=成功, CLOSED=已关闭, FAILED=失败（非字典，代码常量）

**请求体** `PaymentRefundRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `amount` | `String` | 退款金额 |
| `reason` | `String` | 退款原因 |

**响应** `Result<RefundVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `refundId` | `Long` | 退款ID |
| `transactionId` | `Long` | 交易ID |
| `orderId` | `Long` | 订单ID |
| `orderNo` | `String` | 订单编号 |
| `mchId` | `String` | 商户号 |
| `outRefundNo` | `String` | 商户退款单号 |
| `refundIdWx` | `String` | 微信退款单号 |
| `refundAmount` | `BigDecimal` | 退款金额 |
| `totalAmount` | `BigDecimal` | 订单总金额 |
| `reason` | `String` | 退款原因 |
| `status` | `String` | 退款状态 |
| `successTime` | `LocalDateTime` | 退款成功时间 |
| `createTime` | `LocalDateTime` | 创建时间 |

### 🆕 新增: PaymentCallback

> 📖 **接口文档**: [http://192.168.100.236:8084/doc.html](http://192.168.100.236:8084/doc.html) → 标签 **「【回调接口】支付回调」**

### 📌 `GET` /pay/callback/pay/callback

### 📌 `POST` /pay/callback/notify/{mchId}

**参数**

  - `{mchId}` (`String`) — 路径参数

**响应** `ResponseEntity<Map<String, String>>`

### 📌 `POST` /pay/callback/refund-notify/{mchId} — 支付成功回调

> 微信支付成功后的异步通知回调（无需认证，通过微信签名验证安全性）。验证签名 → 更新支付状态 → 发送MQ消息通知订单服务

**参数**

  - `{mchId}` (`String`) — 路径参数

**响应** `ResponseEntity<Map<String, String>>`

---

## 资源服务

### 🆕 新增: AdminGuideArticle

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「攻略文章管理」**

### 📌 `GET` /admin/guide/article/list — 文章列表

> 分页查询攻略文章，支持按分类、状态、关键词筛选

**关联字典**：
- wiki_status：文章状态（列表筛选+显示）

**响应** `Result<PageResult<GuideArticleListVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `articleId` | `Long` | 文章ID |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `title` | `String` | 标题 |
| `coverUrl` | `String` | 封面URL |
| `summary` | `String` | 摘要 |
| `viewCount` | `Integer` | 浏览量 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=草稿，1=已发布，2=已下架 |
| `isRecommend` | `Integer` | 是否推荐：0=否，1=是 |
| `isTop` | `Integer` | 是否置顶：0=否，1=是 |
| `publishTime` | `LocalDateTime` | 发布时间 |
| `tags` | `List<GuideTagVO>` | 标签列表 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/guide/article/{articleId} — 文章详情

> **关联字典**：
- wiki_status：文章状态（显示）

**参数**

  - `{articleId}` (`Long`) — 路径参数

**响应** `Result<GuideArticleVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `articleId` | `Long` | 文章ID |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `title` | `String` | 标题 |
| `subtitle` | `String` | 副标题 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `bannerMaterialIds` | `List<Long>` | 轮播图素材ID列表 |
| `summary` | `String` | 摘要 |
| `content` | `String` | 正文内容 |
| `authorName` | `String` | 作者名称 |
| `source` | `String` | 来源 |
| `viewCount` | `Integer` | 浏览量 |
| `likeCount` | `Integer` | 点赞数 |
| `favoriteCount` | `Integer` | 收藏数 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=草稿，1=已发布，2=已下架 |
| `isRecommend` | `Integer` | 是否推荐：0=否，1=是 |
| `isTop` | `Integer` | 是否置顶：0=否，1=是 |
| `publishTime` | `LocalDateTime` | 发布时间 |
| `tags` | `List<GuideTagVO>` | 标签列表 |
| `resources` | `List<GuideArticleResourceVO>` | 关联资源列表 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `updatedAt` | `LocalDateTime` | 更新时间 |

### 📌 `POST` /admin/guide/article — 创建文章

> 创建攻略文章，需指定分类。创建后默认为草稿状态，需手动发布后小程序端才可见。

**权限**：需管理员登录。

**关联字典**：
- wiki_status：文章状态（创建后默认DRAFT）

**请求体** `ArticleCreateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryId` | `Long` | 分类ID |
| `title` | `String` | 标题 |
| `subtitle` | `String` | 副标题 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `bannerMaterialIds` | `List<Long>` | 轮播图素材ID列表 |
| `summary` | `String` | 摘要 |
| `content` | `String` | 正文内容 |
| `authorName` | `String` | 作者名称 |
| `source` | `String` | 来源 |
| `sortOrder` | `Integer` | 排序（默认0） |
| `tagIds` | `List<Long>` | 标签ID列表 |
| `resources` | `List<ArticleResourceItem>` | 关联资源列表 |
| `resourceType` | `String` | 资源类型：SCENIC/RESTAURANT/HOTEL/ACTIVITY/PRODUCT |
| `resourceId` | `Long` | 资源ID |
| `resourceName` | `String` | 资源名称 |
| `sortOrder` | `Integer` | 排序 |

**响应** `Result<GuideArticleVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `articleId` | `Long` | 文章ID |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `title` | `String` | 标题 |
| `subtitle` | `String` | 副标题 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `bannerMaterialIds` | `List<Long>` | 轮播图素材ID列表 |
| `summary` | `String` | 摘要 |
| `content` | `String` | 正文内容 |
| `authorName` | `String` | 作者名称 |
| `source` | `String` | 来源 |
| `viewCount` | `Integer` | 浏览量 |
| `likeCount` | `Integer` | 点赞数 |
| `favoriteCount` | `Integer` | 收藏数 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=草稿，1=已发布，2=已下架 |
| `isRecommend` | `Integer` | 是否推荐：0=否，1=是 |
| `isTop` | `Integer` | 是否置顶：0=否，1=是 |
| `publishTime` | `LocalDateTime` | 发布时间 |
| `tags` | `List<GuideTagVO>` | 标签列表 |
| `resources` | `List<GuideArticleResourceVO>` | 关联资源列表 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `updatedAt` | `LocalDateTime` | 更新时间 |

### 📌 `PUT` /admin/guide/article/{articleId} — 更新文章

> 更新攻略文章的标题、内容、封面图、分类等信息。已发布的文章更新后立即生效。

**权限**：需管理员登录。

**参数**

  - `{articleId}` (`Long`) — 路径参数

**请求体** `ArticleUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryId` | `Long` | 分类ID |
| `title` | `String` | 标题 |
| `subtitle` | `String` | 副标题 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `bannerMaterialIds` | `List<Long>` | 轮播图素材ID列表 |
| `summary` | `String` | 摘要 |
| `content` | `String` | 正文内容 |
| `authorName` | `String` | 作者名称 |
| `source` | `String` | 来源 |
| `sortOrder` | `Integer` | 排序 |
| `tagIds` | `List<Long>` | 标签ID列表 |

**响应** `Result<GuideArticleVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `articleId` | `Long` | 文章ID |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `title` | `String` | 标题 |
| `subtitle` | `String` | 副标题 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `bannerMaterialIds` | `List<Long>` | 轮播图素材ID列表 |
| `summary` | `String` | 摘要 |
| `content` | `String` | 正文内容 |
| `authorName` | `String` | 作者名称 |
| `source` | `String` | 来源 |
| `viewCount` | `Integer` | 浏览量 |
| `likeCount` | `Integer` | 点赞数 |
| `favoriteCount` | `Integer` | 收藏数 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=草稿，1=已发布，2=已下架 |
| `isRecommend` | `Integer` | 是否推荐：0=否，1=是 |
| `isTop` | `Integer` | 是否置顶：0=否，1=是 |
| `publishTime` | `LocalDateTime` | 发布时间 |
| `tags` | `List<GuideTagVO>` | 标签列表 |
| `resources` | `List<GuideArticleResourceVO>` | 关联资源列表 |
| `createdAt` | `LocalDateTime` | 创建时间 |
| `updatedAt` | `LocalDateTime` | 更新时间 |

### 📌 `DELETE` /admin/guide/article/{articleId} — 删除文章

> 软删除攻略文章，同时清除文章的标签关联。

**权限**：需管理员登录。

**参数**

  - `{articleId}` (`Long`) — 路径参数

**响应** `Result<Void>`

### 📌 `PUT` /admin/guide/article/{articleId}/status — 发布/下架

> 切换文章发布状态。发布后小程序端可见，下架后小程序端不再展示但管理端仍可查看

**关联字典**：
- wiki_status：文章状态（状态切换）

**参数**

  - `{articleId}` (`Long`) — 路径参数

**请求体** `StatusRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `status` | `Integer` | 状态值 |

**响应** `Result<Void>`

### 📌 `PUT` /admin/guide/article/{articleId}/recommend — 设置推荐

> 设置/取消文章推荐。推荐文章会在小程序首页和推荐列表中优先展示

**参数**

  - `{articleId}` (`Long`) — 路径参数

**请求体** `RecommendRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `isRecommend` | `Integer` | 是否推荐：0=否，1=是 |

**响应** `Result<Void>`

### 📌 `PUT` /admin/guide/article/{articleId}/top — 设置置顶

> 设置/取消文章置顶。置顶文章在分类列表中始终排在最前面

**参数**

  - `{articleId}` (`Long`) — 路径参数

**请求体** `TopRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `isTop` | `Integer` | 是否置顶：0=否，1=是 |

**响应** `Result<Void>`

### 🆕 新增: AdminGuideCategory

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「攻略分类管理」**

### 📌 `GET` /admin/guide/category/list — 分类列表

> 返回全部攻略分类（含启用和停用），按排序值升序排列

**关联字典**：
- common_status：通用状态（列表显示，ACTIVE=启用/INACTIVE=停用）

**响应** `Result<List<GuideCategoryVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `icon` | `String` | 图标 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `description` | `String` | 描述 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=禁用，1=启用 |
| `articleCount` | `Integer` | 文章数量 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/guide/category/enabled — 启用的分类列表

> 仅返回状态为启用的分类，创建文章时用于选择分类

**响应** `Result<List<GuideCategoryVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `icon` | `String` | 图标 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `description` | `String` | 描述 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=禁用，1=启用 |
| `articleCount` | `Integer` | 文章数量 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/guide/category — 创建分类

> 创建攻略分类，分类名称不可重复。创建后默认启用，排序值越小越靠前。

**权限**：需管理员登录。

**请求体** `CategoryCreateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryName` | `String` | 分类名称 |
| `icon` | `String` | 图标 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `description` | `String` | 描述 |
| `sortOrder` | `Integer` | 排序（默认0） |

**响应** `Result<GuideCategoryVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `icon` | `String` | 图标 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `description` | `String` | 描述 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=禁用，1=启用 |
| `articleCount` | `Integer` | 文章数量 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/guide/category/{categoryId} — 更新分类

> 更新攻略分类的名称、图标、描述等信息。

**权限**：需管理员登录。

**参数**

  - `{categoryId}` (`Long`) — 路径参数

**请求体** `CategoryUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryName` | `String` | 分类名称 |
| `icon` | `String` | 图标 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `description` | `String` | 描述 |
| `sortOrder` | `Integer` | 排序 |

**响应** `Result<GuideCategoryVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `icon` | `String` | 图标 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `description` | `String` | 描述 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=禁用，1=启用 |
| `articleCount` | `Integer` | 文章数量 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `DELETE` /admin/guide/category/{categoryId} — 删除分类

> 删除分类前需确保分类下无文章，否则删除失败

**参数**

  - `{categoryId}` (`Long`) — 路径参数

**响应** `Result<Void>`

### 📌 `PUT` /admin/guide/category/{categoryId}/status — 更新分类状态

> 启用或停用分类。停用后该分类下的文章不会在小程序端展示，但不影响已有文章

**关联字典**：
- common_status：通用状态（状态切换，ACTIVE=启用/INACTIVE=停用）

**参数**

  - `{categoryId}` (`Long`) — 路径参数

**请求体** `StatusRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `status` | `Integer` | 状态值 |

**响应** `Result<Void>`

### 📌 `PUT` /admin/guide/category/{categoryId}/sort — 更新分类排序

> 更新分类的排序值，排序值越小越靠前。影响小程序端分类导航的展示顺序。

**权限**：需管理员登录。

**参数**

  - `{categoryId}` (`Long`) — 路径参数

**请求体** `CategorySortRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `sortOrder` | `Integer` | 排序值 |

**响应** `Result<Void>`

### 🆕 新增: AdminGuideTag

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「攻略标签管理」**

### 📌 `GET` /admin/guide/tag/managed — 系统标签列表

> 返回管理员创建的系统标签（不含用户自定义标签），用于标签管理页

**响应** `Result<List<GuideTagVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `Long` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `tagType` | `Integer` | 标签类型：0=系统管理，1=自定义 |
| `useCount` | `Integer` | 使用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/guide/tag/all — 所有标签列表

> 返回全部标签（含系统标签和用户自定义标签），用于文章编辑时的标签选择器

**响应** `Result<List<GuideTagVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `Long` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `tagType` | `Integer` | 标签类型：0=系统管理，1=自定义 |
| `useCount` | `Integer` | 使用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/guide/tag — 创建标签

> 创建攻略系统标签，标签名称不可重复。创建后可用于文章分类和筛选。

**权限**：需管理员登录。

**请求体** `TagCreateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagName` | `String` | 标签名称 |

**响应** `Result<GuideTagVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `Long` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `tagType` | `Integer` | 标签类型：0=系统管理，1=自定义 |
| `useCount` | `Integer` | 使用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/guide/tag/{tagId} — 更新标签

> 更新标签名称。标签名称不可与其他已有标签重复。

**权限**：需管理员登录。

**参数**

  - `{tagId}` (`Long`) — 路径参数

**请求体** `TagUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |

**响应** `Result<GuideTagVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `Long` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `tagType` | `Integer` | 标签类型：0=系统管理，1=自定义 |
| `useCount` | `Integer` | 使用次数 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `DELETE` /admin/guide/tag/{tagId} — 删除标签

> 删除标签并自动解除与所有文章的关联关系。

**权限**：需管理员登录。

**参数**

  - `{tagId}` (`Long`) — 路径参数

**响应** `Result<Void>`

### 📌 `PUT` /admin/guide/tag/article/{articleId} — 更新文章标签

> 全量替换文章的标签关联，传入新的标签ID列表（空数组表示清除所有标签）

**参数**

  - `{articleId}` (`Long`) — 路径参数

**请求体** `ArticleTagUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagIds` | `List<Long>` | 标签ID列表 |

**响应** `Result<Void>`

### 🆕 新增: InternalWiki

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「【内部接口】攻略百科（Feign调用）」**

### 📌 `GET` /internal/wiki/categories — 查询已启用的攻略分类列表

> 内部服务间调用。返回所有状态为启用的攻略分类，供小程序端展示分类导航。

**关联字典**：
- common_status：通用状态（仅返回ACTIVE状态的分类）

**响应** `Result<List<GuideCategoryVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryId` | `Long` | 分类ID |
| `categoryName` | `String` | 分类名称 |
| `icon` | `String` | 图标 |
| `coverMaterialId` | `Long` | 封面素材ID |
| `coverUrl` | `String` | 封面URL |
| `description` | `String` | 描述 |
| `sortOrder` | `Integer` | 排序 |
| `status` | `Integer` | 状态：0=禁用，1=启用 |
| `articleCount` | `Integer` | 文章数量 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /internal/wiki/category/{categoryId}/articles — 分页查询指定分类下的已发布文章

> **关联字典**：
- wiki_status：文章状态（返回字段）

**参数**

  - `{categoryId}` (`Long`) — 路径参数
  - `page` (`Integer`) — 查询参数
  - `pageSize` (`Integer`) — 查询参数

**响应** `Result<PageResult<Map<String, Object>>>`

### 📌 `GET` /internal/wiki/article/{articleId} — 查询已发布文章详情

> **关联字典**：
- wiki_status：文章状态（返回字段）

**参数**

  - `{articleId}` (`Long`) — 路径参数

**响应** `Result<Map<String, Object>>`

### 📌 `GET` /internal/wiki/recommend-articles — 查询推荐文章列表

> 内部服务间调用。返回已发布且标记为推荐的文章列表，用于小程序首页推荐位展示。默认返回5条。

**参数**

  - `limit` (`Integer`) — 查询参数

**响应** `Result<List<Map<String, Object>>>`

### 🆕 新增: InternalMaterial

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「素材内部接口（Feign调用）」**

### 📌 `POST` /internal/material/ref/bind — 绑定引用

> 将素材与业务实体建立引用关系（如景区ID+封面图），记录引用类型（COVER/GALLERY/DETAIL等）

**参数**

  - `adminId` (`Long`) — 查询参数

**请求体** `RefBindRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `Long` | 素材ID |
| `bizType` | `String` | 业务类型 |
| `bizId` | `Long` | 业务ID |
| `bizName` | `String` | 业务名称 |
| `usageType` | `String` | 用途类型 |

**响应** `Result<Void>`

### 📌 `POST` /internal/material/ref/batch-bind — 批量绑定引用

> 批量建立素材与业务实体的引用关系，常用于保存包含多张图片的业务数据

**参数**

  - `adminId` (`Long`) — 查询参数

**请求体** `RefBatchBindRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `refs` | `List<RefBindRequest>` | 引用绑定列表 |

**响应** `Result<Void>`

### 📌 `DELETE` /internal/material/ref/unbind — 解绑引用

> 删除单个素材与业务实体的引用关系

**请求体** `RefUnbindRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `Long` | 素材ID |
| `bizType` | `String` | 业务类型 |
| `bizId` | `Long` | 业务ID |
| `usageType` | `String` | 用途类型 |

**响应** `Result<Void>`

### 📌 `DELETE` /internal/material/ref/batch-unbind — 批量解绑引用

> 批量删除素材引用关系，常用于业务实体更新时先清除旧引用再绑定新引用

**请求体** `RefBatchUnbindRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `refs` | `List<RefUnbindRequest>` | 解绑列表 |

**响应** `Result<Void>`

### 📌 `DELETE` /internal/material/ref/unbind-all — 全量解绑业务实体引用

> 删除指定业务实体的所有素材引用，用于业务实体被删除时清理引用数据

**参数**

  - `bizType` (`String`) — 查询参数
  - `bizId` (`Long`) — 查询参数

**响应** `Result<Void>`

### 📌 `POST` /internal/material/by-ids — 批量查询素材信息

> 内部服务间调用。根据素材ID列表批量查询素材信息，用于其他服务获取素材详情（如产品、景区等关联的素材数据）。

**请求体** `BatchMaterialIdsRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialIds` | `List<Long>` | 素材ID列表 |

**响应** `Result<List<MaterialVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `fileId` | `String` | 文件ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `subCategoryId` | `String` | 子分类ID |
| `subCategoryName` | `String` | 子分类名称 |
| `categoryPath` | `String` | 完整分类路径（如：攻略管理 / 999 / 888） |
| `materialName` | `String` | 素材名称 |
| `description` | `String` | 素材描述 |
| `fileType` | `String` | 文件类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileName` | `String` | 文件名 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `imageWidth` | `Integer` | 图片宽度 |
| `imageHeight` | `Integer` | 图片高度 |
| `refCount` | `Integer` | 引用次数 |
| `tags` | `List<MaterialTagVO>` | 标签列表 |
| `createdBy` | `String` | 创建人ID |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 🆕 新增: MaterialCategoryPermission

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「素材分类权限管理」**

### 📌 `GET` /admin/material/category/permissions/{roleCode} — 获取角色的分类权限

> 仅超级管理员可操作。返回指定角色可访问的素材分类编码列表

**参数**

  - `{roleCode}` (`String`) — 路径参数：角色编码

**响应** `Result<List<String>>`

### 📌 `PUT` /admin/material/category/permissions/{roleCode} — 更新角色的分类权限

> 仅超级管理员可操作。全量替换指定角色的素材分类访问权限，传入允许访问的分类编码列表

**参数**

  - `{roleCode}` (`String`) — 路径参数：角色编码

**请求体** `CategoryPermissionUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryCodes` | `List<String>` | 分类编码列表 |

**响应** `Result<Void>`

### 🆕 新增: Material

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「素材管理」**

### 📌 `POST` /admin/material/upload/token — 获取上传凭证

> 上传素材第一步：获取OSS预签名URL和凭证。前端使用凭证直传OSS后调用确认上传。支持基于角色的分类权限校验

**请求体** `MaterialUploadTokenRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryCode` | `String` | 分类编码 |
| `subCategoryId` | `Long` | 子分类ID（文件夹上传时使用） |
| `materialName` | `String` | 素材名称 |
| `filename` | `String` | 文件名 |
| `fileSize` | `Long` | 文件大小(字节) |
| `md5` | `String` | 文件MD5 |
| `contentType` | `String` | 文件MIME类型 |

**响应** `Result<MaterialUploadTokenVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `fileId` | `String` | 文件ID |
| `contentType` | `String` | 上传时必须使用的Content-Type（与预签名URL签名一致） |
| `uploadMode` | `String` | 上传模式: PRESIGNED_URL/STS_MULTIPART |
| `uploadUrl` | `String` | 上传URL |
| `ossKey` | `String` | OSS对象Key |
| `expireAt` | `LocalDateTime` | 过期时间 |
| `stsToken` | `StsTokenInfo` | STS临时凭证 |
| `bucket` | `String` | OSS Bucket名称 |
| `region` | `String` | OSS Region |
| `instantUpload` | `boolean` | 是否秒传 |
| `material` | `MaterialVO` | 秒传时返回的素材信息 |
| `accessKeyId` | `String` | AccessKey ID |
| `accessKeySecret` | `String` | AccessKey Secret |
| `securityToken` | `String` | 安全令牌 |
| `expiration` | `String` | 过期时间 |

### 📌 `POST` /admin/material/upload/confirm — 确认上传完成

> 上传素材第二步：前端直传OSS完成后调用此接口创建素材记录，支持MD5去重

**关联字典**：
- material_tag：素材标签（上传时可选标签）

**请求体** `MaterialUploadConfirmRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `description` | `String` | 素材描述 |
| `tagIds` | `List<String>` | 标签ID列表 |

**响应** `Result<MaterialVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `fileId` | `String` | 文件ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `subCategoryId` | `String` | 子分类ID |
| `subCategoryName` | `String` | 子分类名称 |
| `categoryPath` | `String` | 完整分类路径（如：攻略管理 / 999 / 888） |
| `materialName` | `String` | 素材名称 |
| `description` | `String` | 素材描述 |
| `fileType` | `String` | 文件类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileName` | `String` | 文件名 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `imageWidth` | `Integer` | 图片宽度 |
| `imageHeight` | `Integer` | 图片高度 |
| `refCount` | `Integer` | 引用次数 |
| `tags` | `List<MaterialTagVO>` | 标签列表 |
| `createdBy` | `String` | 创建人ID |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/material/upload/folder — 文件夹上传初始化（创建分类+批量获取凭证）

> 支持整个文件夹上传：自动根据文件夹名创建子分类，为每个文件批量获取上传凭证，前端逐一上传后批量确认

**请求体** `FolderUploadInitRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryCode` | `String` | 分类编码 |
| `folderPaths` | `List<String>` | 文件夹路径列表（如 [\ |
| `files` | `List<FileItem>` | 文件列表 |
| `folderPath` | `String` | 文件所在文件夹路径（与folderPaths中的路径对应） |
| `filename` | `String` | 文件名 |
| `fileSize` | `Long` | 文件大小(字节) |
| `md5` | `String` | 文件MD5 |
| `contentType` | `String` | 文件MIME类型 |
| `materialName` | `String` | 素材名称 |

**响应** `Result<FolderUploadInitVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `folderCategoryMap` | `Map<String, String>` | 文件夹路径 → 子分类ID 映射 |
| `fileTokens` | `List<FileTokenItem>` | 各文件的上传凭证列表 |
| `filename` | `String` | 文件名 |
| `folderPath` | `String` | 文件夹路径 |
| `materialId` | `String` | 素材ID |
| `uploadUrl` | `String` | 上传URL |
| `uploadMethod` | `String` | 上传方式: PUT/POST |
| `uploadHeaders` | `Map<String, String>` | 上传请求头 |
| `ossKey` | `String` | OSS对象Key |
| `bucket` | `String` | OSS Bucket名称 |
| `region` | `String` | OSS Region |
| `instantUpload` | `Boolean` | 是否秒传（文件已存在） |
| `error` | `String` | 错误信息（该文件获取凭证失败时） |

### 📌 `POST` /admin/material/upload/chunk/init — 分片上传-初始化

> 大文件上传第一步：初始化分片上传任务，返回uploadId和每个分片的预签名URL。前端按分片并发上传后调用完成合并接口。

**权限**：需管理员登录，受角色分类权限限制。

**请求体** `ChunkUploadInitRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `filename` | `String` | 文件名 |
| `fileSize` | `Long` | 文件大小（字节） |
| `contentType` | `String` | 文件MIME类型 |
| `fileHash` | `String` | 文件MD5哈希（用于去重） |

**响应** `Result<ChunkUploadInitVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `uploadId` | `String` | 上传ID（OSS multipart uploadId） |
| `chunkSize` | `int` | 推荐分片大小（字节） |
| `fileId` | `String` | 文件ID（file_info记录） |
| `ossKey` | `String` | OSS对象Key |

### 📌 `POST` /admin/material/upload/chunk — 分片上传-上传分片

> 大文件上传第二步：逐个上传分片数据，分片索引从0开始。支持断点续传，已上传的分片无需重传。

**参数**

  - `uploadId` (`String`) — 查询参数：上传ID
  - `chunkIndex` (`int`) — 查询参数：分片索引（从0开始）
  - `chunk` (`MultipartFile`) — 查询参数：分片文件

**响应** `Result<ChunkUploadPartVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `etag` | `String` | 分片ETag（用于合并时校验） |

### 📌 `POST` /admin/material/upload/chunk/complete — 分片上传-完成合并

> 大文件上传第三步：所有分片上传完成后调用，OSS端合并分片为完整文件并创建素材记录。

**请求体** `ChunkUploadCompleteRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `uploadId` | `String` | 上传ID |

**响应** `Result<MaterialVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `fileId` | `String` | 文件ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `subCategoryId` | `String` | 子分类ID |
| `subCategoryName` | `String` | 子分类名称 |
| `categoryPath` | `String` | 完整分类路径（如：攻略管理 / 999 / 888） |
| `materialName` | `String` | 素材名称 |
| `description` | `String` | 素材描述 |
| `fileType` | `String` | 文件类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileName` | `String` | 文件名 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `imageWidth` | `Integer` | 图片宽度 |
| `imageHeight` | `Integer` | 图片高度 |
| `refCount` | `Integer` | 引用次数 |
| `tags` | `List<MaterialTagVO>` | 标签列表 |
| `createdBy` | `String` | 创建人ID |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/material/upload/chunk/cancel — 分片上传-取消

> 取消分片上传任务，清理已上传的分片数据和OSS临时文件。仅上传发起者可取消。

**请求体** `ChunkUploadCancelRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `uploadId` | `String` | 上传ID |

**响应** `Result<Void>`

### 📌 `GET` /admin/material/list — 素材列表

> 分页查询素材，支持按分类、标签、文件类型、关键词筛选。返回结果受角色分类权限限制

**关联字典**：
- file_type：文件类型（列表筛选+显示）

**响应** `Result<PageResult<MaterialVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `fileId` | `String` | 文件ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `subCategoryId` | `String` | 子分类ID |
| `subCategoryName` | `String` | 子分类名称 |
| `categoryPath` | `String` | 完整分类路径（如：攻略管理 / 999 / 888） |
| `materialName` | `String` | 素材名称 |
| `description` | `String` | 素材描述 |
| `fileType` | `String` | 文件类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileName` | `String` | 文件名 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `imageWidth` | `Integer` | 图片宽度 |
| `imageHeight` | `Integer` | 图片高度 |
| `refCount` | `Integer` | 引用次数 |
| `tags` | `List<MaterialTagVO>` | 标签列表 |
| `createdBy` | `String` | 创建人ID |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/material/{materialId} — 素材详情

> 返回素材完整信息，包含文件名、URL、分类、标签、文件大小、上传者等。受角色分类权限限制。

**关联字典**：
- file_type：文件类型（显示）

**参数**

  - `{materialId}` (`Long`) — 路径参数：素材ID

**响应** `Result<MaterialVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `fileId` | `String` | 文件ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `subCategoryId` | `String` | 子分类ID |
| `subCategoryName` | `String` | 子分类名称 |
| `categoryPath` | `String` | 完整分类路径（如：攻略管理 / 999 / 888） |
| `materialName` | `String` | 素材名称 |
| `description` | `String` | 素材描述 |
| `fileType` | `String` | 文件类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileName` | `String` | 文件名 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `imageWidth` | `Integer` | 图片宽度 |
| `imageHeight` | `Integer` | 图片高度 |
| `refCount` | `Integer` | 引用次数 |
| `tags` | `List<MaterialTagVO>` | 标签列表 |
| `createdBy` | `String` | 创建人ID |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/material/{materialId} — 更新素材信息

> **关联字典**：
- material_tag：素材标签（编辑时选择标签）

**参数**

  - `{materialId}` (`Long`) — 路径参数：素材ID

**请求体** `MaterialUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialName` | `String` | 素材名称 |
| `description` | `String` | 素材描述 |
| `categoryCode` | `String` | 分类编码 |
| `subCategoryId` | `Long` | 子分类ID（0表示清除子分类） |

**响应** `Result<MaterialVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `fileId` | `String` | 文件ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `subCategoryId` | `String` | 子分类ID |
| `subCategoryName` | `String` | 子分类名称 |
| `categoryPath` | `String` | 完整分类路径（如：攻略管理 / 999 / 888） |
| `materialName` | `String` | 素材名称 |
| `description` | `String` | 素材描述 |
| `fileType` | `String` | 文件类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileName` | `String` | 文件名 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `imageWidth` | `Integer` | 图片宽度 |
| `imageHeight` | `Integer` | 图片高度 |
| `refCount` | `Integer` | 引用次数 |
| `tags` | `List<MaterialTagVO>` | 标签列表 |
| `createdBy` | `String` | 创建人ID |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `DELETE` /admin/material/{materialId} — 删除素材

> 有引用时自动清理引用后删除

**参数**

  - `{materialId}` (`Long`) — 路径参数：素材ID

**响应** `Result<Void>`

### 📌 `DELETE` /admin/material/batch — 批量删除素材

> 批量删除素材，返回删除结果（成功数/失败数/失败原因）。有引用关系的素材会跳过并记录失败原因

**请求体** `BatchDeleteRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialIds` | `List<String>` | 素材ID列表 |

**响应** `Result<BatchDeleteResultVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `successCount` | `int` | 成功删除数量 |
| `failedItems` | `List<FailedItem>` | 失败项列表 |
| `materialId` | `String` | 素材ID |
| `reason` | `String` | 失败原因 |

### 📌 `PUT` /admin/material/{materialId}/tags — 更新素材标签

> 全量替换单个素材的标签，传入新的标签ID列表

**参数**

  - `{materialId}` (`Long`) — 路径参数：素材ID

**请求体** `MaterialTagUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagIds` | `List<String>` | 标签ID列表 |

**响应** `Result<Void>`

### 📌 `PUT` /admin/material/batch/tags — 批量更新标签

> 对多个素材同时添加和/或移除标签，支持增量操作（addTagIds新增，removeTagIds移除）

**请求体** `BatchTagRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialIds` | `List<String>` | 素材ID列表 |
| `addTagIds` | `List<String>` | 要添加的标签ID列表 |
| `removeTagIds` | `List<String>` | 要移除的标签ID列表 |

**响应** `Result<Void>`

### 📌 `GET` /admin/material/{materialId}/refs — 查看素材引用记录

> 查看素材被哪些业务实体引用（如景区封面、酒店轮播图等），用于判断素材是否可安全删除

**参数**

  - `{materialId}` (`Long`) — 路径参数：素材ID

**响应** `Result<List<MaterialRefVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | `String` | 引用ID |
| `materialId` | `String` | 素材ID |
| `bizType` | `String` | 业务类型 |
| `bizTypeName` | `String` | 业务类型名称 |
| `bizId` | `String` | 业务ID |
| `bizName` | `String` | 业务名称 |
| `usageType` | `String` | 用途类型 |
| `usageTypeName` | `String` | 用途类型名称 |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/material/categories — 获取有权限的分类列表（含素材数量）

> 返回当前角色有权限查看的素材分类树，每个分类包含素材数量统计。超级管理员可见全部分类

**响应** `Result<List<CategoryVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `subCategoryId` | `String` | 子分类ID |
| `parentId` | `String` | 父子分类ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `materialCount` | `Integer` | 素材数量 |
| `children` | `List<CategoryVO>` | 子分类列表 |

### 📌 `POST` /admin/material/category/sub — 创建子分类

> 在一级分类下创建子分类，分类编码自动生成。子分类用于更细粒度的素材归档

**请求体** `SubCategoryCreateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `parentCode` | `String` | 根分类编码(scenic/hotel等) |
| `parentId` | `Long` | 父子分类ID(为空则创建在根分类下) |
| `categoryName` | `String` | 子分类名称 |
| `sortOrder` | `Integer` | 排序值 |

**响应** `Result<CategoryVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `subCategoryId` | `String` | 子分类ID |
| `parentId` | `String` | 父子分类ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `materialCount` | `Integer` | 素材数量 |
| `children` | `List<CategoryVO>` | 子分类列表 |

### 📌 `PUT` /admin/material/category/sub/{categoryId} — 更新子分类

> 更新子分类的名称或排序值。仅有该分类权限的管理员可操作。

**参数**

  - `{categoryId}` (`Long`) — 路径参数：子分类ID

**请求体** `SubCategoryUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryName` | `String` | Subcategory name |
| `sortOrder` | `Integer` | Sort order |

**响应** `Result<CategoryVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `subCategoryId` | `String` | 子分类ID |
| `parentId` | `String` | 父子分类ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `materialCount` | `Integer` | 素材数量 |
| `children` | `List<CategoryVO>` | 子分类列表 |

### 📌 `DELETE` /admin/material/category/sub/{categoryId} — 删除子分类

> 删除子分类前需确保分类下无素材，否则删除失败

**参数**

  - `{categoryId}` (`Long`) — 路径参数：子分类ID

**响应** `Result<Void>`

### 📌 `POST` /admin/material/export — 批量导出素材

> 根据选中的素材ID列表，返回每个素材的下载链接信息（名称+OSS URL）。

### 🆕 新增: MaterialTag

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「素材标签管理」**

### 📌 `GET` /admin/material/tags — 获取管理标签（标签管理用，分页）

> 返回管理员创建的系统标签列表（不含用户自定义标签），用于标签管理页的CRUD操作。支持按标签名称搜索。

**参数**

  - `page` (`int`) — 查询参数：页码（默认1）
  - `pageSize` (`int`) — 查询参数：每页条数（默认20）
  - `keyword` (`String`) — 查询参数：搜索关键词（按标签名称模糊搜索）

**响应** `Result<PageResult<MaterialTagVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `String` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `managed` | `Boolean` | 是否系统管理标签 |
| `useCount` | `Integer` | 使用次数 |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `GET` /admin/material/tags/all — 获取全部标签（选择器用，含自定义标签）

> 返回所有标签（含系统标签和用户自定义标签），用于素材上传/编辑时的标签选择器。

**响应** `Result<List<MaterialTagVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `String` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `managed` | `Boolean` | 是否系统管理标签 |
| `useCount` | `Integer` | 使用次数 |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/material/tag — 创建管理标签

> 创建系统级素材标签，标签名称不可重复。创建后可用于素材分类和筛选。

**权限**：需管理员登录。

**请求体** `TagCreateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagName` | `String` | 标签名称 |

**响应** `Result<MaterialTagVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `String` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `managed` | `Boolean` | 是否系统管理标签 |
| `useCount` | `Integer` | 使用次数 |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `POST` /admin/material/tag/adhoc — 解析自定义标签（按名称查找或创建）

> 按标签名称查找已有标签，不存在则自动创建为用户自定义标签。用于素材上传时输入自由标签文本的场景。

**权限**：需管理员登录。

**请求体** `TagCreateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagName` | `String` | 标签名称 |

**响应** `Result<MaterialTagVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `String` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `managed` | `Boolean` | 是否系统管理标签 |
| `useCount` | `Integer` | 使用次数 |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `PUT` /admin/material/tag/{tagId} — 编辑标签

> 更新标签名称。标签名称不可与其他已有标签重复。

**权限**：需管理员登录。

**参数**

  - `{tagId}` (`Long`) — 路径参数：标签ID

**请求体** `TagUpdateRequest`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |

**响应** `Result<MaterialTagVO>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `tagId` | `String` | 标签ID |
| `tagName` | `String` | 标签名称 |
| `tagColor` | `String` | 标签颜色 |
| `managed` | `Boolean` | 是否系统管理标签 |
| `useCount` | `Integer` | 使用次数 |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 📌 `DELETE` /admin/material/tag/{tagId} — 删除标签

> 删除标签并自动解除与所有素材的关联关系。

**权限**：需管理员登录。

**参数**

  - `{tagId}` (`Long`) — 路径参数：标签ID

**响应** `Result<Void>`

### 🆕 新增: MpMaterial

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「小程序-素材」**

### 📌 `GET` /mp/material/miniprogram — 获取小程序分类下的全部素材

> 返回miniprogram分类下的所有素材，用于小程序端展示公共素材资源（如引导页图片、默认头像等）

**响应** `Result<List<MaterialVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialId` | `String` | 素材ID |
| `fileId` | `String` | 文件ID |
| `categoryCode` | `String` | 分类编码 |
| `categoryName` | `String` | 分类名称 |
| `subCategoryId` | `String` | 子分类ID |
| `subCategoryName` | `String` | 子分类名称 |
| `categoryPath` | `String` | 完整分类路径（如：攻略管理 / 999 / 888） |
| `materialName` | `String` | 素材名称 |
| `description` | `String` | 素材描述 |
| `fileType` | `String` | 文件类型 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileName` | `String` | 文件名 |
| `ossUrl` | `String` | OSS地址 |
| `thumbnailUrl` | `String` | 缩略图地址 |
| `imageWidth` | `Integer` | 图片宽度 |
| `imageHeight` | `Integer` | 图片高度 |
| `refCount` | `Integer` | 引用次数 |
| `tags` | `List<MaterialTagVO>` | 标签列表 |
| `createdBy` | `String` | 创建人ID |
| `createdByName` | `String` | 创建人姓名 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 🆕 新增: AdminTransport

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「交通查询管理」**

### 📌 `GET` /admin/transport/flight/by-flight-no — 按航班号查询航班动态

**参数**

  - `flightNo` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<FlightVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `flightNo` | `String` | 航班号 |
| `airline` | `String` | 航空公司名称 |
| `category` | `String` | 航班属性：国内/国际/地区 |
| `departAirportCode` | `String` | 出发机场三字码 |
| `arriveAirportCode` | `String` | 到达机场三字码 |
| `departAirport` | `String` | 出发机场名称 |
| `arriveAirport` | `String` | 到达机场名称 |
| `departCity` | `String` | 出发城市 |
| `arriveCity` | `String` | 到达城市 |
| `planDepartTime` | `String` | 计划起飞时间（yyyy-MM-dd HH:mm:ss） |
| `planArriveTime` | `String` | 计划到达时间（yyyy-MM-dd HH:mm:ss） |
| `actualDepartTime` | `String` | 实际起飞时间（yyyy-MM-dd HH:mm:ss） |
| `actualArriveTime` | `String` | 实际到达时间（yyyy-MM-dd HH:mm:ss） |
| `status` | `String` | 航班状态：计划/起飞/到达/延误/取消/返航/备降等 |
| `stopFlag` | `String` | 是否经停：0不经停，1经停1次，n经停n次 |
| `shareFlag` | `String` | 是否共享航班：0否，1是 |
| `shareFlightNo` | `String` | 共享航班号（实际承运航班号） |
| `departTerminal` | `String` | 出发航站楼 |
| `arriveTerminal` | `String` | 到达航站楼 |
| `boardGate` | `String` | 登机口 |
| `arriveExit` | `String` | 到达出口 |
| `departTimezone` | `String` | 出发时区偏移（秒） |
| `arriveTimezone` | `String` | 到达时区偏移（秒） |

### 📌 `GET` /admin/transport/flight/by-airport — 按机场三字码查询航班动态

**参数**

  - `dep` (`String`) — 查询参数
  - `arr` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<FlightVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `flightNo` | `String` | 航班号 |
| `airline` | `String` | 航空公司名称 |
| `category` | `String` | 航班属性：国内/国际/地区 |
| `departAirportCode` | `String` | 出发机场三字码 |
| `arriveAirportCode` | `String` | 到达机场三字码 |
| `departAirport` | `String` | 出发机场名称 |
| `arriveAirport` | `String` | 到达机场名称 |
| `departCity` | `String` | 出发城市 |
| `arriveCity` | `String` | 到达城市 |
| `planDepartTime` | `String` | 计划起飞时间（yyyy-MM-dd HH:mm:ss） |
| `planArriveTime` | `String` | 计划到达时间（yyyy-MM-dd HH:mm:ss） |
| `actualDepartTime` | `String` | 实际起飞时间（yyyy-MM-dd HH:mm:ss） |
| `actualArriveTime` | `String` | 实际到达时间（yyyy-MM-dd HH:mm:ss） |
| `status` | `String` | 航班状态：计划/起飞/到达/延误/取消/返航/备降等 |
| `stopFlag` | `String` | 是否经停：0不经停，1经停1次，n经停n次 |
| `shareFlag` | `String` | 是否共享航班：0否，1是 |
| `shareFlightNo` | `String` | 共享航班号（实际承运航班号） |
| `departTerminal` | `String` | 出发航站楼 |
| `arriveTerminal` | `String` | 到达航站楼 |
| `boardGate` | `String` | 登机口 |
| `arriveExit` | `String` | 到达出口 |
| `departTimezone` | `String` | 出发时区偏移（秒） |
| `arriveTimezone` | `String` | 到达时区偏移（秒） |

### 📌 `GET` /admin/transport/flight/by-city — 按城市三字码查询航班动态

**参数**

  - `depCity` (`String`) — 查询参数
  - `arrCity` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<FlightVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `flightNo` | `String` | 航班号 |
| `airline` | `String` | 航空公司名称 |
| `category` | `String` | 航班属性：国内/国际/地区 |
| `departAirportCode` | `String` | 出发机场三字码 |
| `arriveAirportCode` | `String` | 到达机场三字码 |
| `departAirport` | `String` | 出发机场名称 |
| `arriveAirport` | `String` | 到达机场名称 |
| `departCity` | `String` | 出发城市 |
| `arriveCity` | `String` | 到达城市 |
| `planDepartTime` | `String` | 计划起飞时间（yyyy-MM-dd HH:mm:ss） |
| `planArriveTime` | `String` | 计划到达时间（yyyy-MM-dd HH:mm:ss） |
| `actualDepartTime` | `String` | 实际起飞时间（yyyy-MM-dd HH:mm:ss） |
| `actualArriveTime` | `String` | 实际到达时间（yyyy-MM-dd HH:mm:ss） |
| `status` | `String` | 航班状态：计划/起飞/到达/延误/取消/返航/备降等 |
| `stopFlag` | `String` | 是否经停：0不经停，1经停1次，n经停n次 |
| `shareFlag` | `String` | 是否共享航班：0否，1是 |
| `shareFlightNo` | `String` | 共享航班号（实际承运航班号） |
| `departTerminal` | `String` | 出发航站楼 |
| `arriveTerminal` | `String` | 到达航站楼 |
| `boardGate` | `String` | 登机口 |
| `arriveExit` | `String` | 到达出口 |
| `departTimezone` | `String` | 出发时区偏移（秒） |
| `arriveTimezone` | `String` | 到达时区偏移（秒） |

### 📌 `GET` /admin/transport/train/by-train-no-stations — 按车次+出发站+到达站查询火车动态

**参数**

  - `trainNo` (`String`) — 查询参数
  - `dep` (`String`) — 查询参数
  - `arr` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<TrainVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `trainNo` | `String` | 车次 |
| `departStation` | `String` | 出发车站 |
| `arriveStation` | `String` | 到达车站 |
| `shutdown` | `String` | 是否停运：0否，1是 |
| `planDepartTime` | `String` | 计划出发时间 |
| `planArriveTime` | `String` | 计划到达时间 |
| `estimatedDepartTime` | `String` | 预计出发时间 |
| `estimatedArriveTime` | `String` | 预计到达时间 |
| `actualDepartTime` | `String` | 实际出发时间 |
| `actualArriveTime` | `String` | 实际到达时间 |
| `departStatus` | `String` | 出发状态：计划/正点/晚点/出发 |
| `arriveStatus` | `String` | 到达状态：计划/正点/晚点/到达 |
| `duration` | `Integer` | 运行时长（分钟） |
| `stops` | `List<TrainStopVO>` | 经停站列表 |

### 📌 `GET` /admin/transport/train/by-train-no — 按车次查询火车动态（含全部经停站）

**参数**

  - `trainNo` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<TrainVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `trainNo` | `String` | 车次 |
| `departStation` | `String` | 出发车站 |
| `arriveStation` | `String` | 到达车站 |
| `shutdown` | `String` | 是否停运：0否，1是 |
| `planDepartTime` | `String` | 计划出发时间 |
| `planArriveTime` | `String` | 计划到达时间 |
| `estimatedDepartTime` | `String` | 预计出发时间 |
| `estimatedArriveTime` | `String` | 预计到达时间 |
| `actualDepartTime` | `String` | 实际出发时间 |
| `actualArriveTime` | `String` | 实际到达时间 |
| `departStatus` | `String` | 出发状态：计划/正点/晚点/出发 |
| `arriveStatus` | `String` | 到达状态：计划/正点/晚点/到达 |
| `duration` | `Integer` | 运行时长（分钟） |
| `stops` | `List<TrainStopVO>` | 经停站列表 |

### 📌 `GET` /admin/transport/train/by-station — 按出发站+到达站查询火车车次

**参数**

  - `dep` (`String`) — 查询参数
  - `arr` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<TrainVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `trainNo` | `String` | 车次 |
| `departStation` | `String` | 出发车站 |
| `arriveStation` | `String` | 到达车站 |
| `shutdown` | `String` | 是否停运：0否，1是 |
| `planDepartTime` | `String` | 计划出发时间 |
| `planArriveTime` | `String` | 计划到达时间 |
| `estimatedDepartTime` | `String` | 预计出发时间 |
| `estimatedArriveTime` | `String` | 预计到达时间 |
| `actualDepartTime` | `String` | 实际出发时间 |
| `actualArriveTime` | `String` | 实际到达时间 |
| `departStatus` | `String` | 出发状态：计划/正点/晚点/出发 |
| `arriveStatus` | `String` | 到达状态：计划/正点/晚点/到达 |
| `duration` | `Integer` | 运行时长（分钟） |
| `stops` | `List<TrainStopVO>` | 经停站列表 |

### 📌 `GET` /admin/transport/train/by-city — 按出发城市+到达城市查询火车车次

**参数**

  - `depCity` (`String`) — 查询参数
  - `arrCity` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<TrainVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `trainNo` | `String` | 车次 |
| `departStation` | `String` | 出发车站 |
| `arriveStation` | `String` | 到达车站 |
| `shutdown` | `String` | 是否停运：0否，1是 |
| `planDepartTime` | `String` | 计划出发时间 |
| `planArriveTime` | `String` | 计划到达时间 |
| `estimatedDepartTime` | `String` | 预计出发时间 |
| `estimatedArriveTime` | `String` | 预计到达时间 |
| `actualDepartTime` | `String` | 实际出发时间 |
| `actualArriveTime` | `String` | 实际到达时间 |
| `departStatus` | `String` | 出发状态：计划/正点/晚点/出发 |
| `arriveStatus` | `String` | 到达状态：计划/正点/晚点/到达 |
| `duration` | `Integer` | 运行时长（分钟） |
| `stops` | `List<TrainStopVO>` | 经停站列表 |

### 🆕 新增: InternalTransport

> 📖 **接口文档**: [http://192.168.100.236:8082/doc.html](http://192.168.100.236:8082/doc.html) → 标签 **「【内部接口】交通查询（Feign调用）」**

### 📌 `GET` /internal/transport/flight — 按航班号查询航班动态

**参数**

  - `flightNo` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<FlightVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `flightNo` | `String` | 航班号 |
| `airline` | `String` | 航空公司名称 |
| `category` | `String` | 航班属性：国内/国际/地区 |
| `departAirportCode` | `String` | 出发机场三字码 |
| `arriveAirportCode` | `String` | 到达机场三字码 |
| `departAirport` | `String` | 出发机场名称 |
| `arriveAirport` | `String` | 到达机场名称 |
| `departCity` | `String` | 出发城市 |
| `arriveCity` | `String` | 到达城市 |
| `planDepartTime` | `String` | 计划起飞时间（yyyy-MM-dd HH:mm:ss） |
| `planArriveTime` | `String` | 计划到达时间（yyyy-MM-dd HH:mm:ss） |
| `actualDepartTime` | `String` | 实际起飞时间（yyyy-MM-dd HH:mm:ss） |
| `actualArriveTime` | `String` | 实际到达时间（yyyy-MM-dd HH:mm:ss） |
| `status` | `String` | 航班状态：计划/起飞/到达/延误/取消/返航/备降等 |
| `stopFlag` | `String` | 是否经停：0不经停，1经停1次，n经停n次 |
| `shareFlag` | `String` | 是否共享航班：0否，1是 |
| `shareFlightNo` | `String` | 共享航班号（实际承运航班号） |
| `departTerminal` | `String` | 出发航站楼 |
| `arriveTerminal` | `String` | 到达航站楼 |
| `boardGate` | `String` | 登机口 |
| `arriveExit` | `String` | 到达出口 |
| `departTimezone` | `String` | 出发时区偏移（秒） |
| `arriveTimezone` | `String` | 到达时区偏移（秒） |

### 📌 `GET` /internal/transport/train — 按车次查询火车动态

**参数**

  - `trainNo` (`String`) — 查询参数
  - `date` (`String`) — 查询参数

**响应** `Result<List<TrainVO>>`

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `trainNo` | `String` | 车次 |
| `departStation` | `String` | 出发车站 |
| `arriveStation` | `String` | 到达车站 |
| `shutdown` | `String` | 是否停运：0否，1是 |
| `planDepartTime` | `String` | 计划出发时间 |
| `planArriveTime` | `String` | 计划到达时间 |
| `estimatedDepartTime` | `String` | 预计出发时间 |
| `estimatedArriveTime` | `String` | 预计到达时间 |
| `actualDepartTime` | `String` | 实际出发时间 |
| `actualArriveTime` | `String` | 实际到达时间 |
| `departStatus` | `String` | 出发状态：计划/正点/晚点/出发 |
| `arriveStatus` | `String` | 到达状态：计划/正点/晚点/到达 |
| `duration` | `Integer` | 运行时长（分钟） |
| `stops` | `List<TrainStopVO>` | 经停站列表 |

---

## 📦 其他数据对象变更

> 以下变更未直接关联到本次接口变更，但可能影响现有接口的请求/响应

### 用户服务

#### 🆕 AssigneeVO

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `adminId` | `Long` | 管理员ID |
| `username` | `String` | 用户名 |
| `avatarUrl` | `String` | 头像地址 |
| `wechatName` | `String` | 企微昵称 |

#### 🆕 ChatMessageVO

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `msgId` | `String` | 消息ID |
| `fromUser` | `String` | 发送人ID |
| `fromUserName` | `String` | 发送人姓名 |
| `fromUserAvatar` | `String` | 发送人头像 |
| `roomId` | `String` | 群聊ID |
| `msgTime` | `Long` | 消息时间戳 |
| `msgType` | `String` | 消息类型 |
| `content` | `String` | 消息内容 |

#### 🆕 FileQueryRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileType` | `String` | 文件类型 |
| `groupKey` | `String` | 业务分组 |
| `keyword` | `String` | 搜索关键词 |
| `startDate` | `String` | 开始日期 |
| `endDate` | `String` | 结束日期 |

#### 🆕 MpReviewQueryRequest

#### 🆕 ReviewQueryRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `reviewType` | `String` | 评论类型（字典 review_type） |
| `productType` | `String` | 产品类型（字典 review_product_type） |
| `targetType` | `String` | 评价目标类型 |
| `targetId` | `Long` | 评价目标ID |
| `status` | `String` | 评价状态 |
| `ratingLevel` | `String` | 评价等级: GOOD/MEDIUM/BAD |
| `hasImage` | `Boolean` | 是否有图片: true/false |
| `hasVideo` | `Boolean` | 是否有视频: true/false |
| `keyword` | `String` | 搜索关键词 |
| `minRating` | `Integer` | 最低评分(整体满意度) |
| `maxRating` | `Integer` | 最高评分(整体满意度) |

#### 🆕 ReviewableTargetVO

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `targetType` | `String` | 评价目标类型 |
| `targetTypeLabel` | `String` | 评价目标类型标签 |
| `targetId` | `String` | 评价目标ID |
| `targetName` | `String` | 评价目标名称 |
| `reviewed` | `boolean` | 是否已评价 |

#### 🆕 TargetReviewQueryRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `targetType` | `String` | 目标类型 |
| `targetId` | `Long` | 目标ID |
| `ratingLevel` | `String` | 评价等级筛选: GOOD/MEDIUM/BAD |
| `hasImage` | `Boolean` | 是否有图片 |
| `hasVideo` | `Boolean` | 是否有视频 |

#### 🆕 WechatGroupVO

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | `Long` | ID |
| `roomId` | `String` | 企微群聊ID |
| `groupName` | `String` | 群名称 |
| `ownerUserId` | `String` | 群主企微userId |
| `ownerName` | `String` | 群主姓名 |
| `memberCount` | `Integer` | 群成员数 |
| `remark` | `String` | 备注 |
| `recentMessageCount` | `Integer` | 最近消息数 |
| `lastSyncTime` | `LocalDateTime` | 最后同步时间 |
| `createdAt` | `LocalDateTime` | 创建时间 |

### 订单服务

#### 🆕 ContractQueryRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 订单ID |
| `status` | `String` | 合同状态 |
| `platform` | `String` | 签约平台 |

#### 🆕 InsuranceQueryRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderId` | `Long` | 关联旅行订单ID |
| `status` | `String` | 订单状态: PENDING-待出单, INSURED-已承保, CANCELLED-已退保, FAILED-投保失败 |

#### 🆕 PaymentQueryRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `orderNo` | `String` | 订单编号 |
| `mchId` | `String` | 商户号 |
| `status` | `String` | 支付状态 |
| `tradeType` | `String` | 交易类型: JSAPI/H5 |
| `startDate` | `String` | 开始日期 |
| `endDate` | `String` | 结束日期 |

#### 🆕 SelectivePurchaseRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `schemeId` | `Long` | 保险方案ID |
| `travelerIds` | `List<Long>` | 要投保的出行人ID列表 |

#### 🆕 TravelerCoverageVO

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `travelerId` | `String` | 出行人ID |
| `name` | `String` | 姓名 |
| `birthday` | `LocalDate` | 出生日期 |
| `age` | `Integer` | 年龄 |
| `travelerType` | `String` | 出行人类型：ADULT/CHILD |
| `coverageStatus` | `String` | 保险覆盖状态：ONLINE_INSURED=在线已投保, OFFLINE_NOTED=线下已备注, NOT_COVERED=未投保 |
| `policies` | `List<Map<String, Object>>` | 在线保单列表（coverageStatus=ONLINE_INSURED时有值） |
| `noteId` | `String` | 线下备注ID（coverageStatus=OFFLINE_NOTED时有值） |
| `noteType` | `String` | 线下备注类型 |
| `noteRemark` | `String` | 线下备注说明（coverageStatus=OFFLINE_NOTED时有值） |

#### 🆕 TravelerNoteRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `travelerId` | `Long` | 出行人ID |
| `travelerName` | `String` | 出行人姓名 |
| `noteType` | `String` | 备注类型：OFFLINE=线下投保, SKIP=跳过, OTHER=其他 |
| `remark` | `String` | 备注说明 |

### 资源服务

#### 🆕 ArticleQueryRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `keyword` | `String` | 关键词（搜索标题/摘要） |
| `categoryId` | `Long` | 分类ID |
| `status` | `Integer` | 状态：0=草稿，1=已发布，2=已下架 |
| `isRecommend` | `Integer` | 是否推荐：0=否，1=是 |
| `isTop` | `Integer` | 是否置顶：0=否，1=是 |
| `orderBy` | `String` | 排序字段：sortOrder/publishTime/viewCount/createdAt（默认createdAt） |
| `orderDir` | `String` | 排序方向：asc/desc（默认desc） |

#### 🆕 FileBatchIdsRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileIds` | `List<Long>` | 文件ID列表 |

#### 🆕 FileUploadConfirmRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |

#### 🆕 FileUploadTokenRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileName` | `String` | 文件名 |
| `fileSize` | `Long` | 文件大小(字节) |
| `fileHash` | `String` | 文件哈希值 |
| `groupKey` | `String` | 分组标识 |
| `forcePresigned` | `boolean` | 是否强制使用预签名URL |

#### 🆕 FileUploadTokenVO

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `fileId` | `String` | 文件ID |
| `contentType` | `String` | 文件MIME类型 |
| `uploadMode` | `String` | 上传模式 |
| `presignedUrl` | `String` | 预签名上传URL |
| `ossKey` | `String` | OSS对象Key |
| `expireAt` | `LocalDateTime` | 过期时间 |
| `stsToken` | `StsTokenInfo` | STS临时凭证 |
| `bucket` | `String` | OSS存储桶名称 |
| `region` | `String` | OSS区域 |
| `file` | `FileVO` | 文件信息(秒传时返回) |
| `accessKeyId` | `String` | 访问密钥ID |
| `accessKeySecret` | `String` | 访问密钥Secret |
| `securityToken` | `String` | 安全令牌 |
| `expiration` | `String` | 过期时间 |

#### 🆕 GuideArticleResourceVO

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `resourceType` | `String` | 资源类型：SCENIC/RESTAURANT/HOTEL/ACTIVITY/PRODUCT |
| `resourceId` | `Long` | 资源ID |
| `resourceName` | `String` | 资源名称 |
| `sortOrder` | `Integer` | 排序 |

#### 🆕 MaterialQueryRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `categoryCode` | `String` | 分类编码 |
| `subCategoryId` | `Long` | 子分类ID |
| `fileType` | `String` | 文件类型 |
| `tagIds` | `String` | 标签ID列表(逗号分隔) |
| `keyword` | `String` | 搜索关键词 |
| `createdBy` | `Long` | 创建人ID |
| `startDate` | `String` | 开始日期 |
| `endDate` | `String` | 结束日期 |

#### 🆕 MaterialReviewRequest

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `materialIds` | `List<String>` | 素材ID列表 |

#### 🆕 TrainStopVO

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `stationName` | `String` | 车站名称 |
| `arriveTime` | `String` | 到站时间 |
| `departTime` | `String` | 发车时间 |

<details>
<summary>📁 全部变更文件 (点击展开)</summary>

```
A	copyright-materials/design_document.pdf
A	copyright-materials/source_code.pdf
A	docs.zip
A	fadada-home.md
A	fix_12301_url.py
A	fix_agency.py
A	fix_stage.py
M	hl-order-service/pom.xml
A	hl-order-service/src/main/java/com/hulalv/contract/config/ContractPlatformProperties.java
A	hl-order-service/src/main/java/com/hulalv/contract/config/MyBatisPlusConfig.java
A	hl-order-service/src/main/java/com/hulalv/contract/config/RestTemplateConfig.java
A	hl-order-service/src/main/java/com/hulalv/contract/config/WebMvcConfig.java
A	hl-order-service/src/main/java/com/hulalv/contract/constant/ContractConstants.java
A	hl-order-service/src/main/java/com/hulalv/contract/controller/AdminClauseTemplateController.java
A	hl-order-service/src/main/java/com/hulalv/contract/controller/AdminContractController.java
A	hl-order-service/src/main/java/com/hulalv/contract/controller/AdminContractSchemeController.java
A	hl-order-service/src/main/java/com/hulalv/contract/controller/ContractCallbackController.java
A	hl-order-service/src/main/java/com/hulalv/contract/controller/InternalContractController.java
A	hl-order-service/src/main/java/com/hulalv/contract/controller/InternalMpContractController.java
A	hl-order-service/src/main/java/com/hulalv/contract/dto/ClauseTemplateRequest.java
A	hl-order-service/src/main/java/com/hulalv/contract/dto/ContractCallbackPayload.java
A	hl-order-service/src/main/java/com/hulalv/contract/dto/ContractQueryRequest.java
A	hl-order-service/src/main/java/com/hulalv/contract/dto/ContractSchemeRequest.java
A	hl-order-service/src/main/java/com/hulalv/contract/dto/CreateContractRequest.java
A	hl-order-service/src/main/java/com/hulalv/contract/dto/ReportContractRequest.java
A	hl-order-service/src/main/java/com/hulalv/contract/entity/Contract.java
A	hl-order-service/src/main/java/com/hulalv/contract/entity/ContractClauseTemplate.java
A	hl-order-service/src/main/java/com/hulalv/contract/entity/ContractScheme.java
A	hl-order-service/src/main/java/com/hulalv/contract/entity/ContractStatusLog.java
A	hl-order-service/src/main/java/com/hulalv/contract/entity/ContractTemplate.java
A	hl-order-service/src/main/java/com/hulalv/contract/entity/ContractTraveler.java
A	hl-order-service/src/main/java/com/hulalv/contract/feign/OrderContractFeignClient.java
A	hl-order-service/src/main/java/com/hulalv/contract/interceptor/AdminAuthInterceptor.java
A	hl-order-service/src/main/java/com/hulalv/contract/job/ContractStatusRefreshJob.java
A	hl-order-service/src/main/java/com/hulalv/contract/mapper/ContractClauseTemplateMapper.java
A	hl-order-service/src/main/java/com/hulalv/contract/mapper/ContractMapper.java
A	hl-order-service/src/main/java/com/hulalv/contract/mapper/ContractSchemeMapper.java
A	hl-order-service/src/main/java/com/hulalv/contract/mapper/ContractStatusLogMapper.java
A	hl-order-service/src/main/java/com/hulalv/contract/mapper/ContractTemplateMapper.java
A	hl-order-service/src/main/java/com/hulalv/contract/mapper/ContractTravelerMapper.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/ContractApplyParam.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/ContractApplyResult.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/ContractPlatform.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/ContractPlatformFactory.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/ContractPlatformInfo.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/ContractPlatformStatus.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/ContractReportParam.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/ContractReportResult.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/fadada/FadadaApiClient.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/fadada/FadadaContractPlatform.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/fadada/FadadaSignatureUtil.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/tourage/TourageApiClient.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/tourage/TourageContractPlatform.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/tourage/TourageRequestBuilder.java
A	hl-order-service/src/main/java/com/hulalv/contract/platform/tourage/TourageSignatureUtil.java
A	hl-order-service/src/main/java/com/hulalv/contract/service/ClauseTemplateService.java
A	hl-order-service/src/main/java/com/hulalv/contract/service/ContractCallbackService.java
A	hl-order-service/src/main/java/com/hulalv/contract/service/ContractSchemeService.java
A	hl-order-service/src/main/java/com/hulalv/contract/service/ContractService.java
A	hl-order-service/src/main/java/com/hulalv/contract/service/SafetyNoticeService.java
A	hl-order-service/src/main/java/com/hulalv/contract/vo/ClauseTemplateVO.java
A	hl-order-service/src/main/java/com/hulalv/contract/vo/ContractDetailVO.java
A	hl-order-service/src/main/java/com/hulalv/contract/vo/ContractSchemeVO.java
A	hl-order-service/src/main/java/com/hulalv/contract/vo/ContractTemplateVO.java
A	hl-order-service/src/main/java/com/hulalv/contract/vo/ContractVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/config/BaoyouApiProperties.java
A	hl-order-service/src/main/java/com/hulalv/insurance/config/InsuranceEntityProperties.java
A	hl-order-service/src/main/java/com/hulalv/insurance/config/MyBatisPlusConfig.java
A	hl-order-service/src/main/java/com/hulalv/insurance/config/RestTemplateConfig.java
A	hl-order-service/src/main/java/com/hulalv/insurance/config/WebMvcConfig.java
A	hl-order-service/src/main/java/com/hulalv/insurance/constant/InsuranceConstants.java
A	hl-order-service/src/main/java/com/hulalv/insurance/controller/AdminInsuranceController.java
A	hl-order-service/src/main/java/com/hulalv/insurance/controller/AdminInsuranceSchemeController.java
A	hl-order-service/src/main/java/com/hulalv/insurance/controller/InternalInsuranceController.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/ApplySchemeRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/AutoPurchaseRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/InsuranceQueryRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/InsuranceSchemeRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/PurchaseInsuranceRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/RechargeRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/SelectivePurchaseRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/SharePolicyRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/TravelerNoteRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/dto/TrialPriceRequest.java
A	hl-order-service/src/main/java/com/hulalv/insurance/entity/InsuranceOrder.java
A	hl-order-service/src/main/java/com/hulalv/insurance/entity/InsurancePlan.java
A	hl-order-service/src/main/java/com/hulalv/insurance/entity/InsuranceProduct.java
A	hl-order-service/src/main/java/com/hulalv/insurance/entity/InsuranceRate.java
A	hl-order-service/src/main/java/com/hulalv/insurance/entity/InsuranceScheme.java
A	hl-order-service/src/main/java/com/hulalv/insurance/entity/InsuranceSchemeSegment.java
A	hl-order-service/src/main/java/com/hulalv/insurance/entity/InsuranceTravelerNote.java
A	hl-order-service/src/main/java/com/hulalv/insurance/entity/InsuredPerson.java
A	hl-order-service/src/main/java/com/hulalv/insurance/feign/OrderInsuranceFeignClient.java
A	hl-order-service/src/main/java/com/hulalv/insurance/interceptor/AdminAuthInterceptor.java
A	hl-order-service/src/main/java/com/hulalv/insurance/mapper/InsuranceOrderMapper.java
A	hl-order-service/src/main/java/com/hulalv/insurance/mapper/InsurancePlanMapper.java
A	hl-order-service/src/main/java/com/hulalv/insurance/mapper/InsuranceProductMapper.java
A	hl-order-service/src/main/java/com/hulalv/insurance/mapper/InsuranceRateMapper.java
A	hl-order-service/src/main/java/com/hulalv/insurance/mapper/InsuranceSchemeMapper.java
A	hl-order-service/src/main/java/com/hulalv/insurance/mapper/InsuranceSchemeSegmentMapper.java
A	hl-order-service/src/main/java/com/hulalv/insurance/mapper/InsuranceTravelerNoteMapper.java
A	hl-order-service/src/main/java/com/hulalv/insurance/mapper/InsuredPersonMapper.java
A	hl-order-service/src/main/java/com/hulalv/insurance/service/BaoyouApiClient.java
A	hl-order-service/src/main/java/com/hulalv/insurance/service/InsuranceOrderService.java
A	hl-order-service/src/main/java/com/hulalv/insurance/service/InsuranceProductSyncService.java
A	hl-order-service/src/main/java/com/hulalv/insurance/service/InsuranceSchemeService.java
A	hl-order-service/src/main/java/com/hulalv/insurance/service/InsuranceSyncScheduler.java
A	hl-order-service/src/main/java/com/hulalv/insurance/service/PolicyPdfUploadService.java
A	hl-order-service/src/main/java/com/hulalv/insurance/service/PolicyShareService.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/ApplySchemePreviewVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/AutoPurchaseResultVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/InsuranceCoverageVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/InsuranceOrderDetailVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/InsuranceOrderVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/InsurancePlanVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/InsuranceProductVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/InsuranceSchemeVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/PolicyShareVO.java
A	hl-order-service/src/main/java/com/hulalv/insurance/vo/TravelerCoverageVO.java
M	hl-order-service/src/main/java/com/hulalv/order/OrderServiceApplication.java
A	hl-order-service/src/main/java/com/hulalv/payment/config/MyBatisPlusConfig.java
A	hl-order-service/src/main/java/com/hulalv/payment/config/WebMvcConfig.java
A	hl-order-service/src/main/java/com/hulalv/payment/config/WxPayConfig.java
A	hl-order-service/src/main/java/com/hulalv/payment/config/WxPayProperties.java
A	hl-order-service/src/main/java/com/hulalv/payment/constant/PaymentConstants.java
A	hl-order-service/src/main/java/com/hulalv/payment/controller/AdminPaymentController.java
A	hl-order-service/src/main/java/com/hulalv/payment/controller/InternalPaymentController.java
A	hl-order-service/src/main/java/com/hulalv/payment/controller/PaymentCallbackController.java
A	hl-order-service/src/main/java/com/hulalv/payment/dto/PaymentQueryRequest.java
A	hl-order-service/src/main/java/com/hulalv/payment/dto/PrepayRequest.java
A	hl-order-service/src/main/java/com/hulalv/payment/dto/PrepayResponse.java
A	hl-order-service/src/main/java/com/hulalv/payment/dto/RefundRequest.java
A	hl-order-service/src/main/java/com/hulalv/payment/entity/PaymentTransaction.java
A	hl-order-service/src/main/java/com/hulalv/payment/entity/RefundRecord.java
A	hl-order-service/src/main/java/com/hulalv/payment/feign/OrderPaymentFeignClient.java
A	hl-order-service/src/main/java/com/hulalv/payment/feign/OrderPaymentFeignFallbackFactory.java
A	hl-order-service/src/main/java/com/hulalv/payment/feign/UserPaymentFeignClient.java
A	hl-order-service/src/main/java/com/hulalv/payment/feign/UserPaymentFeignFallbackFactory.java
A	hl-order-service/src/main/java/com/hulalv/payment/interceptor/AdminAuthInterceptor.java
A	hl-order-service/src/main/java/com/hulalv/payment/mapper/PaymentTransactionMapper.java
A	hl-order-service/src/main/java/com/hulalv/payment/mapper/RefundRecordMapper.java
A	hl-order-service/src/main/java/com/hulalv/payment/mq/producer/PaymentResultProducer.java
A	hl-order-service/src/main/java/com/hulalv/payment/service/PaymentService.java
A	hl-order-service/src/main/java/com/hulalv/payment/service/RefundService.java
A	hl-order-service/src/main/java/com/hulalv/payment/vo/MerchantVO.java
A	hl-order-service/src/main/java/com/hulalv/payment/vo/PaymentVO.java
A	hl-order-service/src/main/java/com/hulalv/payment/vo/RefundVO.java
A	hl-order-service/src/test/java/com/hulalv/contract/EntityDtoCoverageTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/constant/ContractConstantsTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/controller/AdminClauseTemplateControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/controller/AdminContractControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/controller/AdminContractSchemeControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/controller/ContractCallbackControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/controller/InternalContractControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/controller/InternalMpContractControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/interceptor/AdminAuthInterceptorTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/job/ContractStatusRefreshJobTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/platform/ContractPlatformFactoryTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/platform/fadada/FadadaApiClientTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/platform/fadada/FadadaContractPlatformTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/platform/fadada/FadadaSignatureUtilTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/platform/tourage/TourageContractPlatformTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/platform/tourage/TourageRequestBuilderTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/platform/tourage/TourageSignatureUtilTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/service/ClauseTemplateServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/service/ContractCallbackServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/service/ContractSchemeServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/service/ContractServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/contract/service/SafetyNoticeServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/insurance/constant/InsuranceConstantsTest.java
A	hl-order-service/src/test/java/com/hulalv/insurance/service/BaoyouApiClientTest.java
A	hl-order-service/src/test/java/com/hulalv/insurance/service/InsuranceOrderServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/insurance/service/InsuranceProductSyncServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/insurance/service/InsuranceSchemeServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/EntityDtoCoverageTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/config/WxPayConfigTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/constant/PaymentConstantsTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/controller/AdminPaymentControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/controller/InternalPaymentControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/controller/PaymentCallbackControllerTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/interceptor/AdminAuthInterceptorTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/mq/producer/PaymentResultProducerTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/service/PaymentServiceTest.java
A	hl-order-service/src/test/java/com/hulalv/payment/service/RefundServiceTest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/config/MyBatisPlusConfig.java
A	hl-resource-service/src/main/java/com/hulalv/guide/config/WebMvcConfig.java
A	hl-resource-service/src/main/java/com/hulalv/guide/constant/GuideConstants.java
A	hl-resource-service/src/main/java/com/hulalv/guide/controller/AdminGuideArticleController.java
A	hl-resource-service/src/main/java/com/hulalv/guide/controller/AdminGuideCategoryController.java
A	hl-resource-service/src/main/java/com/hulalv/guide/controller/AdminGuideTagController.java
A	hl-resource-service/src/main/java/com/hulalv/guide/controller/InternalWikiController.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/ArticleCreateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/ArticleQueryRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/ArticleTagUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/ArticleUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/CategoryCreateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/CategorySortRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/CategoryUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/RecommendRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/StatusRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/TagCreateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/TagUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/dto/TopRequest.java
A	hl-resource-service/src/main/java/com/hulalv/guide/entity/GuideArticle.java
A	hl-resource-service/src/main/java/com/hulalv/guide/entity/GuideArticleResource.java
A	hl-resource-service/src/main/java/com/hulalv/guide/entity/GuideCategory.java
A	hl-resource-service/src/main/java/com/hulalv/guide/entity/GuideTag.java
A	hl-resource-service/src/main/java/com/hulalv/guide/entity/GuideTagRel.java
A	hl-resource-service/src/main/java/com/hulalv/guide/interceptor/AdminAuthInterceptor.java
A	hl-resource-service/src/main/java/com/hulalv/guide/mapper/GuideArticleMapper.java
A	hl-resource-service/src/main/java/com/hulalv/guide/mapper/GuideArticleResourceMapper.java
A	hl-resource-service/src/main/java/com/hulalv/guide/mapper/GuideCategoryMapper.java
A	hl-resource-service/src/main/java/com/hulalv/guide/mapper/GuideTagMapper.java
A	hl-resource-service/src/main/java/com/hulalv/guide/mapper/GuideTagRelMapper.java
A	hl-resource-service/src/main/java/com/hulalv/guide/service/GuideArticleService.java
A	hl-resource-service/src/main/java/com/hulalv/guide/service/GuideCategoryService.java
A	hl-resource-service/src/main/java/com/hulalv/guide/service/GuideTagService.java
A	hl-resource-service/src/main/java/com/hulalv/guide/vo/GuideArticleListVO.java
A	hl-resource-service/src/main/java/com/hulalv/guide/vo/GuideArticleResourceVO.java
A	hl-resource-service/src/main/java/com/hulalv/guide/vo/GuideArticleVO.java
A	hl-resource-service/src/main/java/com/hulalv/guide/vo/GuideCategoryVO.java
A	hl-resource-service/src/main/java/com/hulalv/guide/vo/GuideTagVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/config/MyBatisPlusConfig.java
A	hl-resource-service/src/main/java/com/hulalv/material/config/WebMvcConfig.java
A	hl-resource-service/src/main/java/com/hulalv/material/constant/MaterialConstants.java
A	hl-resource-service/src/main/java/com/hulalv/material/controller/DictCacheService.java
A	hl-resource-service/src/main/java/com/hulalv/material/controller/InternalMaterialController.java
A	hl-resource-service/src/main/java/com/hulalv/material/controller/MaterialCategoryPermissionController.java
A	hl-resource-service/src/main/java/com/hulalv/material/controller/MaterialController.java
A	hl-resource-service/src/main/java/com/hulalv/material/controller/MaterialTagController.java
A	hl-resource-service/src/main/java/com/hulalv/material/controller/MpMaterialController.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/BatchDeleteRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/BatchMaterialIdsRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/BatchTagRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/CategoryPermissionUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/ChunkUploadCancelRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/ChunkUploadCompleteRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/ChunkUploadInitRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/FolderUploadInitRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/MaterialQueryRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/MaterialReviewRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/MaterialTagUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/MaterialUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/MaterialUploadConfirmRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/MaterialUploadTokenRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/RefBatchBindRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/RefBatchUnbindRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/RefBindRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/RefUnbindRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/SubCategoryCreateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/SubCategoryUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/TagCreateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/dto/TagUpdateRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/entity/Material.java
A	hl-resource-service/src/main/java/com/hulalv/material/entity/MaterialCategory.java
A	hl-resource-service/src/main/java/com/hulalv/material/entity/MaterialCategoryPermission.java
A	hl-resource-service/src/main/java/com/hulalv/material/entity/MaterialRef.java
A	hl-resource-service/src/main/java/com/hulalv/material/entity/MaterialTag.java
A	hl-resource-service/src/main/java/com/hulalv/material/entity/MaterialTagRel.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/FileServiceClient.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/FileServiceFallbackFactory.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/dto/ChunkUploadCancelRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/dto/ChunkUploadCompleteRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/dto/ChunkUploadInitRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/dto/FileBatchIdsRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/dto/FileUploadConfirmRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/dto/FileUploadTokenRequest.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/vo/ChunkUploadInitVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/vo/ChunkUploadPartVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/vo/FileUploadTokenVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/feign/vo/FileVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/interceptor/AdminAuthInterceptor.java
A	hl-resource-service/src/main/java/com/hulalv/material/mapper/MaterialCategoryMapper.java
A	hl-resource-service/src/main/java/com/hulalv/material/mapper/MaterialCategoryPermissionMapper.java
A	hl-resource-service/src/main/java/com/hulalv/material/mapper/MaterialMapper.java
A	hl-resource-service/src/main/java/com/hulalv/material/mapper/MaterialRefMapper.java
A	hl-resource-service/src/main/java/com/hulalv/material/mapper/MaterialTagMapper.java
A	hl-resource-service/src/main/java/com/hulalv/material/mapper/MaterialTagRelMapper.java
A	hl-resource-service/src/main/java/com/hulalv/material/service/ChunkUploadService.java
A	hl-resource-service/src/main/java/com/hulalv/material/service/MaterialCategoryPermissionService.java
A	hl-resource-service/src/main/java/com/hulalv/material/service/MaterialCategoryService.java
A	hl-resource-service/src/main/java/com/hulalv/material/service/MaterialRefService.java
A	hl-resource-service/src/main/java/com/hulalv/material/service/MaterialService.java
A	hl-resource-service/src/main/java/com/hulalv/material/service/MaterialTagService.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/BatchDeleteResultVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/CategoryVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/ChunkUploadInitVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/ChunkUploadPartVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/FolderUploadInitVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/MaterialRefVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/MaterialTagVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/MaterialUploadTokenVO.java
A	hl-resource-service/src/main/java/com/hulalv/material/vo/MaterialVO.java
M	hl-resource-service/src/main/java/com/hulalv/resource/ResourceServiceApplication.java
A	hl-resource-service/src/main/java/com/hulalv/transport/config/RestTemplateConfig.java
A	hl-resource-service/src/main/java/com/hulalv/transport/config/VariFlightProperties.java
A	hl-resource-service/src/main/java/com/hulalv/transport/config/WebMvcConfig.java
A	hl-resource-service/src/main/java/com/hulalv/transport/constant/TransportConstants.java
A	hl-resource-service/src/main/java/com/hulalv/transport/controller/AdminTransportController.java
A	hl-resource-service/src/main/java/com/hulalv/transport/controller/InternalTransportController.java
A	hl-resource-service/src/main/java/com/hulalv/transport/interceptor/AdminAuthInterceptor.java
A	hl-resource-service/src/main/java/com/hulalv/transport/service/FlightService.java
A	hl-resource-service/src/main/java/com/hulalv/transport/service/TrainService.java
A	hl-resource-service/src/main/java/com/hulalv/transport/service/VariFlightApiClient.java
A	hl-resource-service/src/main/java/com/hulalv/transport/vo/FlightVO.java
A	hl-resource-service/src/main/java/com/hulalv/transport/vo/TrainStopVO.java
A	hl-resource-service/src/main/java/com/hulalv/transport/vo/TrainVO.java
A	hl-resource-service/src/test/java/com/hulalv/guide/EntityDtoCoverageTest.java
A	hl-resource-service/src/test/java/com/hulalv/guide/controller/AdminGuideArticleControllerTest.java
A	hl-resource-service/src/test/java/com/hulalv/guide/controller/AdminGuideCategoryControllerTest.java
A	hl-resource-service/src/test/java/com/hulalv/guide/controller/AdminGuideTagControllerTest.java
A	hl-resource-service/src/test/java/com/hulalv/guide/controller/InternalWikiControllerTest.java
A	hl-resource-service/src/test/java/com/hulalv/guide/service/GuideArticleServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/guide/service/GuideCategoryServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/guide/service/GuideTagServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/EntityDtoCoverageTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/VoFeignCoverageTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/controller/DictCacheServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/interceptor/AdminAuthInterceptorTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/service/ChunkUploadServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/service/MaterialCategoryPermissionServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/service/MaterialCategoryServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/service/MaterialRefServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/service/MaterialServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/material/service/MaterialTagServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/transport/constant/TransportConstantsTest.java
A	hl-resource-service/src/test/java/com/hulalv/transport/service/FlightServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/transport/service/TrainServiceTest.java
A	hl-resource-service/src/test/java/com/hulalv/transport/service/VariFlightApiClientTest.java
M	hl-user-service/pom.xml
A	hl-user-service/src/main/java/com/hulalv/callback/config/MyBatisPlusConfig.java
A	hl-user-service/src/main/java/com/hulalv/callback/constant/CallbackConstants.java
A	hl-user-service/src/main/java/com/hulalv/callback/controller/MsgAuditCallbackController.java
A	hl-user-service/src/main/java/com/hulalv/callback/controller/WxCallbackController.java
A	hl-user-service/src/main/java/com/hulalv/callback/crypto/WxCryptUtil.java
A	hl-user-service/src/main/java/com/hulalv/callback/feign/UserServiceClient.java
A	hl-user-service/src/main/java/com/hulalv/callback/feign/UserServiceClientFallback.java
A	hl-user-service/src/main/java/com/hulalv/callback/handler/ApprovalEventHandler.java
A	hl-user-service/src/main/java/com/hulalv/callback/handler/ContactChangeHandler.java
A	hl-user-service/src/main/java/com/hulalv/callback/handler/ExternalContactHandler.java
A	hl-user-service/src/main/java/com/hulalv/callback/mq/producer/ApprovalResultProducer.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/ChatDataPullJob.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/ChatMessageService.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/ContactsTokenService.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/InternalChatMessageController.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/MsgAuditController.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/MsgAuditProperties.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/MsgAuditService.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/MsgAuditTokenService.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/WechatGroupService.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/entity/ChatMessage.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/entity/ChatPullCursor.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/entity/WechatGroup.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/mapper/ChatMessageMapper.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/mapper/ChatPullCursorMapper.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/mapper/WechatGroupMapper.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/sdk/FinanceSdkBridge.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/sdk/WeWorkFinanceSdkJna.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/vo/ChatMessageVO.java
A	hl-user-service/src/main/java/com/hulalv/callback/msgaudit/vo/WechatGroupVO.java
A	hl-user-service/src/main/java/com/hulalv/file/config/FileConfig.java
A	hl-user-service/src/main/java/com/hulalv/file/config/MyBatisPlusConfig.java
A	hl-user-service/src/main/java/com/hulalv/file/config/OssConfig.java
A	hl-user-service/src/main/java/com/hulalv/file/config/WebMvcConfig.java
A	hl-user-service/src/main/java/com/hulalv/file/constant/FileConstants.java
A	hl-user-service/src/main/java/com/hulalv/file/controller/FileController.java
A	hl-user-service/src/main/java/com/hulalv/file/controller/InternalFileController.java
A	hl-user-service/src/main/java/com/hulalv/file/controller/MpFileController.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/BatchFileRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/BindRefsRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/ChunkUploadCancelRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/ChunkUploadCompleteRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/ChunkUploadInitRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/FileQueryRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/UnbindRefsRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/UploadConfirmRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/dto/UploadTokenRequest.java
A	hl-user-service/src/main/java/com/hulalv/file/entity/FileInfo.java
A	hl-user-service/src/main/java/com/hulalv/file/entity/FileRef.java
A	hl-user-service/src/main/java/com/hulalv/file/interceptor/AdminAuthInterceptor.java
A	hl-user-service/src/main/java/com/hulalv/file/interceptor/UserAuthInterceptor.java
A	hl-user-service/src/main/java/com/hulalv/file/mapper/FileInfoMapper.java
A	hl-user-service/src/main/java/com/hulalv/file/mapper/FileRefMapper.java
A	hl-user-service/src/main/java/com/hulalv/file/service/ChunkUploadService.java
A	hl-user-service/src/main/java/com/hulalv/file/service/FileRefService.java
A	hl-user-service/src/main/java/com/hulalv/file/service/FileService.java
A	hl-user-service/src/main/java/com/hulalv/file/service/OssService.java
A	hl-user-service/src/main/java/com/hulalv/file/vo/ChunkUploadInitVO.java
A	hl-user-service/src/main/java/com/hulalv/file/vo/ChunkUploadPartVO.java
A	hl-user-service/src/main/java/com/hulalv/file/vo/FileRefVO.java
A	hl-user-service/src/main/java/com/hulalv/file/vo/FileStatsVO.java
A	hl-user-service/src/main/java/com/hulalv/file/vo/FileVO.java
A	hl-user-service/src/main/java/com/hulalv/file/vo/UploadTokenVO.java
A	hl-user-service/src/main/java/com/hulalv/monitor/config/MyBatisPlusConfig.java
A	hl-user-service/src/main/java/com/hulalv/monitor/config/WebMvcConfig.java
A	hl-user-service/src/main/java/com/hulalv/monitor/constant/MonitorConstants.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/ApprovalLogController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/DataRetentionController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/ErrorLogController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/InternalLogController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/LoginLogController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/MysqlMonitorController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/NotificationLogController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/OperationLogController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/RedisMonitorController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/RocketMqMonitorController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/controller/ServiceMonitorController.java
A	hl-user-service/src/main/java/com/hulalv/monitor/entity/AlertRecord.java
A	hl-user-service/src/main/java/com/hulalv/monitor/entity/AlertRule.java
A	hl-user-service/src/main/java/com/hulalv/monitor/entity/ApprovalLog.java
A	hl-user-service/src/main/java/com/hulalv/monitor/entity/ErrorLog.java
A	hl-user-service/src/main/java/com/hulalv/monitor/entity/NotificationLog.java
A	hl-user-service/src/main/java/com/hulalv/monitor/entity/OperationLog.java
A	hl-user-service/src/main/java/com/hulalv/monitor/feign/UserServiceClient.java
A	hl-user-service/src/main/java/com/hulalv/monitor/interceptor/AdminAuthInterceptor.java
A	hl-user-service/src/main/java/com/hulalv/monitor/mapper/AlertRecordMapper.java
A	hl-user-service/src/main/java/com/hulalv/monitor/mapper/AlertRuleMapper.java
A	hl-user-service/src/main/java/com/hulalv/monitor/mapper/ApprovalLogMapper.java
A	hl-user-service/src/main/java/com/hulalv/monitor/mapper/ErrorLogMapper.java
A	hl-user-service/src/main/java/com/hulalv/monitor/mapper/NotificationLogMapper.java
A	hl-user-service/src/main/java/com/hulalv/monitor/mapper/OperationLogMapper.java
A	hl-user-service/src/main/java/com/hulalv/monitor/mq/consumer/LogConsumer.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/ApprovalLogService.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/DataRetentionService.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/ErrorLogService.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/MysqlMonitorService.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/NotificationLogService.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/OperationLogService.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/RedisMonitorService.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/RocketMqMonitorService.java
A	hl-user-service/src/main/java/com/hulalv/monitor/service/ServiceMonitorService.java
A	hl-user-service/src/main/java/com/hulalv/review/config/AsyncConfig.java
A	hl-user-service/src/main/java/com/hulalv/review/config/MyBatisPlusConfig.java
A	hl-user-service/src/main/java/com/hulalv/review/config/WebMvcConfig.java
A	hl-user-service/src/main/java/com/hulalv/review/constant/ReviewConstants.java
A	hl-user-service/src/main/java/com/hulalv/review/controller/AdminReviewController.java
A	hl-user-service/src/main/java/com/hulalv/review/controller/InternalMpReviewController.java
A	hl-user-service/src/main/java/com/hulalv/review/controller/InternalReviewController.java
A	hl-user-service/src/main/java/com/hulalv/review/dto/AdminReplyRequest.java
A	hl-user-service/src/main/java/com/hulalv/review/dto/CreateReviewRequest.java
A	hl-user-service/src/main/java/com/hulalv/review/dto/MpReviewQueryRequest.java
A	hl-user-service/src/main/java/com/hulalv/review/dto/RejectRequest.java
A	hl-user-service/src/main/java/com/hulalv/review/dto/ReviewQueryRequest.java
A	hl-user-service/src/main/java/com/hulalv/review/dto/TargetReviewQueryRequest.java
A	hl-user-service/src/main/java/com/hulalv/review/entity/OrderReview.java
A	hl-user-service/src/main/java/com/hulalv/review/entity/OrderReviewImage.java
A	hl-user-service/src/main/java/com/hulalv/review/entity/OrderReviewVideo.java
A	hl-user-service/src/main/java/com/hulalv/review/entity/ReviewLike.java
A	hl-user-service/src/main/java/com/hulalv/review/feign/OrderReviewFeignClient.java
A	hl-user-service/src/main/java/com/hulalv/review/feign/OrderReviewFeignFallbackFactory.java
A	hl-user-service/src/main/java/com/hulalv/review/feign/ProductReviewFeignClient.java
A	hl-user-service/src/main/java/com/hulalv/review/feign/ProductReviewFeignFallbackFactory.java
A	hl-user-service/src/main/java/com/hulalv/review/feign/UserReviewFeignClient.java
A	hl-user-service/src/main/java/com/hulalv/review/feign/UserReviewFeignFallbackFactory.java
A	hl-user-service/src/main/java/com/hulalv/review/interceptor/AdminAuthInterceptor.java
A	hl-user-service/src/main/java/com/hulalv/review/interceptor/UserAuthInterceptor.java
A	hl-user-service/src/main/java/com/hulalv/review/mapper/OrderReviewImageMapper.java
A	hl-user-service/src/main/java/com/hulalv/review/mapper/OrderReviewMapper.java
A	hl-user-service/src/main/java/com/hulalv/review/mapper/OrderReviewVideoMapper.java
A	hl-user-service/src/main/java/com/hulalv/review/mapper/ReviewLikeMapper.java
A	hl-user-service/src/main/java/com/hulalv/review/service/ContentModerationService.java
A	hl-user-service/src/main/java/com/hulalv/review/service/ReviewService.java
A	hl-user-service/src/main/java/com/hulalv/review/vo/MpReviewVO.java
A	hl-user-service/src/main/java/com/hulalv/review/vo/ReviewListVO.java
A	hl-user-service/src/main/java/com/hulalv/review/vo/ReviewStatsVO.java
A	hl-user-service/src/main/java/com/hulalv/review/vo/ReviewVO.java
A	hl-user-service/src/main/java/com/hulalv/review/vo/ReviewableTargetVO.java
A	hl-user-service/src/main/java/com/hulalv/task/config/AsyncConfig.java
A	hl-user-service/src/main/java/com/hulalv/task/config/BoardInitRunner.java
A	hl-user-service/src/main/java/com/hulalv/task/config/MyBatisPlusConfig.java
A	hl-user-service/src/main/java/com/hulalv/task/config/WebMvcConfig.java
A	hl-user-service/src/main/java/com/hulalv/task/config/WebSocketAuthInterceptor.java
A	hl-user-service/src/main/java/com/hulalv/task/config/WebSocketConfig.java
A	hl-user-service/src/main/java/com/hulalv/task/constant/ActivityAction.java
A	hl-user-service/src/main/java/com/hulalv/task/constant/BoardType.java
A	hl-user-service/src/main/java/com/hulalv/task/constant/MemberRole.java
A	hl-user-service/src/main/java/com/hulalv/task/constant/TaskPriority.java
A	hl-user-service/src/main/java/com/hulalv/task/controller/BoardController.java
A	hl-user-service/src/main/java/com/hulalv/task/controller/TaskController.java
A	hl-user-service/src/main/java/com/hulalv/task/controller/WebSocketDocController.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/AddMembersRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/ChangeStatusRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/CreateBoardRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/CreateCommentRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/CreateStatusRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/CreateSubtaskRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/CreateTaskRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/StatusSortRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/TaskSortRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/UpdateBoardRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/UpdateStatusRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/dto/UpdateTaskRequest.java
A	hl-user-service/src/main/java/com/hulalv/task/entity/BoardMember.java
A	hl-user-service/src/main/java/com/hulalv/task/entity/BoardStatus.java
A	hl-user-service/src/main/java/com/hulalv/task/entity/Task.java
A	hl-user-service/src/main/java/com/hulalv/task/entity/TaskActivity.java
A	hl-user-service/src/main/java/com/hulalv/task/entity/TaskAssignee.java
A	hl-user-service/src/main/java/com/hulalv/task/entity/TaskBoard.java
A	hl-user-service/src/main/java/com/hulalv/task/entity/TaskComment.java
A	hl-user-service/src/main/java/com/hulalv/task/interceptor/AdminAuthInterceptor.java
A	hl-user-service/src/main/java/com/hulalv/task/job/TaskReminderJob.java
A	hl-user-service/src/main/java/com/hulalv/task/mapper/BoardMemberMapper.java
A	hl-user-service/src/main/java/com/hulalv/task/mapper/BoardStatusMapper.java
A	hl-user-service/src/main/java/com/hulalv/task/mapper/TaskActivityMapper.java
A	hl-user-service/src/main/java/com/hulalv/task/mapper/TaskAssigneeMapper.java
A	hl-user-service/src/main/java/com/hulalv/task/mapper/TaskBoardMapper.java
A	hl-user-service/src/main/java/com/hulalv/task/mapper/TaskCommentMapper.java
A	hl-user-service/src/main/java/com/hulalv/task/mapper/TaskMapper.java
A	hl-user-service/src/main/java/com/hulalv/task/service/BoardEventService.java
A	hl-user-service/src/main/java/com/hulalv/task/service/BoardMemberService.java
A	hl-user-service/src/main/java/com/hulalv/task/service/BoardService.java
A	hl-user-service/src/main/java/com/hulalv/task/service/BoardStatusService.java
A	hl-user-service/src/main/java/com/hulalv/task/service/TaskActivityService.java
A	hl-user-service/src/main/java/com/hulalv/task/service/TaskCommentService.java
A	hl-user-service/src/main/java/com/hulalv/task/service/TaskNotificationService.java
A	hl-user-service/src/main/java/com/hulalv/task/service/TaskService.java
A	hl-user-service/src/main/java/com/hulalv/task/vo/AssigneeVO.java
A	hl-user-service/src/main/java/com/hulalv/task/vo/BoardMemberVO.java
A	hl-user-service/src/main/java/com/hulalv/task/vo/BoardStatusVO.java
A	hl-user-service/src/main/java/com/hulalv/task/vo/BoardTasksVO.java
A	hl-user-service/src/main/java/com/hulalv/task/vo/BoardVO.java
A	hl-user-service/src/main/java/com/hulalv/task/vo/SubtaskVO.java
A	hl-user-service/src/main/java/com/hulalv/task/vo/TaskVO.java
A	hl-user-service/src/main/java/com/hulalv/task/vo/TimelineItemVO.java
M	hl-user-service/src/main/java/com/hulalv/user/UserServiceApplication.java
A	hl-user-service/src/main/java/com/tencent/wework/Finance.java
A	hl-user-service/src/test/java/com/hulalv/callback/EntityVoCoverageTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/controller/MsgAuditCallbackControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/controller/WxCallbackControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/crypto/WxCryptUtilTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/feign/UserServiceClientFallbackTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/handler/ApprovalEventHandlerTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/handler/ContactChangeHandlerTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/handler/ExternalContactHandlerTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/mq/producer/ApprovalResultProducerTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/msgaudit/ChatDataPullJobTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/msgaudit/ChatMessageServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/msgaudit/InternalChatMessageControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/callback/msgaudit/MsgAuditTokenServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/file/EntityDtoCoverageTest.java
A	hl-user-service/src/test/java/com/hulalv/file/config/FileConfigTest.java
A	hl-user-service/src/test/java/com/hulalv/file/config/OssConfigTest.java
A	hl-user-service/src/test/java/com/hulalv/file/constant/FileConstantsTest.java
A	hl-user-service/src/test/java/com/hulalv/file/controller/FileControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/file/interceptor/AdminAuthInterceptorTest.java
A	hl-user-service/src/test/java/com/hulalv/file/interceptor/UserAuthInterceptorTest.java
A	hl-user-service/src/test/java/com/hulalv/file/service/ChunkUploadServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/file/service/FileRefServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/file/service/FileServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/file/service/OssServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/EntityCoverageTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/ApprovalLogControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/DataRetentionControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/ErrorLogControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/InternalLogControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/LoginLogControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/MysqlMonitorControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/NotificationLogControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/OperationLogControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/RedisMonitorControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/RocketMqMonitorControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/controller/ServiceMonitorControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/interceptor/AdminAuthInterceptorTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/mq/consumer/LogConsumerTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/ApprovalLogServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/DataRetentionServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/ErrorLogServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/MysqlMonitorServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/NotificationLogServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/OperationLogServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/RedisMonitorServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/RocketMqMonitorServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/monitor/service/ServiceMonitorServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/review/EntityDtoCoverageTest.java
A	hl-user-service/src/test/java/com/hulalv/review/constant/ReviewConstantsTest.java
A	hl-user-service/src/test/java/com/hulalv/review/controller/AdminReviewControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/review/controller/InternalMpReviewControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/review/controller/InternalReviewControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/review/service/ContentModerationServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/review/service/ReviewServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/task/EntityDtoCoverageTest.java
A	hl-user-service/src/test/java/com/hulalv/task/controller/BoardControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/task/controller/TaskControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/task/controller/WebSocketDocControllerTest.java
A	hl-user-service/src/test/java/com/hulalv/task/interceptor/AdminAuthInterceptorTest.java
A	hl-user-service/src/test/java/com/hulalv/task/job/TaskReminderJobTest.java
A	hl-user-service/src/test/java/com/hulalv/task/service/BoardEventServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/task/service/BoardMemberServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/task/service/BoardServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/task/service/BoardStatusServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/task/service/TaskActivityServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/task/service/TaskCommentServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/task/service/TaskNotificationServiceTest.java
A	hl-user-service/src/test/java/com/hulalv/task/service/TaskServiceTest.java
A	mastergo_trip_ended_2_zoom.jpg
M	pom.xml
A	scripts/ai-collab/README.md
A	scripts/ai-collab/agent_client.py
A	scripts/ai-collab/client_requirements.txt
A	scripts/ai-collab/data/ai_collab.db
A	scripts/ai-collab/server/agent_manager.py
A	scripts/ai-collab/server/config.py
A	scripts/ai-collab/server/db.py
A	scripts/ai-collab/server/main.py
A	scripts/ai-collab/server/requirements.txt
A	scripts/ai-collab/server/router_admin.py
A	scripts/ai-collab/server/router_agents.py
A	scripts/ai-collab/server/router_messages.py
A	scripts/ai-collab/server/ws_manager.py
A	scripts/ai-collab/web/admin.html
A	scripts/ai-collab/web/app.js
A	scripts/ai-collab/web/index.html
A	scripts/deploy-panel/deploy-panel.sh
A	scripts/fix_coordinates.py
A	scripts/full_api_test.sh
A	scripts/git-auto-pull.py
A	scripts/git-auto-pull.vbs
A	scripts/import_hotels.py
A	scripts/import_restaurants_json.py
A	scripts/import_scenic.py
A	scripts/import_scenic_json.py
A	sql/contract_scheme.sql
A	sql/fix_notification_templates.sql
A	sql/hulunbuir_scenic_spots_seed.json
A	sql/insurance_scheme_total_days.sql
A	sql/order_surcharge.sql
A	sql/remove_max_group_size.sql
A	sql/remove_unused_pricing_fields.sql
A	tmp-contract-config.yml
A	tmp-dev-contract-updated.yml
A	tmp-dev-contract.yml
A	tmp_insurance_xls.json
A	tmp_login.json
A	tmp_login2.json
A	tmp_mock_pay.sql
A	tmp_order.json
A	tmp_prepay.json
A	tmp_prepay2.json
A	tmp_products.json
A	tmp_quote.json
A	tmp_token.txt
A	trip_ended_2_zoomed.jpg
```
</details>