diff --git a/cutejava-front/src/api/features/cute-dynamic-table.js b/cutejava-front/src/api/features/cute-dynamic-table.js
new file mode 100644
index 00000000..10e1992b
--- /dev/null
+++ b/cutejava-front/src/api/features/cute-dynamic-table.js
@@ -0,0 +1,12 @@
+import request from '@/utils/request'
+
+export function searchMenu(query) {
+ return request({
+ url: 'api/features/CuteDynamicTable/searchMenu',
+ method: 'post',
+ data: query
+ })
+}
+
+export default { searchMenu }
+
diff --git a/cutejava-front/src/views/components/advanced/CuteDragTable.vue b/cutejava-front/src/views/components/advanced/CuteDragTable.vue
index a5e1aa83..91bbd956 100644
--- a/cutejava-front/src/views/components/advanced/CuteDragTable.vue
+++ b/cutejava-front/src/views/components/advanced/CuteDragTable.vue
@@ -37,17 +37,18 @@
>
- crud.onPageChange(pageProps.current, size, pageProps.total)"
- @current-change="(current) => crud.onPageChange(current, pageProps.pageSize, pageProps.total)"
- />
-
+
+ crud.onPageChange(pageProps.current, size, pageProps.total)"
+ @current-change="(current) => crud.onPageChange(current, pageProps.pageSize, pageProps.total)"
+ />
+
+
diff --git a/cutejava-front/src/views/componentsDemo/advanced/CuteSimpleTableDemo.vue b/cutejava-front/src/views/componentsDemo/advanced/CuteSimpleTableDemo.vue
index aa4dfeff..d43ad31c 100644
--- a/cutejava-front/src/views/componentsDemo/advanced/CuteSimpleTableDemo.vue
+++ b/cutejava-front/src/views/componentsDemo/advanced/CuteSimpleTableDemo.vue
@@ -74,7 +74,7 @@ export default {
},
curd: {
paramsTransform: (pageProps) => {
- const values = this.form.model
+ const values = this.form
return {
page: pageProps.current,
size: pageProps.pageSize,
@@ -86,12 +86,6 @@ export default {
fetch: async(queryParams) => {
return DictService.searchDict(queryParams)
},
- columns: [
- { prop: 'name', label: '名称' },
- { prop: 'description', label: '描述' },
- { prop: 'createTime', label: '创建时间', formatter: FormatRowDateTimeStr },
- { prop: 'createBy', label: '创建人' }
- ],
pageProps: {
current: 1,
pageSize: 10,
diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/CuteDynamicTableDemoApi.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/CuteDynamicTableDemoApi.java
new file mode 100644
index 00000000..59c71736
--- /dev/null
+++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/CuteDynamicTableDemoApi.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2021-2026 Odboy
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 cn.odboy.system.features;
+
+import cn.hutool.core.util.StrUtil;
+import cn.odboy.base.KitPageArgs;
+import cn.odboy.system.features.core.KitDynamicTableResponse;
+import cn.odboy.system.features.model.SystemMenuDynamicTableModel;
+import cn.odboy.system.dal.dataobject.SystemMenuTb;
+import cn.odboy.system.dal.model.request.SystemQueryMenuArgs;
+import cn.odboy.system.dal.mysql.SystemMenuMapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Api(tags = "系统组件:CuteDynamicTable演示")
+@RequestMapping("/api/features/CuteDynamicTable")
+public class CuteDynamicTableDemoApi {
+
+ @Autowired
+ private SystemMenuMapper systemMenuMapper;
+
+ @ApiOperation("查询动态数据")
+ @PostMapping(value = "/searchMenu")
+ @PreAuthorize("@el.check()")
+ public ResponseEntity> searchMenu(@Validated @RequestBody KitPageArgs pageArgs) {
+ // 请求参数
+ Integer page = pageArgs.getPage();
+ Integer size = pageArgs.getSize();
+ KitPageArgs.OrderBy orderBy = pageArgs.getOrderBy();
+ SystemQueryMenuArgs args = pageArgs.getArgs();
+ // 分页查询
+ QueryWrapper wrapper = new QueryWrapper<>();
+ if (orderBy != null) {
+ orderBy.bindWrapper(wrapper);
+ }
+ IPage iPage = new Page<>(page, size);
+ LambdaQueryWrapper lambda = wrapper.lambda();
+ if (args != null) {
+ lambda.like(StrUtil.isNotBlank(args.getBlurry()), SystemMenuTb::getTitle, args.getBlurry());
+ }
+ IPage pageResult = systemMenuMapper.selectPage(iPage, wrapper);
+ // 响应结果
+ return ResponseEntity.ok(new KitDynamicTableResponse<>(SystemMenuDynamicTableModel.class, "id", pageResult));
+ }
+}
diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/core/KitDynamicTableColumn.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/core/KitDynamicTableColumn.java
new file mode 100644
index 00000000..46660758
--- /dev/null
+++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/core/KitDynamicTableColumn.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021-2026 Odboy
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 cn.odboy.system.features.core;
+
+import java.lang.annotation.*;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
+public @interface KitDynamicTableColumn {
+
+ /**
+ * 标题
+ */
+ String value() default "";
+
+ /**
+ * 宽度
+ */
+ int width() default 0;
+
+ /**
+ * 是否排序字段
+ */
+ boolean sortable() default false;
+}
diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/core/KitDynamicTableResponse.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/core/KitDynamicTableResponse.java
new file mode 100644
index 00000000..17d3799c
--- /dev/null
+++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/core/KitDynamicTableResponse.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2021-2026 Odboy
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 cn.odboy.system.features.core;
+
+import cn.hutool.core.util.ReflectUtil;
+import cn.odboy.base.KitObject;
+import cn.odboy.system.features.model.SystemMenuDynamicTableModel;
+import cn.odboy.system.dal.dataobject.SystemMenuTb;
+import cn.odboy.util.KitBeanUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 动态表格
+ *
+ * @author odboy
+ * @date 2026-02-05
+ */
+@Getter
+public class KitDynamicTableResponse extends KitObject {
+
+ /**
+ * 主键
+ */
+ @Setter
+ private String primaryKey = "id";
+ /**
+ * 表格列定义
+ */
+ private List columns = new ArrayList<>();
+ /**
+ * 数据总数
+ */
+ private Long totalElements;
+ /**
+ * 数据内容
+ */
+ private List content;
+
+ public KitDynamicTableResponse(Class clazz, IPage pageResult) {
+ this.renderColumns(clazz);
+ this.setPage(clazz, pageResult);
+ }
+
+ public KitDynamicTableResponse(Class clazz, String id, IPage pageResult) {
+ this.primaryKey = id;
+ this.renderColumns(clazz);
+ this.setPage(clazz, pageResult);
+ }
+
+ private void renderColumns(Class clazz) {
+ List columns = new ArrayList<>();
+ if (clazz == null) {
+ this.columns = columns;
+ return;
+ }
+ Field[] fields = ReflectUtil.getFields(clazz);
+ for (Field field : fields) {
+ if ("serialVersionUID".equals(field.getName())) {
+ continue;
+ }
+ Column column = new Column();
+ column.setName(field.getName());
+ KitDynamicTableColumn annotation = field.getAnnotation(KitDynamicTableColumn.class);
+ if (annotation == null) {
+ column.setTitle(field.getName());
+ column.setWidth(null);
+ } else {
+ column.setTitle(annotation.value());
+ column.setWidth(annotation.width() == 0 ? null : annotation.width());
+ column.setSortable(annotation.sortable());
+ }
+ columns.add(column);
+ }
+ this.columns = columns;
+ }
+
+ public void setPage(Class clazz, IPage pageResult) {
+ if (pageResult == null) {
+ return;
+ }
+ this.totalElements = pageResult.getTotal();
+ this.content = KitBeanUtil.copyToList(pageResult.getRecords(), clazz);
+ }
+
+ @Getter
+ @Setter
+ public static class Column {
+
+ /**
+ * 索引名称
+ */
+ private String name;
+ /**
+ * 索引标题
+ */
+ private String title;
+ /**
+ * 表格宽度
+ */
+ private Integer width;
+ /**
+ * 是否排序列
+ */
+ private Boolean sortable = false;
+ }
+
+ public static void main(String[] args) {
+ KitDynamicTableResponse response = new KitDynamicTableResponse<>(SystemMenuDynamicTableModel.class, "id", new Page<>());
+ System.err.println(response);
+ }
+}
diff --git a/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/model/SystemMenuDynamicTableModel.java b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/model/SystemMenuDynamicTableModel.java
new file mode 100644
index 00000000..ce9febe5
--- /dev/null
+++ b/cutejava/cutejava-module-system/src/main/java/cn/odboy/system/features/model/SystemMenuDynamicTableModel.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021-2026 Odboy
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 cn.odboy.system.features.model;
+
+import cn.odboy.base.KitObject;
+import cn.odboy.system.features.core.KitDynamicTableColumn;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class SystemMenuDynamicTableModel extends KitObject {
+
+ @KitDynamicTableColumn(value = "ID")
+ private Long id;
+ @KitDynamicTableColumn(value = "菜单标题")
+ private String title;
+ @KitDynamicTableColumn(value = "菜单组件名称")
+ private String componentName;
+ @KitDynamicTableColumn(value = "排序")
+ private Integer menuSort = 999;
+ @KitDynamicTableColumn(value = "组件路径", width = 240)
+ private String component;
+ @KitDynamicTableColumn(value = "路由地址", width = 120)
+ private String path;
+ @KitDynamicTableColumn(value = "菜单类型")
+ private Integer type;
+ @KitDynamicTableColumn(value = "权限标识")
+ private String permission;
+ @KitDynamicTableColumn(value = "菜单图标")
+ private String icon;
+ @KitDynamicTableColumn(value = "缓存")
+ private Boolean cache;
+ @KitDynamicTableColumn(value = "是否隐藏")
+ private Boolean hidden;
+ @KitDynamicTableColumn(value = "上级菜单")
+ private Long pid;
+ @KitDynamicTableColumn(value = "子节点数目", sortable = true)
+ private Integer subCount = 0;
+ @KitDynamicTableColumn(value = "外链菜单")
+ private Boolean iFrame;
+}