|
|
@@ -2,6 +2,7 @@ package org.dromara.system.service.impl.app;
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import org.dromara.common.core.exception.ServiceException;
|
|
|
import org.dromara.common.core.utils.MapstructUtils;
|
|
|
import org.dromara.common.core.utils.StringUtils;
|
|
|
import org.dromara.system.domain.GameAthlete;
|
|
|
@@ -17,16 +18,20 @@ import org.dromara.system.domain.vo.app.UserEventInfoVo;
|
|
|
import org.dromara.system.domain.vo.app.UserLoginVo;
|
|
|
import org.dromara.system.domain.vo.app.ExperienceMyInfoVo;
|
|
|
import org.dromara.system.domain.vo.app.ExperienceMyRecordVo;
|
|
|
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
-import java.util.stream.Collectors;
|
|
|
+import org.dromara.system.domain.vo.app.ExperienceEnrollInfoVo;
|
|
|
+import org.dromara.system.domain.vo.app.ExperienceProjectVo;
|
|
|
+import org.dromara.system.domain.bo.ExperienceEnrollSubmitBo;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import org.dromara.system.mapper.*;
|
|
|
import org.dromara.system.mapper.app.GameUserMapper;
|
|
|
import org.dromara.system.service.app.IUserEventService;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.web.reactive.function.client.WebClient;
|
|
|
import reactor.core.publisher.Mono;
|
|
|
|
|
|
@@ -68,7 +73,7 @@ public class UserEventServiceImpl implements IUserEventService {
|
|
|
try {
|
|
|
// 步骤1:通过code获取微信openid和session_key
|
|
|
WxLoginResult wxResult = getWxLoginResult(loginVo.getCode());
|
|
|
- if (wxResult == null || wxResult.getOpenid() == null || wxResult.getOpenid().isEmpty()) {
|
|
|
+ if (wxResult.getOpenid() == null || wxResult.getOpenid().isEmpty()) {
|
|
|
throw new RuntimeException("微信登录失败,无法获取用户信息");
|
|
|
}
|
|
|
|
|
|
@@ -93,49 +98,42 @@ public class UserEventServiceImpl implements IUserEventService {
|
|
|
* 通过code获取微信登录结果
|
|
|
*/
|
|
|
private WxLoginResult getWxLoginResult(String code) {
|
|
|
- try {
|
|
|
- if (appId == null || appId.isEmpty() || secret == null || secret.isEmpty()) {
|
|
|
- throw new RuntimeException("微信小程序配置未设置");
|
|
|
- }
|
|
|
-
|
|
|
- String url = String.format(
|
|
|
- "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
|
|
|
- appId, secret, code);
|
|
|
-
|
|
|
- // 先获取字符串响应,避免Content-Type不匹配问题
|
|
|
- String responseBody = webClient.get()
|
|
|
- .uri(url)
|
|
|
- .retrieve()
|
|
|
- .onStatus(status -> status.is4xxClientError() || status.is5xxServerError(),
|
|
|
- response -> response.bodyToMono(String.class)
|
|
|
- .flatMap(body -> Mono.error(new RuntimeException(
|
|
|
- "HTTP错误: " + response.statusCode() + ", 响应: " + body))))
|
|
|
- .bodyToMono(String.class)
|
|
|
- .timeout(Duration.ofSeconds(30)) // 30秒超时
|
|
|
- .block(); // 同步等待结果
|
|
|
-
|
|
|
- if (responseBody == null || responseBody.trim().isEmpty()) {
|
|
|
- throw new RuntimeException("微信接口返回空结果");
|
|
|
- }
|
|
|
+ if (appId == null || appId.isEmpty() || secret == null || secret.isEmpty()) {
|
|
|
+ throw new RuntimeException("微信小程序配置未设置");
|
|
|
+ }
|
|
|
|
|
|
- // 手动解析JSON响应
|
|
|
- WxLoginResult result = parseWxResponse(responseBody);
|
|
|
+ String url = String.format(
|
|
|
+ "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
|
|
|
+ appId, secret, code);
|
|
|
+
|
|
|
+ // 先获取字符串响应,避免Content-Type不匹配问题
|
|
|
+ String responseBody = webClient.get()
|
|
|
+ .uri(url)
|
|
|
+ .retrieve()
|
|
|
+ .onStatus(status -> status.is4xxClientError() || status.is5xxServerError(),
|
|
|
+ response -> response.bodyToMono(String.class)
|
|
|
+ .flatMap(body -> Mono.error(new RuntimeException(
|
|
|
+ "HTTP错误: " + response.statusCode() + ", 响应: " + body))))
|
|
|
+ .bodyToMono(String.class)
|
|
|
+ .timeout(Duration.ofSeconds(30)) // 30秒超时
|
|
|
+ .block(); // 同步等待结果
|
|
|
+
|
|
|
+ if (responseBody == null || responseBody.trim().isEmpty()) {
|
|
|
+ throw new RuntimeException("微信接口返回空结果");
|
|
|
+ }
|
|
|
|
|
|
- if (result.getErrcode() != null && result.getErrcode() != 0) {
|
|
|
- throw new RuntimeException("微信接口返回错误:" + result.getErrmsg() + " (错误码: " + result.getErrcode() + ")");
|
|
|
- }
|
|
|
+ // 手动解析JSON响应
|
|
|
+ WxLoginResult result = parseWxResponse(responseBody);
|
|
|
|
|
|
- if (result.getOpenid() == null || result.getOpenid().isEmpty()) {
|
|
|
- throw new RuntimeException("微信接口未返回openid");
|
|
|
- }
|
|
|
+ if (result.getErrcode() != null && result.getErrcode() != 0) {
|
|
|
+ throw new RuntimeException("微信接口返回错误:" + result.getErrmsg() + " (错误码: " + result.getErrcode() + ")");
|
|
|
+ }
|
|
|
|
|
|
- return result;
|
|
|
- } catch (Exception e) {
|
|
|
- if (e instanceof RuntimeException) {
|
|
|
- throw e;
|
|
|
- }
|
|
|
- throw new RuntimeException("调用微信接口失败:" + e.getMessage(), e);
|
|
|
+ if (result.getOpenid() == null || result.getOpenid().isEmpty()) {
|
|
|
+ throw new RuntimeException("微信接口未返回openid");
|
|
|
}
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -144,8 +142,7 @@ public class UserEventServiceImpl implements IUserEventService {
|
|
|
private WxLoginResult parseWxResponse(String responseBody) {
|
|
|
try {
|
|
|
// 使用Jackson解析JSON
|
|
|
- WxLoginResult result = objectMapper.readValue(responseBody, WxLoginResult.class);
|
|
|
- return result;
|
|
|
+ return objectMapper.readValue(responseBody, WxLoginResult.class);
|
|
|
} catch (Exception e) {
|
|
|
throw new RuntimeException("解析微信响应失败:" + e.getMessage() + ", 响应内容: " + responseBody);
|
|
|
}
|
|
|
@@ -362,4 +359,86 @@ public class UserEventServiceImpl implements IUserEventService {
|
|
|
return rawScore.stripTrailingZeros().toPlainString();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ExperienceEnrollInfoVo getExperienceEnrollInfo(String phone, Long eventId) {
|
|
|
+ ExperienceEnrollInfoVo infoVo = new ExperienceEnrollInfoVo();
|
|
|
+ // 1. 获取赛事下的项目列表
|
|
|
+ List<GameEventProject> projects = gameEventProjectMapper.selectList(
|
|
|
+ Wrappers.lambdaQuery(GameEventProject.class)
|
|
|
+ .select(GameEventProject::getProjectId, GameEventProject::getProjectName, GameEventProject::getClassification)
|
|
|
+ .eq(GameEventProject::getEventId, eventId)
|
|
|
+ .eq(GameEventProject::getDelFlag, "0")
|
|
|
+ .orderByAsc(GameEventProject::getProjectId)
|
|
|
+ );
|
|
|
+ List<ExperienceProjectVo> projectVos = new ArrayList<>();
|
|
|
+ if (CollectionUtils.isNotEmpty(projects)) {
|
|
|
+ for (GameEventProject project : projects) {
|
|
|
+ ExperienceProjectVo pVo = new ExperienceProjectVo();
|
|
|
+ pVo.setProjectId(project.getProjectId());
|
|
|
+ pVo.setProjectName(project.getProjectName());
|
|
|
+ pVo.setClassification(project.getClassification());
|
|
|
+ projectVos.add(pVo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ infoVo.setProjects(projectVos);
|
|
|
+
|
|
|
+ // 2. 根据手机号和赛事ID查询是否已经有运动员报名信息
|
|
|
+ GameAthlete athlete = gameAthleteMapper.selectOne(
|
|
|
+ Wrappers.lambdaQuery(GameAthlete.class)
|
|
|
+ .select(GameAthlete::getAthleteId, GameAthlete::getName, GameAthlete::getPhone,
|
|
|
+ GameAthlete::getIdCard, GameAthlete::getGender, GameAthlete::getTshirtSize,
|
|
|
+ GameAthlete::getEmergencyContactName, GameAthlete::getEmergencyContactPhone)
|
|
|
+ .eq(GameAthlete::getPhone, phone.trim())
|
|
|
+ .eq(GameAthlete::getEventId, eventId)
|
|
|
+ .eq(GameAthlete::getDelFlag, "0")
|
|
|
+ );
|
|
|
+
|
|
|
+ if (athlete != null) {
|
|
|
+ infoVo.setAthleteId(athlete.getAthleteId());
|
|
|
+ infoVo.setName(athlete.getName());
|
|
|
+ infoVo.setGender(athlete.getGender());
|
|
|
+ infoVo.setIdCard(athlete.getIdCard());
|
|
|
+ infoVo.setTshirtSize(athlete.getTshirtSize());
|
|
|
+ infoVo.setEmergencyContactName(athlete.getEmergencyContactName());
|
|
|
+ infoVo.setEmergencyContactPhone(athlete.getEmergencyContactPhone());
|
|
|
+ }
|
|
|
+
|
|
|
+ return infoVo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Boolean submitExperienceEnroll(ExperienceEnrollSubmitBo submitBo) {
|
|
|
+ // 1. 验证项目是否存在于该赛事
|
|
|
+ boolean project = gameEventProjectMapper.exists(
|
|
|
+ Wrappers.lambdaQuery(GameEventProject.class)
|
|
|
+ .eq(GameEventProject::getProjectId, submitBo.getProjectId())
|
|
|
+ .eq(GameEventProject::getEventId, submitBo.getEventId())
|
|
|
+ .eq(GameEventProject::getDelFlag, "0")
|
|
|
+ );
|
|
|
+ if (!project) {
|
|
|
+ throw new ServiceException("所选项目在当前赛事中不存在或已被删除");
|
|
|
+ }
|
|
|
+ GameAthlete athlete = gameAthleteMapper.selectOne(Wrappers.lambdaQuery(GameAthlete.class)
|
|
|
+ .eq(GameAthlete::getAthleteId, submitBo.getAthleteId())
|
|
|
+ .eq(GameAthlete::getDelFlag, "0")
|
|
|
+ .select(GameAthlete::getProjectValue)
|
|
|
+ );
|
|
|
+ if (athlete == null){
|
|
|
+ throw new ServiceException("运动员信息不存在或已被删除");
|
|
|
+ }
|
|
|
+ List<Long> list = JSONUtil.toList(athlete.getProjectValue(), Long.class);
|
|
|
+ if (list == null) {
|
|
|
+ list = new ArrayList<>();
|
|
|
+ }
|
|
|
+ if (list.contains(submitBo.getProjectId())){
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ list.add(submitBo.getProjectId());
|
|
|
+ athlete.setProjectValue(JSONUtil.toJsonStr(list));
|
|
|
+ return gameAthleteMapper.update(athlete, Wrappers.lambdaUpdate(GameAthlete.class)
|
|
|
+ .eq(GameAthlete::getAthleteId, submitBo.getAthleteId())
|
|
|
+ ) > 0;
|
|
|
+ }
|
|
|
}
|