diff --git a/aircraft-common/src/main/java/com/aircraft/annotation/rest/AnonymousAccess.java b/aircraft-common/src/main/java/com/aircraft/annotation/rest/AnonymousAccess.java index eaf34e0..0f6867e 100644 --- a/aircraft-common/src/main/java/com/aircraft/annotation/rest/AnonymousAccess.java +++ b/aircraft-common/src/main/java/com/aircraft/annotation/rest/AnonymousAccess.java @@ -21,7 +21,7 @@ import java.lang.annotation.*; * @author jacky * 用于标记匿名访问方法 */ -@Inherited +//@Inherited @Documented @Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) diff --git a/aircraft-system/src/main/java/com/aircraft/modules/aircraft/mapper/AircraftDeviceMapper.java b/aircraft-system/src/main/java/com/aircraft/modules/aircraft/mapper/AircraftDeviceMapper.java index 47f55a3..e2ba17a 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/aircraft/mapper/AircraftDeviceMapper.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/aircraft/mapper/AircraftDeviceMapper.java @@ -9,7 +9,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Param; import java.util.List; -import java.util.Map; /** *

@@ -21,11 +20,11 @@ import java.util.Map; */ public interface AircraftDeviceMapper extends BaseMapper { - Map getAircraftDeviceById(List deviceIds); + List getAircraftDeviceById(List deviceIds); /** * 分页查询 飞行器设备 */ - IPage page(@Param("search")AircraftDevicePageDTO search, Page page); + IPage page(@Param("search") AircraftDevicePageDTO search, Page page); } diff --git a/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpArticleController.java b/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpArticleController.java index 1b6dd02..6166051 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpArticleController.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpArticleController.java @@ -107,8 +107,8 @@ public class CpArticleController { errorResponse.put("message", "不存在该文章"); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse); } - cpArticleMapper.updateViewCountById(id); - entity.setViewCount(entity.getViewCount()+1); +// cpArticleMapper.updateViewCountById(id); +// entity.setViewCount(entity.getViewCount()+1); return ResponseEntity.ok(entity); } catch (Exception e) { LOG.error("查询单个文章失败", e); diff --git a/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpMaterialController.java b/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpMaterialController.java index 4a76312..3f8e20d 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpMaterialController.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpMaterialController.java @@ -63,15 +63,12 @@ public class CpMaterialController { @RequestParam(required = false) String keyword) { try { QueryWrapper wrapper = new QueryWrapper<>(); - // 仅对素材名称进行模糊查询 if (keyword != null && !keyword.isEmpty()) { wrapper.like("name", keyword); } - - // 只查询未删除的素材 - wrapper.eq("del_flag", 0); - + wrapper.eq("del_flag", 0); // 只查询未删除的素材 + wrapper.orderByDesc("create_time");//按时间倒序排序 IPage records = materialService.page(page, wrapper); return new ResponseEntity<>(records, HttpStatus.OK); } catch (Exception e) { @@ -102,7 +99,7 @@ public class CpMaterialController { @PostMapping public ResponseEntity add(@Valid @RequestBody CpMaterialDTO material) { try { - CpMaterial cpMaterial=new CpMaterial(); + CpMaterial cpMaterial = new CpMaterial(); BeanUtils.copyProperties(material, cpMaterial); // 填充默认值 cpMaterial.setCreateTime(LocalDateTime.now()); @@ -152,6 +149,7 @@ public class CpMaterialController { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } + @ApiOperation(value = "删除素材", notes = "逻辑删除:将cp_material表中的del_flag设为1") @ApiImplicitParam(name = "id", value = "素材ID", required = true, paramType = "path", dataType = "int") @DeleteMapping("/{id}") @@ -165,7 +163,7 @@ public class CpMaterialController { // 逻辑删除:更新del_flag=1 material.setDelFlag(1); - materialService.updateDelFlagById(material.getId(),material.getDelFlag()); + materialService.updateDelFlagById(material.getId(), material.getDelFlag()); // 3. 删除成功,返回成功信息 Map success = new HashMap<>(); success.put("code", 200); diff --git a/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpTextController.java b/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpTextController.java index f30eba9..0bc5d73 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpTextController.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/article/controller/CpTextController.java @@ -1,7 +1,11 @@ package com.aircraft.modules.article.controller; + +import com.aircraft.annotation.rest.AnonymousAccess; +import com.aircraft.annotation.rest.AnonymousGetMapping; import com.aircraft.modules.article.domain.CpArticle; import com.aircraft.modules.article.domain.CpText; import com.aircraft.modules.article.mapper.CpLabelMapper; +import com.aircraft.modules.article.mapper.CpTextMapper; import com.aircraft.modules.article.service.CpArticleService; import com.aircraft.modules.article.service.CpTextService; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -44,13 +48,12 @@ public class CpTextController { @Autowired private CpTextService cpTextService; - @Autowired private CpArticleService cpArticleService; - @Autowired - private CpLabelMapper cpLabelMapper; + private CpTextMapper cpTextMapper; +// @AnonymousAccess @ApiOperation(value = "分页查询文本内容", notes = "分页查询文本内容") @RequestMapping(method = RequestMethod.GET) @ApiImplicitParams({ @@ -101,6 +104,8 @@ public class CpTextController { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } + +// @AnonymousAccess @ApiOperation(value = "查询单个文本内容") @RequestMapping(value = "{id}", method = {RequestMethod.GET}) @ApiImplicitParam(name = "id", value = "文本内容ID", required = true, paramType = "path") @@ -110,7 +115,8 @@ public class CpTextController { if (entity == null) { return ResponseEntity.notFound().build(); } - + cpTextMapper.updateViewCountById(id); + entity.setViewCount(entity.getViewCount() + 1); return ResponseEntity.ok(entity); } catch (Exception e) { LOG.error("查询单个文本内容失败", e); diff --git a/aircraft-system/src/main/java/com/aircraft/modules/article/domain/CpText.java b/aircraft-system/src/main/java/com/aircraft/modules/article/domain/CpText.java index b3c3d90..d253e3d 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/article/domain/CpText.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/article/domain/CpText.java @@ -30,6 +30,9 @@ public class CpText { @ApiModelProperty(value = "文章正文") private String text; + @ApiModelProperty(value = "浏览量") + private Long viewCount; + @ApiModelProperty(value = "逻辑删除:1删除,0正常") private Integer del_flag; } diff --git a/aircraft-system/src/main/java/com/aircraft/modules/article/mapper/CpTextMapper.java b/aircraft-system/src/main/java/com/aircraft/modules/article/mapper/CpTextMapper.java index a2fa359..62e3a8c 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/article/mapper/CpTextMapper.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/article/mapper/CpTextMapper.java @@ -18,4 +18,6 @@ import org.apache.ibatis.annotations.Mapper; public interface CpTextMapper extends BaseMapper { IPage findByPage(Page page, String keyWord); + + void updateViewCountById(Integer id); } diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/OrderDetailAnalysisResult.java b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/OrderDetailAnalysisResult.java index 9207e60..2e5f584 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/OrderDetailAnalysisResult.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/domain/dto/OrderDetailAnalysisResult.java @@ -18,6 +18,9 @@ public class OrderDetailAnalysisResult { private BigDecimal completionRate; // 任务完成率 private BigDecimal failedRate; // 任务失败率 + private Double averageTaskCycle; // 平均任务周期 + private BigDecimal droneUsageRate; // 无人机使用率 + private List routeDistribution; // 景区路线统计分布 private PageInfo pageInfo; // 分页信息 private List orderDetailList; // 子单列表(分页) diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderAnalysisServiceImpl.java b/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderAnalysisServiceImpl.java index 08c106a..3c89502 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderAnalysisServiceImpl.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderAnalysisServiceImpl.java @@ -341,7 +341,13 @@ public class OrderAnalysisServiceImpl implements OrderAnalysisService { .collect(Collectors.toList()); // 获取飞行设备 ID 对应的 AircraftDevice 对象的映射 - Map deviceMap = aircraftDeviceMapper.getAircraftDeviceById(deviceIds); + List deviceList = aircraftDeviceMapper.getAircraftDeviceById(deviceIds); + Map deviceMap = deviceList.stream() + .collect(Collectors.toMap( + AircraftDevice::getId, // 提取 ID 作为 key + device -> device, // 设备对象作为 value + (existing, replacement) -> existing // 处理 ID 重复(保留第一个) + )); // 按型号分组统计数量(处理设备不存在的情况) Map modelCountMap = orderDetails.stream() diff --git a/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderDetailAnalysisServiceImpl.java b/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderDetailAnalysisServiceImpl.java index 468643c..df30fba 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderDetailAnalysisServiceImpl.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/order/service/impl/OrderDetailAnalysisServiceImpl.java @@ -1,9 +1,9 @@ package com.aircraft.modules.order.service.impl; import com.aircraft.modules.aircraft.domain.AircraftDevice; +import com.aircraft.modules.aircraft.service.AircraftDeviceService; import com.aircraft.modules.order.controller.OrderAnalysisController; import com.aircraft.modules.order.domain.OrderDetail; -import com.aircraft.modules.order.domain.OrderMain; import com.aircraft.modules.order.domain.dto.*; import com.aircraft.modules.order.mapper.OrderDetailMapper; import com.aircraft.modules.order.service.OrderDetailAnalysisService; @@ -11,20 +11,22 @@ import com.aircraft.modules.route.domain.CpRoute; import com.aircraft.modules.route.mapper.CpRouteMapper; import com.aircraft.modules.system.mapper.EmScenicMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.apache.poi.ss.formula.functions.T; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.Duration; import java.time.LocalDate; import java.time.YearMonth; import java.time.ZoneId; import java.time.format.DateTimeFormatter; +import java.time.temporal.Temporal; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -51,10 +53,12 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic private CpRouteMapper cpRouteMapper; @Autowired private EmScenicMapper emScenicMapper; + @Autowired + private AircraftDeviceService aircraftDeviceService; @Override public OrderDetailAnalysisResult analyzeAllOrderDetails(List allDetails) { - return buildOrderDetailAnalysisResult(allDetails); + return buildOrderDetailAnalysisResult(allDetails); } @Override @@ -260,6 +264,14 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic result.setCompletionRate(calculateRate(completedCount, total)); result.setFailedRate(calculateRate(failedCount, total)); + // 新增: 计算平均任务周期(单位:分钟) + double averageTaskCycle = calculateAverageTaskCycle(orderDetails); + result.setAverageTaskCycle(averageTaskCycle); + + // 新增: 计算无人机使用率 + BigDecimal droneUsageRate = calculateDroneUsageRate(orderDetails); + result.setDroneUsageRate(droneUsageRate); + // 5. 景区路线订单分布 result.setRouteDistribution(calculateRouteDistribution(orderDetails)); @@ -269,11 +281,53 @@ public class OrderDetailAnalysisServiceImpl implements OrderDetailAnalysisServic result.setOrderDetailList(getPagedTasks(orderDetails, pageInfo)); // 7. 时间序列数据(在调用此方法的上层设置) - result.setTimeSeriesData(null); // 由调用者设置具体时间序列数据 + result.setTimeSeriesData(null); return result; } + //计算平均任务周期 + private double calculateAverageTaskCycle(List orderDetails) { + //获取任务数 + List completedTasks = orderDetails.stream() + .filter(task -> task.getOrderItemStatus() == STATUS_COMPLETED) + .collect(Collectors.toList()); + int completedTaskCount = completedTasks.size(); + if (completedTasks.isEmpty()) { + return 0.0; + } + //获取时间范围内任务的执行总时间:更新时间-创建时间 + long totalSeconds = completedTasks.stream() + .mapToLong(task -> + Duration.between(task.getCreateTime().toInstant(), task.getUpdateTime().toInstant()).getSeconds() + ) + .sum(); + + //平均执行任务时间=总执行任务时间÷总任务数 + return (double) totalSeconds / (60.0 * completedTaskCount); + } + + //计算无人机使用率 + private BigDecimal calculateDroneUsageRate(List orderDetails) { + // 1. 获取时间范围内订单中出现的无人机数量(去重) + Set usedDroneIds = orderDetails.stream() + .filter(task -> task.getDeviceId() != null) // 过滤使用了无人机的任务 + .map(OrderDetail::getDeviceId) + .collect(Collectors.toSet()); + int usedDroneCount = usedDroneIds.size(); + + // 2. 获取无人机总量 + QueryWrapper queryWrapper = new QueryWrapper<>(); + int totalDroneCount = aircraftDeviceService.count(queryWrapper); + + // 3. 计算使用率(保留两位小数) + if (totalDroneCount == 0) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf((double) usedDroneCount / totalDroneCount) + .setScale(2, RoundingMode.HALF_UP); + } + /** * 按状态统计任务数量 */ diff --git a/aircraft-system/src/main/java/com/aircraft/modules/security/config/SpringSecurityConfig.java b/aircraft-system/src/main/java/com/aircraft/modules/security/config/SpringSecurityConfig.java index 3d48625..caddeeb 100644 --- a/aircraft-system/src/main/java/com/aircraft/modules/security/config/SpringSecurityConfig.java +++ b/aircraft-system/src/main/java/com/aircraft/modules/security/config/SpringSecurityConfig.java @@ -66,6 +66,14 @@ public class SpringSecurityConfig { protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { // 获取匿名标记 Map> anonymousUrls = AnonTagUtils.getAnonymousUrl(applicationContext); + // 手动添加需要匿名访问的接口路径(核心修改) + // 1. 分页查询接口:GET /cpText + anonymousUrls.computeIfAbsent(RequestMethodEnum.GET.getType(), k -> new HashSet<>()) + .add("/cpText"); + // 2. 通过 ID 查询接口:GET /cpText/{id}(支持任意 ID) + anonymousUrls.computeIfAbsent(RequestMethodEnum.GET.getType(), k -> new HashSet<>()) + .add("/cpText/**"); + return httpSecurity // 禁用 CSRF .csrf().disable() @@ -88,6 +96,10 @@ public class SpringSecurityConfig { // 静态资源等等 .antMatchers( HttpMethod.GET, +// "/swagger-ui.html", +// "/swagger-resources/**", +// "/*/api-docs", // Swagger API 文档接口 +// "/doc.html" , // Knife4j 文档页面 "/*.html", "/**/*.html", "/**/*.css", diff --git a/aircraft-system/src/main/resources/mapper/aircraft/AircraftDeviceMapper.xml b/aircraft-system/src/main/resources/mapper/aircraft/AircraftDeviceMapper.xml index 9b0b078..acf7666 100644 --- a/aircraft-system/src/main/resources/mapper/aircraft/AircraftDeviceMapper.xml +++ b/aircraft-system/src/main/resources/mapper/aircraft/AircraftDeviceMapper.xml @@ -3,22 +3,21 @@ - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - - - - - - - diff --git a/aircraft-system/src/main/resources/mapper/article/CpTextMapper.xml b/aircraft-system/src/main/resources/mapper/article/CpTextMapper.xml index 0bd2cb3..a8f24bc 100644 --- a/aircraft-system/src/main/resources/mapper/article/CpTextMapper.xml +++ b/aircraft-system/src/main/resources/mapper/article/CpTextMapper.xml @@ -10,4 +10,11 @@ ORDER BY id DESC + + + UPDATE cp_text + SET view_count = view_count + 1 -- 自增1 + WHERE id = #{id} + AND del_flag = 0 -- 确保只更新未删除的文章 +