修复丢失文件
This commit is contained in:
+7
-6
@@ -1,7 +1,6 @@
|
|||||||
package cn.novalon.gym.manage.auth.dto;
|
package cn.novalon.gym.manage.auth.dto;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.Pattern;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -9,7 +8,7 @@ import lombok.NoArgsConstructor;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 手机号一键登录请求DTO
|
* 手机号一键登录请求DTO
|
||||||
* uniapp官方一键登录流程:前端通过云函数获取手机号,直接传给后端
|
* uniapp官方一键登录流程:前端通过云函数获取access_token和openid传给后端换取手机号
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@@ -17,11 +16,13 @@ import lombok.NoArgsConstructor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class PhoneLoginDto {
|
public class PhoneLoginDto {
|
||||||
|
|
||||||
@NotBlank(message = "手机号不能为空")
|
@NotBlank(message = "access_token不能为空")
|
||||||
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
|
private String accessToken;
|
||||||
private String phone;
|
|
||||||
|
@NotBlank(message = "openid不能为空")
|
||||||
|
private String openid;
|
||||||
|
|
||||||
private String nickname;
|
private String nickname;
|
||||||
|
|
||||||
private String avatar;
|
private String avatar;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -2,6 +2,7 @@ package cn.novalon.gym.manage.auth.handler;
|
|||||||
|
|
||||||
import cn.novalon.gym.manage.auth.dto.PhoneCodeLoginDto;
|
import cn.novalon.gym.manage.auth.dto.PhoneCodeLoginDto;
|
||||||
import cn.novalon.gym.manage.auth.dto.PhoneLoginDto;
|
import cn.novalon.gym.manage.auth.dto.PhoneLoginDto;
|
||||||
|
import cn.novalon.gym.manage.auth.dto.SendCodeRequest;
|
||||||
import cn.novalon.gym.manage.auth.service.PhoneAuthService;
|
import cn.novalon.gym.manage.auth.service.PhoneAuthService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
@@ -38,8 +39,8 @@ public class PhoneAuthHandler {
|
|||||||
public Mono<ServerResponse> sendSmsCode(ServerRequest request) {
|
public Mono<ServerResponse> sendSmsCode(ServerRequest request) {
|
||||||
log.info("收到发送短信验证码请求");
|
log.info("收到发送短信验证码请求");
|
||||||
|
|
||||||
return request.bodyToMono(PhoneLoginDto.class)
|
return request.bodyToMono(SendCodeRequest.class)
|
||||||
.flatMap(dto -> phoneAuthService.sendSmsCode(dto.getPhone()))
|
.flatMap(req -> phoneAuthService.sendSmsCode(req.getPhone()))
|
||||||
.flatMap(success -> ServerResponse.ok()
|
.flatMap(success -> ServerResponse.ok()
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.bodyValue(Map.of("success", success, "message", success ? "验证码发送成功" : "验证码发送失败")));
|
.bodyValue(Map.of("success", success, "message", success ? "验证码发送成功" : "验证码发送失败")));
|
||||||
|
|||||||
+65
-13
@@ -1,5 +1,6 @@
|
|||||||
package cn.novalon.gym.manage.auth.service.impl;
|
package cn.novalon.gym.manage.auth.service.impl;
|
||||||
|
|
||||||
|
import cn.novalon.gym.manage.auth.config.SmsProperties;
|
||||||
import cn.novalon.gym.manage.auth.dto.PhoneCodeLoginDto;
|
import cn.novalon.gym.manage.auth.dto.PhoneCodeLoginDto;
|
||||||
import cn.novalon.gym.manage.auth.dto.PhoneLoginDto;
|
import cn.novalon.gym.manage.auth.dto.PhoneLoginDto;
|
||||||
import cn.novalon.gym.manage.auth.service.PhoneAuthService;
|
import cn.novalon.gym.manage.auth.service.PhoneAuthService;
|
||||||
@@ -15,6 +16,13 @@ import cn.novalon.gym.manage.member.util.AesUtil;
|
|||||||
import cn.novalon.gym.manage.member.util.EsSyncUtils;
|
import cn.novalon.gym.manage.member.util.EsSyncUtils;
|
||||||
import cn.novalon.gym.manage.member.util.MemberNoGenerator;
|
import cn.novalon.gym.manage.member.util.MemberNoGenerator;
|
||||||
import cn.novalon.gym.manage.sys.security.JwtTokenProvider;
|
import cn.novalon.gym.manage.sys.security.JwtTokenProvider;
|
||||||
|
import com.aliyuncs.DefaultAcsClient;
|
||||||
|
import com.aliyuncs.IAcsClient;
|
||||||
|
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileRequest;
|
||||||
|
import com.aliyuncs.dypnsapi.model.v20170525.GetMobileResponse;
|
||||||
|
import com.aliyuncs.exceptions.ClientException;
|
||||||
|
import com.aliyuncs.exceptions.ServerException;
|
||||||
|
import com.aliyuncs.profile.DefaultProfile;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -35,6 +43,7 @@ public class PhoneAuthServiceImpl implements PhoneAuthService {
|
|||||||
private final EsSyncUtils esSyncUtils;
|
private final EsSyncUtils esSyncUtils;
|
||||||
private final JwtTokenProvider jwtTokenProvider;
|
private final JwtTokenProvider jwtTokenProvider;
|
||||||
private final SmsService smsService;
|
private final SmsService smsService;
|
||||||
|
private final SmsProperties smsProperties;
|
||||||
|
|
||||||
private EsSyncUtils.EntitySyncer<Member, MemberES, String> memberSyncer;
|
private EsSyncUtils.EntitySyncer<Member, MemberES, String> memberSyncer;
|
||||||
|
|
||||||
@@ -45,19 +54,63 @@ public class PhoneAuthServiceImpl implements PhoneAuthService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<PhoneLoginVO> oneClickLogin(PhoneLoginDto request) {
|
public Mono<PhoneLoginVO> oneClickLogin(PhoneLoginDto request) {
|
||||||
log.info("手机号一键登录, phone: {}", request.getPhone());
|
log.info("手机号一键登录请求, accessToken: {}, openid: {}", request.getAccessToken(), request.getOpenid());
|
||||||
|
|
||||||
String encryptedPhone = encryptPhone(request.getPhone());
|
return Mono.fromCallable(() -> getPhoneByToken(request.getAccessToken(), request.getOpenid()))
|
||||||
|
.flatMap(phone -> {
|
||||||
|
log.info("通过access_token获取手机号成功: {}", maskPhone(phone));
|
||||||
|
String encryptedPhone = encryptPhone(phone);
|
||||||
|
|
||||||
return memberRepository.findByPhone(encryptedPhone)
|
return memberRepository.findByPhone(encryptedPhone)
|
||||||
.flatMap(existingMember -> {
|
.flatMap(existingMember -> {
|
||||||
log.info("手机号已注册,直接登录, memberId: {}", existingMember.getId());
|
log.info("手机号已注册,直接登录, memberId: {}", existingMember.getId());
|
||||||
return doLogin(existingMember, false, request);
|
return doLogin(existingMember, false, request);
|
||||||
|
})
|
||||||
|
.switchIfEmpty(Mono.defer(() -> {
|
||||||
|
log.info("手机号未注册,创建新会员");
|
||||||
|
return createNewMemberAndLogin(request, encryptedPhone);
|
||||||
|
}));
|
||||||
})
|
})
|
||||||
.switchIfEmpty(Mono.defer(() -> {
|
.onErrorResume(e -> {
|
||||||
log.info("手机号未注册,创建新会员");
|
log.error("一键登录失败", e);
|
||||||
return createNewMemberAndLogin(request, encryptedPhone);
|
return Mono.error(new SystemException(ErrorCode.AUTH_PHONE_ERROR, "手机号获取失败: " + e.getMessage()));
|
||||||
}));
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过access_token和openid获取手机号
|
||||||
|
* 使用阿里云DYPNS API
|
||||||
|
*/
|
||||||
|
private String getPhoneByToken(String accessToken, String openid) throws Exception {
|
||||||
|
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", smsProperties.getAccessKeyId(), smsProperties.getAccessKeySecret());
|
||||||
|
IAcsClient client = new DefaultAcsClient(profile);
|
||||||
|
GetMobileRequest request = new GetMobileRequest();
|
||||||
|
request.setAccessToken(accessToken);
|
||||||
|
|
||||||
|
try {
|
||||||
|
GetMobileResponse response = client.getAcsResponse(request);
|
||||||
|
if ("OK".equals(response.getCode())) {
|
||||||
|
return response.getGetMobileResultDTO().getMobile();
|
||||||
|
}
|
||||||
|
log.warn("DYPNS API返回错误: code={}, message={}", response.getCode(), response.getMessage());
|
||||||
|
throw new SystemException(ErrorCode.AUTH_PHONE_ERROR, "手机号获取失败: " + response.getMessage());
|
||||||
|
} catch (ServerException e) {
|
||||||
|
log.error("阿里云DYPNS API服务端异常", e);
|
||||||
|
throw new SystemException(ErrorCode.AUTH_PHONE_ERROR, "手机号获取失败");
|
||||||
|
} catch (ClientException e) {
|
||||||
|
log.error("阿里云DYPNS API客户端异常", e);
|
||||||
|
throw new SystemException(ErrorCode.AUTH_PHONE_ERROR, "手机号获取失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 手机号脱敏显示
|
||||||
|
*/
|
||||||
|
private String maskPhone(String phone) {
|
||||||
|
if (phone == null || phone.length() < 11) {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
return phone.substring(0, 3) + "****" + phone.substring(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,7 +140,6 @@ public class PhoneAuthServiceImpl implements PhoneAuthService {
|
|||||||
.switchIfEmpty(Mono.defer(() -> {
|
.switchIfEmpty(Mono.defer(() -> {
|
||||||
log.info("手机号未注册,创建新会员");
|
log.info("手机号未注册,创建新会员");
|
||||||
PhoneLoginDto registerRequest = new PhoneLoginDto();
|
PhoneLoginDto registerRequest = new PhoneLoginDto();
|
||||||
registerRequest.setPhone(request.getPhone());
|
|
||||||
return createNewMemberAndLogin(registerRequest, encryptedPhone);
|
return createNewMemberAndLogin(registerRequest, encryptedPhone);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
@@ -153,7 +205,7 @@ public class PhoneAuthServiceImpl implements PhoneAuthService {
|
|||||||
vo.setNeedCompleteInfo(needCompleteInfo);
|
vo.setNeedCompleteInfo(needCompleteInfo);
|
||||||
vo.setNickname(member.getNickname());
|
vo.setNickname(member.getNickname());
|
||||||
vo.setAvatar(member.getAvatar());
|
vo.setAvatar(member.getAvatar());
|
||||||
vo.setPhone(decryptPhone(member.getPhone()));
|
vo.setPhone(member.getPhone() != null ? decryptPhone(member.getPhone()) : null);
|
||||||
return vo;
|
return vo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,4 +226,4 @@ public class PhoneAuthServiceImpl implements PhoneAuthService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-4
@@ -206,8 +206,4 @@ public class SignInRecord {
|
|||||||
public void restore() {
|
public void restore() {
|
||||||
this.isDelete = false;
|
this.isDelete = false;
|
||||||
}
|
}
|
||||||
<<<<<<< HEAD
|
|
||||||
}
|
}
|
||||||
=======
|
|
||||||
}
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
|
|||||||
-22
@@ -1,12 +1,9 @@
|
|||||||
package cn.novalon.gym.manage.checkIn.handler;
|
package cn.novalon.gym.manage.checkIn.handler;
|
||||||
|
|
||||||
import cn.novalon.gym.manage.checkIn.service.impl.CheckServiceImpl;
|
import cn.novalon.gym.manage.checkIn.service.impl.CheckServiceImpl;
|
||||||
<<<<<<< HEAD
|
|
||||||
import cn.novalon.gym.manage.checkIn.websocket.MyWebSocketHandler;
|
import cn.novalon.gym.manage.checkIn.websocket.MyWebSocketHandler;
|
||||||
=======
|
|
||||||
import cn.novalon.gym.manage.checkIn.vo.SignInRecordVO;
|
import cn.novalon.gym.manage.checkIn.vo.SignInRecordVO;
|
||||||
import cn.novalon.gym.manage.checkIn.vo.SignInStatsVO;
|
import cn.novalon.gym.manage.checkIn.vo.SignInStatsVO;
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
import cn.novalon.gym.manage.sys.util.AuthUtil;
|
import cn.novalon.gym.manage.sys.util.AuthUtil;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -88,12 +85,7 @@ public class CheckInHandler {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Mono<ServerResponse> getSignInRecords(ServerRequest request) {
|
public Mono<ServerResponse> getSignInRecords(ServerRequest request) {
|
||||||
<<<<<<< HEAD
|
|
||||||
Long memberId = authUtil.getMemberIdOrThrow(request);
|
Long memberId = authUtil.getMemberIdOrThrow(request);
|
||||||
=======
|
|
||||||
Long memberId = 1L;
|
|
||||||
// authUtil.getMemberIdOrThrow(request);
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
|
|
||||||
String startDateStr = request.queryParam("startDate").orElse(null);
|
String startDateStr = request.queryParam("startDate").orElse(null);
|
||||||
String endDateStr = request.queryParam("endDate").orElse(null);
|
String endDateStr = request.queryParam("endDate").orElse(null);
|
||||||
@@ -139,12 +131,7 @@ public class CheckInHandler {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Mono<ServerResponse> getSignInStatistics(ServerRequest request) {
|
public Mono<ServerResponse> getSignInStatistics(ServerRequest request) {
|
||||||
<<<<<<< HEAD
|
|
||||||
Long memberId = authUtil.getMemberIdOrThrow(request);
|
Long memberId = authUtil.getMemberIdOrThrow(request);
|
||||||
=======
|
|
||||||
Long memberId = 1L;
|
|
||||||
// authUtil.getMemberIdOrThrow(request);
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
|
|
||||||
String startDateStr = request.queryParam("startDate").orElse(null);
|
String startDateStr = request.queryParam("startDate").orElse(null);
|
||||||
String endDateStr = request.queryParam("endDate").orElse(null);
|
String endDateStr = request.queryParam("endDate").orElse(null);
|
||||||
@@ -169,12 +156,7 @@ public class CheckInHandler {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Mono<ServerResponse> exportSignInRecords(ServerRequest request) {
|
public Mono<ServerResponse> exportSignInRecords(ServerRequest request) {
|
||||||
<<<<<<< HEAD
|
|
||||||
Long memberId = authUtil.getMemberIdOrThrow(request);
|
Long memberId = authUtil.getMemberIdOrThrow(request);
|
||||||
=======
|
|
||||||
Long memberId = 1L;
|
|
||||||
// authUtil.getMemberIdOrThrow(request);
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
|
|
||||||
String startDateStr = request.queryParam("startDate").orElse(null);
|
String startDateStr = request.queryParam("startDate").orElse(null);
|
||||||
String endDateStr = request.queryParam("endDate").orElse(null);
|
String endDateStr = request.queryParam("endDate").orElse(null);
|
||||||
@@ -212,8 +194,4 @@ public class CheckInHandler {
|
|||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
.bodyValue(Map.of("code", 200, "message", "success", "data", stats)));
|
.bodyValue(Map.of("code", 200, "message", "success", "data", stats)));
|
||||||
}
|
}
|
||||||
<<<<<<< HEAD
|
|
||||||
}
|
}
|
||||||
=======
|
|
||||||
}
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
|
|||||||
-4
@@ -78,8 +78,4 @@ public interface ICheckInService {
|
|||||||
* @return 签到统计VO
|
* @return 签到统计VO
|
||||||
*/
|
*/
|
||||||
Mono<SignInStatsVO> getDailySignInStats(LocalDate date);
|
Mono<SignInStatsVO> getDailySignInStats(LocalDate date);
|
||||||
<<<<<<< HEAD
|
|
||||||
}
|
}
|
||||||
=======
|
|
||||||
}
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
|
|||||||
-49
@@ -2,11 +2,8 @@ package cn.novalon.gym.manage.checkIn.service.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
<<<<<<< HEAD
|
|
||||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
import cn.hutool.extra.qrcode.QrCodeUtil;
|
||||||
import cn.hutool.extra.qrcode.QrConfig;
|
import cn.hutool.extra.qrcode.QrConfig;
|
||||||
=======
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
import cn.novalon.gym.manage.checkIn.config.QRCodeConfig;
|
import cn.novalon.gym.manage.checkIn.config.QRCodeConfig;
|
||||||
import cn.novalon.gym.manage.checkIn.constant.QRRedisKey;
|
import cn.novalon.gym.manage.checkIn.constant.QRRedisKey;
|
||||||
import cn.novalon.gym.manage.checkIn.entity.SignInRecord;
|
import cn.novalon.gym.manage.checkIn.entity.SignInRecord;
|
||||||
@@ -24,11 +21,6 @@ import cn.novalon.gym.manage.member.entity.MemberCardRecord;
|
|||||||
import cn.novalon.gym.manage.member.enums.MemberCardType;
|
import cn.novalon.gym.manage.member.enums.MemberCardType;
|
||||||
import cn.novalon.gym.manage.member.repository.MemberCardRecordRepository;
|
import cn.novalon.gym.manage.member.repository.MemberCardRecordRepository;
|
||||||
import cn.novalon.gym.manage.member.repository.MemberCardRepository;
|
import cn.novalon.gym.manage.member.repository.MemberCardRepository;
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
import cn.hutool.extra.qrcode.QrCodeUtil;
|
|
||||||
import cn.hutool.extra.qrcode.QrConfig;
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -92,10 +84,7 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
public Mono<String> checkIn(Long memberId, String qrContent) {
|
public Mono<String> checkIn(Long memberId, String qrContent) {
|
||||||
String key = RedisKeyConstants.QRCODE_USER_DAILY + memberId + LocalDate.now();
|
String key = RedisKeyConstants.QRCODE_USER_DAILY + memberId + LocalDate.now();
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
// 先检查当天是否已经签到(从数据库查询,作为重复签到的额外保障)
|
// 先检查当天是否已经签到(从数据库查询,作为重复签到的额外保障)
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
return checkTodayAlreadySignedIn(memberId)
|
return checkTodayAlreadySignedIn(memberId)
|
||||||
.flatMap(existingRecord -> {
|
.flatMap(existingRecord -> {
|
||||||
String checkInTime = existingRecord.getSignInTime().format(DATE_FORMATTER);
|
String checkInTime = existingRecord.getSignInTime().format(DATE_FORMATTER);
|
||||||
@@ -137,14 +126,11 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* 检查会员当天是否已经签到
|
* 检查会员当天是否已经签到
|
||||||
* @param memberId 会员ID
|
* @param memberId 会员ID
|
||||||
* @return 如果已签到返回签到记录,否则返回空
|
* @return 如果已签到返回签到记录,否则返回空
|
||||||
*/
|
*/
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
private Mono<SignInRecord> checkTodayAlreadySignedIn(Long memberId) {
|
private Mono<SignInRecord> checkTodayAlreadySignedIn(Long memberId) {
|
||||||
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
|
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
|
||||||
LocalDateTime endOfDay = LocalDate.now().atTime(LocalTime.MAX);
|
LocalDateTime endOfDay = LocalDate.now().atTime(LocalTime.MAX);
|
||||||
@@ -152,11 +138,6 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
return signInRecordRepository.findByMemberIdAndDate(memberId, startOfDay, endOfDay);
|
return signInRecordRepository.findByMemberIdAndDate(memberId, startOfDay, endOfDay);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
private Mono<String> processCheckIn(Long memberId, Long memberCardRecordId, Map<String, Object> redisMap, String qrContent) {
|
|
||||||
LocalDateTime now = LocalDateTime.now();
|
|
||||||
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* 处理签到逻辑
|
* 处理签到逻辑
|
||||||
*/
|
*/
|
||||||
@@ -164,7 +145,6 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
|
||||||
// 发送实时进度通知
|
// 发送实时进度通知
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
MyWebSocketHandler.sendProgress(qrContent, "VALIDATE_CARD", "正在验证会员卡...");
|
MyWebSocketHandler.sendProgress(qrContent, "VALIDATE_CARD", "正在验证会员卡...");
|
||||||
|
|
||||||
return memberCardRecordRepository.findById(memberCardRecordId)
|
return memberCardRecordRepository.findById(memberCardRecordId)
|
||||||
@@ -183,15 +163,10 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
return Mono.error(new RuntimeException("会员卡已过期"));
|
return Mono.error(new RuntimeException("会员卡已过期"));
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
MyWebSocketHandler.sendProgress(qrContent, "VALIDATE_BOOKING", "会员卡验证通过,正在检查预约信息...");
|
|
||||||
|
|
||||||
=======
|
|
||||||
// 发送实时进度通知
|
// 发送实时进度通知
|
||||||
MyWebSocketHandler.sendProgress(qrContent, "VALIDATE_BOOKING", "会员卡验证通过,正在检查预约信息...");
|
MyWebSocketHandler.sendProgress(qrContent, "VALIDATE_BOOKING", "会员卡验证通过,正在检查预约信息...");
|
||||||
|
|
||||||
// 检查是否有需要签到的团课预约
|
// 检查是否有需要签到的团课预约
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
return validateBooking(memberId, now)
|
return validateBooking(memberId, now)
|
||||||
.then(memberCardRepository.findByMemberCardIdAndDeletedAtIsNull(cardRecord.getMemberCardId())
|
.then(memberCardRepository.findByMemberCardIdAndDeletedAtIsNull(cardRecord.getMemberCardId())
|
||||||
.switchIfEmpty(Mono.defer(() -> {
|
.switchIfEmpty(Mono.defer(() -> {
|
||||||
@@ -199,10 +174,7 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
return Mono.error(new RuntimeException("会员卡类型不存在"));
|
return Mono.error(new RuntimeException("会员卡类型不存在"));
|
||||||
}))
|
}))
|
||||||
.flatMap(card -> {
|
.flatMap(card -> {
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
// 发送实时进度通知
|
// 发送实时进度通知
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
MyWebSocketHandler.sendProgress(qrContent, "DEDUCT_USAGE", "正在扣减会员卡次数...");
|
MyWebSocketHandler.sendProgress(qrContent, "DEDUCT_USAGE", "正在扣减会员卡次数...");
|
||||||
|
|
||||||
return deductCardUsage(cardRecord, card)
|
return deductCardUsage(cardRecord, card)
|
||||||
@@ -223,12 +195,9 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* 验证预约信息
|
* 验证预约信息
|
||||||
*/
|
*/
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
private Mono<Void> validateBooking(Long memberId, LocalDateTime now) {
|
private Mono<Void> validateBooking(Long memberId, LocalDateTime now) {
|
||||||
return groupCourseBookingService.getBookingsByMemberId(memberId)
|
return groupCourseBookingService.getBookingsByMemberId(memberId)
|
||||||
.filter(booking -> {
|
.filter(booking -> {
|
||||||
@@ -260,12 +229,9 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* 扣减会员卡使用次数/金额
|
* 扣减会员卡使用次数/金额
|
||||||
*/
|
*/
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
private Mono<MemberCardRecord> deductCardUsage(MemberCardRecord record, MemberCard card) {
|
private Mono<MemberCardRecord> deductCardUsage(MemberCardRecord record, MemberCard card) {
|
||||||
MemberCardType cardType = MemberCardType.valueOf(card.getMemberCardType());
|
MemberCardType cardType = MemberCardType.valueOf(card.getMemberCardType());
|
||||||
LocalDateTime now = LocalDateTime.now();
|
LocalDateTime now = LocalDateTime.now();
|
||||||
@@ -301,12 +267,9 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* 保存签到记录
|
* 保存签到记录
|
||||||
*/
|
*/
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
private Mono<Void> saveSignInRecord(Long memberId, Long memberCardRecordId, Long memberCardId) {
|
private Mono<Void> saveSignInRecord(Long memberId, Long memberCardRecordId, Long memberCardId) {
|
||||||
SignInRecord record = SignInRecord.builder()
|
SignInRecord record = SignInRecord.builder()
|
||||||
.memberId(memberId)
|
.memberId(memberId)
|
||||||
@@ -321,12 +284,9 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
return signInRecordRepository.save(record).then();
|
return signInRecordRepository.save(record).then();
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* 构建成功响应
|
* 构建成功响应
|
||||||
*/
|
*/
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
private String buildSuccessResponse(LocalDateTime dateTime) {
|
private String buildSuccessResponse(LocalDateTime dateTime) {
|
||||||
Map<String, Object> res = new HashMap<>();
|
Map<String, Object> res = new HashMap<>();
|
||||||
res.put("message", "签到成功");
|
res.put("message", "签到成功");
|
||||||
@@ -334,12 +294,9 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
return JSONUtil.toJsonStr(res);
|
return JSONUtil.toJsonStr(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* 查找会员的有效会员卡(优先选择有效期最早到期的)
|
* 查找会员的有效会员卡(优先选择有效期最早到期的)
|
||||||
*/
|
*/
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
private Mono<MemberCardRecord> findValidMemberCard(Long memberId) {
|
private Mono<MemberCardRecord> findValidMemberCard(Long memberId) {
|
||||||
return memberCardRecordRepository.findActiveCardsByMemberId(memberId)
|
return memberCardRecordRepository.findActiveCardsByMemberId(memberId)
|
||||||
.filter(record -> {
|
.filter(record -> {
|
||||||
@@ -357,11 +314,8 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
.next();
|
.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
// ==================== 签到记录管理功能 ====================
|
// ==================== 签到记录管理功能 ====================
|
||||||
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
@Override
|
@Override
|
||||||
public Flux<SignInRecordVO> getSignInRecords(Long memberId, LocalDate startTime, LocalDate endTime) {
|
public Flux<SignInRecordVO> getSignInRecords(Long memberId, LocalDate startTime, LocalDate endTime) {
|
||||||
LocalDateTime start = startTime.atStartOfDay();
|
LocalDateTime start = startTime.atStartOfDay();
|
||||||
@@ -459,12 +413,9 @@ public class CheckServiceImpl implements ICheckInService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
/**
|
/**
|
||||||
* 转换实体到VO
|
* 转换实体到VO
|
||||||
*/
|
*/
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
private SignInRecordVO convertToVO(SignInRecord record) {
|
private SignInRecordVO convertToVO(SignInRecord record) {
|
||||||
SignInRecordVO vo = new SignInRecordVO();
|
SignInRecordVO vo = new SignInRecordVO();
|
||||||
vo.setId(record.getId());
|
vo.setId(record.getId());
|
||||||
|
|||||||
-78
@@ -77,11 +77,7 @@ public class MyWebSocketHandler implements WebSocketHandler {
|
|||||||
.doOnError(e -> {
|
.doOnError(e -> {
|
||||||
log.error("接收消息出错,sessionId={}", sessionId, e);
|
log.error("接收消息出错,sessionId={}", sessionId, e);
|
||||||
})
|
})
|
||||||
<<<<<<< HEAD
|
|
||||||
.subscribe();
|
|
||||||
=======
|
|
||||||
.subscribe(); // 必须订阅,否则不会执行
|
.subscribe(); // 必须订阅,否则不会执行
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
|
|
||||||
// 发送流给客户端
|
// 发送流给客户端
|
||||||
return session.send(sink.asFlux().map(session::textMessage))
|
return session.send(sink.asFlux().map(session::textMessage))
|
||||||
@@ -104,10 +100,7 @@ public class MyWebSocketHandler implements WebSocketHandler {
|
|||||||
* @return 是否发送成功
|
* @return 是否发送成功
|
||||||
*/
|
*/
|
||||||
public static boolean sendMessageToClient(String qrContent, String message) {
|
public static boolean sendMessageToClient(String qrContent, String message) {
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
// 先清理超时连接
|
// 先清理超时连接
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
cleanupTimeoutConnections();
|
cleanupTimeoutConnections();
|
||||||
|
|
||||||
Sinks.Many<String> sink = qrContentToSink.get(qrContent);
|
Sinks.Many<String> sink = qrContentToSink.get(qrContent);
|
||||||
@@ -137,77 +130,6 @@ public class MyWebSocketHandler implements WebSocketHandler {
|
|||||||
String progressMessage = buildMessage("PROGRESS", message);
|
String progressMessage = buildMessage("PROGRESS", message);
|
||||||
sendMessageToClient(qrContent, progressMessage);
|
sendMessageToClient(qrContent, progressMessage);
|
||||||
log.debug("发送进度消息: qrContent={}, step={}, message={}", qrContent, step, message);
|
log.debug("发送进度消息: qrContent={}, step={}, message={}", qrContent, step, message);
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送签到成功消息
|
|
||||||
*
|
|
||||||
* @param qrContent 二维码内容
|
|
||||||
* @param memberId 会员ID
|
|
||||||
* @param signInTime 签到时间
|
|
||||||
*/
|
|
||||||
public static void sendSuccess(String qrContent, Long memberId, String signInTime) {
|
|
||||||
String successMessage = buildMessage("SUCCESS", "签到成功!欢迎光临\n会员ID: " + memberId + "\n签到时间: " + signInTime);
|
|
||||||
sendMessageToClient(qrContent, successMessage);
|
|
||||||
log.info("发送成功消息: qrContent={}, memberId={}", qrContent, memberId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送签到失败消息
|
|
||||||
*
|
|
||||||
* @param qrContent 二维码内容
|
|
||||||
* @param reason 失败原因
|
|
||||||
*/
|
|
||||||
public static void sendFailure(String qrContent, String reason) {
|
|
||||||
String failureMessage = buildMessage("FAILURE", "签到失败:" + reason);
|
|
||||||
sendMessageToClient(qrContent, failureMessage);
|
|
||||||
log.warn("发送失败消息: qrContent={}, reason={}", qrContent, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建标准消息格式
|
|
||||||
*
|
|
||||||
* @param type 消息类型
|
|
||||||
* @param content 消息内容
|
|
||||||
* @return 格式化后的消息字符串
|
|
||||||
*/
|
|
||||||
private static String buildMessage(String type, String content) {
|
|
||||||
return JSONUtil.toJsonStr(Map.of(
|
|
||||||
"type", type,
|
|
||||||
"content", content,
|
|
||||||
"timestamp", System.currentTimeMillis()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 清理超时连接
|
|
||||||
*/
|
|
||||||
private static void cleanupTimeoutConnections() {
|
|
||||||
LocalDateTime now = LocalDateTime.now();
|
|
||||||
qrContentToCreateTime.entrySet().removeIf(entry -> {
|
|
||||||
LocalDateTime createTime = entry.getValue();
|
|
||||||
long secondsDiff = java.time.Duration.between(createTime, now).getSeconds();
|
|
||||||
if (secondsDiff > TIMEOUT_SECONDS) {
|
|
||||||
String qrContent = entry.getKey();
|
|
||||||
qrContentToSink.remove(qrContent);
|
|
||||||
log.debug("清理超时连接: qrContent={}, 超时时间={}秒", qrContent, secondsDiff);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取当前连接数
|
|
||||||
*
|
|
||||||
* @return 连接数
|
|
||||||
*/
|
|
||||||
public static int getConnectionCount() {
|
|
||||||
cleanupTimeoutConnections();
|
|
||||||
return qrContentToSink.size();
|
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
-3
@@ -25,10 +25,7 @@ import reactor.test.StepVerifier;
|
|||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
>>>>>>> f52451d (feat: 添加签到模块和数据库表结构)
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,12 @@
|
|||||||
<artifactId>javase</artifactId>
|
<artifactId>javase</artifactId>
|
||||||
<version>3.5.3</version>
|
<version>3.5.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- 阿里云OSS SDK -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun.oss</groupId>
|
||||||
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
|
<version>3.17.4</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
package cn.novalon.gym.manage.groupcourse.util;
|
package cn.novalon.gym.manage.groupcourse.util;
|
||||||
|
|
||||||
//import com.aliyun.oss.OSS;
|
import com.aliyun.oss.OSS;
|
||||||
//import com.aliyun.oss.OSSClientBuilder;
|
import com.aliyun.oss.OSSClientBuilder;
|
||||||
//import com.aliyun.oss.model.PutObjectRequest;
|
import com.aliyun.oss.model.PutObjectRequest;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|||||||
-3
@@ -61,7 +61,6 @@ public final class RedisKeyConstants {
|
|||||||
* appType: miniapp(小程序), mp(公众号)
|
* appType: miniapp(小程序), mp(公众号)
|
||||||
*/
|
*/
|
||||||
public static final String WECHAT_ACCESS_TOKEN = "wechat:access_token:";
|
public static final String WECHAT_ACCESS_TOKEN = "wechat:access_token:";
|
||||||
<<<<<<< HEAD
|
|
||||||
|
|
||||||
// ==================== 认证模块 ====================
|
// ==================== 认证模块 ====================
|
||||||
|
|
||||||
@@ -71,6 +70,4 @@ public final class RedisKeyConstants {
|
|||||||
* 用途:存储登录/注册等场景的短信验证码
|
* 用途:存储登录/注册等场景的短信验证码
|
||||||
*/
|
*/
|
||||||
public static final String SMS_CODE = "sms:code:";
|
public static final String SMS_CODE = "sms:code:";
|
||||||
=======
|
|
||||||
>>>>>>> 08cf82a (签到模块)
|
|
||||||
}
|
}
|
||||||
Binary file not shown.
+5
-5
@@ -1,4 +1,4 @@
|
|||||||
package cn.novalon.gym.manage.sys.config;
|
package cn.novalon.gym.manage.sys.config;
|
||||||
|
|
||||||
import cn.novalon.gym.manage.sys.audit.OperationLogWebFilter;
|
import cn.novalon.gym.manage.sys.audit.OperationLogWebFilter;
|
||||||
import cn.novalon.gym.manage.sys.security.JwtAuthenticationFilter;
|
import cn.novalon.gym.manage.sys.security.JwtAuthenticationFilter;
|
||||||
@@ -21,7 +21,7 @@ public class SecurityConfig {
|
|||||||
private final OperationLogWebFilter operationLogWebFilter;
|
private final OperationLogWebFilter operationLogWebFilter;
|
||||||
private final Environment environment;
|
private final Environment environment;
|
||||||
|
|
||||||
public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter,
|
public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter,
|
||||||
OperationLogWebFilter operationLogWebFilter,
|
OperationLogWebFilter operationLogWebFilter,
|
||||||
Environment environment) {
|
Environment environment) {
|
||||||
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
|
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
|
||||||
@@ -33,11 +33,11 @@ public class SecurityConfig {
|
|||||||
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
||||||
String[] activeProfiles = environment.getActiveProfiles();
|
String[] activeProfiles = environment.getActiveProfiles();
|
||||||
final boolean isDevOrTest;
|
final boolean isDevOrTest;
|
||||||
|
|
||||||
isDevOrTest = java.util.Arrays.stream(activeProfiles)
|
isDevOrTest = java.util.Arrays.stream(activeProfiles)
|
||||||
.anyMatch(profile -> "dev".equals(profile) || "test".equals(profile) || "h2-test".equals(profile));
|
.anyMatch(profile -> "dev".equals(profile) || "test".equals(profile) || "h2-test".equals(profile));
|
||||||
|
|
||||||
logger.info("SecurityConfig初始化: 当前环境={}, Swagger启用状态={}",
|
logger.info("SecurityConfig初始化: 当前环境={}, Swagger启用状态={}",
|
||||||
activeProfiles.length > 0 ? String.join(",", activeProfiles) : "default", isDevOrTest);
|
activeProfiles.length > 0 ? String.join(",", activeProfiles) : "default", isDevOrTest);
|
||||||
|
|
||||||
http
|
http
|
||||||
|
|||||||
Reference in New Issue
Block a user