174 Commits

Author SHA1 Message Date
MichaelWin
1a726b8b7d 【改进】使用内网环境 2026-03-16 10:08:31 +08:00
8f5f998c3a Merge remote-tracking branch 'origin/main' 2026-03-16 10:03:52 +08:00
37182d7efb 【新增】Sirius固件查询接口及API文档
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 10:02:38 +08:00
MichaelWin
e472a3207f 【改进】查询固件版本增加当前版本参数 2026-03-06 14:58:52 +08:00
MichaelWin
c0896c199d 【新增】根据类型,型号查询固件版本 2026-03-06 14:08:11 +08:00
MichaelWin
ccfac2a9eb Merge remote-tracking branch 'origin/main' 2026-03-06 11:29:30 +08:00
MichaelWin
84594dda48 【新增】固件版本升级校验 2026-03-06 11:28:40 +08:00
MichaelWin
da144b7c6a 【改进】全局异常捕获 2026-03-06 11:28:15 +08:00
306222c55e 新增产品QC 2026-02-28 13:32:29 +08:00
MichaelWin
bd3523fd3d 测试 2026-02-27 18:33:44 +08:00
fa16fec0a0 新增产品QC 2026-02-27 17:41:08 +08:00
MichaelWin
7d5a62f8f2 【改进】不拦截工厂激活接口 2026-02-26 09:12:51 +08:00
MichaelWin
2ac80ae4d0 【新增】活动 2026-02-25 18:52:42 +08:00
MichaelWin
e5e540305d 【新增】用户设备激活,工厂设备激活 2026-02-25 18:52:34 +08:00
MichaelWin
16626af8f2 【改进】产品分页 2026-02-11 15:58:40 +08:00
MichaelWin
70fbd1ad07 【改进】APP登出日志 2026-02-10 15:24:46 +08:00
MichaelWin
bd304cee09 【新增】APP登录登出日志 2026-02-10 15:15:39 +08:00
MichaelWin
0118b5a84e 【改进】获取当前用户数据接口 2026-02-10 09:41:42 +08:00
MichaelWin
db39b2092c 【改进】线上环境 2026-02-09 18:52:24 +08:00
MichaelWin
4928db5287 【新增】接口操作,登录,登出日志 2026-02-09 18:50:29 +08:00
MichaelWin
f6c3326c4a 【新增】使用线上环境 2026-02-09 16:24:32 +08:00
MichaelWin
1c1f407d27 【新增】运行日志 2026-02-09 16:22:19 +08:00
MichaelWin
facff46bb6 【改进】参数中心增加次数下载限制 2026-02-09 12:32:23 +08:00
MichaelWin
71589ab13a 【改进】短信发送增加次数验证 2026-02-09 12:24:31 +08:00
MichaelWin
edbcf2729b 【改进】分页 2026-02-09 09:34:47 +08:00
MichaelWin
476ea60b27 【新增】资源排序 2026-02-05 21:32:00 +08:00
MichaelWin
740a343863 【新增】公开资源接口 2026-02-05 17:58:16 +08:00
MichaelWin
a76d954979 【新增】资源接口 2026-02-05 17:57:50 +08:00
MichaelWin
ecbb2e993c 【新增】资源分类接口 2026-02-05 17:57:39 +08:00
MichaelWin
de53fb7838 【新增】反馈增加IP以及地址 2026-02-02 12:12:46 +08:00
MichaelWin
2079e6a1a8 【改进】IP地址XDB 2026-02-02 11:58:47 +08:00
MichaelWin
0e164f9623 【改进】APP访问统计增加品牌以及系统类型 2026-02-02 11:38:43 +08:00
MichaelWin
a8d1c73390 【改进】APP访问统计增加地址 2026-02-02 11:22:27 +08:00
MichaelWin
2516e1e1a3 【改进】APP访问统计接口服务 2026-01-30 15:26:58 +08:00
MichaelWin
cbdce6211f 【改进】APP访问统计接口服务 2026-01-30 15:17:02 +08:00
MichaelWin
f048818b4c 【新增】APP访问统计增加访问设备 2026-01-30 14:42:03 +08:00
MichaelWin
e85b25754d 【新增】APP访问统计接口 2026-01-30 14:32:54 +08:00
MichaelWin
ed3209d69d 【优化】设备型号参数 2026-01-29 09:22:34 +08:00
MichaelWin
344cb30e5d 【优化】产品标签 2026-01-28 12:12:23 +08:00
MichaelWin
3ae7b9ac52 【优化】产品接口 2026-01-28 11:50:44 +08:00
MichaelWin
7d51a13dd7 【优化】分页 2026-01-28 09:22:46 +08:00
MichaelWin
de8f44f063 【优化】产品接口 2026-01-27 17:30:17 +08:00
MichaelWin
6da2b05345 【新增】设备激活接口 2026-01-27 16:43:21 +08:00
MichaelWin
c93a74e9a5 【改进】APP下载接口文档 2026-01-27 15:44:02 +08:00
MichaelWin
bdd48ead74 【新增】官网产品页接口 2026-01-27 15:43:35 +08:00
MichaelWin
6b793228e3 【改进】APP更新接口 2026-01-22 17:57:09 +08:00
MichaelWin
b24f647c87 【改进】API文档 2026-01-22 17:46:11 +08:00
MichaelWin
8a0032cfa4 【新增】官网获取最新APP接口 2026-01-22 17:09:12 +08:00
MichaelWin
dffa3ea84a 【改进】APP升级校验接口 2026-01-22 17:08:50 +08:00
MichaelWin
dca88d28cd 【新增】获取公共固件板载类型集合 2026-01-08 16:28:28 +08:00
MichaelWin
c07537c527 【废除】mongoDBjar包 2026-01-08 16:26:17 +08:00
MichaelWin
978eb7501b 【新增】获取公共固件版本接口 2026-01-08 15:58:34 +08:00
MichaelWin
a13fcf8440 【改进】废除mongoDB连接池 2026-01-08 15:39:10 +08:00
MichaelWin
bd8fd15b32 【新增】获取公共固件类型接口 2026-01-08 15:38:36 +08:00
MichaelWin
7807d6be80 【修复】兼容LocalDateTime以及date 2025-12-26 23:58:36 +08:00
MichaelWin
d5e423ee45 【修复】参数错误 2025-12-26 23:29:23 +08:00
MichaelWin
b93e064edc 【改进】创建与修改时间 2025-12-26 23:14:08 +08:00
MichaelWin
aefb8d0c12 【改进】接口返回数据模型参数标识 2025-12-26 23:13:28 +08:00
MichaelWin
2955df71e9 【改进】排除模型无需登录接口 2025-12-26 23:12:30 +08:00
MichaelWin
23511407ab 【改进】参数创建默认状态 2025-12-22 18:38:41 +08:00
MichaelWin
ecfe64c188 【改进】API接口文档 2025-12-22 18:36:40 +08:00
MichaelWin
58f512df4a 【改进】oss使用自定义域名 2025-12-22 18:36:18 +08:00
MichaelWin
77c1155b38 【新增】模型模块接口 2025-12-22 18:35:58 +08:00
MichaelWin
e96c54c328 【改进】后台管理系统剥离APP接口 2025-12-19 18:43:46 +08:00
MichaelWin
59307d612c 【新增】参数审核提交接口 2025-12-17 18:04:21 +08:00
MichaelWin
48800adccd 【废除】后台登录 2025-12-17 18:03:58 +08:00
2933b1961e 【改进】delete请求 2025-12-15 09:56:02 +08:00
7be8216a5a 【改进】改进用户注销接口 2025-12-15 09:50:28 +08:00
c74505b8c3 【新增】改进用户注销接口 2025-12-12 11:44:56 +08:00
8ac012f49c 【新增】用户注销接口 2025-12-11 12:55:43 +08:00
068ca75caf 【新增】用户注销接口 2025-12-11 11:42:52 +08:00
6248147389 【修复】短信验证码 2025-12-08 10:17:46 +08:00
01f18f87ba 【改进】改进版本校验规则 2025-12-06 10:50:35 +08:00
9917e46c29 【新增】APP版本更新校验功能接口 2025-12-05 17:53:44 +08:00
54cd851245 【新增】排除APP版本校验接口 2025-12-05 17:53:21 +08:00
8b13d4cd92 【改进】教程创建时间 2025-12-05 17:52:59 +08:00
46175c7295 【改进】使用顶层跳转登录 2025-12-05 11:04:30 +08:00
d72f637be3 【修复】教程分页数据接口重复问题 2025-12-05 11:04:07 +08:00
6da50d70d0 【修复】教程修改分类不生效问题 2025-12-04 18:41:26 +08:00
eec3fc663b 【新增】教程增加知识库地址 2025-12-04 17:34:53 +08:00
29bdb9ddbb 【改进】文件上传大小 2025-12-02 18:38:40 +08:00
86e0935353 【改进】文件上传大小 2025-12-02 18:34:12 +08:00
4c2cb4f0e5 【新增】反馈日志记录接口 2025-12-01 16:46:54 +08:00
3442591d2b 【优化】隐私政策 2025-11-26 14:25:31 +08:00
4928c71b19 【优化】验证码登录 2025-11-25 18:38:34 +08:00
5cd5353f97 【新增】排除验证码登录接口 2025-11-25 18:20:47 +08:00
73ab200daf 【优化】验证码登录接口 2025-11-25 18:09:51 +08:00
4298fcb402 【新增】验证码登录接口 2025-11-25 17:54:25 +08:00
37c0ac035e 【改进】统一异常捕获 2025-11-25 17:42:12 +08:00
977ca260da 【优化】忘记密码 2025-11-25 17:41:47 +08:00
4808960491 【优化】代码格式 2025-11-25 16:35:41 +08:00
74d8c66a6e 【新增】忘记密码接口 2025-11-25 16:35:11 +08:00
fca95e1203 【新增】封装账号类型校验工具 2025-11-25 16:34:19 +08:00
b7d3e07d16 【改进】账号类型校验 2025-11-25 16:33:56 +08:00
35ac70e82d 【修复】bug 2025-11-24 12:14:17 +08:00
632b37d5bd 【新增】完善后台首页面板 2025-11-21 18:39:51 +08:00
75ed266532 【新增】完善固件上传 2025-11-21 18:39:28 +08:00
884459e91a 【新增】完善固件上传 2025-11-19 09:47:45 +08:00
5acb3a34e0 【新增】OSS文件管理工具 2025-11-18 18:18:06 +08:00
9dc9bff8b1 【新增】飞行记录删除接口及数据同步 2025-11-18 18:17:44 +08:00
b44214f74a 【新增】上传飞行记录接口 2025-11-18 10:50:17 +08:00
78ff89ba0d 【修复】飞行记录接口 2025-11-18 09:33:10 +08:00
8bbb3ac38f 【新增】获取飞行记录接口 2025-11-17 18:28:20 +08:00
983f8cb429 【新增】隐私政策分类接口 2025-11-17 16:15:37 +08:00
0d9ae593c6 【改进】隐私政策分类 2025-11-17 16:15:26 +08:00
07e8151736 【优化】修改密码接口 2025-11-17 15:10:29 +08:00
ad5ca8c545 【新增】mongoDB支持 2025-11-17 15:10:09 +08:00
95e7b752e3 【改进】修改密码接口 2025-11-17 15:09:47 +08:00
3ea2777c94 【改进】隐私政策 2025-11-17 15:09:26 +08:00
1db7b3f6a1 【新增】排除咨询接口 2025-11-17 15:09:00 +08:00
03c5226a6a 【新增】咨询接口 2025-11-17 15:08:52 +08:00
7bd3d54d97 【新增】系统用户 2025-11-17 15:08:06 +08:00
61371a4a76 【改进】隐私政策 2025-11-13 16:27:46 +08:00
6606438862 【改进】密码校验 2025-11-12 09:26:59 +08:00
c9332b85db 【新增】增加跨域支持 2025-11-12 09:26:45 +08:00
74d19bb9d6 【新增】新增OSS-SDK 2025-11-12 09:26:35 +08:00
57f97a490a 【改进】固件上传 2025-11-12 09:26:16 +08:00
746e5051cf 【改进】完善教程 2025-11-12 09:25:35 +08:00
f27b57ec8b 【改进】完善教程详情页 2025-11-04 10:47:29 +08:00
5e0773a59f 【改进】更换接口 2025-11-04 10:47:15 +08:00
70ea5f4dd4 【改进】完善APP隐私协议政策 2025-11-04 10:46:57 +08:00
31ea86d90c 【新增】封装时间工具 2025-11-04 10:46:10 +08:00
73dda8b648 【新增】反馈管理 2025-11-04 10:06:20 +08:00
80a60e37af 【优化】页面组件优化,提升加载速度 2025-11-04 00:00:51 +08:00
71885c8796 【优化】固件管理 2025-11-03 23:23:51 +08:00
bfbb94481f 【改进】教程列表 2025-11-03 23:23:30 +08:00
3dcf9ca3ef 【新增】新增隐私协议 2025-11-03 23:22:25 +08:00
2b92f29a17 【优化】教程分类以及教程 2025-11-03 18:41:15 +08:00
3dbfff5f41 【新增】单行字体省略 2025-11-03 18:19:06 +08:00
f04385a306 【新增】教程指南管理 2025-11-03 18:18:37 +08:00
44f817eced 【优化】优化用户管理界面 2025-11-03 11:43:37 +08:00
0f2cc6a33c 【新增】完善固件管理 2025-11-03 11:43:11 +08:00
0d1127f25e 【新增】完善用户管理 2025-11-03 10:40:53 +08:00
bb7b4035fc 【改进】表格样式优化 2025-11-03 10:40:09 +08:00
c3b3ed3681 【新增】封装提示框 2025-11-03 10:39:46 +08:00
3fe027661b 【新增】封装提示模态框 2025-11-03 10:39:36 +08:00
74034ed26a 【改进】主页动态化 2025-10-31 17:39:24 +08:00
ad98033faa 【新增】系统用户界面 2025-10-31 17:39:05 +08:00
bd8f47d9ae 【优化】仪表盘 2025-10-31 17:38:33 +08:00
c975c205df 【改进】消息结果集 2025-10-31 17:38:17 +08:00
3ead596483 【新增】固件管理路由 2025-10-31 17:37:40 +08:00
882df50f75 【新增】仪表盘 2025-10-31 17:37:16 +08:00
13da68b90d 【新增】系统菜单控制器 2025-10-31 17:36:51 +08:00
5f8bc1af55 【新增】系统设置 2025-10-31 17:36:23 +08:00
1391239193 【新增】用户修改密码 2025-10-31 17:35:39 +08:00
fe93d9fac0 【新增】用户管理 2025-10-31 17:35:19 +08:00
6ed65f89b5 【改进】区分模块 2025-10-31 17:33:25 +08:00
9ff5b98b05 【改进】区分模块DTO 2025-10-31 17:32:54 +08:00
461c390cf7 【新增】分页参数拦截封装 2025-10-31 17:31:21 +08:00
1b9c9e9b86 【新增】分页参数拦截封装 2025-10-31 17:31:01 +08:00
be30f31990 【优化】拦截地址 2025-10-31 10:13:52 +08:00
ac4d7d8176 【改进】菜单动态化 2025-10-31 10:13:34 +08:00
54997d4e3d 【新增】实体基类 2025-10-31 10:13:13 +08:00
7bbb1be2a2 【新增】首页样式封装 2025-10-31 10:12:31 +08:00
19312e7a6f 【新增】系统菜单 2025-10-31 10:12:00 +08:00
727dd254f0 【新增】封装axios 2025-10-31 10:11:33 +08:00
2942fdabfe 【优化】优化政策协议接口 2025-10-30 16:05:23 +08:00
5ea30d6f85 【新增】排除隐私政策接口拦截 2025-10-30 12:29:30 +08:00
e6ae7d60e3 【新增】隐私政策 2025-10-30 12:29:03 +08:00
cca1847fbf 【优化】路径 2025-10-30 10:27:52 +08:00
10a317bed6 【新增】接口注释 2025-10-30 10:20:39 +08:00
a3bf673440 Merge branch 'main' of http://120.24.204.180:3000/admin/core_wing_web 2025-10-30 09:55:37 +08:00
30c4ec612a Merge remote-tracking branch 'origin/main' 2025-10-30 09:50:14 +08:00
486455af81 Merge branch 'dev_20251030' 2025-10-30 09:49:24 +08:00
e8dc76ef82 【新增】新增显示教程详情
Some checks failed
CI Build and Test / build (pull_request) Has been cancelled
2025-10-30 09:36:39 +08:00
8aa6fc0abf 【优化】拦截地址 2025-10-30 09:36:09 +08:00
7eda1a85eb 【优化】使用Thymeleaf渲染 2025-10-30 09:35:46 +08:00
6a124a5754 【删除】教程展示测试文件 2025-10-30 09:34:03 +08:00
564e617802 【改进】模块化 2025-10-30 09:32:55 +08:00
3f09aa1238 【新增】模板引擎支持包 2025-10-30 09:31:24 +08:00
bc77cd244b Merge pull request #5
dev_20251029
2025-10-29 18:26:53 +08:00
5306431417 Merge pull request #4
dev_20251029
2025-10-29 18:15:44 +08:00
53287f0a1d Merge pull request #3
dev_20251029
2025-10-29 18:12:57 +08:00
a1cbb9fdf0 Merge pull request #2 from MakeSomeFakeNews/dev_20251029
dev_20251029
2025-10-29 16:57:06 +08:00
274 changed files with 11124 additions and 1700 deletions

2
.gitignore vendored
View File

@@ -16,7 +16,7 @@ build/
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
logs
### IntelliJ IDEA ###
.idea
*.iws

View File

@@ -29,18 +29,31 @@ 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' // 代码生成器
implementation("com.baomidou:mybatis-plus-jsqlparser") // SQL 解析器
implementation 'cn.dev33:sa-token-spring-boot-starter:1.44.0' // 权限认证
implementation 'cn.dev33:sa-token-redis-template:1.44.0' // Sa-Token 整合 RedisTemplate
implementation 'org.apache.commons:commons-pool2' // 提供 Redis 连接池
implementation 'com.alibaba:druid-spring-boot-starter:1.2.27' // 数据库连接池
implementation 'org.lionsoul:ip2region:2.7.0' // IP 归属地
// implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' // mongodb
compileOnly 'org.projectlombok:lombok' // Lombok
developmentOnly 'org.springframework.boot:spring-boot-devtools' // 热重载
runtimeOnly 'com.mysql:mysql-connector-j' // MySQL 驱动
annotationProcessor 'org.projectlombok:lombok' // Lombok 注解处理
testImplementation 'org.springframework.boot:spring-boot-starter-test' // 测试框架
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' // thymeleaf模版引擎
implementation 'com.aliyun.oss:aliyun-sdk-oss:3.18.3' // OSS SDK
implementation 'cn.hutool:hutool-all:5.8.42' // hutool工具包
implementation 'io.springfox:springfox-swagger2:2.10.5'
implementation 'com.github.xiaoymin:knife4j-openapi2-spring-boot-starter:4.4.0'
implementation 'org.lionsoul:ip2region:3.3.4'
implementation 'jakarta.servlet:jakarta.servlet-api:5.0.0'
}
tasks.named('test') {

View 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-ELRS2-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-ELRS2-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-ELRS2-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
View 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
View File

@@ -0,0 +1,116 @@
-- ============================================================
-- Corewing QC 后端数据库建表 SQLMySQL
-- ============================================================
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');

View File

@@ -1,6 +1,7 @@
package com.corewing.app.common;
import com.corewing.app.util.I18nUtil;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@@ -16,21 +17,25 @@ public class Result<T> implements Serializable {
/**
* 状态码
*/
@ApiModelProperty("状态码")
private Integer code;
/**
* 返回消息
*/
@ApiModelProperty("消息内容")
private String message;
/**
* 返回数据
*/
@ApiModelProperty("数据")
private T data;
/**
* 成功标识
*/
@ApiModelProperty("是否成功")
private Boolean success;
public Result(Integer code, String message, T data, Boolean success) {
@@ -54,6 +59,13 @@ public class Result<T> implements Serializable {
return new Result<>(200, I18nUtil.getMessage("common.success"), data, true);
}
/**
* 成功返回(自定义消息)
*/
public static <T> Result<T> success(String message) {
return new Result<>(200, message, null, true);
}
/**
* 成功返回(自定义消息和数据)
*/
@@ -81,4 +93,27 @@ public class Result<T> implements Serializable {
public static <T> Result<T> error(Integer code, String message) {
return new Result<>(code, message, null, false);
}
/**
* 根据状态返回信息结果
*/
public static <T> Result<T> isBool(boolean flag) {
return flag ? Result.success() : Result.error();
}
/**
* 根据状态返回信息结果(自定义成功消息)
*/
public static <T> Result<T> isBoolAsMsg(boolean flag, String successMsg) {
return flag ? Result.success(successMsg) : Result.error();
}
/**
* 根据状态返回信息结果(自定义消息)
*/
public static <T> Result<T> isBoolAsMsg(boolean flag, String successMsg, String errorMsg) {
return flag ? Result.success(successMsg) : Result.error(errorMsg);
}
}

View File

@@ -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 "未命名";
}

View File

@@ -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();
}
}

View 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);
}
}

View File

@@ -0,0 +1,37 @@
package com.corewing.app.common.base;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
@Data
public class BaseEntity {
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 创建人
*/
private String createBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
/**
* 修改人
*/
private String updateBy;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,49 @@
package com.corewing.app.common.base;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Date;
@Getter
@Setter
public class CommonEntity implements Serializable {
/** 删除标志 */
@JsonIgnore
@TableLogic
@TableField(fill = FieldFill.INSERT)
private String deleteFlag;
/** 创建时间 */
@ApiModelProperty("创建时间")
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/** 创建人 */
@TableField(fill = FieldFill.INSERT)
private String createUser;
/** 创建人名称 */
@TableField(exist = false)
private String createUserName;
/** 更新时间 */
@ApiModelProperty("更新时间")
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
/** 更新人 */
@TableField(fill = FieldFill.UPDATE)
private String updateUser;
/** 更新人名称 */
@TableField(exist = false)
private String updateUserName;
}

View File

@@ -0,0 +1,19 @@
package com.corewing.app.common.enums;
import lombok.Getter;
/**
* 通用删除标志枚举
*
* @author xuyuxiang
* @date 2021/10/11 14:02
**/
@Getter
public enum CommonDeleteFlagEnum {
/** 未删除 */
NOT_DELETE,
/** 已删除 */
DELETED
}

View File

@@ -0,0 +1,134 @@
package com.corewing.app.common.page;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.HashMap;
import java.util.Map;
public class PageContext {
private static final ThreadLocal<PagePool> PAGE_POOL_HOLDER = new ThreadLocal<>();
private static class PagePool {
private final Map<String, Page<?>> pool = new HashMap<>();
private int counter = 0;
public synchronized String generateKey() {
return "page_" + (counter++);
}
public Page<?> get(String key) {
return pool.get(key);
}
public void put(String key, Page<?> page) {
pool.put(key, page);
}
public void remove(String key) {
pool.remove(key);
}
public void clear() {
pool.clear();
counter = 0;
}
public boolean isEmpty() {
return pool.isEmpty();
}
}
/**
* 获取一个新的 Page 对象带唯一key
* 适合单个查询场景
*/
public static <T> Page<T> getPage(Class<T> clazz) {
PagePool pool = getPagePool();
String key = pool.generateKey();
Page<T> page = new Page<>();
pool.put(key, page);
return page;
}
/**
* 获取带有默认分页参数的 Page 对象
*/
public static <T> Page<T> getPage(Class<T> clazz, Integer current, Integer size) {
int pageNum = current != null && current > 0 ? current : 1;
int pageSize = size != null && size > 0 ? size : 10;
PagePool pool = getPagePool();
String key = pool.generateKey();
Page<T> page = new Page<>(pageNum, pageSize);
pool.put(key, page);
return page;
}
/**
* 注册一个 Page 对象到池中(供 PageInterceptor 使用)
*/
public static <T> void registerPage(Page<T> page) {
PagePool pool = getPagePool();
String key = pool.generateKey();
pool.put(key, page);
}
/**
* 获取默认的 Page 对象(第一个注册的)
* 保持向后兼容性
*/
@SuppressWarnings("unchecked")
public static <T> Page<T> getDefaultPage(Class<T> clazz) {
PagePool pool = PAGE_POOL_HOLDER.get();
if (pool == null || pool.isEmpty()) {
return null;
}
// 返回第一个 Page 对象
return (Page<T>) pool.pool.values().stream().findFirst().orElse(null);
}
/**
* 通过 key 获取 Page 对象
*/
@SuppressWarnings("unchecked")
public static <T> Page<T> getPageByKey(String key) {
PagePool pool = PAGE_POOL_HOLDER.get();
if (pool == null) {
return null;
}
return (Page<T>) pool.get(key);
}
/**
* 获取 PagePool
*/
private static PagePool getPagePool() {
PagePool pool = PAGE_POOL_HOLDER.get();
if (pool == null) {
pool = new PagePool();
PAGE_POOL_HOLDER.set(pool);
}
return pool;
}
/**
* 清除指定 key 的 Page 对象
*/
public static void clearPage(String key) {
PagePool pool = PAGE_POOL_HOLDER.get();
if (pool != null) {
pool.remove(key);
}
}
/**
* 清除所有
*/
public static void clear() {
PagePool pool = PAGE_POOL_HOLDER.get();
if (pool != null) {
pool.clear();
}
PAGE_POOL_HOLDER.remove();
}
}

View File

@@ -0,0 +1,63 @@
package com.corewing.app.common.page;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class PageInterceptor implements HandlerInterceptor {
// 默认的 Page key用于获取默认分页参数
public static final String DEFAULT_PAGE_KEY = "default_page";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 默认分页参数
int pageNum = 1;
int pageSize = 10;
// 从请求参数中获取分页信息
String current = request.getParameter("current");
String size = request.getParameter("size");
// 解析页码
if (current != null && !current.isEmpty()) {
try {
pageNum = Integer.parseInt(current);
if (pageNum < 1) pageNum = 1; // 页码不能小于1
} catch (NumberFormatException e) {
// 非法参数使用默认值
}
}
// 解析每页条数
if (size != null && !size.isEmpty()) {
try {
pageSize = Integer.parseInt(size);
if (pageSize < 1) pageSize = 10; // 每页条数不能小于1
if (pageSize > 100) pageSize = 100; // 限制最大条数
} catch (NumberFormatException e) {
// 非法参数使用默认值
}
}
// 创建 MyBatis-Plus 的 Page 对象并注册到 PagePool
Page<?> page = new Page<>(pageNum, pageSize);
PageContext.registerPage(page);
// 将分页参数存储到 request 属性中,方便其他地方使用
request.setAttribute("pageNum", pageNum);
request.setAttribute("pageSize", pageSize);
request.setAttribute("pageCurrent", pageNum); // 兼容 current 参数名
request.setAttribute("pageSize", pageSize);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 清除ThreadLocal中的数据防止内存泄漏
PageContext.clear();
}
}

View File

@@ -0,0 +1,39 @@
package com.corewing.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration // 标记为配置类
public class CorsConfig implements WebMvcConfigurer {
/**
* 配置跨域过滤器,优先级高于所有拦截器
*/
@Bean
public CorsFilter corsFilter() {
// 1. 配置跨域参数
CorsConfiguration config = new CorsConfiguration();
// 允许的前端域名(根据实际环境修改)
config.addAllowedOriginPattern("*");
// 允许携带 Cookie前后端都需要开启
config.setAllowCredentials(true);
// 允许的请求方法(包含预检请求 OPTIONS
config.addAllowedMethod("*");
// 允许的请求头(* 表示所有)
config.addAllowedHeader("*");
// 预检请求缓存时间1小时减少重复验证
config.setMaxAge(3600L);
// 2. 配置路径匹配规则(对所有接口生效)
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
// 3. 返回过滤器(优先级最高)
return new CorsFilter(source);
}
}

View File

@@ -0,0 +1,35 @@
package com.corewing.app.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfiguration {
@Bean(value = "defaultApi")
public Docket defaultApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("CoreWing APP APIs")
.description("CoreWing APP APIs")
.contact(new Contact("CoreWing", "www.corewing.com", "main@corewing.com"))
.version("1.0")
.build())
//分组名称
.groupName("1.1.0版本")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.corewing.app.modules"))
.paths(PathSelectors.any())
.build();
}
}

View File

@@ -2,8 +2,11 @@ package com.corewing.app.config;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import com.corewing.app.common.page.PageInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
@@ -17,27 +20,61 @@ public class SaTokenConfig implements WebMvcConfigurer {
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 分页参数拦截
registry.addInterceptor(new PageInterceptor());
// 注册 Sa-Token 拦截器,校验规则为 StpUtil.checkLogin() 登录校验。
registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
// 拦截所有路由
.addPathPatterns("/**")
// 排除登录、注册、发送验证码接口
.excludePathPatterns("/user/login", "/user/register", "/user/sendCode")
// 排除登录、注册、发送验证码, 忘记密码接口
.excludePathPatterns("/user/login", "/user/register", "/user/sendCode", "/user/forgetPassword", "/user/codeLogin")
// 排除后台管理登录接口
.excludePathPatterns("/sys/user/login")
//排除QC接口
.excludePathPatterns("/api/qc/**")
// 排除反馈接口(支持匿名提交)
.excludePathPatterns("/feedback", "/feedback/**")
// 排除教程接口(支持匿名查询)
.excludePathPatterns("/tutorial", "/tutorial/**")
// 排除隐私政策接口(支持匿名查询)
.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("/", "/index.html", "/admin/login.html", "/*.css", "/*.js", "/*.ico", "/static/**")
// 排除后台管理静态资源
.excludePathPatterns("/admin/**")
.excludePathPatterns("/", "/*.html", "/*.css", "/*.js", "/*.ico", "/static/**", "/assets/**")
// 排除接口静态资源
.excludePathPatterns("/doc.html", "/webjars/**")
.excludePathPatterns("/v3/api-docs/swagger-config", "/v3/api-docs/**", "/swagger-resources")
// 排除 Druid 监控
.excludePathPatterns("/druid/**")
// 排除错误页面
.excludePathPatterns("/error", "/error/**");
.excludePathPatterns("/error", "/error/**")
// 排除校验更新接口
.excludePathPatterns("/app_version/**")
// 排除获取最新app接口
.excludePathPatterns("/api/app", "/api/app/getAppVersion")
.excludePathPatterns("/api/website/**")
.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/**")
// 排除咨询接口
.excludePathPatterns("/contactMsg", "/contactMsg/**");
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX + "/META-INF/resources/webjars/");
}
}

View File

@@ -1,101 +0,0 @@
package com.corewing.app.controller;
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.entity.Firmware;
import com.corewing.app.service.FirmwareService;
import com.corewing.app.util.I18nUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
/**
* 固件 Controller
*/
@RestController
@RequestMapping("/firmware")
public class FirmwareController {
private final FirmwareService firmwareService;
public FirmwareController(FirmwareService firmwareService) {
this.firmwareService = firmwareService;
}
/**
* 根据ID查询固件
*/
@GetMapping("/{id}")
public Result<Firmware> getById(@PathVariable Long id) {
Firmware firmware = firmwareService.getById(id);
if (firmware != null) {
return Result.success(firmware);
}
return Result.error(I18nUtil.getMessage("firmware.not.found"));
}
/**
* 分页查询固件列表
*
* @param current 当前页
* @param size 每页大小
* @param firmwareName 固件名称(可选)
* @param firmwareType 固件类型(可选)
*/
@GetMapping("/page")
public Result<IPage<Firmware>> page(
@RequestParam(defaultValue = "1") Long current,
@RequestParam(defaultValue = "10") Long size,
@RequestParam(required = false) String firmwareName,
@RequestParam(required = false) String firmwareType) {
Page<Firmware> page = new Page<>(current, size);
QueryWrapper<Firmware> wrapper = new QueryWrapper<>();
// 根据固件名称模糊查询
if (StringUtils.hasText(firmwareName)) {
wrapper.like("firmware_name", firmwareName);
}
// 根据固件类型查询
if (StringUtils.hasText(firmwareType)) {
wrapper.eq("firmware_type", firmwareType);
}
// 按创建时间倒序排列
wrapper.orderByDesc("create_time");
IPage<Firmware> result = firmwareService.page(page, wrapper);
return Result.success(result);
}
/**
* 查询所有固件
*/
@GetMapping("/list")
public Result<java.util.List<Firmware>> list() {
java.util.List<Firmware> list = firmwareService.list();
return Result.success(list);
}
/**
* 根据类型查询固件版本
*
* @param firmwareType 固件类型
*/
@GetMapping("/type/{firmwareType}")
public Result<java.util.List<Firmware>> listByType(@PathVariable Integer firmwareType) {
if (firmwareType == null) {
return Result.error(I18nUtil.getMessage("firmware.type.required"));
}
QueryWrapper<Firmware> wrapper = new QueryWrapper<>();
wrapper.eq("firmware_type", firmwareType);
// 按版本号或创建时间倒序排列,最新版本在前
wrapper.orderByDesc("create_time");
java.util.List<Firmware> list = firmwareService.list(wrapper);
return Result.success(list);
}
}

View File

@@ -1,75 +0,0 @@
package com.corewing.app.controller;
import cn.dev33.satoken.stp.StpUtil;
import com.corewing.app.common.Result;
import com.corewing.app.dto.SysLoginRequest;
import com.corewing.app.entity.SysUser;
import com.corewing.app.service.SysUserService;
import com.corewing.app.util.I18nUtil;
import com.corewing.app.util.IpUtil;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 后台管理用户 Controller
*/
@RestController
@RequestMapping("/sys/user")
public class SysUserController {
private final SysUserService sysUserService;
public SysUserController(SysUserService sysUserService) {
this.sysUserService = sysUserService;
}
/**
* 后台管理登录
*/
@PostMapping("/login")
public Result<Map<String, Object>> login(@RequestBody SysLoginRequest request, HttpServletRequest httpRequest) {
try {
String loginIp = IpUtil.getClientIp(httpRequest);
// 执行登录
String token = sysUserService.login(request.getUsername(), request.getPassword(), loginIp);
// 查询用户信息
SysUser user = sysUserService.getByUsername(request.getUsername());
Map<String, Object> data = new HashMap<>();
data.put("token", token);
data.put("userId", user.getId());
data.put("username", user.getUsername());
data.put("realName", user.getRealName());
return Result.success(I18nUtil.getMessage("user.login.success"), data);
} catch (Exception e) {
return Result.error(e.getMessage());
}
}
/**
* 后台管理登出
*/
@PostMapping("/logout")
public Result<String> logout() {
StpUtil.logout();
return Result.success(I18nUtil.getMessage("user.logout.success"));
}
/**
* 获取当前登录用户信息
*/
@GetMapping("/info")
public Result<SysUser> getUserInfo() {
Long userId = StpUtil.getLoginIdAsLong();
SysUser user = sysUserService.getById(userId);
// 隐藏密码
user.setPassword(null);
return Result.success(user);
}
}

View File

@@ -0,0 +1,23 @@
package com.corewing.app.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@ApiModel("APP统计请求模型")
@Data
public class AccessStatisticsRequest {
@ApiModelProperty("访问页面")
private String visitPage;
@ApiModelProperty("访问类型")
private String accessType;
@ApiModelProperty(value = "访问设备", required = true)
@NotBlank(message = "访问设备不能为空")
private String accessDevice;
}

View File

@@ -0,0 +1,12 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ModelCategoryListRequest {
@ApiModelProperty(value = "搜索参数(分类名称)")
private String searchKey;
}

View File

@@ -0,0 +1,12 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ModelCategoryPageRequest {
@ApiModelProperty(value = "搜索参数(分类名称)")
private String searchKey;
}

View File

@@ -0,0 +1,37 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class ModelCreateRequest {
@ApiModelProperty(value = "模型标题", required = true)
@NotBlank(message = "模型标题不能为空")
private String title;
@ApiModelProperty(value = "模型描述", required = true)
@NotBlank(message = "模型描述不能为空")
private String description;
@ApiModelProperty(value = "模型分类id", required = true)
@NotBlank(message = "模型分类id不能为空")
private String categoryId;
@ApiModelProperty(value = "模型封面", required = true)
@NotBlank(message = "模型封面不能为空")
private String coverImage;
@ApiModelProperty(value = "备注", required = false)
private String remark;
@ApiModelProperty("模型文件")
@NotNull(message = "模型文件不能为空")
private List<MultipartFile> files;
}

View File

@@ -0,0 +1,12 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ModelDownloadLogListRequest {
@ApiModelProperty(value = "模型标题", required = false)
private String searchKey;
}

View File

@@ -0,0 +1,12 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ModelDownloadLogPageRequest {
@ApiModelProperty(value = "模型标题", required = false)
private String searchKey;
}

View File

@@ -0,0 +1,15 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class ModelDownloadRequest {
@ApiModelProperty(value = "模型id", required = true)
@NotBlank(message = "模型id不能为空")
private String modelId;
}

View File

@@ -0,0 +1,14 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class ModelFavoriteListRequest {
@ApiModelProperty(value = "模型标题", required = false)
private String searchKey;
}

View File

@@ -0,0 +1,12 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ModelFavoritePageRequest {
@ApiModelProperty(value = "模型标题", required = false)
private String searchKey;
}

View File

@@ -0,0 +1,15 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class ModelFavoriteRequest {
@ApiModelProperty(value = "模型id", required = true)
@NotBlank(message = "模型id不能为空")
private String modelId;
}

View File

@@ -0,0 +1,15 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class ModelIdRequest {
@ApiModelProperty(value = "模型id", required = true)
@NotBlank(message = "模型Id不能为空")
private String modelId;
}

View File

@@ -0,0 +1,15 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class ModelLikeRequest {
@ApiModelProperty(value = "模型id", required = true)
@NotBlank(message = "模型id不能为空")
private String modelId;
}

View File

@@ -0,0 +1,23 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ModelListRequest {
@ApiModelProperty(value = "用户id")
private Long userId;
@ApiModelProperty(value = "搜索参数(模型标题)")
private String searchKey;
@ApiModelProperty(value = "模型状态1正常 0下架 2审核中")
private String status;
@ApiModelProperty(value = "模型公布状态1公开 0私有")
private String isPublic;
@ApiModelProperty(value = "分类id")
private String categoryId;
}

View File

@@ -0,0 +1,24 @@
package com.corewing.app.dto.AppModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ModelPageRequest {
@ApiModelProperty(value = "用户id")
private Long userId;
@ApiModelProperty(value = "搜索参数(模型标题)")
private String searchKey;
@ApiModelProperty(value = "模型状态1正常 0下架 2审核中")
private String status;
@ApiModelProperty(value = "模型公布状态1公开 0私有")
private String isPublic;
@ApiModelProperty(value = "分类id")
private String categoryId;
}

View File

@@ -0,0 +1,19 @@
package com.corewing.app.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class CheckVersionRequest {
@NotBlank(message = "版本不能为空")
private String localVersion;
@NotBlank(message = "构建版本不能为空")
private int localBuildNumber;
@NotBlank(message = "类型不能为空")
private String type;
}

View File

@@ -0,0 +1,19 @@
package com.corewing.app.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 验证码登录请求对象
*/
@Data
public class CodeLoginRequest {
@NotBlank(message = "手机号或邮箱不能为空")
private String account;
@NotBlank(message = "验证码不能为空")
private String verificationCode;
}

View File

@@ -0,0 +1,22 @@
package com.corewing.app.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class DeviceActivationRequest {
@ApiModelProperty(value = "MAC地址", required = true)
@NotBlank(message = "MAC地址不能为空")
private String mac;
@ApiModelProperty(value = "设备型号", required = true)
@NotBlank(message = "设备型号不能为空")
private String modelId;
@ApiModelProperty(value = "时间戳", required = true)
private String timestamp;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,19 @@
package com.corewing.app.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class ForgetPasswordRequest {
@NotBlank(message = "手机号或邮箱不能为空")
private String account;
@NotBlank(message = "验证码不能为空")
private String verificationCode;
@NotBlank(message = "密码不能为空")
private String password;
}

View File

@@ -0,0 +1,13 @@
package com.corewing.app.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class LogoffRequest {
@NotBlank(message = "验证码不能为空")
private String code;
}

View File

@@ -0,0 +1,7 @@
package com.corewing.app.dto;
import lombok.Data;
@Data
public class ResourceCategoryTreeRequest {
}

View File

@@ -0,0 +1,14 @@
package com.corewing.app.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ResourcePageRequest {
@ApiModelProperty(value = "搜索参数")
private String searchKey;
@ApiModelProperty(value = "分类id")
private String categoryId;
}

View File

@@ -17,7 +17,7 @@ public class SendCodeRequest {
private String account;
/**
* 验证码类型register-注册, login-登录, reset-重置密码
* 验证码类型register-注册, login-登录, reset-重置密码, forget-忘记密码logoff-注销
*/
@NotBlank(message = "验证码类型不能为空")
private String type;

View File

@@ -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;
}

View File

@@ -0,0 +1,47 @@
package com.corewing.app.dto;
import lombok.Data;
@Data
public class TrajectoryData {
private Long id;
private Long session_id;
private Long timestamp;
// 基础遥测数据
private Long rc;
private Long gps;
private Long gps_status;
private double voltage;
private double cell_voltage;
private Long consumption;
private double current;
private double speed;
private double air_speed;
private double v_speed;
private double altitude;
private double distance;
private double range;
private Long throttle;
private Long wind_direction;
private double wind_speed;
private Long heading;
private double roll;
private double pitch;
private double yaw;
// 扩展数据
private double compass_heading;
private double drone_lat;
private double drone_lon;
private double home_lat;
private double home_lon;
private String map_type;
private Boolean show_trajectory;
private String flight_mode;
private Long vehicle_type;
private Long autopilot_type;
private Boolean is_armed;
private String sync_id;
}

View File

@@ -0,0 +1,7 @@
package com.corewing.app.dto;
import lombok.Data;
@Data
public class TutorialListRequest {
}

View File

@@ -0,0 +1,19 @@
package com.corewing.app.dto.publicFirmware;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class PublicBoardTypeListRequest {
@ApiModelProperty(value = "固件类型", required = true)
@NotBlank(message = "固件类型不能为空")
public String firmwareType;
@ApiModelProperty(value = "固件版本id", required = true)
@NotBlank(message = "固件版本id不能为空")
public String versionId;
}

View File

@@ -0,0 +1,23 @@
package com.corewing.app.dto.publicFirmware;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class PublicFirmwareListRequest {
@ApiModelProperty(value = "固件类型", required = true)
@NotBlank(message = "固件类型不能为空")
public String firmwareType;
@ApiModelProperty(value = "固件版本id", required = true)
@NotBlank(message = "固件版本id不能为空")
public String versionId;
@ApiModelProperty(value = "板载类型", required = true)
@NotBlank(message = "板载类型不能为空")
public String boardType;
}

View File

@@ -0,0 +1,15 @@
package com.corewing.app.dto.publicFirmware;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class PublicFirmwareVersionListRequest {
@ApiModelProperty(value = "固件类型", required = true)
@NotBlank(message = "固件类型不能为空")
public String firmwareType;
}

View 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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,9 @@
package com.corewing.app.dto.qc;
import lombok.Data;
@Data
public class ValidateSnRequest {
private String sn;
}

View File

@@ -0,0 +1,8 @@
package com.corewing.app.dto.qc;
import lombok.Data;
@Data
public class ValidateWirelessBoardRequest {
private String mac;
}

View File

@@ -0,0 +1,26 @@
package com.corewing.app.dto;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
public class uploadReplaySessionRequest {
private Long id;
private String name;
private String description;
private Long start_time;
private Long end_time;
private Long duration; // 持续时间(秒)
private Long data_count; // 数据点数量
private Date created_at;
private Date updated_at;
private String sync_id;
List<TrajectoryData> trajectoryDataList;
}

View File

@@ -0,0 +1,13 @@
package com.corewing.app.dto.website;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ProductCategoryRequest {
@ApiModelProperty(value = "产品名称")
private String searchKey;
}

View File

@@ -0,0 +1,16 @@
package com.corewing.app.dto.website;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ProductPageRequest {
@ApiModelProperty(value = "产品名称")
private String searchKey;
@ApiModelProperty(value = "产品分类")
private String categoryId;
}

View 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;
}

View File

@@ -0,0 +1,56 @@
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 io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ApiModel("APP访问统计")
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("app_access_statistics")
public class AppAccessStatistics extends CommonEntity {
@ApiModelProperty("id")
@TableId
private String id;
@ApiModelProperty("用户id")
private Long userId;
@ApiModelProperty("访问页面")
private String visitPage;
@ApiModelProperty("访问类型")
private String accessType;
@ApiModelProperty("访问设备")
private String accessDevice;
@ApiModelProperty("设备型号")
private String deviceModel;
@ApiModelProperty("设备系统")
private String deviceSystem;
@ApiModelProperty("设备品牌")
private String deviceBrand;
@ApiModelProperty("访问IP")
private String accessIp;
@ApiModelProperty("访问地址")
private String accessAddress;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("扩展参数")
private String extJson;
}

View File

@@ -0,0 +1,71 @@
package com.corewing.app.entity;
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 com.corewing.app.common.base.CommonEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("app_model")
public class AppModel extends CommonEntity {
@TableId
@ApiModelProperty("模型id")
private String id;
@ApiModelProperty("用户id")
private Long userId;
@ApiModelProperty("模型标题")
private String title;
@ApiModelProperty("模型描述")
private String description;
@ApiModelProperty("分类id")
private String categoryId;
@ApiModelProperty("模型封面(base64)")
private String coverImage;
@ApiModelProperty("是否公开:(1公开0私有)")
private String isPublic;
@ApiModelProperty("状态:(1正常0下架2审核中)")
private String status;
@ApiModelProperty("下载次数")
private int downloadCount;
@ApiModelProperty("点赞次数")
private int likeCount;
@ApiModelProperty("收藏次数")
private int favoriteCount;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("扩展参数")
private String extJson;
@ApiModelProperty("暂未使用【点击详情接口获取文件模型】")
@TableField(exist = false)
private List<AppModelFile> modelFile;
/**
* 分类名称
*/
@ApiModelProperty("分类名称")
@TableField(exist = false)
private String categoryTitle;
}

View File

@@ -0,0 +1,35 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.corewing.app.common.base.CommonEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("app_model_category")
public class AppModelCategory extends CommonEntity {
@TableId
@ApiModelProperty("分类id")
private String id;
@ApiModelProperty("分类名称")
private String name;
@ApiModelProperty("父级id")
private String parentId;
@ApiModelProperty("排序码")
private int sortCode;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("扩展参数")
private String extJson;
}

View File

@@ -0,0 +1,36 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.corewing.app.common.base.CommonEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("app_model_download_log")
public class AppModelDownloadLog extends CommonEntity {
@TableId
@ApiModelProperty("id")
private String id;
@ApiModelProperty("用户id")
private Long userId;
@ApiModelProperty("模型id")
private String modelId;
@ApiModelProperty("下载ip")
private String ipAddress;
@ApiModelProperty("下载备注")
private String remark;
@ApiModelProperty("扩展参数")
private String extJson;
}

View File

@@ -0,0 +1,25 @@
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;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("app_model_favorite")
public class AppModelFavorite extends CommonEntity {
@TableId
private Long id;
private Long userId;
private String modelId;
private String remark;
private String extJson;
}

View File

@@ -0,0 +1,38 @@
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 io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("app_model_file")
public class AppModelFile extends CommonEntity {
@TableId
@ApiModelProperty("id")
private String id;
@ApiModelProperty("模型id")
private String modelId;
@ApiModelProperty("文件名称")
private String fileName;
@ApiModelProperty("文件类型")
private String fileType;
@ApiModelProperty("文件大小")
private Long fileSize;
@ApiModelProperty("文件地址")
private String fileUrl;
@ApiModelProperty("文件排序")
private int sortCode;
}

View File

@@ -0,0 +1,86 @@
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("app_public_firmware_plane")
public class AppPublicFirmwarePlane extends CommonEntity {
/**
* 主键
*/
@TableId
private String id;
/**
* 版本号Id
*/
private String versionId;
/**
* 板载类型
*/
private String boardType;
/**
* 固件类型
*/
private String type;
/**
* 固件下载地址
*/
private String downloadUrl;
/**
* 固件名称
*/
private String firmwareName;
/**
* 固件大小
*/
private Long fileSize;
/**
* 固件发布时间
*/
private Date releaseTime;
/**
* 固件同步时间
*/
private Date crawlTime;
/**
* 是否有效
*/
private int isValid;
/**
* 排序
*/
private int sortCode;
/**
* 备注
*/
private String remark;
/**
* 扩展字段
*/
private String extJson;
}

View File

@@ -0,0 +1,65 @@
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("app_public_firmware_version")
public class AppPublicFirmwareVersion extends CommonEntity {
/**
* 主键
*/
@TableId
public String id;
/**
* 固件版本类型
*/
private String type;
/**
* 版本类型
*/
private String versionType;
/**
* 版本号
*/
private String versionNumber;
/**
* 数字版本号
*/
private int versionCode;
/**
* 发布时间
*/
private Date releaseDate;
/**
* 排序
*/
private int sortCode;
/**
* 备注
*/
private String remark;
/**
* 扩展字段
*/
private String extJson;
}

View File

@@ -0,0 +1,38 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
/**
* app版本控制
*/
@Data
@TableName("app_version")
public class AppVersion {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String version;
private int versionNumber;
private int buildNumber;
private String updateContent;
private String downloadUrl;
private String type;
private Integer status;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
}

View 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;
}

View File

@@ -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;
}

View File

@@ -0,0 +1,44 @@
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 io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 设备表
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("biz_device")
public class BizDevice extends CommonEntity {
@TableId
@ApiModelProperty("设备id")
private String id;
@ApiModelProperty("设备mac地址")
private String deviceMac;
@ApiModelProperty("状态")
private String status;
@ApiModelProperty("公布状态")
private String publicStatus;
@ApiModelProperty("型号")
private String categoryId;
@ApiModelProperty("排序")
private int sortCode;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("扩展字段")
private String extJson;
}

View File

@@ -0,0 +1,45 @@
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 io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 设备激活表
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("biz_device_activation")
public class BizDeviceActivation extends CommonEntity {
@TableId
@ApiModelProperty("激活id")
private String id;
@ApiModelProperty("设备mac地址")
private String deviceMac;
@ApiModelProperty("设备id")
private String deviceId;
@ApiModelProperty("激活时间")
private Date activationTime;
@ApiModelProperty("用户id")
private Long userId;
@ApiModelProperty("激活ip")
private String activationIp;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("扩展字段")
private String extJson;
}

View File

@@ -0,0 +1,41 @@
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 io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 设备型号表
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("biz_device_category")
public class BizDeviceCategory extends CommonEntity {
@TableId
@ApiModelProperty("设备型号id")
private String id;
@ApiModelProperty("设备型号缩略图")
private String thumbnail;
@ApiModelProperty("型号id")
private Integer modelId;
@ApiModelProperty("设备型号名称")
private String categoryName;
@ApiModelProperty("排序")
private int sortCode;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("扩展字段")
private String extJson;
}

View File

@@ -0,0 +1,50 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.corewing.app.common.base.CommonEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
* 字典实体
*
* @author xuyuxiang
* @date 2022/2/23 18:27
**/
@Getter
@Setter
@TableName("DEV_DICT")
public class BizDict extends CommonEntity {
/** id */
@ApiModelProperty("id")
private String id;
/** 父id */
@ApiModelProperty("父级id")
private String parentId;
/** 字典文字 */
@ApiModelProperty("字典文字")
private String dictLabel;
/** 字典值 */
@ApiModelProperty("字典值")
private String dictValue;
/** 分类 */
@ApiModelProperty("分类")
private String category;
/** 排序码 */
@ApiModelProperty("排序码")
private Integer sortCode;
/** 扩展信息 */
@ApiModelProperty("扩展信息")
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
private String extJson;
}

View File

@@ -0,0 +1,59 @@
package com.corewing.app.entity;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
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.math.BigDecimal;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("biz_product")
public class BizProduct extends CommonEntity {
@TableId
private String id;
private String title;
private String description;
private String thumbnail;
private String hotStatus;
private String showType;
private String content;
private String tag;
private String detailUrl;
private BigDecimal amount;
private String status;
private int sortCode;
private String remark;
private String extJson;
@TableField(exist = false)
private String categoryId;
@TableField(exist = false)
private String[] features;
public String[] getFeatures() {
if(StrUtil.isNotBlank(tag)) {
return tag.split(",");
}
return null;
}
}

View File

@@ -0,0 +1,39 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.corewing.app.common.base.CommonEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("biz_product_category")
public class BizProductCategory extends CommonEntity {
@TableId
private String id;
private String parentId;
private String thumbnail;
private String categoryTitle;
private String description;
private String status;
private Integer sortCode;
private String remark;
private String extJson;
@TableField(exist = false)
Page<BizProduct> productPage;
}

View File

@@ -0,0 +1,18 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("biz_product_category_relation")
public class BizProductCategoryRelation {
@TableId
private String id;
private String productId;
private String categoryId;
}

View File

@@ -0,0 +1,44 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.corewing.app.common.base.CommonEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class BizResource extends CommonEntity {
@TableId
private String id;
private String thumbnail;
private String title;
private String fileName;
private String categoryId;
private String subtitle;
private String content;
private String status;
private String version;
private String downloadUrl;
private Integer sortCode;
private String remark;
private String extJson;
@TableField(exist = false)
private String categoryName;
}

View File

@@ -0,0 +1,25 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.corewing.app.common.base.CommonEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class BizResourceCategory extends CommonEntity {
@TableId
private String id;
private String categoryName;
private String parentId;
private Integer sortCode;
private String remark;
private String extJson;
}

View File

@@ -0,0 +1,52 @@
package com.corewing.app.entity;
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 com.corewing.app.common.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.data.annotation.Id;
/**
* 联系消息
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("app_contact_msg")
public class ContactMsg extends BaseEntity {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 咨询人
*/
private String name;
/**
* 咨询类型
*/
private int category;
/**
* 联系方式
*/
private String contact;
/**
* 咨询内容
*/
private String msg;
/**
* 咨询状态
*/
private int status;
}

View 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;
}

View File

@@ -55,6 +55,16 @@ public class Feedback implements Serializable {
*/
private Integer status;
/**
* 反馈IP
*/
private String submitIp;
/**
* 反馈地址
*/
private String submitRegion;
/**
* 创建时间
*/
@@ -66,4 +76,34 @@ public class Feedback implements Serializable {
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
/**
* 用户昵称
*/
@TableField(exist = false)
private String nickName;
/**
* 用户名
*/
@TableField(exist = false)
private String username;
@TableField(exist = false)
private String statusName;
public String getStatusName() {
switch (status) {
case 0:
return "待处理";
case 1:
return "处理中";
case 2:
return "已完成";
case 3:
return "已关闭";
default:
return "";
}
}
}

View File

@@ -0,0 +1,62 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 反馈日志
*/
@Data
@TableName("app_feedback_log")
public class FeedbackLog implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 反馈用户id
*/
private Long userId;
/**
* oss地址
*/
private String ossPath;
/**
* 日志文件大小
*/
private Long logSize;
/**
* 反馈日志内容
*/
private String logContent;
/**
* 日志文件名称
*/
private String logName;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
}

View File

@@ -45,6 +45,21 @@ public class Firmware implements Serializable {
*/
private Integer firmwareType;
/**
* 模型id
*/
private String modelId;
/**
* 版本校验id
*/
private Integer versionId;
/**
* 版本号
*/
private String version;
/**
* 固件下载地址
*/
@@ -61,4 +76,20 @@ public class Firmware implements Serializable {
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableField(exist = false)
private String firmwareTypeName;
public String getFirmwareTypeName() {
switch (firmwareType) {
case 1:
return "调参固件";
case 2:
return "AP固件";
case 3:
return "INAV固件";
default:
return "";
}
}
}

View 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;
}

View File

@@ -70,6 +70,21 @@ public class ParamsCenter implements Serializable {
*/
private Integer downloadCount;
/**
* 状态
*/
private String status;
/**
* 审核状态
*/
private String auditStatus;
/**
* 失败原因
*/
private String auditErrorMsg;
/**
* 创建时间
*/
@@ -79,6 +94,6 @@ public class ParamsCenter implements Serializable {
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,48 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.corewing.app.common.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 隐私政策实体
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("app_privacy_policy")
public class PrivacyPolicy extends BaseEntity {
/**
* 隐私政策id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 隐私政策名称
*/
private String title;
/**
* 隐私政策内容
*/
private String content;
/**
* 是否显示
*/
private Integer visible;
/**
* 排序
*/
private Integer sort;
/**
* 类型
*/
private Integer category;
}

View 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;
}

View 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;
}

View 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;
}

View File

@@ -0,0 +1,80 @@
package com.corewing.app.entity;
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 com.corewing.app.dto.TrajectoryData;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
@TableName("app_replay_session")
public class ReplaySession {
/**
* id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String syncId;
/**
* 用户id
*/
private Long userId;
/**
* 名称
*/
private String name;
/**
* oss地址
*/
private String ossPath;
/**
* 描述
*/
private String description;
/**
* 开始时间戳
*/
private Long startTime;
/**
* 结束时间戳
*/
private Long endTime;
/**
* 持续时间
*/
private Long duration;
/**
* 数据点
*/
private Long dataCount;
/**
* 创建时间
*/
private Date createdAt;
/**
* 更新时间
*/
private Date updatedAt;
/**
* 轨迹数据点
*/
@TableField(exist = false)
List<TrajectoryData> trajectoryDataList;
}

View 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-ELRS2-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;
}

View File

@@ -0,0 +1,57 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.corewing.app.common.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("sys_menu")
public class SysMenu extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 菜单id
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 菜单名称
*/
private String menuName;
/**
* 菜单地址
*/
private String menuUrl;
/**
* 菜单图标
*/
private String menuIcon;
/**
* 菜单分类
*/
private String menuCategory;
/**
* 是否隐藏
*/
private boolean visible;
/**
* 排序
*/
private int sort;
}

View File

@@ -0,0 +1,31 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.corewing.app.common.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("sys_option")
public class SysOption extends BaseEntity {
/**
* 主键
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 键名
*/
private String key;
/**
* 键值
*/
private String value;
}

View File

@@ -1,12 +1,11 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
@@ -39,6 +38,11 @@ public class Tutorial implements Serializable {
*/
private String content;
/**
* 知识库地址
*/
private String knowledgeUrl;
/**
* 查看次数
*/
@@ -62,12 +66,23 @@ public class Tutorial implements Serializable {
/**
* 创建时间
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新时间
*/
private Date updateTime;
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
/**
* 教程分类id
*/
@TableField(exist = false)
private Long categoryId;
@TableField(exist = false)
private String categoryName;
}

View File

@@ -1,13 +1,13 @@
package com.corewing.app.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
/**
* 教程分类
@@ -65,11 +65,19 @@ public class TutorialCategory implements Serializable {
/**
* 创建时间
*/
private Date createTime;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新时间
*/
private Date updateTime;
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime updateTime;
public static final String typeCategory = "category";
public static final String typeTag = "tag";
@TableField(exist = false)
private List<Tutorial> tutorials;
}

View File

@@ -25,6 +25,11 @@ public class User implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 用户昵称
*/
private String nickName;
/**
* 用户名
*/

View 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;
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,121 @@
package com.corewing.app.handler;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.corewing.app.common.enums.CommonDeleteFlagEnum;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectionException;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Date;
/**
* MyBatis-Plus 自动填充处理器
* 兼容 Date 和 LocalDateTime 两种时间类型的自动填充
*/
@Component
public class CustomMetaObjectHandler implements MetaObjectHandler {
/** 删除标志 */
private static final String DELETE_FLAG = "deleteFlag";
/** 创建人 */
private static final String CREATE_USER = "createUser";
/** 创建时间 */
private static final String CREATE_TIME = "createTime";
/** 更新人 */
private static final String UPDATE_USER = "updateUser";
/** 更新时间 */
private static final String UPDATE_TIME = "updateTime";
@Override
public void insertFill(MetaObject metaObject) {
try {
//为空则设置deleteFlag
Object deleteFlag = metaObject.getValue(DELETE_FLAG);
if (ObjectUtil.isNull(deleteFlag)) {
setFieldValByName(DELETE_FLAG, EnumUtil.toString(CommonDeleteFlagEnum.NOT_DELETE), metaObject);
}
} catch (ReflectionException ignored) { }
try {
//为空则设置createUser
Object createUser = metaObject.getValue(CREATE_USER);
if (ObjectUtil.isNull(createUser)) {
setFieldValByName(CREATE_USER, this.getUserId(), metaObject);
}
} catch (ReflectionException ignored) { }
try {
// 兼容 Date 和 LocalDateTime 类型的 createTime 填充
fillTimeField(metaObject, CREATE_TIME);
} catch (ReflectionException ignored) { }
try {
// 兼容 Date 和 LocalDateTime 类型的 updateTime 填充
fillTimeField(metaObject, UPDATE_TIME);
} catch (ReflectionException ignored) { }
}
@Override
public void updateFill(MetaObject metaObject) {
try {
//设置updateUser
setFieldValByName(UPDATE_USER, this.getUserId(), metaObject);
} catch (ReflectionException ignored) {
}
try {
// 兼容 Date 和 LocalDateTime 类型的 updateTime 填充
fillTimeField(metaObject, UPDATE_TIME);
} catch (ReflectionException ignored) {
}
}
/**
* 统一填充时间字段(自动识别 Date/LocalDateTime 类型)
* @param metaObject 元对象
* @param fieldName 时间字段名createTime/updateTime
*/
private void fillTimeField(MetaObject metaObject, String fieldName) {
// 先判断字段是否为空
Object fieldValue = metaObject.getValue(fieldName);
if (ObjectUtil.isNotNull(fieldValue)) {
return; // 字段已有值,不填充
}
// 获取字段的类型,自动匹配填充值类型
Class<?> fieldType = metaObject.getGetterType(fieldName);
if (fieldType == LocalDateTime.class) {
// 字段是 LocalDateTime 类型
setFieldValByName(fieldName, LocalDateTime.now(), metaObject);
} else if (fieldType == Date.class || fieldType == DateTime.class) {
// 字段是 Date/hutool DateTime 类型
setFieldValByName(fieldName, new Date(), metaObject);
}
// 其他类型不处理(避免填充错误)
}
/**
* 获取用户id
*/
private String getUserId() {
try {
String loginId = StpUtil.getLoginIdAsString();
if (ObjectUtil.isNotEmpty(loginId)) {
return loginId;
} else {
return "-1";
}
} catch (Exception e) {
return "-1";
}
}
}

View File

@@ -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(),
I18nUtil.getMessage("error.server.internal", e.getMessage()));
I18nUtil.getMessage("error.system"));
}
}

View File

@@ -1,35 +0,0 @@
package com.corewing.app.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* MyBatis-Plus 自动填充处理器
* 用于自动填充创建时间和更新时间
*/
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入时的填充策略
*/
@Override
public void insertFill(MetaObject metaObject) {
// 自动填充创建时间
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
// 自动填充更新时间
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
/**
* 更新时的填充策略
*/
@Override
public void updateFill(MetaObject metaObject) {
// 自动填充更新时间
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}

View 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> {
}

Some files were not shown because too many files have changed in this diff Show More