Merge remote-tracking branch 'origin/main'

This commit is contained in:
2026-03-16 10:03:52 +08:00
9 changed files with 181 additions and 14 deletions

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

@@ -45,6 +45,21 @@ public class Firmware implements Serializable {
*/ */
private Integer firmwareType; private Integer firmwareType;
/**
* 模型id
*/
private String modelId;
/**
* 版本校验id
*/
private Integer versionId;
/**
* 版本号
*/
private String version;
/** /**
* 固件下载地址 * 固件下载地址
*/ */

View File

@@ -5,10 +5,16 @@ import com.corewing.app.common.Result;
import com.corewing.app.util.I18nUtil; import com.corewing.app.util.I18nUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus; 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.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice; 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); 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) @ExceptionHandler(Exception.class)
// @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Result<String> handleException(Exception e) { public Result<String> handleException(Exception e) {
log.error(e.getMessage()); log.error("系统异常: ", e);
return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), return Result.error(HttpStatus.INTERNAL_SERVER_ERROR.value(),
e.getMessage()); I18nUtil.getMessage("error.system"));
} }
} }

View File

@@ -1,31 +1,41 @@
package com.corewing.app.modules.app; package com.corewing.app.modules.app;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.corewing.app.common.Result; import com.corewing.app.common.Result;
import com.corewing.app.common.annotation.CommonLog; import com.corewing.app.common.annotation.CommonLog;
import com.corewing.app.dto.FirmwareVersionRequest;
import com.corewing.app.entity.BizDeviceCategory;
import com.corewing.app.entity.Firmware; import com.corewing.app.entity.Firmware;
import com.corewing.app.service.BizDeviceCategoryService;
import com.corewing.app.service.FirmwareService; import com.corewing.app.service.FirmwareService;
import com.corewing.app.util.I18nUtil; import com.corewing.app.util.I18nUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/** /**
* 固件 Controller * 固件 Controller
*/ */
@Api(tags = "固件接口") @Api(tags = "固件接口")
@RestController @RestController
@RequestMapping("/firmware") @RequestMapping("/firmware")
@Validated
public class AppFirmwareController { public class AppFirmwareController {
private final FirmwareService firmwareService; @Resource
private FirmwareService firmwareService;
public AppFirmwareController(FirmwareService firmwareService) { @Resource
this.firmwareService = firmwareService; private BizDeviceCategoryService bizDeviceCategoryService;
}
/** /**
* 根据ID查询固件 * 根据ID查询固件
@@ -84,20 +94,20 @@ public class AppFirmwareController {
@CommonLog("查询所有固件集合") @CommonLog("查询所有固件集合")
@ApiOperation("查询所有固件集合") @ApiOperation("查询所有固件集合")
@GetMapping("/list") @GetMapping("/list")
public Result<java.util.List<Firmware>> list() { public Result<List<Firmware>> list() {
java.util.List<Firmware> list = firmwareService.list(); List<Firmware> list = firmwareService.list();
return Result.success(list); return Result.success(list);
} }
/** /**
* 根据类型查询固件版本 * 根据类型查询固件版本 【兼容旧版APP】
* *
* @param firmwareType 固件类型 * @param firmwareType 固件类型
*/ */
@CommonLog("根据类型查询固件版本") @CommonLog("根据类型查询固件版本")
@ApiOperation("根据类型查询固件版本") @ApiOperation("根据类型查询固件版本")
@GetMapping("/type/{firmwareType}") @GetMapping("/type/{firmwareType}")
public Result<java.util.List<Firmware>> listByType(@PathVariable Integer firmwareType) { public Result<List<Firmware>> listByType(@PathVariable Integer firmwareType) {
if (firmwareType == null) { if (firmwareType == null) {
return Result.error(I18nUtil.getMessage("firmware.type.required")); return Result.error(I18nUtil.getMessage("firmware.type.required"));
} }
@@ -107,7 +117,49 @@ public class AppFirmwareController {
// 按版本号或创建时间倒序排列,最新版本在前 // 按版本号或创建时间倒序排列,最新版本在前
wrapper.orderByDesc("create_time"); wrapper.orderByDesc("create_time");
java.util.List<Firmware> list = firmwareService.list(wrapper); List<Firmware> list = firmwareService.list(wrapper);
return Result.success(list); return Result.success(list);
} }
/**
* 根据类型查询固件版本 【兼容新版APP】
*
* @param firmwareType 固件类型
*/
@CommonLog("根据类型,型号,当前版本查询固件版本")
@ApiOperation("根据类型,当前版本查询固件版本")
@GetMapping("/type/{firmwareType}/{modelId}/{softwareVersion}")
public Result<List<Firmware>> listByType(@PathVariable Integer firmwareType, @PathVariable Integer modelId, @PathVariable Integer softwareVersion) {
if (firmwareType == null && modelId == null) {
return Result.error(I18nUtil.getMessage("firmware.type.or.model.required"));
}
LambdaQueryWrapper<BizDeviceCategory> categoryQueryWrapper = new LambdaQueryWrapper<>();
categoryQueryWrapper.eq(BizDeviceCategory::getModelId, modelId);
BizDeviceCategory bizDeviceCategory = bizDeviceCategoryService.getOne(categoryQueryWrapper);
if(bizDeviceCategory == null) {
return Result.error(I18nUtil.getMessage("firmware.device.not.found"));
}
LambdaQueryWrapper<Firmware> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Firmware::getFirmwareType, firmwareType);
wrapper.eq(Firmware::getModelId, bizDeviceCategory.getId());
wrapper.ge(Firmware::getVersionId, softwareVersion);
// 按版本号或创建时间倒序排列,最新版本在前
wrapper.orderByDesc(Firmware::getCreateTime);
List<Firmware> list = firmwareService.list(wrapper);
return Result.success(list);
}
/**
* 校验是否存在新固件
* @return
*/
@CommonLog("校验是否存在新固件")
@ApiOperation("校验是否存在新固件")
@PostMapping("/checkVersion")
public Result<Firmware> checkVersion(@RequestBody @Valid FirmwareVersionRequest firmwareVersionRequest) {
return Result.success(firmwareService.checkVersion(firmwareVersionRequest));
}
} }

View File

@@ -3,6 +3,7 @@ package com.corewing.app.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.corewing.app.common.Result; import com.corewing.app.common.Result;
import com.corewing.app.dto.FirmwareVersionRequest;
import com.corewing.app.entity.Firmware; import com.corewing.app.entity.Firmware;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@@ -40,4 +41,11 @@ public interface FirmwareService extends IService<Firmware> {
* @return * @return
*/ */
boolean removeData(Long id); boolean removeData(Long id);
/**
* 校验固件是否有新固件
* @param firmwareVersionRequest
* @return
*/
Firmware checkVersion(FirmwareVersionRequest firmwareVersionRequest);
} }

View File

@@ -4,8 +4,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.corewing.app.common.page.PageContext; import com.corewing.app.common.page.PageContext;
import com.corewing.app.dto.FirmwareVersionRequest;
import com.corewing.app.entity.BizDeviceCategory;
import com.corewing.app.entity.Firmware; import com.corewing.app.entity.Firmware;
import com.corewing.app.mapper.FirmwareMapper; import com.corewing.app.mapper.FirmwareMapper;
import com.corewing.app.service.BizDeviceCategoryService;
import com.corewing.app.service.FirmwareService; import com.corewing.app.service.FirmwareService;
import com.corewing.app.util.OSSUploadUtil; import com.corewing.app.util.OSSUploadUtil;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -13,7 +16,9 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException; import java.io.IOException;
import java.util.Objects;
/** /**
* 固件 Service 实现类 * 固件 Service 实现类
@@ -21,6 +26,9 @@ import java.io.IOException;
@Service @Service
public class FirmwareServiceImpl extends ServiceImpl<FirmwareMapper, Firmware> implements FirmwareService { public class FirmwareServiceImpl extends ServiceImpl<FirmwareMapper, Firmware> implements FirmwareService {
@Resource
private BizDeviceCategoryService bizDeviceCategoryService;
@Override @Override
public Page<Firmware> page(Firmware firmware) { public Page<Firmware> page(Firmware firmware) {
Page<Firmware> page = PageContext.getDefaultPage(Firmware.class); Page<Firmware> page = PageContext.getDefaultPage(Firmware.class);
@@ -63,6 +71,30 @@ public class FirmwareServiceImpl extends ServiceImpl<FirmwareMapper, Firmware> i
return false; return false;
} }
@Override
public Firmware checkVersion(FirmwareVersionRequest firmwareVersionRequest) {
// 根据型号id搜索到设备分类id
LambdaQueryWrapper<BizDeviceCategory> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
categoryLambdaQueryWrapper.eq(BizDeviceCategory::getModelId, firmwareVersionRequest.getModelId());
BizDeviceCategory deviceCategory = bizDeviceCategoryService.getOne(categoryLambdaQueryWrapper);
if(Objects.isNull(deviceCategory)){
throw new RuntimeException("该设备型号不存在设备");
}
LambdaQueryWrapper<Firmware> wrapper = new LambdaQueryWrapper<>();
wrapper.ge(Firmware::getVersionId, firmwareVersionRequest.getVersion());
wrapper.eq(Firmware::getModelId, deviceCategory.getId());
wrapper.eq(Firmware::getFirmwareType, firmwareVersionRequest.getFirmwareType());
wrapper.orderByDesc(Firmware::getVersionId);
wrapper.last("LIMIT 1");
Firmware firmware = this.getOne(wrapper);
if (firmware == null) {
throw new RuntimeException("未找到匹配的固件版本");
}
return firmware;
}
/** /**
* 获取 URL 路径的最后一节(忽略查询参数 ? 和锚点 # * 获取 URL 路径的最后一节(忽略查询参数 ? 和锚点 #
* @param urlStr URL字符串 * @param urlStr URL字符串

View File

@@ -1,9 +1,9 @@
# spring profiles configuration # spring profiles configuration
######################################### #########################################
#spring.profiles.active=local spring.profiles.active=local
#spring.profiles.active=test #spring.profiles.active=test
spring.profiles.active=prod #spring.profiles.active=prod
######################################### #########################################
# 应用服务 WEB 访问端口 # 应用服务 WEB 访问端口

View File

@@ -64,6 +64,7 @@ error.token.replaced=Account has been logged in elsewhere
error.token.kicked.out=Account has been kicked offline error.token.kicked.out=Account has been kicked offline
error.not.login=Not logged in, please login first error.not.login=Not logged in, please login first
error.server.internal=Internal server error: {0} error.server.internal=Internal server error: {0}
error.system=System error, please try again later
# ==================== Utility Classes ==================== # ==================== Utility Classes ====================
# Redis Utility # Redis Utility
@@ -143,3 +144,5 @@ firmware.update.success=Firmware updated successfully
firmware.update.failed=Failed to update firmware firmware.update.failed=Failed to update firmware
firmware.not.found=Firmware not found firmware.not.found=Firmware not found
firmware.type.required=Firmware type is required firmware.type.required=Firmware type is required
firmware.type.or.model.required=Firmware type or model is required
firmware.device.not.found=Device not found

View File

@@ -64,6 +64,7 @@ error.token.replaced=账号已在其他地方登录
error.token.kicked.out=账号已被踢下线 error.token.kicked.out=账号已被踢下线
error.not.login=未登录,请先登录 error.not.login=未登录,请先登录
error.server.internal=服务器内部错误:{0} error.server.internal=服务器内部错误:{0}
error.system=系统错误,请稍后重试
# ==================== 工具类 ==================== # ==================== 工具类 ====================
# Redis工具类 # Redis工具类
@@ -143,3 +144,5 @@ firmware.update.success=固件更新成功
firmware.update.failed=固件更新失败 firmware.update.failed=固件更新失败
firmware.not.found=固件不存在 firmware.not.found=固件不存在
firmware.type.required=固件类型不能为空 firmware.type.required=固件类型不能为空
firmware.type.or.model.required=固件类型或型号不能为空
firmware.device.not.found=设备不存在