From 4c10c1d9396fd949e0fba0e410e04fc2364af2eb Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 31 Oct 2025 18:44:43 +0800 Subject: [PATCH] 2 --- .../service/pc/helper/ScenicConfigFacade.java | 214 ++++++++++++++++++ .../service/pc/impl/FaceServiceImpl.java | 51 ++--- .../pc/processor/BuyStatusProcessor.java | 10 +- .../pc/processor/FaceRecoveryStrategy.java | 6 +- .../pc/processor/SourceRelationProcessor.java | 32 +-- .../pc/processor/VideoRecreationHandler.java | 16 +- 6 files changed, 273 insertions(+), 56 deletions(-) create mode 100644 src/main/java/com/ycwl/basic/service/pc/helper/ScenicConfigFacade.java diff --git a/src/main/java/com/ycwl/basic/service/pc/helper/ScenicConfigFacade.java b/src/main/java/com/ycwl/basic/service/pc/helper/ScenicConfigFacade.java new file mode 100644 index 00000000..7b429aad --- /dev/null +++ b/src/main/java/com/ycwl/basic/service/pc/helper/ScenicConfigFacade.java @@ -0,0 +1,214 @@ +package com.ycwl.basic.service.pc.helper; + +import com.ycwl.basic.repository.ScenicRepository; +import com.ycwl.basic.integration.common.manager.ScenicConfigManager; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 景区配置门面类 + * 提供类型安全的配置访问方法,避免配置键的字符串硬编码 + * 集中管理所有景区配置项的访问逻辑 + * + * @author Claude + * @since 2025-10-31 + */ +@Slf4j +@Component +public class ScenicConfigFacade { + + @Autowired + private ScenicRepository scenicRepository; + + /** + * 获取景区配置管理器 + */ + private ScenicConfigManager getConfig(Long scenicId) { + return scenicRepository.getScenicConfigManager(scenicId); + } + + // ==================== 人脸识别相关配置 ==================== + + /** + * 是否优先手动选择人脸 + * 如果为 true,则不自动创建任务 + * + * @param scenicId 景区ID + * @return true-需要手动选择,false-自动创建任务 + */ + public boolean isFaceSelectFirst(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return false; + } + Boolean value = config.getBoolean("face_select_first"); + return Boolean.TRUE.equals(value); + } + + /** + * 获取自定义人脸匹配的最大次数 + * 用于限制用户手动重新匹配的次数 + * + * @param scenicId 景区ID + * @return 最大匹配次数,null 或 0 表示不限制 + */ + public Integer getFaceSelectMaxCount(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return null; + } + return config.getInteger("face_select_max_count"); + } + + /** + * 获取人脸分数低阈值 + * 低于此分数的匹配结果会被标记为低置信度 + * + * @param scenicId 景区ID + * @return 分数阈值,默认 30.0 + */ + public Float getFaceScoreLowThreshold(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return 30.0F; + } + return config.getFloat("face_score_low_threshold", 30.0F); + } + + /** + * 获取人脸检测辅助阈值 + * 当匹配结果数量少于此阈值时,会触发补救逻辑 + * + * @param scenicId 景区ID + * @return 辅助阈值,默认 0(不启用) + */ + public Integer getFaceDetectHelperThreshold(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return 0; + } + return config.getInteger("face_detect_helper_threshold", 0); + } + + /** + * 获取人脸选择后处理模式 + * 0-并集模式,1-交集模式 + * + * @param scenicId 景区ID + * @return 后处理模式,默认 0 + */ + public Integer getFaceSelectPostMode(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return 0; + } + return config.getInteger("face_select_post_mode", 0); + } + + /** + * 获取重新匹配模式 + * 用于决定在什么条件下需要重新进行人脸匹配 + * + * @param scenicId 景区ID + * @return 匹配模式,默认 0 + */ + public Integer getRematchMode(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return 0; + } + return config.getInteger("re_match_mode", 0); + } + + // ==================== 源文件相关配置 ==================== + + /** + * 是否禁用源图片功能 + * + * @param scenicId 景区ID + * @return true-禁用,false-启用 + */ + public boolean isDisableSourceImage(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return false; + } + Boolean value = config.getBoolean("disable_source_image"); + return Boolean.TRUE.equals(value); + } + + /** + * 是否禁用源视频功能 + * + * @param scenicId 景区ID + * @return true-禁用,false-启用 + */ + public boolean isDisableSourceVideo(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return false; + } + Boolean value = config.getBoolean("disable_source_video"); + return Boolean.TRUE.equals(value); + } + + /** + * 获取免费照片数量 + * 新用户首次识别时赠送的免费照片数量 + * + * @param scenicId 景区ID + * @return 免费照片数量,null 或 0 表示不赠送 + */ + public Integer getPhotoFreeNum(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return null; + } + return config.getInteger("photo_free_num"); + } + + // ==================== 游玩时间相关配置 ==================== + + /** + * 获取最大游玩时间(分钟) + * 用于判断照片是否在合理的游玩时间范围内 + * + * @param scenicId 景区ID + * @return 最大游玩时间(分钟),null 表示不限制 + */ + public Integer getTourTime(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return null; + } + return config.getInteger("tour_time"); + } + + /** + * 获取最小游玩时间(分钟) + * 用于判断照片是否在合理的游玩时间范围内 + * + * @param scenicId 景区ID + * @return 最小游玩时间(分钟),null 表示不限制 + */ + public Integer getTourMinTime(Long scenicId) { + ScenicConfigManager config = getConfig(scenicId); + if (config == null) { + return null; + } + return config.getInteger("tour_min_time"); + } + + /** + * 检查是否配置了游玩时间限制 + * + * @param scenicId 景区ID + * @return true-已配置,false-未配置 + */ + public boolean hasTourTimeConfig(Long scenicId) { + Integer maxTime = getTourTime(scenicId); + Integer minTime = getTourMinTime(scenicId); + return maxTime != null && minTime != null; + } +} diff --git a/src/main/java/com/ycwl/basic/service/pc/impl/FaceServiceImpl.java b/src/main/java/com/ycwl/basic/service/pc/impl/FaceServiceImpl.java index d230fb90..edf31df3 100644 --- a/src/main/java/com/ycwl/basic/service/pc/impl/FaceServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/pc/impl/FaceServiceImpl.java @@ -6,11 +6,9 @@ import com.github.pagehelper.PageInfo; import com.ycwl.basic.biz.OrderBiz; import com.ycwl.basic.biz.TemplateBiz; import com.ycwl.basic.constant.BaseContextHandler; -import com.ycwl.basic.enums.StatisticEnum; import com.ycwl.basic.exception.BaseException; import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter; import com.ycwl.basic.facebody.entity.SearchFaceResultItem; -import com.ycwl.basic.integration.common.manager.DeviceConfigManager; import com.ycwl.basic.mapper.FaceSampleMapper; import com.ycwl.basic.mapper.ProjectMapper; import com.ycwl.basic.mapper.SourceMapper; @@ -24,7 +22,6 @@ import com.ycwl.basic.model.mobile.face.FaceStatusResp; import com.ycwl.basic.model.mobile.goods.VideoTaskStatusVO; import com.ycwl.basic.model.mobile.order.IsBuyRespVO; import com.ycwl.basic.model.mobile.scenic.content.ContentPageVO; -import com.ycwl.basic.model.mobile.statistic.req.StatisticsRecordAddReq; import com.ycwl.basic.model.pc.device.entity.DeviceEntity; import com.ycwl.basic.model.pc.face.entity.FaceEntity; import com.ycwl.basic.model.mobile.face.FaceRecognitionUpdateReq; @@ -58,8 +55,10 @@ import com.ycwl.basic.repository.VideoTaskRepository; import com.ycwl.basic.service.mobile.GoodsService; import com.ycwl.basic.service.pc.FaceService; import com.ycwl.basic.service.pc.ScenicService; +import com.ycwl.basic.constant.SourceType; import com.ycwl.basic.service.pc.helper.FaceMetricsRecorder; import com.ycwl.basic.service.pc.helper.SearchResultMerger; +import com.ycwl.basic.service.pc.helper.ScenicConfigFacade; import com.ycwl.basic.service.pc.processor.BuyStatusProcessor; import com.ycwl.basic.service.pc.processor.FaceRecoveryStrategy; import com.ycwl.basic.service.pc.processor.SourceRelationProcessor; @@ -73,12 +72,10 @@ import com.ycwl.basic.storage.StorageFactory; import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.storage.enums.StorageAcl; import com.ycwl.basic.storage.utils.StorageUtil; -import com.ycwl.basic.task.VideoPieceGetter; import com.ycwl.basic.utils.*; import lombok.extern.slf4j.Slf4j; import org.apache.logging.log4j.util.Strings; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -86,10 +83,8 @@ import java.io.File; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -98,14 +93,9 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.Stream; -import static com.ycwl.basic.constant.FaceConstant.FACE_CUSTOM_MATCH_COUNT_PFX; -import static com.ycwl.basic.constant.FaceConstant.FACE_LOW_THRESHOLD_PFX; -import static com.ycwl.basic.constant.FaceConstant.FACE_RECOGNITION_COUNT_PFX; import static com.ycwl.basic.constant.FaceConstant.USER_FACE_DB_NAME; import static com.ycwl.basic.constant.StorageConstant.USER_FACE; @@ -138,8 +128,6 @@ public class FaceServiceImpl implements FaceService { @Autowired private ScenicService scenicService; @Autowired - private TemplateMapper templateMapper; - @Autowired private VideoRepository videoRepository; @Autowired private VideoTaskRepository videoTaskRepository; @@ -150,8 +138,6 @@ public class FaceServiceImpl implements FaceService { @Autowired private OrderMapper orderMapper; @Autowired - private RedisTemplate redisTemplate; - @Autowired private FaceSampleMapper faceSampleMapper; @Autowired private GoodsService goodsService; @@ -169,6 +155,8 @@ public class FaceServiceImpl implements FaceService { private SearchResultMerger resultMerger; @Autowired private RematchStrategyFactory rematchStrategyFactory; + @Autowired + private ScenicConfigFacade scenicConfigFacade; // 第二阶段的处理器 @Autowired @@ -374,12 +362,12 @@ public class FaceServiceImpl implements FaceService { if (!memberSourceEntityList.isEmpty()) { // 5. 业务逻辑处理:免费逻辑、购买状态、任务创建 - List freeSourceIds = sourceRelationProcessor.processFreeSourceLogic(memberSourceEntityList, scenicConfig, isNew); + List freeSourceIds = sourceRelationProcessor.processFreeSourceLogic(memberSourceEntityList, face.getScenicId(), isNew); buyStatusProcessor.processBuyStatus(memberSourceEntityList, freeSourceIds, face.getMemberId(), face.getScenicId(), faceId); // 处理视频重切逻辑 - videoRecreationHandler.handleVideoRecreation(scenicConfig, memberSourceEntityList, faceId, + videoRecreationHandler.handleVideoRecreation(face.getScenicId(), memberSourceEntityList, faceId, face.getMemberId(), sampleListIds, isNew); // 过滤已存在的关联关系和无效的source引用,防止数据不一致 @@ -395,8 +383,7 @@ public class FaceServiceImpl implements FaceService { memberRelationRepository.clearSCacheByFace(faceId); // 检查景区配置中的 face_select_first,如果为 true 则不自动创建任务 - Boolean faceSelectFirst = scenicConfig != null ? scenicConfig.getBoolean("face_select_first") : null; - if (!Boolean.TRUE.equals(faceSelectFirst)) { + if (!scenicConfigFacade.isFaceSelectFirst(face.getScenicId())) { taskTaskService.autoCreateTaskByFaceId(faceId); } else { log.debug("景区配置 face_select_first=true,跳过自动创建任务:faceId={}", faceId); @@ -573,8 +560,8 @@ public class FaceServiceImpl implements FaceService { sourceVideoContent.setGroup("直出原片"); sourceImageContent.setGroup("直出原片"); ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(face.getScenicId()); - if (!Boolean.TRUE.equals(scenicConfig.getBoolean("disable_source_image"))) { - IsBuyRespVO isBuyRespVO = orderBiz.isBuy(userId, face.getScenicId(), 2, faceId); + if (!scenicConfigFacade.isDisableSourceImage(face.getScenicId())) { + IsBuyRespVO isBuyRespVO = orderBiz.isBuy(userId, face.getScenicId(), SourceType.IMAGE.getCode(), faceId); sourceImageContent.setSourceType(isBuyRespVO.getGoodsType()); sourceImageContent.setContentId(isBuyRespVO.getGoodsId()); if (isBuyRespVO.isBuy()) { @@ -592,8 +579,8 @@ public class FaceServiceImpl implements FaceService { sourceImageContent.setFreeCount((int) freeCount); contentList.add(sourceImageContent); } - if (!Boolean.TRUE.equals(scenicConfig.getBoolean("disable_source_video"))) { - IsBuyRespVO isBuyRespVO = orderBiz.isBuy(userId, face.getScenicId(), 1, faceId); + if (!scenicConfigFacade.isDisableSourceVideo(face.getScenicId())) { + IsBuyRespVO isBuyRespVO = orderBiz.isBuy(userId, face.getScenicId(), SourceType.VIDEO.getCode(), faceId); sourceVideoContent.setSourceType(isBuyRespVO.getGoodsType()); sourceVideoContent.setContentId(isBuyRespVO.getGoodsId()); if (isBuyRespVO.isBuy()) { @@ -764,15 +751,15 @@ public class FaceServiceImpl implements FaceService { long customMatchCount = metricsRecorder.getCustomMatchCount(faceId); boolean hasLowThreshold = metricsRecorder.hasLowThreshold(faceId); - Integer faceSelectMaxCount = scenicConfig.getInteger("face_select_max_count"); + Integer faceSelectMaxCount = scenicConfigFacade.getFaceSelectMaxCount(face.getScenicId()); if (faceSelectMaxCount != null && faceSelectMaxCount > 0 && customMatchCount > faceSelectMaxCount) { log.debug("自定义人脸匹配次数超过限制:faceId={}, customMatchCount={}, limit={}", faceId, customMatchCount, faceSelectMaxCount); return false; } - Integer maxTourTime = scenicConfig.getInteger("tour_time"); - Integer minTourTime = scenicConfig.getInteger("tour_min_time"); + Integer maxTourTime = scenicConfigFacade.getTourTime(face.getScenicId()); + Integer minTourTime = scenicConfigFacade.getTourMinTime(face.getScenicId()); boolean tourMatch = false; if (maxTourTime != null && minTourTime != null) { if ((new Date().getTime()) - face.getCreateAt().getTime() < maxTourTime * 60 * 1000 @@ -811,7 +798,7 @@ public class FaceServiceImpl implements FaceService { } // 使用策略模式替换switch语句 - Integer mode = scenicConfig.getInteger("re_match_mode", 0); + Integer mode = scenicConfigFacade.getRematchMode(face.getScenicId()); RematchContext context = RematchContext.builder() .recognitionCount(recognitionCount) .hasLowThreshold(hasLowThreshold) @@ -839,7 +826,7 @@ public class FaceServiceImpl implements FaceService { if (scenicConfig == null) { return List.of(); } - Float lowThreshold = scenicConfig.getFloat("face_score_low_threshold", 30.0F); + Float lowThreshold = scenicConfigFacade.getFaceScoreLowThreshold(face.getScenicId()); List resultItems = JacksonUtil.fromJsonToList(matchResult, SearchFaceResultItem.class); if (resultItems == null || resultItems.isEmpty()) { return List.of(); @@ -893,7 +880,7 @@ public class FaceServiceImpl implements FaceService { } // 获取face_select_post_mode配置,默认为0(并集) - Integer faceSelectPostMode = scenicConfig != null ? scenicConfig.getInteger("face_select_post_mode", 0) : 0; + Integer faceSelectPostMode = scenicConfigFacade.getFaceSelectPostMode(face.getScenicId()); log.debug("face_select_post_mode配置值: {}", faceSelectPostMode); SearchFaceRespVo mergedResult; @@ -958,11 +945,11 @@ public class FaceServiceImpl implements FaceService { List memberSourceEntityList = sourceRelationProcessor.processMemberSources(sampleListIds, face); if (!memberSourceEntityList.isEmpty()) { - List freeSourceIds = sourceRelationProcessor.processFreeSourceLogic(memberSourceEntityList, scenicConfig, false); + List freeSourceIds = sourceRelationProcessor.processFreeSourceLogic(memberSourceEntityList, face.getScenicId(), false); buyStatusProcessor.processBuyStatus(memberSourceEntityList, freeSourceIds, face.getMemberId(), face.getScenicId(), faceId); - videoRecreationHandler.handleVideoRecreation(scenicConfig, memberSourceEntityList, faceId, + videoRecreationHandler.handleVideoRecreation(face.getScenicId(), memberSourceEntityList, faceId, face.getMemberId(), sampleListIds, false); List existingFiltered = sourceMapper.filterExistingRelations(memberSourceEntityList); diff --git a/src/main/java/com/ycwl/basic/service/pc/processor/BuyStatusProcessor.java b/src/main/java/com/ycwl/basic/service/pc/processor/BuyStatusProcessor.java index 39394f5d..811c8afb 100644 --- a/src/main/java/com/ycwl/basic/service/pc/processor/BuyStatusProcessor.java +++ b/src/main/java/com/ycwl/basic/service/pc/processor/BuyStatusProcessor.java @@ -1,6 +1,8 @@ package com.ycwl.basic.service.pc.processor; import com.ycwl.basic.biz.OrderBiz; +import com.ycwl.basic.constant.BuyStatus; +import com.ycwl.basic.constant.FreeStatus; import com.ycwl.basic.model.mobile.order.IsBuyRespVO; import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity; import lombok.extern.slf4j.Slf4j; @@ -51,17 +53,17 @@ public class BuyStatusProcessor { // 设置购买状态 if (isBuy.isBuy()) { // 如果用户买过 - memberSourceEntity.setIsBuy(1); + memberSourceEntity.setIsBuy(BuyStatus.BOUGHT.getCode()); } else if (isBuy.isFree()) { // 全免费逻辑 - memberSourceEntity.setIsBuy(1); + memberSourceEntity.setIsBuy(BuyStatus.BOUGHT.getCode()); } else { - memberSourceEntity.setIsBuy(0); + memberSourceEntity.setIsBuy(BuyStatus.NOT_BOUGHT.getCode()); } // 设置免费状态 if (freeSourceIds.contains(memberSourceEntity.getSourceId())) { - memberSourceEntity.setIsFree(1); + memberSourceEntity.setIsFree(FreeStatus.FREE.getCode()); } } diff --git a/src/main/java/com/ycwl/basic/service/pc/processor/FaceRecoveryStrategy.java b/src/main/java/com/ycwl/basic/service/pc/processor/FaceRecoveryStrategy.java index 5a9c610c..e288da0c 100644 --- a/src/main/java/com/ycwl/basic/service/pc/processor/FaceRecoveryStrategy.java +++ b/src/main/java/com/ycwl/basic/service/pc/processor/FaceRecoveryStrategy.java @@ -5,6 +5,7 @@ import com.ycwl.basic.integration.common.manager.ScenicConfigManager; import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; import com.ycwl.basic.model.task.resp.SearchFaceRespVo; import com.ycwl.basic.repository.FaceRepository; +import com.ycwl.basic.service.pc.helper.ScenicConfigFacade; import com.ycwl.basic.service.task.TaskFaceService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -27,6 +28,9 @@ public class FaceRecoveryStrategy { @Autowired private TaskFaceService faceService; + @Autowired + private ScenicConfigFacade scenicConfigFacade; + /** * 执行人脸识别补救逻辑 * 当匹配结果数量少于阈值时,使用第一个匹配结果重新进行人脸搜索 @@ -51,7 +55,7 @@ public class FaceRecoveryStrategy { } // 检查是否需要执行补救逻辑 - Integer helperThreshold = scenicConfig.getInteger("face_detect_helper_threshold", 0); + Integer helperThreshold = scenicConfigFacade.getFaceDetectHelperThreshold(scenicId); if (helperThreshold == null || helperThreshold <= 0) { return originalResult; } diff --git a/src/main/java/com/ycwl/basic/service/pc/processor/SourceRelationProcessor.java b/src/main/java/com/ycwl/basic/service/pc/processor/SourceRelationProcessor.java index e33c6f08..bb02fa08 100644 --- a/src/main/java/com/ycwl/basic/service/pc/processor/SourceRelationProcessor.java +++ b/src/main/java/com/ycwl/basic/service/pc/processor/SourceRelationProcessor.java @@ -1,5 +1,7 @@ package com.ycwl.basic.service.pc.processor; +import com.ycwl.basic.constant.FreeStatus; +import com.ycwl.basic.constant.SourceType; import com.ycwl.basic.integration.common.manager.DeviceConfigManager; import com.ycwl.basic.integration.common.manager.ScenicConfigManager; import com.ycwl.basic.mapper.SourceMapper; @@ -7,6 +9,7 @@ import com.ycwl.basic.model.pc.face.entity.FaceEntity; import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity; import com.ycwl.basic.model.pc.source.entity.SourceEntity; import com.ycwl.basic.repository.DeviceRepository; +import com.ycwl.basic.service.pc.helper.ScenicConfigFacade; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -32,6 +35,9 @@ public class SourceRelationProcessor { @Autowired private DeviceRepository deviceRepository; + @Autowired + private ScenicConfigFacade scenicConfigFacade; + /** * 处理源文件关联逻辑 * 根据匹配的样本ID创建MemberSourceEntity列表 @@ -60,8 +66,8 @@ public class SourceRelationProcessor { if (configManager.getInteger("limit_video", 0) > 0) { // 优先保留所有图片,然后限制视频数量 return Stream.concat( - entry.getValue().stream().filter(item -> item.getType() == 2), - entry.getValue().stream().filter(item -> item.getType() == 1) + entry.getValue().stream().filter(item -> SourceType.isImage(item.getType())), + entry.getValue().stream().filter(item -> SourceType.isVideo(item.getType())) .limit(Math.min(entry.getValue().size(), configManager.getInteger("limit_video", 0))) ); } @@ -79,19 +85,19 @@ public class SourceRelationProcessor { memberSourceEntity.setType(sourceEntity.getType()); // 设置免费状态 - 默认收费 - memberSourceEntity.setIsFree(0); + memberSourceEntity.setIsFree(FreeStatus.PAID.getCode()); if (deviceConfig != null) { // 视频类型检查 - if (sourceEntity.getType() == 1) { + if (SourceType.isVideo(sourceEntity.getType())) { if (Integer.valueOf(1).equals(deviceConfig.getInteger("video_free"))) { - memberSourceEntity.setIsFree(1); + memberSourceEntity.setIsFree(FreeStatus.FREE.getCode()); } } // 图片类型检查 - else if (sourceEntity.getType() == 2) { + else if (SourceType.isImage(sourceEntity.getType())) { if (Integer.valueOf(1).equals(deviceConfig.getInteger("image_free"))) { - memberSourceEntity.setIsFree(1); + memberSourceEntity.setIsFree(FreeStatus.FREE.getCode()); } } } @@ -105,12 +111,12 @@ public class SourceRelationProcessor { * 根据景区配置和是否新用户决定哪些照片可以免费 * * @param memberSourceEntityList 源文件关联列表 - * @param scenicConfig 景区配置 + * @param scenicId 景区ID * @param isNew 是否新用户 * @return 免费的源文件ID列表 */ public List processFreeSourceLogic(List memberSourceEntityList, - ScenicConfigManager scenicConfig, + Long scenicId, boolean isNew) { List freeSourceIds = new ArrayList<>(); @@ -121,12 +127,12 @@ public class SourceRelationProcessor { if (isNew) { // 新用户送照片逻辑 List photoSource = memberSourceEntityList.stream() - .filter(item -> item.getIsFree() == 0) // 只考虑收费的 - .filter(item -> Integer.valueOf(2).equals(item.getType())) // 只考虑照片类型 + .filter(item -> FreeStatus.isPaid(item.getIsFree())) // 只考虑收费的 + .filter(item -> SourceType.isImage(item.getType())) // 只考虑照片类型 .toList(); - Integer photoFreeNum = scenicConfig != null ? scenicConfig.getInteger("photo_free_num") : null; - if (scenicConfig != null && photoFreeNum != null && photoFreeNum > 0) { + Integer photoFreeNum = scenicConfigFacade.getPhotoFreeNum(scenicId); + if (photoFreeNum != null && photoFreeNum > 0) { int freePhotoCount = Math.min(photoFreeNum, photoSource.size()); freeSourceIds.addAll(photoSource.stream() diff --git a/src/main/java/com/ycwl/basic/service/pc/processor/VideoRecreationHandler.java b/src/main/java/com/ycwl/basic/service/pc/processor/VideoRecreationHandler.java index 2787370a..c34593ed 100644 --- a/src/main/java/com/ycwl/basic/service/pc/processor/VideoRecreationHandler.java +++ b/src/main/java/com/ycwl/basic/service/pc/processor/VideoRecreationHandler.java @@ -1,11 +1,13 @@ package com.ycwl.basic.service.pc.processor; +import com.ycwl.basic.constant.SourceType; import com.ycwl.basic.integration.common.manager.DeviceConfigManager; import com.ycwl.basic.integration.common.manager.ScenicConfigManager; import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity; import com.ycwl.basic.model.pc.source.entity.MemberSourceEntity; import com.ycwl.basic.repository.DeviceRepository; import com.ycwl.basic.repository.FaceRepository; +import com.ycwl.basic.service.pc.helper.ScenicConfigFacade; import com.ycwl.basic.task.VideoPieceGetter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -32,18 +34,21 @@ public class VideoRecreationHandler { @Autowired private DeviceRepository deviceRepository; + @Autowired + private ScenicConfigFacade scenicConfigFacade; + /** * 处理视频重切逻辑 * 当非新用户且照片数量大于视频数量时,创建视频重切任务 * - * @param scenicConfig 景区配置 + * @param scenicId 景区ID * @param memberSourceEntityList 源文件关联列表 * @param faceId 人脸ID * @param memberId 会员ID * @param sampleListIds 样本ID列表(用于日志) * @param isNew 是否新用户 */ - public void handleVideoRecreation(ScenicConfigManager scenicConfig, + public void handleVideoRecreation(Long scenicId, List memberSourceEntityList, Long faceId, Long memberId, @@ -55,18 +60,17 @@ public class VideoRecreationHandler { } // 检查景区是否禁用源视频功能 - Boolean disableSourceVideo = scenicConfig != null ? scenicConfig.getBoolean("disable_source_video") : null; - if (scenicConfig == null || Boolean.TRUE.equals(disableSourceVideo)) { + if (scenicConfigFacade.isDisableSourceVideo(scenicId)) { log.debug("视频重切逻辑跳过:景区禁用了源视频功能"); return; } // 统计视频和照片数量 long videoCount = memberSourceEntityList.stream() - .filter(item -> Integer.valueOf(1).equals(item.getType())) + .filter(item -> SourceType.isVideo(item.getType())) .count(); long photoCount = memberSourceEntityList.stream() - .filter(item -> Integer.valueOf(2).equals(item.getType())) + .filter(item -> SourceType.isImage(item.getType())) .count(); List faceSampleList = faceRepository.getFaceSampleList(faceId);