Files
FrameTour-BE/src/main/java/com/ycwl/basic/biz/TemplateBiz.java
Jerry Yan e805fdac9a feat(template): 添加人脸样本和视频源为空时的日志提示
- 在视频源查询为空时添加日志记录- 在人脸样本查询为空时添加日志记录
- 提高代码调试和问题排查的便利性
2025-10-27 13:58:32 +08:00

220 lines
9.4 KiB
Java

package com.ycwl.basic.biz;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.pc.template.entity.TemplateConfigEntity;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.SourceRepository;
import com.ycwl.basic.repository.TemplateRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@Slf4j
@Component
public class TemplateBiz {
@Autowired
private TemplateRepository templateRepository;
@Autowired
private FaceRepository faceRepository;
@Autowired
private SourceMapper sourceMapper;
public boolean determineTemplateCanGenerate(Long templateId, Long faceId) {
return determineTemplateCanGenerate(templateId, faceId, true);
}
public boolean determineTemplateCanGenerate(Long templateId, Long faceId, boolean scanSource) {
List<String> placeholderList = templateRepository.getTemplatePlaceholder(templateId);
TemplateConfigEntity templateConfig = templateRepository.getTemplateConfig(templateId);
int minimalPlaceholderFill = 1;
if (null != templateConfig) {
if (null != templateConfig.getMinimalPlaceholderFill()) {
minimalPlaceholderFill = templateConfig.getMinimalPlaceholderFill();
}
}
if (minimalPlaceholderFill <= 0) {
return true;
}
FaceEntity face = faceRepository.getFace(faceId);
long count;
if (scanSource) {
List<SourceEntity> sourceEntities = sourceMapper.listVideoByScenicFaceRelation(face.getScenicId(), faceId);
if (sourceEntities == null || sourceEntities.isEmpty()) {
log.info("faceId:{} has no source", faceId);
return false;
}
count = sourceEntities.stream()
.map(SourceEntity::getDeviceId)
.filter(Objects::nonNull) // 添加对 null 的检查
.distinct()
.filter(deviceId -> placeholderList.contains(deviceId.toString()))
.count();
} else {
List<FaceSampleEntity> faceSampleList = faceRepository.getFaceSampleList(faceId);
if (faceSampleList == null || faceSampleList.isEmpty()) {
log.info("faceId:{} has no faceSample", faceId);
return false;
}
count = faceSampleList.stream()
.map(FaceSampleEntity::getDeviceId)
.filter(Objects::nonNull) // 添加对 null 的检查
.distinct()
.filter(deviceId -> placeholderList.contains(deviceId.toString()))
.count();
}
return count >= minimalPlaceholderFill;
}
public boolean determineTemplateCanAutoGenerate(Long templateId, Long faceId) {
return determineTemplateCanAutoGenerate(templateId, faceId, true);
}
public boolean determineTemplateCanAutoGenerate(Long templateId, Long faceId, boolean scanSource) {
List<String> placeholderList = templateRepository.getTemplatePlaceholder(templateId);
TemplateConfigEntity templateConfig = templateRepository.getTemplateConfig(templateId);
Integer minimalPlaceholderFill = null;
if (null != templateConfig) {
if (null != templateConfig.getAutomaticPlaceholderFill()) {
minimalPlaceholderFill = templateConfig.getAutomaticPlaceholderFill();
}
}
if (minimalPlaceholderFill == null) {
// 未开启
log.info("模板:{},未配置最小自动生成功能,默认生成!", templateId);
minimalPlaceholderFill = 1;
}
if (minimalPlaceholderFill <= 0) {
return true;
}
FaceEntity face = faceRepository.getFace(faceId);
List<FaceSampleEntity> faceSampleList = faceRepository.getFaceSampleList(faceId);
if (faceSampleList.isEmpty()) {
return false;
}
long count;
if (scanSource) {
List<SourceEntity> sourceEntities = sourceMapper.listVideoByScenicFaceRelation(face.getScenicId(), faceId);
count = sourceEntities.stream()
.map(SourceEntity::getDeviceId)
.filter(Objects::nonNull) // 添加对 null 的检查
.distinct()
.filter(deviceId -> placeholderList.contains(deviceId.toString()))
.count();
} else {
count = faceSampleList.stream()
.map(FaceSampleEntity::getDeviceId)
.distinct()
.filter(deviceId -> placeholderList.contains(deviceId.toString()))
.count();
}
return count >= minimalPlaceholderFill;
}
public Map<String, List<SourceEntity>> filterTaskParams(Long templateId, Map<String, List<SourceEntity>> allTaskParams) {
if (allTaskParams == null || allTaskParams.isEmpty()) {
return Map.of();
}
List<String> templatePlaceholders = templateRepository.getTemplatePlaceholder(templateId);
if (templatePlaceholders == null || templatePlaceholders.isEmpty()) {
log.info("filterTaskParams: templateId:{} has no placeholders", templateId);
return Map.of();
}
TemplateConfigEntity templateConfig = templateRepository.getTemplateConfig(templateId);
// 统计每个 placeholder 在模板中出现的次数
Map<String, Long> placeholderCounts = templatePlaceholders.stream()
.collect(Collectors.groupingBy(
placeholder -> placeholder,
Collectors.counting()
));
Map<String, List<SourceEntity>> filteredParams = new HashMap<>();
// 判断是否允许片段重复
boolean allowDuplicate = templateConfig != null && Integer.valueOf(1).equals(templateConfig.getDuplicateEnable());
for (Map.Entry<String, Long> entry : placeholderCounts.entrySet()) {
String placeholder = entry.getKey();
Long requiredCount = entry.getValue();
if (placeholder.startsWith("P")) {
// 图片源:占位符格式为 "P{deviceId}"
String imageKey = placeholder;
if (allTaskParams.containsKey(imageKey)) {
List<SourceEntity> allSources = allTaskParams.get(imageKey);
List<SourceEntity> selectedSources = selectSources(allSources, requiredCount.intValue(), allowDuplicate);
if (!selectedSources.isEmpty()) {
filteredParams.put(imageKey, selectedSources);
}
}
} else {
// 视频源:占位符直接对应设备ID
String videoKey = placeholder;
if (allTaskParams.containsKey(videoKey)) {
List<SourceEntity> allSources = allTaskParams.get(videoKey);
List<SourceEntity> selectedSources = selectSources(allSources, requiredCount.intValue(), allowDuplicate);
if (!selectedSources.isEmpty()) {
filteredParams.put(videoKey, selectedSources);
}
}
}
}
log.debug("filterTaskParams: templateId:{}, original keys:{}, filtered keys:{}, placeholder counts:{}, allowDuplicate:{}",
templateId, allTaskParams.keySet().size(), filteredParams.keySet().size(), placeholderCounts, allowDuplicate);
return filteredParams;
}
private List<SourceEntity> selectSources(List<SourceEntity> allSources, int requiredCount, boolean allowDuplicate) {
if (allSources == null || allSources.isEmpty()) {
return new ArrayList<>();
}
if (!allowDuplicate) {
// 不允许重复,使用原有逻辑
int actualCount = Math.min(requiredCount, allSources.size());
return new ArrayList<>(allSources.subList(0, actualCount));
}
// 允许重复,循环填充到所需数量
List<SourceEntity> selectedSources = new ArrayList<>();
int sourceIndex = 0;
for (int i = 0; i < requiredCount; i++) {
selectedSources.add(allSources.get(sourceIndex));
sourceIndex = (sourceIndex + 1) % allSources.size();
}
return selectedSources;
}
public Long findFirstAvailableTemplate(List<Long> templateIds, Long faceId, boolean scanSource) {
if (templateIds == null || templateIds.isEmpty() || faceId == null) {
return null;
}
for (Long templateId : templateIds) {
if (determineTemplateCanGenerate(templateId, faceId, scanSource)) {
return templateId;
}
}
return null;
}
}