diff --git a/src/main/java/com/youlai/boot/admin/service/impl/PointManageServiceImpl.java b/src/main/java/com/youlai/boot/admin/service/impl/PointManageServiceImpl.java index fe8ee5f..a62951d 100644 --- a/src/main/java/com/youlai/boot/admin/service/impl/PointManageServiceImpl.java +++ b/src/main/java/com/youlai/boot/admin/service/impl/PointManageServiceImpl.java @@ -3,6 +3,7 @@ package com.youlai.boot.admin.service.impl; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -28,6 +29,7 @@ import com.youlai.boot.mini.service.MiniPointAccountService; import jodd.util.StringUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -138,50 +140,80 @@ public class PointManageServiceImpl extends ServiceImpl() - .eq(MiniPointAccount::getUserId, form.getUserId()) - .eq(MiniPointAccount::getDeleted, false)); - // 账户不存在自动创建,新用户第一次获得积分的时候自动初始化账户 - if (account == null) { - account = new MiniPointAccount(); - account.setUuid(IdUtil.fastSimpleUUID()); - account.setUserId(form.getUserId()); - account.setPoints(0); - account.setCreateBy(form.getUserId()); - account.setCreateTime(new Date()); - account.setCreateTimestamp(System.currentTimeMillis()); - miniPointAccountService.save(account); + int changeAmount = form.getChangeAmount(); // 调整积分值 + Long operateUserId = form.getUserId(); // 操作用户ID + boolean isDeduct = changeAmount < 0; // 是否为扣减 + int updateCount; // 更新数量 + MiniPointAccount account; + + if (isDeduct) { + // 扣减场景:原子更新+积分校验,解决并发超扣 + int deductAmount = -changeAmount; // 要扣的正数值 + updateCount = miniPointAccountMapper.update(null, new LambdaUpdateWrapper() + .eq(MiniPointAccount::getUserId, operateUserId) + .eq(MiniPointAccount::getDeleted, false) + // 核心:当前积分 >= 扣减金额,保证扣完不会为负,原子操作靠数据库行锁隔离并发 + .ge(MiniPointAccount::getPoints, deductAmount) // 当前积分 >= 扣减金额 + .setSql("points = points + " + changeAmount) + .set(MiniPointAccount::getUpdateBy, SecurityUtils.getUserId()) + .set(MiniPointAccount::getUpdateTime, new Date()) + .set(MiniPointAccount::getUpdateTimestamp, System.currentTimeMillis()) + ); + if (updateCount == 0) { + // 更新行数为0:要么账户不存在(用户从来没获得过积分=0,扣减肯定失败),要么积分不足 + throw new MsgException("积分不足,扣减后余额不能为负数"); + } + // 查询更新后的最新账户信息,用于流水记录 + account = miniPointAccountService.getOne(new LambdaQueryWrapper() + .eq(MiniPointAccount::getUserId, operateUserId) + .eq(MiniPointAccount::getDeleted, false)); + } else { + // 增加积分场景:不需要校验余额,直接原子更新,避免并发少加 + updateCount = miniPointAccountMapper.update(null, new LambdaUpdateWrapper() + .eq(MiniPointAccount::getUserId, operateUserId) + .eq(MiniPointAccount::getDeleted, false) + .setSql("points = points + " + changeAmount) + .set(MiniPointAccount::getUpdateBy, operateUserId) + .set(MiniPointAccount::getUpdateTime, new Date()) + .set(MiniPointAccount::getUpdateTimestamp, System.currentTimeMillis()) + ); + if (updateCount == 0) { + // 账户不存在,自动创建(兼容原有新用户首次获得积分自动开户逻辑) + account = new MiniPointAccount(); + account.setUuid(IdUtil.fastSimpleUUID()); + account.setUserId(operateUserId); + account.setPoints(changeAmount); // 新账户初始积分就是本次增加的 + account.setCreateBy(operateUserId); + account.setCreateTime(new Date()); + account.setCreateTimestamp(System.currentTimeMillis()); + miniPointAccountService.save(account); + } else { + // 更新成功,查询最新账户信息 + account = miniPointAccountService.getOne(new LambdaQueryWrapper() + .eq(MiniPointAccount::getUserId, operateUserId) + .eq(MiniPointAccount::getDeleted, false)); + } } - // 4. 计算变更后余额,校验不能为负数 - Integer afterBalance = account.getPoints() + form.getChangeAmount(); - if (afterBalance < 0) { - throw new MsgException("积分不足,扣减后余额不能为负数"); - } - - // 5. 更新用户积分账户余额 - MiniPointAccount updateAccount = new MiniPointAccount(); - updateAccount.setId(account.getId()); - updateAccount.setPoints(afterBalance); - updateAccount.setUpdateBy(SecurityUtils.getUserId()); - updateAccount.setUpdateTime(new Date()); - updateAccount.setUpdateTimestamp(System.currentTimeMillis()); - miniPointAccountService.updateById(updateAccount); - - // 6. 插入积分流水记录 + // 6. 插入积分流水记录(用最新查询的账户余额,保证流水和实际完全一致) MiniPointRecord record = new MiniPointRecord(); record.setUuid(IdUtil.fastSimpleUUID()); record.setUserId(account.getUserId()); - record.setChangeAmount(form.getChangeAmount()); - record.setBalanceAfter(afterBalance); + record.setChangeAmount(changeAmount); + record.setBalanceAfter(account.getPoints()); // 直接用最新的账户积分,不用自己计算,避免不一致 record.setBizType(form.getBizType()); - // 优先用传进来的业务唯一ID(比如AI任务ID),没有的话自动生成,保证幂等 + // 优先用传进来的业务唯一ID,没有的话自动生成,保证幂等 record.setBizId(StrUtil.isNotBlank(form.getBizId()) ? form.getBizId() : UUID.randomUUID().toString().replace("-", "")); - record.setCreateBy(SecurityUtils.getUserId()); + record.setCreateBy(operateUserId); record.setCreateTime(new Date()); record.setCreateTimestamp(System.currentTimeMillis()); - miniPointRecordMapper.insert(record); + try { + miniPointRecordMapper.insert(record); + } catch (DuplicateKeyException e) { + // bizId 唯一索引冲突,说明是重复请求 + log.warn("重复请求,bizId: {}", record.getBizId()); + throw new MsgException("请勿重复提交"); + } } @Override diff --git a/src/main/java/com/youlai/boot/mini/controller/MiniUserController.java b/src/main/java/com/youlai/boot/mini/controller/MiniUserController.java index a428c46..2631112 100644 --- a/src/main/java/com/youlai/boot/mini/controller/MiniUserController.java +++ b/src/main/java/com/youlai/boot/mini/controller/MiniUserController.java @@ -1,6 +1,7 @@ package com.youlai.boot.mini.controller; import com.youlai.boot.common.annotation.Log; +import com.youlai.boot.common.annotation.RepeatSubmit; import com.youlai.boot.common.enums.ActionTypeEnum; import com.youlai.boot.common.enums.LogModuleEnum; import com.youlai.boot.common.result.Result; @@ -14,6 +15,9 @@ import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; /** * C端用户信息接口 @@ -40,7 +44,7 @@ public class MiniUserController { } @Operation(summary = "修改当前登录用户基本信息") - @PostMapping(value = "/updateInfo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @PostMapping(value = "/updateInfo") @Log(module = LogModuleEnum.USER, value = ActionTypeEnum.UPDATE) public Result updateCurrentUserInfo(@Valid MiniUserUpdateForm form) { Long userId = SecurityUtils.getUserId(); @@ -48,4 +52,16 @@ public class MiniUserController { return Result.success(); } + @Operation(summary = "上传用户头像") + @PostMapping(value = "save/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @RepeatSubmit + @Log(module = LogModuleEnum.USER, value = ActionTypeEnum.UPDATE) + public Result saveFile( + @RequestPart(name = "image", required = true) MultipartFile image + ) { + Long userId = SecurityUtils.getUserId(); + miniUserService.saveFile(userId, image); + return Result.success(); + } + } diff --git a/src/main/java/com/youlai/boot/mini/controller/PointController.java b/src/main/java/com/youlai/boot/mini/controller/PointController.java index 8f77040..cbff918 100644 --- a/src/main/java/com/youlai/boot/mini/controller/PointController.java +++ b/src/main/java/com/youlai/boot/mini/controller/PointController.java @@ -8,6 +8,7 @@ import com.youlai.boot.common.result.PageResult; import com.youlai.boot.common.result.Result; import com.youlai.boot.framework.security.util.SecurityUtils; import com.youlai.boot.mini.model.query.MyPointRecordQuery; +import com.youlai.boot.mini.model.form.MiniDeductPointForm; import com.youlai.boot.mini.model.vo.MyPointRecordVO; import com.youlai.boot.mini.model.vo.MyPointVO; import com.youlai.boot.mini.model.vo.SignResultVO; @@ -18,6 +19,7 @@ import com.youlai.boot.mini.service.MiniSignService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springdoc.core.annotations.ParameterObject; import org.springframework.web.bind.annotation.*; @@ -83,13 +85,12 @@ public class PointController { return Result.success(point); } - @Operation(summary = "AI生成扣除积分") - @PostMapping("/ai-generate/deduct") - @Log(module = LogModuleEnum.OTHER, value = ActionTypeEnum.OTHER) - public Result aiGenerateImageDeduct( - @Parameter(description = "AI生成任务唯一ID(用于幂等)", required = true) @RequestParam String taskId) { + @Operation(summary = "通用扣减积分接口") + @PostMapping("/deduct") + @Log(module = LogModuleEnum.POINT_RECORD, value = ActionTypeEnum.UPDATE, title = "通用扣减积分") + public Result deductPoint(@Valid @RequestBody MiniDeductPointForm form) { Long userId = SecurityUtils.getUserId(); - Integer deductPoint = pointRecordService.deductAiGenerateImagePoint(userId, taskId); + Integer deductPoint = pointRecordService.deductPoint(userId, form.getRuleCode(), form.getBizId()); return Result.success(deductPoint); } diff --git a/src/main/java/com/youlai/boot/mini/model/form/MiniDeductPointForm.java b/src/main/java/com/youlai/boot/mini/model/form/MiniDeductPointForm.java new file mode 100644 index 0000000..91966f8 --- /dev/null +++ b/src/main/java/com/youlai/boot/mini/model/form/MiniDeductPointForm.java @@ -0,0 +1,21 @@ +package com.youlai.boot.mini.model.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import lombok.Data; + +@Data +@Schema(description = "通用扣积分请求") +public class MiniDeductPointForm { + + @Schema(description = "积分规则编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "AI_GENERATE_IMAGE") + @NotBlank(message = "规则编码不能为空") + @Size(max = 50, message = "规则编码长度不能超过50字符") + private String ruleCode; + + @Schema(description = "业务唯一ID(幂等用,确保同一次业务请求唯一)", requiredMode = Schema.RequiredMode.REQUIRED, example = "task_123456") + @NotBlank(message = "业务ID不能为空") + @Size(max = 100, message = "业务ID长度不能超过100字符") + private String bizId; +} diff --git a/src/main/java/com/youlai/boot/mini/model/form/MiniUserUpdateForm.java b/src/main/java/com/youlai/boot/mini/model/form/MiniUserUpdateForm.java index 9e2d95c..5a145dc 100644 --- a/src/main/java/com/youlai/boot/mini/model/form/MiniUserUpdateForm.java +++ b/src/main/java/com/youlai/boot/mini/model/form/MiniUserUpdateForm.java @@ -14,9 +14,6 @@ public class MiniUserUpdateForm { @Size(max = 20, message = "昵称长度不能超过20个字符") private String nickname; - @Schema(description = "头像文件") - private MultipartFile avatar; - @Schema(description = "性别:0-未知 1-男 2-女") private Integer gender; } diff --git a/src/main/java/com/youlai/boot/mini/service/MiniPointRecordService.java b/src/main/java/com/youlai/boot/mini/service/MiniPointRecordService.java index e6052a6..4fcb6de 100644 --- a/src/main/java/com/youlai/boot/mini/service/MiniPointRecordService.java +++ b/src/main/java/com/youlai/boot/mini/service/MiniPointRecordService.java @@ -8,42 +8,12 @@ import com.youlai.boot.mini.model.vo.MyPointRecordVO; public interface MiniPointRecordService extends IService { - /** - * 后台手动调整用户积分 - * @param form 调整参数 - */ -// void adjustPoint(AdjustUserPointForm form); - - /** - * 分页查询当前用户的积分流水(用户端专属) - * @param userId 当前登录用户ID,内部传参避免越权 - * @param query 用户端查询条件 - * @return 用户端积分流水分页 - */ IPage pageMyPointRecord(Long userId, MyPointRecordQuery query); - /** - * 发放分享奖励 - * @param userId 用户ID - * @return 获得的积分 - */ Integer giveShareReward(Long userId); - /** - * 登记流浪动物领取积分 - * @param userId 用户ID - * @param animalId 登记的动物ID(幂等用,防止同一动物重复领积分) - * @return 获得的积分,0表示没有获得(次数超限/已经领过) - */ Integer giveRegisterAnimalReward(Long userId, Long animalId); - /** - * AI生成图片扣除用户积分 - * @param userId 用户ID - * @param taskId AI生成任务唯一ID(幂等用,防止重复扣费) - * @return 扣除的积分值(负数),大于等于0表示扣除失败(积分不足/已经扣过) - */ - Integer deductAiGenerateImagePoint(Long userId, String taskId); - + Integer deductPoint(Long userId, String ruleCode, String bizId); } diff --git a/src/main/java/com/youlai/boot/mini/service/MiniUserService.java b/src/main/java/com/youlai/boot/mini/service/MiniUserService.java index af3b11c..88bd380 100644 --- a/src/main/java/com/youlai/boot/mini/service/MiniUserService.java +++ b/src/main/java/com/youlai/boot/mini/service/MiniUserService.java @@ -2,10 +2,15 @@ package com.youlai.boot.mini.service; import com.youlai.boot.mini.model.form.MiniUserUpdateForm; import com.youlai.boot.mini.model.vo.MiniUserInfoVO; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; public interface MiniUserService { MiniUserInfoVO getCurrentUserInfo(Long userId); void updateCurrentUserInfo(Long userId, MiniUserUpdateForm form); + + void saveFile(Long userId, MultipartFile image); } diff --git a/src/main/java/com/youlai/boot/mini/service/impl/MiniPointRecordServiceImpl.java b/src/main/java/com/youlai/boot/mini/service/impl/MiniPointRecordServiceImpl.java index 2a7e1c2..52719ff 100644 --- a/src/main/java/com/youlai/boot/mini/service/impl/MiniPointRecordServiceImpl.java +++ b/src/main/java/com/youlai/boot/mini/service/impl/MiniPointRecordServiceImpl.java @@ -19,6 +19,7 @@ import com.youlai.boot.mini.service.MiniPointAccountService; import com.youlai.boot.mini.service.MiniPointRecordService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DuplicateKeyException; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -50,17 +51,18 @@ public class MiniPointRecordServiceImpl extends ServiceImpl() - .eq(MiniPointRule::getRuleCode, ruleCode) - .eq(MiniPointRule::getStatus, false) - .last("LIMIT 1")); + .eq(MiniPointRule::getRuleCode, ruleCode) + .eq(MiniPointRule::getStatus, false) + .last("LIMIT 1")); if (rule == null || rule.getPoints() <= 0) { return new Object[]{false, 0, null, 0L, null, "活动暂未开放", true}; } @@ -117,8 +119,8 @@ public class MiniPointRecordServiceImpl extends ServiceImpl() - .eq(MiniPointRecord::getUserId, userId) - .eq(MiniPointRecord::getBizType, bizType.toUpperCase()) - .eq(MiniPointRecord::getDeleted, 0)); + .eq(MiniPointRecord::getUserId, userId) + .eq(MiniPointRecord::getBizType, bizType.toUpperCase()) + .eq(MiniPointRecord::getDeleted, 0)); } LocalDateTime startTime, endTime; switch (limitPeriod) { @@ -187,11 +189,11 @@ public class MiniPointRecordServiceImpl extends ServiceImpl() - .eq(MiniPointRecord::getUserId, userId) - .eq(MiniPointRecord::getBizType, bizType.toUpperCase()) // 和流水的biz_type保持一致 - .ge(MiniPointRecord::getCreateTime, startTime) - .le(MiniPointRecord::getCreateTime, endTime) - .eq(MiniPointRecord::getDeleted, 0)); + .eq(MiniPointRecord::getUserId, userId) + .eq(MiniPointRecord::getBizType, bizType.toUpperCase()) // 和流水的biz_type保持一致 + .ge(MiniPointRecord::getCreateTime, startTime) + .le(MiniPointRecord::getCreateTime, endTime) + .eq(MiniPointRecord::getDeleted, 0)); } @Override @@ -233,82 +235,6 @@ public class MiniPointRecordServiceImpl extends ServiceImpl() - .eq(MiniPointRecord::getBizType, "AI_GENERATE_IMAGE") - .eq(MiniPointRecord::getBizId, taskId) - .eq(MiniPointRecord::getDeleted, 0)); - alreadyDeducted = count > 0; - } - if (alreadyDeducted) { - throw new MsgException("任务已处理"); - } - - // 2. 调用通用周期校验,规则编码AI_GENERATE_IMAGE,业务前缀ai_generate_image - Object[] checkResult = checkPeriodLimit("AI_GENERATE_IMAGE", userId, "ai_generate_image"); - boolean allow = (boolean) checkResult[0]; - int deductPoint = (int) checkResult[1]; // 规则配置的扣除积分数,应该是负数 - String countKey = (String) checkResult[2]; - long expireDays = (long) checkResult[3]; - String limitPeriod = (String) checkResult[4]; - boolean redisNormal = (boolean) checkResult[6]; - - // 校验不通过(次数超限/规则未配置)或者扣除的积分>=0(规则配置错误),返回0 - if (!allow || deductPoint >= 0) { - throw new MsgException("积分规则配置错误"); - } - - // 3. 检查用户积分是否足够 - LambdaQueryWrapper pointAccountQuery = new LambdaQueryWrapper<>(); - pointAccountQuery.eq(MiniPointAccount::getUserId, userId); - pointAccountQuery.last("LIMIT 1"); - MiniPointAccount account = miniPointAccountMapper.selectOne(pointAccountQuery); - // 账户不存在积分就是0,扣除后为负说明积分不足 - if (account == null || account.getPoints() + deductPoint < 0) { - throw new MsgException("用户积分不足"); - } - - // 4. 执行扣费 - AdjustUserPointForm adjustForm = new AdjustUserPointForm(); - adjustForm.setUserId(userId); - adjustForm.setBizType("AI_GENERATE_IMAGE"); - adjustForm.setChangeAmount(deductPoint); - adjustForm.setBizId(taskId); -// adjustForm.setRemark("AI生成图片扣费,任务ID:" + taskId); - pointManageService.adjustPoint(adjustForm); - - // 5. 更新周期计数缓存 - if (countKey != null && expireDays > 0 && redisNormal) { - redisTemplate.opsForValue().increment(countKey, 1); - if ("DAY".equals(limitPeriod)) { - redisTemplate.expire(countKey, 25, TimeUnit.HOURS); - } else { - redisTemplate.expire(countKey, expireDays, TimeUnit.DAYS); - } - } - - // 6. 写入幂等标记,存1年足够 - if (redisNormal) { - redisTemplate.opsForValue().set(idempotentKey, "1", 365, TimeUnit.DAYS); - } - - return deductPoint; // 返回扣除的积分数,负数表示扣除成功 - } catch (Exception e) { - log.error("用户{}AI生成图片任务{}扣费失败", userId, taskId, e); - return 0; - } - } - @Override @Transactional(rollbackFor = Exception.class) public Integer giveRegisterAnimalReward(Long userId, Long animalId) { @@ -352,4 +278,48 @@ public class MiniPointRecordServiceImpl extends ServiceImpl() + .eq(MiniPointRecord::getBizType, ruleCode) + .eq(MiniPointRecord::getBizId, bizId) + .eq(MiniPointRecord::getDeleted, 0)); + if (existCount > 0) { + throw new MsgException("业务已处理,请勿重复请求"); + } + + // 2. 查询积分规则并校验:必须存在、启用、且是扣费项目(points < 0) + MiniPointRule rule = pointManageService.getOne(new LambdaQueryWrapper() + .eq(MiniPointRule::getRuleCode, ruleCode) + .eq(MiniPointRule::getStatus, false) // 启用状态 + .last("LIMIT 1")); + if (rule == null) { + throw new MsgException("积分规则不存在"); + } + if (rule.getPoints() >= 0) { + throw new MsgException("当前规则不是扣减类型,无法调用此接口"); + } + + // 3. 执行扣减:uk_biz_id唯一索引兜底幂等,adjustPoint内置原子积分校验,不会超扣 + AdjustUserPointForm adjustForm = new AdjustUserPointForm(); + adjustForm.setUserId(userId); + adjustForm.setBizType(ruleCode.toUpperCase()); + adjustForm.setChangeAmount(rule.getPoints()); + adjustForm.setBizId(bizId); + pointManageService.adjustPoint(adjustForm); + + return rule.getPoints(); + } catch (MsgException e) { + throw e; + } catch (DuplicateKeyException e) { + throw new MsgException("重复请求"); + } catch (Exception e) { + log.error("用户{}扣积分失败,规则:{},业务ID:{}", userId, ruleCode, bizId, e); + throw new MsgException("积分扣除失败,请重试"); + } + } + } diff --git a/src/main/java/com/youlai/boot/mini/service/impl/MiniSignServiceImpl.java b/src/main/java/com/youlai/boot/mini/service/impl/MiniSignServiceImpl.java index f212ed4..9c836b3 100644 --- a/src/main/java/com/youlai/boot/mini/service/impl/MiniSignServiceImpl.java +++ b/src/main/java/com/youlai/boot/mini/service/impl/MiniSignServiceImpl.java @@ -91,7 +91,7 @@ public class MiniSignServiceImpl extends ServiceImpl 0) { AdjustUserPointForm adjustForm = new AdjustUserPointForm(); adjustForm.setUserId(userId); - adjustForm.setBizType("SIGN_IN"); + adjustForm.setBizType("SIGN_IN_BASE"); adjustForm.setChangeAmount(totalPoint); pointManageService.adjustPoint(adjustForm); } diff --git a/src/main/java/com/youlai/boot/mini/service/impl/MiniUserServiceImpl.java b/src/main/java/com/youlai/boot/mini/service/impl/MiniUserServiceImpl.java index bb470f1..3a6daea 100644 --- a/src/main/java/com/youlai/boot/mini/service/impl/MiniUserServiceImpl.java +++ b/src/main/java/com/youlai/boot/mini/service/impl/MiniUserServiceImpl.java @@ -26,6 +26,7 @@ import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.util.Date; +import java.util.List; import java.util.UUID; /** @@ -71,6 +72,36 @@ public class MiniUserServiceImpl implements MiniUserService { @Override @Transactional(rollbackFor = Exception.class) public void updateCurrentUserInfo(Long userId, MiniUserUpdateForm form) { + if (userId == null) { + throw new MsgException("用户不存在"); + } + + SysUser sysUser = sysUserService.getById(userId); + if (sysUser == null) { + throw new MsgException("用户不存在"); + } + + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(SysUser::getId, userId); + if (StringUtils.hasText(form.getNickname())) { + updateWrapper.set(SysUser::getNickname, form.getNickname()); + } + if (form.getGender() != null) { + updateWrapper.set(SysUser::getGender, form.getGender()); + } + + boolean success = sysUserService.update(updateWrapper); + if (!success) { + throw new MsgException("用户信息更新失败,请重试"); + } + } + + @Override + public void saveFile(Long userId, MultipartFile image) { + if (userId == null) { + throw new MsgException("用户不存在"); + } + SysUser sysUser = sysUserService.getById(userId); if (sysUser == null) { throw new MsgException("用户不存在"); @@ -79,16 +110,14 @@ public class MiniUserServiceImpl implements MiniUserService { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); updateWrapper.eq(SysUser::getId, userId); - // 处理头像上传 - MultipartFile avatar = form.getAvatar(); long currentTimestamp = System.currentTimeMillis(); - if (avatar != null && !avatar.isEmpty()) { + if (image != null && !image.isEmpty()) { try { String objectName = "user_avatar/image/" + currentTimestamp + RandomNumberUtils.createRandomLowerLetterAndNumber(8) + "." - + FilenameUtils.getExtension(avatar.getOriginalFilename()); - String newAvatarUrl = aliyunFileService.uploadFile(objectName, avatar.getInputStream()); + + FilenameUtils.getExtension(image.getOriginalFilename()); + String newAvatarUrl = aliyunFileService.uploadFile(objectName, image.getInputStream()); //更新数据库头像字段 updateWrapper.set(SysUser::getAvatar, newAvatarUrl); @@ -108,19 +137,7 @@ public class MiniUserServiceImpl implements MiniUserService { throw new MsgException("头像上传失败"); } } + } - // 处理其他字段 - if (StringUtils.hasText(form.getNickname())) { - updateWrapper.set(SysUser::getNickname, form.getNickname()); - } - if (form.getGender() != null) { - updateWrapper.set(SysUser::getGender, form.getGender()); - } - // 执行更新 - boolean success = sysUserService.update(updateWrapper); - if (!success) { - throw new MsgException("用户信息更新失败,请重试"); - } - } }