fix(user-invite-codes): 修复字段名拼写错误并新增代理邀请码生成
修正 owenrSystemUserId → ownerSystemUserId 拼写错误; 新增 UserInviteCodeApi 及实现,为代理租户自动生成 6 位唯一邀请码。
This commit is contained in:
@@ -0,0 +1,55 @@
|
|||||||
|
package com.yolo.keyboard.api.invitecode;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import com.yolo.keyboard.dal.dataobject.userinvitecodes.KeyboardUserInviteCodesDO;
|
||||||
|
import com.yolo.keyboard.dal.mysql.userinvitecodes.KeyboardUserInviteCodesMapper;
|
||||||
|
import com.yolo.keyboard.module.system.api.invitecode.UserInviteCodeApi;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邀请码 API 实现类
|
||||||
|
*
|
||||||
|
* @author ziin
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class UserInviteCodeApiImpl implements UserInviteCodeApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private KeyboardUserInviteCodesMapper userInviteCodesMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String createInviteCodeForAgent(Long userId, Long tenantId) {
|
||||||
|
String inviteCode = generateUniqueInviteCode();
|
||||||
|
KeyboardUserInviteCodesDO inviteCodeDO = KeyboardUserInviteCodesDO.builder()
|
||||||
|
.code(inviteCode)
|
||||||
|
.ownerSystemUserId(userId)
|
||||||
|
.ownerTenantId(tenantId)
|
||||||
|
.status((short) 1)
|
||||||
|
.createdAt(LocalDateTime.now())
|
||||||
|
.usedCount(0)
|
||||||
|
.inviteType("AGENT")
|
||||||
|
.build();
|
||||||
|
userInviteCodesMapper.insert(inviteCodeDO);
|
||||||
|
return inviteCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成唯一的6位邀请码(字母和数字混合)
|
||||||
|
*/
|
||||||
|
private String generateUniqueInviteCode() {
|
||||||
|
String code;
|
||||||
|
int maxAttempts = 100;
|
||||||
|
int attempt = 0;
|
||||||
|
do {
|
||||||
|
code = RandomUtil.randomString("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 6);
|
||||||
|
attempt++;
|
||||||
|
if (attempt >= maxAttempts) {
|
||||||
|
throw new RuntimeException("无法生成唯一的邀请码,请稍后重试");
|
||||||
|
}
|
||||||
|
} while (userInviteCodesMapper.selectOne(KeyboardUserInviteCodesDO::getCode, code) != null);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ public class KeyboardUserInviteCodesPageReqVO extends PageParam {
|
|||||||
private Long ownerTenantId;
|
private Long ownerTenantId;
|
||||||
|
|
||||||
@Schema(description = "邀请码所属系统用户", example = "772")
|
@Schema(description = "邀请码所属系统用户", example = "772")
|
||||||
private Long owenrSystemUserId;
|
private Long ownerSystemUserId;
|
||||||
|
|
||||||
@Schema(description = "邀请码类型", example = "1")
|
@Schema(description = "邀请码类型", example = "1")
|
||||||
private String inviteType;
|
private String inviteType;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ public class KeyboardUserInviteCodesRespVO {
|
|||||||
|
|
||||||
@Schema(description = "邀请码所属系统用户", example = "772")
|
@Schema(description = "邀请码所属系统用户", example = "772")
|
||||||
@ExcelProperty("邀请码所属系统用户")
|
@ExcelProperty("邀请码所属系统用户")
|
||||||
private Long owenrSystemUserId;
|
private Long ownerSystemUserId;
|
||||||
|
|
||||||
@Schema(description = "邀请码类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
@Schema(description = "邀请码类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
@ExcelProperty("邀请码类型")
|
@ExcelProperty("邀请码类型")
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class KeyboardUserInviteCodesSaveReqVO {
|
|||||||
private Long ownerTenantId;
|
private Long ownerTenantId;
|
||||||
|
|
||||||
@Schema(description = "邀请码所属系统用户", example = "772")
|
@Schema(description = "邀请码所属系统用户", example = "772")
|
||||||
private Long owenrSystemUserId;
|
private Long ownerSystemUserId;
|
||||||
|
|
||||||
@Schema(description = "邀请码类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
@Schema(description = "邀请码类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||||
@NotEmpty(message = "邀请码类型不能为空")
|
@NotEmpty(message = "邀请码类型不能为空")
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import com.yolo.keyboard.framework.mybatis.core.dataobject.BaseDO;
|
|||||||
* @author ziin
|
* @author ziin
|
||||||
*/
|
*/
|
||||||
@TableName("keyboard_user_invite_codes")
|
@TableName("keyboard_user_invite_codes")
|
||||||
@KeySequence("keyboard_user_invite_codes_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
@KeySequence("invite_codes_id_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
@Builder
|
@Builder
|
||||||
@@ -67,7 +67,7 @@ public class KeyboardUserInviteCodesDO {
|
|||||||
/**
|
/**
|
||||||
* 邀请码所属系统用户
|
* 邀请码所属系统用户
|
||||||
*/
|
*/
|
||||||
private Long owenrSystemUserId;
|
private Long ownerSystemUserId;
|
||||||
/**
|
/**
|
||||||
* 邀请码类型
|
* 邀请码类型
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public interface KeyboardUserInviteCodesMapper extends BaseMapperX<KeyboardUserI
|
|||||||
.eqIfPresent(KeyboardUserInviteCodesDO::getUsedCount, reqVO.getUsedCount())
|
.eqIfPresent(KeyboardUserInviteCodesDO::getUsedCount, reqVO.getUsedCount())
|
||||||
.eqIfPresent(KeyboardUserInviteCodesDO::getSystemUserId, reqVO.getSystemUserId())
|
.eqIfPresent(KeyboardUserInviteCodesDO::getSystemUserId, reqVO.getSystemUserId())
|
||||||
.eqIfPresent(KeyboardUserInviteCodesDO::getOwnerTenantId, reqVO.getOwnerTenantId())
|
.eqIfPresent(KeyboardUserInviteCodesDO::getOwnerTenantId, reqVO.getOwnerTenantId())
|
||||||
.eqIfPresent(KeyboardUserInviteCodesDO::getOwenrSystemUserId, reqVO.getOwenrSystemUserId())
|
.eqIfPresent(KeyboardUserInviteCodesDO::getOwnerSystemUserId, reqVO.getOwnerSystemUserId())
|
||||||
.eqIfPresent(KeyboardUserInviteCodesDO::getInviteType, reqVO.getInviteType())
|
.eqIfPresent(KeyboardUserInviteCodesDO::getInviteType, reqVO.getInviteType())
|
||||||
.orderByDesc(KeyboardUserInviteCodesDO::getId));
|
.orderByDesc(KeyboardUserInviteCodesDO::getId));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,21 +5,18 @@ import com.yolo.keyboard.controller.admin.themes.vo.KeyboardThemesPageReqVO;
|
|||||||
import com.yolo.keyboard.controller.admin.themes.vo.KeyboardThemesSaveReqVO;
|
import com.yolo.keyboard.controller.admin.themes.vo.KeyboardThemesSaveReqVO;
|
||||||
import com.yolo.keyboard.dal.dataobject.themes.KeyboardThemesDO;
|
import com.yolo.keyboard.dal.dataobject.themes.KeyboardThemesDO;
|
||||||
import com.yolo.keyboard.dal.mysql.themes.KeyboardThemesMapper;
|
import com.yolo.keyboard.dal.mysql.themes.KeyboardThemesMapper;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.yolo.keyboard.framework.common.pojo.PageResult;
|
import com.yolo.keyboard.framework.common.pojo.PageResult;
|
||||||
import com.yolo.keyboard.framework.common.pojo.PageParam;
|
|
||||||
import com.yolo.keyboard.framework.common.util.object.BeanUtils;
|
import com.yolo.keyboard.framework.common.util.object.BeanUtils;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.yolo.keyboard.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static com.yolo.keyboard.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static com.yolo.keyboard.framework.common.util.collection.CollectionUtils.convertList;
|
|
||||||
import static com.yolo.keyboard.framework.common.util.collection.CollectionUtils.diffList;
|
|
||||||
import static com.yolo.keyboard.module.infra.enums.ErrorCodeConstants.THEMES_NOT_EXISTS;
|
import static com.yolo.keyboard.module.infra.enums.ErrorCodeConstants.THEMES_NOT_EXISTS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,15 +28,25 @@ import static com.yolo.keyboard.module.infra.enums.ErrorCodeConstants.THEMES_NOT
|
|||||||
@Validated
|
@Validated
|
||||||
public class KeyboardThemesServiceImpl implements KeyboardThemesService {
|
public class KeyboardThemesServiceImpl implements KeyboardThemesService {
|
||||||
|
|
||||||
|
private static final String THEME_STYLE_KEY_PREFIX = "theme:style:";
|
||||||
|
private static final String THEME_STYLE_ALL_KEY = "theme:style:all";
|
||||||
|
private static final Long ALL_STYLE_ID = 9999L;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private KeyboardThemesMapper themesMapper;
|
private KeyboardThemesMapper themesMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long createThemes(KeyboardThemesSaveReqVO createReqVO) {
|
public Long createThemes(KeyboardThemesSaveReqVO createReqVO) {
|
||||||
// 插入
|
// 插入
|
||||||
KeyboardThemesDO themes = BeanUtils.toBean(createReqVO, KeyboardThemesDO.class);
|
KeyboardThemesDO themes = BeanUtils.toBean(createReqVO, KeyboardThemesDO.class);
|
||||||
themesMapper.insert(themes);
|
themesMapper.insert(themes);
|
||||||
|
|
||||||
|
// 同步更新 Redis 缓存
|
||||||
|
refreshThemeStyleCache(themes.getThemeStyle());
|
||||||
|
|
||||||
// 返回
|
// 返回
|
||||||
return themes.getId();
|
return themes.getId();
|
||||||
}
|
}
|
||||||
@@ -47,24 +54,56 @@ public class KeyboardThemesServiceImpl implements KeyboardThemesService {
|
|||||||
@Override
|
@Override
|
||||||
public void updateThemes(KeyboardThemesSaveReqVO updateReqVO) {
|
public void updateThemes(KeyboardThemesSaveReqVO updateReqVO) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
|
KeyboardThemesDO oldTheme = themesMapper.selectById(updateReqVO.getId());
|
||||||
validateThemesExists(updateReqVO.getId());
|
validateThemesExists(updateReqVO.getId());
|
||||||
|
|
||||||
// 更新
|
// 更新
|
||||||
KeyboardThemesDO updateObj = BeanUtils.toBean(updateReqVO, KeyboardThemesDO.class);
|
KeyboardThemesDO updateObj = BeanUtils.toBean(updateReqVO, KeyboardThemesDO.class);
|
||||||
themesMapper.updateById(updateObj);
|
themesMapper.updateById(updateObj);
|
||||||
|
|
||||||
|
// 同步更新 Redis 缓存(如果风格变更,需要刷新新旧两个风格的缓存)
|
||||||
|
refreshThemeStyleCache(updateReqVO.getThemeStyle());
|
||||||
|
if (oldTheme != null && oldTheme.getThemeStyle() != null
|
||||||
|
&& !oldTheme.getThemeStyle().equals(updateReqVO.getThemeStyle())) {
|
||||||
|
refreshThemeStyleCache(oldTheme.getThemeStyle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteThemes(Long id) {
|
public void deleteThemes(Long id) {
|
||||||
// 校验存在
|
// 校验存在
|
||||||
|
KeyboardThemesDO theme = themesMapper.selectById(id);
|
||||||
validateThemesExists(id);
|
validateThemesExists(id);
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
themesMapper.deleteById(id);
|
themesMapper.deleteById(id);
|
||||||
|
|
||||||
|
// 同步更新 Redis 缓存
|
||||||
|
if (theme != null && theme.getThemeStyle() != null) {
|
||||||
|
refreshThemeStyleCache(theme.getThemeStyle());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteThemesListByIds(List<Long> ids) {
|
public void deleteThemesListByIds(List<Long> ids) {
|
||||||
|
// 获取要删除的主题列表,记录其风格
|
||||||
|
List<KeyboardThemesDO> themes = themesMapper.selectBatchIds(ids);
|
||||||
|
Set<Long> styleIds = new HashSet<>();
|
||||||
|
if (CollUtil.isNotEmpty(themes)) {
|
||||||
|
for (KeyboardThemesDO theme : themes) {
|
||||||
|
if (theme.getThemeStyle() != null) {
|
||||||
|
styleIds.add(theme.getThemeStyle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 删除
|
// 删除
|
||||||
themesMapper.deleteByIds(ids);
|
themesMapper.deleteByIds(ids);
|
||||||
|
|
||||||
|
// 同步更新 Redis 缓存
|
||||||
|
for (Long styleId : styleIds) {
|
||||||
|
refreshThemeStyleCache(styleId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -84,4 +123,32 @@ public class KeyboardThemesServiceImpl implements KeyboardThemesService {
|
|||||||
return themesMapper.selectPage(pageReqVO);
|
return themesMapper.selectPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新主题风格缓存
|
||||||
|
*
|
||||||
|
* @param styleId 风格ID
|
||||||
|
*/
|
||||||
|
private void refreshThemeStyleCache(Long styleId) {
|
||||||
|
if (styleId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 刷新指定风格的缓存
|
||||||
|
String styleKey = THEME_STYLE_KEY_PREFIX + styleId;
|
||||||
|
List<KeyboardThemesDO> themesByStyle = themesMapper.selectList(KeyboardThemesDO::getThemeStyle, styleId);
|
||||||
|
if (CollUtil.isNotEmpty(themesByStyle)) {
|
||||||
|
redisTemplate.opsForValue().set(styleKey, themesByStyle);
|
||||||
|
} else {
|
||||||
|
redisTemplate.delete(styleKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 刷新全部主题缓存(theme:style:all)
|
||||||
|
List<KeyboardThemesDO> allThemes = themesMapper.selectList();
|
||||||
|
if (CollUtil.isNotEmpty(allThemes)) {
|
||||||
|
redisTemplate.opsForValue().set(THEME_STYLE_ALL_KEY, allThemes);
|
||||||
|
} else {
|
||||||
|
redisTemplate.delete(THEME_STYLE_ALL_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.yolo.keyboard.module.system.api.invitecode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户邀请码 API 接口
|
||||||
|
*
|
||||||
|
* @author ziin
|
||||||
|
*/
|
||||||
|
public interface UserInviteCodeApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为代理租户创建邀请码
|
||||||
|
*
|
||||||
|
* @param userId 系统用户ID
|
||||||
|
* @param tenantId 租户ID
|
||||||
|
* @return 生成的邀请码
|
||||||
|
*/
|
||||||
|
String createInviteCodeForAgent(Long userId, Long tenantId);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import com.yolo.keyboard.module.system.dal.dataobject.permission.RoleDO;
|
|||||||
import com.yolo.keyboard.module.system.dal.dataobject.tenant.TenantDO;
|
import com.yolo.keyboard.module.system.dal.dataobject.tenant.TenantDO;
|
||||||
import com.yolo.keyboard.module.system.dal.dataobject.tenant.TenantPackageDO;
|
import com.yolo.keyboard.module.system.dal.dataobject.tenant.TenantPackageDO;
|
||||||
import com.yolo.keyboard.module.system.dal.mysql.tenant.TenantMapper;
|
import com.yolo.keyboard.module.system.dal.mysql.tenant.TenantMapper;
|
||||||
|
import com.yolo.keyboard.module.system.api.invitecode.UserInviteCodeApi;
|
||||||
import com.yolo.keyboard.module.system.enums.permission.RoleCodeEnum;
|
import com.yolo.keyboard.module.system.enums.permission.RoleCodeEnum;
|
||||||
import com.yolo.keyboard.module.system.enums.permission.RoleTypeEnum;
|
import com.yolo.keyboard.module.system.enums.permission.RoleTypeEnum;
|
||||||
import com.yolo.keyboard.module.system.service.permission.MenuService;
|
import com.yolo.keyboard.module.system.service.permission.MenuService;
|
||||||
@@ -75,6 +76,9 @@ public class TenantServiceImpl implements TenantService {
|
|||||||
@Resource
|
@Resource
|
||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
private UserInviteCodeApi userInviteCodeApi;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Long> getTenantIdList() {
|
public List<Long> getTenantIdList() {
|
||||||
List<TenantDO> tenants = tenantMapper.selectList();
|
List<TenantDO> tenants = tenantMapper.selectList();
|
||||||
@@ -135,6 +139,10 @@ public class TenantServiceImpl implements TenantService {
|
|||||||
Long userId = createUser(roleId, createReqVO);
|
Long userId = createUser(roleId, createReqVO);
|
||||||
// 修改租户的管理员
|
// 修改租户的管理员
|
||||||
tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId));
|
tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId));
|
||||||
|
// 为代理租户创建邀请码
|
||||||
|
if ("代理".equals(createReqVO.getTenantType()) && userInviteCodeApi != null) {
|
||||||
|
userInviteCodeApi.createInviteCodeForAgent(userId, tenant.getId());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return tenant.getId();
|
return tenant.getId();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user