lrj
2 天以前 93eb6b470773bc49ea6e1a9d4cbd914eb95d525b
backend/src/main/java/com/rongyichuang/player/service/ActivityPlayerDetailService.java
@@ -1,19 +1,27 @@
package com.rongyichuang.player.service;
import com.rongyichuang.player.dto.response.*;
import com.rongyichuang.player.dto.response.RegionInfoResponse;
import com.rongyichuang.rating.dto.response.RatingItemResponse;
import com.rongyichuang.rating.entity.RatingScheme;
import com.rongyichuang.rating.repository.RatingSchemeRepository;
import com.rongyichuang.common.entity.Media;
import com.rongyichuang.common.enums.MediaTargetType;
import com.rongyichuang.common.repository.MediaRepository;
import com.rongyichuang.common.dto.response.MediaResponse;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;
/**
@@ -29,6 +37,9 @@
    private final MediaRepository mediaRepository;
    private final RatingSchemeRepository ratingSchemeRepository;
    @Value("${app.media-url}")
    private String mediaBaseUrl;
    public ActivityPlayerDetailService(MediaRepository mediaRepository, 
                                     RatingSchemeRepository ratingSchemeRepository) {
@@ -44,54 +55,149 @@
    public ActivityPlayerDetailResponse getDetailForRating(Long activityPlayerId) {
        log.info("获取报名详情用于评分,activityPlayerId: {}", activityPlayerId);
        // 查询基本信息
        // 查询基本信息,包含区域信息
        String sql = """
            SELECT ap.id, ap.description, ap.activity_id,
            SELECT ap.id as ap_id, ap.description as ap_description, ap.activity_id, ap.region_id,
                   ap.project_name, ap.feedback, ap.state as ap_state,
                   p.id as player_id, p.name as player_name, p.phone, p.description as player_desc,
                   a.name as activity_name, a.rating_scheme_id
            FROM t_avtivity_player ap
                   p.gender, u.birthday, p.education, p.introduction, u.id as user_id,
                   a.name as activity_name, a.rating_scheme_id,
                   r.id as region_id, r.name as region_name, r.full_path as region_path
            FROM t_activity_player ap
            JOIN t_player p ON p.id = ap.player_id
            JOIN t_user u ON u.id = p.user_id
            JOIN t_activity a ON a.id = ap.activity_id
            LEFT JOIN t_region r ON r.id = ap.region_id
            WHERE ap.id = ?
            """;
        @SuppressWarnings("unchecked")
        List<Object[]> results = em.createNativeQuery(sql)
                .setParameter(1, activityPlayerId)
                .getResultList();
        Query query = em.createNativeQuery(sql);
        query.setParameter(1, activityPlayerId);
        // 使用 Tuple 来获取命名字段
        query.unwrap(org.hibernate.query.NativeQuery.class).setTupleTransformer(
            (tuple, aliases) -> {
                Map<String, Object> result = new HashMap<>();
                for (int i = 0; i < aliases.length; i++) {
                    result.put(aliases[i], tuple[i]);
                }
                return result;
            }
        );
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> results = query.getResultList();
        if (results.isEmpty()) {
            log.warn("未找到报名记录,activityPlayerId: {}", activityPlayerId);
            return null;
        }
        Object[] row = results.get(0);
        Map<String, Object> row = results.get(0);
        ActivityPlayerDetailResponse response = new ActivityPlayerDetailResponse();
        response.setId(activityPlayerId);
        response.setDescription(row[1] != null ? row[1].toString() : "");
        response.setActivityName(row[7] != null ? row[7].toString() : "");
        response.setDescription(row.get("ap_description") != null ? row.get("ap_description").toString() : "");
        response.setProjectName(row.get("project_name") != null ? row.get("project_name").toString() : "");
        response.setFeedback(row.get("feedback") != null ? row.get("feedback").toString() : "");
        Object stateObj = row.get("ap_state");
        if (stateObj != null) {
            if (stateObj instanceof Number) {
                response.setState(((Number) stateObj).intValue());
            } else {
                log.warn("状态类型不匹配: {}, 类型: {}", stateObj, stateObj.getClass().getName());
                response.setState(Integer.valueOf(stateObj.toString()));
            }
        } else {
            response.setState(0);
        }
        response.setActivityName(row.get("activity_name") != null ? row.get("activity_name").toString() : "");
        // 构建学员信息
        PlayerInfoResponse playerInfo = new PlayerInfoResponse();
        playerInfo.setId(row[3] != null ? Long.valueOf(row[3].toString()) : null);
        playerInfo.setName(row[4] != null ? row[4].toString() : "");
        playerInfo.setPhone(row[5] != null ? row[5].toString() : "");
        playerInfo.setDescription(row[6] != null ? row[6].toString() : "");
        Object playerIdObj = row.get("player_id");
        if (playerIdObj != null) {
            if (playerIdObj instanceof Number) {
                playerInfo.setId(((Number) playerIdObj).longValue());
            } else {
                log.warn("学员ID类型不匹配: {}, 类型: {}", playerIdObj, playerIdObj.getClass().getName());
                playerInfo.setId(Long.valueOf(playerIdObj.toString()));
            }
        } else {
            playerInfo.setId(null);
        }
        playerInfo.setName(row.get("player_name") != null ? row.get("player_name").toString() : "");
        playerInfo.setPhone(row.get("phone") != null ? row.get("phone").toString() : "");
        playerInfo.setDescription(row.get("player_desc") != null ? row.get("player_desc").toString() : "");
        Object genderObj = row.get("gender");
        if (genderObj != null) {
            if (genderObj instanceof Number) {
                playerInfo.setGender(((Number) genderObj).intValue());
            } else {
                log.warn("性别类型不匹配: {}, 类型: {}", genderObj, genderObj.getClass().getName());
                playerInfo.setGender(Integer.valueOf(genderObj.toString()));
            }
        } else {
            playerInfo.setGender(null);
        }
        Object birthdayObj = row.get("birthday");
        playerInfo.setBirthday(birthdayObj != null ?
            (birthdayObj instanceof java.sql.Date ? ((java.sql.Date) birthdayObj).toString() : birthdayObj.toString()) : null);
        playerInfo.setEducation(row.get("education") != null ? row.get("education").toString() : "");
        playerInfo.setIntroduction(row.get("introduction") != null ? row.get("introduction").toString() : "");
        // 查询学员头像(target_type=5)
        if (playerInfo.getId() != null) {
            List<Media> avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(5, playerInfo.getId(), 1);
        // 构建区域信息
        Object regionIdObj = row.get("region_id");
        if (regionIdObj != null) {
            RegionInfoResponse regionInfo = new RegionInfoResponse();
            if (regionIdObj instanceof Number) {
                regionInfo.setId(((Number) regionIdObj).longValue());
            } else {
                log.warn("区域ID类型不匹配: {}, 类型: {}", regionIdObj, regionIdObj.getClass().getName());
                regionInfo.setId(Long.valueOf(regionIdObj.toString()));
            }
            regionInfo.setName(row.get("region_name") != null ? row.get("region_name").toString() : "");
            regionInfo.setFullPath(row.get("region_path") != null ? row.get("region_path").toString() : "");
            response.setRegionInfo(regionInfo);
            log.info("找到区域信息: {}", regionInfo.getName());
        }
        // 查询用户头像(使用USER_AVATAR关联到用户)
        Object userIdObj = row.get("user_id");
        log.info("调试:从查询结果中获取的user_id: {}", userIdObj);
        if (userIdObj != null) {
            Long userId;
            if (userIdObj instanceof Number) {
                userId = ((Number) userIdObj).longValue();
            } else {
                userId = Long.valueOf(userIdObj.toString());
            }
            log.info("调试:解析后的userId: {}", userId);
            List<Media> avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(
                MediaTargetType.USER_AVATAR.getValue(), userId, 1);
            log.info("调试:查询到的头像媒体数量: {}", avatarMedias.size());
            if (!avatarMedias.isEmpty()) {
                Media avatar = avatarMedias.get(0);
                String avatarUrl = avatar.getPath();
                String avatarUrl = buildFullMediaUrl(avatar.getPath());
                playerInfo.setAvatarUrl(avatarUrl);
                log.info("找到学员头像: {}", avatarUrl);
                // 设置avatar对象
                playerInfo.setAvatar(convertToMediaResponse(avatar));
                log.info("找到用户头像: {}", avatarUrl);
            } else {
                log.info("调试:未找到用户头像,userId: {}, targetType: {}", userId, MediaTargetType.USER_AVATAR.getValue());
            }
        } else {
            log.warn("调试:user_id为null");
        }
        response.setPlayerInfo(playerInfo);
        // 查询提交的资料(target_type=4)
        List<Media> submissionMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(4, activityPlayerId, 1);
        // 查询提交的资料(使用枚举常量表示参赛报名资料类型)
        List<Media> submissionMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(
            MediaTargetType.ACTIVITY_PLAYER_SUBMISSION.getValue(), activityPlayerId, 1);
        List<SubmissionMediaResponse> submissionFiles = submissionMedias.stream()
                .map(this::convertToSubmissionMedia)
                .collect(Collectors.toList());
@@ -99,7 +205,8 @@
        log.info("找到提交资料 {} 个", submissionFiles.size());
        // 查询评分模板
        Long ratingSchemeId = row[8] != null ? Long.valueOf(row[8].toString()) : null;
        Object ratingSchemeIdObj = row.get("rating_scheme_id");
        Long ratingSchemeId = ratingSchemeIdObj != null ? ((Number) ratingSchemeIdObj).longValue() : null;
        if (ratingSchemeId != null) {
            RatingFormResponse ratingForm = buildRatingForm(ratingSchemeId);
            response.setRatingForm(ratingForm);
@@ -115,10 +222,11 @@
        SubmissionMediaResponse response = new SubmissionMediaResponse();
        response.setId(media.getId());
        response.setName(media.getName());
        response.setUrl(media.getPath());
        response.setUrl(buildFullMediaUrl(media.getPath()));
        response.setFileExt(media.getFileExt());
        response.setFileSize(media.getFileSize() != null ? media.getFileSize().longValue() : null);
        response.setMediaType(media.getMediaType());
        response.setThumbUrl(buildFullMediaUrl(media.getThumbPath()));
        return response;
    }
@@ -152,4 +260,49 @@
        return response;
    }
    /**
     * 转换媒体文件为MediaResponse
     */
    private MediaResponse convertToMediaResponse(Media media) {
        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.setThumbPath(media.getThumbPath());
        response.setDuration(media.getDuration());
        response.setDescription(media.getDescription());
        response.setTargetType(media.getTargetType());
        response.setTargetId(media.getTargetId());
        response.setMediaType(media.getMediaType());
        // 设置完整URL
        response.setFullUrl(buildFullMediaUrl(media.getPath()));
        response.setFullThumbUrl(buildFullMediaUrl(media.getThumbPath()));
        return response;
    }
    private String buildFullMediaUrl(String path) {
        if (!StringUtils.hasText(path)) {
            return null;
        }
        // 如果已经是完整URL,直接返回
        if (path.startsWith("http://") || path.startsWith("https://")) {
            return path;
        }
        // 如果没有配置mediaBaseUrl,返回原路径
        if (!StringUtils.hasText(mediaBaseUrl)) {
            return path;
        }
        // 拼接完整URL
        String baseUrl = mediaBaseUrl.endsWith("/") ? mediaBaseUrl : mediaBaseUrl + "/";
        String relativePath = path.startsWith("/") ? path.substring(1) : path;
        return baseUrl + relativePath;
    }
}