lutong 2 месяцев назад
Родитель
Сommit
0502c8ce6b

+ 12 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreOperationalStatisticsHistory.java

@@ -62,6 +62,18 @@ public class StoreOperationalStatisticsHistory {
     @TableField("pdf_url")
     @TableField("pdf_url")
     private String pdfUrl;
     private String pdfUrl;
 
 
+    @ApiModelProperty(value = "AI分析是否完成, 0:未完成, 1:已完成")
+    @TableField("ai_analysis_completed")
+    private Integer aiAnalysisCompleted;
+
+    @ApiModelProperty(value = "总结")
+    @TableField("summary")
+    private String summary;
+
+    @ApiModelProperty(value = "优化建议")
+    @TableField("optimization_suggestions")
+    private String optimizationSuggestions;
+
     @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
     @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
     @TableField("delete_flag")
     @TableField("delete_flag")
     @TableLogic
     @TableLogic

+ 11 - 0
alien-store/src/main/java/shop/alien/store/service/StoreOperationalStatisticsService.java

@@ -85,6 +85,17 @@ public interface StoreOperationalStatisticsService {
     boolean updateHistoryPdfUrl(Integer historyId, String pdfUrl);
     boolean updateHistoryPdfUrl(Integer historyId, String pdfUrl);
 
 
     /**
     /**
+     * 更新历史统计记录的AI分析结果
+     *
+     * @param historyId             历史记录ID
+     * @param aiAnalysisCompleted   AI分析是否完成, 0:未完成, 1:已完成
+     * @param summary               总结
+     * @param optimizationSuggestions 优化建议
+     * @return 是否成功
+     */
+    boolean updateHistoryAiAnalysis(Integer historyId, Integer aiAnalysisCompleted, String summary, String optimizationSuggestions);
+
+    /**
      * 生成统计数据对比PDF报告并上传到OSS
      * 生成统计数据对比PDF报告并上传到OSS
      *
      *
      * @param storeId           店铺ID
      * @param storeId           店铺ID

+ 149 - 14
alien-store/src/main/java/shop/alien/store/service/impl/StoreOperationalStatisticsServiceImpl.java

@@ -63,6 +63,18 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
     @Override
     @Override
     public StoreOperationalStatisticsVo getStatistics(Integer storeId, String startTime, String endTime) {
     public StoreOperationalStatisticsVo getStatistics(Integer storeId, String startTime, String endTime) {
         log.info("StoreOperationalStatisticsServiceImpl.getStatistics - storeId={}, startTime={}, endTime={}", storeId, startTime, endTime);
         log.info("StoreOperationalStatisticsServiceImpl.getStatistics - storeId={}, startTime={}, endTime={}", storeId, startTime, endTime);
+        
+        // 参数校验
+        if (storeId == null || storeId <= 0) {
+            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
+        }
+        if (startTime == null || startTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("开始时间不能为空");
+        }
+        if (endTime == null || endTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("结束时间不能为空");
+        }
+        
         return calculateStatistics(storeId, startTime, endTime);
         return calculateStatistics(storeId, startTime, endTime);
     }
     }
 
 
@@ -173,6 +185,23 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
         log.info("StoreOperationalStatisticsServiceImpl.getStatisticsComparison - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}",
         log.info("StoreOperationalStatisticsServiceImpl.getStatisticsComparison - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}",
                 storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
                 storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
 
 
+        // 参数校验
+        if (storeId == null || storeId <= 0) {
+            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
+        }
+        if (currentStartTime == null || currentStartTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("当期开始时间不能为空");
+        }
+        if (currentEndTime == null || currentEndTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("当期结束时间不能为空");
+        }
+        if (previousStartTime == null || previousStartTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("上期开始时间不能为空");
+        }
+        if (previousEndTime == null || previousEndTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("上期结束时间不能为空");
+        }
+
         StoreOperationalStatisticsComparisonVo comparison = new StoreOperationalStatisticsComparisonVo();
         StoreOperationalStatisticsComparisonVo comparison = new StoreOperationalStatisticsComparisonVo();
         comparison.setCurrentStartTime(currentStartTime);
         comparison.setCurrentStartTime(currentStartTime);
         comparison.setCurrentEndTime(currentEndTime);
         comparison.setCurrentEndTime(currentEndTime);
@@ -347,8 +376,10 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
 
 
         // 浏览记录统计
         // 浏览记录统计
         LambdaQueryWrapper<LifeBrowseRecord> browseWrapper = new LambdaQueryWrapper<>();
         LambdaQueryWrapper<LifeBrowseRecord> browseWrapper = new LambdaQueryWrapper<>();
-        browseWrapper.eq(LifeBrowseRecord::getStoreId, String.valueOf(storeId))
-                .between(LifeBrowseRecord::getCreatedTime, startDate, endDate)
+        if (storeId != null) {
+            browseWrapper.eq(LifeBrowseRecord::getStoreId, String.valueOf(storeId));
+        }
+        browseWrapper.between(LifeBrowseRecord::getCreatedTime, startDate, endDate)
                 .eq(LifeBrowseRecord::getDeleteFlag, 0);
                 .eq(LifeBrowseRecord::getDeleteFlag, 0);
         List<LifeBrowseRecord> browseRecords = lifeBrowseRecordMapper.selectList(browseWrapper);
         List<LifeBrowseRecord> browseRecords = lifeBrowseRecordMapper.selectList(browseWrapper);
 
 
@@ -382,8 +413,10 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
 
 
         // 收藏次数
         // 收藏次数
         LambdaQueryWrapper<LifeCollect> collectWrapper = new LambdaQueryWrapper<>();
         LambdaQueryWrapper<LifeCollect> collectWrapper = new LambdaQueryWrapper<>();
-        collectWrapper.eq(LifeCollect::getStoreId, String.valueOf(storeId))
-                .between(LifeCollect::getCreatedTime, startDate, endDate)
+        if (storeId != null) {
+            collectWrapper.eq(LifeCollect::getStoreId, String.valueOf(storeId));
+        }
+        collectWrapper.between(LifeCollect::getCreatedTime, startDate, endDate)
                 .eq(LifeCollect::getDeleteFlag, 0);
                 .eq(LifeCollect::getDeleteFlag, 0);
         long collectionCount = lifeCollectMapper.selectCount(collectWrapper);
         long collectionCount = lifeCollectMapper.selectCount(collectWrapper);
         interactionData.setStoreCollectionCount(collectionCount);
         interactionData.setStoreCollectionCount(collectionCount);
@@ -979,8 +1012,11 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
         log.info("StoreOperationalStatisticsServiceImpl.getHistoryList - storeId={}, page={}, size={}", storeId, page, size);
         log.info("StoreOperationalStatisticsServiceImpl.getHistoryList - storeId={}, page={}, size={}", storeId, page, size);
         
         
         // 参数校验
         // 参数校验
-        int pageNum = page > 0 ? page : 1;
-        int pageSize = size > 0 ? size : 10;
+        if (storeId == null || storeId <= 0) {
+            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
+        }
+        int pageNum = page != null && page > 0 ? page : 1;
+        int pageSize = size != null && size > 0 ? size : 10;
         
         
         // 构建分页对象
         // 构建分页对象
         IPage<StoreOperationalStatisticsHistory> pageObj = new Page<>(pageNum, pageSize);
         IPage<StoreOperationalStatisticsHistory> pageObj = new Page<>(pageNum, pageSize);
@@ -1086,6 +1122,56 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
             return false;
             return false;
         }
         }
     }
     }
+
+    @Override
+    public boolean updateHistoryAiAnalysis(Integer historyId, Integer aiAnalysisCompleted, String summary, String optimizationSuggestions) {
+        log.info("StoreOperationalStatisticsServiceImpl.updateHistoryAiAnalysis - historyId={}, aiAnalysisCompleted={}", historyId, aiAnalysisCompleted);
+        
+        if (historyId == null || historyId <= 0) {
+            log.warn("更新历史统计记录AI分析结果失败,历史记录ID无效 - historyId={}", historyId);
+            return false;
+        }
+        
+        try {
+            // 查询历史记录是否存在且未删除
+            StoreOperationalStatisticsHistory history = statisticsHistoryMapper.selectOne(
+                    new LambdaQueryWrapper<StoreOperationalStatisticsHistory>()
+                            .eq(StoreOperationalStatisticsHistory::getId, historyId)
+                            .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0));
+            
+            if (history == null) {
+                log.warn("更新历史统计记录AI分析结果失败,历史记录不存在或已删除 - historyId={}", historyId);
+                return false;
+            }
+            
+            // 更新AI分析相关字段
+            LambdaUpdateWrapper<StoreOperationalStatisticsHistory> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.eq(StoreOperationalStatisticsHistory::getId, historyId)
+                   .eq(StoreOperationalStatisticsHistory::getDeleteFlag, 0);
+            
+            if (aiAnalysisCompleted != null) {
+                wrapper.set(StoreOperationalStatisticsHistory::getAiAnalysisCompleted, aiAnalysisCompleted);
+            }
+            if (summary != null) {
+                wrapper.set(StoreOperationalStatisticsHistory::getSummary, summary.trim());
+            }
+            if (optimizationSuggestions != null) {
+                wrapper.set(StoreOperationalStatisticsHistory::getOptimizationSuggestions, optimizationSuggestions.trim());
+            }
+            
+            int result = statisticsHistoryMapper.update(null, wrapper);
+            if (result > 0) {
+                log.info("更新历史统计记录AI分析结果成功 - historyId={}, aiAnalysisCompleted={}", historyId, aiAnalysisCompleted);
+                return true;
+            } else {
+                log.warn("更新历史统计记录AI分析结果失败,未更新任何记录 - historyId={}", historyId);
+                return false;
+            }
+        } catch (Exception e) {
+            log.error("更新历史统计记录AI分析结果失败 - historyId={}, error={}", historyId, e.getMessage(), e);
+            return false;
+        }
+    }
     
     
     // ==================== 累加和转换方法 ====================
     // ==================== 累加和转换方法 ====================
     
     
@@ -1297,14 +1383,17 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
         
         
         // 访问时长转换为秒(原数据是毫秒)
         // 访问时长转换为秒(原数据是毫秒)
         Long totalDuration = accumulator.getOrDefault("totalDuration", 0L);
         Long totalDuration = accumulator.getOrDefault("totalDuration", 0L);
-        vo.setVisitDuration(totalDuration / 1000);
+        vo.setVisitDuration(totalDuration > 0 ? totalDuration / 1000 : 0L);
         
         
-        // 平均访问时长:如果有多个统计记录,需要重新计算平均值
-        Long avgDuration = accumulator.getOrDefault("avgDuration", 0L);
-        if (count > 0 && avgDuration > 0) {
-            vo.setAvgVisitDuration(avgDuration / 1000); // 转换为秒
+        // 平均访问时长:总时长除以访问次数(转换为秒)
+        Long visitorCount = accumulator.getOrDefault("visitorCount", 0L);
+        if (count > 0 && totalDuration > 0 && visitorCount > 0) {
+            // 平均访问时长 = 总时长 / 访客数(转换为秒)
+            vo.setAvgVisitDuration((totalDuration / visitorCount) / 1000);
         } else {
         } else {
-            vo.setAvgVisitDuration(0L);
+            // 如果没有访客数,使用原有的平均时长数据
+            Long avgDuration = accumulator.getOrDefault("avgDuration", 0L);
+            vo.setAvgVisitDuration(avgDuration > 0 ? avgDuration / 1000 : 0L);
         }
         }
         
         
         return vo;
         return vo;
@@ -1569,9 +1658,26 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
         log.info("StoreOperationalStatisticsServiceImpl.generateStatisticsComparisonPdf - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}",
         log.info("StoreOperationalStatisticsServiceImpl.generateStatisticsComparisonPdf - storeId={}, currentStartTime={}, currentEndTime={}, previousStartTime={}, previousEndTime={}",
                 storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
                 storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
         
         
+        // 参数校验
+        if (storeId == null || storeId <= 0) {
+            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
+        }
+        if (currentStartTime == null || currentStartTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("当期开始时间不能为空");
+        }
+        if (currentEndTime == null || currentEndTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("当期结束时间不能为空");
+        }
+        if (previousStartTime == null || previousStartTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("上期开始时间不能为空");
+        }
+        if (previousEndTime == null || previousEndTime.trim().isEmpty()) {
+            throw new IllegalArgumentException("上期结束时间不能为空");
+        }
+        
         try {
         try {
-            // 1. 获取统计数据对比
-            StoreOperationalStatisticsComparisonVo comparison = getStatisticsComparison(
+            // 1. 获取统计数据对比(不保存历史记录,因为后面会保存带PDF URL的记录)
+            StoreOperationalStatisticsComparisonVo comparison = getStatisticsComparisonWithoutSave(
                     storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
                     storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
             
             
             // 2. 生成图片
             // 2. 生成图片
@@ -1602,5 +1708,34 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
             throw new RuntimeException("生成图片并转PDF上传失败: " + e.getMessage(), e);
             throw new RuntimeException("生成图片并转PDF上传失败: " + e.getMessage(), e);
         }
         }
     }
     }
+    
+    /**
+     * 获取统计数据对比(不保存历史记录)
+     * 用于 generateStatisticsComparisonPdf 方法,避免重复保存历史记录
+     */
+    private StoreOperationalStatisticsComparisonVo getStatisticsComparisonWithoutSave(Integer storeId, String currentStartTime, String currentEndTime,
+                                                                                      String previousStartTime, String previousEndTime) {
+        StoreOperationalStatisticsComparisonVo comparison = new StoreOperationalStatisticsComparisonVo();
+        comparison.setCurrentStartTime(currentStartTime);
+        comparison.setCurrentEndTime(currentEndTime);
+        comparison.setPreviousStartTime(previousStartTime);
+        comparison.setPreviousEndTime(previousEndTime);
+
+        // 获取当期和上期的统计数据
+        StoreOperationalStatisticsVo currentStatistics = calculateStatistics(storeId, currentStartTime, currentEndTime);
+        StoreOperationalStatisticsVo previousStatistics = calculateStatistics(storeId, previousStartTime, previousEndTime);
+
+        // 构建对比数据
+        comparison.setTrafficData(buildTrafficDataComparison(currentStatistics.getTrafficData(), previousStatistics.getTrafficData()));
+        comparison.setInteractionData(buildInteractionDataComparison(currentStatistics.getInteractionData(), previousStatistics.getInteractionData()));
+        comparison.setCouponData(buildCouponDataComparison(currentStatistics.getCouponData(), previousStatistics.getCouponData()));
+        comparison.setVoucherData(buildVoucherDataComparison(currentStatistics.getVoucherData(), previousStatistics.getVoucherData()));
+        comparison.setServiceQualityData(buildServiceQualityDataComparison(currentStatistics.getServiceQualityData(), previousStatistics.getServiceQualityData()));
+        comparison.setPriceListRanking(buildPriceListRankingComparison(currentStatistics.getPriceListRanking(), previousStatistics.getPriceListRanking()));
+
+        // 不保存历史记录,由调用方决定是否保存
+
+        return comparison;
+    }
 
 
 }
 }