package com.rongyichuang.user.resolver;
|
|
import com.rongyichuang.auth.dto.LoginResponse.EmployeeInfo;
|
import com.rongyichuang.auth.dto.LoginResponse.JudgeInfo;
|
import com.rongyichuang.auth.dto.LoginResponse.PlayerInfo;
|
import com.rongyichuang.common.util.UserContextUtil;
|
import com.rongyichuang.employee.entity.Employee;
|
import com.rongyichuang.employee.service.EmployeeService;
|
import com.rongyichuang.judge.entity.Judge;
|
import com.rongyichuang.judge.service.JudgeService;
|
import com.rongyichuang.player.entity.Player;
|
import com.rongyichuang.player.service.PlayerService;
|
import com.rongyichuang.player.repository.ActivityPlayerRepository;
|
import com.rongyichuang.common.repository.MediaRepository;
|
import com.rongyichuang.common.entity.Media;
|
import com.rongyichuang.common.enums.MediaTargetType;
|
import com.rongyichuang.user.dto.response.UserProfile;
|
import com.rongyichuang.user.dto.response.UserStats;
|
import com.rongyichuang.user.dto.response.UserRegistration;
|
import com.rongyichuang.user.dto.response.UserProject;
|
import com.rongyichuang.user.dto.request.UserInput;
|
import com.rongyichuang.user.dto.response.UserProfileInfo;
|
import com.rongyichuang.user.entity.User;
|
import com.rongyichuang.user.repository.UserRepository;
|
import com.rongyichuang.player.dto.response.SubmissionMediaResponse;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.graphql.data.method.annotation.Argument;
|
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
import org.springframework.graphql.data.method.annotation.MutationMapping;
|
import org.springframework.stereotype.Controller;
|
import org.springframework.util.StringUtils;
|
|
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.PersistenceContext;
|
import jakarta.persistence.Query;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Optional;
|
import java.time.LocalDate;
|
import java.time.format.DateTimeFormatter;
|
|
/**
|
* 用户GraphQL解析器
|
*/
|
@Controller
|
public class UserResolver {
|
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(UserResolver.class);
|
|
@Autowired
|
private EmployeeService employeeService;
|
|
@Autowired
|
private JudgeService judgeService;
|
|
@Autowired
|
private PlayerService playerService;
|
|
@Autowired
|
private ActivityPlayerRepository activityPlayerRepository;
|
|
@Autowired
|
private MediaRepository mediaRepository;
|
|
@Autowired
|
private UserRepository userRepository;
|
|
@PersistenceContext
|
private EntityManager entityManager;
|
|
@Autowired
|
private UserContextUtil userContextUtil;
|
|
@Value("${app.media-url}")
|
private String mediaBaseUrl;
|
|
/**
|
* 获取当前用户档案
|
*/
|
@QueryMapping
|
public UserProfile userProfile() {
|
try {
|
Long userId = userContextUtil.getCurrentUserId();
|
logger.debug("进入userProfile,解析到用户ID: {}", userId);
|
if (userId == null) {
|
throw new RuntimeException("用户未登录");
|
}
|
|
UserProfile profile = new UserProfile();
|
profile.setId(userId.toString());
|
|
// 获取用户基本信息
|
Optional<User> userOpt = userRepository.findById(userId);
|
User user = null;
|
if (userOpt.isPresent()) {
|
user = userOpt.get();
|
// 设置性别
|
if (user.getGender() != null) {
|
profile.setGender(user.getGender() == 1 ? "MALE" : "FEMALE");
|
}
|
// 设置生日
|
if (user.getBirthday() != null) {
|
profile.setBirthday(user.getBirthday().toString());
|
}
|
}
|
|
List<String> roles = new ArrayList<>();
|
|
// 检查是否是员工
|
logger.debug("开始查询员工信息,userId={}", userId);
|
Employee employee = employeeService.findByUserId(userId);
|
logger.debug("员工查询结果: {}", employee != null ? ("id=" + employee.getId() + ", name=" + employee.getName()) : "无");
|
if (employee != null) {
|
profile.setName(employee.getName());
|
profile.setPhone(employee.getPhone());
|
roles.add("EMPLOYEE");
|
|
EmployeeInfo employeeInfo = new EmployeeInfo(
|
employee.getId(),
|
employee.getName(),
|
employee.getRoleId(),
|
employee.getDescription()
|
);
|
profile.setEmployee(employeeInfo);
|
}
|
|
// 检查是否是评委
|
logger.debug("开始查询评委信息,userId={}", userId);
|
Judge judge = judgeService.findByUserId(userId);
|
logger.debug("评委查询结果: {}", judge != null ? ("id=" + judge.getId() + ", name=" + judge.getName()) : "无");
|
if (judge != null) {
|
if (profile.getName() == null) {
|
profile.setName(judge.getName());
|
profile.setPhone(judge.getPhone());
|
}
|
roles.add("JUDGE");
|
|
JudgeInfo judgeInfo = new JudgeInfo(
|
judge.getId(),
|
judge.getName(),
|
judge.getTitle(),
|
judge.getCompany(),
|
judge.getDescription()
|
);
|
profile.setJudge(judgeInfo);
|
}
|
|
// 检查是否是学员
|
logger.debug("开始查询学员信息,userId={}", userId);
|
Player player = playerService.findByUserId(userId);
|
logger.debug("学员查询结果: {}", player != null ? ("id=" + player.getId() + ", name=" + player.getName()) : "无");
|
if (player != null) {
|
if (profile.getName() == null) {
|
profile.setName(player.getName());
|
profile.setPhone(player.getPhone());
|
}
|
roles.add("PLAYER");
|
|
PlayerInfo playerInfo = new PlayerInfo(
|
player.getId(),
|
player.getName(),
|
player.getPhone(),
|
player.getDescription()
|
);
|
profile.setPlayer(playerInfo);
|
}
|
|
profile.setRoles(roles);
|
|
// 获取用户头像
|
try {
|
List<Media> avatarMediaList = mediaRepository.findByTargetTypeAndTargetIdAndState(
|
MediaTargetType.USER_AVATAR.getValue(),
|
userId,
|
1
|
);
|
if (!avatarMediaList.isEmpty()) {
|
Media avatarMedia = avatarMediaList.get(0);
|
String fullAvatarUrl = buildFullMediaUrl(avatarMedia.getPath());
|
profile.setAvatar(fullAvatarUrl);
|
logger.debug("找到用户头像: {} -> {}", avatarMedia.getPath(), fullAvatarUrl);
|
} else {
|
logger.debug("用户{}没有找到头像", userId);
|
}
|
} catch (Exception e) {
|
logger.warn("获取用户头像失败: {}", e.getMessage());
|
}
|
|
logger.debug("userProfile构建完成,roles={}, name={}, phone={}, avatar={}",
|
roles, profile.getName(), profile.getPhone(), profile.getAvatar());
|
profile.setCreatedAt(java.time.LocalDateTime.now().toString());
|
|
return profile;
|
} catch (Exception e) {
|
logger.error("获取用户档案失败", e);
|
throw new RuntimeException("获取用户档案失败: " + e.getMessage(), e);
|
}
|
}
|
|
/**
|
* 获取用户统计数据
|
*/
|
@QueryMapping
|
public UserStats userStats() {
|
try {
|
Long userId = userContextUtil.getCurrentUserId();
|
if (userId == null) {
|
return null;
|
}
|
|
UserStats stats = new UserStats();
|
stats.setTotalRegistrations(0);
|
stats.setOngoingActivities(0);
|
stats.setCompletedActivities(0);
|
stats.setAwards(0);
|
|
return stats;
|
} catch (Exception e) {
|
e.printStackTrace();
|
return null;
|
}
|
}
|
|
/**
|
* 获取我的报名记录
|
*/
|
@QueryMapping
|
public List<UserRegistration> myRegistrations(@Argument Integer limit) {
|
try {
|
Long userId = userContextUtil.getCurrentUserId();
|
if (userId == null) {
|
return new ArrayList<>();
|
}
|
|
// 构建SQL查询,获取用户的报名记录
|
StringBuilder sql = new StringBuilder();
|
sql.append("SELECT ap.id, a.id as activity_id, a.name as activity_name, ");
|
sql.append("ap.project_name, ap.state, ap.create_time, ");
|
sql.append("m.path as cover_image_path ");
|
sql.append("FROM t_activity_player ap ");
|
sql.append("INNER JOIN t_player p ON ap.player_id = p.id ");
|
sql.append("INNER JOIN t_activity a ON ap.activity_id = a.id ");
|
sql.append("LEFT JOIN t_media m ON a.cover_image_id = m.id ");
|
sql.append("WHERE p.user_id = :userId ");
|
sql.append("ORDER BY ap.create_time DESC");
|
|
if (limit != null && limit > 0) {
|
sql.append(" LIMIT :limit");
|
}
|
|
Query query = entityManager.createNativeQuery(sql.toString());
|
query.setParameter("userId", userId);
|
if (limit != null && limit > 0) {
|
query.setParameter("limit", limit);
|
}
|
|
@SuppressWarnings("unchecked")
|
List<Object[]> results = query.getResultList();
|
|
List<UserRegistration> registrations = new ArrayList<>();
|
for (Object[] row : results) {
|
UserRegistration registration = new UserRegistration();
|
registration.setId(String.valueOf(row[0]));
|
|
// 创建ActivityInfo
|
UserRegistration.ActivityInfo activityInfo = new UserRegistration.ActivityInfo();
|
activityInfo.setId(String.valueOf(row[1]));
|
activityInfo.setTitle((String) row[2]);
|
|
// 设置封面图片
|
if (row[6] != null) {
|
UserRegistration.MediaInfo mediaInfo = new UserRegistration.MediaInfo();
|
mediaInfo.setPath((String) row[6]);
|
mediaInfo.setFullUrl(buildFullMediaUrl((String) row[6]));
|
activityInfo.setCoverImage(mediaInfo);
|
}
|
|
registration.setActivity(activityInfo);
|
|
// 设置状态
|
Integer state = (Integer) row[4];
|
String status = "pending";
|
if (state != null) {
|
switch (state) {
|
case 0: status = "pending"; break;
|
case 1: status = "approved"; break;
|
case 2: status = "rejected"; break;
|
default: status = "unknown"; break;
|
}
|
}
|
registration.setStatus(status);
|
|
// 设置报名时间
|
if (row[5] != null) {
|
registration.setRegistrationTime(row[5].toString());
|
}
|
|
registrations.add(registration);
|
}
|
|
return registrations;
|
} catch (Exception e) {
|
logger.error("获取用户报名记录失败", e);
|
return new ArrayList<>();
|
}
|
}
|
|
/**
|
* 获取我的项目列表
|
*/
|
@QueryMapping
|
public List<UserProject> myProjects() {
|
try {
|
Long userId = userContextUtil.getCurrentUserId();
|
logger.debug("获取用户项目列表,userId: {}", userId);
|
if (userId == null) {
|
return new ArrayList<>();
|
}
|
|
// 查询用户的所有项目(state = 0, 1, 2)
|
// 使用 t_activity_player join t_player join t_user 的方式通过用户ID查询
|
String sql = """
|
SELECT ap.id, ap.project_name, a.name as activity_name, ap.state, ap.create_time
|
FROM t_activity_player ap
|
JOIN t_player p ON ap.player_id = p.id
|
JOIN t_activity a ON a.id = ap.activity_id
|
WHERE p.user_id = ? AND ap.state IN (0, 1, 2)
|
ORDER BY ap.create_time DESC
|
""";
|
|
Query query = entityManager.createNativeQuery(sql);
|
query.setParameter(1, userId);
|
|
@SuppressWarnings("unchecked")
|
List<Object[]> results = query.getResultList();
|
|
List<UserProject> projects = new ArrayList<>();
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
for (Object[] row : results) {
|
String id = row[0].toString();
|
String projectName = row[1] != null ? row[1].toString() : "";
|
String activityName = row[2] != null ? row[2].toString() : "";
|
String status = row[3] != null ? row[3].toString() : "0";
|
String createTime = row[4] != null ? row[4].toString() : "";
|
|
UserProject project = new UserProject(id, projectName, activityName, status, createTime);
|
|
// 查询项目的提交文件
|
List<SubmissionMediaResponse> submissionFiles = getSubmissionFiles(Long.parseLong(id));
|
project.setSubmissionFiles(submissionFiles);
|
|
projects.add(project);
|
}
|
|
logger.debug("查询到 {} 个项目", projects.size());
|
return projects;
|
} catch (Exception e) {
|
logger.error("获取用户项目列表失败", e);
|
return new ArrayList<>();
|
}
|
}
|
|
/**
|
* 获取项目的提交文件
|
* @param activityPlayerId 活动参与者ID
|
* @return 提交文件列表
|
*/
|
private List<SubmissionMediaResponse> getSubmissionFiles(Long activityPlayerId) {
|
try {
|
// 查询提交的媒体文件 (target_type = 5 表示活动参与者提交的文件,state = 1 表示有效状态)
|
List<Media> medias = mediaRepository.findByTargetTypeAndTargetIdAndState(5, activityPlayerId, 1);
|
|
List<SubmissionMediaResponse> submissionFiles = new ArrayList<>();
|
for (Media media : medias) {
|
SubmissionMediaResponse response = new SubmissionMediaResponse();
|
response.setId(media.getId());
|
response.setName(media.getName());
|
response.setPath(media.getPath());
|
response.setUrl(buildFullMediaUrl(media.getPath()));
|
response.setFullUrl(buildFullMediaUrl(media.getPath()));
|
response.setFullThumbUrl(buildFullMediaUrl(media.getThumbPath()));
|
response.setFileExt(media.getFileExt());
|
response.setFileSize(media.getFileSize() != null ? media.getFileSize().longValue() : null);
|
response.setMediaType(media.getMediaType());
|
response.setThumbUrl(buildFullMediaUrl(media.getThumbPath()));
|
submissionFiles.add(response);
|
}
|
|
return submissionFiles;
|
} catch (Exception e) {
|
logger.error("获取项目提交文件失败,activityPlayerId: {}", activityPlayerId, e);
|
return new ArrayList<>();
|
}
|
}
|
|
/**
|
* 构建完整的媒体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;
|
}
|
|
/**
|
* 保存用户信息
|
*/
|
@MutationMapping
|
public UserProfileInfo saveUserInfo(@Argument UserInput input) {
|
try {
|
Long userId = userContextUtil.getCurrentUserId();
|
logger.debug("进入saveUserInfo,解析到用户ID: {}", userId);
|
if (userId == null) {
|
throw new RuntimeException("用户未登录");
|
}
|
|
// 查找现有用户
|
Optional<User> userOpt = userRepository.findById(userId);
|
User user;
|
|
if (userOpt.isPresent()) {
|
// 用户存在,更新信息
|
user = userOpt.get();
|
logger.debug("更新现有用户信息,用户ID: {}", userId);
|
} else {
|
// 用户不存在,创建新用户
|
user = new User();
|
user.setId(userId);
|
logger.debug("创建新用户,用户ID: {}", userId);
|
}
|
|
// 更新用户基本信息(不包含头像)
|
user.setName(input.getName());
|
user.setPhone(input.getPhone());
|
|
// 处理性别转换:MALE -> 1, FEMALE -> 0
|
if ("MALE".equals(input.getGender())) {
|
user.setGender(1);
|
} else if ("FEMALE".equals(input.getGender())) {
|
user.setGender(0);
|
}
|
|
// 处理生日转换
|
if (StringUtils.hasText(input.getBirthday())) {
|
try {
|
LocalDate birthday = LocalDate.parse(input.getBirthday());
|
user.setBirthday(birthday);
|
} catch (Exception e) {
|
logger.warn("生日格式解析失败: {}", input.getBirthday(), e);
|
}
|
}
|
|
// 保存用户基本信息
|
user = userRepository.save(user);
|
logger.debug("用户信息保存成功,用户ID: {}", user.getId());
|
|
// 构建返回结果
|
UserProfileInfo result = new UserProfileInfo();
|
result.setId(user.getId().toString());
|
result.setName(user.getName());
|
result.setPhone(user.getPhone());
|
// 正确处理性别转换:1 -> MALE, 0 -> FEMALE, null -> null
|
if (user.getGender() != null) {
|
result.setGender(user.getGender() == 1 ? "MALE" : "FEMALE");
|
} else {
|
result.setGender(null);
|
}
|
result.setBirthday(user.getBirthday() != null ? user.getBirthday().toString() : null);
|
result.setWxOpenId(user.getWxOpenid());
|
result.setUnionId(user.getWxUnionid());
|
|
// 查找并设置头像URL(从t_media表获取)
|
try {
|
List<Media> avatarMedias = mediaRepository.findByTargetTypeAndTargetIdAndState(
|
MediaTargetType.USER_AVATAR.getValue(),
|
userId,
|
1
|
);
|
if (!avatarMedias.isEmpty()) {
|
Media avatarMedia = avatarMedias.get(0);
|
result.setAvatar(buildFullMediaUrl(avatarMedia.getPath()));
|
}
|
} catch (Exception e) {
|
logger.warn("获取头像失败: {}", e.getMessage(), e);
|
}
|
|
return result;
|
} catch (Exception e) {
|
logger.error("保存用户信息失败", e);
|
throw new RuntimeException("保存用户信息失败: " + e.getMessage());
|
}
|
}
|
}
|