Parcourir la source

Merge remote-tracking branch 'origin/sit' into sit

刘云鑫 il y a 2 mois
Parent
commit
5ae6df3757

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

@@ -62,6 +62,18 @@ public class StoreOperationalStatisticsHistory {
     @TableField("pdf_url")
     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:已删除")
     @TableField("delete_flag")
     @TableLogic

+ 1 - 1
alien-entity/src/main/java/shop/alien/mapper/LifeUserDynamicsMapper.java

@@ -49,7 +49,7 @@ public interface LifeUserDynamicsMapper extends BaseMapper<LifeUserDynamics> {
             "on llr.huifu_id = lud.id\n" +
             "and lu.user_phone = (select CONCAT('user_',lu1.user_phone) from life_user lu1 where lu1.id = #{userId})" +
             "${ew.customSqlSegment}")
-    List<LifeUserDynamicsVo> getStoreDynamicslist(@Param("userId") String userId, @Param(Constants.WRAPPER) QueryWrapper<LifeUserDynamics> dynamicsWrapper);
+    List<LifeUserDynamicsVo> getStoreDynamicslistWithWrapper(@Param("userId") String userId, @Param(Constants.WRAPPER) QueryWrapper<LifeUserDynamics> dynamicsWrapper);
 
     @Select("with middle_lud as (\n" +
             "  select distinct  \n" +

+ 1 - 1
alien-entity/src/main/java/shop/alien/mapper/PlatformStoreCouponMapper.java

@@ -26,7 +26,7 @@ public interface PlatformStoreCouponMapper extends BaseMapper<LifeCoupon> {
             "join store_info store on store.id = coupon.store_id " +
             "join store_user user on store.id = user.store_id " +
             "${ew.customSqlSegment}")
-    List<LifeCouponVo> getCouponList(@Param(Constants.WRAPPER) QueryWrapper<LifeCouponVo> wrapper);
+    List<LifeCouponVo> getCouponListWithoutPage(@Param(Constants.WRAPPER) QueryWrapper<LifeCouponVo> wrapper);
 
     @Select("select lc.*,si.store_name,si.store_tel phone\n" +
             "from life_coupon lc \n" +

+ 1 - 1
alien-entity/src/main/java/shop/alien/mapper/PlatformStoreLifeGroupBuyMainMapper.java

@@ -30,6 +30,6 @@ public interface PlatformStoreLifeGroupBuyMainMapper extends BaseMapper<LifeGrou
             "\tJOIN store_info store ON store.id = life.store_id\n" +
             "\tJOIN store_user user ON store.id = user.store_id\n"+
             "${ew.customSqlSegment}")
-    List<LifeGroupBuyMainVo> getLifeGroupBuyMainList(@Param(Constants.WRAPPER) QueryWrapper<LifeGroupBuyMainVo> wrapper);
+    List<LifeGroupBuyMainVo> getLifeGroupBuyMainListWithoutPage(@Param(Constants.WRAPPER) QueryWrapper<LifeGroupBuyMainVo> wrapper);
 
 }

+ 1 - 1
alien-store/src/main/java/shop/alien/store/service/LifeUserStoreService.java

@@ -451,7 +451,7 @@ public class LifeUserStoreService {
         QueryWrapper<LifeUserDynamics> dynamicsWrapper = new QueryWrapper<>();
         dynamicsWrapper.eq("phone_id", "store_" + storeInfoVoOne.getStorePhone())
                 .orderByDesc("lud.created_time");
-        List<LifeUserDynamicsVo> storeDynamicslist = lifeUserDynamicsMapper.getStoreDynamicslist(userId, dynamicsWrapper);
+        List<LifeUserDynamicsVo> storeDynamicslist = lifeUserDynamicsMapper.getStoreDynamicslistWithWrapper(userId, dynamicsWrapper);
         List<Map<String, Object>> dynamicsList = new ArrayList<>();
         List<LifeUserDynamicsVo> storeDynamicslist2 = storeDynamicslist.stream().limit(10).collect(Collectors.toList());
         for (LifeUserDynamicsVo lifeUserDynamicsVo : storeDynamicslist2) {

+ 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);
 
     /**
+     * 更新历史统计记录的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
      *
      * @param storeId           店铺ID

+ 2 - 2
alien-store/src/main/java/shop/alien/store/service/impl/PlatformStoreCouponServiceImpl.java

@@ -307,7 +307,7 @@ public class PlatformStoreCouponServiceImpl implements PlatformStoreCouponServic
             wrapper.lt("coupon.end_date", currentDate);
         }
 
-        List<LifeCouponVo> lifeCouponVo = platformStoreCouponMapper.getCouponList(wrapper);
+        List<LifeCouponVo> lifeCouponVo = platformStoreCouponMapper.getCouponListWithoutPage(wrapper);
         lifeCouponVo.forEach(item -> {
             if (item.getStatus() == 5 && item.getStockQty() > 0) {
                 item.setCouponState("进行中");
@@ -412,7 +412,7 @@ public class PlatformStoreCouponServiceImpl implements PlatformStoreCouponServic
 
         wrapper.orderByDesc("life.created_time");
 
-        List<LifeGroupBuyMainVo> lifeGroupBuyMainList = platformStoreLifeGroupBuyMainMapper.getLifeGroupBuyMainList(wrapper);
+        List<LifeGroupBuyMainVo> lifeGroupBuyMainList = platformStoreLifeGroupBuyMainMapper.getLifeGroupBuyMainListWithoutPage(wrapper);
         lifeGroupBuyMainList.forEach(item -> {
             if (item.getStatus() == 1) {
                 item.setCouponState("待审核");

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

@@ -63,6 +63,18 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
     @Override
     public StoreOperationalStatisticsVo getStatistics(Integer storeId, String startTime, String 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);
     }
 
@@ -173,6 +185,23 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
         log.info("StoreOperationalStatisticsServiceImpl.getStatisticsComparison - 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();
         comparison.setCurrentStartTime(currentStartTime);
         comparison.setCurrentEndTime(currentEndTime);
@@ -347,8 +376,10 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
 
         // 浏览记录统计
         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);
         List<LifeBrowseRecord> browseRecords = lifeBrowseRecordMapper.selectList(browseWrapper);
 
@@ -382,8 +413,10 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
 
         // 收藏次数
         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);
         long collectionCount = lifeCollectMapper.selectCount(collectWrapper);
         interactionData.setStoreCollectionCount(collectionCount);
@@ -979,8 +1012,11 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
         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);
@@ -1086,6 +1122,56 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
             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);
-        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 {
-            vo.setAvgVisitDuration(0L);
+            // 如果没有访客数,使用原有的平均时长数据
+            Long avgDuration = accumulator.getOrDefault("avgDuration", 0L);
+            vo.setAvgVisitDuration(avgDuration > 0 ? avgDuration / 1000 : 0L);
         }
         
         return vo;
@@ -1569,9 +1658,26 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
         log.info("StoreOperationalStatisticsServiceImpl.generateStatisticsComparisonPdf - 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 {
-            // 1. 获取统计数据对比
-            StoreOperationalStatisticsComparisonVo comparison = getStatisticsComparison(
+            // 1. 获取统计数据对比(不保存历史记录,因为后面会保存带PDF URL的记录)
+            StoreOperationalStatisticsComparisonVo comparison = getStatisticsComparisonWithoutSave(
                     storeId, currentStartTime, currentEndTime, previousStartTime, previousEndTime);
             
             // 2. 生成图片
@@ -1602,5 +1708,34 @@ public class StoreOperationalStatisticsServiceImpl implements StoreOperationalSt
             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;
+    }
 
 }