From 685cc3d92cb1dd6879b17a6deaad8333563b8bb7 Mon Sep 17 00:00:00 2001 From: cuijiawang Date: Sat, 27 Sep 2025 17:15:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=99=A8=20=E8=87=AA=E5=AE=9A=E4=B9=89=E6=A8=A1=E6=9D=BF=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=A0=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/UserTemplateController.java | 16 +++- .../codegen/mapper/UserTemplateMapper.java | 27 ++---- .../service/impl/UserTemplateServiceImpl.java | 85 ++++++++++--------- sql/fix_user_template_unique_constraint.sql | 16 ++++ 4 files changed, 81 insertions(+), 63 deletions(-) create mode 100644 sql/fix_user_template_unique_constraint.sql diff --git a/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/controller/UserTemplateController.java b/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/controller/UserTemplateController.java index f6f4a6a..927b230 100644 --- a/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/controller/UserTemplateController.java +++ b/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/controller/UserTemplateController.java @@ -128,9 +128,19 @@ public class UserTemplateController { public R removeBatch(@RequestBody Map params) { try { @SuppressWarnings("unchecked") - List idsInt = (List) params.get("ids"); - Long[] ids = idsInt.stream() - .map(Integer::longValue) + List idsObj = (List) params.get("ids"); + Long[] ids = idsObj.stream() + .map(obj -> { + if (obj instanceof Integer) { + return ((Integer) obj).longValue(); + } else if (obj instanceof Long) { + return (Long) obj; + } else if (obj instanceof String) { + return Long.parseLong((String) obj); + } else { + throw new RuntimeException("不支持的ID类型: " + obj.getClass()); + } + }) .toArray(Long[]::new); boolean success = userTemplateService.deleteUserTemplateByIds(ids); return success ? R.ok() : R.fail("批量删除模板失败"); diff --git a/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/mapper/UserTemplateMapper.java b/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/mapper/UserTemplateMapper.java index cc3f24d..77013e4 100644 --- a/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/mapper/UserTemplateMapper.java +++ b/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/mapper/UserTemplateMapper.java @@ -2,9 +2,6 @@ package com.agileboot.codegen.mapper; import com.agileboot.codegen.entity.UserTemplate; import com.agileboot.common.mybatis.mapper.BaseMapperDelete; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; @@ -14,30 +11,20 @@ import java.util.List; /** * 用户模板 Mapper接口 - * + * * @author system * @date 2025-09-26 */ @Mapper public interface UserTemplateMapper extends BaseMapperDelete { - /** - * 分页查询用户模板列表 - * - * @param page 页码对象 - * @param queryWrapper 查询条件 - * @return 用户模板列表 - */ - @Select("SELECT * FROM user_template ${ew.customSqlSegment}") - Page selectUserTemplateList(Page page, @Param(Constants.WRAPPER) Wrapper queryWrapper); - /** * 查询公开模板列表 * * @param templateGroup 模板分组(可选) * @return 公开模板列表 */ - @Select("SELECT * FROM user_template WHERE is_public = 1 AND status = 1 ORDER BY use_count DESC, create_time DESC") + @Select("SELECT * FROM user_template WHERE is_public = 1 AND status = 1 AND deleted = 0 ORDER BY use_count DESC, create_time DESC") List selectPublicTemplates(@Param("templateGroup") String templateGroup); /** @@ -48,10 +35,10 @@ public interface UserTemplateMapper extends BaseMapperDelete { * @param excludeId 排除的模板ID(更新时使用) * @return 存在的数量 */ - @Select("SELECT COUNT(*) FROM user_template WHERE user_id = #{userId} AND template_name = #{templateName}") - int checkTemplateNameExists(@Param("userId") Long userId, - @Param("templateName") String templateName, - @Param("excludeId") Long excludeId); + @Select("SELECT COUNT(*) FROM user_template WHERE user_id = #{userId} AND template_name = #{templateName} AND deleted = 0 AND (#{excludeId} IS NULL OR id != #{excludeId})") + int checkTemplateNameExists(@Param("userId") Long userId, + @Param("templateName") String templateName, + @Param("excludeId") Long excludeId); /** * 增加模板使用次数 @@ -69,6 +56,6 @@ public interface UserTemplateMapper extends BaseMapperDelete { * @param status 状态 * @return 模板数量 */ - @Select("SELECT COUNT(*) FROM user_template WHERE user_id = #{userId} AND status = #{status}") + @Select("SELECT COUNT(*) FROM user_template WHERE user_id = #{userId} AND status = #{status} AND deleted = 0") int countByUserIdAndStatus(@Param("userId") Long userId, @Param("status") Integer status); } diff --git a/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/service/impl/UserTemplateServiceImpl.java b/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/service/impl/UserTemplateServiceImpl.java index 99646e5..e6b7632 100644 --- a/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/service/impl/UserTemplateServiceImpl.java +++ b/agileboot-system/wol-codegenerator/src/main/java/com/agileboot/codegen/service/impl/UserTemplateServiceImpl.java @@ -9,6 +9,7 @@ import cn.hutool.core.bean.BeanUtil; import com.agileboot.common.satoken.utils.LoginHelper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import java.util.Arrays; import freemarker.template.Configuration; import freemarker.template.Template; import lombok.RequiredArgsConstructor; @@ -25,7 +26,7 @@ import java.util.stream.Collectors; /** * 用户模板 Service实现类 - * + * * @author system * @date 2025-09-26 */ @@ -43,16 +44,16 @@ public class UserTemplateServiceImpl implements IUserTemplateService { .eq(StringUtils.isNotBlank(templateGroup), UserTemplate::getTemplateGroup, templateGroup) .eq(isPublic != null, UserTemplate::getIsPublic, isPublic) .orderByDesc(UserTemplate::getCreateTime); - - Page templatePage = userTemplateMapper.selectUserTemplateList(page, wrapper); - + + Page templatePage = userTemplateMapper.selectPage(page, wrapper); + // 转换为VO Page voPage = new Page<>(templatePage.getCurrent(), templatePage.getSize(), templatePage.getTotal()); List voList = templatePage.getRecords().stream() .map(this::convertToVO) .collect(Collectors.toList()); voPage.setRecords(voList); - + return voPage; } @@ -78,19 +79,19 @@ public class UserTemplateServiceImpl implements IUserTemplateService { @Transactional public boolean insertUserTemplate(UserTemplateDTO dto) { Long currentUserId = LoginHelper.getUserId(); - + // 检查模板名称是否存在 if (checkTemplateNameExists(currentUserId, dto.getTemplateName(), null)) { throw new RuntimeException("模板名称已存在"); } - + UserTemplate template = new UserTemplate(); BeanUtil.copyProperties(dto, template); template.setUserId(currentUserId); template.setUseCount(0); template.setStatus(dto.getStatus() != null ? dto.getStatus() : 1); template.setVersion(StringUtils.isNotBlank(dto.getVersion()) ? dto.getVersion() : "1.0.0"); - + return userTemplateMapper.insert(template) > 0; } @@ -100,46 +101,55 @@ public class UserTemplateServiceImpl implements IUserTemplateService { if (dto.getId() == null) { throw new RuntimeException("模板ID不能为空"); } - + UserTemplate existTemplate = userTemplateMapper.selectById(dto.getId()); if (existTemplate == null) { throw new RuntimeException("模板不存在"); } - + Long currentUserId = LoginHelper.getUserId(); // 只能修改自己的模板 if (!currentUserId.equals(existTemplate.getUserId())) { throw new RuntimeException("无权限修改此模板"); } - + // 检查模板名称是否存在(只在名称发生变化时才检查) - if (!existTemplate.getTemplateName().equals(dto.getTemplateName()) && + if (!existTemplate.getTemplateName().equals(dto.getTemplateName()) && checkTemplateNameExists(currentUserId, dto.getTemplateName(), dto.getId())) { throw new RuntimeException("模板名称已存在"); } - + UserTemplate template = new UserTemplate(); BeanUtil.copyProperties(dto, template); template.setUserId(currentUserId); - + return userTemplateMapper.updateById(template) > 0; } @Override @Transactional public boolean deleteUserTemplateById(Long id) { + if (id == null) { + throw new RuntimeException("模板ID不能为空"); + } + UserTemplate template = userTemplateMapper.selectById(id); if (template == null) { - return false; + throw new RuntimeException("模板不存在或已被删除"); } - + Long currentUserId = LoginHelper.getUserId(); // 只能删除自己的模板 if (!currentUserId.equals(template.getUserId())) { throw new RuntimeException("无权限删除此模板"); } - - return userTemplateMapper.deleteById(id) > 0; + + int result = userTemplateMapper.deleteById(id); + if (result <= 0) { + throw new RuntimeException("删除操作失败"); + } + + return true; } @Override @@ -148,9 +158,9 @@ public class UserTemplateServiceImpl implements IUserTemplateService { if (ids == null || ids.length == 0) { return false; } - + Long currentUserId = LoginHelper.getUserId(); - + // 检查所有模板是否属于当前用户 for (Long id : ids) { UserTemplate template = userTemplateMapper.selectById(id); @@ -158,13 +168,8 @@ public class UserTemplateServiceImpl implements IUserTemplateService { throw new RuntimeException("无权限删除模板ID: " + id); } } - - // 批量删除 - for (Long id : ids) { - userTemplateMapper.deleteById(id); - } - - return true; + + return userTemplateMapper.deleteByIds(Arrays.asList(ids)) > 0; } @Override @@ -174,19 +179,19 @@ public class UserTemplateServiceImpl implements IUserTemplateService { if (sourceTemplate == null) { throw new RuntimeException("源模板不存在"); } - + // 只能复制公开模板 if (sourceTemplate.getIsPublic() != 1) { throw new RuntimeException("该模板不是公开模板,无法复制"); } - + Long currentUserId = LoginHelper.getUserId(); - + // 检查新模板名称是否存在 if (checkTemplateNameExists(currentUserId, newName, null)) { throw new RuntimeException("模板名称已存在"); } - + UserTemplate newTemplate = new UserTemplate(); BeanUtil.copyProperties(sourceTemplate, newTemplate); newTemplate.setId(null); @@ -194,7 +199,7 @@ public class UserTemplateServiceImpl implements IUserTemplateService { newTemplate.setTemplateName(newName); newTemplate.setIsPublic(0); // 复制的模板默认为私有 newTemplate.setUseCount(0); - + return userTemplateMapper.insert(newTemplate) > 0; } @@ -203,18 +208,18 @@ public class UserTemplateServiceImpl implements IUserTemplateService { try { Configuration cfg = new Configuration(Configuration.VERSION_2_3_31); cfg.setDefaultEncoding("UTF-8"); - + // 创建模板对象 Template template = new Template("validate", new StringReader(templateContent), cfg); - + // 使用测试数据验证模板 StringWriter writer = new StringWriter(); HashMap testData = new HashMap<>(); testData.put("className", "TestClass"); testData.put("tableName", "test_table"); - + template.process(testData, writer); - + return "模板语法验证通过"; } catch (Exception e) { return "模板语法错误: " + e.getMessage(); @@ -238,10 +243,10 @@ public class UserTemplateServiceImpl implements IUserTemplateService { private UserTemplateVO convertToVO(UserTemplate template) { UserTemplateVO vo = new UserTemplateVO(); BeanUtil.copyProperties(template, vo); - + // 设置文本描述 vo.setIsPublicText(template.getIsPublic() == 1 ? "公开" : "私有"); - + String statusText; switch (template.getStatus()) { case 0: @@ -257,11 +262,11 @@ public class UserTemplateServiceImpl implements IUserTemplateService { statusText = "未知"; } vo.setStatusText(statusText); - + // 判断是否为当前用户创建 Long currentUserId = LoginHelper.getUserId(); vo.setIsOwner(currentUserId != null && currentUserId.equals(template.getUserId())); - + return vo; } } diff --git a/sql/fix_user_template_unique_constraint.sql b/sql/fix_user_template_unique_constraint.sql new file mode 100644 index 0000000..e96d651 --- /dev/null +++ b/sql/fix_user_template_unique_constraint.sql @@ -0,0 +1,16 @@ +-- 修复用户模板表的唯一约束问题 +-- 解决逻辑删除与唯一约束的冲突 + +-- 1. 删除原有的唯一约束 +ALTER TABLE `user_template` DROP INDEX `uk_user_template_name`; + +-- 2. 创建条件唯一索引,只对未删除的记录生效 +-- MySQL 5.7+ 支持函数索引,但为了兼容性,我们使用另一种方案 +-- 创建一个复合索引,对于已删除的记录,使用 NULL 值来避免唯一约束 +ALTER TABLE `user_template` ADD UNIQUE INDEX `uk_user_template_name_active` (`user_id`, `template_name`, (CASE WHEN deleted = 0 THEN 0 ELSE NULL END)); + +-- 注意:这个索引允许以下情况: +-- - 用户A有模板"test1",deleted=0(正常)- 唯一 +-- - 用户A有多个模板"test1",deleted=1(已删除)- 允许多个 +-- 但不允许: +-- - 用户A有两个模板"test1",都是deleted=0