From 2ae7c39b9f3edb5e4b367077a875f8f6276b3095 Mon Sep 17 00:00:00 2001 From: jiangdingxuan Date: Mon, 8 Jan 2024 13:38:00 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=20=E5=AD=97?= =?UTF-8?q?=E5=85=B8=20=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/net/rzdata/demo/trait/TreeNode.java | 18 ++++++ .../net/rzdata/demo/dict/DictController.java | 21 +++++++ .../net/rzdata/demo/dict/DictService.java | 16 +++++ .../net/rzdata/demo/dict/domain/Dict.java | 58 +++++++++++++++++++ .../rzdata/demo/dict/mapper/DictMapper.java | 9 +++ .../demo/dict/mapper/DictRepository.java | 13 +++++ .../net/rzdata/demo/DemoTestApplication.java | 12 ++++ .../net/rzdata/demo/dict/DictServiceTest.java | 12 ++++ .../src/test/resources/application-test.yml | 0 9 files changed, 159 insertions(+) create mode 100644 common/src/main/java/net/rzdata/demo/trait/TreeNode.java create mode 100644 service/system/src/main/java/net/rzdata/demo/dict/DictController.java create mode 100644 service/system/src/main/java/net/rzdata/demo/dict/DictService.java create mode 100644 service/system/src/main/java/net/rzdata/demo/dict/domain/Dict.java create mode 100644 service/system/src/main/java/net/rzdata/demo/dict/mapper/DictMapper.java create mode 100644 service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java create mode 100644 service/system/src/test/java/net/rzdata/demo/DemoTestApplication.java create mode 100644 service/system/src/test/java/net/rzdata/demo/dict/DictServiceTest.java create mode 100644 service/system/src/test/resources/application-test.yml diff --git a/common/src/main/java/net/rzdata/demo/trait/TreeNode.java b/common/src/main/java/net/rzdata/demo/trait/TreeNode.java new file mode 100644 index 0000000..5ab7fd1 --- /dev/null +++ b/common/src/main/java/net/rzdata/demo/trait/TreeNode.java @@ -0,0 +1,18 @@ +package net.rzdata.demo.trait; + +import java.util.List; + +public interface TreeNode, ID> { + + ID getId(); + + ID getParentId(); + + List getChildren(); + + void setChildren(List children); + + default boolean isLeaf() { + return getChildren() == null; + } +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java new file mode 100644 index 0000000..2abfb8b --- /dev/null +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java @@ -0,0 +1,21 @@ +package net.rzdata.demo.dict; + +import net.rzdata.demo.dict.domain.AddDictTypeReq; +import net.rzdata.demo.dict.domain.Dict; +import net.rzdata.demo.dict.domain.UpdateDictReq; +import net.rzdata.domain.Id; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/dict") +public class DictController { + + private final DictService dictService; + + public DictController(DictService dictService) { + this.dictService = dictService; + } +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java new file mode 100644 index 0000000..2f41fab --- /dev/null +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java @@ -0,0 +1,16 @@ +package net.rzdata.demo.dict; + +import net.rzdata.demo.dict.domain.Dict; +import net.rzdata.demo.dict.mapper.DictMapper; +import net.rzdata.demo.dict.mapper.DictRepository; +import org.springframework.stereotype.Service; + +@Service +public class DictService { + + private final DictRepository dictRepository; + + public DictService(DictRepository dictRepository) { + this.dictRepository = dictRepository; + } +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/domain/Dict.java b/service/system/src/main/java/net/rzdata/demo/dict/domain/Dict.java new file mode 100644 index 0000000..dee7e75 --- /dev/null +++ b/service/system/src/main/java/net/rzdata/demo/dict/domain/Dict.java @@ -0,0 +1,58 @@ +package net.rzdata.demo.dict.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.*; +import net.rzdata.demo.trait.TreeNode; + +import java.util.Collections; +import java.util.List; + +/** + * 字典 + */ +@Getter +@Setter +@ToString +@NoArgsConstructor +@AllArgsConstructor +public class Dict implements TreeNode { + + public static final Dict ROOT = new Dict("0", "字典", "dict", "dict", 0, false, "0", Collections.emptyList()); + + /** + * 字典主键 + */ + @TableId(type = IdType.ASSIGN_ID) + String id; + /** + * 字典标签 + */ + String label; + /** + * 字典键值 + */ + String value; + /** + * 字典类型 + */ + String type; + /** + * 字典排序 + */ + Integer sort; + /** + * 是否停用 + */ + Boolean disabled; + /** + * 父节点ID + */ + String parentId; + /** + * 子节点 + */ + @TableField(exist = false) + List children; +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictMapper.java b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictMapper.java new file mode 100644 index 0000000..d307a19 --- /dev/null +++ b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictMapper.java @@ -0,0 +1,9 @@ +package net.rzdata.demo.dict.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.rzdata.demo.dict.domain.Dict; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface DictMapper extends BaseMapper { +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java new file mode 100644 index 0000000..b8cbe79 --- /dev/null +++ b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java @@ -0,0 +1,13 @@ +package net.rzdata.demo.dict.mapper; + +import net.rzdata.demo.dict.domain.Dict; +import net.rzdata.demo.trait.BaseRepository; +import org.springframework.stereotype.Repository; + +@Repository +public class DictRepository extends BaseRepository { + + public DictRepository(DictMapper mapper) { + super(mapper); + } +} diff --git a/service/system/src/test/java/net/rzdata/demo/DemoTestApplication.java b/service/system/src/test/java/net/rzdata/demo/DemoTestApplication.java new file mode 100644 index 0000000..41bee7f --- /dev/null +++ b/service/system/src/test/java/net/rzdata/demo/DemoTestApplication.java @@ -0,0 +1,12 @@ +package net.rzdata.demo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoTestApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoTestApplication.class, args); + } +} diff --git a/service/system/src/test/java/net/rzdata/demo/dict/DictServiceTest.java b/service/system/src/test/java/net/rzdata/demo/dict/DictServiceTest.java new file mode 100644 index 0000000..c45114a --- /dev/null +++ b/service/system/src/test/java/net/rzdata/demo/dict/DictServiceTest.java @@ -0,0 +1,12 @@ +package net.rzdata.demo.dict; + +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DictServiceTest { + + @Resource + private transient DictService dictService; +} diff --git a/service/system/src/test/resources/application-test.yml b/service/system/src/test/resources/application-test.yml new file mode 100644 index 0000000..e69de29 From 90d9af2eb270a8b0a444af3784ca009403f53191 Mon Sep 17 00:00:00 2001 From: jiangdingxuan Date: Mon, 8 Jan 2024 14:37:08 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AD=97=E5=85=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rzdata/exception/RepeatDataException.java | 18 ++++++ .../net/rzdata/demo/dict/DictController.java | 15 ++++- .../net/rzdata/demo/dict/DictService.java | 25 +++++++- .../rzdata/demo/dict/domain/AddDictReq.java | 58 +++++++++++++++++++ .../demo/dict/mapper/DictRepository.java | 10 ++++ .../net/rzdata/demo/dict/DictServiceTest.java | 8 +++ 6 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/net/rzdata/exception/RepeatDataException.java create mode 100644 service/system/src/main/java/net/rzdata/demo/dict/domain/AddDictReq.java diff --git a/core/src/main/java/net/rzdata/exception/RepeatDataException.java b/core/src/main/java/net/rzdata/exception/RepeatDataException.java new file mode 100644 index 0000000..502ed07 --- /dev/null +++ b/core/src/main/java/net/rzdata/exception/RepeatDataException.java @@ -0,0 +1,18 @@ +package net.rzdata.exception; + +/** + * 数据重复异常 + */ +public class RepeatDataException extends ClientException { + + public static final String ERROR_CODE = "A0428"; + public static final String ERROR_MESSAGE = "数据已存在"; + + public RepeatDataException() { + super(ERROR_CODE, ERROR_MESSAGE); + } + + public RepeatDataException(String message) { + super(ERROR_CODE, message); + } +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java index 2abfb8b..e6d2ee3 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java @@ -1,11 +1,9 @@ package net.rzdata.demo.dict; -import net.rzdata.demo.dict.domain.AddDictTypeReq; +import net.rzdata.demo.dict.domain.AddDictReq; import net.rzdata.demo.dict.domain.Dict; -import net.rzdata.demo.dict.domain.UpdateDictReq; import net.rzdata.domain.Id; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -18,4 +16,15 @@ public class DictController { public DictController(DictService dictService) { this.dictService = dictService; } + + @PostMapping() + public Id addDictData(AddDictReq req) { + Dict dict = req.into(); + if (dict.getParentId() == null) { + dict.setParentId(Dict.ROOT.getId()); + dict.setType(Dict.ROOT.getType()); + } + dictService.addDict(dict); + return Id.of(dict.getId()); + } } diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java index 2f41fab..86d790f 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java @@ -1,10 +1,14 @@ package net.rzdata.demo.dict; import net.rzdata.demo.dict.domain.Dict; -import net.rzdata.demo.dict.mapper.DictMapper; import net.rzdata.demo.dict.mapper.DictRepository; +import net.rzdata.exception.RepeatDataException; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + @Service public class DictService { @@ -13,4 +17,23 @@ public class DictService { public DictService(DictRepository dictRepository) { this.dictRepository = dictRepository; } + + protected void addDict(Dict dict) { + Optional exist = this.getDictByTypeAndValue(dict.getType(), dict.getValue()); + if (exist.isPresent()) { + throw new RepeatDataException(String.format("字典类型:%s, 值:%s 已存在", dict.getType(), dict.getValue())); + } + dictRepository.get().insert(dict); + } + + protected List getDictByType(String type) { + return dictRepository.findByTypeOrderBySortAsc(type); + } + + private Optional getDictByTypeAndValue(String type, String value) { + List dictList = this.getDictByType(type); + return dictList.parallelStream() + .filter(d -> Objects.equals(d.getValue(), value)) + .findAny(); + } } diff --git a/service/system/src/main/java/net/rzdata/demo/dict/domain/AddDictReq.java b/service/system/src/main/java/net/rzdata/demo/dict/domain/AddDictReq.java new file mode 100644 index 0000000..594bc5e --- /dev/null +++ b/service/system/src/main/java/net/rzdata/demo/dict/domain/AddDictReq.java @@ -0,0 +1,58 @@ +package net.rzdata.demo.dict.domain; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import net.rzdata.trait.IConverter; +import net.rzdata.trait.IQuery; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Getter +@Setter +@ToString +public class AddDictReq implements IQuery { + + /** + * 字典标签 + */ + private String label; + /** + * 字典值 + */ + private String value; + /** + * 字典类型 + */ + private String type; + /** + * 父级ID + * 如果是顶级字典 则为0 + */ + private String parentId; + /** + * 排序 + */ + private Integer sort; + /** + * 是否禁用 + */ + private Boolean disabled; + + @Override + public Dict into() { + return AddDictReqConverter.INSTANCE.convert(this); + } +} + +@Mapper +interface AddDictReqConverter extends IConverter { + + AddDictReqConverter INSTANCE = Mappers.getMapper(AddDictReqConverter.class); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "children", ignore = true) + @Override + Dict convert(AddDictReq req); +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java index b8cbe79..4dbdf0b 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java @@ -1,13 +1,23 @@ package net.rzdata.demo.dict.mapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import net.rzdata.demo.dict.domain.Dict; import net.rzdata.demo.trait.BaseRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public class DictRepository extends BaseRepository { public DictRepository(DictMapper mapper) { super(mapper); } + + public List findByTypeOrderBySortAsc(String type) { + return this.get().selectList(new LambdaQueryWrapper() + .eq(Dict::getType, type) + .orderByAsc(Dict::getSort) + ); + } } diff --git a/service/system/src/test/java/net/rzdata/demo/dict/DictServiceTest.java b/service/system/src/test/java/net/rzdata/demo/dict/DictServiceTest.java index c45114a..27f03f6 100644 --- a/service/system/src/test/java/net/rzdata/demo/dict/DictServiceTest.java +++ b/service/system/src/test/java/net/rzdata/demo/dict/DictServiceTest.java @@ -9,4 +9,12 @@ class DictServiceTest { @Resource private transient DictService dictService; + + @Test + void addDict() { + } + + @Test + void getDictByType() { + } } From 711e20c0402d38f470dd23652c161bdd005f54b9 Mon Sep 17 00:00:00 2001 From: jiangdingxuan Date: Mon, 8 Jan 2024 14:44:43 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=AD=97=E5=85=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/NotExistDataException.java | 18 ++++++ .../net/rzdata/demo/dict/DictController.java | 11 +++- .../net/rzdata/demo/dict/DictService.java | 28 ++++++++-- .../demo/dict/domain/UpdateDictReq.java | 56 +++++++++++++++++++ .../demo/dict/mapper/DictRepository.java | 8 +++ 5 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 core/src/main/java/net/rzdata/exception/NotExistDataException.java create mode 100644 service/system/src/main/java/net/rzdata/demo/dict/domain/UpdateDictReq.java diff --git a/core/src/main/java/net/rzdata/exception/NotExistDataException.java b/core/src/main/java/net/rzdata/exception/NotExistDataException.java new file mode 100644 index 0000000..ab32ae1 --- /dev/null +++ b/core/src/main/java/net/rzdata/exception/NotExistDataException.java @@ -0,0 +1,18 @@ +package net.rzdata.exception; + +/** + * 操作不存在的数据异常 + */ +public class NotExistDataException extends ClientException { + + public static final String ERROR_CODE = "A0429"; + public static final String ERROR_MESSAGE = "数据不存在"; + + public NotExistDataException() { + super(ERROR_CODE, ERROR_MESSAGE); + } + + public NotExistDataException(String message) { + super(ERROR_CODE, message); + } +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java index e6d2ee3..71a9ed8 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java @@ -2,8 +2,10 @@ package net.rzdata.demo.dict; import net.rzdata.demo.dict.domain.AddDictReq; import net.rzdata.demo.dict.domain.Dict; +import net.rzdata.demo.dict.domain.UpdateDictReq; import net.rzdata.domain.Id; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -18,7 +20,7 @@ public class DictController { } @PostMapping() - public Id addDictData(AddDictReq req) { + public Id addDict(AddDictReq req) { Dict dict = req.into(); if (dict.getParentId() == null) { dict.setParentId(Dict.ROOT.getId()); @@ -27,4 +29,11 @@ public class DictController { dictService.addDict(dict); return Id.of(dict.getId()); } + + @PutMapping() + public Id updateDict(UpdateDictReq req) { + Dict dict = req.into(); + dictService.updateDict(dict); + return Id.of(dict.getId()); + } } diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java index 86d790f..50d94a6 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java @@ -2,6 +2,7 @@ package net.rzdata.demo.dict; import net.rzdata.demo.dict.domain.Dict; import net.rzdata.demo.dict.mapper.DictRepository; +import net.rzdata.exception.NotExistDataException; import net.rzdata.exception.RepeatDataException; import org.springframework.stereotype.Service; @@ -19,10 +20,7 @@ public class DictService { } protected void addDict(Dict dict) { - Optional exist = this.getDictByTypeAndValue(dict.getType(), dict.getValue()); - if (exist.isPresent()) { - throw new RepeatDataException(String.format("字典类型:%s, 值:%s 已存在", dict.getType(), dict.getValue())); - } + check(dict); dictRepository.get().insert(dict); } @@ -30,10 +28,32 @@ public class DictService { return dictRepository.findByTypeOrderBySortAsc(type); } + protected void updateDict(Dict dict) { + Dict exist = dictRepository.get().selectById(dict.getId()); + if (exist == null) { + throw new NotExistDataException("字典已被删除,无法更新"); + } + if (!Objects.equals(dict.getValue(), exist.getValue())) { + check(dict); + } + dictRepository.get().updateById(dict); + // 如果是字典类 则需要更新该类下所有值的type字段 + if (Objects.equals(exist.getParentId(), Dict.ROOT.getId())) { + dictRepository.updateType(exist.getType(), dict.getType()); + } + } + private Optional getDictByTypeAndValue(String type, String value) { List dictList = this.getDictByType(type); return dictList.parallelStream() .filter(d -> Objects.equals(d.getValue(), value)) .findAny(); } + + private void check(Dict dict) { + Optional exist = this.getDictByTypeAndValue(dict.getType(), dict.getValue()); + if (exist.isPresent()) { + throw new RepeatDataException(String.format("字典类型:%s, 值:%s 已存在", dict.getType(), dict.getValue())); + } + } } diff --git a/service/system/src/main/java/net/rzdata/demo/dict/domain/UpdateDictReq.java b/service/system/src/main/java/net/rzdata/demo/dict/domain/UpdateDictReq.java new file mode 100644 index 0000000..46f79a7 --- /dev/null +++ b/service/system/src/main/java/net/rzdata/demo/dict/domain/UpdateDictReq.java @@ -0,0 +1,56 @@ +package net.rzdata.demo.dict.domain; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import net.rzdata.trait.IConverter; +import net.rzdata.trait.IQuery; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +@Getter +@Setter +@ToString +public class UpdateDictReq implements IQuery { + + /** + * 字典ID + */ + private String id; + /** + * 字典标签 + */ + private String label; + /** + * 字典值 + */ + private String value; + /** + * 排序 + */ + private Integer sort; + /** + * 父级ID + */ + private String parentId; + /** + * 是否禁用 + */ + private Boolean disabled; + + public Dict into() { + return UpdateDictReqConverter.INSTANCE.convert(this); + } +} + +@Mapper +interface UpdateDictReqConverter extends IConverter { + + UpdateDictReqConverter INSTANCE = Mappers.getMapper(UpdateDictReqConverter.class); + + @Mapping(target = "type", ignore = true) + @Mapping(target = "children", ignore = true) + @Override + Dict convert(UpdateDictReq req); +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java index 4dbdf0b..9b86f1b 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java @@ -1,6 +1,7 @@ package net.rzdata.demo.dict.mapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import net.rzdata.demo.dict.domain.Dict; import net.rzdata.demo.trait.BaseRepository; import org.springframework.stereotype.Repository; @@ -20,4 +21,11 @@ public class DictRepository extends BaseRepository { .orderByAsc(Dict::getSort) ); } + + public int updateType(String oldValue, String newValue) { + return this.get().update(null, new LambdaUpdateWrapper() + .set(Dict::getType, newValue) + .eq(Dict::getType, oldValue) + ); + } } From a4315b8f6fdf20dfb8bb1a0b9d15759d75044b98 Mon Sep 17 00:00:00 2001 From: jiangdingxuan Date: Mon, 8 Jan 2024 15:30:58 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E9=80=9A=E8=BF=87=20Liquibase=20=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E6=95=B0=E6=8D=AE=E5=BA=93=E7=89=88=E6=9C=AC=E6=8E=A7?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- service/system/pom.xml | 6 ++++++ .../src/main/resources/config/application.yml | 2 ++ .../resources/db/changelog/db.changelog-master.yaml | 3 +++ .../src/main/resources/db/changelog/sql/dict.sql | 13 +++++++++++++ 4 files changed, 24 insertions(+) create mode 100644 service/system/src/main/resources/db/changelog/db.changelog-master.yaml create mode 100644 service/system/src/main/resources/db/changelog/sql/dict.sql diff --git a/service/system/pom.xml b/service/system/pom.xml index 5843d8a..0b490c7 100644 --- a/service/system/pom.xml +++ b/service/system/pom.xml @@ -18,4 +18,10 @@ 4567 + + + org.liquibase + liquibase-core + + diff --git a/service/system/src/main/resources/config/application.yml b/service/system/src/main/resources/config/application.yml index 8e7d599..24b174d 100644 --- a/service/system/src/main/resources/config/application.yml +++ b/service/system/src/main/resources/config/application.yml @@ -19,3 +19,5 @@ spring: maximum-pool-size: 20 idle-timeout: 30000 max-lifetime: 1800000 + liquibase: + change-log: classpath:/db/changelog/db.changelog-master.yaml diff --git a/service/system/src/main/resources/db/changelog/db.changelog-master.yaml b/service/system/src/main/resources/db/changelog/db.changelog-master.yaml new file mode 100644 index 0000000..062d441 --- /dev/null +++ b/service/system/src/main/resources/db/changelog/db.changelog-master.yaml @@ -0,0 +1,3 @@ +databaseChangeLog: + - includeAll: + path: db/changelog/sql diff --git a/service/system/src/main/resources/db/changelog/sql/dict.sql b/service/system/src/main/resources/db/changelog/sql/dict.sql new file mode 100644 index 0000000..fa331fc --- /dev/null +++ b/service/system/src/main/resources/db/changelog/sql/dict.sql @@ -0,0 +1,13 @@ +create table dict +( + id varchar(64) not null comment '字典主键', + label varchar(255) not null comment '字典标签', + value varchar(255) not null comment '字典键值', + type varchar(255) not null comment '字典类型', + sort int default 1 not null comment '字典排序', + disabled bool default false not null comment '是否停用', + parent_id varchar(64) default 0 not null comment '父级字典主键', + constraint table_name_pk primary key (id), + constraint table_name_uk_type_value unique (type, value) +) comment '字典'; + From d6516cafa9921d25f86c3181c3e664f3fa64ccb4 Mon Sep 17 00:00:00 2001 From: jiangdingxuan Date: Mon, 8 Jan 2024 15:38:41 +0800 Subject: [PATCH 5/8] =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/net/rzdata/demo/dict/DictController.java | 9 +++------ .../java/net/rzdata/demo/dict/domain/AddDictReq.java | 9 +++++++++ .../java/net/rzdata/demo/dict/domain/UpdateDictReq.java | 8 ++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java index 71a9ed8..337721c 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java @@ -4,10 +4,7 @@ import net.rzdata.demo.dict.domain.AddDictReq; import net.rzdata.demo.dict.domain.Dict; import net.rzdata.demo.dict.domain.UpdateDictReq; import net.rzdata.domain.Id; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/dict") @@ -20,7 +17,7 @@ public class DictController { } @PostMapping() - public Id addDict(AddDictReq req) { + public Id addDict(@RequestBody AddDictReq req) { Dict dict = req.into(); if (dict.getParentId() == null) { dict.setParentId(Dict.ROOT.getId()); @@ -31,7 +28,7 @@ public class DictController { } @PutMapping() - public Id updateDict(UpdateDictReq req) { + public Id updateDict(@RequestBody UpdateDictReq req) { Dict dict = req.into(); dictService.updateDict(dict); return Id.of(dict.getId()); diff --git a/service/system/src/main/java/net/rzdata/demo/dict/domain/AddDictReq.java b/service/system/src/main/java/net/rzdata/demo/dict/domain/AddDictReq.java index 594bc5e..c33338e 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/domain/AddDictReq.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/domain/AddDictReq.java @@ -1,5 +1,8 @@ package net.rzdata.demo.dict.domain; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -17,14 +20,19 @@ public class AddDictReq implements IQuery { /** * 字典标签 */ + @Max(255) private String label; /** * 字典值 */ + @Max(255) + @NotNull(message = "字典值不能为空") + @Pattern(regexp = "[\\w-]+", message = "字典值只允许英文字母、下划线、短横线") private String value; /** * 字典类型 */ + @NotNull(message = "字典类型不能为空") private String type; /** * 父级ID @@ -34,6 +42,7 @@ public class AddDictReq implements IQuery { /** * 排序 */ + @NotNull(message = "排序值不能为空") private Integer sort; /** * 是否禁用 diff --git a/service/system/src/main/java/net/rzdata/demo/dict/domain/UpdateDictReq.java b/service/system/src/main/java/net/rzdata/demo/dict/domain/UpdateDictReq.java index 46f79a7..9dc1b1f 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/domain/UpdateDictReq.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/domain/UpdateDictReq.java @@ -1,5 +1,8 @@ package net.rzdata.demo.dict.domain; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; import lombok.Getter; import lombok.Setter; import lombok.ToString; @@ -21,14 +24,19 @@ public class UpdateDictReq implements IQuery { /** * 字典标签 */ + @Max(255) private String label; /** * 字典值 */ + @Max(255) + @NotNull(message = "字典值不能为空") + @Pattern(regexp = "[\\w-]+", message = "字典值只允许英文字母、下划线、短横线") private String value; /** * 排序 */ + @NotNull(message = "排序值不能为空") private Integer sort; /** * 父级ID From 8eebf7e94c3c1cdf97a64202661bf354228ebc0c Mon Sep 17 00:00:00 2001 From: jiangdingxuan Date: Mon, 8 Jan 2024 16:47:17 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=AD=97=E5=85=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/net/rzdata/demo/trait/GetReq.java | 29 +++++++++++ .../net/rzdata/demo/dict/DictController.java | 49 +++++++++++++++++++ .../net/rzdata/demo/dict/DictService.java | 31 ++++++++++-- .../demo/dict/domain/GetDictTypeListReq.java | 6 +++ .../demo/dict/mapper/DictRepository.java | 13 +++++ 5 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 common/src/main/java/net/rzdata/demo/trait/GetReq.java create mode 100644 service/system/src/main/java/net/rzdata/demo/dict/domain/GetDictTypeListReq.java diff --git a/common/src/main/java/net/rzdata/demo/trait/GetReq.java b/common/src/main/java/net/rzdata/demo/trait/GetReq.java new file mode 100644 index 0000000..be01903 --- /dev/null +++ b/common/src/main/java/net/rzdata/demo/trait/GetReq.java @@ -0,0 +1,29 @@ +package net.rzdata.demo.trait; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +public class GetReq { + + private Integer pageSize = 15; + private Integer pageNum = 1; + private String orderBy; + private Boolean asc = true; + + public IPage into() { + Page page = new Page<>(); + page.setSize(pageSize); + page.setCurrent(pageNum - 1); + if (orderBy != null) { + page.addOrder(this.asc ? OrderItem.asc(orderBy) : OrderItem.desc(orderBy)); + } + return page; + } +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java index 337721c..6e1aa1c 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java @@ -1,11 +1,16 @@ package net.rzdata.demo.dict; +import com.baomidou.mybatisplus.core.metadata.IPage; import net.rzdata.demo.dict.domain.AddDictReq; import net.rzdata.demo.dict.domain.Dict; +import net.rzdata.demo.dict.domain.GetDictTypeListReq; import net.rzdata.demo.dict.domain.UpdateDictReq; import net.rzdata.domain.Id; import org.springframework.web.bind.annotation.*; +import java.util.Collections; +import java.util.List; + @RestController @RequestMapping("/dict") public class DictController { @@ -16,6 +21,11 @@ public class DictController { this.dictService = dictService; } + /** + * 新增字典 + * @param req 新增字典请求 + * @return 新增字典的ID + */ @PostMapping() public Id addDict(@RequestBody AddDictReq req) { Dict dict = req.into(); @@ -27,10 +37,49 @@ public class DictController { return Id.of(dict.getId()); } + /** + * 更新字典 + * @param req 更新字典请求 + * @return 字典的ID + */ @PutMapping() public Id updateDict(@RequestBody UpdateDictReq req) { Dict dict = req.into(); dictService.updateDict(dict); return Id.of(dict.getId()); } + + /** + * 获取字典类型列表 + * @param req 获取字典类型列表请求 + * @return 字典类型列表(分页) + */ + @GetMapping("/type") + public IPage getDictTypePage(@RequestParam GetDictTypeListReq req) { + return dictService.getDictTypePage(req); + } + + /** + * 获取字典树 + * @param parentId 父ID + * @param level 层级 + * @return 字典树 + */ + @GetMapping("/tree") + public List getDictTree( + @RequestParam(required = false, defaultValue = "0") String parentId, + @RequestParam(required = false, defaultValue = "-1") Integer level + ) { + return dictService.getDictTreeTopDown(Collections.singleton(parentId), level); + } + + /** + * 获取字典数据 + * @param type 字典类型 + * @return 字典数据 + */ + @GetMapping("/data/{type}") + public List getDictData(@PathVariable String type) { + return dictService.getDictByType(type); + } } diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java index 50d94a6..f1ca1e7 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java @@ -1,14 +1,15 @@ package net.rzdata.demo.dict; +import com.baomidou.mybatisplus.core.metadata.IPage; import net.rzdata.demo.dict.domain.Dict; +import net.rzdata.demo.dict.domain.GetDictTypeListReq; import net.rzdata.demo.dict.mapper.DictRepository; import net.rzdata.exception.NotExistDataException; import net.rzdata.exception.RepeatDataException; import org.springframework.stereotype.Service; -import java.util.List; -import java.util.Objects; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; @Service public class DictService { @@ -43,6 +44,30 @@ public class DictService { } } + protected IPage getDictTypePage(GetDictTypeListReq req) { + return dictRepository.getDictTypePage(req); + } + + protected List getDictTreeTopDown(Collection parentId, int level) { + if (level == 0 || level < Byte.MIN_VALUE) { + return Collections.emptyList(); + } else if (parentId.isEmpty()) { + return Collections.emptyList(); + } + List children = dictRepository.findByParentIdIn(parentId); + Set childIds = children.parallelStream() + .map(Dict::getId) + .collect(Collectors.toSet()); + List grandchildren = getDictTreeTopDown(childIds, level); + for (Dict child : children) { + List grandchild = grandchildren.parallelStream() + .filter(g -> Objects.equals(g.getParentId(), child.getId())) + .toList(); + child.setChildren(grandchild); + } + return children; + } + private Optional getDictByTypeAndValue(String type, String value) { List dictList = this.getDictByType(type); return dictList.parallelStream() diff --git a/service/system/src/main/java/net/rzdata/demo/dict/domain/GetDictTypeListReq.java b/service/system/src/main/java/net/rzdata/demo/dict/domain/GetDictTypeListReq.java new file mode 100644 index 0000000..48a7814 --- /dev/null +++ b/service/system/src/main/java/net/rzdata/demo/dict/domain/GetDictTypeListReq.java @@ -0,0 +1,6 @@ +package net.rzdata.demo.dict.domain; + +import net.rzdata.demo.trait.GetReq; + +public class GetDictTypeListReq extends GetReq { +} diff --git a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java index 9b86f1b..5a137b7 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java @@ -2,10 +2,13 @@ package net.rzdata.demo.dict.mapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; import net.rzdata.demo.dict.domain.Dict; +import net.rzdata.demo.dict.domain.GetDictTypeListReq; import net.rzdata.demo.trait.BaseRepository; import org.springframework.stereotype.Repository; +import java.util.Collection; import java.util.List; @Repository @@ -28,4 +31,14 @@ public class DictRepository extends BaseRepository { .eq(Dict::getType, oldValue) ); } + + public List findByParentIdIn(Collection parentId) { + return this.get().selectList(new LambdaQueryWrapper() + .in(Dict::getParentId, parentId) + ); + } + + public IPage getDictTypePage(GetDictTypeListReq req) { + return this.get().selectPage(req.into(), new LambdaQueryWrapper<>()); + } } From 2ebeb0976b8d9197c988eb0ff26331566f1d2327 Mon Sep 17 00:00:00 2001 From: jiangdingxuan Date: Mon, 8 Jan 2024 17:10:52 +0800 Subject: [PATCH 7/8] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=AD=97=E5=85=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/net/rzdata/demo/dict/DictController.java | 5 +++++ .../src/main/java/net/rzdata/demo/dict/DictService.java | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java index 6e1aa1c..124534d 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java @@ -82,4 +82,9 @@ public class DictController { public List getDictData(@PathVariable String type) { return dictService.getDictByType(type); } + + @DeleteMapping("{id}") + public void deleteDict(@PathVariable String id) { + dictService.deleteDict(Collections.singleton(id)); + } } diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java index f1ca1e7..9c9366c 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java @@ -81,4 +81,11 @@ public class DictService { throw new RepeatDataException(String.format("字典类型:%s, 值:%s 已存在", dict.getType(), dict.getValue())); } } + + public void deleteDict(Collection ids) { + if (ids == null || ids.isEmpty()) { + return; + } + dictRepository.get().deleteBatchIds(ids); + } } From d1f7563cce39376716ae6f3429636b6f6dec1328 Mon Sep 17 00:00:00 2001 From: jiangdingxuan Date: Mon, 8 Jan 2024 17:40:34 +0800 Subject: [PATCH 8/8] =?UTF-8?q?API=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/net/rzdata/demo/trait/GetReq.java | 2 +- .../net/rzdata/demo/dict/DictController.java | 12 +++++++- .../net/rzdata/demo/dict/DictService.java | 28 +++++++++++++++++-- .../demo/dict/mapper/DictRepository.java | 6 +++- .../src/main/resources/config/application.yml | 8 ++++++ 5 files changed, 51 insertions(+), 5 deletions(-) diff --git a/common/src/main/java/net/rzdata/demo/trait/GetReq.java b/common/src/main/java/net/rzdata/demo/trait/GetReq.java index be01903..0f14655 100644 --- a/common/src/main/java/net/rzdata/demo/trait/GetReq.java +++ b/common/src/main/java/net/rzdata/demo/trait/GetReq.java @@ -20,7 +20,7 @@ public class GetReq { public IPage into() { Page page = new Page<>(); page.setSize(pageSize); - page.setCurrent(pageNum - 1); + page.setCurrent(pageNum); if (orderBy != null) { page.addOrder(this.asc ? OrderItem.asc(orderBy) : OrderItem.desc(orderBy)); } diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java index 124534d..18cb671 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictController.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictController.java @@ -55,7 +55,7 @@ public class DictController { * @return 字典类型列表(分页) */ @GetMapping("/type") - public IPage getDictTypePage(@RequestParam GetDictTypeListReq req) { + public IPage getDictTypePage(GetDictTypeListReq req) { return dictService.getDictTypePage(req); } @@ -83,6 +83,16 @@ public class DictController { return dictService.getDictByType(type); } + /** + * 获取字典数据 + * @param type 字典类型 + * @return 字典数据(树形结构) + */ + @GetMapping("/data/{type}/tree") + public List getDictDataTree(@PathVariable String type) { + return dictService.getDictByTypeAsTree(type); + } + @DeleteMapping("{id}") public void deleteDict(@PathVariable String id) { dictService.deleteDict(Collections.singleton(id)); diff --git a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java index 9c9366c..c492dcc 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/DictService.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/DictService.java @@ -29,6 +29,30 @@ public class DictService { return dictRepository.findByTypeOrderBySortAsc(type); } + protected List getDictByTypeAsTree(String type) { + List dictList = dictRepository.findByTypeOrderBySortAsc(type); + Set idSet = dictList.parallelStream() + .map(Dict::getId) + .collect(Collectors.toSet()); + List root = dictList.parallelStream() + .filter(dict -> !idSet.contains(dict.getParentId())) + .toList(); + List increment = root; + while (!increment.isEmpty()) { + for (Dict dict : increment) { + List children = dictList.parallelStream() + .filter(d -> Objects.equals(d.getParentId(), dict.getId())) + .toList(); + dict.setChildren(children); + } + increment = increment.parallelStream() + .map(Dict::getChildren) + .flatMap(List::stream) + .toList(); + } + return root; + } + protected void updateDict(Dict dict) { Dict exist = dictRepository.get().selectById(dict.getId()); if (exist == null) { @@ -40,7 +64,7 @@ public class DictService { dictRepository.get().updateById(dict); // 如果是字典类 则需要更新该类下所有值的type字段 if (Objects.equals(exist.getParentId(), Dict.ROOT.getId())) { - dictRepository.updateType(exist.getType(), dict.getType()); + dictRepository.updateType(exist.getValue(), dict.getValue()); } } @@ -58,7 +82,7 @@ public class DictService { Set childIds = children.parallelStream() .map(Dict::getId) .collect(Collectors.toSet()); - List grandchildren = getDictTreeTopDown(childIds, level); + List grandchildren = getDictTreeTopDown(childIds, level - 1); for (Dict child : children) { List grandchild = grandchildren.parallelStream() .filter(g -> Objects.equals(g.getParentId(), child.getId())) diff --git a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java index 5a137b7..f5fc8f3 100644 --- a/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java +++ b/service/system/src/main/java/net/rzdata/demo/dict/mapper/DictRepository.java @@ -35,10 +35,14 @@ public class DictRepository extends BaseRepository { public List findByParentIdIn(Collection parentId) { return this.get().selectList(new LambdaQueryWrapper() .in(Dict::getParentId, parentId) + .orderByAsc(Dict::getSort) ); } public IPage getDictTypePage(GetDictTypeListReq req) { - return this.get().selectPage(req.into(), new LambdaQueryWrapper<>()); + return this.get().selectPage(req.into(), new LambdaQueryWrapper() + .eq(Dict::getParentId, Dict.ROOT.getId()) + .orderByAsc(Dict::getSort) + ); } } diff --git a/service/system/src/main/resources/config/application.yml b/service/system/src/main/resources/config/application.yml index 24b174d..89a3e1c 100644 --- a/service/system/src/main/resources/config/application.yml +++ b/service/system/src/main/resources/config/application.yml @@ -21,3 +21,11 @@ spring: max-lifetime: 1800000 liquibase: change-log: classpath:/db/changelog/db.changelog-master.yaml +mybatis-plus: + configuration: + log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl +logging: + level: + root: info + net.rzdata: debug + com.baomidou.example.mapper: debug