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