diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/annotation/DictField.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/annotation/DictField.java
new file mode 100644
index 00000000..d1ed5ea1
--- /dev/null
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/annotation/DictField.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package top.continew.starter.extension.crud.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 字典结构字段
+ *
+ * @author Charles7c
+ * @since 2.1.0
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DictField {
+
+ /**
+ * 标签字段名
+ *
+ * @return 标签字段名
+ */
+ String labelKey() default "name";
+
+ /**
+ * 值字段名
+ *
+ * @return 值字段名
+ */
+ String valueKey() default "id";
+}
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/resp/LabelValueResp.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/resp/LabelValueResp.java
new file mode 100644
index 00000000..44a25930
--- /dev/null
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-core/src/main/java/top/continew/starter/extension/crud/model/resp/LabelValueResp.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
+ *
+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.gnu.org/licenses/lgpl.html
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package top.continew.starter.extension.crud.model.resp;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 键值对信息
+ *
+ * @param
+ * @author Charles7c
+ * @since 2.1.0
+ */
+@Schema(description = "键值对信息")
+public class LabelValueResp implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 标签
+ */
+ @Schema(description = "标签", example = "男")
+ private String label;
+
+ /**
+ * 值
+ */
+ @Schema(description = "值", example = "1")
+ private T value;
+
+ /**
+ * 是否禁用
+ */
+ @Schema(description = "是否禁用", example = "false")
+ private Boolean disabled;
+
+ /**
+ * 扩展
+ */
+ @Schema(description = "扩展")
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private Object extend;
+
+ public LabelValueResp() {
+ }
+
+ public LabelValueResp(String label, T value) {
+ this.label = label;
+ this.value = value;
+ }
+
+ public LabelValueResp(String label, T value, Object extend) {
+ this.label = label;
+ this.value = value;
+ this.extend = extend;
+ }
+
+ public LabelValueResp(String label, T value, Boolean disabled) {
+ this.label = label;
+ this.value = value;
+ this.disabled = disabled;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public T getValue() {
+ return value;
+ }
+
+ public void setValue(T value) {
+ this.value = value;
+ }
+
+ public Boolean getDisabled() {
+ return disabled;
+ }
+
+ public void setDisabled(Boolean disabled) {
+ this.disabled = disabled;
+ }
+
+ public Object getExtend() {
+ return extend;
+ }
+
+ public void setExtend(Object extend) {
+ this.extend = extend;
+ }
+}
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/service/BaseService.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/service/BaseService.java
index e4c89ffc..63689a8e 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/service/BaseService.java
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mf/src/main/java/top/continew/starter/extension/crud/service/BaseService.java
@@ -20,6 +20,7 @@ import cn.hutool.core.lang.tree.Tree;
import jakarta.servlet.http.HttpServletResponse;
import top.continew.starter.extension.crud.model.query.SortQuery;
import top.continew.starter.extension.crud.model.query.PageQuery;
+import top.continew.starter.extension.crud.model.resp.LabelValueResp;
import top.continew.starter.extension.crud.model.resp.PageResp;
import java.util.List;
@@ -72,6 +73,15 @@ public interface BaseService {
*/
D get(Long id);
+ /**
+ * 查询字典列表
+ *
+ * @param query 查询条件
+ * @param sortQuery 排序查询条件
+ * @return 字典列表信息
+ */
+ List listDict(Q query, SortQuery sortQuery);
+
/**
* 新增
*
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/BaseService.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/BaseService.java
index 64733b9f..d163c3ae 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/BaseService.java
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/BaseService.java
@@ -18,9 +18,10 @@ package top.continew.starter.extension.crud.service;
import cn.hutool.core.lang.tree.Tree;
import jakarta.servlet.http.HttpServletResponse;
-import top.continew.starter.extension.crud.model.query.SortQuery;
-import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.extension.crud.model.query.PageQuery;
+import top.continew.starter.extension.crud.model.query.SortQuery;
+import top.continew.starter.extension.crud.model.resp.LabelValueResp;
+import top.continew.starter.extension.crud.model.resp.PageResp;
import java.util.List;
@@ -65,13 +66,23 @@ public interface BaseService {
List list(Q query, SortQuery sortQuery);
/**
- * 查看详情
+ * 查询详情
*
* @param id ID
* @return 详情信息
*/
D get(Long id);
+ /**
+ * 查询字典列表
+ *
+ * @param query 查询条件
+ * @param sortQuery 排序查询条件
+ * @return 字典列表信息
+ * @since 2.1.0
+ */
+ List listDict(Q query, SortQuery sortQuery);
+
/**
* 新增
*
diff --git a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
index f3968a1b..e61fbd2b 100644
--- a/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
+++ b/continew-starter-extension/continew-starter-extension-crud/continew-starter-extension-crud-mp/src/main/java/top/continew/starter/extension/crud/service/impl/BaseServiceImpl.java
@@ -23,6 +23,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
+import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.extra.spring.SpringUtil;
@@ -34,13 +35,16 @@ import org.springframework.transaction.annotation.Transactional;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.util.ClassUtils;
import top.continew.starter.core.util.ReflectUtils;
+import top.continew.starter.core.util.validate.CheckUtils;
import top.continew.starter.core.util.validate.ValidationUtils;
import top.continew.starter.data.mybatis.plus.base.BaseMapper;
import top.continew.starter.data.mybatis.plus.query.QueryWrapperHelper;
import top.continew.starter.data.mybatis.plus.service.impl.ServiceImpl;
+import top.continew.starter.extension.crud.annotation.DictField;
import top.continew.starter.extension.crud.annotation.TreeField;
import top.continew.starter.extension.crud.model.entity.BaseIdDO;
import top.continew.starter.extension.crud.model.query.SortQuery;
+import top.continew.starter.extension.crud.model.resp.LabelValueResp;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.extension.crud.service.BaseService;
import top.continew.starter.extension.crud.util.TreeUtils;
@@ -48,9 +52,7 @@ import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.file.excel.util.ExcelUtils;
import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
/**
* 业务实现基类
@@ -126,6 +128,23 @@ public abstract class BaseServiceImpl, T extends BaseIdD
return detail;
}
+ @Override
+ public List listDict(Q query, SortQuery sortQuery) {
+ QueryWrapper queryWrapper = this.buildQueryWrapper(query);
+ this.sort(queryWrapper, sortQuery);
+ DictField dictField = entityClass.getDeclaredAnnotation(DictField.class);
+ CheckUtils.throwIfNull(dictField, "请添加并配置 @DictField 字典结构信息");
+ // 指定查询字典字段
+ queryWrapper.select(dictField.labelKey(), dictField.valueKey());
+ List entityList = baseMapper.selectList(queryWrapper);
+ // 解析映射
+ Map fieldMapping = MapUtil.newHashMap(2);
+ fieldMapping.put(dictField.labelKey(), "label");
+ fieldMapping.put(dictField.valueKey(), "value");
+ return BeanUtil.copyToList(entityList, LabelValueResp.class, CopyOptions.create()
+ .setFieldMapping(fieldMapping));
+ }
+
@Override
@Transactional(rollbackFor = Exception.class)
public Long add(C req) {