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,7 +2,7 @@ package cn.iocoder.yudao.module.im.controller.admin.face;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO; 6 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO; 7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
8 import cn.iocoder.yudao.module.im.service.face.ImFacePackItemService; 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,8 +2,8 @@ package cn.iocoder.yudao.module.im.controller.admin.face;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO; 7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO;
8 import cn.iocoder.yudao.module.im.service.face.ImFaceUserItemService; 8 import cn.iocoder.yudao.module.im.service.face.ImFaceUserItemService;
9 import io.swagger.v3.oas.annotations.Operation; 9 import io.swagger.v3.oas.annotations.Operation;
@@ -30,8 +30,8 @@ public class ImFaceUserItemController { @@ -30,8 +30,8 @@ public class ImFaceUserItemController {
30 30
31 @GetMapping("/list") 31 @GetMapping("/list")
32 @Operation(summary = "获得我的个人表情列表") 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 return success(BeanUtils.toBean(items, ImFaceUserItemRespVO.class)); 35 return success(BeanUtils.toBean(items, ImFaceUserItemRespVO.class));
36 } 36 }
37 37
@@ -49,13 +49,4 @@ public class ImFaceUserItemController { @@ -49,13 +49,4 @@ public class ImFaceUserItemController {
49 return success(true); 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 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 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 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 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 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import jakarta.validation.constraints.NotBlank; 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,9 +3,9 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.face;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO; 9 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
10 import cn.iocoder.yudao.module.im.service.face.ImFacePackItemService; 10 import cn.iocoder.yudao.module.im.service.face.ImFacePackItemService;
11 import io.swagger.v3.oas.annotations.Operation; 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,9 +3,9 @@ package cn.iocoder.yudao.module.im.controller.admin.manager.face;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO; 9 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
10 import cn.iocoder.yudao.module.im.service.face.ImFacePackService; 10 import cn.iocoder.yudao.module.im.service.face.ImFacePackService;
11 import io.swagger.v3.oas.annotations.Operation; 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 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 import io.swagger.v3.oas.annotations.media.Schema; 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 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 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 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import jakarta.validation.constraints.NotBlank; 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 import cn.iocoder.yudao.framework.common.pojo.PageParam; 3 import cn.iocoder.yudao.framework.common.pojo.PageParam;
4 import io.swagger.v3.oas.annotations.media.Schema; 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 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.Data; 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 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import jakarta.validation.constraints.NotBlank; 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,7 +3,7 @@ package cn.iocoder.yudao.module.im.dal.mysql.face;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO; 7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
8 import org.apache.ibatis.annotations.Mapper; 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,7 +3,7 @@ package cn.iocoder.yudao.module.im.dal.mysql.face;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO; 7 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
8 import org.apache.ibatis.annotations.Mapper; 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 package cn.iocoder.yudao.module.im.service.face; 1 package cn.iocoder.yudao.module.im.service.face;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO; 6 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
7 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
8 8
9 import java.util.Collection; 9 import java.util.Collection;
10 import java.util.List; 10 import java.util.List;
11 11
  12 +// TODO @AI:已经分了用户端、和管理后台,注释上就不用写【用户端】【【管理后台】】了。。。
  13 +// TODO @AI:注释的风格,参考下别的模块,一些 params、return 都要写呀;
12 /** 14 /**
13 * IM 表情包项 Service 接口 15 * IM 表情包项 Service 接口
14 * 16 *
@@ -23,6 +25,16 @@ public interface ImFacePackItemService { @@ -23,6 +25,16 @@ public interface ImFacePackItemService {
23 */ 25 */
24 List<ImFacePackItemDO> getEnabledItemListByPackIds(Collection<Long> packIds); 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,8 +4,8 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO; 9 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackItemDO;
10 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFacePackItemMapper; 10 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFacePackItemMapper;
11 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
@@ -43,6 +43,19 @@ public class ImFacePackItemServiceImpl implements ImFacePackItemService { @@ -43,6 +43,19 @@ public class ImFacePackItemServiceImpl implements ImFacePackItemService {
43 return facePackItemMapper.selectListByPackIdsAndStatus(packIds, CommonStatusEnum.ENABLE.getStatus()); 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 @Override 61 @Override
@@ -57,32 +70,33 @@ public class ImFacePackItemServiceImpl implements ImFacePackItemService { @@ -57,32 +70,33 @@ public class ImFacePackItemServiceImpl implements ImFacePackItemService {
57 70
58 @Override 71 @Override
59 public Long createFacePackItem(ImFacePackItemSaveReqVO reqVO) { 72 public Long createFacePackItem(ImFacePackItemSaveReqVO reqVO) {
60 - // 校验所属表情包存在 73 + // 1. 校验所属表情包存在
61 facePackService.validateFacePackExists(reqVO.getPackId()); 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 facePackItemMapper.insert(item); 78 facePackItemMapper.insert(item);
66 return item.getId(); 79 return item.getId();
67 } 80 }
68 81
69 @Override 82 @Override
70 public void updateFacePackItem(ImFacePackItemSaveReqVO reqVO) { 83 public void updateFacePackItem(ImFacePackItemSaveReqVO reqVO) {
71 - // TODO @AI:注释风格,和别的模块一致 84 + // 1.1 校验存在
72 validateFacePackItemExists(reqVO.getId()); 85 validateFacePackItemExists(reqVO.getId());
73 - // TODO @AI:注释风格,和别的模块一致 86 + // 1.2 校验所属表情包存在
74 facePackService.validateFacePackExists(reqVO.getPackId()); 87 facePackService.validateFacePackExists(reqVO.getPackId());
75 88
76 - // TODO @AI:注释风格,和别的模块一致 89 + // 2. 更新
77 ImFacePackItemDO updateObj = BeanUtils.toBean(reqVO, ImFacePackItemDO.class); 90 ImFacePackItemDO updateObj = BeanUtils.toBean(reqVO, ImFacePackItemDO.class);
78 facePackItemMapper.updateById(updateObj); 91 facePackItemMapper.updateById(updateObj);
79 } 92 }
80 93
81 @Override 94 @Override
82 public void deleteFacePackItem(Long id) { 95 public void deleteFacePackItem(Long id) {
83 - // TODO @AI:注释风格,和别的模块一致 96 + // 1. 校验存在
84 validateFacePackItemExists(id); 97 validateFacePackItemExists(id);
85 - // TODO @AI:注释风格,和别的模块一致 98 +
  99 + // 2. 删除
86 facePackItemMapper.deleteById(id); 100 facePackItemMapper.deleteById(id);
87 } 101 }
88 102
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/face/ImFacePackService.java
1 package cn.iocoder.yudao.module.im.service.face; 1 package cn.iocoder.yudao.module.im.service.face;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO; 6 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
7 import jakarta.validation.Valid; 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,12 +4,12 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO; 9 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFacePackDO;
10 -import cn.iocoder.yudao.module.im.dal.mysql.face.ImFacePackItemMapper;  
11 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFacePackMapper; 10 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFacePackMapper;
12 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
  12 +import org.springframework.context.annotation.Lazy;
13 import org.springframework.stereotype.Service; 13 import org.springframework.stereotype.Service;
14 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
15 15
@@ -31,9 +31,12 @@ public class ImFacePackServiceImpl implements ImFacePackService { @@ -31,9 +31,12 @@ public class ImFacePackServiceImpl implements ImFacePackService {
31 @Resource 31 @Resource
32 private ImFacePackMapper facePackMapper; 32 private ImFacePackMapper facePackMapper;
33 33
34 - // TODO @AI:跨模块操作,需要调用对方 service; 34 + /**
  35 + * @Lazy 解决与 ImFacePackItemServiceImpl 的循环依赖(item.create / update 校验所属包存在 → 反向调用本类)
  36 + */
35 @Resource 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,10 +75,10 @@ public class ImFacePackServiceImpl implements ImFacePackService {
72 75
73 @Override 76 @Override
74 public void updateFacePack(ImFacePackSaveReqVO reqVO) { 77 public void updateFacePack(ImFacePackSaveReqVO reqVO) {
75 - // TODO @AI:注释,参考别的模块 78 + // 1. 校验存在
76 validateFacePackExists(reqVO.getId()); 79 validateFacePackExists(reqVO.getId());
77 80
78 - // TODO @AI:注释,参考别的模块 81 + // 2. 更新
79 ImFacePackDO updateObj = BeanUtils.toBean(reqVO, ImFacePackDO.class); 82 ImFacePackDO updateObj = BeanUtils.toBean(reqVO, ImFacePackDO.class);
80 facePackMapper.updateById(updateObj); 83 facePackMapper.updateById(updateObj);
81 } 84 }
@@ -85,7 +88,7 @@ public class ImFacePackServiceImpl implements ImFacePackService { @@ -85,7 +88,7 @@ public class ImFacePackServiceImpl implements ImFacePackService {
85 // 1.1 校验存在 88 // 1.1 校验存在
86 validateFacePackExists(id); 89 validateFacePackExists(id);
87 // 1.2 校验表情包下没有表情;防止误删表情包导致历史 face 消息无法回查归属 90 // 1.2 校验表情包下没有表情;防止误删表情包导致历史 face 消息无法回查归属
88 - if (facePackItemMapper.selectCountByPackId(id) > 0) { 91 + if (facePackItemService.getFacePackItemCount(id) > 0) {
89 throw exception(FACE_PACK_HAS_ITEMS); 92 throw exception(FACE_PACK_HAS_ITEMS);
90 } 93 }
91 94
@@ -95,15 +98,15 @@ public class ImFacePackServiceImpl implements ImFacePackService { @@ -95,15 +98,15 @@ public class ImFacePackServiceImpl implements ImFacePackService {
95 98
96 @Override 99 @Override
97 public void deleteFacePackList(List<Long> ids) { 100 public void deleteFacePackList(List<Long> ids) {
  101 + // 1. 任一存在表情则拒绝整批删除,避免「只删一半」的中间态
98 if (CollUtil.isEmpty(ids)) { 102 if (CollUtil.isEmpty(ids)) {
99 return; 103 return;
100 } 104 }
101 - // 任一存在表情则拒绝整批删除,避免「只删一半」的中间态  
102 - if (facePackItemMapper.selectCountByPackIds(ids) > 0) { 105 + if (facePackItemService.getFacePackItemCount(ids) > 0) {
103 throw exception(FACE_PACK_HAS_ITEMS); 106 throw exception(FACE_PACK_HAS_ITEMS);
104 } 107 }
105 108
106 - // 执行删除 109 + // 2. 删除
107 facePackMapper.deleteByIds(ids); 110 facePackMapper.deleteByIds(ids);
108 } 111 }
109 112
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/face/ImFaceUserItemService.java
1 package cn.iocoder.yudao.module.im.service.face; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO; 4 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO;
5 import jakarta.validation.Valid; 5 import jakarta.validation.Valid;
6 6
@@ -14,25 +14,20 @@ import java.util.List; @@ -14,25 +14,20 @@ import java.util.List;
14 public interface ImFaceUserItemService { 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 * <p> 23 * <p>
24 - * 同 URL 重复添加时返回旧记录 id,不报错 24 + * 同 URL 重复添加抛 FACE_USER_ITEM_DUPLICATED;表上 (user_id, url) 唯一约束兜底并发 race
25 */ 25 */
26 Long createFaceUserItem(Long userId, @Valid ImFaceUserItemSaveReqVO reqVO); 26 Long createFaceUserItem(Long userId, @Valid ImFaceUserItemSaveReqVO reqVO);
27 27
28 /** 28 /**
29 - * 删除我的某条个人表情 29 + * 删除指定用户的某条个人表情
30 */ 30 */
31 void deleteFaceUserItem(Long userId, Long id); 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 package cn.iocoder.yudao.module.im.service.face; 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 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO; 6 import cn.iocoder.yudao.module.im.dal.dataobject.face.ImFaceUserItemDO;
7 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFaceUserItemMapper; 7 import cn.iocoder.yudao.module.im.dal.mysql.face.ImFaceUserItemMapper;
8 import jakarta.annotation.Resource; 8 import jakarta.annotation.Resource;
  9 +import org.springframework.dao.DuplicateKeyException;
9 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
10 import org.springframework.validation.annotation.Validated; 11 import org.springframework.validation.annotation.Validated;
11 12
12 import java.util.List; 13 import java.util.List;
13 14
14 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 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 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FACE_USER_ITEM_NOT_EXISTS; 17 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FACE_USER_ITEM_NOT_EXISTS;
16 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FACE_USER_ITEM_NOT_OWN; 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,66 +29,44 @@ public class ImFaceUserItemServiceImpl implements ImFaceUserItemService {
27 @Resource 29 @Resource
28 private ImFaceUserItemMapper faceUserItemMapper; 30 private ImFaceUserItemMapper faceUserItemMapper;
29 31
30 - // TODO @AI:传递了 userid,就不用写 myXXX 了;  
31 @Override 32 @Override
32 - public List<ImFaceUserItemDO> getMyFaceUserItemList(Long userId) { 33 + public List<ImFaceUserItemDO> getFaceUserItemList(Long userId) {
33 return faceUserItemMapper.selectListByUserId(userId); 34 return faceUserItemMapper.selectListByUserId(userId);
34 } 35 }
35 36
36 @Override 37 @Override
37 public Long createFaceUserItem(Long userId, ImFaceUserItemSaveReqVO reqVO) { 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 return item.getId(); 53 return item.getId();
52 } 54 }
53 55
54 @Override 56 @Override
55 public void deleteFaceUserItem(Long userId, Long id) { 57 public void deleteFaceUserItem(Long userId, Long id) {
  58 + // 1.1 校验存在
56 ImFaceUserItemDO item = faceUserItemMapper.selectById(id); 59 ImFaceUserItemDO item = faceUserItemMapper.selectById(id);
57 if (item == null) { 60 if (item == null) {
58 throw exception(FACE_USER_ITEM_NOT_EXISTS); 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 throw exception(FACE_USER_ITEM_NOT_OWN); 65 throw exception(FACE_USER_ITEM_NOT_OWN);
64 } 66 }
65 67
66 - // TODO @AI:注释 68 + // 2. 删除
67 faceUserItemMapper.deleteById(id); 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,15 +14,14 @@ public class FaceMessage {
14 * 表情图 URL 14 * 表情图 URL
15 */ 15 */
16 private String url; 16 private String url;
17 - // TODO @AI:openim 有这个字段么?不是一般 url 就足够了呀。  
18 /** 17 /**
19 - * 渲染宽度(像素) 18 + * 渲染宽度(像素,可选)
20 * <p> 19 * <p>
21 - * 客户端渲染时按此尺寸占位,避免图片加载完成后的布局抖动 20 + * 客户端渲染时按此尺寸占位,避免图片加载完成后的布局抖动;缺失时由客户端 CSS max-width 兜底
22 */ 21 */
23 private Integer width; 22 private Integer width;
24 /** 23 /**
25 - * 渲染高度(像素) 24 + * 渲染高度(像素,可选)
26 */ 25 */
27 private Integer height; 26 private Integer height;
28 /** 27 /**