| | |
| | | import com.rongyichuang.judge.dto.request.JudgeInput; |
| | | import com.rongyichuang.judge.dto.response.JudgeResponse; |
| | | import com.rongyichuang.judge.entity.Judge; |
| | | import com.rongyichuang.judge.entity.Tag; |
| | | 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.judge.repository.TagRepository; |
| | | import com.rongyichuang.common.exception.BusinessException; |
| | | import com.rongyichuang.common.enums.MediaTargetType; |
| | | import com.rongyichuang.tag.repository.TagRepository; |
| | | import com.rongyichuang.user.service.UserService; |
| | | import com.rongyichuang.user.entity.User; |
| | | 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; |
| | | |
| | |
| | | private final TagRepository tagRepository; |
| | | private final MediaRepository mediaRepository; |
| | | private final MediaService mediaService; |
| | | private final UserService userService; |
| | | |
| | | @Value("${app.media-url}") |
| | | private String mediaBaseUrl; |
| | | |
| | | public JudgeService(JudgeRepository judgeRepository, TagRepository tagRepository, |
| | | MediaRepository mediaRepository, MediaService mediaService) { |
| | | MediaRepository mediaRepository, MediaService mediaService, |
| | | UserService userService) { |
| | | this.judgeRepository = judgeRepository; |
| | | this.tagRepository = tagRepository; |
| | | this.mediaRepository = mediaRepository; |
| | | this.mediaService = mediaService; |
| | | this.userService = userService; |
| | | } |
| | | |
| | | public List<JudgeResponse> findAll() { |
| | |
| | | @Transactional |
| | | public JudgeResponse save(JudgeInput input) { |
| | | Judge judge; |
| | | User user; |
| | | |
| | | // 处理User表逻辑 |
| | | if (input.getPassword() != null && !input.getPassword().trim().isEmpty() && !"••••••••".equals(input.getPassword())) { |
| | | // 有密码且不是占位符时,创建或更新用户(包含密码) |
| | | user = userService.findOrCreateUserByPhone(input.getPhone(), input.getName(), input.getPassword()); |
| | | } else { |
| | | // 无密码或是占位符时,只更新用户基本信息(不更新密码) |
| | | user = userService.findOrCreateUserByPhone(input.getPhone(), input.getName(), null); |
| | | } |
| | | |
| | | if (input.getId() != null) { |
| | | judge = judgeRepository.findById(input.getId()) |
| | | .orElseThrow(() -> new RuntimeException("评委不存在")); |
| | | .orElseThrow(() -> new BusinessException("评委不存在")); |
| | | } else { |
| | | judge = new Judge(); |
| | | // 新增评委时检查手机号是否已存在 |
| | | if (judgeRepository.existsByPhone(input.getPhone())) { |
| | | throw new RuntimeException("手机号码已存在,请使用其他手机号码"); |
| | | throw new BusinessException("PHONE_EXISTS", "手机号码已存在,请使用其他手机号码"); |
| | | } |
| | | } |
| | | |
| | |
| | | judge.setPhone(input.getPhone()); |
| | | judge.setGender(input.getGender()); |
| | | judge.setDescription(input.getDescription()); |
| | | |
| | | // 头像处理已移除,因为数据库表结构中没有avatar_media_id字段 |
| | | judge.setTitle(input.getTitle()); |
| | | judge.setCompany(input.getCompany()); |
| | | judge.setIntroduction(input.getIntroduction()); |
| | | judge.setUserId(user.getId()); // 设置关联的用户ID |
| | | // 头像信息通过t_media表的target_type和target_id关联 |
| | | |
| | | // 设置专业标签 |
| | | if (input.getMajorIds() != null && !input.getMajorIds().isEmpty()) { |
| | | List<Tag> specialties = tagRepository.findAllById(input.getMajorIds()); |
| | | judge.setSpecialties(specialties); |
| | | List<Tag> specialtiesList = tagRepository.findAllById(input.getMajorIds()); |
| | | judge.setSpecialties(new HashSet<>(specialtiesList)); |
| | | } else { |
| | | judge.setSpecialties(Collections.emptyList()); |
| | | judge.setSpecialties(Collections.emptySet()); |
| | | } |
| | | |
| | | Judge savedJudge = judgeRepository.save(judge); |
| | |
| | | @Transactional |
| | | public void delete(Long id) { |
| | | Judge judge = judgeRepository.findById(id) |
| | | .orElseThrow(() -> new RuntimeException("评委不存在")); |
| | | .orElseThrow(() -> new BusinessException("评委不存在")); |
| | | judgeRepository.delete(judge); |
| | | } |
| | | |
| | |
| | | response.setPhone(judge.getPhone()); |
| | | response.setGender(judge.getGender()); |
| | | response.setDescription(judge.getDescription()); |
| | | response.setTitle(judge.getTitle()); |
| | | response.setCompany(judge.getCompany()); |
| | | response.setIntroduction(judge.getIntroduction()); |
| | | |
| | | // 查询头像信息:target_type=1表示评委,target_id为评委ID |
| | | // 查询头像信息:使用枚举常量表示评委头像类型 |
| | | log.info("=== Querying media for judge ID: {}", judge.getId()); |
| | | List<Media> avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(1, judge.getId(), 1); |
| | | List<Media> 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 avatarUrl = avatarMedia.getPath(); |
| | | String avatarPath = avatarMedia.getPath(); |
| | | String avatarUrl = buildFullMediaUrl(avatarPath); |
| | | log.info("=== Setting avatarUrl: {}", avatarUrl); |
| | | response.setAvatarUrl(avatarUrl); |
| | | } else { |
| | |
| | | |
| | | 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; |
| | | } |
| | | |
| | | /** |
| | | * 保存媒体信息 |