package com.rongyichuang.judge.service; import com.rongyichuang.judge.dto.request.JudgeInput; import com.rongyichuang.judge.dto.response.JudgeResponse; import com.rongyichuang.judge.entity.Judge; import com.rongyichuang.tag.entity.Tag; import com.rongyichuang.judge.repository.JudgeRepository; import com.rongyichuang.common.entity.Media; import com.rongyichuang.common.repository.MediaRepository; import com.rongyichuang.common.dto.request.MediaInput; import com.rongyichuang.common.dto.response.MediaResponse; import com.rongyichuang.common.service.MediaService; import com.rongyichuang.common.exception.BusinessException; import com.rongyichuang.common.enums.MediaTargetType; import com.rongyichuang.tag.repository.TagRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; @Service public class JudgeService { private static final Logger log = LoggerFactory.getLogger(JudgeService.class); private final JudgeRepository judgeRepository; private final TagRepository tagRepository; private final MediaRepository mediaRepository; private final MediaService mediaService; @Value("${app.media-url:${app.media.url:}}") private String mediaBaseUrl; public JudgeService(JudgeRepository judgeRepository, TagRepository tagRepository, MediaRepository mediaRepository, MediaService mediaService) { this.judgeRepository = judgeRepository; this.tagRepository = tagRepository; this.mediaRepository = mediaRepository; this.mediaService = mediaService; } public List findAll() { return judgeRepository.findAll(Sort.by(Sort.Direction.DESC, "updateTime")).stream() .map(this::convertToResponse) .collect(Collectors.toList()); } public List findByName(String name) { return judgeRepository.findByNameContaining(name).stream() .map(this::convertToResponse) .collect(Collectors.toList()); } public JudgeResponse findById(Long id) { return judgeRepository.findById(id) .map(this::convertToResponse) .orElse(null); } @Transactional public JudgeResponse save(JudgeInput input) { Judge judge; if (input.getId() != null) { judge = judgeRepository.findById(input.getId()) .orElseThrow(() -> new BusinessException("评委不存在")); } else { judge = new Judge(); // 新增评委时检查手机号是否已存在 if (judgeRepository.existsByPhone(input.getPhone())) { throw new BusinessException("PHONE_EXISTS", "手机号码已存在,请使用其他手机号码"); } } judge.setName(input.getName()); judge.setPhone(input.getPhone()); judge.setGender(input.getGender()); judge.setDescription(input.getDescription()); judge.setTitle(input.getTitle()); judge.setCompany(input.getCompany()); judge.setIntroduction(input.getIntroduction()); // 头像信息通过t_media表的target_type和target_id关联 // 设置专业标签 if (input.getMajorIds() != null && !input.getMajorIds().isEmpty()) { List specialtiesList = tagRepository.findAllById(input.getMajorIds()); judge.setSpecialties(new HashSet<>(specialtiesList)); } else { judge.setSpecialties(Collections.emptySet()); } Judge savedJudge = judgeRepository.save(judge); return convertToResponse(savedJudge); } @Transactional public void delete(Long id) { Judge judge = judgeRepository.findById(id) .orElseThrow(() -> new BusinessException("评委不存在")); judgeRepository.delete(judge); } private JudgeResponse convertToResponse(Judge judge) { log.info("=== convertToResponse called for judge: {} (ID: {})", judge.getName(), judge.getId()); JudgeResponse response = new JudgeResponse(); response.setId(judge.getId()); response.setName(judge.getName()); response.setPhone(judge.getPhone()); response.setGender(judge.getGender()); response.setDescription(judge.getDescription()); response.setTitle(judge.getTitle()); response.setCompany(judge.getCompany()); response.setIntroduction(judge.getIntroduction()); // 查询头像信息:使用枚举常量表示评委头像类型 log.info("=== Querying media for judge ID: {}", judge.getId()); List avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState( MediaTargetType.JUDGE_AVATAR.getValue(), judge.getId(), 1); log.info("=== Found {} media records", avatarMedias.size()); if (!avatarMedias.isEmpty()) { // 取第一个媒体作为头像 Media avatarMedia = avatarMedias.get(0); String avatarPath = avatarMedia.getPath(); String avatarUrl = buildFullMediaUrl(avatarPath); log.info("=== Setting avatarUrl: {}", avatarUrl); response.setAvatarUrl(avatarUrl); } else { log.info("=== No media found, avatarUrl will be null"); } if (judge.getSpecialties() != null) { response.setSpecialties(judge.getSpecialties().stream() .map(tag -> { JudgeResponse.TagResponse tagResponse = new JudgeResponse.TagResponse(); tagResponse.setId(tag.getId()); tagResponse.setName(tag.getName()); tagResponse.setCode(tag.getCode()); return tagResponse; }) .collect(Collectors.toList())); } return response; } /** * 构建完整的媒体URL * @param path 媒体路径 * @return 完整的URL */ private String buildFullMediaUrl(String path) { if (!StringUtils.hasText(path)) { return null; } // 如果路径已经是完整URL,直接返回 if (path.startsWith("http://") || path.startsWith("https://")) { return path; } // 构建完整URL if (StringUtils.hasText(mediaBaseUrl)) { // 确保baseUrl以/结尾,path不以/开头 String baseUrl = mediaBaseUrl.endsWith("/") ? mediaBaseUrl : mediaBaseUrl + "/"; String relativePath = path.startsWith("/") ? path.substring(1) : path; return baseUrl + relativePath; } // 如果没有配置baseUrl,返回原路径 return path; } /** * 保存媒体信息 */ public MediaResponse saveMediaInfo(MediaInput input) { Media media = mediaService.saveMedia( input.getName(), input.getPath(), input.getFileSize(), input.getFileExt(), input.getMediaType(), input.getTargetType(), input.getTargetId() ); MediaResponse response = new MediaResponse(); response.setId(media.getId()); response.setName(media.getName()); response.setPath(media.getPath()); response.setFileSize(media.getFileSize()); response.setFileExt(media.getFileExt()); response.setMediaType(media.getMediaType()); response.setTargetType(media.getTargetType()); response.setTargetId(media.getTargetId()); return response; } }