Compare commits
24 Commits
edbcf2729b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a726b8b7d | ||
| 8f5f998c3a | |||
| 37182d7efb | |||
|
|
e472a3207f | ||
|
|
c0896c199d | ||
|
|
ccfac2a9eb | ||
|
|
84594dda48 | ||
|
|
da144b7c6a | ||
| 306222c55e | |||
|
|
bd3523fd3d | ||
| fa16fec0a0 | |||
|
|
7d5a62f8f2 | ||
|
|
2ac80ae4d0 | ||
|
|
e5e540305d | ||
|
|
16626af8f2 | ||
|
|
70fbd1ad07 | ||
|
|
bd304cee09 | ||
|
|
0118b5a84e | ||
|
|
db39b2092c | ||
|
|
4928db5287 | ||
|
|
f6c3326c4a | ||
|
|
1c1f407d27 | ||
|
|
facff46bb6 | ||
|
|
71589ab13a |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -16,7 +16,7 @@ build/
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
logs
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
|
||||
@@ -29,6 +29,7 @@ dependencies {
|
||||
implementation 'org.springframework.boot:spring-boot-starter-jdbc' // JDBC 支持
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web' // Web MVC
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation' // 参数校验
|
||||
implementation 'org.springframework.boot:spring-boot-starter-aop' // AOP
|
||||
implementation 'org.springframework.boot:spring-boot-starter-mail' // 邮件发送
|
||||
implementation 'com.baomidou:mybatis-plus-boot-starter' // MyBatis Plus
|
||||
implementation 'com.baomidou:mybatis-plus-generator' // 代码生成器
|
||||
|
||||
346
docs/API接口说明-Sirius固件版本管理.md
Normal file
346
docs/API接口说明-Sirius固件版本管理.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# Sirius 固件 API 接口文档
|
||||
|
||||
## 基本信息
|
||||
|
||||
- **Base URL**: `https://api.corewing.com`
|
||||
- **接口前缀**: `/sirius_firmware`
|
||||
|
||||
## 统一响应格式
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": {},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| code | Integer | 状态码(200 成功,500 失败) |
|
||||
| message | String | 提示消息 |
|
||||
| data | Object | 返回数据 |
|
||||
| success | Boolean | 是否成功 |
|
||||
|
||||
## 枚举说明
|
||||
|
||||
### 固件类型(firmwareType)
|
||||
|
||||
| 值 | 说明 |
|
||||
|----|------|
|
||||
| 1 | 高频头 |
|
||||
| 2 | 接收机 |
|
||||
| 3 | 背包 |
|
||||
|
||||
### 协议类型(protocolType)
|
||||
|
||||
| 值 | 说明 |
|
||||
|----|------|
|
||||
| 1 | ELRS |
|
||||
| 2 | CWLink |
|
||||
|
||||
## 固件对象字段说明
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | Integer | 主键ID |
|
||||
| firmwareType | Integer | 固件类型:1-高频头,2-接收机,3-背包 |
|
||||
| protocolType | Integer | 协议类型:1-ELRS,2-CWLink |
|
||||
| versionNumber | String | 版本号,如 v3.0.1 |
|
||||
| fileName | String | 文件名 |
|
||||
| filePath | String | 文件存储路径 |
|
||||
| fileSize | Long | 文件大小(字节) |
|
||||
| md5Hash | String | MD5 校验值 |
|
||||
| releaseNotes | String | 版本更新说明(可能为 null) |
|
||||
| createTime | String | 创建时间 |
|
||||
| updateTime | String | 更新时间 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 查询最新固件版本
|
||||
|
||||
**接口描述:** 根据固件类型和协议类型查询最新版本,用于设备端检查更新。
|
||||
|
||||
**请求方式:** `GET`
|
||||
|
||||
**请求路径:** `/sirius_firmware/latest`
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| firmwareType | Integer | 是 | 固件类型:1-高频头,2-接收机,3-背包 |
|
||||
| protocolType | Integer | 是 | 协议类型:1-ELRS,2-CWLink |
|
||||
|
||||
**请求示例:**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://your-server-host:8080/sirius_firmware/latest?firmwareType=1&protocolType=1"
|
||||
```
|
||||
|
||||
**成功响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"firmwareType": 1,
|
||||
"protocolType": 1,
|
||||
"versionNumber": "v3.0.1",
|
||||
"fileName": "sirius_hf_elrs_v3.0.1.bin",
|
||||
"filePath": "https://oss.corewing.com/sirius_firmware/sirius_hf_elrs_v3.0.1.bin",
|
||||
"fileSize": 1048576,
|
||||
"md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"releaseNotes": "优化信号连接稳定性",
|
||||
"createTime": "2026-03-10 10:30:00",
|
||||
"updateTime": "2026-03-10 10:30:00"
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**失败响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 500,
|
||||
"message": "固件不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 根据固件类型查询版本列表
|
||||
|
||||
**接口描述:** 查询指定固件类型下所有版本,按时间倒序排列。
|
||||
|
||||
**请求方式:** `GET`
|
||||
|
||||
**请求路径:** `/sirius_firmware/type/{firmwareType}`
|
||||
|
||||
**路径参数:**
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| firmwareType | Integer | 是 | 固件类型:1-高频头,2-接收机,3-背包 |
|
||||
|
||||
**请求示例:**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://your-server-host:8080/sirius_firmware/type/1"
|
||||
```
|
||||
|
||||
**成功响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": [
|
||||
{
|
||||
"id": 3,
|
||||
"firmwareType": 1,
|
||||
"protocolType": 2,
|
||||
"versionNumber": "v2.1.0",
|
||||
"fileName": "sirius_hf_cwlink_v2.1.0.bin",
|
||||
"filePath": "https://oss.corewing.com/sirius_firmware/sirius_hf_cwlink_v2.1.0.bin",
|
||||
"fileSize": 2097152,
|
||||
"md5Hash": "098f6bcd4621d373cade4e832627b4f6",
|
||||
"releaseNotes": "新增CWLink协议支持",
|
||||
"createTime": "2026-03-12 14:00:00",
|
||||
"updateTime": "2026-03-12 14:00:00"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"firmwareType": 1,
|
||||
"protocolType": 1,
|
||||
"versionNumber": "v3.0.1",
|
||||
"fileName": "sirius_hf_elrs_v3.0.1.bin",
|
||||
"filePath": "https://oss.corewing.com/sirius_firmware/sirius_hf_elrs_v3.0.1.bin",
|
||||
"fileSize": 1048576,
|
||||
"md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"releaseNotes": "优化信号连接稳定性",
|
||||
"createTime": "2026-03-10 10:30:00",
|
||||
"updateTime": "2026-03-10 10:30:00"
|
||||
}
|
||||
],
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 根据固件类型和协议类型查询版本列表
|
||||
|
||||
**接口描述:** 查询指定固件类型和协议类型下所有版本,按时间倒序排列。
|
||||
|
||||
**请求方式:** `GET`
|
||||
|
||||
**请求路径:** `/sirius_firmware/type/{firmwareType}/protocol/{protocolType}`
|
||||
|
||||
**路径参数:**
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| firmwareType | Integer | 是 | 固件类型:1-高频头,2-接收机,3-背包 |
|
||||
| protocolType | Integer | 是 | 协议类型:1-ELRS,2-CWLink |
|
||||
|
||||
**请求示例:**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://your-server-host:8080/sirius_firmware/type/1/protocol/1"
|
||||
```
|
||||
|
||||
**成功响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": [
|
||||
{
|
||||
"id": 5,
|
||||
"firmwareType": 1,
|
||||
"protocolType": 1,
|
||||
"versionNumber": "v3.0.1",
|
||||
"fileName": "sirius_hf_elrs_v3.0.1.bin",
|
||||
"filePath": "https://oss.corewing.com/sirius_firmware/sirius_hf_elrs_v3.0.1.bin",
|
||||
"fileSize": 1048576,
|
||||
"md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"releaseNotes": "优化信号连接稳定性",
|
||||
"createTime": "2026-03-12 14:00:00",
|
||||
"updateTime": "2026-03-12 14:00:00"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"firmwareType": 1,
|
||||
"protocolType": 1,
|
||||
"versionNumber": "v3.0.0",
|
||||
"fileName": "sirius_hf_elrs_v3.0.0.bin",
|
||||
"filePath": "https://oss.corewing.com/sirius_firmware/sirius_hf_elrs_v3.0.0.bin",
|
||||
"fileSize": 1024000,
|
||||
"md5Hash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
|
||||
"releaseNotes": null,
|
||||
"createTime": "2026-03-01 08:00:00",
|
||||
"updateTime": "2026-03-01 08:00:00"
|
||||
}
|
||||
],
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 查询所有固件
|
||||
|
||||
**接口描述:** 查询所有固件记录。
|
||||
|
||||
**请求方式:** `GET`
|
||||
|
||||
**请求路径:** `/sirius_firmware/list`
|
||||
|
||||
**请求示例:**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://your-server-host:8080/sirius_firmware/list"
|
||||
```
|
||||
|
||||
**成功响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": [
|
||||
{
|
||||
"id": 1,
|
||||
"firmwareType": 1,
|
||||
"protocolType": 1,
|
||||
"versionNumber": "v3.0.1",
|
||||
"fileName": "sirius_hf_elrs_v3.0.1.bin",
|
||||
"filePath": "https://oss.corewing.com/sirius_firmware/sirius_hf_elrs_v3.0.1.bin",
|
||||
"fileSize": 1048576,
|
||||
"md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"releaseNotes": "优化信号连接稳定性",
|
||||
"createTime": "2026-03-10 10:30:00",
|
||||
"updateTime": "2026-03-10 10:30:00"
|
||||
}
|
||||
],
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 根据ID查询固件
|
||||
|
||||
**接口描述:** 根据固件ID查询详情。
|
||||
|
||||
**请求方式:** `GET`
|
||||
|
||||
**请求路径:** `/sirius_firmware/{id}`
|
||||
|
||||
**路径参数:**
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| id | Integer | 是 | 固件ID |
|
||||
|
||||
**请求示例:**
|
||||
|
||||
```bash
|
||||
curl -X GET "http://your-server-host:8080/sirius_firmware/1"
|
||||
```
|
||||
|
||||
**成功响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"firmwareType": 1,
|
||||
"protocolType": 1,
|
||||
"versionNumber": "v3.0.1",
|
||||
"fileName": "sirius_hf_elrs_v3.0.1.bin",
|
||||
"filePath": "https://oss.corewing.com/sirius_firmware/sirius_hf_elrs_v3.0.1.bin",
|
||||
"fileSize": 1048576,
|
||||
"md5Hash": "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"releaseNotes": "优化信号连接稳定性",
|
||||
"createTime": "2026-03-10 10:30:00",
|
||||
"updateTime": "2026-03-10 10:30:00"
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**失败响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 500,
|
||||
"message": "固件不存在",
|
||||
"data": null,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 接口总览
|
||||
|
||||
| 方法 | 路径 | 说明 | 使用场景 |
|
||||
|------|------|------|----------|
|
||||
| GET | `/sirius_firmware/latest?firmwareType=&protocolType=` | 查询最新版本 | 设备端检查更新 |
|
||||
| GET | `/sirius_firmware/type/{firmwareType}` | 按固件类型查版本列表 | 查看某类固件所有版本 |
|
||||
| GET | `/sirius_firmware/type/{firmwareType}/protocol/{protocolType}` | 按类型+协议查版本列表 | 精确筛选版本列表 |
|
||||
| GET | `/sirius_firmware/list` | 查询所有固件 | 管理端展示全部数据 |
|
||||
| GET | `/sirius_firmware/{id}` | 按ID查询固件 | 查看固件详情 |
|
||||
|
||||
---
|
||||
303
docs/backend-api.md
Normal file
303
docs/backend-api.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# Corewing QC 后端接口文档
|
||||
|
||||
> 基础路径: `/api/qc`
|
||||
|
||||
## 通用响应结构
|
||||
|
||||
所有接口统一返回 `Result<T>`:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"data": T,
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---------|---------|---------------------------|
|
||||
| code | Integer | 状态码 |
|
||||
| message | String | 消息内容 |
|
||||
| data | T | 业务数据 |
|
||||
| success | Boolean | 是否成功 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 验证无线板
|
||||
|
||||
验证 BLE MAC 地址对应的无线板是否已在系统中注册。
|
||||
|
||||
- **URL**: `POST /api/qc/wireless/validate-wireless`
|
||||
- **Content-Type**: `application/json`
|
||||
|
||||
### 请求体
|
||||
|
||||
```json
|
||||
{
|
||||
"mac": "AA:BB:CC:DD:EE:FF"
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|--------|------|----------------------------------|
|
||||
| mac | String | 是 | BLE MAC 地址,即设备 SN |
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "验证通过",
|
||||
"data": true,
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
- `data = true` — 设备已注册,允许进行 QC 测试
|
||||
- `data = false` / `success = false` — 设备未注册或验证失败,APP 端将**作废本次测试**
|
||||
|
||||
---
|
||||
|
||||
## 2. 上传测试记录
|
||||
|
||||
上传完整的 QC 测试结果(含所有步骤数据和照片 URL)。
|
||||
|
||||
- **URL**: `POST /api/qc/test/upload`
|
||||
- **Content-Type**: `application/json`
|
||||
|
||||
### 请求体
|
||||
|
||||
```json
|
||||
{
|
||||
"testNo": "WL-20260227-001",
|
||||
"productType": "WIRELESS_BOARD",
|
||||
"sn": "AA:BB:CC:DD:EE:FF",
|
||||
"operatorId": "OP001",
|
||||
"operatorName": "张三",
|
||||
"phoneModel": "Pixel 7",
|
||||
"appVersion": "1.0.0",
|
||||
"status": "PASS",
|
||||
"createTime": "1740000000000",
|
||||
"updatedAt": "1740001000000",
|
||||
"uploadTime": "1740002000000",
|
||||
"steps": [
|
||||
{
|
||||
"stepIndex": 1,
|
||||
"stepName": "BLE连接与特征订阅",
|
||||
"result": "PASS",
|
||||
"dataJson": "{\"deviceName\":\"CoreWing-001\",\"deviceMac\":\"AA:BB:CC:DD:EE:FF\",\"validated\":true}",
|
||||
"duration": 5200,
|
||||
"completedAt": "1740000500000"
|
||||
}
|
||||
],
|
||||
"photoUrls": [
|
||||
"https://qc.corewing.com/photos/xxx.jpg"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|--------------|------------------|------|------------------------------------------------|
|
||||
| testNo | String | 是 | 测试单号,格式: `WL-yyyyMMdd-NNN` 或 `FC-yyyyMMdd-NNN` |
|
||||
| productType | String | 是 | `WIRELESS_BOARD` / `FLIGHT_CONTROLLER` |
|
||||
| sn | String | 是 | 产品序列号(无线板为 BLE MAC 地址) |
|
||||
| operatorId | String | 是 | 测试员 ID |
|
||||
| operatorName | String | 是 | 测试员姓名 |
|
||||
| phoneModel | String | 否 | 测试手机型号 |
|
||||
| appVersion | String | 否 | APP 版本号 |
|
||||
| status | String | 是 | `PASS` / `FAIL` |
|
||||
| createTime | String | 是 | 创建时间(毫秒时间戳字符串) |
|
||||
| updatedAt | String | 否 | 最后更新时间(毫秒时间戳字符串) |
|
||||
| uploadTime | String | 否 | 上传时间(毫秒时间戳字符串) |
|
||||
| steps | StepResultData[] | 是 | 步骤结果数组 |
|
||||
| photoUrls | String[] | 否 | 已上传照片的远程 URL 列表 |
|
||||
|
||||
**StepResultData:**
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|-------------|--------|------|--------------------------------------|
|
||||
| stepIndex | int | 是 | 步骤序号(从 1 开始) |
|
||||
| stepName | String | 是 | 步骤名称 |
|
||||
| result | String | 否 | `PASS` / `FAIL` / null(未完成) |
|
||||
| dataJson | String | 否 | 步骤详细数据 JSON 字符串 |
|
||||
| duration | long | 否 | 步骤耗时(毫秒) |
|
||||
| completedAt | String | 否 | 完成时间(毫秒时间戳字符串) |
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "上传成功",
|
||||
"data": "https://qc.corewing.com/report/WL-20260227-001",
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
- `data` — 测试报告 URL(可为 null)
|
||||
|
||||
---
|
||||
|
||||
## 3. 上传照片
|
||||
|
||||
上传测试步骤关联的照片。
|
||||
|
||||
- **URL**: `POST /api/qc/test/upload-photo`
|
||||
- **Content-Type**: `multipart/form-data`
|
||||
|
||||
### 请求参数
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|--------|---------------|------|------------------|
|
||||
| testNo | String (text) | 是 | 测试单号 |
|
||||
| photo | File | 是 | 照片文件 (JPEG等)|
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "上传成功",
|
||||
"data": {
|
||||
"url": "https://qc.corewing.com/photos/xxx.jpg"
|
||||
},
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 验证 SN
|
||||
|
||||
验证序列号是否有效(飞控板扫码流程使用)。
|
||||
|
||||
- **URL**: `POST /api/qc/test/validate-sn`
|
||||
- **Content-Type**: `application/json`
|
||||
|
||||
### 请求体
|
||||
|
||||
```json
|
||||
{
|
||||
"sn": "FC-SN-20260001"
|
||||
}
|
||||
```
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "SN 有效",
|
||||
"data": true,
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 获取测试配置
|
||||
|
||||
获取指定产品类型的测试参数/阈值。
|
||||
|
||||
- **URL**: `GET /api/qc/config/test-params?productType=WIRELESS_BOARD`
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"success": true,
|
||||
"data": { }
|
||||
}
|
||||
```
|
||||
|
||||
> `data` 结构由后端自定义,APP 当前未使用。
|
||||
|
||||
---
|
||||
|
||||
## 6. 查询 SN 历史记录
|
||||
|
||||
- **URL**: `GET /api/qc/test/history?sn=AA:BB:CC:DD:EE:FF`
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"success": true,
|
||||
"data": { }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 获取测试报告
|
||||
|
||||
- **URL**: `GET /api/qc/test/report?testNo=WL-20260227-001`
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"success": true,
|
||||
"data": "https://qc.corewing.com/report/WL-20260227-001"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 枚举值参考
|
||||
|
||||
### productType(产品类型)
|
||||
|
||||
| 值 | 说明 |
|
||||
|---------------------|--------|
|
||||
| WIRELESS_BOARD | 无线板 |
|
||||
| FLIGHT_CONTROLLER | 飞控板 |
|
||||
|
||||
### status(测试状态)
|
||||
|
||||
| 值 | 说明 |
|
||||
|-------------|----------|
|
||||
| IN_PROGRESS | 进行中 |
|
||||
| PASS | 通过 |
|
||||
| FAIL | 失败 |
|
||||
| UPLOADED | 已上传 |
|
||||
|
||||
### result(步骤结果)
|
||||
|
||||
| 值 | 说明 |
|
||||
|------|------|
|
||||
| PASS | 通过 |
|
||||
| FAIL | 失败 |
|
||||
|
||||
### 无线板测试步骤(7 步)
|
||||
|
||||
| stepIndex | stepName |
|
||||
|-----------|------------------------|
|
||||
| 1 | BLE连接与特征订阅 |
|
||||
| 2 | 安装无线板/外观检查 |
|
||||
| 3 | 供电测试(4.5V) |
|
||||
| 4 | Type-C USB测试 |
|
||||
| 5 | BLE信号质量测试 |
|
||||
| 6 | MAVLink心跳通信测试 |
|
||||
| 7 | 激活/入库 |
|
||||
|
||||
### 飞控板测试步骤(12 步)
|
||||
|
||||
| stepIndex | stepName |
|
||||
|-----------|-----------------|
|
||||
| 1 | USB串口连接 |
|
||||
| 2 | 安装SD卡与装夹 |
|
||||
| 3 | 心跳检测 |
|
||||
| 4 | IMU测试 |
|
||||
| 5 | 气压计测试 |
|
||||
| 6 | GPS模块检测 |
|
||||
| 7 | RC输入测试 |
|
||||
| 8 | ADC接口测试 |
|
||||
| 9 | PWM输出测试 |
|
||||
| 10 | 图传与OSD检查 |
|
||||
| 11 | 参数重置 |
|
||||
| 12 | 数据上传/结束 |
|
||||
116
docs/schema.sql
Normal file
116
docs/schema.sql
Normal file
@@ -0,0 +1,116 @@
|
||||
-- ============================================================
|
||||
-- Corewing QC 后端数据库建表 SQL(MySQL)
|
||||
-- ============================================================
|
||||
|
||||
|
||||
CREATE TABLE `flight_controller` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`sn` VARCHAR(64) NOT NULL COMMENT '序列号',
|
||||
`model` VARCHAR(64) DEFAULT NULL COMMENT '型号',
|
||||
`batch_no` VARCHAR(64) DEFAULT NULL COMMENT '批次号',
|
||||
`status` VARCHAR(32) NOT NULL DEFAULT 'REGISTERED' COMMENT '状态: REGISTERED / QC_PASS / QC_FAIL / ACTIVATED',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_sn` (`sn`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='飞控板设备注册表';
|
||||
|
||||
|
||||
CREATE TABLE `qc_test_record` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`test_no` VARCHAR(32) NOT NULL COMMENT '测试单号,格式: WL-yyyyMMdd-NNN / FC-yyyyMMdd-NNN',
|
||||
`product_type` VARCHAR(32) NOT NULL COMMENT '产品类型: WIRELESS_BOARD / FLIGHT_CONTROLLER',
|
||||
`sn` VARCHAR(64) NOT NULL COMMENT '产品序列号(无线板为 BLE MAC)',
|
||||
`operator_id` VARCHAR(32) NOT NULL COMMENT '测试员 ID',
|
||||
`operator_name` VARCHAR(64) NOT NULL COMMENT '测试员姓名',
|
||||
`phone_model` VARCHAR(64) DEFAULT NULL COMMENT '测试手机型号',
|
||||
`app_version` VARCHAR(16) DEFAULT NULL COMMENT 'APP 版本',
|
||||
`status` VARCHAR(16) NOT NULL COMMENT '测试结果: PASS / FAIL',
|
||||
`create_time` DATETIME NOT NULL COMMENT 'APP 端创建时间',
|
||||
`updated_at` DATETIME DEFAULT NULL COMMENT 'APP 端最后更新时间',
|
||||
`upload_time` DATETIME DEFAULT NULL COMMENT 'APP 端上传时间',
|
||||
`report_url` VARCHAR(512) DEFAULT NULL COMMENT '测试报告 URL',
|
||||
`server_create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '服务端入库时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_test_no` (`test_no`),
|
||||
KEY `idx_sn` (`sn`),
|
||||
KEY `idx_product_type` (`product_type`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='QC 测试记录主表';
|
||||
|
||||
|
||||
CREATE TABLE `qc_step_result` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`test_record_id` BIGINT NOT NULL COMMENT '关联 qc_test_record.id',
|
||||
`step_index` INT NOT NULL COMMENT '步骤序号(从 1 开始)',
|
||||
`step_name` VARCHAR(64) NOT NULL COMMENT '步骤名称',
|
||||
`result` VARCHAR(8) DEFAULT NULL COMMENT '步骤结果: PASS / FAIL / NULL',
|
||||
`data_json` TEXT DEFAULT NULL COMMENT '步骤详细数据 JSON',
|
||||
`duration` BIGINT DEFAULT 0 COMMENT '步骤耗时(毫秒)',
|
||||
`completed_at` DATETIME DEFAULT NULL COMMENT '步骤完成时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_test_record_id` (`test_record_id`),
|
||||
UNIQUE KEY `uk_record_step` (`test_record_id`, `step_index`),
|
||||
CONSTRAINT `fk_step_record` FOREIGN KEY (`test_record_id`)
|
||||
REFERENCES `qc_test_record` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='QC 步骤结果表';
|
||||
|
||||
|
||||
CREATE TABLE `qc_photo` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`test_record_id` BIGINT NOT NULL COMMENT '关联 qc_test_record.id',
|
||||
`test_no` VARCHAR(32) NOT NULL COMMENT '测试单号',
|
||||
`url` VARCHAR(512) NOT NULL COMMENT '照片远程 URL',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_test_no` (`test_no`),
|
||||
CONSTRAINT `fk_photo_record` FOREIGN KEY (`test_record_id`)
|
||||
REFERENCES `qc_test_record` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='QC 测试照片表';
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 固件表
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE `app_aat_version` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`firmware_type` VARCHAR(50) NOT NULL COMMENT '固件类型: lb_main / lb_signal_master / lbPro_main / lbPro_signal_master / lbPro_screen_ui',
|
||||
`firmware_name` VARCHAR(100) NOT NULL COMMENT '固件文件名',
|
||||
`firmware_version` VARCHAR(20) NOT NULL COMMENT '固件版本号',
|
||||
`min_hardware_version` VARCHAR(20) NOT NULL DEFAULT '0.0' COMMENT '最低硬件版本',
|
||||
`download_url` VARCHAR(500) DEFAULT NULL COMMENT '固件下载地址',
|
||||
`firmware_size` BIGINT DEFAULT NULL COMMENT '固件大小(字节)',
|
||||
`firmware_description` TEXT DEFAULT NULL COMMENT '固件描述',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_type_version` (`firmware_type`, `firmware_version`),
|
||||
KEY `idx_firmware_type` (`firmware_type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='AAT固件版本表';
|
||||
|
||||
-- 插入固件数据
|
||||
INSERT INTO `app_aat_version` (`firmware_type`, `firmware_name`, `firmware_version`, `min_hardware_version`)
|
||||
VALUES
|
||||
-- lb_main
|
||||
('lb_main', 'lb_main_2.1.bin', '2.1', '1.0'),
|
||||
-- lb_signal_master
|
||||
('lb_signal_master', 'lbsm_1.1.bin', '1.1', '0.0'),
|
||||
-- lbPro_main
|
||||
('lbPro_main', 'lbPro_main_2.3.bin', '2.3', '0.0'),
|
||||
-- lbPro_signal_master
|
||||
('lbPro_signal_master', 'lbPro_sm_1.4.bin', '1.4', '0.0'),
|
||||
-- lbPro_screen_ui
|
||||
('lbPro_screen_ui', 'lbPro_ui_2.7.tft', '2.7', '0.0');
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 示例数据(可选)
|
||||
-- ============================================================
|
||||
|
||||
-- 注册一批无线板
|
||||
-- INSERT INTO `wireless_board` (`mac`) VALUES
|
||||
-- ('AA:BB:CC:DD:EE:01'),
|
||||
-- ('AA:BB:CC:DD:EE:02'),
|
||||
-- ('AA:BB:CC:DD:EE:03');
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.corewing.app.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 自定义日志注解
|
||||
*
|
||||
**/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface CommonLog {
|
||||
|
||||
/**
|
||||
* 日志的名称,例如:"修改菜单"
|
||||
*/
|
||||
String value() default "未命名";
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.corewing.app.common.aspect;
|
||||
|
||||
import ch.qos.logback.classic.pattern.ClassicConverter;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import com.corewing.app.util.CommonTraceIdUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CustomTraceIdConverter extends ClassicConverter {
|
||||
|
||||
// 使用常量避免重复创建字符串
|
||||
private static final String LEFT_BRACKET = "[";
|
||||
private static final String RIGHT_BRACKET = "]";
|
||||
|
||||
// 缓存StringBuilder以减少对象创建
|
||||
private static final ThreadLocal<StringBuilder> bufferHolder =
|
||||
ThreadLocal.withInitial(() -> new StringBuilder(64));
|
||||
|
||||
@Override
|
||||
public String convert(ILoggingEvent event) {
|
||||
StringBuilder buffer = bufferHolder.get();
|
||||
buffer.setLength(0);
|
||||
String traceId = CommonTraceIdUtil.getTraceId();
|
||||
|
||||
buffer.append(LEFT_BRACKET);
|
||||
if (traceId != null && !traceId.isEmpty()) {
|
||||
buffer.append(traceId);
|
||||
} else {
|
||||
buffer.append(event.getThreadName());
|
||||
}
|
||||
buffer.append(RIGHT_BRACKET);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
104
src/main/java/com/corewing/app/common/aspect/DevLogAop.java
Normal file
104
src/main/java/com/corewing/app/common/aspect/DevLogAop.java
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
package com.corewing.app.common.aspect;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.entity.User;
|
||||
import com.corewing.app.service.UserService;
|
||||
import com.corewing.app.util.DevLogUtil;
|
||||
import com.corewing.app.util.RedisUtil;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 业务日志aop切面
|
||||
*
|
||||
*/
|
||||
@Aspect
|
||||
@Order
|
||||
@Component
|
||||
public class DevLogAop {
|
||||
|
||||
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
/**
|
||||
* 日志切入点
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2020/3/23 17:10
|
||||
*/
|
||||
@Pointcut("@annotation(com.corewing.app.common.annotation.CommonLog)")
|
||||
private void getLogPointCut() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作成功返回结果记录日志
|
||||
*
|
||||
*/
|
||||
@AfterReturning(pointcut = "getLogPointCut()", returning = "result")
|
||||
public void doAfterReturning(JoinPoint joinPoint, Object result) {
|
||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
CommonLog commonLog = method.getAnnotation(CommonLog.class);
|
||||
String userName = "未知";
|
||||
String userId = "-1";
|
||||
try {
|
||||
try {
|
||||
if( StpUtil.isLogin()) {
|
||||
User user = (User) redisUtil.get("APP_" + StpUtil.getLoginId());
|
||||
userName = user.getUsername();
|
||||
userId = user.getId().toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
User user = userService.getById(StpUtil.getLoginIdAsLong());
|
||||
userName = user.getUsername();
|
||||
userId = user.getId().toString();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
// 异步记录日志
|
||||
DevLogUtil.executeOperationLog(commonLog, userName, userId, joinPoint, JSONUtil.toJsonStr(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作发生异常记录日志
|
||||
*
|
||||
*/
|
||||
@AfterThrowing(pointcut = "getLogPointCut()", throwing = "exception")
|
||||
public void doAfterThrowing(JoinPoint joinPoint, Exception exception) {
|
||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
CommonLog commonLog = method.getAnnotation(CommonLog.class);
|
||||
String userName = "未知";
|
||||
String userId = "-1";
|
||||
try {
|
||||
if( StpUtil.isLogin()) {
|
||||
User user = (User) redisUtil.get("APP_" + StpUtil.getLoginId());
|
||||
userName = user.getUsername();
|
||||
userId = user.getId().toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
User user = userService.getById(StpUtil.getLoginIdAsLong());
|
||||
userName = user.getUsername();
|
||||
userId = user.getId().toString();
|
||||
}
|
||||
//异步记录日志
|
||||
DevLogUtil.executeExceptionLog(commonLog, userName, userId, joinPoint, exception);
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@ public class SaTokenConfig implements WebMvcConfigurer {
|
||||
.excludePathPatterns("/user/login", "/user/register", "/user/sendCode", "/user/forgetPassword", "/user/codeLogin")
|
||||
// 排除后台管理登录接口
|
||||
.excludePathPatterns("/sys/user/login")
|
||||
//排除QC接口
|
||||
.excludePathPatterns("/api/qc/**")
|
||||
// 排除反馈接口(支持匿名提交)
|
||||
.excludePathPatterns("/feedback", "/feedback/**")
|
||||
// 排除教程接口(支持匿名查询)
|
||||
@@ -38,12 +40,16 @@ public class SaTokenConfig implements WebMvcConfigurer {
|
||||
.excludePathPatterns("/privacy_policy", "/privacy_policy/**")
|
||||
// 排除固件查询接口(不需要登录)
|
||||
.excludePathPatterns("/firmware/**")
|
||||
// 排除AAT固件版本接口
|
||||
.excludePathPatterns("/aat_version/**")
|
||||
// 排除Sirius固件接口
|
||||
.excludePathPatterns("/sirius_firmware/**")
|
||||
// 排除公共固件
|
||||
.excludePathPatterns("/public_firmware/**")
|
||||
// 排除系统登录页(不需要登录)
|
||||
// .excludePathPatterns("/loading.html", "/admin/login.html")
|
||||
// 排除静态资源
|
||||
.excludePathPatterns("/", "/*.css", "/*.js", "/*.ico", "/static/**", "/assets/**")
|
||||
.excludePathPatterns("/", "/*.html", "/*.css", "/*.js", "/*.ico", "/static/**", "/assets/**")
|
||||
// 排除接口静态资源
|
||||
.excludePathPatterns("/doc.html", "/webjars/**")
|
||||
.excludePathPatterns("/v3/api-docs/swagger-config", "/v3/api-docs/**", "/swagger-resources")
|
||||
@@ -59,6 +65,7 @@ public class SaTokenConfig implements WebMvcConfigurer {
|
||||
.excludePathPatterns("/api/app/access_statistics/accumulate")
|
||||
.excludePathPatterns("/api/app/resource_category/**")
|
||||
.excludePathPatterns("/api/app/resource/**")
|
||||
.excludePathPatterns("/api/app/device/factoryActivation")
|
||||
// 排除模型接口
|
||||
.excludePathPatterns("/model/page", "/model/list", "/model/detail/**", "/model/category/**")
|
||||
// 排除咨询接口
|
||||
|
||||
@@ -12,4 +12,11 @@ public class DeviceActivationRequest {
|
||||
@NotBlank(message = "MAC地址不能为空")
|
||||
private String mac;
|
||||
|
||||
@ApiModelProperty(value = "设备型号", required = true)
|
||||
@NotBlank(message = "设备型号不能为空")
|
||||
private String modelId;
|
||||
|
||||
@ApiModelProperty(value = "时间戳", required = true)
|
||||
private String timestamp;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.corewing.app.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class FirmwareVersionRequest {
|
||||
|
||||
@ApiModelProperty(value = "型号id", required = true)
|
||||
@NotNull(message = "型号不能为空")
|
||||
private Integer modelId;
|
||||
|
||||
@ApiModelProperty(value = "版本号", required = true)
|
||||
@NotNull(message = "版本号不能为空")
|
||||
private String version;
|
||||
|
||||
@ApiModelProperty(value = "固件类型", required = true)
|
||||
@NotNull(message = "固件类型不能为空")
|
||||
private Integer firmwareType;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.corewing.app.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SubmitActivityRequest {
|
||||
|
||||
@ApiModelProperty("活动id")
|
||||
private String activityId;
|
||||
|
||||
/* 创作平台 */
|
||||
@ApiModelProperty("创作平台")
|
||||
private String creationPlatform;
|
||||
|
||||
/* 提交内容 */
|
||||
@ApiModelProperty("提交内容")
|
||||
private String content;
|
||||
}
|
||||
19
src/main/java/com/corewing/app/dto/qc/StepResultData.java
Normal file
19
src/main/java/com/corewing/app/dto/qc/StepResultData.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.corewing.app.dto.qc;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class StepResultData {
|
||||
|
||||
private Integer stepIndex;
|
||||
|
||||
private String stepName;
|
||||
|
||||
private String result;
|
||||
|
||||
private String dataJson;
|
||||
|
||||
private Long duration;
|
||||
|
||||
private String completedAt;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.corewing.app.dto.qc;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class UploadTestRecordRequest {
|
||||
|
||||
private String testNo;
|
||||
|
||||
private String productType;
|
||||
|
||||
private String sn;
|
||||
|
||||
private String operatorId;
|
||||
|
||||
private String operatorName;
|
||||
|
||||
private String phoneModel;
|
||||
|
||||
private String appVersion;
|
||||
|
||||
private String status;
|
||||
|
||||
private String createTime;
|
||||
|
||||
private String updatedAt;
|
||||
|
||||
private String uploadTime;
|
||||
|
||||
private List<StepResultData> steps;
|
||||
|
||||
private List<String> photoUrls;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.corewing.app.dto.qc;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ValidateSnRequest {
|
||||
|
||||
private String sn;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.corewing.app.dto.qc;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ValidateWirelessBoardRequest {
|
||||
private String mac;
|
||||
}
|
||||
74
src/main/java/com/corewing/app/entity/AatVersion.java
Normal file
74
src/main/java/com/corewing/app/entity/AatVersion.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* AAT固件版本实体类
|
||||
*/
|
||||
@Data
|
||||
@TableName("app_aat_version")
|
||||
public class AatVersion implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 固件类型: lb_main / lb_signal_master / lbPro_main / lbPro_signal_master / lbPro_screen_ui
|
||||
*/
|
||||
private String firmwareType;
|
||||
|
||||
/**
|
||||
* 固件文件名
|
||||
*/
|
||||
private String firmwareName;
|
||||
|
||||
/**
|
||||
* 固件版本号
|
||||
*/
|
||||
private String firmwareVersion;
|
||||
|
||||
/**
|
||||
* 最低硬件版本
|
||||
*/
|
||||
private String minHardwareVersion;
|
||||
|
||||
/**
|
||||
* 固件下载地址
|
||||
*/
|
||||
private String downloadUrl;
|
||||
|
||||
/**
|
||||
* 固件大小(字节)
|
||||
*/
|
||||
private Long firmwareSize;
|
||||
|
||||
/**
|
||||
* 固件描述
|
||||
*/
|
||||
private String firmwareDescription;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
71
src/main/java/com/corewing/app/entity/BizActivity.java
Normal file
71
src/main/java/com/corewing/app/entity/BizActivity.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.corewing.app.common.base.CommonEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 活动
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@TableName("biz_activity")
|
||||
public class BizActivity extends CommonEntity {
|
||||
|
||||
/* id */
|
||||
@TableId
|
||||
private String id;
|
||||
|
||||
/* 活动图 */
|
||||
private String thumbnail;
|
||||
|
||||
/* 活动标题 */
|
||||
private String title;
|
||||
|
||||
/* 活动描述 */
|
||||
private String description;
|
||||
|
||||
/* 活动分类 */
|
||||
private String category;
|
||||
|
||||
/* 活动平台 */
|
||||
private String platformCategory;
|
||||
|
||||
/* 活动人数 */
|
||||
private Integer participationCount;
|
||||
|
||||
/* 当前参与人数 */
|
||||
private Integer currentCount;
|
||||
|
||||
/* 活动详情 */
|
||||
private String content;
|
||||
|
||||
/* 活动开始时间 */
|
||||
private Date startTime;
|
||||
|
||||
/* 活动结束时间 */
|
||||
private Date endTime;
|
||||
|
||||
/* 活动状态 */
|
||||
private String status;
|
||||
|
||||
/* 是否开启活动参与人员审核 */
|
||||
private String personnelReview;
|
||||
|
||||
/* 活动排序 */
|
||||
private Integer sortCode;
|
||||
|
||||
/* 备注 */
|
||||
private String remark;
|
||||
|
||||
/* 扩展 */
|
||||
private String extJson;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.corewing.app.common.base.CommonEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@TableName("biz_activity_lottery")
|
||||
public class BizActivityLottery extends CommonEntity {
|
||||
|
||||
/* id */
|
||||
@TableId
|
||||
private String id;
|
||||
|
||||
/* 活动id */
|
||||
private String activityId;
|
||||
|
||||
/* 分类 */
|
||||
private String category;
|
||||
|
||||
/* 用户名 */
|
||||
private String userName;
|
||||
|
||||
/* 用户id */
|
||||
private Long userId;
|
||||
|
||||
/* 状态 */
|
||||
private String status;
|
||||
|
||||
/* 提交内容 */
|
||||
private String content;
|
||||
|
||||
/* 审核时间 */
|
||||
private Date reviewTime;
|
||||
|
||||
/* 创作平台 */
|
||||
private String creationPlatform;
|
||||
|
||||
/* 备注 */
|
||||
private String remark;
|
||||
|
||||
/* 排序 */
|
||||
private Integer sortCode;
|
||||
|
||||
/* 扩展字段 */
|
||||
private String extJson;
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import lombok.EqualsAndHashCode;
|
||||
* 设备表
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
|
||||
@Data
|
||||
@TableName("biz_device")
|
||||
public class BizDevice extends CommonEntity {
|
||||
@@ -28,6 +29,9 @@ public class BizDevice extends CommonEntity {
|
||||
@ApiModelProperty("公布状态")
|
||||
private String publicStatus;
|
||||
|
||||
@ApiModelProperty("型号")
|
||||
private String categoryId;
|
||||
|
||||
@ApiModelProperty("排序")
|
||||
private int sortCode;
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ public class BizDeviceCategory extends CommonEntity {
|
||||
@ApiModelProperty("设备型号缩略图")
|
||||
private String thumbnail;
|
||||
|
||||
@ApiModelProperty("型号id")
|
||||
private Integer modelId;
|
||||
|
||||
@ApiModelProperty("设备型号名称")
|
||||
private String categoryName;
|
||||
|
||||
|
||||
89
src/main/java/com/corewing/app/entity/DevLog.java
Normal file
89
src/main/java/com/corewing/app/entity/DevLog.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 日志实体
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("DEV_LOG")
|
||||
public class DevLog {
|
||||
|
||||
/** id */
|
||||
private String id;
|
||||
|
||||
/** 日志分类 */
|
||||
private String category;
|
||||
|
||||
/** 日志名称 */
|
||||
private String name;
|
||||
|
||||
/** 执行状态 */
|
||||
private String exeStatus;
|
||||
|
||||
/** 具体消息 */
|
||||
private String exeMessage;
|
||||
|
||||
/** 操作ip */
|
||||
private String opIp;
|
||||
|
||||
/** 操作地址 */
|
||||
private String opAddress;
|
||||
|
||||
/** 操作浏览器 */
|
||||
private String opBrowser;
|
||||
|
||||
/** 操作系统 */
|
||||
private String opOs;
|
||||
|
||||
/** 类名称 */
|
||||
private String className;
|
||||
|
||||
/** 方法名称 */
|
||||
private String methodName;
|
||||
|
||||
/** 请求方式 */
|
||||
private String reqMethod;
|
||||
|
||||
/** 请求地址 */
|
||||
private String reqUrl;
|
||||
|
||||
/** 请求参数 */
|
||||
private String paramJson;
|
||||
|
||||
/** 返回结果 */
|
||||
private String resultJson;
|
||||
|
||||
/** 操作时间 */
|
||||
private Date opTime;
|
||||
|
||||
/** 操作人姓名 */
|
||||
private String opUser;
|
||||
|
||||
/** 签名数据 */
|
||||
private String signData;
|
||||
|
||||
/** 创建时间 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private Date createTime;
|
||||
|
||||
/** 创建人 */
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private String createUser;
|
||||
|
||||
/** 更新时间 */
|
||||
@TableField(fill = FieldFill.UPDATE)
|
||||
private Date updateTime;
|
||||
|
||||
/** 更新人 */
|
||||
@TableField(fill = FieldFill.UPDATE)
|
||||
private String updateUser;
|
||||
}
|
||||
@@ -45,6 +45,21 @@ public class Firmware implements Serializable {
|
||||
*/
|
||||
private Integer firmwareType;
|
||||
|
||||
/**
|
||||
* 模型id
|
||||
*/
|
||||
private String modelId;
|
||||
|
||||
/**
|
||||
* 版本校验id
|
||||
*/
|
||||
private Integer versionId;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 固件下载地址
|
||||
*/
|
||||
|
||||
28
src/main/java/com/corewing/app/entity/FlightController.java
Normal file
28
src/main/java/com/corewing/app/entity/FlightController.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("flight_controller")
|
||||
public class FlightController {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String sn;
|
||||
|
||||
private String model;
|
||||
|
||||
private String batchNo;
|
||||
|
||||
private String status;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
24
src/main/java/com/corewing/app/entity/QcPhoto.java
Normal file
24
src/main/java/com/corewing/app/entity/QcPhoto.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("qc_photo")
|
||||
public class QcPhoto {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Long testRecordId;
|
||||
|
||||
private String testNo;
|
||||
|
||||
private String url;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
30
src/main/java/com/corewing/app/entity/QcStepResult.java
Normal file
30
src/main/java/com/corewing/app/entity/QcStepResult.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("qc_step_result")
|
||||
public class QcStepResult {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private Long testRecordId;
|
||||
|
||||
private Integer stepIndex;
|
||||
|
||||
private String stepName;
|
||||
|
||||
private String result;
|
||||
|
||||
private String dataJson;
|
||||
|
||||
private Long duration;
|
||||
|
||||
private LocalDateTime completedAt;
|
||||
}
|
||||
42
src/main/java/com/corewing/app/entity/QcTestRecord.java
Normal file
42
src/main/java/com/corewing/app/entity/QcTestRecord.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@TableName("qc_test_record")
|
||||
public class QcTestRecord {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String testNo;
|
||||
|
||||
private String productType;
|
||||
|
||||
private String sn;
|
||||
|
||||
private String operatorId;
|
||||
|
||||
private String operatorName;
|
||||
|
||||
private String phoneModel;
|
||||
|
||||
private String appVersion;
|
||||
|
||||
private String status;
|
||||
|
||||
private LocalDateTime createTime;
|
||||
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
private LocalDateTime uploadTime;
|
||||
|
||||
private String reportUrl;
|
||||
|
||||
private LocalDateTime serverCreateTime;
|
||||
}
|
||||
79
src/main/java/com/corewing/app/entity/SiriusFirmware.java
Normal file
79
src/main/java/com/corewing/app/entity/SiriusFirmware.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package com.corewing.app.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Sirius固件信息实体类
|
||||
*/
|
||||
@Data
|
||||
@TableName("app_sirius_firmware")
|
||||
public class SiriusFirmware implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 主键ID
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
/**
|
||||
* 固件类型:1-高频头,2-接收机,3-背包
|
||||
*/
|
||||
private Integer firmwareType;
|
||||
|
||||
/**
|
||||
* 协议类型:1-ELRS,2-CWLink
|
||||
*/
|
||||
private Integer protocolType;
|
||||
|
||||
/**
|
||||
* 版本号,如:v3.0.1
|
||||
*/
|
||||
private String versionNumber;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件存储路径
|
||||
*/
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 文件大小(字节)
|
||||
*/
|
||||
private Long fileSize;
|
||||
|
||||
/**
|
||||
* MD5校验值
|
||||
*/
|
||||
private String md5Hash;
|
||||
|
||||
/**
|
||||
* 版本更新说明
|
||||
*/
|
||||
private String releaseNotes;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||
private LocalDateTime updateTime;
|
||||
}
|
||||
29
src/main/java/com/corewing/app/enums/DevLogCategoryEnum.java
Normal file
29
src/main/java/com/corewing/app/enums/DevLogCategoryEnum.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.corewing.app.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 日志分类枚举
|
||||
*
|
||||
**/
|
||||
@Getter
|
||||
public enum DevLogCategoryEnum {
|
||||
|
||||
/** APP操作日志 */
|
||||
APP_OPERATE("APP_OPERATE"),
|
||||
|
||||
/** APP异常日志 */
|
||||
APP_EXCEPTION("APP_EXCEPTION"),
|
||||
|
||||
/** APP登录日志 */
|
||||
APP_LOGIN("APP_LOGIN"),
|
||||
|
||||
/** APP登出日志 */
|
||||
APP_LOGOUT("APP_LOGOUT");
|
||||
|
||||
private final String value;
|
||||
|
||||
DevLogCategoryEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.corewing.app.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum DevLogExeStatusEnum {
|
||||
|
||||
/** 成功 */
|
||||
SUCCESS("SUCCESS"),
|
||||
|
||||
/** 失败 */
|
||||
FAIL("FAIL");
|
||||
|
||||
private final String value;
|
||||
|
||||
DevLogExeStatusEnum(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,11 @@ public class CustomMetaObjectHandler implements MetaObjectHandler {
|
||||
// 兼容 Date 和 LocalDateTime 类型的 createTime 填充
|
||||
fillTimeField(metaObject, CREATE_TIME);
|
||||
} catch (ReflectionException ignored) { }
|
||||
|
||||
try {
|
||||
// 兼容 Date 和 LocalDateTime 类型的 updateTime 填充
|
||||
fillTimeField(metaObject, UPDATE_TIME);
|
||||
} catch (ReflectionException ignored) { }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,10 +5,16 @@ import com.corewing.app.common.Result;
|
||||
import com.corewing.app.util.I18nUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
*/
|
||||
@@ -46,14 +52,39 @@ public class GlobalExceptionHandler {
|
||||
return Result.error(HttpStatus.UNAUTHORIZED.value(), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 @Valid 参数校验异常(RequestBody 参数)
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Result<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
||||
// 获取第一个错误信息
|
||||
String errorMessage = e.getBindingResult().getFieldErrors().stream()
|
||||
.map(FieldError::getDefaultMessage)
|
||||
.collect(Collectors.joining("; "));
|
||||
return Result.error(HttpStatus.BAD_REQUEST.value(), errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 @Validated 参数校验异常(RequestParam/PathVariable 参数)
|
||||
*/
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Result<String> handleConstraintViolationException(ConstraintViolationException e) {
|
||||
// 获取第一个错误信息
|
||||
String errorMessage = e.getConstraintViolations().stream()
|
||||
.map(ConstraintViolation::getMessage)
|
||||
.collect(Collectors.joining("; "));
|
||||
return Result.error(HttpStatus.BAD_REQUEST.value(), errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理其他异常
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
// @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Result<String> handleException(Exception e) {
|
||||
log.error(e.getMessage());
|
||||
log.error("系统异常: ", e);
|
||||
return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(),
|
||||
e.getMessage());
|
||||
I18nUtil.getMessage("error.system"));
|
||||
}
|
||||
}
|
||||
|
||||
13
src/main/java/com/corewing/app/mapper/AatVersionMapper.java
Normal file
13
src/main/java/com/corewing/app/mapper/AatVersionMapper.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.AatVersion;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* AAT固件版本 Mapper 接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface AatVersionMapper extends BaseMapper<AatVersion> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.BizActivityLottery;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BizActivityLotteryMapper extends BaseMapper<BizActivityLottery> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.BizActivity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface BizActivityMapper extends BaseMapper<BizActivity> {
|
||||
}
|
||||
11
src/main/java/com/corewing/app/mapper/DevLogMapper.java
Normal file
11
src/main/java/com/corewing/app/mapper/DevLogMapper.java
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.DevLog;
|
||||
|
||||
/**
|
||||
* 日志Mapper接口
|
||||
**/
|
||||
public interface DevLogMapper extends BaseMapper<DevLog> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.FlightController;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface FlightControllerMapper extends BaseMapper<FlightController> {
|
||||
}
|
||||
9
src/main/java/com/corewing/app/mapper/QcPhotoMapper.java
Normal file
9
src/main/java/com/corewing/app/mapper/QcPhotoMapper.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.QcPhoto;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface QcPhotoMapper extends BaseMapper<QcPhoto> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.QcStepResult;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface QcStepResultMapper extends BaseMapper<QcStepResult> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.QcTestRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface QcTestRecordMapper extends BaseMapper<QcTestRecord> {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.corewing.app.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.corewing.app.entity.SiriusFirmware;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* Sirius固件信息 Mapper 接口
|
||||
*/
|
||||
@Mapper
|
||||
public interface SiriusFirmwareMapper extends BaseMapper<SiriusFirmware> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.entity.AatVersion;
|
||||
import com.corewing.app.service.AatVersionService;
|
||||
import com.corewing.app.util.I18nUtil;
|
||||
import com.corewing.app.util.OSSUploadUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* AAT固件版本 Controller
|
||||
*/
|
||||
@Api(tags = "AAT固件版本接口")
|
||||
@RestController
|
||||
@RequestMapping("/aat_version")
|
||||
public class AppAatVersionController {
|
||||
|
||||
private final AatVersionService aatVersionService;
|
||||
|
||||
public AppAatVersionController(AatVersionService aatVersionService) {
|
||||
this.aatVersionService = aatVersionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有类型的最新固件版本(返回与原始JSON结构一致)
|
||||
*/
|
||||
@CommonLog("查询所有AAT最新固件版本")
|
||||
@ApiOperation("查询所有AAT最新固件版本")
|
||||
@GetMapping("/latest")
|
||||
public Result<Map<String, Object>> getAllLatestVersions() {
|
||||
return Result.success(aatVersionService.getAllLatestVersions());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据固件类型查询最新版本
|
||||
*/
|
||||
@CommonLog("根据类型查询AAT最新固件版本")
|
||||
@ApiOperation("根据类型查询AAT最新固件版本")
|
||||
@GetMapping("/latest/{firmwareType}")
|
||||
public Result<AatVersion> getLatestByType(@PathVariable String firmwareType) {
|
||||
AatVersion version = aatVersionService.getLatestByType(firmwareType);
|
||||
if (version != null) {
|
||||
return Result.success(version);
|
||||
}
|
||||
return Result.error(I18nUtil.getMessage("firmware.not.found"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据固件类型查询版本列表
|
||||
*/
|
||||
@CommonLog("根据类型查询AAT固件版本列表")
|
||||
@ApiOperation("根据类型查询AAT固件版本列表")
|
||||
@GetMapping("/type/{firmwareType}")
|
||||
public Result<List<AatVersion>> listByType(@PathVariable String firmwareType) {
|
||||
QueryWrapper<AatVersion> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("firmware_type", firmwareType);
|
||||
wrapper.orderByDesc("create_time");
|
||||
return Result.success(aatVersionService.list(wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询固件版本列表
|
||||
*/
|
||||
@CommonLog("分页查询AAT固件版本列表")
|
||||
@ApiOperation("分页查询AAT固件版本列表")
|
||||
@GetMapping("/page")
|
||||
public Result<IPage<AatVersion>> page(
|
||||
@RequestParam(defaultValue = "1") Long current,
|
||||
@RequestParam(defaultValue = "10") Long size,
|
||||
@RequestParam(required = false) String firmwareType,
|
||||
@RequestParam(required = false) String firmwareName) {
|
||||
|
||||
Page<AatVersion> page = new Page<>(current, size);
|
||||
QueryWrapper<AatVersion> wrapper = new QueryWrapper<>();
|
||||
|
||||
if (StringUtils.hasText(firmwareType)) {
|
||||
wrapper.eq("firmware_type", firmwareType);
|
||||
}
|
||||
if (StringUtils.hasText(firmwareName)) {
|
||||
wrapper.like("firmware_name", firmwareName);
|
||||
}
|
||||
wrapper.orderByDesc("create_time");
|
||||
|
||||
return Result.success(aatVersionService.page(page, wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有固件版本
|
||||
*/
|
||||
@CommonLog("查询所有AAT固件版本")
|
||||
@ApiOperation("查询所有AAT固件版本")
|
||||
@GetMapping("/list")
|
||||
public Result<List<AatVersion>> list() {
|
||||
return Result.success(aatVersionService.list());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询固件版本
|
||||
*/
|
||||
@CommonLog("根据ID查询AAT固件版本")
|
||||
@ApiOperation("根据ID查询AAT固件版本")
|
||||
@GetMapping("/{id}")
|
||||
public Result<AatVersion> getById(@PathVariable Long id) {
|
||||
AatVersion version = aatVersionService.getById(id);
|
||||
if (version != null) {
|
||||
return Result.success(version);
|
||||
}
|
||||
return Result.error(I18nUtil.getMessage("firmware.not.found"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增固件版本
|
||||
*/
|
||||
@CommonLog("新增AAT固件版本")
|
||||
@ApiOperation("新增AAT固件版本")
|
||||
@PostMapping
|
||||
public Result<AatVersion> add(@RequestBody AatVersion aatVersion) {
|
||||
boolean saved = aatVersionService.save(aatVersion);
|
||||
return saved ? Result.success(aatVersion) : Result.error();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改固件版本
|
||||
*/
|
||||
@CommonLog("修改AAT固件版本")
|
||||
@ApiOperation("修改AAT固件版本")
|
||||
@PutMapping
|
||||
public Result<Void> update(@RequestBody AatVersion aatVersion) {
|
||||
return Result.isBool(aatVersionService.updateById(aatVersion));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除固件版本
|
||||
*/
|
||||
@CommonLog("删除AAT固件版本")
|
||||
@ApiOperation("删除AAT固件版本")
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<Void> delete(@PathVariable Long id) {
|
||||
AatVersion version = aatVersionService.getById(id);
|
||||
if (version == null) {
|
||||
return Result.error(I18nUtil.getMessage("firmware.not.found"));
|
||||
}
|
||||
// 删除OSS上的文件
|
||||
if (StringUtils.hasText(version.getDownloadUrl())) {
|
||||
String objectName = version.getDownloadUrl().replace("https://oss.corewing.com/", "");
|
||||
OSSUploadUtil.deleteFile(objectName);
|
||||
}
|
||||
return Result.isBool(aatVersionService.removeById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传固件文件
|
||||
*/
|
||||
@CommonLog("上传AAT固件文件")
|
||||
@ApiOperation("上传AAT固件文件")
|
||||
@PostMapping("/upload/{id}")
|
||||
public Result<AatVersion> upload(@PathVariable Long id, @RequestParam("file") MultipartFile file) {
|
||||
AatVersion version = aatVersionService.getById(id);
|
||||
if (version == null) {
|
||||
return Result.error(I18nUtil.getMessage("firmware.not.found"));
|
||||
}
|
||||
try {
|
||||
String objectName = "aat_firmware/" + file.getOriginalFilename();
|
||||
String downloadUrl = OSSUploadUtil.uploadFile(file.getInputStream(), objectName);
|
||||
version.setDownloadUrl(downloadUrl);
|
||||
version.setFirmwareSize(file.getSize());
|
||||
version.setFirmwareName(file.getOriginalFilename());
|
||||
aatVersionService.updateById(version);
|
||||
return Result.success(version);
|
||||
} catch (IOException e) {
|
||||
return Result.error("上传失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.dto.SubmitActivityRequest;
|
||||
import com.corewing.app.service.BizActivityLotteryService;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Api(tags = "活动控制")
|
||||
@Controller
|
||||
@RequestMapping("/api/app/activity")
|
||||
public class AppActivityController {
|
||||
|
||||
@Resource
|
||||
private BizActivityLotteryService bizActivityLotteryService;
|
||||
|
||||
/**
|
||||
* 活动参与地址
|
||||
* @param activityId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/eventVenue/{activityId}")
|
||||
public String eventVenue(@PathVariable String activityId) {
|
||||
return "/activity/eventVenue";
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交活动
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/submitActivity")
|
||||
@ResponseBody
|
||||
public Result<String> submitActivity(SubmitActivityRequest submitActivityRequest) {
|
||||
return Result.isBool(bizActivityLotteryService.submitActivity(submitActivityRequest));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.entity.ContactMsg;
|
||||
import com.corewing.app.service.ContactMsgService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -20,6 +21,7 @@ public class AppContactMsgController {
|
||||
@Resource
|
||||
private ContactMsgService contactMsgService;
|
||||
|
||||
@CommonLog("反馈消息")
|
||||
@ApiOperation("消息保存接口")
|
||||
@PostMapping("/save")
|
||||
public Result<String> save(@RequestBody ContactMsg contactMsg) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.DeviceActivationRequest;
|
||||
import com.corewing.app.service.BizDeviceActivationService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -23,11 +24,19 @@ public class AppDeviceController {
|
||||
@Resource
|
||||
private BizDeviceActivationService activationService;
|
||||
|
||||
@CommonLog("激活设备")
|
||||
@ApiOperation("激活接口")
|
||||
@PostMapping("activation")
|
||||
public Result<Boolean> activation(@RequestBody DeviceActivationRequest deviceActivationRequest) {
|
||||
return Result.success(activationService.activation(deviceActivationRequest));
|
||||
}
|
||||
|
||||
@CommonLog("工厂激活设备")
|
||||
@ApiOperation("工厂激活设备")
|
||||
@PostMapping("factoryActivation")
|
||||
public Result<Boolean> factoryActivation(@RequestBody DeviceActivationRequest deviceActivationRequest) {
|
||||
return Result.success(activationService.factoryActivation(deviceActivationRequest));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.FeedbackRequest;
|
||||
import com.corewing.app.entity.Feedback;
|
||||
import com.corewing.app.service.FeedbackService;
|
||||
@@ -39,6 +40,7 @@ public class AppFeedbackController {
|
||||
/**
|
||||
* 创建反馈(支持匿名提交)
|
||||
*/
|
||||
@CommonLog("创建反馈")
|
||||
@ApiOperation("创建反馈")
|
||||
@PostMapping
|
||||
public Result<String> create(@RequestBody FeedbackRequest request, HttpServletRequest httpRequest) {
|
||||
@@ -81,6 +83,7 @@ public class AppFeedbackController {
|
||||
/**
|
||||
* 查询当前用户的反馈列表
|
||||
*/
|
||||
@CommonLog("查询反馈列表")
|
||||
@ApiOperation("查询当前用户的反馈列表")
|
||||
@GetMapping("/my")
|
||||
public Result<List<Feedback>> getMyFeedbackList() {
|
||||
@@ -97,6 +100,7 @@ public class AppFeedbackController {
|
||||
/**
|
||||
* 根据ID查询反馈详情
|
||||
*/
|
||||
@CommonLog("查询反馈详情")
|
||||
@ApiOperation("根据id查询反馈详情")
|
||||
@GetMapping("/{id}")
|
||||
public Result<Feedback> getById(@PathVariable Long id) {
|
||||
@@ -120,6 +124,7 @@ public class AppFeedbackController {
|
||||
* @param feedbackType 问题类型(可选)
|
||||
* @param status 状态(可选)
|
||||
*/
|
||||
@CommonLog("查询反馈列表分页")
|
||||
@ApiOperation("分页查询反馈列表")
|
||||
@GetMapping("/page")
|
||||
public Result<IPage<Feedback>> getPageList(
|
||||
@@ -140,6 +145,7 @@ public class AppFeedbackController {
|
||||
/**
|
||||
* 更新反馈状态
|
||||
*/
|
||||
@CommonLog("更新反馈状态")
|
||||
@ApiOperation("更新反馈状态")
|
||||
@PutMapping("/{id}/status")
|
||||
public Result<String> updateStatus(@PathVariable Long id, @RequestParam Integer status) {
|
||||
@@ -157,6 +163,7 @@ public class AppFeedbackController {
|
||||
/**
|
||||
* 删除反馈
|
||||
*/
|
||||
@CommonLog("删除反馈")
|
||||
@ApiOperation("删除反馈")
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<String> delete(@PathVariable Long id) {
|
||||
@@ -174,6 +181,7 @@ public class AppFeedbackController {
|
||||
/**
|
||||
* 测试钉钉推送
|
||||
*/
|
||||
@CommonLog("测试钉钉推送")
|
||||
@ApiOperation("测试钉钉推送")
|
||||
@GetMapping("/test-dingtalk")
|
||||
public Result<String> testDingTalk() {
|
||||
@@ -196,6 +204,7 @@ public class AppFeedbackController {
|
||||
/**
|
||||
* 发送反馈信息到钉钉
|
||||
*/
|
||||
@CommonLog("发送反馈信息到钉钉")
|
||||
@ApiOperation("发送反馈信息到钉钉")
|
||||
private void sendFeedbackToDingTalk(Feedback feedback, String submitIp, String submitRegion) {
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.entity.FeedbackLog;
|
||||
import com.corewing.app.service.FeedbackLogService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -28,6 +29,7 @@ public class AppFeedbackLogController {
|
||||
* @param feedbackLog
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("上传反馈日志")
|
||||
@ApiOperation("上传日志")
|
||||
@PostMapping("/uploadFeedbackLog")
|
||||
public Result<String> uploadFeedbackLog(MultipartFile file, FeedbackLog feedbackLog) {
|
||||
|
||||
@@ -1,34 +1,46 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.FirmwareVersionRequest;
|
||||
import com.corewing.app.entity.BizDeviceCategory;
|
||||
import com.corewing.app.entity.Firmware;
|
||||
import com.corewing.app.service.BizDeviceCategoryService;
|
||||
import com.corewing.app.service.FirmwareService;
|
||||
import com.corewing.app.util.I18nUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 固件 Controller
|
||||
*/
|
||||
@Api(tags = "固件接口")
|
||||
@RestController
|
||||
@RequestMapping("/firmware")
|
||||
@Validated
|
||||
public class AppFirmwareController {
|
||||
|
||||
private final FirmwareService firmwareService;
|
||||
@Resource
|
||||
private FirmwareService firmwareService;
|
||||
|
||||
public AppFirmwareController(FirmwareService firmwareService) {
|
||||
this.firmwareService = firmwareService;
|
||||
}
|
||||
@Resource
|
||||
private BizDeviceCategoryService bizDeviceCategoryService;
|
||||
|
||||
/**
|
||||
* 根据ID查询固件
|
||||
*/
|
||||
@CommonLog("根据id查询固件")
|
||||
@ApiOperation("根据id查询固件")
|
||||
@GetMapping("/{id}")
|
||||
public Result<Firmware> getById(@PathVariable Long id) {
|
||||
@@ -47,6 +59,7 @@ public class AppFirmwareController {
|
||||
* @param firmwareName 固件名称(可选)
|
||||
* @param firmwareType 固件类型(可选)
|
||||
*/
|
||||
@CommonLog("分页查询固件列表")
|
||||
@ApiOperation("分页查询固件列表")
|
||||
@GetMapping("/page")
|
||||
public Result<IPage<Firmware>> page(
|
||||
@@ -78,21 +91,23 @@ public class AppFirmwareController {
|
||||
/**
|
||||
* 查询所有固件
|
||||
*/
|
||||
@CommonLog("查询所有固件集合")
|
||||
@ApiOperation("查询所有固件集合")
|
||||
@GetMapping("/list")
|
||||
public Result<java.util.List<Firmware>> list() {
|
||||
java.util.List<Firmware> list = firmwareService.list();
|
||||
public Result<List<Firmware>> list() {
|
||||
List<Firmware> list = firmwareService.list();
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型查询固件版本
|
||||
* 根据类型查询固件版本 【兼容旧版APP】
|
||||
*
|
||||
* @param firmwareType 固件类型
|
||||
*/
|
||||
@CommonLog("根据类型查询固件版本")
|
||||
@ApiOperation("根据类型查询固件版本")
|
||||
@GetMapping("/type/{firmwareType}")
|
||||
public Result<java.util.List<Firmware>> listByType(@PathVariable Integer firmwareType) {
|
||||
public Result<List<Firmware>> listByType(@PathVariable Integer firmwareType) {
|
||||
if (firmwareType == null) {
|
||||
return Result.error(I18nUtil.getMessage("firmware.type.required"));
|
||||
}
|
||||
@@ -102,7 +117,49 @@ public class AppFirmwareController {
|
||||
// 按版本号或创建时间倒序排列,最新版本在前
|
||||
wrapper.orderByDesc("create_time");
|
||||
|
||||
java.util.List<Firmware> list = firmwareService.list(wrapper);
|
||||
List<Firmware> list = firmwareService.list(wrapper);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型查询固件版本 【兼容新版APP】
|
||||
*
|
||||
* @param firmwareType 固件类型
|
||||
*/
|
||||
@CommonLog("根据类型,型号,当前版本查询固件版本")
|
||||
@ApiOperation("根据类型,当前版本查询固件版本")
|
||||
@GetMapping("/type/{firmwareType}/{modelId}/{softwareVersion}")
|
||||
public Result<List<Firmware>> listByType(@PathVariable Integer firmwareType, @PathVariable Integer modelId, @PathVariable Integer softwareVersion) {
|
||||
if (firmwareType == null && modelId == null) {
|
||||
return Result.error(I18nUtil.getMessage("firmware.type.or.model.required"));
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<BizDeviceCategory> categoryQueryWrapper = new LambdaQueryWrapper<>();
|
||||
categoryQueryWrapper.eq(BizDeviceCategory::getModelId, modelId);
|
||||
BizDeviceCategory bizDeviceCategory = bizDeviceCategoryService.getOne(categoryQueryWrapper);
|
||||
if(bizDeviceCategory == null) {
|
||||
return Result.error(I18nUtil.getMessage("firmware.device.not.found"));
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<Firmware> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(Firmware::getFirmwareType, firmwareType);
|
||||
wrapper.eq(Firmware::getModelId, bizDeviceCategory.getId());
|
||||
wrapper.ge(Firmware::getVersionId, softwareVersion);
|
||||
// 按版本号或创建时间倒序排列,最新版本在前
|
||||
wrapper.orderByDesc(Firmware::getCreateTime);
|
||||
|
||||
List<Firmware> list = firmwareService.list(wrapper);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验是否存在新固件
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("校验是否存在新固件")
|
||||
@ApiOperation("校验是否存在新固件")
|
||||
@PostMapping("/checkVersion")
|
||||
public Result<Firmware> checkVersion(@RequestBody @Valid FirmwareVersionRequest firmwareVersionRequest) {
|
||||
return Result.success(firmwareService.checkVersion(firmwareVersionRequest));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.corewing.app.modules.app;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.AppModel.*;
|
||||
import com.corewing.app.entity.AppModel;
|
||||
import com.corewing.app.entity.AppModelCategory;
|
||||
@@ -37,6 +38,7 @@ public class AppModelController {
|
||||
* @param modelPageRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("模型数据分页")
|
||||
@ApiOperation("模型数据分页")
|
||||
@GetMapping("/page")
|
||||
public Result<Page<AppModel>> page(ModelPageRequest modelPageRequest) {
|
||||
@@ -48,6 +50,7 @@ public class AppModelController {
|
||||
* @param modelListRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("模型数据集合")
|
||||
@ApiOperation("模型数据集合")
|
||||
@GetMapping("/list")
|
||||
public Result<List<AppModel>> list(ModelListRequest modelListRequest) {
|
||||
@@ -60,6 +63,7 @@ public class AppModelController {
|
||||
* @param modelCategoryPageRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("模型分类数据分页")
|
||||
@ApiOperation("模型分类数据分页")
|
||||
@GetMapping("/category/page")
|
||||
public Result<Page<AppModelCategory>> categoryPage(ModelCategoryPageRequest modelCategoryPageRequest) {
|
||||
@@ -71,6 +75,7 @@ public class AppModelController {
|
||||
* @param modelCategoryListRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("模型分类数据集合")
|
||||
@ApiOperation("模型分类数据集合")
|
||||
@GetMapping("/category/list")
|
||||
public Result<List<AppModelCategory>> categoryList(ModelCategoryListRequest modelCategoryListRequest) {
|
||||
@@ -82,6 +87,7 @@ public class AppModelController {
|
||||
* @param modelCategoryListRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("模型分类树形集合")
|
||||
@ApiOperation("模型分类树形集合")
|
||||
@GetMapping("/category/tree")
|
||||
public Result<List<Tree<String>>> categoryTree(ModelCategoryListRequest modelCategoryListRequest) {
|
||||
@@ -93,6 +99,7 @@ public class AppModelController {
|
||||
* @param modelFavoriteRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("收藏模型")
|
||||
@ApiOperation("收藏模型")
|
||||
@PostMapping("/favorite")
|
||||
public Result<String> favorite(@RequestBody @Valid ModelFavoriteRequest modelFavoriteRequest) {
|
||||
@@ -104,6 +111,7 @@ public class AppModelController {
|
||||
* @param modelDownloadRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("增加模型下载记录")
|
||||
@ApiOperation("增加模型下载记录")
|
||||
@PostMapping("/download")
|
||||
public Result<String> download(@RequestBody @Valid ModelDownloadRequest modelDownloadRequest) {
|
||||
@@ -115,6 +123,7 @@ public class AppModelController {
|
||||
* @param modelLikeRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("点赞模型")
|
||||
@ApiOperation("点赞模型")
|
||||
@PostMapping("/like")
|
||||
public Result<String> like(@RequestBody @Valid ModelLikeRequest modelLikeRequest) {
|
||||
@@ -125,6 +134,7 @@ public class AppModelController {
|
||||
* 模型详情
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("模型详情")
|
||||
@ApiOperation("模型详情")
|
||||
@GetMapping("/detail/{modelId}")
|
||||
public Result<AppModel> detail(@PathVariable String modelId) {
|
||||
@@ -136,6 +146,7 @@ public class AppModelController {
|
||||
* @param modelCreateRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("创建模型")
|
||||
@ApiOperation("创建模型")
|
||||
@PostMapping("/create")
|
||||
public Result<String> create(@Valid ModelCreateRequest modelCreateRequest) {
|
||||
@@ -147,6 +158,7 @@ public class AppModelController {
|
||||
* @param modelIdRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("提交模型审核")
|
||||
@ApiOperation("提交模型审核")
|
||||
@PostMapping("/audit")
|
||||
public Result<String> audit(@RequestBody @Valid ModelIdRequest modelIdRequest) {
|
||||
@@ -158,6 +170,7 @@ public class AppModelController {
|
||||
* @param modelFavoriteListRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("收藏模型列表")
|
||||
@ApiOperation("收藏模型列表")
|
||||
@GetMapping("/favorite/list")
|
||||
public Result<List<AppModel>> favoriteList(ModelFavoriteListRequest modelFavoriteListRequest) {
|
||||
@@ -169,7 +182,8 @@ public class AppModelController {
|
||||
* @param modelFavoritePageRequest
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation("收藏模型分页列表")
|
||||
@CommonLog("收藏模型分页列表分页")
|
||||
@ApiOperation("收藏模型分页列表分页")
|
||||
@GetMapping("/favorite/page")
|
||||
public Result<Page<AppModel>> favoritePage(ModelFavoritePageRequest modelFavoritePageRequest) {
|
||||
return Result.success(appModelService.favoritePage(modelFavoritePageRequest));
|
||||
@@ -180,6 +194,7 @@ public class AppModelController {
|
||||
* @param modelIdRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("模型下架")
|
||||
@ApiOperation("模型下架")
|
||||
@PostMapping("/delisted")
|
||||
public Result<String> delisted(@RequestBody @Valid ModelIdRequest modelIdRequest) {
|
||||
@@ -192,6 +207,7 @@ public class AppModelController {
|
||||
* @param modelDownloadLogListRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("模型下载记录列表")
|
||||
@ApiOperation("模型下载记录列表")
|
||||
@GetMapping("/download_log/list")
|
||||
public Result<List<AppModel>> downloadLogList(ModelDownloadLogListRequest modelDownloadLogListRequest) {
|
||||
@@ -203,7 +219,8 @@ public class AppModelController {
|
||||
* @param modelDownloadLogPageRequest
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation("模型下载记录分页列表")
|
||||
@CommonLog("模型下载记录分页列表分页")
|
||||
@ApiOperation("模型下载记录分页列表分页")
|
||||
@GetMapping("/download_log/page")
|
||||
public Result<Page<AppModel>> downloadLogPage(ModelDownloadLogPageRequest modelDownloadLogPageRequest) {
|
||||
return Result.success(appModelService.downloadLogPage(modelDownloadLogPageRequest));
|
||||
@@ -213,6 +230,7 @@ public class AppModelController {
|
||||
* 删除模型
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("删除模型")
|
||||
@ApiOperation("删除模型")
|
||||
@DeleteMapping("/delete/{id}")
|
||||
public Result<String> delete(@PathVariable String id) {
|
||||
|
||||
@@ -4,18 +4,22 @@ import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.CreateParamRequest;
|
||||
import com.corewing.app.dto.UpdateParamRequest;
|
||||
import com.corewing.app.entity.ParamsCenter;
|
||||
import com.corewing.app.service.ParamsCenterService;
|
||||
import com.corewing.app.util.I18nUtil;
|
||||
import com.corewing.app.util.RedisUtil;
|
||||
import com.corewing.app.vo.ParamsCenterVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 参数配置中心 Controller
|
||||
@@ -25,15 +29,16 @@ import java.util.List;
|
||||
@RequestMapping("/params")
|
||||
public class AppParamsCenterController {
|
||||
|
||||
private final ParamsCenterService paramsService;
|
||||
@Resource
|
||||
private ParamsCenterService paramsService;
|
||||
|
||||
public AppParamsCenterController(ParamsCenterService paramsService) {
|
||||
this.paramsService = paramsService;
|
||||
}
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
/**
|
||||
* 创建参数配置
|
||||
*/
|
||||
@CommonLog("创建参数配置接口")
|
||||
@ApiOperation("创建参数配置接口")
|
||||
@PostMapping
|
||||
public Result<String> create(@Valid @RequestBody CreateParamRequest request) {
|
||||
@@ -66,6 +71,7 @@ public class AppParamsCenterController {
|
||||
/**
|
||||
* 更新参数配置
|
||||
*/
|
||||
@CommonLog("更新参数配置接口")
|
||||
@ApiOperation("更新参数配置接口")
|
||||
@PutMapping
|
||||
public Result<String> update(@Valid @RequestBody UpdateParamRequest request) {
|
||||
@@ -104,6 +110,7 @@ public class AppParamsCenterController {
|
||||
/**
|
||||
* 删除参数配置
|
||||
*/
|
||||
@CommonLog("根据id删除参数配置")
|
||||
@ApiOperation("根据id删除参数配置")
|
||||
@DeleteMapping("/{id}")
|
||||
public Result<String> delete(@PathVariable Long id) {
|
||||
@@ -132,6 +139,7 @@ public class AppParamsCenterController {
|
||||
/**
|
||||
* 根据ID查询参数配置
|
||||
*/
|
||||
@CommonLog("根据id查询参数配置")
|
||||
@ApiOperation("根据id查询参数配置")
|
||||
@GetMapping("/{id}")
|
||||
public Result<ParamsCenterVO> getById(@PathVariable Long id) {
|
||||
@@ -155,6 +163,7 @@ public class AppParamsCenterController {
|
||||
/**
|
||||
* 查询所有公共参数列表(公开接口,支持飞控型号过滤)
|
||||
*/
|
||||
@CommonLog("获取所有公共参数集合")
|
||||
@ApiOperation("获取所有公共参数集合")
|
||||
@GetMapping("/all/list")
|
||||
public Result<List<ParamsCenterVO>> listAll(@RequestParam(required = false) String fcModel) {
|
||||
@@ -169,6 +178,7 @@ public class AppParamsCenterController {
|
||||
/**
|
||||
* 查询当前用户的参数列表(支持飞控型号过滤)
|
||||
*/
|
||||
@CommonLog("获取当前用户的参数列表")
|
||||
@ApiOperation("获取当前用户的参数列表")
|
||||
@GetMapping("/my/list")
|
||||
public Result<List<ParamsCenterVO>> listMy(@RequestParam(required = false) String fcModel) {
|
||||
@@ -184,6 +194,7 @@ public class AppParamsCenterController {
|
||||
/**
|
||||
* 分页查询所有参数列表(公开接口,支持飞控型号过滤)
|
||||
*/
|
||||
@CommonLog("分页查询所有公共参数集合")
|
||||
@ApiOperation("分页查询所有公共参数集合")
|
||||
@GetMapping("/all/page")
|
||||
public Result<IPage<ParamsCenterVO>> pageAll(
|
||||
@@ -202,7 +213,8 @@ public class AppParamsCenterController {
|
||||
/**
|
||||
* 分页查询当前用户的参数列表(支持飞控型号过滤)
|
||||
*/
|
||||
@ApiOperation("分页查询当前用户参数列表")
|
||||
@CommonLog("分页查询当前用户参数列表分页")
|
||||
@ApiOperation("分页查询当前用户参数列表分页")
|
||||
@GetMapping("/my/page")
|
||||
public Result<IPage<ParamsCenterVO>> pageMy(
|
||||
@RequestParam(defaultValue = "1") Long current,
|
||||
@@ -221,10 +233,20 @@ public class AppParamsCenterController {
|
||||
/**
|
||||
* 增加下载次数
|
||||
*/
|
||||
@CommonLog("增加参数中心下载次数")
|
||||
@ApiOperation("增加参数中心下载次数")
|
||||
@PostMapping("/{id}/download")
|
||||
public Result<String> incrementDownloadCount(@PathVariable Long id) {
|
||||
try {
|
||||
|
||||
Object loginId = StpUtil.getLoginId();
|
||||
boolean isNew = redisUtil.setIfAbsent("paramCenter_" + loginId, 1, 1, TimeUnit.DAYS);
|
||||
// 如果键已存在,递增计数器
|
||||
long sendCount = isNew ? 1 : redisUtil.incr("paramCenter_" + loginId, 1);
|
||||
if(sendCount > 3) {
|
||||
return Result.error(I18nUtil.getMessage("params.download.exceed"));
|
||||
}
|
||||
|
||||
ParamsCenter params = paramsService.getById(id);
|
||||
if (params == null) {
|
||||
return Result.error(I18nUtil.getMessage("params.not.found"));
|
||||
@@ -250,6 +272,7 @@ public class AppParamsCenterController {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("发布公共参数提交审核")
|
||||
@ApiOperation("发布公共参数提交审核")
|
||||
@GetMapping("/review/{id}")
|
||||
public Result<String> review(@PathVariable Long id) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.corewing.app.modules.app;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.entity.PrivacyPolicy;
|
||||
import com.corewing.app.service.PrivacyPolicyService;
|
||||
import io.swagger.annotations.Api;
|
||||
@@ -31,6 +32,7 @@ public class AppPrivacyPolicyController {
|
||||
* 隐私政策列表
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("隐私政策列表")
|
||||
@ApiOperation("隐私政策列表")
|
||||
@GetMapping("/view_list/{lang}")
|
||||
public String viewList(@PathVariable String lang, ModelMap modelMap) {
|
||||
@@ -46,6 +48,7 @@ public class AppPrivacyPolicyController {
|
||||
* @param category
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("根据类型获取集合数据")
|
||||
@ApiOperation("根据类型获取集合数据")
|
||||
@GetMapping("/getListByCategory/{category}")
|
||||
@ResponseBody
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.publicFirmware.PublicBoardTypeListRequest;
|
||||
import com.corewing.app.dto.publicFirmware.PublicFirmwareListRequest;
|
||||
import com.corewing.app.dto.publicFirmware.PublicFirmwareVersionListRequest;
|
||||
@@ -33,25 +34,28 @@ public class AppPublicFirmwareController {
|
||||
@Resource
|
||||
private AppPublicFirmwarePlaneService appPublicFirmwarePlaneService;
|
||||
|
||||
|
||||
@CommonLog("获取固件类型集合")
|
||||
@ApiOperation("获取固件类型集合")
|
||||
@GetMapping("/getFirmwareTypeAll")
|
||||
public Result<List<BizDict>> getFirmwareTypeAll() {
|
||||
return Result.success(bizDictService.getDataListByKey());
|
||||
}
|
||||
|
||||
@CommonLog("根据固件类型获取版本集合")
|
||||
@ApiOperation("根据固件类型获取版本集合")
|
||||
@GetMapping("/getVersionList")
|
||||
public Result<List<AppPublicFirmwareVersion>> getVersionList(PublicFirmwareVersionListRequest publicFirmwareVersionListRequest) {
|
||||
return Result.success(appPublicFirmwareVersionService.getVersionList(publicFirmwareVersionListRequest));
|
||||
}
|
||||
|
||||
@CommonLog("根据固件类型&版本获取板载类型集合")
|
||||
@ApiOperation("根据固件类型&版本获取板载类型集合")
|
||||
@GetMapping("/getBoardTypeList")
|
||||
public Result<List<String>> getBoardTypeList(PublicBoardTypeListRequest publicBoardTypeListRequest) {
|
||||
return Result.success(appPublicFirmwarePlaneService.getBoardTypeList(publicBoardTypeListRequest));
|
||||
}
|
||||
|
||||
@CommonLog("根据固件类型&版本&板载获取固件集合")
|
||||
@ApiOperation("根据固件类型&版本&板载获取固件集合")
|
||||
@GetMapping("/getFirmwareList")
|
||||
public Result<List<AppPublicFirmwarePlane>> getFirmwareList(PublicFirmwareListRequest publicFirmwareListRequest) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.corewing.app.modules.app;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.uploadReplaySessionRequest;
|
||||
import com.corewing.app.entity.ReplaySession;
|
||||
import com.corewing.app.service.ReplaySessionService;
|
||||
@@ -24,6 +25,7 @@ public class AppReplaySessionController {
|
||||
* 获取飞行记录
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("获取当前用户飞行记录")
|
||||
@ApiOperation("获取当前用户飞行记录")
|
||||
@GetMapping("/getReplayList")
|
||||
public Result<List<ReplaySession>> getReplayList() {
|
||||
@@ -35,6 +37,7 @@ public class AppReplaySessionController {
|
||||
* @param uploadReplaySessionRequests
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("上传飞行记录")
|
||||
@ApiOperation("上传飞行记录")
|
||||
@PostMapping("/uploadReplaySession")
|
||||
public Result<Boolean> uploadReplaySession(@RequestBody List<uploadReplaySessionRequest> uploadReplaySessionRequests) {
|
||||
@@ -46,6 +49,7 @@ public class AppReplaySessionController {
|
||||
* @param syncId
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("根据同步id删除飞行记录")
|
||||
@ApiOperation("根据同步id删除飞行记录")
|
||||
@DeleteMapping("/deleteReplaySession/{syncId}")
|
||||
public Result<Boolean> deleteReplaySession(@PathVariable String syncId) {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.entity.SiriusFirmware;
|
||||
import com.corewing.app.service.SiriusFirmwareService;
|
||||
import com.corewing.app.util.I18nUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Sirius固件信息 Controller
|
||||
*/
|
||||
@Api(tags = "Sirius固件信息接口")
|
||||
@RestController
|
||||
@RequestMapping("/sirius_firmware")
|
||||
public class AppSiriusFirmwareController {
|
||||
|
||||
private final SiriusFirmwareService siriusFirmwareService;
|
||||
|
||||
public AppSiriusFirmwareController(SiriusFirmwareService siriusFirmwareService) {
|
||||
this.siriusFirmwareService = siriusFirmwareService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据固件类型和协议类型查询最新版本
|
||||
*/
|
||||
@CommonLog("查询Sirius最新固件版本")
|
||||
@ApiOperation("根据固件类型和协议类型查询最新版本")
|
||||
@GetMapping("/latest")
|
||||
public Result<SiriusFirmware> getLatest(
|
||||
@RequestParam Integer firmwareType,
|
||||
@RequestParam Integer protocolType) {
|
||||
SiriusFirmware firmware = siriusFirmwareService.getLatestByTypeAndProtocol(firmwareType, protocolType);
|
||||
if (firmware != null) {
|
||||
return Result.success(firmware);
|
||||
}
|
||||
return Result.error(I18nUtil.getMessage("firmware.not.found"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据固件类型查询版本列表
|
||||
*/
|
||||
@CommonLog("根据类型查询Sirius固件版本列表")
|
||||
@ApiOperation("根据固件类型查询版本列表")
|
||||
@GetMapping("/type/{firmwareType}")
|
||||
public Result<List<SiriusFirmware>> listByType(@PathVariable Integer firmwareType) {
|
||||
QueryWrapper<SiriusFirmware> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("firmware_type", firmwareType);
|
||||
wrapper.orderByDesc("create_time");
|
||||
return Result.success(siriusFirmwareService.list(wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据固件类型和协议类型查询版本列表
|
||||
*/
|
||||
@CommonLog("根据类型和协议查询Sirius固件版本列表")
|
||||
@ApiOperation("根据固件类型和协议类型查询版本列表")
|
||||
@GetMapping("/type/{firmwareType}/protocol/{protocolType}")
|
||||
public Result<List<SiriusFirmware>> listByTypeAndProtocol(
|
||||
@PathVariable Integer firmwareType,
|
||||
@PathVariable Integer protocolType) {
|
||||
QueryWrapper<SiriusFirmware> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("firmware_type", firmwareType);
|
||||
wrapper.eq("protocol_type", protocolType);
|
||||
wrapper.orderByDesc("create_time");
|
||||
return Result.success(siriusFirmwareService.list(wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有固件
|
||||
*/
|
||||
@CommonLog("查询所有Sirius固件")
|
||||
@ApiOperation("查询所有固件")
|
||||
@GetMapping("/list")
|
||||
public Result<List<SiriusFirmware>> list() {
|
||||
return Result.success(siriusFirmwareService.list());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询固件
|
||||
*/
|
||||
@CommonLog("根据ID查询Sirius固件")
|
||||
@ApiOperation("根据ID查询固件")
|
||||
@GetMapping("/{id}")
|
||||
public Result<SiriusFirmware> getById(@PathVariable Integer id) {
|
||||
SiriusFirmware firmware = siriusFirmwareService.getById(id);
|
||||
if (firmware != null) {
|
||||
return Result.success(firmware);
|
||||
}
|
||||
return Result.error(I18nUtil.getMessage("firmware.not.found"));
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.entity.Tutorial;
|
||||
import com.corewing.app.entity.TutorialCategory;
|
||||
import com.corewing.app.service.TutorialCategoryService;
|
||||
@@ -41,6 +42,7 @@ public class AppTutorialController {
|
||||
* @param model 数据模型
|
||||
* @return 详情页
|
||||
*/
|
||||
@CommonLog("跳转到界面查看教程详情")
|
||||
@ApiOperation("跳转到界面查看教程详情")
|
||||
@GetMapping("/viewDetail/{tutorialId}")
|
||||
public String viewDetail(@PathVariable Long tutorialId, ModelMap model) {
|
||||
@@ -55,6 +57,7 @@ public class AppTutorialController {
|
||||
* @param tutorialId 教程id
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("添加查看次数")
|
||||
@ApiOperation("添加查看次数")
|
||||
@GetMapping("/addViewCount")
|
||||
@ResponseBody
|
||||
@@ -74,6 +77,7 @@ public class AppTutorialController {
|
||||
* @param firstStatus 置首状态(选填)
|
||||
*
|
||||
*/
|
||||
@CommonLog("分类查询集合")
|
||||
@ApiOperation("分类查询集合")
|
||||
@GetMapping("/category")
|
||||
@ResponseBody
|
||||
@@ -97,6 +101,7 @@ public class AppTutorialController {
|
||||
* @param tutorialTitle 教程标题(选填)
|
||||
*
|
||||
*/
|
||||
@CommonLog("分页查询教程列表")
|
||||
@ApiOperation("分页查询教程列表")
|
||||
@GetMapping("/page")
|
||||
@ResponseBody
|
||||
|
||||
@@ -2,16 +2,21 @@ package com.corewing.app.modules.app;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.*;
|
||||
import com.corewing.app.entity.DevLog;
|
||||
import com.corewing.app.entity.User;
|
||||
import com.corewing.app.service.UserService;
|
||||
import com.corewing.app.service.VerifyCodeService;
|
||||
import com.corewing.app.util.DevLogUtil;
|
||||
import com.corewing.app.util.I18nUtil;
|
||||
import com.corewing.app.util.IpUtil;
|
||||
import com.corewing.app.util.RedisUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.util.HashMap;
|
||||
@@ -25,17 +30,20 @@ import java.util.Map;
|
||||
@RequestMapping("/user")
|
||||
public class AppUserController {
|
||||
|
||||
private final UserService userService;
|
||||
private final VerifyCodeService verifyCodeService;
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@Resource
|
||||
private VerifyCodeService verifyCodeService;
|
||||
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
public AppUserController(UserService userService, VerifyCodeService verifyCodeService) {
|
||||
this.userService = userService;
|
||||
this.verifyCodeService = verifyCodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送验证码
|
||||
*/
|
||||
@CommonLog("发送验证码接口")
|
||||
@ApiOperation("发送验证码接口")
|
||||
@PostMapping("/sendCode")
|
||||
public Result<String> sendCode(@RequestBody SendCodeRequest request) {
|
||||
@@ -69,6 +77,8 @@ public class AppUserController {
|
||||
data.put("userId", user.getId());
|
||||
data.put("username", user.getUsername());
|
||||
|
||||
redisUtil.set("APP_" + user.getId(), user);
|
||||
DevLogUtil.executeLoginLog(user.getUsername());
|
||||
return Result.success(I18nUtil.getMessage("user.login.success"), data);
|
||||
} catch (Exception e) {
|
||||
return Result.error(e.getMessage());
|
||||
@@ -104,6 +114,13 @@ public class AppUserController {
|
||||
@ApiOperation("用户登出接口")
|
||||
@PostMapping("/logout")
|
||||
public Result<String> logout() {
|
||||
Long userId = StpUtil.getLoginIdAsLong();
|
||||
User user = (User) redisUtil.get("APP_" + userId);
|
||||
if(user == null) {
|
||||
user = userService.getById(userId);
|
||||
}
|
||||
redisUtil.del("APP_" + userId);
|
||||
DevLogUtil.executeLogoutLog(user.getUsername());
|
||||
StpUtil.logout();
|
||||
return Result.success(I18nUtil.getMessage("user.logout.success"));
|
||||
}
|
||||
@@ -111,19 +128,32 @@ public class AppUserController {
|
||||
/**
|
||||
* 获取当前登录用户信息
|
||||
*/
|
||||
@CommonLog("获取当前登录用户信息")
|
||||
@ApiOperation("获取当前登录用户信息")
|
||||
@GetMapping("/info")
|
||||
public Result<User> getUserInfo() {
|
||||
Long userId = StpUtil.getLoginIdAsLong();
|
||||
|
||||
try {
|
||||
// 缓存获取
|
||||
User user = (User) redisUtil.get("APP_" + userId);
|
||||
if(user == null) {
|
||||
user = userService.getById(userId);
|
||||
redisUtil.set("APP_" + user.getId(), user);
|
||||
}
|
||||
return Result.success(user);
|
||||
} catch (Exception e) {
|
||||
User user = userService.getById(userId);
|
||||
// 隐藏密码
|
||||
user.setPassword(null);
|
||||
return Result.success(user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询用户
|
||||
*/
|
||||
@CommonLog("根据id查询用户")
|
||||
@ApiOperation("根据id查询用户")
|
||||
@GetMapping("/{id}")
|
||||
public Result<User> getById(@PathVariable Long id) {
|
||||
@@ -139,6 +169,7 @@ public class AppUserController {
|
||||
/**
|
||||
* 更新用户信息
|
||||
*/
|
||||
@CommonLog("更新用户信息")
|
||||
@ApiOperation("更新用户信息")
|
||||
@PutMapping("/update")
|
||||
public Result<String> update(@RequestBody User user) {
|
||||
@@ -147,6 +178,10 @@ public class AppUserController {
|
||||
// 不允许通过此接口修改密码
|
||||
user.setPassword(null);
|
||||
boolean success = userService.updateById(user);
|
||||
|
||||
// 更新缓存
|
||||
User cacheUser = userService.getById(userId);
|
||||
redisUtil.set("APP_" + user.getId(), cacheUser);
|
||||
if (success) {
|
||||
return Result.success(I18nUtil.getMessage("user.update.success"));
|
||||
}
|
||||
@@ -156,6 +191,7 @@ public class AppUserController {
|
||||
/**
|
||||
* 修改密码
|
||||
*/
|
||||
@CommonLog("用户修改密码")
|
||||
@ApiOperation("用户修改密码")
|
||||
@PutMapping("/password")
|
||||
public Result<String> updatePassword(@RequestBody UpdatePasswordRequest request) {
|
||||
@@ -189,6 +225,7 @@ public class AppUserController {
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("忘记密码")
|
||||
@ApiOperation("忘记密码")
|
||||
@PutMapping("/forgetPassword")
|
||||
public Result<String> forgetPassword(@RequestBody ForgetPasswordRequest request) {
|
||||
@@ -213,6 +250,8 @@ public class AppUserController {
|
||||
data.put("token", token);
|
||||
data.put("userId", user.getId());
|
||||
data.put("username", user.getUsername());
|
||||
redisUtil.set("APP_" + user.getId(), user);
|
||||
DevLogUtil.executeLoginLog(user.getUsername());
|
||||
return Result.success(I18nUtil.getMessage("user.login.success"), data);
|
||||
}
|
||||
|
||||
@@ -221,6 +260,7 @@ public class AppUserController {
|
||||
* @param logoffRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("注销用户")
|
||||
@ApiOperation("注销用户")
|
||||
@DeleteMapping("/delete")
|
||||
public Result<String> logoff(@RequestBody @Valid LogoffRequest logoffRequest) {
|
||||
@@ -231,6 +271,7 @@ public class AppUserController {
|
||||
* 注销发送验证码
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("发送注销验证码")
|
||||
@ApiOperation("发送注销验证码")
|
||||
@PostMapping("/delete/sendCode")
|
||||
public Result<Map<String, String>> deleteSendCode() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.corewing.app.modules.app;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.dto.CheckVersionRequest;
|
||||
import com.corewing.app.entity.AppVersion;
|
||||
import com.corewing.app.service.AppVersionService;
|
||||
@@ -28,6 +29,7 @@ public class AppVersionController {
|
||||
* @param checkVersionRequest
|
||||
* @return
|
||||
*/
|
||||
@CommonLog("校验是否有新版本")
|
||||
@ApiOperation("校验是否有新版本")
|
||||
@GetMapping("/checkUpdate")
|
||||
public Result<Object> checkUpdate(CheckVersionRequest checkVersionRequest) {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.corewing.app.modules.qc;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Api(tags = "QC配置")
|
||||
@RestController
|
||||
@RequestMapping("/api/qc/config")
|
||||
public class QcConfigController {
|
||||
|
||||
@ApiOperation("获取测试配置")
|
||||
@GetMapping("/test-params")
|
||||
public Result<Map<String, Object>> getTestParams(@RequestParam("productType") String productType) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
// 后续可根据 productType 返回不同的测试参数/阈值
|
||||
params.put("productType", productType);
|
||||
return Result.success(params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.corewing.app.modules.qc;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.dto.qc.UploadTestRecordRequest;
|
||||
import com.corewing.app.dto.qc.ValidateSnRequest;
|
||||
import com.corewing.app.entity.QcTestRecord;
|
||||
import com.corewing.app.service.QcTestService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Api(tags = "QC测试")
|
||||
@RestController
|
||||
@RequestMapping("/api/qc/test")
|
||||
public class QcTestController {
|
||||
|
||||
private final QcTestService qcTestService;
|
||||
|
||||
public QcTestController(QcTestService qcTestService) {
|
||||
this.qcTestService = qcTestService;
|
||||
}
|
||||
|
||||
@ApiOperation("上传测试记录")
|
||||
@PostMapping("/upload")
|
||||
public Result<String> uploadTestRecord(@RequestBody UploadTestRecordRequest request) {
|
||||
return qcTestService.uploadTestRecord(request);
|
||||
}
|
||||
|
||||
@ApiOperation("上传照片")
|
||||
@PostMapping("/upload-photo")
|
||||
public Result<Map<String, String>> uploadPhoto(@RequestParam("testNo") String testNo,
|
||||
@RequestParam("photo") MultipartFile photo) {
|
||||
return qcTestService.uploadPhoto(testNo, photo);
|
||||
}
|
||||
|
||||
@ApiOperation("验证SN")
|
||||
@PostMapping("/validate-sn")
|
||||
public Result<Boolean> validateSn(@RequestBody ValidateSnRequest request) {
|
||||
return qcTestService.validateSn(request);
|
||||
}
|
||||
|
||||
@ApiOperation("查询SN历史记录")
|
||||
@GetMapping("/history")
|
||||
public Result<List<QcTestRecord>> getHistory(@RequestParam("sn") String sn) {
|
||||
return qcTestService.getHistory(sn);
|
||||
}
|
||||
|
||||
@ApiOperation("获取测试报告")
|
||||
@GetMapping("/report")
|
||||
public Result<String> getReport(@RequestParam("testNo") String testNo) {
|
||||
return qcTestService.getReport(testNo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.corewing.app.modules.qc;
|
||||
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.dto.qc.ValidateWirelessBoardRequest;
|
||||
import com.corewing.app.service.BizDeviceService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Api(tags = "无线版QC")
|
||||
@RestController
|
||||
@RequestMapping("/api/qc/wireless")
|
||||
public class WirelessBoardController {
|
||||
private final BizDeviceService bizDeviceService;
|
||||
|
||||
public WirelessBoardController(BizDeviceService bizDeviceService) {
|
||||
this.bizDeviceService = bizDeviceService;
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("验证已经激活的无线板")
|
||||
@PostMapping("/validate-wireless")
|
||||
public Result<Boolean> validateWirelessBoard(@RequestBody ValidateWirelessBoardRequest validateWirelessBoardRequest) {
|
||||
return bizDeviceService.validateWirelessBoard(validateWirelessBoardRequest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.corewing.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.corewing.app.entity.AatVersion;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* AAT固件版本 Service 接口
|
||||
*/
|
||||
public interface AatVersionService extends IService<AatVersion> {
|
||||
|
||||
/**
|
||||
* 根据固件类型查询最新版本
|
||||
*
|
||||
* @param firmwareType 固件类型
|
||||
* @return 最新固件版本
|
||||
*/
|
||||
AatVersion getLatestByType(String firmwareType);
|
||||
|
||||
/**
|
||||
* 查询所有类型的最新固件版本(返回与原始JSON结构一致的格式)
|
||||
*
|
||||
* @return 所有类型的最新版本映射
|
||||
*/
|
||||
Map<String, Object> getAllLatestVersions();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.corewing.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.corewing.app.dto.SubmitActivityRequest;
|
||||
import com.corewing.app.entity.BizActivityLottery;
|
||||
|
||||
public interface BizActivityLotteryService extends IService<BizActivityLottery> {
|
||||
|
||||
Boolean submitActivity(SubmitActivityRequest submitActivityRequest);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.corewing.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.corewing.app.entity.BizActivity;
|
||||
|
||||
public interface BizActivityService extends IService<BizActivity> {
|
||||
}
|
||||
@@ -6,4 +6,6 @@ import com.corewing.app.entity.BizDeviceActivation;
|
||||
|
||||
public interface BizDeviceActivationService extends IService<BizDeviceActivation> {
|
||||
Boolean activation(DeviceActivationRequest deviceActivationRequest);
|
||||
|
||||
Boolean factoryActivation(DeviceActivationRequest deviceActivationRequest);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.corewing.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.dto.qc.ValidateWirelessBoardRequest;
|
||||
import com.corewing.app.entity.BizDevice;
|
||||
|
||||
public interface BizDeviceService extends IService<BizDevice> {
|
||||
Result<Boolean> validateWirelessBoard(ValidateWirelessBoardRequest validateWirelessBoardRequest);
|
||||
}
|
||||
|
||||
19
src/main/java/com/corewing/app/service/DevLogService.java
Normal file
19
src/main/java/com/corewing/app/service/DevLogService.java
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
package com.corewing.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.corewing.app.entity.DevLog;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 日志Service接口
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/9/2 15:04
|
||||
*/
|
||||
public interface DevLogService extends IService<DevLog> {
|
||||
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.corewing.app.service;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.dto.FirmwareVersionRequest;
|
||||
import com.corewing.app.entity.Firmware;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@@ -40,4 +41,11 @@ public interface FirmwareService extends IService<Firmware> {
|
||||
* @return
|
||||
*/
|
||||
boolean removeData(Long id);
|
||||
|
||||
/**
|
||||
* 校验固件是否有新固件
|
||||
* @param firmwareVersionRequest
|
||||
* @return
|
||||
*/
|
||||
Firmware checkVersion(FirmwareVersionRequest firmwareVersionRequest);
|
||||
}
|
||||
|
||||
24
src/main/java/com/corewing/app/service/QcTestService.java
Normal file
24
src/main/java/com/corewing/app/service/QcTestService.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.corewing.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.dto.qc.UploadTestRecordRequest;
|
||||
import com.corewing.app.dto.qc.ValidateSnRequest;
|
||||
import com.corewing.app.entity.QcTestRecord;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface QcTestService extends IService<QcTestRecord> {
|
||||
|
||||
Result<String> uploadTestRecord(UploadTestRecordRequest request);
|
||||
|
||||
Result<Map<String, String>> uploadPhoto(String testNo, MultipartFile photo);
|
||||
|
||||
Result<Boolean> validateSn(ValidateSnRequest request);
|
||||
|
||||
Result<List<QcTestRecord>> getHistory(String sn);
|
||||
|
||||
Result<String> getReport(String testNo);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.corewing.app.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.corewing.app.entity.SiriusFirmware;
|
||||
|
||||
/**
|
||||
* Sirius固件信息 Service 接口
|
||||
*/
|
||||
public interface SiriusFirmwareService extends IService<SiriusFirmware> {
|
||||
|
||||
/**
|
||||
* 根据固件类型和协议类型查询最新版本
|
||||
*
|
||||
* @param firmwareType 固件类型
|
||||
* @param protocolType 协议类型
|
||||
* @return 最新固件版本
|
||||
*/
|
||||
SiriusFirmware getLatestByTypeAndProtocol(Integer firmwareType, Integer protocolType);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.corewing.app.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.entity.AatVersion;
|
||||
import com.corewing.app.mapper.AatVersionMapper;
|
||||
import com.corewing.app.service.AatVersionService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* AAT固件版本 Service 实现类
|
||||
*/
|
||||
@Service
|
||||
public class AatVersionServiceImpl extends ServiceImpl<AatVersionMapper, AatVersion> implements AatVersionService {
|
||||
|
||||
@Override
|
||||
public AatVersion getLatestByType(String firmwareType) {
|
||||
LambdaQueryWrapper<AatVersion> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(AatVersion::getFirmwareType, firmwareType);
|
||||
wrapper.orderByDesc(AatVersion::getCreateTime);
|
||||
wrapper.last("LIMIT 1");
|
||||
return getOne(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAllLatestVersions() {
|
||||
// 查询所有固件,按类型分组,每组取最新的一条
|
||||
List<AatVersion> allVersions = list(
|
||||
new LambdaQueryWrapper<AatVersion>().orderByDesc(AatVersion::getCreateTime)
|
||||
);
|
||||
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
Map<String, List<AatVersion>> grouped = allVersions.stream()
|
||||
.collect(Collectors.groupingBy(AatVersion::getFirmwareType, LinkedHashMap::new, Collectors.toList()));
|
||||
|
||||
for (Map.Entry<String, List<AatVersion>> entry : grouped.entrySet()) {
|
||||
Map<String, Object> typeInfo = new HashMap<>();
|
||||
List<Map<String, String>> firmwares = new ArrayList<>();
|
||||
// 取该类型下最新的一条
|
||||
AatVersion latest = entry.getValue().get(0);
|
||||
Map<String, String> firmwareInfo = new HashMap<>();
|
||||
firmwareInfo.put("firmware_name", latest.getFirmwareName());
|
||||
firmwareInfo.put("firmware_version", latest.getFirmwareVersion());
|
||||
firmwareInfo.put("min_hardware_version", latest.getMinHardwareVersion());
|
||||
firmwares.add(firmwareInfo);
|
||||
typeInfo.put("firmwares", firmwares);
|
||||
result.put(entry.getKey(), typeInfo);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.corewing.app.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.dto.SubmitActivityRequest;
|
||||
import com.corewing.app.entity.BizActivity;
|
||||
import com.corewing.app.entity.BizActivityLottery;
|
||||
import com.corewing.app.mapper.BizActivityLotteryMapper;
|
||||
import com.corewing.app.service.BizActivityLotteryService;
|
||||
import com.corewing.app.service.BizActivityService;
|
||||
import com.corewing.app.util.DateUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
public class BizActivityLotteryServiceImpl extends ServiceImpl<BizActivityLotteryMapper, BizActivityLottery> implements BizActivityLotteryService {
|
||||
|
||||
@Resource
|
||||
private BizActivityService bizActivityService;
|
||||
|
||||
@Override
|
||||
public Boolean submitActivity(SubmitActivityRequest submitActivityRequest) {
|
||||
|
||||
Long userid = StpUtil.getLoginIdAsLong();
|
||||
|
||||
BizActivity activity = bizActivityService.getById(submitActivityRequest.getActivityId());
|
||||
if(activity == null) {
|
||||
throw new RuntimeException("该活动不存在");
|
||||
}
|
||||
|
||||
// 验证活动是否在有效期内
|
||||
if(activity.getStartTime() != null && activity.getEndTime() != null) {
|
||||
if(!DateUtils.isBefore(activity.getStartTime())) {
|
||||
throw new RuntimeException("活动还未开始");
|
||||
}
|
||||
|
||||
if(!DateUtils.isAfter(activity.getEndTime())) {
|
||||
throw new RuntimeException("活动已过期");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 校验是否参与
|
||||
LambdaQueryWrapper<BizActivityLottery> checkLotteryWrapper = new LambdaQueryWrapper<>();
|
||||
checkLotteryWrapper.eq(BizActivityLottery::getUserId, userid);
|
||||
checkLotteryWrapper.eq(BizActivityLottery::getActivityId, submitActivityRequest.getActivityId());
|
||||
if(count(checkLotteryWrapper) > 0) {
|
||||
throw new RuntimeException("该活动你已经参与");
|
||||
}
|
||||
|
||||
BizActivityLottery bizActivityLottery = new BizActivityLottery();
|
||||
bizActivityLottery.setActivityId(submitActivityRequest.getActivityId());
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.corewing.app.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.entity.BizActivity;
|
||||
import com.corewing.app.mapper.BizActivityMapper;
|
||||
import com.corewing.app.service.BizActivityService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class BizActivityServiceImpl extends ServiceImpl<BizActivityMapper, BizActivity> implements BizActivityService {
|
||||
}
|
||||
@@ -2,17 +2,19 @@ package com.corewing.app.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.dto.DeviceActivationRequest;
|
||||
import com.corewing.app.entity.BizDevice;
|
||||
import com.corewing.app.entity.BizDeviceActivation;
|
||||
import com.corewing.app.entity.BizDeviceCategory;
|
||||
import com.corewing.app.mapper.BizDeviceActivationMapper;
|
||||
import com.corewing.app.service.BizDeviceActivationService;
|
||||
import com.corewing.app.service.BizDeviceCategoryService;
|
||||
import com.corewing.app.service.BizDeviceService;
|
||||
import com.corewing.app.util.CommonServletUtil;
|
||||
import com.corewing.app.util.IpUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
@@ -24,6 +26,9 @@ public class BizDeviceActivationServiceImpl extends ServiceImpl<BizDeviceActivat
|
||||
@Resource
|
||||
private BizDeviceService deviceService;
|
||||
|
||||
@Resource
|
||||
private BizDeviceCategoryService categoryService;
|
||||
|
||||
@Override
|
||||
public Boolean activation(DeviceActivationRequest deviceActivationRequest) {
|
||||
Object loginId = StpUtil.getLoginId();
|
||||
@@ -57,4 +62,36 @@ public class BizDeviceActivationServiceImpl extends ServiceImpl<BizDeviceActivat
|
||||
deviceActivation.setDeviceId(bizDevice.getId());
|
||||
return this.saveOrUpdate(deviceActivation);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public Boolean factoryActivation(DeviceActivationRequest deviceActivationRequest) {
|
||||
BizDeviceActivation checkDeviceActivation = getBizDeviceActivationByMac(deviceActivationRequest.getMac());
|
||||
if (checkDeviceActivation != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<BizDeviceCategory> findWrapper = new LambdaQueryWrapper<>();
|
||||
findWrapper.eq(BizDeviceCategory::getModelId, deviceActivationRequest.getModelId());
|
||||
BizDeviceCategory deviceCategory = categoryService.getOne(findWrapper);
|
||||
|
||||
BizDevice device = new BizDevice();
|
||||
device.setDeviceMac(deviceActivationRequest.getMac());
|
||||
device.setStatus("0");
|
||||
device.setPublicStatus("1");
|
||||
device.setCategoryId(deviceCategory.getId());
|
||||
return deviceService.save(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据mac地址获取激活设备
|
||||
*
|
||||
* @param mac mac地址
|
||||
* @return 激活设备
|
||||
*/
|
||||
private BizDeviceActivation getBizDeviceActivationByMac(String mac) {
|
||||
LambdaQueryWrapper<BizDeviceActivation> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(BizDeviceActivation::getDeviceMac, mac);
|
||||
return getOne(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.corewing.app.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.dto.qc.ValidateWirelessBoardRequest;
|
||||
import com.corewing.app.entity.BizDevice;
|
||||
import com.corewing.app.mapper.BizDeviceMapper;
|
||||
import com.corewing.app.service.BizDeviceService;
|
||||
@@ -8,4 +11,16 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class BizDeviceServiceImpl extends ServiceImpl<BizDeviceMapper, BizDevice> implements BizDeviceService {
|
||||
@Override
|
||||
public Result<Boolean> validateWirelessBoard(ValidateWirelessBoardRequest validateWirelessBoardRequest) {
|
||||
|
||||
LambdaQueryWrapper<BizDevice> bizDeviceLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
bizDeviceLambdaQueryWrapper.eq(BizDevice::getDeviceMac, validateWirelessBoardRequest.getMac());
|
||||
long deviceCount = count(bizDeviceLambdaQueryWrapper);
|
||||
if (deviceCount > 0) {
|
||||
return Result.success(true);
|
||||
}
|
||||
|
||||
return Result.error("设备不存在或未激活");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public class BizProductServiceImpl extends ServiceImpl<BizProductMapper, BizProd
|
||||
|
||||
@Override
|
||||
public Page<BizProduct> page(ProductPageRequest productPageRequest) {
|
||||
Page<BizProduct> page = PageContext.getDefaultPage(BizProduct.class);
|
||||
Page<BizProduct> page = PageContext.getPage(BizProduct.class);
|
||||
return bizProductMapper.page(page, productPageRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.corewing.app.service.impl;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.entity.DevLog;
|
||||
import com.corewing.app.mapper.DevLogMapper;
|
||||
import com.corewing.app.service.DevLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
/**
|
||||
* 日志Service接口实现类
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/9/2 15:05
|
||||
*/
|
||||
@Service
|
||||
public class DevLogServiceImpl extends ServiceImpl<DevLogMapper, DevLog> implements DevLogService {
|
||||
|
||||
|
||||
}
|
||||
@@ -4,8 +4,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.common.page.PageContext;
|
||||
import com.corewing.app.dto.FirmwareVersionRequest;
|
||||
import com.corewing.app.entity.BizDeviceCategory;
|
||||
import com.corewing.app.entity.Firmware;
|
||||
import com.corewing.app.mapper.FirmwareMapper;
|
||||
import com.corewing.app.service.BizDeviceCategoryService;
|
||||
import com.corewing.app.service.FirmwareService;
|
||||
import com.corewing.app.util.OSSUploadUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -13,7 +16,9 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 固件 Service 实现类
|
||||
@@ -21,6 +26,9 @@ import java.io.IOException;
|
||||
@Service
|
||||
public class FirmwareServiceImpl extends ServiceImpl<FirmwareMapper, Firmware> implements FirmwareService {
|
||||
|
||||
@Resource
|
||||
private BizDeviceCategoryService bizDeviceCategoryService;
|
||||
|
||||
@Override
|
||||
public Page<Firmware> page(Firmware firmware) {
|
||||
Page<Firmware> page = PageContext.getDefaultPage(Firmware.class);
|
||||
@@ -63,6 +71,30 @@ public class FirmwareServiceImpl extends ServiceImpl<FirmwareMapper, Firmware> i
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Firmware checkVersion(FirmwareVersionRequest firmwareVersionRequest) {
|
||||
|
||||
// 根据型号id搜索到设备分类id
|
||||
LambdaQueryWrapper<BizDeviceCategory> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
categoryLambdaQueryWrapper.eq(BizDeviceCategory::getModelId, firmwareVersionRequest.getModelId());
|
||||
BizDeviceCategory deviceCategory = bizDeviceCategoryService.getOne(categoryLambdaQueryWrapper);
|
||||
if(Objects.isNull(deviceCategory)){
|
||||
throw new RuntimeException("该设备型号不存在设备");
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<Firmware> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.ge(Firmware::getVersionId, firmwareVersionRequest.getVersion());
|
||||
wrapper.eq(Firmware::getModelId, deviceCategory.getId());
|
||||
wrapper.eq(Firmware::getFirmwareType, firmwareVersionRequest.getFirmwareType());
|
||||
wrapper.orderByDesc(Firmware::getVersionId);
|
||||
wrapper.last("LIMIT 1");
|
||||
Firmware firmware = this.getOne(wrapper);
|
||||
if (firmware == null) {
|
||||
throw new RuntimeException("未找到匹配的固件版本");
|
||||
}
|
||||
return firmware;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 URL 路径的最后一节(忽略查询参数 ? 和锚点 #)
|
||||
* @param urlStr URL字符串
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
package com.corewing.app.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.common.Result;
|
||||
import com.corewing.app.dto.qc.StepResultData;
|
||||
import com.corewing.app.dto.qc.UploadTestRecordRequest;
|
||||
import com.corewing.app.dto.qc.ValidateSnRequest;
|
||||
import com.corewing.app.entity.FlightController;
|
||||
import com.corewing.app.entity.QcPhoto;
|
||||
import com.corewing.app.entity.QcStepResult;
|
||||
import com.corewing.app.entity.QcTestRecord;
|
||||
import com.corewing.app.mapper.FlightControllerMapper;
|
||||
import com.corewing.app.mapper.QcPhotoMapper;
|
||||
import com.corewing.app.mapper.QcStepResultMapper;
|
||||
import com.corewing.app.mapper.QcTestRecordMapper;
|
||||
import com.corewing.app.service.QcTestService;
|
||||
import com.corewing.app.util.OSSUploadUtil;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class QcTestServiceImpl extends ServiceImpl<QcTestRecordMapper, QcTestRecord> implements QcTestService {
|
||||
|
||||
@Resource
|
||||
private QcStepResultMapper qcStepResultMapper;
|
||||
|
||||
@Resource
|
||||
private QcPhotoMapper qcPhotoMapper;
|
||||
|
||||
@Resource
|
||||
private FlightControllerMapper flightControllerMapper;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Result<String> uploadTestRecord(UploadTestRecordRequest request) {
|
||||
if (request.getTestNo() == null || request.getTestNo().isEmpty()) {
|
||||
return Result.error("测试单号不能为空");
|
||||
}
|
||||
|
||||
// 查找是否已存在相同 testNo 的记录
|
||||
LambdaQueryWrapper<QcTestRecord> testNoQuery = new LambdaQueryWrapper<>();
|
||||
testNoQuery.eq(QcTestRecord::getTestNo, request.getTestNo());
|
||||
QcTestRecord existByTestNo = baseMapper.selectOne(testNoQuery);
|
||||
|
||||
QcTestRecord record;
|
||||
if (existByTestNo != null) {
|
||||
// 相同 testNo 已存在 → 更新(APP 重传场景)
|
||||
record = existByTestNo;
|
||||
fillRecord(record, request);
|
||||
baseMapper.updateById(record);
|
||||
// 清除旧的步骤和照片,后面重新插入
|
||||
deleteStepsAndPhotos(record.getId());
|
||||
} else {
|
||||
// 查找同一 SN 是否已有记录(返修重测场景)
|
||||
LambdaQueryWrapper<QcTestRecord> snQuery = new LambdaQueryWrapper<>();
|
||||
snQuery.eq(QcTestRecord::getSn, request.getSn())
|
||||
.eq(QcTestRecord::getProductType, request.getProductType())
|
||||
.orderByDesc(QcTestRecord::getCreateTime)
|
||||
.last("LIMIT 1");
|
||||
QcTestRecord existBySn = baseMapper.selectOne(snQuery);
|
||||
|
||||
if (existBySn != null) {
|
||||
// 同一 SN 已有记录 → 更新最近一条(返修后重新 QC)
|
||||
record = existBySn;
|
||||
fillRecord(record, request);
|
||||
baseMapper.updateById(record);
|
||||
deleteStepsAndPhotos(record.getId());
|
||||
} else {
|
||||
// 全新记录
|
||||
record = new QcTestRecord();
|
||||
fillRecord(record, request);
|
||||
baseMapper.insert(record);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存步骤结果
|
||||
if (!CollectionUtils.isEmpty(request.getSteps())) {
|
||||
for (StepResultData stepData : request.getSteps()) {
|
||||
QcStepResult step = new QcStepResult();
|
||||
BeanUtils.copyProperties(stepData, step, "completedAt");
|
||||
step.setTestRecordId(record.getId());
|
||||
step.setCompletedAt(parseTimestamp(stepData.getCompletedAt()));
|
||||
qcStepResultMapper.insert(step);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存照片 URL
|
||||
if (!CollectionUtils.isEmpty(request.getPhotoUrls())) {
|
||||
for (String photoUrl : request.getPhotoUrls()) {
|
||||
QcPhoto photo = new QcPhoto();
|
||||
photo.setTestRecordId(record.getId());
|
||||
photo.setTestNo(request.getTestNo());
|
||||
photo.setUrl(photoUrl);
|
||||
qcPhotoMapper.insert(photo);
|
||||
}
|
||||
}
|
||||
|
||||
// 返回报告 URL(可为 null)
|
||||
return Result.success("上传成功", record.getReportUrl());
|
||||
}
|
||||
|
||||
private void fillRecord(QcTestRecord record, UploadTestRecordRequest request) {
|
||||
// 拷贝同名同类型字段(testNo, productType, sn, operatorId, operatorName, phoneModel, appVersion, status)
|
||||
BeanUtils.copyProperties(request, record, "createTime", "updatedAt", "uploadTime");
|
||||
// 时间戳字符串 → LocalDateTime 需要手动转换
|
||||
record.setCreateTime(parseTimestamp(request.getCreateTime()));
|
||||
record.setUpdatedAt(parseTimestamp(request.getUpdatedAt()));
|
||||
record.setUploadTime(parseTimestamp(request.getUploadTime()));
|
||||
}
|
||||
|
||||
private void deleteStepsAndPhotos(Long recordId) {
|
||||
LambdaQueryWrapper<QcStepResult> stepDelete = new LambdaQueryWrapper<>();
|
||||
stepDelete.eq(QcStepResult::getTestRecordId, recordId);
|
||||
qcStepResultMapper.delete(stepDelete);
|
||||
|
||||
LambdaQueryWrapper<QcPhoto> photoDelete = new LambdaQueryWrapper<>();
|
||||
photoDelete.eq(QcPhoto::getTestRecordId, recordId);
|
||||
qcPhotoMapper.delete(photoDelete);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Map<String, String>> uploadPhoto(String testNo, MultipartFile photo) {
|
||||
if (photo == null || photo.isEmpty()) {
|
||||
return Result.error("照片文件不能为空");
|
||||
}
|
||||
if (testNo == null || testNo.isEmpty()) {
|
||||
return Result.error("测试单号不能为空");
|
||||
}
|
||||
|
||||
// 查找对应的测试记录
|
||||
LambdaQueryWrapper<QcTestRecord> query = new LambdaQueryWrapper<>();
|
||||
query.eq(QcTestRecord::getTestNo, testNo);
|
||||
QcTestRecord record = baseMapper.selectOne(query);
|
||||
if (record == null) {
|
||||
return Result.error("测试记录不存在: " + testNo);
|
||||
}
|
||||
|
||||
try {
|
||||
// 生成 OSS 存储路径
|
||||
String originalFilename = photo.getOriginalFilename();
|
||||
String suffix = "";
|
||||
if (originalFilename != null && originalFilename.contains(".")) {
|
||||
suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
|
||||
}
|
||||
String objectName = "qc/photos/" + testNo + "/" + UUID.randomUUID().toString().replace("-", "") + suffix;
|
||||
|
||||
// 上传到 OSS
|
||||
String url = OSSUploadUtil.uploadFile(photo.getInputStream(), objectName);
|
||||
|
||||
// 保存照片记录
|
||||
QcPhoto qcPhoto = new QcPhoto();
|
||||
qcPhoto.setTestRecordId(record.getId());
|
||||
qcPhoto.setTestNo(testNo);
|
||||
qcPhoto.setUrl(url);
|
||||
qcPhotoMapper.insert(qcPhoto);
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
result.put("url", url);
|
||||
return Result.success("上传成功", result);
|
||||
} catch (Exception e) {
|
||||
log.error("照片上传失败", e);
|
||||
return Result.error("照片上传失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Boolean> validateSn(ValidateSnRequest request) {
|
||||
if (request.getSn() == null || request.getSn().isEmpty()) {
|
||||
return Result.error("SN 不能为空");
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<FlightController> query = new LambdaQueryWrapper<>();
|
||||
query.eq(FlightController::getSn, request.getSn());
|
||||
Long count = flightControllerMapper.selectCount(query);
|
||||
|
||||
if (count > 0) {
|
||||
return Result.success("SN 有效", true);
|
||||
}
|
||||
|
||||
return Result.error("SN 无效或未注册");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<List<QcTestRecord>> getHistory(String sn) {
|
||||
if (sn == null || sn.isEmpty()) {
|
||||
return Result.error("SN 不能为空");
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<QcTestRecord> query = new LambdaQueryWrapper<>();
|
||||
query.eq(QcTestRecord::getSn, sn)
|
||||
.orderByDesc(QcTestRecord::getCreateTime);
|
||||
List<QcTestRecord> records = baseMapper.selectList(query);
|
||||
|
||||
return Result.success(records);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> getReport(String testNo) {
|
||||
if (testNo == null || testNo.isEmpty()) {
|
||||
return Result.error("测试单号不能为空");
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<QcTestRecord> query = new LambdaQueryWrapper<>();
|
||||
query.eq(QcTestRecord::getTestNo, testNo);
|
||||
QcTestRecord record = baseMapper.selectOne(query);
|
||||
|
||||
if (record == null) {
|
||||
return Result.error("测试记录不存在");
|
||||
}
|
||||
|
||||
return Result.success(record.getReportUrl());
|
||||
}
|
||||
|
||||
private LocalDateTime parseTimestamp(String timestamp) {
|
||||
if (timestamp == null || timestamp.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
long millis = Long.parseLong(timestamp);
|
||||
if (millis <= 0) {
|
||||
return null;
|
||||
}
|
||||
return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault());
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.corewing.app.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.corewing.app.entity.SiriusFirmware;
|
||||
import com.corewing.app.mapper.SiriusFirmwareMapper;
|
||||
import com.corewing.app.service.SiriusFirmwareService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Sirius固件信息 Service 实现类
|
||||
*/
|
||||
@Service
|
||||
public class SiriusFirmwareServiceImpl extends ServiceImpl<SiriusFirmwareMapper, SiriusFirmware> implements SiriusFirmwareService {
|
||||
|
||||
@Override
|
||||
public SiriusFirmware getLatestByTypeAndProtocol(Integer firmwareType, Integer protocolType) {
|
||||
LambdaQueryWrapper<SiriusFirmware> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(SiriusFirmware::getFirmwareType, firmwareType);
|
||||
wrapper.eq(SiriusFirmware::getProtocolType, protocolType);
|
||||
wrapper.orderByDesc(SiriusFirmware::getCreateTime);
|
||||
wrapper.last("LIMIT 1");
|
||||
return getOne(wrapper);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import javax.annotation.Resource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 应用用户 Service 实现类
|
||||
@@ -292,7 +293,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
||||
throw new RuntimeException(I18nUtil.getMessage("error.verify.code.invalid"));
|
||||
}
|
||||
StpUtil.logout();
|
||||
|
||||
DevLogUtil.executeLogoutLog(user.getUsername());
|
||||
// 删除记录
|
||||
this.removeById(user.getId());
|
||||
return true;
|
||||
@@ -315,6 +316,17 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
||||
|
||||
// 发送验证码
|
||||
if (StringUtils.hasText(user.getTelephone())) {
|
||||
|
||||
// 获取当前ip
|
||||
String clientIp = IpUtil.getClientIp(CommonServletUtil.getRequest());
|
||||
clientIp = clientIp.replaceAll(":", "");
|
||||
// 使用 setIfAbsent 初始化计数器(只在键不存在时创建,并设置过期时间为1天)
|
||||
boolean isNew = redisUtil.setIfAbsent("exceed_" + clientIp, 1, 1, TimeUnit.DAYS);
|
||||
// 如果键已存在,递增计数器
|
||||
long sendCount = isNew ? 1 : redisUtil.incr("exceed_" + clientIp, 1);
|
||||
|
||||
if (sendCount <= 4) {
|
||||
|
||||
// 发送短信验证码
|
||||
boolean success = smsBaoUtil.sendVerifyCode(user.getTelephone(), code);
|
||||
if (!success) {
|
||||
@@ -323,6 +335,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("account", user.getTelephone());
|
||||
return Result.success(map);
|
||||
}
|
||||
throw new RuntimeException(I18nUtil.getMessage("error.sms.send.exceed"));
|
||||
} else {
|
||||
// 发送邮件验证码
|
||||
boolean success = emailUtil.sendVerifyCode(user.getEmail(), code);
|
||||
|
||||
@@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 验证码服务实现类
|
||||
@@ -30,6 +30,7 @@ public class VerifyCodeServiceImpl implements VerifyCodeService {
|
||||
|
||||
@Override
|
||||
public boolean sendCode(String account, String type) {
|
||||
|
||||
if (!StringUtils.hasText(account)) {
|
||||
throw new RuntimeException(I18nUtil.getMessage("error.account.empty"));
|
||||
}
|
||||
@@ -53,11 +54,24 @@ public class VerifyCodeServiceImpl implements VerifyCodeService {
|
||||
|
||||
// 发送验证码
|
||||
if (AccountUtil.isPhone(account)) {
|
||||
// 获取当前ip
|
||||
String clientIp = IpUtil.getClientIp(CommonServletUtil.getRequest());
|
||||
clientIp = clientIp.replaceAll(":", "");
|
||||
// 校验IP发短信次数
|
||||
// 使用 setIfAbsent 初始化计数器(只在键不存在时创建,并设置过期时间为1天)
|
||||
boolean isNew = redisUtil.setIfAbsent("exceed_" + clientIp, 1, 1, TimeUnit.DAYS);
|
||||
// 如果键已存在,递增计数器
|
||||
long sendCount = isNew ? 1 : redisUtil.incr("exceed_" + clientIp, 1);
|
||||
|
||||
if (sendCount <= 4) {
|
||||
// 发送短信验证码
|
||||
boolean success = smsBaoUtil.sendVerifyCode(account, code);
|
||||
if (!success) {
|
||||
throw new RuntimeException(I18nUtil.getMessage("error.sms.send.failed"));
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException(I18nUtil.getMessage("error.sms.send.exceed"));
|
||||
}
|
||||
} else {
|
||||
// 发送邮件验证码
|
||||
boolean success = emailUtil.sendVerifyCode(account, code);
|
||||
|
||||
@@ -18,8 +18,6 @@ import java.io.InputStream;
|
||||
* 根据ip地址定位工具类,离线方式
|
||||
* 参考地址:<a href="https://gitee.com/lionsoul/ip2region/tree/master/binding/java">ip2region</a>
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2020/3/16 11:25
|
||||
*/
|
||||
@Slf4j
|
||||
public class CommonIpAddressUtil {
|
||||
@@ -62,8 +60,6 @@ public class CommonIpAddressUtil {
|
||||
/**
|
||||
* 获取客户端ip
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2020/3/19 9:32
|
||||
*/
|
||||
public static String getIp(HttpServletRequest request) {
|
||||
if (ObjectUtil.isEmpty(request)) {
|
||||
@@ -81,8 +77,6 @@ public class CommonIpAddressUtil {
|
||||
/**
|
||||
* 根据IP地址离线获取城市
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/4/27 23:14
|
||||
*/
|
||||
public static String getCityInfo(String ip) {
|
||||
try {
|
||||
|
||||
60
src/main/java/com/corewing/app/util/CommonJoinPointUtil.java
Normal file
60
src/main/java/com/corewing/app/util/CommonJoinPointUtil.java
Normal file
@@ -0,0 +1,60 @@
|
||||
package com.corewing.app.util;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.Signature;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CommonJoinPointUtil {
|
||||
|
||||
/**
|
||||
* 获取切面的参数JSON
|
||||
*
|
||||
*/
|
||||
public static String getArgsJsonString(JoinPoint joinPoint) {
|
||||
Signature signature = joinPoint.getSignature();
|
||||
// 参数名数组
|
||||
String[] parameterNames = ((MethodSignature) signature).getParameterNames();
|
||||
// 构造参数组集合
|
||||
Map<String, Object> map = MapUtil.newHashMap();
|
||||
Object[] args = joinPoint.getArgs();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if(ObjectUtil.isNotEmpty(args[i]) && isUsefulParam(args[i])) {
|
||||
if(JSONUtil.isTypeJSON(StrUtil.toString(args[i]))) {
|
||||
try {
|
||||
JSONObject jsonObject = JSONUtil.parseObj(args[i]);
|
||||
if(ObjectUtil.isNotEmpty(jsonObject)) {
|
||||
map.put(parameterNames[i], jsonObject);
|
||||
} else {
|
||||
map.put(parameterNames[i], JSONUtil.parseArray(args[i]));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
map.put(parameterNames[i], null);
|
||||
}
|
||||
} else {
|
||||
map.put(parameterNames[i], JSONUtil.toJsonStr(args[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return JSONUtil.toJsonStr(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否需要拼接的参数,过滤掉HttpServletRequest,MultipartFile,HttpServletResponse等类型参数
|
||||
*
|
||||
*/
|
||||
private static boolean isUsefulParam(Object arg) {
|
||||
return !(arg instanceof MultipartFile) &&
|
||||
!(arg instanceof HttpServletRequest) &&
|
||||
!(arg instanceof HttpServletResponse);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/**
|
||||
* HttpServlet工具类,获取当前request和response
|
||||
*/
|
||||
@@ -18,8 +19,6 @@ public class CommonServletUtil {
|
||||
/**
|
||||
* 从请求中中获取参数
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2021/10/14 10:44
|
||||
**/
|
||||
public static String getParamFromRequest(String paramName) {
|
||||
HttpServletRequest request = getRequest();
|
||||
@@ -47,7 +46,7 @@ public class CommonServletUtil {
|
||||
return paramValue;
|
||||
}
|
||||
|
||||
public static HttpServletRequest getRequest() {
|
||||
public static javax.servlet.http.HttpServletRequest getRequest() {
|
||||
ServletRequestAttributes servletRequestAttributes;
|
||||
try {
|
||||
servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
|
||||
42
src/main/java/com/corewing/app/util/CommonTraceIdUtil.java
Normal file
42
src/main/java/com/corewing/app/util/CommonTraceIdUtil.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.corewing.app.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CommonTraceIdUtil {
|
||||
|
||||
public static final String TRACE_ID_STRING = "traceId";
|
||||
|
||||
private static final InheritableThreadLocal<String> TRACE_ID = new InheritableThreadLocal<>();
|
||||
|
||||
public static String generateTraceId(HttpServletRequest request) {
|
||||
String header = request.getHeader(TRACE_ID_STRING);
|
||||
if (header != null) {
|
||||
return header;
|
||||
}
|
||||
return UUID.randomUUID().toString().replace(StrUtil.DASHED, StrUtil.EMPTY);
|
||||
}
|
||||
|
||||
public static String getTraceId() {
|
||||
return TRACE_ID.get();
|
||||
}
|
||||
|
||||
public static String getTraceId(HttpServletRequest request) {
|
||||
String traceId = getTraceId();
|
||||
if (traceId == null) {
|
||||
traceId = generateTraceId(request);
|
||||
setTraceId(traceId);
|
||||
}
|
||||
return traceId;
|
||||
}
|
||||
|
||||
public static void setTraceId(String traceId) {
|
||||
TRACE_ID.set(traceId);
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
TRACE_ID.remove();
|
||||
}
|
||||
}
|
||||
66
src/main/java/com/corewing/app/util/CommonUaUtil.java
Normal file
66
src/main/java/com/corewing/app/util/CommonUaUtil.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package com.corewing.app.util;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.servlet.ServletUtil;
|
||||
import cn.hutool.http.useragent.Browser;
|
||||
import cn.hutool.http.useragent.UserAgent;
|
||||
import cn.hutool.http.useragent.UserAgentUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 用户代理工具类
|
||||
*
|
||||
*/
|
||||
public class CommonUaUtil {
|
||||
|
||||
/**
|
||||
* 获取客户端浏览器
|
||||
*
|
||||
*/
|
||||
public static String getBrowser(HttpServletRequest request) {
|
||||
UserAgent userAgent = getUserAgent(request);
|
||||
if (ObjectUtil.isEmpty(userAgent)) {
|
||||
return StrUtil.DASHED;
|
||||
} else {
|
||||
String browser = userAgent.getBrowser().toString();
|
||||
if (StrUtil.isNotBlank(browser) && browser.length() > 250) {
|
||||
browser = browser.substring(0, 250);
|
||||
}
|
||||
return "Unknown".equals(browser) ? StrUtil.DASHED : browser;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端操作系统
|
||||
*
|
||||
*/
|
||||
public static String getOs(HttpServletRequest request) {
|
||||
UserAgent userAgent = getUserAgent(request);
|
||||
if (ObjectUtil.isEmpty(userAgent)) {
|
||||
return StrUtil.DASHED;
|
||||
} else {
|
||||
String os = userAgent.getOs().toString();
|
||||
if (StrUtil.isNotBlank(os) && os.length() > 250) {
|
||||
os = os.substring(0, 250);
|
||||
}
|
||||
return "Unknown".equals(os) ? StrUtil.DASHED : os;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取请求代理头
|
||||
*
|
||||
*/
|
||||
private static UserAgent getUserAgent(HttpServletRequest request) {
|
||||
String userAgentStr = ServletUtil.getHeaderIgnoreCase(request, "User-Agent");
|
||||
UserAgent userAgent = UserAgentUtil.parse(userAgentStr);
|
||||
if (ObjectUtil.isNotEmpty(userAgentStr)) {
|
||||
if ("Unknown".equals(userAgent.getBrowser().getName())) {
|
||||
userAgent.setBrowser(new Browser(userAgentStr, null, ""));
|
||||
}
|
||||
}
|
||||
return userAgent;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,526 @@
|
||||
package com.corewing.app.util;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
|
||||
public class DateUtils {
|
||||
|
||||
// 格式化LocalDateTime为字符串
|
||||
public static void main(String[] args) {
|
||||
//2026-02-24 08:40:90
|
||||
System.out.println(isAfter(parseToLocalDateTime("2026-02-22 08:40:30")));
|
||||
}
|
||||
|
||||
//==================== 字符串格式化方法 ====================
|
||||
|
||||
/**
|
||||
* 将字符串格式化为LocalDateTime
|
||||
* @param dateTimeStr 日期时间字符串
|
||||
* @param pattern 格式模式,如:yyyy-MM-dd HH:mm:ss
|
||||
* @return LocalDateTime对象
|
||||
*/
|
||||
public static LocalDateTime parseToLocalDateTime(String dateTimeStr, String pattern) {
|
||||
if (dateTimeStr == null || dateTimeStr.isEmpty() || pattern == null || pattern.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return LocalDateTime.parse(dateTimeStr, formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串格式化为LocalDate
|
||||
* @param dateStr 日期字符串
|
||||
* @param pattern 格式模式,如:yyyy-MM-dd
|
||||
* @return LocalDate对象
|
||||
*/
|
||||
public static LocalDate parseToLocalDate(String dateStr, String pattern) {
|
||||
if (dateStr == null || dateStr.isEmpty() || pattern == null || pattern.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return LocalDate.parse(dateStr, formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串格式化为LocalTime
|
||||
* @param timeStr 时间字符串
|
||||
* @param pattern 格式模式,如:HH:mm:ss
|
||||
* @return LocalTime对象
|
||||
*/
|
||||
public static LocalTime parseToLocalTime(String timeStr, String pattern) {
|
||||
if (timeStr == null || timeStr.isEmpty() || pattern == null || pattern.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return LocalTime.parse(timeStr, formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串格式化为Date
|
||||
* @param dateTimeStr 日期时间字符串
|
||||
* @param pattern 格式模式,如:yyyy-MM-dd HH:mm:ss
|
||||
* @return Date对象
|
||||
*/
|
||||
public static Date parseToDate(String dateTimeStr, String pattern) {
|
||||
if (dateTimeStr == null || dateTimeStr.isEmpty() || pattern == null || pattern.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
||||
return sdf.parse(dateTimeStr);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("日期解析失败: " + dateTimeStr, e);
|
||||
}
|
||||
}
|
||||
|
||||
//==================== 常用格式的快捷方法 ====================
|
||||
|
||||
/**
|
||||
* 将字符串格式化为LocalDateTime(默认格式:yyyy-MM-dd HH:mm:ss)
|
||||
*/
|
||||
public static LocalDateTime parseToLocalDateTime(String dateTimeStr) {
|
||||
return parseToLocalDateTime(dateTimeStr, "yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串格式化为LocalDate(默认格式:yyyy-MM-dd)
|
||||
*/
|
||||
public static LocalDate parseToLocalDate(String dateStr) {
|
||||
return parseToLocalDate(dateStr, "yyyy-MM-dd");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串格式化为LocalTime(默认格式:HH:mm:ss)
|
||||
*/
|
||||
public static LocalTime parseToLocalTime(String timeStr) {
|
||||
return parseToLocalTime(timeStr, "HH:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串格式化为Date(默认格式:yyyy-MM-dd HH:mm:ss)
|
||||
*/
|
||||
public static Date parseToDate(String dateTimeStr) {
|
||||
return parseToDate(dateTimeStr, "yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
//==================== 智能解析方法 ====================
|
||||
|
||||
/**
|
||||
* 智能解析字符串为LocalDateTime(自动识别常见格式)
|
||||
* 支持格式:
|
||||
* - yyyy-MM-dd HH:mm:ss
|
||||
* - yyyy/MM/dd HH:mm:ss
|
||||
* - yyyy-MM-dd'T'HH:mm:ss
|
||||
* - yyyy-MM-dd HH:mm
|
||||
* - yyyy-MM-dd
|
||||
* - yyyy/MM/dd
|
||||
*/
|
||||
public static LocalDateTime smartParseToLocalDateTime(String dateTimeStr) {
|
||||
if (dateTimeStr == null || dateTimeStr.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String str = dateTimeStr.trim();
|
||||
|
||||
// 尝试各种格式
|
||||
try {
|
||||
// 格式1: yyyy-MM-dd HH:mm:ss
|
||||
return LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
} catch (Exception e1) {
|
||||
try {
|
||||
// 格式2: yyyy/MM/dd HH:mm:ss
|
||||
return LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
|
||||
} catch (Exception e2) {
|
||||
try {
|
||||
// 格式3: yyyy-MM-dd'T'HH:mm:ss
|
||||
return LocalDateTime.parse(str, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
|
||||
} catch (Exception e3) {
|
||||
try {
|
||||
// 格式4: yyyy-MM-dd HH:mm
|
||||
return LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
|
||||
} catch (Exception e4) {
|
||||
try {
|
||||
// 格式5: yyyy-MM-dd (转为当天开始时间)
|
||||
LocalDate date = LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
return date.atStartOfDay();
|
||||
} catch (Exception e5) {
|
||||
try {
|
||||
// 格式6: yyyy/MM/dd
|
||||
LocalDate date = LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
||||
return date.atStartOfDay();
|
||||
} catch (Exception e6) {
|
||||
throw new IllegalArgumentException("无法解析的日期时间字符串: " + str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能解析字符串为LocalDate(自动识别常见格式)
|
||||
* 支持格式:
|
||||
* - yyyy-MM-dd
|
||||
* - yyyy/MM/dd
|
||||
* - yyyyMMdd
|
||||
* - dd/MM/yyyy
|
||||
*/
|
||||
public static LocalDate smartParseToLocalDate(String dateStr) {
|
||||
if (dateStr == null || dateStr.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String str = dateStr.trim();
|
||||
|
||||
try {
|
||||
return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
} catch (Exception e1) {
|
||||
try {
|
||||
return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
||||
} catch (Exception e2) {
|
||||
try {
|
||||
return LocalDate.parse(str, DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
} catch (Exception e3) {
|
||||
try {
|
||||
return LocalDate.parse(str, DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
||||
} catch (Exception e4) {
|
||||
throw new IllegalArgumentException("无法解析的日期字符串: " + str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==================== 格式化输出方法 ====================
|
||||
|
||||
/**
|
||||
* 将LocalDateTime格式化为字符串
|
||||
* @param dateTime LocalDateTime对象
|
||||
* @param pattern 格式模式
|
||||
* @return 格式化后的字符串
|
||||
*/
|
||||
public static String format(LocalDateTime dateTime, String pattern) {
|
||||
if (dateTime == null || pattern == null || pattern.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return dateTime.format(formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将LocalDate格式化为字符串
|
||||
*/
|
||||
public static String format(LocalDate date, String pattern) {
|
||||
if (date == null || pattern == null || pattern.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return date.format(formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将LocalTime格式化为字符串
|
||||
*/
|
||||
public static String format(LocalTime time, String pattern) {
|
||||
if (time == null || pattern == null || pattern.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return time.format(formatter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Date格式化为字符串
|
||||
*/
|
||||
public static String format(Date time, String pattern) {
|
||||
if (time == null || pattern == null || pattern.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
// 创建SimpleDateFormat实例
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
||||
// 格式化日期为字符串
|
||||
return sdf.format(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将LocalDateTime格式化为默认格式:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String formatDateTime(LocalDateTime dateTime) {
|
||||
return format(dateTime, "yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将LocalDate格式化为默认格式:yyyy-MM-dd
|
||||
*/
|
||||
public static String formatDate(LocalDate date) {
|
||||
return format(date, "yyyy-MM-dd");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将LocalTime格式化为默认格式:HH:mm:ss
|
||||
*/
|
||||
public static String formatTime(LocalTime time) {
|
||||
return format(time, "HH:mm:ss");
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Date格式化为默认格式:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String formatDateTime(Date date) {
|
||||
return format(date, "yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
|
||||
//==================== 判断方法 ====================
|
||||
|
||||
/**
|
||||
* 判断传入时间是否大于当前时间
|
||||
* @param time 支持:Date, LocalDateTime, LocalDate, String
|
||||
*/
|
||||
public static boolean isAfter(Object time) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
return dateTime.isAfter(LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入时间是否小于当前时间
|
||||
* @param time 支持:Date, LocalDateTime, LocalDate, String
|
||||
*/
|
||||
public static boolean isBefore(Object time) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
return dateTime.isBefore(LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入时间是否等于当前时间(近似到分钟)
|
||||
* @param time 支持:Date, LocalDateTime, LocalDate, String
|
||||
*/
|
||||
public static boolean isEqual(Object time) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
LocalDateTime now = LocalDateTime.now().withSecond(0).withNano(0);
|
||||
return dateTime.withSecond(0).withNano(0).isEqual(now);
|
||||
}
|
||||
|
||||
//==================== 日期时间专用判断 ====================
|
||||
|
||||
/**
|
||||
* 判断传入时间是否大于等于当前时间
|
||||
*/
|
||||
public static boolean isAfterOrEqual(Object time) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
return !dateTime.isBefore(LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入时间是否小于等于当前时间
|
||||
*/
|
||||
public static boolean isBeforeOrEqual(Object time) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
return !dateTime.isAfter(LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入时间是否大于等于指定时间
|
||||
* @param time 要判断的时间
|
||||
* @param targetTime 目标时间
|
||||
*/
|
||||
public static boolean isAfterOrEqual(Object time, Object targetTime) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
LocalDateTime target = convertToLocalDateTime(targetTime);
|
||||
return !dateTime.isBefore(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入时间是否小于等于指定时间
|
||||
* @param time 要判断的时间
|
||||
* @param targetTime 目标时间
|
||||
*/
|
||||
public static boolean isBeforeOrEqual(Object time, Object targetTime) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
LocalDateTime target = convertToLocalDateTime(targetTime);
|
||||
return !dateTime.isAfter(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入时间是否在指定时间范围内(包含边界)
|
||||
* @param time 要判断的时间
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
*/
|
||||
public static boolean isBetween(Object time, Object start, Object end) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
LocalDateTime startTime = convertToLocalDateTime(start);
|
||||
LocalDateTime endTime = convertToLocalDateTime(end);
|
||||
return !dateTime.isBefore(startTime) && !dateTime.isAfter(endTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入时间是否在指定时间范围内(不包含边界)
|
||||
* @param time 要判断的时间
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
*/
|
||||
public static boolean isBetweenExclusive(Object time, Object start, Object end) {
|
||||
LocalDateTime dateTime = convertToLocalDateTime(time);
|
||||
LocalDateTime startTime = convertToLocalDateTime(start);
|
||||
LocalDateTime endTime = convertToLocalDateTime(end);
|
||||
return dateTime.isAfter(startTime) && dateTime.isBefore(endTime);
|
||||
}
|
||||
|
||||
//==================== 两个时间比较 ====================
|
||||
|
||||
/**
|
||||
* 判断time1是否大于time2
|
||||
*/
|
||||
public static boolean isAfter(Object time1, Object time2) {
|
||||
LocalDateTime dt1 = convertToLocalDateTime(time1);
|
||||
LocalDateTime dt2 = convertToLocalDateTime(time2);
|
||||
return dt1.isAfter(dt2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断time1是否小于time2
|
||||
*/
|
||||
public static boolean isBefore(Object time1, Object time2) {
|
||||
LocalDateTime dt1 = convertToLocalDateTime(time1);
|
||||
LocalDateTime dt2 = convertToLocalDateTime(time2);
|
||||
return dt1.isBefore(dt2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个时间是否相等
|
||||
*/
|
||||
public static boolean isEqual(Object time1, Object time2) {
|
||||
LocalDateTime dt1 = convertToLocalDateTime(time1);
|
||||
LocalDateTime dt2 = convertToLocalDateTime(time2);
|
||||
return dt1.isEqual(dt2);
|
||||
}
|
||||
|
||||
//==================== 日期专用判断 ====================
|
||||
|
||||
/**
|
||||
* 判断传入日期是否大于今天(只比较年月日)
|
||||
*/
|
||||
public static boolean isAfterDate(Object date) {
|
||||
LocalDate localDate = convertToLocalDate(date);
|
||||
return localDate.isAfter(LocalDate.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入日期是否小于今天(只比较年月日)
|
||||
*/
|
||||
public static boolean isBeforeDate(Object date) {
|
||||
LocalDate localDate = convertToLocalDate(date);
|
||||
return localDate.isBefore(LocalDate.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入日期是否等于今天
|
||||
*/
|
||||
public static boolean isToday(Object date) {
|
||||
LocalDate localDate = convertToLocalDate(date);
|
||||
return localDate.isEqual(LocalDate.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入日期是否大于等于今天(只比较年月日)
|
||||
*/
|
||||
public static boolean isAfterOrEqualDate(Object date) {
|
||||
LocalDate localDate = convertToLocalDate(date);
|
||||
return !localDate.isBefore(LocalDate.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断传入日期是否小于等于今天(只比较年月日)
|
||||
*/
|
||||
public static boolean isBeforeOrEqualDate(Object date) {
|
||||
LocalDate localDate = convertToLocalDate(date);
|
||||
return !localDate.isAfter(LocalDate.now());
|
||||
}
|
||||
|
||||
//==================== 私有转换方法 ====================
|
||||
|
||||
/**
|
||||
* 将各种类型转换为LocalDateTime
|
||||
*/
|
||||
private static LocalDateTime convertToLocalDateTime(Object time) {
|
||||
if (time == null) {
|
||||
throw new IllegalArgumentException("时间不能为null");
|
||||
}
|
||||
|
||||
// 1. LocalDateTime
|
||||
if (time instanceof LocalDateTime) {
|
||||
return (LocalDateTime) time;
|
||||
}
|
||||
|
||||
// 2. LocalDate
|
||||
if (time instanceof LocalDate) {
|
||||
return ((LocalDate) time).atStartOfDay();
|
||||
}
|
||||
|
||||
// 3. Date
|
||||
if (time instanceof Date) {
|
||||
return ((Date) time).toInstant()
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDateTime();
|
||||
}
|
||||
|
||||
// 4. String
|
||||
if (time instanceof String) {
|
||||
return smartParseToLocalDateTime((String) time);
|
||||
}
|
||||
|
||||
// 5. Long (时间戳)
|
||||
if (time instanceof Long) {
|
||||
return LocalDateTime.ofInstant(
|
||||
java.time.Instant.ofEpochMilli((Long) time),
|
||||
ZoneId.systemDefault()
|
||||
);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("不支持的时间类型: " + time.getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将各种类型转换为LocalDate
|
||||
*/
|
||||
private static LocalDate convertToLocalDate(Object date) {
|
||||
if (date == null) {
|
||||
throw new IllegalArgumentException("日期不能为null");
|
||||
}
|
||||
|
||||
// 1. LocalDate
|
||||
if (date instanceof LocalDate) {
|
||||
return (LocalDate) date;
|
||||
}
|
||||
|
||||
// 2. LocalDateTime
|
||||
if (date instanceof LocalDateTime) {
|
||||
return ((LocalDateTime) date).toLocalDate();
|
||||
}
|
||||
|
||||
// 3. Date
|
||||
if (date instanceof Date) {
|
||||
return ((Date) date).toInstant()
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate();
|
||||
}
|
||||
|
||||
// 4. String
|
||||
if (date instanceof String) {
|
||||
return smartParseToLocalDate((String) date);
|
||||
}
|
||||
|
||||
// 5. Long (时间戳)
|
||||
if (date instanceof Long) {
|
||||
return LocalDateTime.ofInstant(
|
||||
java.time.Instant.ofEpochMilli((Long) date),
|
||||
ZoneId.systemDefault()
|
||||
).toLocalDate();
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("不支持的日期类型: " + date.getClass().getName());
|
||||
}
|
||||
}
|
||||
143
src/main/java/com/corewing/app/util/DevLogUtil.java
Normal file
143
src/main/java/com/corewing/app/util/DevLogUtil.java
Normal file
@@ -0,0 +1,143 @@
|
||||
package com.corewing.app.util;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.corewing.app.common.annotation.CommonLog;
|
||||
import com.corewing.app.entity.DevLog;
|
||||
import com.corewing.app.enums.DevLogCategoryEnum;
|
||||
import com.corewing.app.enums.DevLogExeStatusEnum;
|
||||
import com.corewing.app.service.DevLogService;
|
||||
import org.apache.commons.codec.digest.Md5Crypt;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
/**
|
||||
* 日志工具类
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/9/2 15:26
|
||||
*/
|
||||
public class DevLogUtil {
|
||||
|
||||
private static final DevLogService devLogService = SpringUtil.getBean(DevLogService.class);
|
||||
|
||||
/**
|
||||
* 记录操作日志
|
||||
*
|
||||
*/
|
||||
public static void executeOperationLog(CommonLog commonLog, String userName, String userId, JoinPoint joinPoint, String resultJson) {
|
||||
HttpServletRequest request = CommonServletUtil.getRequest();
|
||||
String requestURI = request.getRequestURI();
|
||||
String method = request.getRequestURI();
|
||||
DevLog devLog = genBasOpLog();
|
||||
ThreadUtil.execute(() -> {
|
||||
devLog.setCategory(DevLogCategoryEnum.APP_OPERATE.getValue());
|
||||
devLog.setName(commonLog.value());
|
||||
devLog.setExeStatus(DevLogExeStatusEnum.SUCCESS.getValue());
|
||||
devLog.setClassName(joinPoint.getTarget().getClass().getName());
|
||||
devLog.setMethodName(joinPoint.getSignature().getName());
|
||||
devLog.setReqMethod(method);
|
||||
devLog.setReqUrl(requestURI);
|
||||
devLog.setParamJson(CommonJoinPointUtil.getArgsJsonString(joinPoint));
|
||||
devLog.setResultJson(resultJson);
|
||||
devLog.setOpTime(DateTime.now());
|
||||
devLog.setOpUser(userName);
|
||||
devLog.setCreateUser(userId);
|
||||
creatLogSignValue(devLog);
|
||||
devLogService.save(devLog);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录异常日志
|
||||
*
|
||||
*/
|
||||
public static void executeExceptionLog(CommonLog commonLog, String userName, String userId, JoinPoint joinPoint, Exception exception) {
|
||||
HttpServletRequest request = CommonServletUtil.getRequest();
|
||||
String requestURI = request.getRequestURI();
|
||||
String method = request.getRequestURI();
|
||||
DevLog devLog = genBasOpLog();
|
||||
ThreadUtil.execute(() -> {
|
||||
devLog.setCategory(DevLogCategoryEnum.APP_EXCEPTION.getValue());
|
||||
devLog.setName(commonLog.value());
|
||||
devLog.setExeStatus(DevLogExeStatusEnum.FAIL.getValue());
|
||||
devLog.setExeMessage(ExceptionUtil.stacktraceToString(exception, Integer.MAX_VALUE));
|
||||
devLog.setClassName(joinPoint.getTarget().getClass().getName());
|
||||
devLog.setMethodName(joinPoint.getSignature().getName());
|
||||
devLog.setReqMethod(method);
|
||||
devLog.setReqUrl(requestURI);
|
||||
devLog.setParamJson(CommonJoinPointUtil.getArgsJsonString(joinPoint));
|
||||
devLog.setOpTime(DateTime.now());
|
||||
devLog.setOpUser(userName);
|
||||
devLog.setCreateUser(userId);
|
||||
creatLogSignValue(devLog);
|
||||
devLogService.save(devLog);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录日志
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/9/2 16:08
|
||||
*/
|
||||
public static void executeLoginLog(String userName) {
|
||||
DevLog devLog = genBasOpLog();
|
||||
ThreadUtil.execute(() -> {
|
||||
devLog.setCategory(DevLogCategoryEnum.APP_LOGIN.getValue());
|
||||
devLog.setName("用户登录");
|
||||
devLog.setExeStatus(DevLogExeStatusEnum.SUCCESS.getValue());
|
||||
devLog.setOpTime(DateTime.now());
|
||||
devLog.setOpUser(userName);
|
||||
creatLogSignValue(devLog);
|
||||
devLogService.save(devLog);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登出日志
|
||||
*
|
||||
* @author xuyuxiang
|
||||
* @date 2022/9/2 16:08
|
||||
*/
|
||||
public static void executeLogoutLog(String userName) {
|
||||
DevLog devLog = genBasOpLog();
|
||||
ThreadUtil.execute(() -> {
|
||||
devLog.setCategory(DevLogCategoryEnum.APP_LOGOUT.getValue());
|
||||
devLog.setName("用户登出");
|
||||
devLog.setExeStatus(DevLogExeStatusEnum.SUCCESS.getValue());
|
||||
devLog.setOpTime(DateTime.now());
|
||||
devLog.setOpUser(userName);
|
||||
creatLogSignValue(devLog);
|
||||
devLogService.save(devLog);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建基础操作日志
|
||||
*
|
||||
*/
|
||||
private static DevLog genBasOpLog() {
|
||||
HttpServletRequest request = CommonServletUtil.getRequest();
|
||||
String ip = IpUtil.getClientIp(request);
|
||||
DevLog devLog = new DevLog();
|
||||
devLog.setOpIp(ip);
|
||||
devLog.setOpAddress(CommonIpAddressUtil.getCityInfo(ip));
|
||||
devLog.setOpBrowser(CommonUaUtil.getBrowser(request));
|
||||
devLog.setOpOs(CommonUaUtil.getOs(request));
|
||||
return devLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建日志完整性保护签名数据
|
||||
*/
|
||||
private static void creatLogSignValue (DevLog devLog) {
|
||||
String logStr = devLog.toString().replaceAll(" +","");
|
||||
devLog.setSignData(Md5Crypt.md5Crypt(logStr.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,43 @@ public class RedisUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通缓存放入并设置时间
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param time 时间(天)
|
||||
* @return true成功 false 失败
|
||||
*/
|
||||
public boolean set(String key, Object value, Integer time, TimeUnit timeUnit) {
|
||||
try {
|
||||
redisTemplate.opsForValue().set(key, value, time, timeUnit);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通缓存放入并设置时间(仅在键不存在时设置)
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
* @param time 时间
|
||||
* @param timeUnit 时间单位
|
||||
* @return true成功 false失败(键已存在或设置失败)
|
||||
*/
|
||||
public boolean setIfAbsent(String key, Object value, long time, TimeUnit timeUnit) {
|
||||
try {
|
||||
Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, time, timeUnit);
|
||||
return result != null && result;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递增
|
||||
*
|
||||
|
||||
107
src/main/resources/application-local.properties
Normal file
107
src/main/resources/application-local.properties
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
# 数据源配置
|
||||
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://120.24.204.180:3306/app?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
spring.datasource.username=app
|
||||
spring.datasource.password=AB636NGhhH2cC5A5
|
||||
|
||||
# Druid 连接池配置
|
||||
spring.datasource.druid.initial-size=5
|
||||
spring.datasource.druid.min-idle=5
|
||||
spring.datasource.druid.max-active=20
|
||||
spring.datasource.druid.max-wait=60000
|
||||
spring.datasource.druid.test-while-idle=true
|
||||
spring.datasource.druid.test-on-borrow=false
|
||||
spring.datasource.druid.test-on-return=false
|
||||
spring.datasource.druid.time-between-eviction-runs-millis=60000
|
||||
spring.datasource.druid.min-evictable-idle-time-millis=300000
|
||||
spring.datasource.druid.validation-query=SELECT 1
|
||||
spring.datasource.druid.pool-prepared-statements=true
|
||||
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
|
||||
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
|
||||
spring.datasource.druid.filters=stat,wall
|
||||
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
|
||||
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
|
||||
|
||||
# MyBatis-Plus 配置
|
||||
mybatis-plus.mapper-locations=classpath*:/mapper/**/*.xml
|
||||
mybatis-plus.type-aliases-package=com.corewing.app.entity
|
||||
mybatis-plus.configuration.map-underscore-to-camel-case=true
|
||||
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
mybatis-plus.global-config.db-config.id-type=ASSIGN_ID
|
||||
mybatis-plus.global-config.db-config.table-prefix=
|
||||
# ========== 逻辑删除核心配置 ==========
|
||||
# 1. 自定义逻辑删除字段名(替换为你的字段,如 is_delete、del_flag 等)
|
||||
mybatis-plus.global-config.db-config.logic-delete-field=del_flag
|
||||
# 2. 逻辑未删除值(替换为你的业务未删除值,如 0、false、N 等)
|
||||
mybatis-plus.global-config.db-config.logic-not-delete-value=NOT_DELETE
|
||||
# 3. 逻辑已删除值(替换为你的业务已删除值,如 1、true、Y 等)
|
||||
mybatis-plus.global-config.db-config.logic-delete-value=DELETE
|
||||
|
||||
# Redis 配置
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
spring.redis.password=
|
||||
spring.redis.database=0
|
||||
spring.redis.timeout=3000
|
||||
spring.redis.lettuce.pool.max-active=8
|
||||
spring.redis.lettuce.pool.max-idle=8
|
||||
spring.redis.lettuce.pool.min-idle=0
|
||||
spring.redis.lettuce.pool.max-wait=-1ms
|
||||
|
||||
# MongoDB 配置
|
||||
#spring.data.mongodb.host=120.24.204.180
|
||||
#spring.data.mongodb.database=app
|
||||
#spring.data.mongodb.port=27017
|
||||
|
||||
# Sa-Token 配置
|
||||
sa-token.token-name=Authorization
|
||||
sa-token.timeout=2592000
|
||||
sa-token.active-timeout=-1
|
||||
sa-token.is-concurrent=true
|
||||
sa-token.is-share=true
|
||||
sa-token.token-style=uuid
|
||||
sa-token.is-log=false
|
||||
|
||||
# 短信宝配置
|
||||
# 请前往 https://www.smsbao.com/ 注册账号并获取用户名和密码
|
||||
smsbao.username=corewing
|
||||
smsbao.password=755dc3ac40c94d319cf6e314f24dc659
|
||||
|
||||
# 邮件配置
|
||||
# SMTP 服务器地址
|
||||
spring.mail.host=smtp.em.dingtalk.com
|
||||
# SMTP 服务器端口(465 为 SSL 加密端口)
|
||||
spring.mail.port=465
|
||||
# 发件人邮箱
|
||||
spring.mail.username=dev@corewing.com
|
||||
# 邮箱授权码(不是邮箱密码!需要在邮箱设置中开启 SMTP 服务并获取授权码)
|
||||
spring.mail.password=t035gngwYl0xgvZF
|
||||
# 编码格式
|
||||
spring.mail.default-encoding=UTF-8
|
||||
# 其他配置
|
||||
spring.mail.properties.mail.smtp.auth=true
|
||||
# 465 端口使用 SSL 加密,需要启用 SSL
|
||||
spring.mail.properties.mail.smtp.ssl.enable=true
|
||||
spring.mail.properties.mail.smtp.ssl.required=true
|
||||
# SSL Socket Factory 配置
|
||||
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
|
||||
spring.mail.properties.mail.smtp.socketFactory.port=465
|
||||
spring.mail.properties.mail.smtp.socketFactory.fallback=false
|
||||
|
||||
# 钉钉机器人配置
|
||||
# 请前往钉钉群设置 -> 智能群助手 -> 添加机器人 -> 自定义机器人,获取 Webhook 地址和密钥
|
||||
dingtalk.webhook=https://oapi.dingtalk.com/robot/send?access_token=7eed4b3483303c9ec71ef37a08c347bb597fd4c64211a96a8f55f72405ff6444
|
||||
# 如果使用加签安全设置,请填写密钥(secret)
|
||||
dingtalk.secret=SEC0f2b835f28139905e3c0b5be979b215df1735f1154f36514aafbae8708014148
|
||||
|
||||
|
||||
|
||||
# ===================== Knife4j 核心增强配置 =====================
|
||||
# 启用Knife4j增强模式
|
||||
knife4j.enable=true
|
||||
knife4j.setting.language=zh_cn
|
||||
knife4j.basic.enable=true
|
||||
knife4j.basic.username=corewing
|
||||
knife4j.basic.password=Aaa123..
|
||||
107
src/main/resources/application-prod.properties
Normal file
107
src/main/resources/application-prod.properties
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
# 数据源配置
|
||||
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/app?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
spring.datasource.username=app
|
||||
spring.datasource.password=AB636NGhhH2cC5A5
|
||||
|
||||
# Druid 连接池配置
|
||||
spring.datasource.druid.initial-size=5
|
||||
spring.datasource.druid.min-idle=5
|
||||
spring.datasource.druid.max-active=20
|
||||
spring.datasource.druid.max-wait=60000
|
||||
spring.datasource.druid.test-while-idle=true
|
||||
spring.datasource.druid.test-on-borrow=false
|
||||
spring.datasource.druid.test-on-return=false
|
||||
spring.datasource.druid.time-between-eviction-runs-millis=60000
|
||||
spring.datasource.druid.min-evictable-idle-time-millis=300000
|
||||
spring.datasource.druid.validation-query=SELECT 1
|
||||
spring.datasource.druid.pool-prepared-statements=true
|
||||
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
|
||||
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
|
||||
spring.datasource.druid.filters=stat,wall
|
||||
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
|
||||
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
|
||||
|
||||
# MyBatis-Plus 配置
|
||||
mybatis-plus.mapper-locations=classpath*:/mapper/**/*.xml
|
||||
mybatis-plus.type-aliases-package=com.corewing.app.entity
|
||||
mybatis-plus.configuration.map-underscore-to-camel-case=true
|
||||
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
mybatis-plus.global-config.db-config.id-type=ASSIGN_ID
|
||||
mybatis-plus.global-config.db-config.table-prefix=
|
||||
# ========== 逻辑删除核心配置 ==========
|
||||
# 1. 自定义逻辑删除字段名(替换为你的字段,如 is_delete、del_flag 等)
|
||||
mybatis-plus.global-config.db-config.logic-delete-field=del_flag
|
||||
# 2. 逻辑未删除值(替换为你的业务未删除值,如 0、false、N 等)
|
||||
mybatis-plus.global-config.db-config.logic-not-delete-value=NOT_DELETE
|
||||
# 3. 逻辑已删除值(替换为你的业务已删除值,如 1、true、Y 等)
|
||||
mybatis-plus.global-config.db-config.logic-delete-value=DELETE
|
||||
|
||||
# Redis 配置
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
spring.redis.password=
|
||||
spring.redis.database=0
|
||||
spring.redis.timeout=3000
|
||||
spring.redis.lettuce.pool.max-active=8
|
||||
spring.redis.lettuce.pool.max-idle=8
|
||||
spring.redis.lettuce.pool.min-idle=0
|
||||
spring.redis.lettuce.pool.max-wait=-1ms
|
||||
|
||||
# MongoDB 配置
|
||||
#spring.data.mongodb.host=120.24.204.180
|
||||
#spring.data.mongodb.database=app
|
||||
#spring.data.mongodb.port=27017
|
||||
|
||||
# Sa-Token 配置
|
||||
sa-token.token-name=Authorization
|
||||
sa-token.timeout=2592000
|
||||
sa-token.active-timeout=-1
|
||||
sa-token.is-concurrent=true
|
||||
sa-token.is-share=true
|
||||
sa-token.token-style=uuid
|
||||
sa-token.is-log=false
|
||||
|
||||
# 短信宝配置
|
||||
# 请前往 https://www.smsbao.com/ 注册账号并获取用户名和密码
|
||||
smsbao.username=corewing
|
||||
smsbao.password=755dc3ac40c94d319cf6e314f24dc659
|
||||
|
||||
# 邮件配置
|
||||
# SMTP 服务器地址
|
||||
spring.mail.host=smtp.em.dingtalk.com
|
||||
# SMTP 服务器端口(465 为 SSL 加密端口)
|
||||
spring.mail.port=465
|
||||
# 发件人邮箱
|
||||
spring.mail.username=dev@corewing.com
|
||||
# 邮箱授权码(不是邮箱密码!需要在邮箱设置中开启 SMTP 服务并获取授权码)
|
||||
spring.mail.password=t035gngwYl0xgvZF
|
||||
# 编码格式
|
||||
spring.mail.default-encoding=UTF-8
|
||||
# 其他配置
|
||||
spring.mail.properties.mail.smtp.auth=true
|
||||
# 465 端口使用 SSL 加密,需要启用 SSL
|
||||
spring.mail.properties.mail.smtp.ssl.enable=true
|
||||
spring.mail.properties.mail.smtp.ssl.required=true
|
||||
# SSL Socket Factory 配置
|
||||
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
|
||||
spring.mail.properties.mail.smtp.socketFactory.port=465
|
||||
spring.mail.properties.mail.smtp.socketFactory.fallback=false
|
||||
|
||||
# 钉钉机器人配置
|
||||
# 请前往钉钉群设置 -> 智能群助手 -> 添加机器人 -> 自定义机器人,获取 Webhook 地址和密钥
|
||||
dingtalk.webhook=https://oapi.dingtalk.com/robot/send?access_token=7eed4b3483303c9ec71ef37a08c347bb597fd4c64211a96a8f55f72405ff6444
|
||||
# 如果使用加签安全设置,请填写密钥(secret)
|
||||
dingtalk.secret=SEC0f2b835f28139905e3c0b5be979b215df1735f1154f36514aafbae8708014148
|
||||
|
||||
|
||||
|
||||
# ===================== Knife4j 核心增强配置 =====================
|
||||
# 启用Knife4j增强模式
|
||||
knife4j.enable=true
|
||||
knife4j.setting.language=zh_cn
|
||||
knife4j.basic.enable=true
|
||||
knife4j.basic.username=corewing
|
||||
knife4j.basic.password=Aaa123..
|
||||
107
src/main/resources/application-test.properties
Normal file
107
src/main/resources/application-test.properties
Normal file
@@ -0,0 +1,107 @@
|
||||
|
||||
# 数据源配置
|
||||
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/app?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=123456
|
||||
|
||||
# Druid 连接池配置
|
||||
spring.datasource.druid.initial-size=5
|
||||
spring.datasource.druid.min-idle=5
|
||||
spring.datasource.druid.max-active=20
|
||||
spring.datasource.druid.max-wait=60000
|
||||
spring.datasource.druid.test-while-idle=true
|
||||
spring.datasource.druid.test-on-borrow=false
|
||||
spring.datasource.druid.test-on-return=false
|
||||
spring.datasource.druid.time-between-eviction-runs-millis=60000
|
||||
spring.datasource.druid.min-evictable-idle-time-millis=300000
|
||||
spring.datasource.druid.validation-query=SELECT 1
|
||||
spring.datasource.druid.pool-prepared-statements=true
|
||||
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
|
||||
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
|
||||
spring.datasource.druid.filters=stat,wall
|
||||
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
|
||||
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
|
||||
|
||||
# MyBatis-Plus 配置
|
||||
mybatis-plus.mapper-locations=classpath*:/mapper/**/*.xml
|
||||
mybatis-plus.type-aliases-package=com.corewing.app.entity
|
||||
mybatis-plus.configuration.map-underscore-to-camel-case=true
|
||||
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
mybatis-plus.global-config.db-config.id-type=ASSIGN_ID
|
||||
mybatis-plus.global-config.db-config.table-prefix=
|
||||
# ========== 逻辑删除核心配置 ==========
|
||||
# 1. 自定义逻辑删除字段名(替换为你的字段,如 is_delete、del_flag 等)
|
||||
mybatis-plus.global-config.db-config.logic-delete-field=del_flag
|
||||
# 2. 逻辑未删除值(替换为你的业务未删除值,如 0、false、N 等)
|
||||
mybatis-plus.global-config.db-config.logic-not-delete-value=NOT_DELETE
|
||||
# 3. 逻辑已删除值(替换为你的业务已删除值,如 1、true、Y 等)
|
||||
mybatis-plus.global-config.db-config.logic-delete-value=DELETE
|
||||
|
||||
# Redis 配置
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
spring.redis.password=
|
||||
spring.redis.database=0
|
||||
spring.redis.timeout=3000
|
||||
spring.redis.lettuce.pool.max-active=8
|
||||
spring.redis.lettuce.pool.max-idle=8
|
||||
spring.redis.lettuce.pool.min-idle=0
|
||||
spring.redis.lettuce.pool.max-wait=-1ms
|
||||
|
||||
# MongoDB 配置
|
||||
#spring.data.mongodb.host=120.24.204.180
|
||||
#spring.data.mongodb.database=app
|
||||
#spring.data.mongodb.port=27017
|
||||
|
||||
# Sa-Token 配置
|
||||
sa-token.token-name=Authorization
|
||||
sa-token.timeout=2592000
|
||||
sa-token.active-timeout=-1
|
||||
sa-token.is-concurrent=true
|
||||
sa-token.is-share=true
|
||||
sa-token.token-style=uuid
|
||||
sa-token.is-log=false
|
||||
|
||||
# 短信宝配置
|
||||
# 请前往 https://www.smsbao.com/ 注册账号并获取用户名和密码
|
||||
smsbao.username=corewing
|
||||
smsbao.password=755dc3ac40c94d319cf6e314f24dc659
|
||||
|
||||
# 邮件配置
|
||||
# SMTP 服务器地址
|
||||
spring.mail.host=smtp.em.dingtalk.com
|
||||
# SMTP 服务器端口(465 为 SSL 加密端口)
|
||||
spring.mail.port=465
|
||||
# 发件人邮箱
|
||||
spring.mail.username=dev@corewing.com
|
||||
# 邮箱授权码(不是邮箱密码!需要在邮箱设置中开启 SMTP 服务并获取授权码)
|
||||
spring.mail.password=t035gngwYl0xgvZF
|
||||
# 编码格式
|
||||
spring.mail.default-encoding=UTF-8
|
||||
# 其他配置
|
||||
spring.mail.properties.mail.smtp.auth=true
|
||||
# 465 端口使用 SSL 加密,需要启用 SSL
|
||||
spring.mail.properties.mail.smtp.ssl.enable=true
|
||||
spring.mail.properties.mail.smtp.ssl.required=true
|
||||
# SSL Socket Factory 配置
|
||||
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
|
||||
spring.mail.properties.mail.smtp.socketFactory.port=465
|
||||
spring.mail.properties.mail.smtp.socketFactory.fallback=false
|
||||
|
||||
# 钉钉机器人配置
|
||||
# 请前往钉钉群设置 -> 智能群助手 -> 添加机器人 -> 自定义机器人,获取 Webhook 地址和密钥
|
||||
dingtalk.webhook=https://oapi.dingtalk.com/robot/send?access_token=7eed4b3483303c9ec71ef37a08c347bb597fd4c64211a96a8f55f72405ff6444
|
||||
# 如果使用加签安全设置,请填写密钥(secret)
|
||||
dingtalk.secret=SEC0f2b835f28139905e3c0b5be979b215df1735f1154f36514aafbae8708014148
|
||||
|
||||
|
||||
|
||||
# ===================== Knife4j 核心增强配置 =====================
|
||||
# 启用Knife4j增强模式
|
||||
knife4j.enable=true
|
||||
knife4j.setting.language=zh_cn
|
||||
knife4j.basic.enable=true
|
||||
knife4j.basic.username=corewing
|
||||
knife4j.basic.password=Aaa123..
|
||||
@@ -1,114 +1,16 @@
|
||||
|
||||
# spring profiles configuration
|
||||
#########################################
|
||||
#spring.profiles.active=local
|
||||
#spring.profiles.active=test
|
||||
spring.profiles.active=prod
|
||||
#########################################
|
||||
|
||||
# 应用服务 WEB 访问端口
|
||||
server.port=8080
|
||||
|
||||
|
||||
# 单文件最大大小(例如:10MB,支持单位:B, KB, MB, GB)
|
||||
spring.servlet.multipart.max-file-size=100MB
|
||||
# 一次请求中所有文件的总大小(例如:50MB)
|
||||
spring.servlet.multipart.max-request-size=100MB
|
||||
|
||||
# 数据源配置
|
||||
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
||||
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.url=jdbc:mysql://120.24.204.180:3306/app?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
spring.datasource.username=app
|
||||
spring.datasource.password=AB636NGhhH2cC5A5
|
||||
|
||||
# Druid 连接池配置
|
||||
spring.datasource.druid.initial-size=5
|
||||
spring.datasource.druid.min-idle=5
|
||||
spring.datasource.druid.max-active=20
|
||||
spring.datasource.druid.max-wait=60000
|
||||
spring.datasource.druid.test-while-idle=true
|
||||
spring.datasource.druid.test-on-borrow=false
|
||||
spring.datasource.druid.test-on-return=false
|
||||
spring.datasource.druid.time-between-eviction-runs-millis=60000
|
||||
spring.datasource.druid.min-evictable-idle-time-millis=300000
|
||||
spring.datasource.druid.validation-query=SELECT 1
|
||||
spring.datasource.druid.pool-prepared-statements=true
|
||||
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
|
||||
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
|
||||
spring.datasource.druid.filters=stat,wall
|
||||
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
|
||||
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
|
||||
|
||||
# MyBatis-Plus 配置
|
||||
mybatis-plus.mapper-locations=classpath*:/mapper/**/*.xml
|
||||
mybatis-plus.type-aliases-package=com.corewing.app.entity
|
||||
mybatis-plus.configuration.map-underscore-to-camel-case=true
|
||||
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
mybatis-plus.global-config.db-config.id-type=ASSIGN_ID
|
||||
mybatis-plus.global-config.db-config.table-prefix=
|
||||
# ========== 逻辑删除核心配置 ==========
|
||||
# 1. 自定义逻辑删除字段名(替换为你的字段,如 is_delete、del_flag 等)
|
||||
mybatis-plus.global-config.db-config.logic-delete-field=del_flag
|
||||
# 2. 逻辑未删除值(替换为你的业务未删除值,如 0、false、N 等)
|
||||
mybatis-plus.global-config.db-config.logic-not-delete-value=NOT_DELETE
|
||||
# 3. 逻辑已删除值(替换为你的业务已删除值,如 1、true、Y 等)
|
||||
mybatis-plus.global-config.db-config.logic-delete-value=DELETE
|
||||
|
||||
# Redis 配置
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
spring.redis.password=
|
||||
spring.redis.database=0
|
||||
spring.redis.timeout=3000
|
||||
spring.redis.lettuce.pool.max-active=8
|
||||
spring.redis.lettuce.pool.max-idle=8
|
||||
spring.redis.lettuce.pool.min-idle=0
|
||||
spring.redis.lettuce.pool.max-wait=-1ms
|
||||
|
||||
# MongoDB 配置
|
||||
#spring.data.mongodb.host=120.24.204.180
|
||||
#spring.data.mongodb.database=app
|
||||
#spring.data.mongodb.port=27017
|
||||
|
||||
# Sa-Token 配置
|
||||
sa-token.token-name=Authorization
|
||||
sa-token.timeout=2592000
|
||||
sa-token.active-timeout=-1
|
||||
sa-token.is-concurrent=true
|
||||
sa-token.is-share=true
|
||||
sa-token.token-style=uuid
|
||||
sa-token.is-log=false
|
||||
|
||||
# 短信宝配置
|
||||
# 请前往 https://www.smsbao.com/ 注册账号并获取用户名和密码
|
||||
smsbao.username=corewing
|
||||
smsbao.password=755dc3ac40c94d319cf6e314f24dc659
|
||||
|
||||
# 邮件配置
|
||||
# SMTP 服务器地址
|
||||
spring.mail.host=smtp.em.dingtalk.com
|
||||
# SMTP 服务器端口(465 为 SSL 加密端口)
|
||||
spring.mail.port=465
|
||||
# 发件人邮箱
|
||||
spring.mail.username=dev@corewing.com
|
||||
# 邮箱授权码(不是邮箱密码!需要在邮箱设置中开启 SMTP 服务并获取授权码)
|
||||
spring.mail.password=t035gngwYl0xgvZF
|
||||
# 编码格式
|
||||
spring.mail.default-encoding=UTF-8
|
||||
# 其他配置
|
||||
spring.mail.properties.mail.smtp.auth=true
|
||||
# 465 端口使用 SSL 加密,需要启用 SSL
|
||||
spring.mail.properties.mail.smtp.ssl.enable=true
|
||||
spring.mail.properties.mail.smtp.ssl.required=true
|
||||
# SSL Socket Factory 配置
|
||||
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
|
||||
spring.mail.properties.mail.smtp.socketFactory.port=465
|
||||
spring.mail.properties.mail.smtp.socketFactory.fallback=false
|
||||
|
||||
# 钉钉机器人配置
|
||||
# 请前往钉钉群设置 -> 智能群助手 -> 添加机器人 -> 自定义机器人,获取 Webhook 地址和密钥
|
||||
dingtalk.webhook=https://oapi.dingtalk.com/robot/send?access_token=7eed4b3483303c9ec71ef37a08c347bb597fd4c64211a96a8f55f72405ff6444
|
||||
# 如果使用加签安全设置,请填写密钥(secret)
|
||||
dingtalk.secret=SEC0f2b835f28139905e3c0b5be979b215df1735f1154f36514aafbae8708014148
|
||||
|
||||
|
||||
|
||||
# ===================== Knife4j 核心增强配置 =====================
|
||||
# 启用Knife4j增强模式
|
||||
knife4j.enable=true
|
||||
knife4j.setting.language=zh_cn
|
||||
knife4j.basic.enable=true
|
||||
knife4j.basic.username=corewing
|
||||
knife4j.basic.password=Aaa123..
|
||||
|
||||
81
src/main/resources/db/qc.sql
Normal file
81
src/main/resources/db/qc.sql
Normal file
@@ -0,0 +1,81 @@
|
||||
-- ============================================================
|
||||
-- Corewing QC 后端数据库建表 SQL(MySQL)
|
||||
-- ============================================================
|
||||
|
||||
|
||||
CREATE TABLE `flight_controller` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`sn` VARCHAR(64) NOT NULL COMMENT '序列号',
|
||||
`model` VARCHAR(64) DEFAULT NULL COMMENT '型号',
|
||||
`batch_no` VARCHAR(64) DEFAULT NULL COMMENT '批次号',
|
||||
`status` VARCHAR(32) NOT NULL DEFAULT 'REGISTERED' COMMENT '状态: REGISTERED / QC_PASS / QC_FAIL / ACTIVATED',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_sn` (`sn`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='飞控板设备注册表';
|
||||
|
||||
|
||||
CREATE TABLE `qc_test_record` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`test_no` VARCHAR(32) NOT NULL COMMENT '测试单号,格式: WL-yyyyMMdd-NNN / FC-yyyyMMdd-NNN',
|
||||
`product_type` VARCHAR(32) NOT NULL COMMENT '产品类型: WIRELESS_BOARD / FLIGHT_CONTROLLER',
|
||||
`sn` VARCHAR(64) NOT NULL COMMENT '产品序列号(无线板为 BLE MAC)',
|
||||
`operator_id` VARCHAR(32) NOT NULL COMMENT '测试员 ID',
|
||||
`operator_name` VARCHAR(64) NOT NULL COMMENT '测试员姓名',
|
||||
`phone_model` VARCHAR(64) DEFAULT NULL COMMENT '测试手机型号',
|
||||
`app_version` VARCHAR(16) DEFAULT NULL COMMENT 'APP 版本',
|
||||
`status` VARCHAR(16) NOT NULL COMMENT '测试结果: PASS / FAIL',
|
||||
`create_time` DATETIME NOT NULL COMMENT 'APP 端创建时间',
|
||||
`updated_at` DATETIME DEFAULT NULL COMMENT 'APP 端最后更新时间',
|
||||
`upload_time` DATETIME DEFAULT NULL COMMENT 'APP 端上传时间',
|
||||
`report_url` VARCHAR(512) DEFAULT NULL COMMENT '测试报告 URL',
|
||||
`server_create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '服务端入库时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_test_no` (`test_no`),
|
||||
KEY `idx_sn` (`sn`),
|
||||
KEY `idx_product_type` (`product_type`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='QC 测试记录主表';
|
||||
|
||||
|
||||
CREATE TABLE `qc_step_result` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`test_record_id` BIGINT NOT NULL COMMENT '关联 qc_test_record.id',
|
||||
`step_index` INT NOT NULL COMMENT '步骤序号(从 1 开始)',
|
||||
`step_name` VARCHAR(64) NOT NULL COMMENT '步骤名称',
|
||||
`result` VARCHAR(8) DEFAULT NULL COMMENT '步骤结果: PASS / FAIL / NULL',
|
||||
`data_json` TEXT DEFAULT NULL COMMENT '步骤详细数据 JSON',
|
||||
`duration` BIGINT DEFAULT 0 COMMENT '步骤耗时(毫秒)',
|
||||
`completed_at` DATETIME DEFAULT NULL COMMENT '步骤完成时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_test_record_id` (`test_record_id`),
|
||||
UNIQUE KEY `uk_record_step` (`test_record_id`, `step_index`),
|
||||
CONSTRAINT `fk_step_record` FOREIGN KEY (`test_record_id`)
|
||||
REFERENCES `qc_test_record` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='QC 步骤结果表';
|
||||
|
||||
|
||||
CREATE TABLE `qc_photo` (
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`test_record_id` BIGINT NOT NULL COMMENT '关联 qc_test_record.id',
|
||||
`test_no` VARCHAR(32) NOT NULL COMMENT '测试单号',
|
||||
`url` VARCHAR(512) NOT NULL COMMENT '照片远程 URL',
|
||||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_test_no` (`test_no`),
|
||||
CONSTRAINT `fk_photo_record` FOREIGN KEY (`test_record_id`)
|
||||
REFERENCES `qc_test_record` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='QC 测试照片表';
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 示例数据(可选)
|
||||
-- ============================================================
|
||||
|
||||
-- 注册一批无线板
|
||||
-- INSERT INTO `wireless_board` (`mac`) VALUES
|
||||
-- ('AA:BB:CC:DD:EE:01'),
|
||||
-- ('AA:BB:CC:DD:EE:02'),
|
||||
-- ('AA:BB:CC:DD:EE:03');
|
||||
@@ -35,6 +35,7 @@ error.verify.type.empty=Verification type cannot be empty
|
||||
error.account.format.invalid=Please enter a valid phone number or email
|
||||
error.sms.send.failed=SMS sending failed, please try again later
|
||||
error.email.send.failed=Email sending failed, please try again later
|
||||
error.sms.send.exceed=SMS sending failed, the number of available times on that day exceeded
|
||||
|
||||
# ==================== Feedback Module ====================
|
||||
# Feedback Controller
|
||||
@@ -63,6 +64,7 @@ error.token.replaced=Account has been logged in elsewhere
|
||||
error.token.kicked.out=Account has been kicked offline
|
||||
error.not.login=Not logged in, please login first
|
||||
error.server.internal=Internal server error: {0}
|
||||
error.system=System error, please try again later
|
||||
|
||||
# ==================== Utility Classes ====================
|
||||
# Redis Utility
|
||||
@@ -129,6 +131,7 @@ params.not.found=Parameter not found
|
||||
params.no.permission=No permission to operate this parameter
|
||||
params.download.success=Download successful
|
||||
params.download.failed=Download failed
|
||||
params.download.exceed=Exceeded the number of downloads
|
||||
|
||||
# ==================== Firmware Management Module ====================
|
||||
# Firmware Controller
|
||||
@@ -141,3 +144,5 @@ firmware.update.success=Firmware updated successfully
|
||||
firmware.update.failed=Failed to update firmware
|
||||
firmware.not.found=Firmware not found
|
||||
firmware.type.required=Firmware type is required
|
||||
firmware.type.or.model.required=Firmware type or model is required
|
||||
firmware.device.not.found=Device not found
|
||||
|
||||
@@ -35,6 +35,7 @@ error.verify.type.empty=验证码类型不能为空
|
||||
error.account.format.invalid=请输入正确的手机号或邮箱
|
||||
error.sms.send.failed=短信发送失败,请稍后重试
|
||||
error.email.send.failed=邮件发送失败,请稍后重试
|
||||
error.sms.send.exceed=短信发送失败,当天可用次数超出
|
||||
|
||||
# ==================== 反馈模块 ====================
|
||||
# 反馈Controller
|
||||
@@ -63,6 +64,7 @@ error.token.replaced=账号已在其他地方登录
|
||||
error.token.kicked.out=账号已被踢下线
|
||||
error.not.login=未登录,请先登录
|
||||
error.server.internal=服务器内部错误:{0}
|
||||
error.system=系统错误,请稍后重试
|
||||
|
||||
# ==================== 工具类 ====================
|
||||
# Redis工具类
|
||||
@@ -129,6 +131,7 @@ params.not.found=参数不存在
|
||||
params.no.permission=无权限操作该参数
|
||||
params.download.success=下载成功
|
||||
params.download.failed=下载失败
|
||||
params.download.exceed=超出次数下载
|
||||
|
||||
# ==================== 固件管理模块 ====================
|
||||
# 固件Controller
|
||||
@@ -141,3 +144,5 @@ firmware.update.success=固件更新成功
|
||||
firmware.update.failed=固件更新失败
|
||||
firmware.not.found=固件不存在
|
||||
firmware.type.required=固件类型不能为空
|
||||
firmware.type.or.model.required=固件类型或型号不能为空
|
||||
firmware.device.not.found=设备不存在
|
||||
|
||||
89
src/main/resources/logback-spring.xml
Normal file
89
src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<!-- 引入 Spring Boot 2.6.x 的默认配置 -->
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
|
||||
<!-- 定义属性 -->
|
||||
<springProperty scope="context" name="LOG_PATH" source="logging.file.path" defaultValue="./logs"/>
|
||||
|
||||
<!-- 自定义转换器 -->
|
||||
<conversionRule conversionWord="tid" converterClass="com.corewing.app.common.aspect.CustomTraceIdConverter"/>
|
||||
|
||||
<!-- 修正:使用正确的属性名 -->
|
||||
<property name="CONSOLE_LOG_PATTERN"
|
||||
value="%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %tid %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
|
||||
|
||||
<!-- 文件日志格式 -->
|
||||
<property name="FILE_LOG_PATTERN"
|
||||
value="%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %tid %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
|
||||
|
||||
<!-- 本地环境 -->
|
||||
<springProfile name="local">
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
|
||||
<logger name="com.corewing.app" level="DEBUG" additivity="false">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</logger>
|
||||
</springProfile>
|
||||
|
||||
<!-- 非本地环境 -->
|
||||
<springProfile name="!local">
|
||||
<!-- 控制台输出(用于捕获不到的日志) -->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 错误日志 -->
|
||||
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_PATH}/error.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_PATH}/error/error-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
<maxHistory>30</maxHistory>
|
||||
<totalSizeCap>1GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 所有日志 -->
|
||||
<appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_PATH}/app.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_PATH}/total/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
<maxHistory>30</maxHistory>
|
||||
<totalSizeCap>3GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="FILE_ALL"/>
|
||||
<appender-ref ref="FILE_ERROR"/>
|
||||
</root>
|
||||
</springProfile>
|
||||
</configuration>
|
||||
6
src/main/resources/mapper/BizActivityLotteryMapper.xml
Normal file
6
src/main/resources/mapper/BizActivityLotteryMapper.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.corewing.app.mapper.BizActivityLotteryMapper">
|
||||
|
||||
|
||||
</mapper>
|
||||
6
src/main/resources/mapper/BizActivityMapper.xml
Normal file
6
src/main/resources/mapper/BizActivityMapper.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.corewing.app.mapper.BizActivityMapper">
|
||||
|
||||
|
||||
</mapper>
|
||||
6
src/main/resources/mapper/DevLogMapper.xml
Normal file
6
src/main/resources/mapper/DevLogMapper.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.corewing.app.mapper.DevLogMapper">
|
||||
|
||||
|
||||
</mapper>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user