Răsfoiți Sursa

字典模块开发

chenxiaofei 1 lună în urmă
părinte
comite
fee97b836a

+ 72 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/config/MyBatisMixedConfig.java

@@ -0,0 +1,72 @@
+package com.sckw.system.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.sql.DataSource;
+
+/**
+ * MyBatis 统一配置(使用 MyBatis-Plus)
+ * dao 和 mapper 包都使用同一个 SqlSessionFactory
+ * @author system
+ * @date 2024
+ */
+@Configuration
+@EnableTransactionManagement
+@MapperScan(basePackages = {"com.sckw.system.dao", "com.sckw.system.mapper"}, 
+            sqlSessionFactoryRef = "sqlSessionFactory")
+public class MyBatisMixedConfig {
+    
+    // ========== 统一的 MyBatis 配置 ==========
+    
+    @Bean(name = "sqlSessionFactory")
+    @Primary
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
+        MybatisConfiguration configuration = new MybatisConfiguration();
+        configuration.setMapUnderscoreToCamelCase(true);
+        
+        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
+        factory.setDataSource(dataSource);
+        factory.setConfiguration(configuration);
+        
+        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+        factory.setMapperLocations(resolver.getResources("classpath*:/mapper/**/*.xml"));
+        // 同时扫描两个包的实体类
+        factory.setTypeAliasesPackage("com.sckw.system.model,com.sckw.system.entity.flex");
+        
+        // 添加 MyBatis-Plus 插件
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+        factory.setPlugins(interceptor);
+        
+        return factory.getObject();
+    }
+    
+    @Bean(name = "sqlSessionTemplate")
+    @Primary
+    public SqlSessionTemplate sqlSessionTemplate(
+            @Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
+        return new SqlSessionTemplate(sqlSessionFactory);
+    }
+    
+    // 事务管理器
+    @Bean
+    @Primary
+    public PlatformTransactionManager transactionManager(DataSource dataSource) {
+        return new DataSourceTransactionManager(dataSource);
+    }
+}

+ 97 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/controller/SysDictFlexController.java

@@ -0,0 +1,97 @@
+package com.sckw.system.controller;
+
+import com.sckw.core.web.response.BaseResult;
+import com.sckw.core.web.response.result.PageDataResult;
+import com.sckw.system.model.vo.req.SysDictReqVo;
+import com.sckw.system.model.vo.res.SysDictResp;
+import com.sckw.system.service.SysDictFlexBusinessService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 字典控制器 (MyBatis-Flex)
+ * @author system
+ * @date 2024
+ */
+@Tag(name = "字典管理")
+@RestController
+@RequestMapping("/flex/sysDict")
+@RequiredArgsConstructor
+public class SysDictFlexController {
+
+    private final SysDictFlexBusinessService sysDictService;
+
+    /**
+     * 新增字典
+     */
+    @Operation(summary = "新增字典")
+    @PostMapping("/insert")
+    public BaseResult<Boolean> insert(@RequestBody SysDictReqVo reqVo) {
+        return BaseResult.success(sysDictService.insert(reqVo.getEntity()));
+    }
+
+
+
+
+
+    /**
+     * 逻辑删除字典
+     */
+    @Operation(summary = "逻辑删除字典")
+    @PostMapping("/logicDelete")
+    public BaseResult<Integer> logicDeleteById(@RequestBody SysDictReqVo reqVo) {
+        int rows = sysDictService.logicDeleteById(reqVo.getId());
+        return BaseResult.success(rows);
+    }
+
+    /**
+     * 更新字典
+     */
+    @Operation(summary = "更新字典")
+    @PostMapping("/update")
+    public BaseResult<Boolean> update(@RequestBody SysDictReqVo reqVo) {
+        return BaseResult.success(sysDictService.update(reqVo.getEntity()));
+    }
+    
+    /**
+     * 分页查询字典
+     */
+    @Operation(summary = "分页查询字典")
+    @PostMapping("/selectPage")
+    public BaseResult<PageDataResult<SysDictResp>> selectPage(@RequestBody SysDictReqVo reqVo) {
+        return BaseResult.success(sysDictService.selectPage(reqVo));
+    }
+
+    /**
+     * 统计字典数量
+     */
+    @Operation(summary = "统计字典数量")
+    @PostMapping("/count")
+    public BaseResult<Long> count(@RequestBody SysDictReqVo reqVo) {
+        long count = sysDictService.count(reqVo.getType());
+        return BaseResult.success(count);
+    }
+
+    /**
+     * 查询上级字典单选下拉(支持输入搜索)
+     * 用于字典项选择父级字典
+     */
+    @Operation(summary = "查询上级字典下拉列表")
+    @PostMapping("/searchParentForSelect")
+    public BaseResult<List<SysDictResp>> searchParentForSelect(@RequestBody SysDictReqVo reqVo) {
+        return BaseResult.success(sysDictService.searchParentDictForSelect( reqVo));
+    }
+
+    /**
+     * 快捷更改字典状态(启用/停用)
+     */
+    @Operation(summary = "快捷更改字典状态")
+    @PostMapping("/updateStatus")
+    public BaseResult<Boolean> updateStatus(@RequestBody SysDictReqVo reqVo) {
+        return BaseResult.success(sysDictService.updateStatus(reqVo.getId(), reqVo.getStatus()));
+    }
+}

+ 78 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/controller/SysDictTypeFlexController.java

@@ -0,0 +1,78 @@
+package com.sckw.system.controller;
+
+import com.sckw.core.web.response.BaseResult;
+import com.sckw.core.web.response.result.PageDataResult;
+import com.sckw.system.model.vo.req.SysDictTypeReqVo;
+import com.sckw.system.model.vo.res.SysDictTypeResp;
+import com.sckw.system.service.SysDictTypeService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 字典类型控制器 (MyBatis-Flex)
+ * @author system
+ * @date 2024
+ */
+@Tag(name = "字典类型管理")
+@RestController
+@RequestMapping("/flex/sysDictType")
+@RequiredArgsConstructor
+public class SysDictTypeFlexController {
+
+    private final SysDictTypeService sysDictTypeService;
+
+    /**
+     * 新增字典类型
+     */
+    @Operation(summary = "新增字典类型")
+    @PostMapping("/insert")
+    public BaseResult<Integer> insert(@RequestBody SysDictTypeReqVo reqVo) {
+        return BaseResult.success(sysDictTypeService.insert(reqVo.getEntity()));
+    }
+
+
+    /**
+     * 逻辑删除字典类型
+     */
+    @Operation(summary = "逻辑删除字典类型")
+    @PostMapping("/logicDelete")
+    public BaseResult<Integer> logicDeleteById(@RequestBody SysDictTypeReqVo reqVo) {
+        int rows = sysDictTypeService.logicDeleteById(reqVo.getId());
+        return BaseResult.success(rows);
+    }
+
+    /**
+     * 更新字典类型
+     */
+    @Operation(summary = "更新字典类型")
+    @PostMapping("/update")
+    public BaseResult<Integer> update(@RequestBody SysDictTypeReqVo reqVo) {
+        int rows = sysDictTypeService.update(reqVo.getEntity());
+        return BaseResult.success(rows);
+    }
+
+
+    /**
+     * 分页查询字典类型
+     */
+    @Operation(summary = "分页查询字典类型")
+    @PostMapping("/selectPage")
+    public BaseResult<PageDataResult<SysDictTypeResp>> selectPage(@RequestBody SysDictTypeReqVo reqVo) {
+
+        return BaseResult.success(sysDictTypeService.selectPage(reqVo));
+    }
+
+    /**
+     * 搜索字典类型(支持下拉选择,支持输入搜索)
+     */
+    @Operation(summary = "搜索字典类型下拉列表", description = "支持按名称或类型模糊搜索,返回id、name、type字段")
+    @PostMapping("/searchForSelect")
+    public BaseResult<List<SysDictTypeResp>> searchForSelect(@RequestBody SysDictTypeReqVo reqVo) {
+        return BaseResult.success(sysDictTypeService.searchForSelect(reqVo.getKeyword()));
+    }
+
+}

+ 2 - 1
sckw-modules/sckw-system/src/main/java/com/sckw/system/dao/SysDictDao.java

@@ -1,5 +1,6 @@
 package com.sckw.system.dao;
 
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.sckw.system.model.SysDict;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -13,7 +14,7 @@ import java.util.Map;
  * @date 2023-05-30
  */
 @Mapper
-public interface SysDictDao {
+public interface SysDictDao extends BaseMapper<SysDict> {
 
     /**
      * 新增

+ 2 - 1
sckw-modules/sckw-system/src/main/java/com/sckw/system/dao/SysDictTypeDao.java

@@ -1,5 +1,6 @@
 package com.sckw.system.dao;
 
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.sckw.system.model.SysDict;
 import com.sckw.system.model.SysDictType;
 import org.apache.ibatis.annotations.Mapper;
@@ -12,7 +13,7 @@ import java.util.Map;
  * @date 2023-05-30
  */
 @Mapper
-public interface SysDictTypeDao {
+public interface SysDictTypeDao extends BaseMapper<SysDictType> {
 
     /**
      * 新增

+ 149 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/model/vo/req/SysDictReqVo.java

@@ -0,0 +1,149 @@
+package com.sckw.system.model.vo.req;
+
+import com.sckw.core.web.request.PageReq;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * 字典请求参数对象
+ *
+ * @author system
+ * @date 2024
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(description = "字典请求参数对象")
+public class SysDictReqVo extends PageReq implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = -1221233313543576005L;
+    /**
+     * 主键ID
+     */
+    @Schema(description = "主键ID")
+    private Long id;
+
+    /**
+     * 字典实体
+     */
+    @Schema(description = "字典实体")
+    private SysDictInfo entity;
+
+    /**
+     * 类型
+     */
+    @Schema(description = "类型")
+    private String type;
+
+    /**
+     * 选项值
+     */
+    @Schema(description = "选项值")
+    private String value;
+
+    /**
+     * 选项标签
+     */
+    @Schema(description = "选项标签")
+    private String label;
+
+    /**
+     * 字典类型ID
+     */
+    @Schema(description = "字典类型ID")
+    private Long dictId;
+
+    /**
+     * 父级ID
+     */
+    @Schema(description = "父级ID")
+    private String parentId;
+
+    /**
+     * 状态
+     */
+    @Schema(description = "状态")
+    private Integer status;
+
+    /**
+     * 搜索关键词(用于下拉搜索)
+     */
+    @Schema(description = "搜索关键词(用于下拉搜索)")
+    private String keyword;
+
+    @Data
+    @Schema(description = "字典信息")
+    public static class SysDictInfo implements Serializable {
+        @Serial
+        private static final long serialVersionUID = -2031642328618437889L;
+
+        /**
+         * 主键
+         */
+        @Schema(description = "主键")
+        private Long id;
+
+        /**
+         * 字典类型id
+         */
+        @Schema(description = "字典类型id")
+        private Long dictId;
+
+        /**
+         * 选项值
+         */
+        @Schema(description = "选项值")
+        private String value;
+
+        /**
+         * 选项
+         */
+        @Schema(description = "选项")
+        private String label;
+
+        /**
+         * 类型
+         */
+        @Schema(description = "类型")
+        private String type;
+
+        /**
+         * 描述
+         */
+        @Schema(description = "描述")
+        private String description;
+
+        /**
+         * 排序(升序)
+         */
+        @Schema(description = "排序(升序)")
+        private Long sort;
+
+        /**
+         * 父级编号
+         */
+        @Schema(description = "父级编号")
+        private String parentId;
+
+        /**
+         * 图标、文件等
+         */
+        @Schema(description = "图标、文件等")
+        private String url;
+
+        /**
+         * 备注
+         */
+        @Size(max = 200, message = "备注长度不能超过200")
+        @Schema(description = "备注", maxLength = 200)
+        private String remark;
+
+    }
+}

+ 92 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/model/vo/req/SysDictTypeReqVo.java

@@ -0,0 +1,92 @@
+package com.sckw.system.model.vo.req;
+
+import com.sckw.core.web.request.PageReq;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 字典类型请求参数对象
+ * @author system
+ * @date 2024
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(description = "字典类型请求参数对象")
+public class SysDictTypeReqVo extends PageReq {
+
+    @Serial
+    private static final long serialVersionUID = 7701153842223116600L;
+
+    /**
+     * 主键ID
+     */
+    @Schema(description = "主键ID")
+    private Long id;
+
+    /**
+     * 字典类型实体
+     */
+    @Schema(description = "字典类型实体")
+    private SysDictTypeInfo entity;
+
+    /**
+     * 字典类型名称
+     */
+    @Schema(description = "字典类型名称")
+    private String name;
+
+    /**
+     * 类型
+     */
+    @Schema(description = "类型")
+    private String type;
+
+    /**
+     * 状态
+     */
+    @Schema(description = "状态")
+    private Integer status;
+
+    /**
+     * 搜索关键词(用于下拉搜索)
+     */
+    @Schema(description = "搜索关键词(用于下拉搜索)")
+    private String keyword;
+
+    @Data
+    @Schema(description = "字典类型信息")
+    public static class SysDictTypeInfo implements Serializable {
+        @Serial
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 主键
+         */
+        @Schema(description = "主键")
+        private Long id;
+
+        /**
+         * 字典类型名称
+         */
+        @Schema(description = "字典类型名称")
+        private String name;
+
+        /**
+         * 类型
+         */
+        @Schema(description = "类型")
+        private String type;
+
+        /**
+         * 备注
+         */
+        @Size(max = 200, message = "备注长度不能超过200")
+        @Schema(description = "备注", maxLength = 200)
+        private String remark;
+    }
+}

+ 130 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/model/vo/res/SysDictResp.java

@@ -0,0 +1,130 @@
+package com.sckw.system.model.vo.res;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 字典响应类
+ * @author system
+ * @date 2024
+ */
+@Data
+public class SysDictResp implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @Schema(description = "主键")
+    private Long id;
+
+    /**
+     * 字典类型id
+     */
+    @Schema(description = "字典类型id")
+    private Long dictId;
+
+    /**
+     * 选项值
+     */
+    @Schema(description = "选项值")
+    private String value;
+
+    /**
+     * 字典名称
+     */
+    @Schema(description = "字典名称")
+    private String label;
+
+    /**
+     * 类型
+     */
+    @Schema(description = "类型")
+    private String type;
+
+    /**
+     * 描述
+     */
+    @Schema(description = "描述")
+    private String description;
+
+    /**
+     * 排序(升序)
+     */
+    @Schema(description = "排序(升序)")
+    private Long sort;
+
+    /**
+     * 父级编号
+     */
+    @Schema(description = "父级编号")
+    private String parentId;
+    /**
+     * 上级字典名称
+     */
+    @Schema(description = "上级字典名称")
+    private String parentName;
+
+    /**
+     * 图标、文件等
+     */
+    @Schema(description = "图标、文件等")
+    private String url;
+
+    /**
+     * 备注
+     */
+    @Schema(description = "备注")
+    private String remark;
+
+    /**
+     * 状态:0正常/1锁定
+     */
+    @Schema(description = "状态:0正常/1锁定")
+    private Integer status;
+    /**
+     * 状态名称
+     */
+    @Schema(description = "状态名称")
+    private String statusName;
+
+
+    /**
+     * 创建人
+     */
+    @Schema(description = "创建人")
+    private Long createBy;
+
+    /**
+     * 创建时间
+     */
+    @Schema(description = "创建时间")
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    /**
+     * 更新人
+     */
+    @Schema(description = "更新人")
+    private Long updateBy;
+
+    /**
+     * 更新时间
+     */
+    @Schema(description = "更新时间")
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+
+    /**
+     * 删除标识(0正常/-1删除)
+     */
+    @Schema(description = "删除标识(0正常/-1删除)")
+    private Integer delFlag;
+}

+ 84 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/model/vo/res/SysDictTypeResp.java

@@ -0,0 +1,84 @@
+package com.sckw.system.model.vo.res;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 字典类型实体类 (MyBatis-Flex)
+ * @author system
+ * @date 2024
+ */
+@Data
+public class SysDictTypeResp implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @Schema(description = "主键")
+    private Long id;
+
+    /**
+     * 字典类型名称
+     */
+    @Schema(description = "字典类型名称")
+    private String name;
+
+    /**
+     * 类型
+     */
+    @Schema(description = "类型")
+    private String type;
+
+    /**
+     * 备注
+     */
+    @Schema(description = "备注")
+    private String remark;
+
+    /**
+     * 状态:0正常/1锁定
+     */
+    @Schema(description = "状态:0正常/1锁定")
+    private Integer status;
+
+
+    /**
+     * 创建人
+     */
+    @Schema(description = "创建人")
+    private String createBy;
+
+    /**
+     * 创建时间
+     */
+    @Schema(description = "创建时间")
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    /**
+     * 更新人
+     */
+    @Schema(description = "更新人")
+    private String updateBy;
+
+    /**
+     * 更新时间
+     */
+    @Schema(description = "更新时间")
+    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+
+    /**
+     * 删除标识(0正常/-1删除)
+     */
+    @Schema(description = "删除标识(0正常/-1删除)")
+    private Integer delFlag;
+}

+ 137 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/repository/SysDictRepository.java

@@ -0,0 +1,137 @@
+package com.sckw.system.repository;
+
+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.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sckw.core.model.base.BaseModel;
+import com.sckw.system.dao.SysDictDao;
+import com.sckw.system.model.SysDict;
+import jakarta.annotation.Resource;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Repository;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * 字典服务层(MyBatis-Plus 版本)
+ * @author system
+ * @date 2024
+ */
+@Repository
+public class SysDictRepository extends ServiceImpl<SysDictDao, SysDict> {
+
+
+    /**
+     * 根据条件查询唯一字典
+     */
+    public SysDict selectUniqueDict(Long dictTypeId, String value, String label, String parentId) {
+        LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SysDict::getDelFlag, 0);
+        
+        if (dictTypeId != null) {
+            wrapper.eq(SysDict::getDictId, dictTypeId);
+        }
+        if (StringUtils.isNotBlank(value)) {
+            wrapper.eq(SysDict::getValue, value);
+        }
+        if (StringUtils.isNotBlank(label)) {
+            wrapper.eq(SysDict::getLabel, label);
+        }
+        if (StringUtils.isNotBlank(parentId)) {
+            wrapper.eq(SysDict::getParentId, parentId);
+        }
+        wrapper.last("limit 1");
+        return this.getOne(wrapper);
+    }
+
+    /**
+     * 逻辑删除
+     */
+    public int logicDeleteById(Long id) {
+        return this.baseMapper.deleteById(id);
+    }
+
+    /**
+     * 根据主键查询
+     */
+    public SysDict selectById(Long id) {
+        return this.getById(id);
+    }
+
+    /**
+     * 更新字典
+     */
+    public Boolean update(SysDict entity) {
+        return updateById(entity);
+    }
+
+    /**
+     * 分页查询字典(包含父级名称)
+     */
+    public IPage<SysDict> selectPage(int pageNum, int pageSize, String type, String parentId, String label) {
+        Page<SysDict> page = new Page<>(pageNum, pageSize);
+        
+        // 使用自定义 SQL 查询(包含父级名称)
+        LambdaQueryWrapper<SysDict> wrapper = Wrappers.<SysDict>lambdaQuery()
+                .eq(SysDict::getDelFlag, 0)
+                .eq(StringUtils.isNotBlank(type), SysDict::getType, type)
+                .eq(StringUtils.isNotBlank(parentId), SysDict::getParentId, parentId)
+                .eq(StringUtils.isNotBlank(label), SysDict::getLabel, label)
+                .orderByDesc(BaseModel::getCreateTime)
+                .orderByAsc(SysDict::getSort);
+        return page(page,wrapper);
+    }
+
+    /**
+     * 统计字典数量
+     */
+    public long count(String type) {
+        LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SysDict::getDelFlag, 0);
+        
+        if (StringUtils.isNotBlank(type)) {
+            wrapper.eq(SysDict::getType, type);
+        }
+        
+        return this.count(wrapper);
+    }
+
+    /**
+     * 查询上级字典下拉列表
+     */
+    public List<SysDict> searchParentDictForSelect(String keyword) {
+        return list(Wrappers.<SysDict>lambdaQuery()
+                .eq(BaseModel::getDelFlag,0)
+                .eq(BaseModel::getStatus,0)
+                .like (StringUtils.isNotBlank( keyword), SysDict::getLabel, keyword));
+    }
+
+    /**
+     * 快捷更改字典状态
+     */
+    public Boolean updateStatus(Long id, Integer status) {
+        LambdaUpdateWrapper<SysDict> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.eq(SysDict::getId, id)
+               .set(SysDict::getStatus, status);
+        return update(null, wrapper);
+    }
+
+    public List<SysDict> queryByIds(Set<String> parentIds) {
+        return list(Wrappers.<SysDict>lambdaQuery()
+                .eq(BaseModel::getDelFlag,0)
+                .eq(BaseModel::getStatus,0)
+                .in(SysDict::getId, parentIds));
+    }
+
+    public List<SysDict> selectByType(String testDictType) {
+        return list(Wrappers.<SysDict>lambdaQuery()
+                .eq(BaseModel::getDelFlag,0)
+                .eq(BaseModel::getStatus,0)
+                .eq(SysDict::getType, testDictType));
+    }
+}

+ 90 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/repository/SysDictTypeRepository.java

@@ -0,0 +1,90 @@
+package com.sckw.system.repository;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.sckw.system.dao.SysDictTypeDao;
+import com.sckw.system.model.SysDictType;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Repository;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 字典类型服务层(MyBatis-Plus 版本)
+ * @author system
+ * @date 2024
+ */
+@Repository
+public class SysDictTypeRepository extends ServiceImpl<SysDictTypeDao, SysDictType> {
+
+    /**
+     * 根据类型查询字典类型
+     */
+    public SysDictType selectByType(String type) {
+        LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SysDictType::getType, type)
+               .eq(SysDictType::getDelFlag, 0);
+        return this.getOne(wrapper);
+    }
+
+    /**
+     * 逻辑删除
+     */
+    public int logicDeleteById(Long id) {
+        return this.baseMapper.deleteById(id);
+    }
+
+    /**
+     * 更新字典类型
+     */
+    public int update(SysDictType entity) {
+        return this.baseMapper.updateById(entity);
+    }
+
+    /**
+     * 分页查询字典类型
+     */
+    public Page<SysDictType> selectPage(int pageNum, int pageSize, String name, String type, Integer status) {
+        Page<SysDictType> page = new Page<>(pageNum, pageSize);
+        
+        LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(SysDictType::getDelFlag, 0);
+        
+        if (StringUtils.isNotBlank(name)) {
+            wrapper.like(SysDictType::getName, name);
+        }
+        if (StringUtils.isNotBlank(type)) {
+            wrapper.like(SysDictType::getType, type);
+        }
+        if (status != null) {
+            wrapper.eq(SysDictType::getStatus, status);
+        }
+        
+        wrapper.orderByDesc(SysDictType::getCreateTime);
+        
+        return this.page(page, wrapper);
+    }
+
+    /**
+     * 搜索字典类型(支持下拉选择)
+     */
+    public List<SysDictType> searchForSelect(String keyword) {
+        LambdaQueryWrapper<SysDictType> wrapper = new LambdaQueryWrapper<>();
+        wrapper.select(SysDictType::getId, SysDictType::getName, SysDictType::getType)
+               .eq(SysDictType::getDelFlag, 0)
+               .eq(SysDictType::getStatus, 0);
+        
+        if (StringUtils.isNotBlank(keyword)) {
+            wrapper.and(w -> w.like(SysDictType::getName, keyword)
+                             .or()
+                             .like(SysDictType::getType, keyword));
+        }
+        
+        wrapper.orderByDesc(SysDictType::getCreateTime)
+               .last("LIMIT 100");
+        
+        return this.list(wrapper);
+    }
+}

+ 231 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/service/SysDictFlexBusinessService.java

@@ -0,0 +1,231 @@
+package com.sckw.system.service;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.google.common.collect.Maps;
+import com.sckw.core.model.base.BaseModel;
+import com.sckw.core.utils.IdWorker;
+import com.sckw.core.web.context.LoginUserHolder;
+import com.sckw.core.web.response.result.PageDataResult;
+import com.sckw.system.model.SysDict;
+import com.sckw.system.model.vo.req.SysDictReqVo;
+import com.sckw.system.model.vo.res.SysDictResp;
+import com.sckw.system.repository.SysDictRepository;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 字典业务服务层(中间层) - MyBatis-Plus 版本
+ * 在 SysDictService 基础上添加业务逻辑
+ * @author system
+ * @date 2024
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SysDictFlexBusinessService {
+
+    private final SysDictRepository sysDictRepository;
+
+    /**
+     * 新增字典
+     */
+    public Boolean insert(SysDictReqVo.SysDictInfo entity) {
+        log.info("新增字典,请求参数:{}", JSON.toJSONString(entity));
+        
+        // 业务校验:检查是否存在相同的字典项
+        SysDict existDict = sysDictRepository.selectUniqueDict(
+            entity.getDictId(), 
+            entity.getValue(), 
+            entity.getLabel(), 
+            entity.getParentId()
+        );
+        if (existDict != null) {
+            log.error("字典项已存在,请勿重复添加");
+            return Boolean.FALSE;
+        }
+        
+        // 设置创建信息
+        Long userId = LoginUserHolder.getUserId();
+        long id = new IdWorker(1L).nextId();
+        SysDict sysDict = getSysDict(entity, id, userId);
+        return sysDictRepository.save(sysDict) ;
+    }
+
+    @NotNull
+    private static SysDict getSysDict(SysDictReqVo.SysDictInfo entity, long id, Long userId) {
+        SysDict sysDict = new SysDict();
+        sysDict.setId(id);
+        sysDict.setDictId(entity.getDictId());
+        sysDict.setValue(entity.getValue());
+        sysDict.setLabel(entity.getLabel());
+        sysDict.setType(entity.getType());
+        sysDict.setDescription(entity.getDescription());
+        sysDict.setSort(entity.getSort());
+        sysDict.setParentId(entity.getParentId());
+        sysDict.setUrl(entity.getUrl());
+        sysDict.setRemark(entity.getRemark());
+        sysDict.setStatus(0);
+        sysDict.setCreateBy(userId);
+        sysDict.setUpdateBy(userId);
+        sysDict.setCreateTime(new Date());
+        sysDict.setUpdateTime(new Date());
+        sysDict.setDelFlag(0);
+        return sysDict;
+    }
+
+
+    /**
+     * 逻辑删除
+     */
+    public int logicDeleteById(Long id) {
+        log.info("逻辑删除字典,ID:{}", id);
+        return sysDictRepository.logicDeleteById(id);
+    }
+
+    /**
+     * 更新字典
+     */
+    public Boolean update(SysDictReqVo.SysDictInfo entity) {
+        log.info("更新字典,ID:{}", entity.getId());
+        
+        // 业务校验:检查是否存在相同的字典项(排除自己)
+        SysDict existDict = sysDictRepository.selectById(entity.getId());
+        if (Objects.isNull(existDict)) {
+            log.error("字典项不存在");
+            return Boolean.FALSE;
+        }
+
+        // 设置更新信息
+        Long userId = LoginUserHolder.getUserId();
+        SysDict sysDict = new SysDict();
+        sysDict.setId(existDict.getId());
+        sysDict.setSort(entity.getSort());
+        sysDict.setRemark(entity.getRemark());
+        sysDict.setUpdateBy(userId);
+        sysDict.setUpdateTime(new Date());
+        
+        return sysDictRepository.update(sysDict);
+    }
+
+
+
+
+
+
+
+    /**
+     * 分页查询字典
+     */
+    public PageDataResult<SysDictResp> selectPage(SysDictReqVo reqVo) {
+        log.info("分页查询字典,请求参数:{}", JSON.toJSONString(reqVo));
+        int pageNum = reqVo.getPageNum();
+        int pageSize = reqVo.getPageSize();
+
+        IPage<SysDict> page = sysDictRepository.selectPage(pageNum, pageSize, reqVo.getType(), reqVo.getParentId(), reqVo.getLabel());
+        
+        List<SysDict> records = page.getRecords();
+        if (records == null || records.isEmpty()) {
+            return PageDataResult.empty(reqVo.getPageNum(), reqVo.getPageSize());
+        }
+        Set<String> parentIds = records.stream()
+                .map(SysDict::getParentId)
+                .collect(Collectors.toSet());
+        //查询父字典
+        List<SysDict> parentDicts = sysDictRepository.queryByIds(parentIds);
+        Map<Long, SysDict> idAndParentDictMap = Maps.newHashMap();
+        if (CollectionUtils.isNotEmpty(parentDicts)){
+            idAndParentDictMap = parentDicts.stream()
+                    .collect(Collectors.toMap(BaseModel::getId, Function.identity(), (k1, k2) -> k1));
+        }
+
+        List<SysDictResp> sysDictResps = convertToRespList(records,idAndParentDictMap);
+        return PageDataResult.of(page, sysDictResps);
+    }
+
+    /**
+     * 统计字典数量
+     */
+    public long count(String type) {
+        log.info("统计字典数量,type:{}", type);
+        return sysDictRepository.count(type);
+    }
+
+    /**
+     * 查询上级字典下拉列表(支持输入搜索)
+     * 用于字典项选择父级字典
+     * @return 字典响应列表
+     */
+    public List<SysDictResp> searchParentDictForSelect(SysDictReqVo reqVo) {
+        log.info("查询上级字典下拉列表,请求参数:{}", JSON.toJSONString(reqVo));
+        List<SysDict> list = sysDictRepository.searchParentDictForSelect(reqVo.getKeyword());
+        return convertToRespList(list,new HashMap<>());
+    }
+
+    /**
+     * 快捷更改字典状态(启用/停用)
+     * @param id 字典ID
+     * @param status 状态(0正常/1锁定)
+     * @return 影响行数
+     */
+    public Boolean updateStatus(Long id, Integer status) {
+        log.info("快捷更改字典状态,ID:{}, 新状态:{}", id, status);
+        
+        // 业务校验
+        if (id == null) {
+            log.error("字典ID不能为空");
+            return Boolean.FALSE;
+        }
+        if (status == null || (status != 0 && status != 1)) {
+            log.error("状态值无效,只能为0(正常)或1(锁定)");
+            return Boolean.FALSE;
+        }
+        
+        // 检查字典是否存在
+        SysDict existDict = sysDictRepository.selectById(id);
+        if (Objects.isNull(existDict)) {
+            log.error("字典项不存在,ID:{}", id);
+            return Boolean.FALSE;
+        }
+        
+        // 更新状态
+        return sysDictRepository.updateStatus(id, status);
+    }
+
+    /**
+     * 将实体转换为响应对象
+     */
+    private SysDictResp convertToResp(SysDict entity,Map<Long, SysDict> idAndParentDictMap) {
+        if (entity == null) {
+            return null;
+        }
+        SysDictResp resp = new SysDictResp();
+        BeanUtils.copyProperties(entity, resp);
+        resp.setStatusName(Objects.equals(entity.getStatus(), 0) ? " 正常" : "锁定");
+        // 设置父级字典名称
+        Long parentId = Optional.ofNullable(entity.getParentId()).map(Long::parseLong).orElse(null);
+        SysDict parentDict = idAndParentDictMap.getOrDefault(parentId, new SysDict());
+        resp.setParentName(parentDict.getLabel());
+        return resp;
+    }
+
+    /**
+     * 将实体列表转换为响应对象列表
+     */
+    private List<SysDictResp> convertToRespList(List<SysDict> entities,Map<Long, SysDict> idAndParentDictMap ) {
+        if (entities == null || entities.isEmpty()) {
+            return List.of();
+        }
+        return entities.stream()
+                .map(x->convertToResp(x,idAndParentDictMap))
+                .collect(Collectors.toList());
+    }
+}

+ 137 - 0
sckw-modules/sckw-system/src/main/java/com/sckw/system/service/SysDictTypeService.java

@@ -0,0 +1,137 @@
+package com.sckw.system.service;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.sckw.core.utils.IdWorker;
+import com.sckw.core.web.context.LoginUserHolder;
+import com.sckw.core.web.response.result.PageDataResult;
+import com.sckw.system.model.SysDictType;
+import com.sckw.system.model.vo.req.SysDictTypeReqVo;
+import com.sckw.system.model.vo.res.SysDictTypeResp;
+import com.sckw.system.repository.SysDictTypeRepository;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 字典类型业务服务层(中间层) - MyBatis-Plus 版本
+ * @author system
+ * @date 2024
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class SysDictTypeService {
+
+    private final SysDictTypeRepository sysDictTypeService;
+
+    /**
+     * 新增字典类型
+     */
+    public int insert(SysDictTypeReqVo.SysDictTypeInfo entity) {
+        log.info("新增字典类型,请求参数:{}", JSON.toJSONString(entity));
+        SysDictType existType = sysDictTypeService.selectByType(entity.getType());
+        if (existType != null) {
+            log.error("字典类型已存在,请勿重复添加");
+            return 0;
+        }
+        Long userId = LoginUserHolder.getUserId();
+
+        long id = new IdWorker(1L).nextId();
+        SysDictType sysDictType = getSysDictType(entity, id, userId);
+        return sysDictTypeService.save(sysDictType) ? 1 : 0;
+    }
+
+    @NotNull
+    private static SysDictType getSysDictType(SysDictTypeReqVo.SysDictTypeInfo entity, long id, Long userId) {
+        SysDictType sysDictType = new SysDictType();
+        sysDictType.setId(id);
+        sysDictType.setName(entity.getName());
+        sysDictType.setType(entity.getType());
+        sysDictType.setRemark(entity.getRemark());
+        sysDictType.setStatus(0);
+        sysDictType.setCreateBy(userId);
+        sysDictType.setUpdateBy(userId);
+        sysDictType.setCreateTime(new Date());
+        sysDictType.setUpdateTime(new Date());
+        return sysDictType;
+    }
+
+
+    /**
+     * 逻辑删除
+     */
+    public int logicDeleteById(Long id) {
+        return sysDictTypeService.logicDeleteById(id);
+    }
+
+    /**
+     * 更新字典类型
+     */
+    public int update(SysDictTypeReqVo.SysDictTypeInfo entity) {
+        SysDictType sysDictType = new SysDictType();
+        sysDictType.setId(entity.getId());
+        sysDictType.setName(entity.getName());
+        sysDictType.setType(entity.getType());
+        sysDictType.setRemark(entity.getRemark());
+        sysDictType.setUpdateBy(LoginUserHolder.getUserId());
+        sysDictType.setUpdateTime(new Date());
+        return sysDictTypeService.update(sysDictType);
+    }
+
+
+
+    /**
+     * 分页查询字典类型
+     */
+    public PageDataResult<SysDictTypeResp> selectPage(SysDictTypeReqVo reqVo) {
+        log.info("分页查询字典类型,请求参数:{}", JSON.toJSONString(reqVo));
+        int pageNum = reqVo.getPageNum();
+        int pageSize = reqVo.getPageSize();
+        Page<SysDictType> page = sysDictTypeService.selectPage(pageNum, pageSize, reqVo.getName(), reqVo.getType(), reqVo.getStatus());
+        List<SysDictType> records = page.getRecords();
+        if (CollectionUtils.isEmpty(records)) {
+            return PageDataResult.empty(reqVo.getPageNum(), reqVo.getPageSize());
+        }
+        List<SysDictTypeResp> sysDictTypes = records.stream()
+                .map(SysDictTypeService::getSysDictTypeResp)
+                .collect(Collectors.toList());
+        return PageDataResult.of(page, sysDictTypes);
+    }
+
+    @NotNull
+    private static SysDictTypeResp getSysDictTypeResp(SysDictType s) {
+        SysDictTypeResp sysDictTypeResp = new SysDictTypeResp();
+        sysDictTypeResp.setId(s.getId());
+        sysDictTypeResp.setName(s.getName());
+        sysDictTypeResp.setType(s.getType());
+        sysDictTypeResp.setRemark(s.getRemark());
+        sysDictTypeResp.setStatus(s.getStatus());
+        sysDictTypeResp.setCreateTime(s.getCreateTime());
+        sysDictTypeResp.setUpdateTime(s.getUpdateTime());
+        sysDictTypeResp.setDelFlag(s.getDelFlag());
+        return sysDictTypeResp;
+    }
+
+    /**
+     * 搜索字典类型(支持下拉选择)
+     */
+    public List<SysDictTypeResp> searchForSelect(String keyword) {
+        List<SysDictType> sysDictTypes = sysDictTypeService.searchForSelect(keyword);
+        if (CollectionUtils.isEmpty(sysDictTypes)) {
+            return List.of();
+        }
+
+        return sysDictTypes.stream()
+                .map(SysDictTypeService::getSysDictTypeResp)
+                .collect(Collectors.toList());
+    }
+
+
+}