blob: 99675914f9ddc81c7e724f100c74b959c1432736 [file] [log] [blame]
package com.example.myproject.service;
import cn.dev33.satoken.stp.StpUtil;
import com.example.myproject.entity.FriendRelation;
import com.example.myproject.entity.User;
import com.example.myproject.entity.Users;
import com.example.myproject.entity.UserInviteCode;
import com.example.myproject.repository.FriendRelationRepository;
import com.example.myproject.repository.LoginLogRepository;
import com.example.myproject.repository.UserRepository;
import com.example.myproject.repository.UserInviteCodeRepository;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserInviteCodeRepository userInviteCodeRepository;
@Autowired
private FriendRelationRepository friendRelationRepository;
private final LoginLogRepository loginLogRepository;
// public UserService(LoginLogRepository loginLogRepository) {
// this.loginLogRepository = loginLogRepository;
// }
// 生成邀请码
public Map<String, Object> generateInviteCode(Long userId) {
// 获取用户信息
Users user = userRepository.findById(userId).orElse(null);
// 如果用户不存在,返回错误
if (user == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("status", "failure");
errorResponse.put("message", "用户不存在");
return errorResponse;
}
// 检查用户的邀请数量
if (user.getInviteCount() <= 0) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("status", "failure");
errorResponse.put("message", "没有剩余的邀请码");
return errorResponse;
}
// 生成唯一的邀请码
String inviteCode = generateUniqueInviteCode();
// 将邀请码保存到 `user_invite_code` 表
UserInviteCode userInviteCode = new UserInviteCode();
userInviteCode.setUserId(userId);
userInviteCode.setInviteCode(inviteCode);
userInviteCode.setCreatedAt(java.time.LocalDateTime.now());
userInviteCodeRepository.save(userInviteCode);
// 更新用户的 `invite_count`,减少1
user.setInviteCount(user.getInviteCount() - 1);
userRepository.save(user);
// 返回成功信息
Map<String, Object> response = new HashMap<>();
response.put("status", "success");
response.put("message", "邀请码生成成功");
response.put("invite_code", inviteCode);
return response;
}
// 生成唯一的邀请码,使用26个字母(大小写)
private String generateUniqueInviteCode() {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
StringBuilder inviteCode = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 10; i++) {
inviteCode.append(characters.charAt(random.nextInt(characters.length())));
}
return inviteCode.toString();
}
public String registerUser(String username, String email, String password, String role, String inviteCode) {
// 检查邮箱是否已经注册
Optional<Users> existingEmailUser = userRepository.findByEmail(email);
if (existingEmailUser.isPresent()) {
return "该邮箱已被注册";
}
// 检查用户名是否已经存在
Optional<Users> existingUsernameUser = userRepository.findByUsername(username); // 需要根据用户名查询
if (existingUsernameUser.isPresent()) {
return "该用户名已被注册";
}
// 检查邀请码是否有效
if (inviteCode == null || inviteCode.isEmpty()) {
return "邀请码不能为空";
}
Optional<UserInviteCode> invite = userInviteCodeRepository.findByInviteCode(inviteCode);
if (invite.isEmpty() || invite.get().getIsUsed()) {
return "邀请码无效或已被使用";
}
// 设置默认等级为1(由于邀请码有效)
Long level = 1L;
// 设置默认头像 URL
String avatarUrl = "https://example.com/default-avatar.jpg"; // 默认头像
// 获取邀请码对应的用户ID
UserInviteCode inviteEntity = invite.get();
Long inviteUserId = inviteEntity.getUserId();
// 创建新用户
Users newUser = new Users();
newUser.setUsername(username);
newUser.setEmail(email);
newUser.setPassword(password);
newUser.setRole(role);
newUser.setInviteCount(0); // 初始邀请码数量为 0
newUser.setLevel(level);
newUser.setAvatarUrl(avatarUrl); // 设置默认头像
newUser.setRegistrationDate(new java.util.Date()); // 设置注册日期
newUser.setCurrentExperience(0); // 默认经验为 0
newUser.setCurrentSeedingHours(0f); // 默认做种时长为 0
newUser.setRegistrationTime(new java.util.Date()); // 设置注册时间为当前时间
// 保存用户信息
userRepository.save(newUser);
FriendRelation newFriendRelation = new FriendRelation();
newFriendRelation.setUserId(newUser.getUserId());
newFriendRelation.setCreateTime(new Date());
newFriendRelation.setFriendId(inviteUserId);
FriendRelation newFriendRelations = new FriendRelation();
newFriendRelations.setUserId(inviteUserId);
newFriendRelations.setCreateTime(new Date());
newFriendRelations.setFriendId(newUser.getUserId());
friendRelationRepository.save(newFriendRelation);
friendRelationRepository.save(newFriendRelations);
// 更新邀请码的使用状态
inviteEntity.setIsUsed(true);
userInviteCodeRepository.save(inviteEntity);
return "用户注册成功";
}
public String loginUser(String username, String password) {
// 检查用户是否存在
Optional<Users> userOptional = userRepository.findByUsername(username);
if (userOptional.isEmpty()) {
return "用户名不存在";
}
Users user = userOptional.get();
// 检查密码是否正确
if (!user.getPassword().equals(password)) {
return "密码错误";
}
StpUtil.login(user.getUserId());
// 登录成功
return "登录成功";
}
public String changePassword(Long userId, String oldPassword, String newPassword, String confirmPassword) {
// 查找用户
Users user = userRepository.findById(userId).orElse(null);
if (user == null) {
return "用户不存在";
}
// 检查旧密码是否正确
if (!user.getPassword().equals(oldPassword)) {
return "旧密码错误";
}
// 检查新密码和确认密码是否一致
if (!newPassword.equals(confirmPassword)) {
return "新密码与确认密码不一致";
}
// 更新密码
user.setPassword(newPassword);
userRepository.save(user);
return "密码修改成功";
}
// 获取用户个人资料
public Map<String, Object> getProfile(Long userId) {
Optional<Users> userOptional = userRepository.findById(userId);
// 如果用户不存在,返回null或者可以抛出异常
if (userOptional.isEmpty()) {
return null; // 可以返回 null 或者根据需要返回错误信息
}
Users user = userOptional.get();
// 将需要的字段放入 Map 中
Map<String, Object> profile = new LinkedHashMap<>();
profile.put("avatarUrl", user.getAvatarUrl());
profile.put("username", user.getUsername());
profile.put("email", user.getEmail());
profile.put("gender", user.getGender());
profile.put("description", user.getDescription());
profile.put("hobbies", user.getHobbies());
profile.put("level", user.getLevel());
profile.put("Experience", user.getCurrentExperience());
profile.put("uploadCount", user.getUploadCount());
profile.put("downloadCount", user.getDownloadCount());
profile.put("shareRate", user.getShareRate());
profile.put("registrationTime", user.getRegistrationTime());
return profile;
}
// 修改用户个人资料
public boolean editProfile(Long userId, String nickname, String gender, String description, String hobbies) {
Optional<Users> userOptional = userRepository.findById(userId);
// 如果用户不存在,返回false
if (userOptional.isEmpty()) {
return false; // 用户不存在
}
Users user = userOptional.get();
// 更新用户资料,只有传入值才会更新对应字段
if (nickname != null) {
user.setUsername(nickname);
}
if (gender != null) {
user.setGender(gender);
}
if (description != null) {
user.setDescription(description);
}
if (hobbies != null) {
user.setHobbies(hobbies);
}
// 保存更新后的用户信息
userRepository.save(user);
return true; // 更新成功
}
public Map<String, Object> calculateShareRate(Long userId) {
// 查找用户
Users user = userRepository.findById(userId).orElse(null);
if (user == null) {
return Map.of("status", "error", "message", "用户不存在");
}
// 获取上传量和下载量
Float uploadCount = user.getUploadCount();
Float downloadCount = user.getDownloadCount();
// 计算分享率
Float shareRate = 0f; // 默认分享率为0
if (downloadCount != 0) {
shareRate = uploadCount / downloadCount; // 分享率 = 上传量 / 下载量
}
// 更新用户的分享率
user.setShareRate(shareRate);
user.setLastupdatetime(new Date());
userRepository.save(user);
// 返回结果
return Map.of("status", "success", "message", "分享率计算成功", "shareRate", shareRate);
}
private static final String AVATAR_DIR = "uploads/avatarUrl/";
public Map<String, Object> uploadUserAvatar(Long userId, MultipartFile file) {
Users user = userRepository.findById(userId)
.orElseThrow(() -> new RuntimeException("用户不存在"));
try {
String avatarUrl = saveAvatar(file, userId);
user.setAvatarUrl(avatarUrl);
userRepository.save(user);
Map<String, Object> response = new HashMap<>();
response.put("status", "success");
response.put("message", "头像上传成功");
response.put("userId", user.getUserId());
response.put("avatarUrl", avatarUrl);
return response;
} catch (IOException e) {
throw new RuntimeException("头像上传失败: " + e.getMessage());
}
}
// 保存头像文件并返回可访问 URL
public String saveAvatar(MultipartFile file, Long userId) throws IOException {
String originalFilename = file.getOriginalFilename();
String extension = originalFilename.substring(originalFilename.lastIndexOf('.'));
String fileName = userId + extension; // 以用户ID作为文件名
Path path = Paths.get(AVATAR_DIR + fileName);
Files.createDirectories(path.getParent());
Files.write(path, file.getBytes());
return "/" + AVATAR_DIR + fileName; // 返回相对URL路径
}
@Transactional
public String checkUserShareRate(Long userId) {
Optional<Users> optionalUser = userRepository.findById(userId);
if (optionalUser.isEmpty()) {
return "用户不存在";
}
Users user = optionalUser.get();
// 检查用户是否注册超过3天
LocalDate registrationDate = user.getRegistrationTime().toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
LocalDate today = LocalDate.now();
if (today.minusDays(3).isAfter(registrationDate)) {
// 用户注册超过3天,检查分享率
// 假设我们有一个方法可以获取用户最近3天的分享率历史
boolean hasLowShareRateForThreeDays = checkShareRateHistory(userId);
if (hasLowShareRateForThreeDays) {
// 分享率连续3天低于0.5
// 检查是否已发送过警告且超过24小时
Date lastUpdateTime = user.getLastupdatetime();
if (lastUpdateTime != null) {
LocalDate warningDate = lastUpdateTime.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
if (today.minusDays(1).isAfter(warningDate)) {
// 已警告超过24小时,执行账号注销
userRepository.delete(user);
return "用户因分享率长期低于标准,账号已被注销";
}
}
// 首次发现或未超过24小时,发送警告
user.setLastupdatetime(new Date());
userRepository.save(user);
return "警告:您的分享率已连续3天低于0.5,请尽快提升,否则账号将被注销";
}
}
return "用户状态正常";
}
private boolean checkShareRateHistory(Long userId) {
Users user = userRepository.findById(userId).orElse(null);
if (user != null && user.getShareRate() < 0.5) {
// 实际应用中应查询历史记录,这里简化处理
return true;
}
return false;
}
public String recharge(Long userId, Integer amount) {
if (amount == null || amount <= 0) {
return "充值金额必须大于0";
}
Users user = userRepository.findById(userId).orElse(null);
if (user == null) {
return "用户不存在";
}
// 处理money为BigDecimal
BigDecimal currentMoney = user.getMoney() == null ? BigDecimal.ZERO : user.getMoney();
BigDecimal rechargeAmount = new BigDecimal(amount);
BigDecimal newMoney = currentMoney.add(rechargeAmount);
user.setMoney(newMoney);
userRepository.save(user);
return "充值成功,当前余额:" + user.getMoney();
}
public Users getById(Long userId) {
return userRepository.findById(userId).orElse(null);
}
/**
* 检查用户是否有连续三天的登录记录
* @param userId 用户ID
* @return 是否有连续三天的登录记录
*/
public boolean hasConsecutiveLoginDays(Long userId) {
// 获取用户的所有登录日期
List<LocalDateTime> loginDates = loginLogRepository.findDistinctLoginDates(userId);
if (loginDates.size() < 3) {
return false;
}
// 将日期转换为LocalDate并排序
List<LocalDate> dates = loginDates.stream()
.map(LocalDateTime::toLocalDate)
.distinct()
.sorted()
.toList();
// 检查是否有连续的三天
for (int i = 0; i < dates.size() - 2; i++) {
LocalDate date1 = dates.get(i);
LocalDate date2 = dates.get(i + 1);
LocalDate date3 = dates.get(i + 2);
if (date2.equals(date1.plusDays(1)) && date3.equals(date2.plusDays(1))) {
return true;
}
}
return false;
}
}