Commit bed0a463f51168f11227864d98174969dd31fff9

Authored by YunaiV
1 parent 8a4ad959

✨ feat(im): 初始化表情包 v0.1:第二把 review

Showing 22 changed files with 106 additions and 112 deletions
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/face/ImFacePackController.java
... ... @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.im.controller.admin.face;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5   -import cn.iocoder.yudao.module.im.controller.admin.face.vo.ImFacePackUserRespVO;
  5 +import cn.iocoder.yudao.module.im.controller.admin.face.vo.pack.ImFacePackUserRespVO;
6 6 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
7 7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
8 8 import cn.iocoder.yudao.module.im.service.face.ImFacePackItemService;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/face/ImFaceUserItemController.java
... ... @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.im.controller.admin.face;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5   -import cn.iocoder.yudao.module.im.controller.admin.face.vo.ImFaceUserItemRespVO;
6   -import cn.iocoder.yudao.module.im.controller.admin.face.vo.ImFaceUserItemSaveReqVO;
  5 +import cn.iocoder.yudao.module.im.controller.admin.face.vo.userItem.ImFaceUserItemRespVO;
  6 +import cn.iocoder.yudao.module.im.controller.admin.face.vo.userItem.ImFaceUserItemSaveReqVO;
7 7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO;
8 8 import cn.iocoder.yudao.module.im.service.face.ImFaceUserItemService;
9 9 import io.swagger.v3.oas.annotations.Operation;
... ... @@ -30,8 +30,8 @@ public class ImFaceUserItemController {
30 30  
31 31 @GetMapping("/list")
32 32 @Operation(summary = "获得我的个人表情列表")
33   - public CommonResult<List<ImFaceUserItemRespVO>> getMyFaceUserItemList() {
34   - List<ImFaceUserItemDO> items = faceUserItemService.getMyFaceUserItemList(getLoginUserId());
  33 + public CommonResult<List<ImFaceUserItemRespVO>> getFaceUserItemList() {
  34 + List<ImFaceUserItemDO> items = faceUserItemService.getFaceUserItemList(getLoginUserId());
35 35 return success(BeanUtils.toBean(items, ImFaceUserItemRespVO.class));
36 36 }
37 37  
... ... @@ -49,13 +49,4 @@ public class ImFaceUserItemController {
49 49 return success(true);
50 50 }
51 51  
52   - // TODO @AI:个人应该没批量删除把?应该就一个一个删除呢。
53   - @DeleteMapping("/delete-list")
54   - @Operation(summary = "批量删除个人表情")
55   - @Parameter(name = "ids", description = "编号列表", required = true)
56   - public CommonResult<Boolean> deleteFaceUserItemList(@RequestParam("ids") List<Long> ids) {
57   - faceUserItemService.deleteFaceUserItemList(getLoginUserId(), ids);
58   - return success(true);
59   - }
60   -
61 52 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/face/vo/ImFacePackUserRespVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/face/vo/pack/ImFacePackUserRespVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.face.vo.pack;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/face/vo/ImFaceUserItemRespVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/face/vo/userItem/ImFaceUserItemRespVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.face.vo.userItem;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/face/vo/ImFaceUserItemSaveReqVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/face/vo/userItem/ImFaceUserItemSaveReqVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.face.vo.userItem;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import jakarta.validation.constraints.NotBlank;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/ImFacePackItemManagerController.java
... ... @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.face;
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackItemPageReqVO;
7   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackItemRespVO;
8   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackItemSaveReqVO;
  6 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item.ImFacePackItemPageReqVO;
  7 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item.ImFacePackItemRespVO;
  8 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item.ImFacePackItemSaveReqVO;
9 9 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
10 10 import cn.iocoder.yudao.module.im.service.face.ImFacePackItemService;
11 11 import io.swagger.v3.oas.annotations.Operation;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/ImFacePackManagerController.java
... ... @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.face;
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackPageReqVO;
7   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackRespVO;
8   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackSaveReqVO;
  6 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack.ImFacePackPageReqVO;
  7 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack.ImFacePackRespVO;
  8 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack.ImFacePackSaveReqVO;
9 9 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
10 10 import cn.iocoder.yudao.module.im.service.face.ImFacePackService;
11 11 import io.swagger.v3.oas.annotations.Operation;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/ImFacePackItemPageReqVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/item/ImFacePackItemPageReqVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/ImFacePackItemRespVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/item/ImFacePackItemRespVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/ImFacePackItemSaveReqVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/item/ImFacePackItemSaveReqVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import jakarta.validation.constraints.NotBlank;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/ImFacePackPageReqVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/pack/ImFacePackPageReqVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 4 import io.swagger.v3.oas.annotations.media.Schema;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/ImFacePackRespVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/pack/ImFacePackRespVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import lombok.Data;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/ImFacePackSaveReqVO.java renamed to yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/manager/face/vo/pack/ImFacePackSaveReqVO.java
1   -package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo;
  1 +package cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import jakarta.validation.constraints.NotBlank;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/face/ImFacePackItemMapper.java
... ... @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.im.dal.mysql.face;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackItemPageReqVO;
  6 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item.ImFacePackItemPageReqVO;
7 7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
8 8 import org.apache.ibatis.annotations.Mapper;
9 9  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/face/ImFacePackMapper.java
... ... @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.im.dal.mysql.face;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackPageReqVO;
  6 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack.ImFacePackPageReqVO;
7 7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
8 8 import org.apache.ibatis.annotations.Mapper;
9 9  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/face/ImFacePackItemService.java
1 1 package cn.iocoder.yudao.module.im.service.face;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackItemPageReqVO;
5   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackItemSaveReqVO;
  4 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item.ImFacePackItemPageReqVO;
  5 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item.ImFacePackItemSaveReqVO;
6 6 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
7 7 import jakarta.validation.Valid;
8 8  
9 9 import java.util.Collection;
10 10 import java.util.List;
11 11  
  12 +// TODO @AI:已经分了用户端、和管理后台,注释上就不用写【用户端】【【管理后台】】了。。。
  13 +// TODO @AI:注释的风格,参考下别的模块,一些 params、return 都要写呀;
12 14 /**
13 15 * IM 表情包项 Service 接口
14 16 *
... ... @@ -23,6 +25,16 @@ public interface ImFacePackItemService {
23 25 */
24 26 List<ImFacePackItemDO> getEnabledItemListByPackIds(Collection<Long> packIds);
25 27  
  28 + /**
  29 + * 取某个表情包下的表情数量;ImFacePackService 删除前校验「包下无项」用
  30 + */
  31 + Long getFacePackItemCount(Long packId);
  32 +
  33 + /**
  34 + * 取多个表情包下的表情数量合计;ImFacePackService 批量删除前校验用
  35 + */
  36 + Long getFacePackItemCount(Collection<Long> packIds);
  37 +
26 38 // ==================== 管理后台 ====================
27 39  
28 40 /**
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/face/ImFacePackItemServiceImpl.java
... ... @@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil;
4 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackItemPageReqVO;
8   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackItemSaveReqVO;
  7 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item.ImFacePackItemPageReqVO;
  8 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.item.ImFacePackItemSaveReqVO;
9 9 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
10 10 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFacePackItemMapper;
11 11 import jakarta.annotation.Resource;
... ... @@ -43,6 +43,19 @@ public class ImFacePackItemServiceImpl implements ImFacePackItemService {
43 43 return facePackItemMapper.selectListByPackIdsAndStatus(packIds, CommonStatusEnum.ENABLE.getStatus());
44 44 }
45 45  
  46 + @Override
  47 + public Long getFacePackItemCount(Long packId) {
  48 + return facePackItemMapper.selectCountByPackId(packId);
  49 + }
  50 +
  51 + @Override
  52 + public Long getFacePackItemCount(Collection<Long> packIds) {
  53 + if (CollUtil.isEmpty(packIds)) {
  54 + return 0L;
  55 + }
  56 + return facePackItemMapper.selectCountByPackIds(packIds);
  57 + }
  58 +
46 59 // ==================== 管理后台 ====================
47 60  
48 61 @Override
... ... @@ -57,32 +70,33 @@ public class ImFacePackItemServiceImpl implements ImFacePackItemService {
57 70  
58 71 @Override
59 72 public Long createFacePackItem(ImFacePackItemSaveReqVO reqVO) {
60   - // 校验所属表情包存在
  73 + // 1. 校验所属表情包存在
61 74 facePackService.validateFacePackExists(reqVO.getPackId());
62   - ImFacePackItemDO item = BeanUtils.toBean(reqVO, ImFacePackItemDO.class);
63 75  
64   - // TODO @AI:注释风格,和别的模块一致
  76 + // 2. 入库
  77 + ImFacePackItemDO item = BeanUtils.toBean(reqVO, ImFacePackItemDO.class);
65 78 facePackItemMapper.insert(item);
66 79 return item.getId();
67 80 }
68 81  
69 82 @Override
70 83 public void updateFacePackItem(ImFacePackItemSaveReqVO reqVO) {
71   - // TODO @AI:注释风格,和别的模块一致
  84 + // 1.1 校验存在
72 85 validateFacePackItemExists(reqVO.getId());
73   - // TODO @AI:注释风格,和别的模块一致
  86 + // 1.2 校验所属表情包存在
74 87 facePackService.validateFacePackExists(reqVO.getPackId());
75 88  
76   - // TODO @AI:注释风格,和别的模块一致
  89 + // 2. 更新
77 90 ImFacePackItemDO updateObj = BeanUtils.toBean(reqVO, ImFacePackItemDO.class);
78 91 facePackItemMapper.updateById(updateObj);
79 92 }
80 93  
81 94 @Override
82 95 public void deleteFacePackItem(Long id) {
83   - // TODO @AI:注释风格,和别的模块一致
  96 + // 1. 校验存在
84 97 validateFacePackItemExists(id);
85   - // TODO @AI:注释风格,和别的模块一致
  98 +
  99 + // 2. 删除
86 100 facePackItemMapper.deleteById(id);
87 101 }
88 102  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/face/ImFacePackService.java
1 1 package cn.iocoder.yudao.module.im.service.face;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackPageReqVO;
5   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackSaveReqVO;
  4 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack.ImFacePackPageReqVO;
  5 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack.ImFacePackSaveReqVO;
6 6 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
7 7 import jakarta.validation.Valid;
8 8  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/face/ImFacePackServiceImpl.java
... ... @@ -4,12 +4,12 @@ import cn.hutool.core.collection.CollUtil;
4 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackPageReqVO;
8   -import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.ImFacePackSaveReqVO;
  7 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack.ImFacePackPageReqVO;
  8 +import cn.iocoder.yudao.module.im.controller.admin.manager.face.vo.pack.ImFacePackSaveReqVO;
9 9 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
10   -import cn.iocoder.yudao.module.im.dal.mysql.face.ImFacePackItemMapper;
11 10 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFacePackMapper;
12 11 import jakarta.annotation.Resource;
  12 +import org.springframework.context.annotation.Lazy;
13 13 import org.springframework.stereotype.Service;
14 14 import org.springframework.validation.annotation.Validated;
15 15  
... ... @@ -31,9 +31,12 @@ public class ImFacePackServiceImpl implements ImFacePackService {
31 31 @Resource
32 32 private ImFacePackMapper facePackMapper;
33 33  
34   - // TODO @AI:跨模块操作,需要调用对方 service;
  34 + /**
  35 + * @Lazy 解决与 ImFacePackItemServiceImpl 的循环依赖(item.create / update 校验所属包存在 → 反向调用本类)
  36 + */
35 37 @Resource
36   - private ImFacePackItemMapper facePackItemMapper;
  38 + @Lazy
  39 + private ImFacePackItemService facePackItemService;
37 40  
38 41 // ==================== 用户端 ====================
39 42  
... ... @@ -72,10 +75,10 @@ public class ImFacePackServiceImpl implements ImFacePackService {
72 75  
73 76 @Override
74 77 public void updateFacePack(ImFacePackSaveReqVO reqVO) {
75   - // TODO @AI:注释,参考别的模块
  78 + // 1. 校验存在
76 79 validateFacePackExists(reqVO.getId());
77 80  
78   - // TODO @AI:注释,参考别的模块
  81 + // 2. 更新
79 82 ImFacePackDO updateObj = BeanUtils.toBean(reqVO, ImFacePackDO.class);
80 83 facePackMapper.updateById(updateObj);
81 84 }
... ... @@ -85,7 +88,7 @@ public class ImFacePackServiceImpl implements ImFacePackService {
85 88 // 1.1 校验存在
86 89 validateFacePackExists(id);
87 90 // 1.2 校验表情包下没有表情;防止误删表情包导致历史 face 消息无法回查归属
88   - if (facePackItemMapper.selectCountByPackId(id) > 0) {
  91 + if (facePackItemService.getFacePackItemCount(id) > 0) {
89 92 throw exception(FACE_PACK_HAS_ITEMS);
90 93 }
91 94  
... ... @@ -95,15 +98,15 @@ public class ImFacePackServiceImpl implements ImFacePackService {
95 98  
96 99 @Override
97 100 public void deleteFacePackList(List<Long> ids) {
  101 + // 1. 任一存在表情则拒绝整批删除,避免「只删一半」的中间态
98 102 if (CollUtil.isEmpty(ids)) {
99 103 return;
100 104 }
101   - // 任一存在表情则拒绝整批删除,避免「只删一半」的中间态
102   - if (facePackItemMapper.selectCountByPackIds(ids) > 0) {
  105 + if (facePackItemService.getFacePackItemCount(ids) > 0) {
103 106 throw exception(FACE_PACK_HAS_ITEMS);
104 107 }
105 108  
106   - // 执行删除
  109 + // 2. 删除
107 110 facePackMapper.deleteByIds(ids);
108 111 }
109 112  
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/face/ImFaceUserItemService.java
1 1 package cn.iocoder.yudao.module.im.service.face;
2 2  
3   -import cn.iocoder.yudao.module.im.controller.admin.face.vo.ImFaceUserItemSaveReqVO;
  3 +import cn.iocoder.yudao.module.im.controller.admin.face.vo.userItem.ImFaceUserItemSaveReqVO;
4 4 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO;
5 5 import jakarta.validation.Valid;
6 6  
... ... @@ -14,25 +14,20 @@ import java.util.List;
14 14 public interface ImFaceUserItemService {
15 15  
16 16 /**
17   - * 获取我的个人表情列表
  17 + * 获取指定用户的个人表情列表
18 18 */
19   - List<ImFaceUserItemDO> getMyFaceUserItemList(Long userId);
  19 + List<ImFaceUserItemDO> getFaceUserItemList(Long userId);
20 20  
21 21 /**
22   - * 添加个人表情;返回新增 id(已存在则直接返回旧 id)
  22 + * 添加个人表情;返回新增记录 id
23 23 * <p>
24   - * 同 URL 重复添加时返回旧记录 id,不报错
  24 + * 同 URL 重复添加抛 FACE_USER_ITEM_DUPLICATED;表上 (user_id, url) 唯一约束兜底并发 race
25 25 */
26 26 Long createFaceUserItem(Long userId, @Valid ImFaceUserItemSaveReqVO reqVO);
27 27  
28 28 /**
29   - * 删除我的某条个人表情
  29 + * 删除指定用户的某条个人表情
30 30 */
31 31 void deleteFaceUserItem(Long userId, Long id);
32 32  
33   - /**
34   - * 批量删除我的个人表情
35   - */
36   - void deleteFaceUserItemList(Long userId, List<Long> ids);
37   -
38 33 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/face/ImFaceUserItemServiceImpl.java
1 1 package cn.iocoder.yudao.module.im.service.face;
2 2  
3   -import cn.hutool.core.collection.CollUtil;
  3 +import cn.hutool.core.util.ObjectUtil;
4 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5   -import cn.iocoder.yudao.module.im.controller.admin.face.vo.ImFaceUserItemSaveReqVO;
  5 +import cn.iocoder.yudao.module.im.controller.admin.face.vo.userItem.ImFaceUserItemSaveReqVO;
6 6 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO;
7 7 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFaceUserItemMapper;
8 8 import jakarta.annotation.Resource;
  9 +import org.springframework.dao.DuplicateKeyException;
9 10 import org.springframework.stereotype.Service;
10 11 import org.springframework.validation.annotation.Validated;
11 12  
12 13 import java.util.List;
13 14  
14 15 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  16 +import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FACE_USER_ITEM_DUPLICATED;
15 17 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FACE_USER_ITEM_NOT_EXISTS;
16 18 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FACE_USER_ITEM_NOT_OWN;
17 19  
... ... @@ -27,66 +29,44 @@ public class ImFaceUserItemServiceImpl implements ImFaceUserItemService {
27 29 @Resource
28 30 private ImFaceUserItemMapper faceUserItemMapper;
29 31  
30   - // TODO @AI:传递了 userid,就不用写 myXXX 了;
31 32 @Override
32   - public List<ImFaceUserItemDO> getMyFaceUserItemList(Long userId) {
  33 + public List<ImFaceUserItemDO> getFaceUserItemList(Long userId) {
33 34 return faceUserItemMapper.selectListByUserId(userId);
34 35 }
35 36  
36 37 @Override
37 38 public Long createFaceUserItem(Long userId, ImFaceUserItemSaveReqVO reqVO) {
38   - // 1. 同 URL 已添加:直接返回旧 id;避免一张图反复添加占额度,并保证「添加到表情」幂等
39   - // TODO @AI:是不是提示下,已经有这个标签库了。。。
40   - ImFaceUserItemDO exist = faceUserItemMapper.selectByUserIdAndUrl(userId, reqVO.getUrl());
41   - if (exist != null) {
42   - return exist.getId();
  39 + // 1. 同 URL 已存在则报错;前端 catch 后 toast「已添加过」
  40 + if (faceUserItemMapper.selectByUserIdAndUrl(userId, reqVO.getUrl()) != null) {
  41 + throw exception(FACE_USER_ITEM_DUPLICATED);
43 42 }
44 43  
45   - // 2. 入库
46   - // TODO @AI:链式调用
47   - ImFaceUserItemDO item = BeanUtils.toBean(reqVO, ImFaceUserItemDO.class);
48   - item.setUserId(userId);
49   - item.setSort(0);
50   - faceUserItemMapper.insert(item);
  44 + // 2. 入库;表 (user_id, url, tenant_id) 唯一约束兜底并发 race —— 两个请求同时过 step 1 时 DB 拦截
  45 + // TODO @AI:不加唯一索引。不然删除后恢复麻烦。按照我说的来。
  46 + ImFaceUserItemDO item = BeanUtils.toBean(reqVO, ImFaceUserItemDO.class)
  47 + .setUserId(userId);
  48 + try {
  49 + faceUserItemMapper.insert(item);
  50 + } catch (DuplicateKeyException ignored) {
  51 + throw exception(FACE_USER_ITEM_DUPLICATED);
  52 + }
51 53 return item.getId();
52 54 }
53 55  
54 56 @Override
55 57 public void deleteFaceUserItem(Long userId, Long id) {
  58 + // 1.1 校验存在
56 59 ImFaceUserItemDO item = faceUserItemMapper.selectById(id);
57 60 if (item == null) {
58 61 throw exception(FACE_USER_ITEM_NOT_EXISTS);
59 62 }
60   - // 防止 A 用户传 B 用户的表情 id 删除别人的表情
61   - // TODO @AI:notEquals;
62   - if (!item.getUserId().equals(userId)) {
  63 + // 1.2 校验归属:防止 A 用户传 B 用户的表情 id 删别人的
  64 + if (ObjectUtil.notEqual(item.getUserId(), userId)) {
63 65 throw exception(FACE_USER_ITEM_NOT_OWN);
64 66 }
65 67  
66   - // TODO @AI:注释
  68 + // 2. 删除
67 69 faceUserItemMapper.deleteById(id);
68 70 }
69 71  
70   - @Override
71   - public void deleteFaceUserItemList(Long userId, List<Long> ids) {
72   - if (CollUtil.isEmpty(ids)) {
73   - return;
74   - }
75   - // 一次性查全部待删项;任一不属于当前用户则整批拒绝
76   - // TODO @AI:过滤掉,不属于自己的;
77   - List<ImFaceUserItemDO> items = faceUserItemMapper.selectByIds(ids);
78   - // TODO @AI:不存在的,直接跳过;
79   - if (CollUtil.size(items) != CollUtil.size(ids)) {
80   - throw exception(FACE_USER_ITEM_NOT_EXISTS);
81   - }
82   - for (ImFaceUserItemDO item : items) {
83   - if (!item.getUserId().equals(userId)) {
84   - throw exception(FACE_USER_ITEM_NOT_OWN);
85   - }
86   - }
87   -
88   - // TODO @AI:注释
89   - faceUserItemMapper.deleteByIds(ids);
90   - }
91   -
92 72 }
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/websocket/dto/message/FaceMessage.java
... ... @@ -14,15 +14,14 @@ public class FaceMessage {
14 14 * 表情图 URL
15 15 */
16 16 private String url;
17   - // TODO @AI:openim 有这个字段么?不是一般 url 就足够了呀。
18 17 /**
19   - * 渲染宽度(像素)
  18 + * 渲染宽度(像素,可选)
20 19 * <p>
21   - * 客户端渲染时按此尺寸占位,避免图片加载完成后的布局抖动
  20 + * 客户端渲染时按此尺寸占位,避免图片加载完成后的布局抖动;缺失时由客户端 CSS max-width 兜底
22 21 */
23 22 private Integer width;
24 23 /**
25   - * 渲染高度(像素)
  24 + * 渲染高度(像素,可选)
26 25 */
27 26 private Integer height;
28 27 /**
... ...