From 8c16467e31803d9e9873b4e34c307f5e242da1f8 Mon Sep 17 00:00:00 2001
From: 潘志宝 <979469083@qq.com>
Date: 星期五, 01 十一月 2024 14:55:31 +0800
Subject: [PATCH] 计划数据

---
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/dao/PlanItemDao.java                                 |   27 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/entity/PlanItemEntity.java                           |   80 +++
 iailab-module-data/iailab-module-data-biz/db/mysql/tenant.sql                                                                                 |   48 ++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/package-info.java                                |    1 
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/service/PlanItemCategoryService.java             |   28 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/entity/PlanDataSetEntity.java                        |   73 +++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/package-info.java                                         |    1 
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/dao/PlanItemCategoryDao.java                     |   26 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategorySaveReqVO.java                |   34 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/service/impl/PlanItemServiceImpl.java                |   74 +++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/package-info.java                                    |    1 
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/controller/package-info.java                         |    1 
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/service/PlanDataSetService.java                      |   29 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetSaveReqVO.java                         |   34 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemRespVO.java                               |   65 ++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/controller/admin/PlanItemCategoryController.java |   88 ++++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/controller/admin/PlanDataSetController.java          |   85 +++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/controller/package-info.java                         |    1 
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/service/PlanItemService.java                         |   31 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategoryRespVO.java                   |   44 ++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemSaveReqVO.java                            |   46 ++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/package-info.java                                    |    1 
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/entity/PlanItemCategoryEntity.java               |   65 ++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/service/impl/PlanItemCategoryServiceImpl.java    |   90 ++++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategoryReqVO.java                    |   18 
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/dao/PlanDataSetDao.java                              |   25 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/service/impl/PlanDataSetServiceImpl.java             |   60 ++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetRespVO.java                            |   50 ++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/controller/admin/PlanItemController.java             |   90 ++++
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/controller/package-info.java                     |    1 
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemPageReqVO.java                            |   28 +
 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetPageReqVO.java                         |   22 +
 32 files changed, 1,266 insertions(+), 1 deletions(-)

diff --git a/iailab-module-data/iailab-module-data-biz/db/mysql/tenant.sql b/iailab-module-data/iailab-module-data-biz/db/mysql/tenant.sql
index f6e6d3c..06da6ef 100644
--- a/iailab-module-data/iailab-module-data-biz/db/mysql/tenant.sql
+++ b/iailab-module-data/iailab-module-data-biz/db/mysql/tenant.sql
@@ -340,4 +340,50 @@
                                   PRIMARY KEY (`id`) USING BTREE,
                                   KEY `idx_item_no` (`item_no`) USING BTREE,
                                   KEY `idx_data_time` (`data_time`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='指标值表';
\ No newline at end of file
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='指标值表';
+
+
+-- 计划数据------------
+CREATE TABLE t_plan_data_set(
+                               `id` VARCHAR(36) NOT NULL  COMMENT 'ID' ,
+                               `name` VARCHAR(30) NOT NULL   COMMENT '名称' ,
+                               `data_source` VARCHAR(64) NOT NULL   COMMENT '数据源ID',
+                               `query_sql` VARCHAR(200) NOT NULL   COMMENT '查询语句',
+                               `remark` VARCHAR(100)   COMMENT '备注',
+                               `sort` int   COMMENT '排序',
+                               `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '创建者',
+                               `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                               `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+                               `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                               PRIMARY KEY (id) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT = '计划数据集';
+
+
+CREATE TABLE t_plan_item_category(
+                                    `id` VARCHAR(36) NOT NULL  COMMENT 'ID' ,
+                                    `label` VARCHAR(20)   COMMENT '标签' ,
+                                    `pid` VARCHAR(36)   COMMENT '父ID',
+                                    `sort` int   COMMENT '排序',
+                                    `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '创建者',
+                                    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                                    `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+                                    `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                                    PRIMARY KEY (id) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT = '计划数据分类';
+
+CREATE TABLE t_plan_item(
+                           `id` VARCHAR(36) NOT NULL  COMMENT 'ID' ,
+                           `item_no` VARCHAR(36)   COMMENT '指标编码' ,
+                           `item_name` VARCHAR(36)   COMMENT '指标名称' ,
+                           `item_category` VARCHAR(36)   COMMENT '指标分类',
+                           `time_granularity` VARCHAR(10)   COMMENT '时间粒度',
+                           `data_source` VARCHAR(64)   COMMENT '数据源',
+                           `remark` VARCHAR(255)   COMMENT '备注' ,
+                           `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)',
+                           `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '创建者',
+                           `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                           `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '更新者',
+                           `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+                           PRIMARY KEY (id) USING BTREE,
+                           UNIQUE INDEX `uk_item_no` (`item_no`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT = '计划数据项';
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/controller/admin/PlanItemCategoryController.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/controller/admin/PlanItemCategoryController.java
new file mode 100644
index 0000000..f1c101c
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/controller/admin/PlanItemCategoryController.java
@@ -0,0 +1,88 @@
+package com.iailab.module.data.plan.category.controller.admin;
+
+import com.iailab.framework.common.pojo.CommonResult;
+import com.iailab.framework.common.util.object.BeanUtils;
+import com.iailab.module.data.plan.category.entity.PlanItemCategoryEntity;
+import com.iailab.module.data.plan.category.service.PlanItemCategoryService;
+import com.iailab.module.data.plan.category.vo.PlanItemCategoryReqVO;
+import com.iailab.module.data.plan.category.vo.PlanItemCategoryRespVO;
+import com.iailab.module.data.plan.category.vo.PlanItemCategorySaveReqVO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.Comparator;
+import java.util.List;
+
+import static com.iailab.framework.common.pojo.CommonResult.success;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Tag(name = "数据平台 - 计划分类")
+@RestController
+@RequestMapping("/data/plan/category")
+@Validated
+public class PlanItemCategoryController {
+
+    @Autowired
+    private PlanItemCategoryService indItemCategoryService;
+
+    @GetMapping("/list")
+    @Operation(summary = "获取计划分类列表", description = "用于【计划分类】界面")
+    @PreAuthorize("@ss.hasPermission('data:plan-item-category:query')")
+    public CommonResult<List<PlanItemCategoryRespVO>> getList(PlanItemCategoryReqVO reqVO) {
+        List<PlanItemCategoryEntity> list = indItemCategoryService.getList(reqVO);
+        list.sort(Comparator.comparing(PlanItemCategoryEntity::getSort));
+        return success(BeanUtils.toBean(list, PlanItemCategoryRespVO.class));
+    }
+
+    @GetMapping("/list-all-simple")
+    @Operation(summary = "获取计划分类列表", description = "用于【计划分类】界面")
+    @PreAuthorize("@ss.hasPermission('data:plan-item-category:query')")
+    public CommonResult<List<PlanItemCategoryRespVO>> getList() {
+        List<PlanItemCategoryEntity> list = indItemCategoryService.getSimpleList();
+        list.sort(Comparator.comparing(PlanItemCategoryEntity::getSort));
+        return success(BeanUtils.toBean(list, PlanItemCategoryRespVO.class));
+    }
+
+    @PostMapping("/create")
+    @Operation(summary = "创建计划分类")
+    @PreAuthorize("@ss.hasPermission('data:plan-item-category:create')")
+    public CommonResult<Boolean> create(@Valid @RequestBody PlanItemCategorySaveReqVO createReqVO) {
+        indItemCategoryService.create(createReqVO);
+        return success(true);
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "修改计划分类")
+    @PreAuthorize("@ss.hasPermission('data:plan-item-category:update')")
+    public CommonResult<Boolean> update(@Valid @RequestBody PlanItemCategorySaveReqVO updateReqVO) {
+        indItemCategoryService.update(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除计划分类")
+    @Parameter(name = "id", description = "计划分类编号", required= true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('data:plan-item-category:delete')")
+    public CommonResult<Boolean> delete(@RequestParam("id") String id) {
+        indItemCategoryService.delete(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获取计划分类信息")
+    @PreAuthorize("@ss.hasPermission('data:plan-item-category:query')")
+    public CommonResult<PlanItemCategoryRespVO> get(String id) {
+        PlanItemCategoryEntity entity = indItemCategoryService.get(id);
+        return success(BeanUtils.toBean(entity, PlanItemCategoryRespVO.class));
+    }
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/controller/package-info.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/controller/package-info.java
new file mode 100644
index 0000000..4d1c10a
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/controller/package-info.java
@@ -0,0 +1 @@
+package com.iailab.module.data.plan.category.controller;
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/dao/PlanItemCategoryDao.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/dao/PlanItemCategoryDao.java
new file mode 100644
index 0000000..b99208a
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/dao/PlanItemCategoryDao.java
@@ -0,0 +1,26 @@
+package com.iailab.module.data.plan.category.dao;
+
+import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
+import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.iailab.framework.tenant.core.db.dynamic.TenantDS;
+
+import com.iailab.module.data.plan.category.entity.PlanItemCategoryEntity;
+import com.iailab.module.data.plan.category.vo.PlanItemCategoryReqVO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@TenantDS
+@Mapper
+public interface PlanItemCategoryDao extends BaseMapperX<PlanItemCategoryEntity> {
+
+    default List<PlanItemCategoryEntity> selectList(PlanItemCategoryReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<PlanItemCategoryEntity>()
+                .likeIfPresent(PlanItemCategoryEntity::getLabel, reqVO.getLabel()));
+    }
+}
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/entity/PlanItemCategoryEntity.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/entity/PlanItemCategoryEntity.java
new file mode 100644
index 0000000..5d29ca8
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/entity/PlanItemCategoryEntity.java
@@ -0,0 +1,65 @@
+package com.iailab.module.data.plan.category.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Data
+@TableName("t_plan_item_category")
+public class PlanItemCategoryEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    public static final String ID_ROOT = "0";
+
+    /**
+     * 主键
+     */
+    @Schema(description = "主键")
+    @TableId(value = "id",type = IdType.INPUT)
+    private String id;
+
+    /**
+     * 标签
+     */
+    private String label;
+
+    /**
+     * 父ID
+     */
+    private String pid;
+
+    /**
+     * 排序
+     */
+    private Integer sort;
+
+    /**
+     * 创建者
+     */
+    private String creator;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private String updater;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/package-info.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/package-info.java
new file mode 100644
index 0000000..2bcee43
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/package-info.java
@@ -0,0 +1 @@
+package com.iailab.module.data.plan.category;
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/service/PlanItemCategoryService.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/service/PlanItemCategoryService.java
new file mode 100644
index 0000000..1afb252
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/service/PlanItemCategoryService.java
@@ -0,0 +1,28 @@
+package com.iailab.module.data.plan.category.service;
+
+
+import com.iailab.module.data.plan.category.entity.PlanItemCategoryEntity;
+import com.iailab.module.data.plan.category.vo.PlanItemCategoryReqVO;
+import com.iailab.module.data.plan.category.vo.PlanItemCategorySaveReqVO;
+
+import java.util.List;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+public interface PlanItemCategoryService {
+
+    List<PlanItemCategoryEntity> getList(PlanItemCategoryReqVO reqVO);
+
+    List<PlanItemCategoryEntity> getSimpleList();
+
+    void create(PlanItemCategorySaveReqVO createReqVO);
+
+    void update(PlanItemCategorySaveReqVO updateReqVO);
+
+    PlanItemCategoryEntity get(String id);
+
+    void delete(String id);
+}
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/service/impl/PlanItemCategoryServiceImpl.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/service/impl/PlanItemCategoryServiceImpl.java
new file mode 100644
index 0000000..b55e90e
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/service/impl/PlanItemCategoryServiceImpl.java
@@ -0,0 +1,90 @@
+package com.iailab.module.data.plan.category.service.impl;
+
+import com.iailab.framework.common.util.object.BeanUtils;
+import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.iailab.module.data.plan.category.dao.PlanItemCategoryDao;
+import com.iailab.module.data.plan.category.entity.PlanItemCategoryEntity;
+import com.iailab.module.data.plan.category.service.PlanItemCategoryService;
+import com.iailab.module.data.plan.category.vo.PlanItemCategoryReqVO;
+import com.iailab.module.data.plan.category.vo.PlanItemCategorySaveReqVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static com.iailab.module.data.plan.category.entity.PlanItemCategoryEntity.ID_ROOT;
+import static com.iailab.module.system.enums.ErrorCodeConstants.MENU_PARENT_ERROR;
+import static com.iailab.module.system.enums.ErrorCodeConstants.MENU_PARENT_NOT_EXISTS;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Service
+@Slf4j
+public class PlanItemCategoryServiceImpl implements PlanItemCategoryService {
+
+    @Resource
+    private PlanItemCategoryDao planItemCategoryDao;
+
+    @Override
+    public List<PlanItemCategoryEntity> getList(PlanItemCategoryReqVO reqVO) {
+        return planItemCategoryDao.selectList(reqVO);
+    }
+
+    @Override
+    public List<PlanItemCategoryEntity> getSimpleList() {
+        return planItemCategoryDao.selectList(new LambdaQueryWrapperX<PlanItemCategoryEntity>());
+    }
+
+    @Override
+    public void create(PlanItemCategorySaveReqVO createReqVO) {
+        // 校验父菜单存在
+        validateParentMenu(createReqVO.getPid(), null);
+
+        // 插入数据库
+        PlanItemCategoryEntity entity = BeanUtils.toBean(createReqVO, PlanItemCategoryEntity.class);
+        entity.setId(UUID.randomUUID().toString());
+        entity.setCreateTime(new Date());
+        planItemCategoryDao.insert(entity);
+    }
+
+    @Override
+    public void update(PlanItemCategorySaveReqVO updateReqVO) {
+        // 校验父菜单存在
+        validateParentMenu(updateReqVO.getPid(), null);
+        PlanItemCategoryEntity entity = BeanUtils.toBean(updateReqVO, PlanItemCategoryEntity.class);
+        entity.setUpdateTime(new Date());
+        planItemCategoryDao.updateById(entity);
+    }
+
+    @Override
+    public PlanItemCategoryEntity get(String id) {
+        return planItemCategoryDao.selectById(id);
+    }
+
+    @Override
+    public void delete(String id) {
+        planItemCategoryDao.deleteById(id);
+    }
+
+    private void validateParentMenu(String parentId, String childId) {
+        if (parentId == null || ID_ROOT.equals(parentId)) {
+            return;
+        }
+        // 不能设置自己为父菜单
+        if (parentId.equals(childId)) {
+            throw exception(MENU_PARENT_ERROR);
+        }
+        PlanItemCategoryEntity category = planItemCategoryDao.selectById(parentId);
+        // 父菜单不存在
+        if (category == null) {
+            throw exception(MENU_PARENT_NOT_EXISTS);
+        }
+    }
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategoryReqVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategoryReqVO.java
new file mode 100644
index 0000000..8c23ded
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategoryReqVO.java
@@ -0,0 +1,18 @@
+package com.iailab.module.data.plan.category.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.ToString;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Schema(description = "数据服务 - 计划分类分页 Request VO")
+@Data
+@ToString(callSuper = true)
+public class PlanItemCategoryReqVO {
+
+    private String label;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategoryRespVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategoryRespVO.java
new file mode 100644
index 0000000..62e1a81
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategoryRespVO.java
@@ -0,0 +1,44 @@
+package com.iailab.module.data.plan.category.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月10日
+ */
+@Schema(description = "数据平台 - 指标分类 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class PlanItemCategoryRespVO {
+
+    @Schema(description = "指标分类ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @ExcelProperty("指标分类ID")
+    private String id;
+
+    @Schema(description = "标签", example = "")
+    private String label;
+
+    @Schema(description = "父ID", example = "")
+    private String pid;
+
+    @Schema(description = "排序", example = "")
+    private Integer sort;
+
+    @Schema(description = "创建者", example = "")
+    private String creator;
+
+    @Schema(description = "创建时间", example = "")
+    private Date createTime;
+
+    @Schema(description = "更新者", example = "")
+    private String updater;
+
+    @Schema(description = "更新时间", example = "")
+    private Date updateTime;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategorySaveReqVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategorySaveReqVO.java
new file mode 100644
index 0000000..2210c04
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/category/vo/PlanItemCategorySaveReqVO.java
@@ -0,0 +1,34 @@
+package com.iailab.module.data.plan.category.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月10日
+ */
+@Schema(description = "数据平台 - 指标分类创建/修改 Request VO")
+@Data
+public class PlanItemCategorySaveReqVO {
+
+    @Schema(description = "ID", example = "1024")
+    private String id;
+
+    @Schema(description = "标签", requiredMode = Schema.RequiredMode.REQUIRED, example = "平台")
+    @NotBlank(message = "标签")
+    @Size(max = 50, message = "标签长度不能超过20个字符")
+    private String label;
+
+    @Schema(description = "父菜单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @NotNull(message = "父菜单 ID 不能为空")
+    private String pid;
+
+    @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @NotNull(message = "显示顺序不能为空")
+    private Integer sort;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/controller/admin/PlanDataSetController.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/controller/admin/PlanDataSetController.java
new file mode 100644
index 0000000..bacdaba
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/controller/admin/PlanDataSetController.java
@@ -0,0 +1,85 @@
+package com.iailab.module.data.plan.data.controller.admin;
+
+import com.iailab.framework.common.pojo.CommonResult;
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.util.object.BeanUtils;
+import com.iailab.module.data.plan.data.entity.PlanDataSetEntity;
+import com.iailab.module.data.plan.data.service.PlanDataSetService;
+import com.iailab.module.data.plan.data.vo.PlanDataSetPageReqVO;
+import com.iailab.module.data.plan.data.vo.PlanDataSetRespVO;
+import com.iailab.module.data.plan.data.vo.PlanDataSetSaveReqVO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+import static com.iailab.framework.common.pojo.CommonResult.success;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Tag(name = "数据平台 - 计划数据集")
+@RestController
+@RequestMapping("/data/plan/data-set")
+@Validated
+public class PlanDataSetController {
+    @Autowired
+    private PlanDataSetService indDataSetService;
+
+    @GetMapping("/page")
+    @Operation(summary = "获取计划数据集列表", description = "用于【计划数据集】界面")
+    @PreAuthorize("@ss.hasPermission('data:plan-data-set:query')")
+    public CommonResult<PageResult<PlanDataSetRespVO>> page(PlanDataSetPageReqVO reqVO) {
+        PageResult<PlanDataSetEntity> page = indDataSetService.page(reqVO);
+        return success(BeanUtils.toBean(page, PlanDataSetRespVO.class));
+    }
+
+    @PostMapping("/create")
+    @Operation(summary = "创建计划数据集")
+    @PreAuthorize("@ss.hasPermission('data:plan-data-set:create')")
+    public CommonResult<Boolean> create(@Valid @RequestBody PlanDataSetSaveReqVO createReqVO) {
+        indDataSetService.create(createReqVO);
+        return success(true);
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "修改计划数据集")
+    @PreAuthorize("@ss.hasPermission('data:plan-data-set:update')")
+    public CommonResult<Boolean> update(@Valid @RequestBody PlanDataSetSaveReqVO updateReqVO) {
+        indDataSetService.update(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除计划数据集")
+    @Parameter(name = "id", description = "计划数据集编号", required= true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('data:plan-data-set:delete')")
+    public CommonResult<Boolean> delete(@RequestParam("id") String id) {
+        indDataSetService.delete(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获取计划数据集信息")
+    @PreAuthorize("@ss.hasPermission('data:plan-data-set:query')")
+    public CommonResult<PlanDataSetRespVO> get(String id) {
+        PlanDataSetEntity entity = indDataSetService.get(id);
+        return success(BeanUtils.toBean(entity, PlanDataSetRespVO.class));
+    }
+
+    @GetMapping("/list-all-simple")
+    @Operation(summary = "获取计划数据集列表", description = "用于【计划数据集】界面")
+    @PreAuthorize("@ss.hasPermission('data:plan-data-set:query')")
+    public CommonResult<List<PlanDataSetRespVO>> list(PlanDataSetPageReqVO reqVO) {
+        List<PlanDataSetEntity> list = indDataSetService.list(reqVO);
+        return success(BeanUtils.toBean(list, PlanDataSetRespVO.class));
+    }
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/controller/package-info.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/controller/package-info.java
new file mode 100644
index 0000000..93a1e16
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/controller/package-info.java
@@ -0,0 +1 @@
+package com.iailab.module.data.plan.data.controller;
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/dao/PlanDataSetDao.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/dao/PlanDataSetDao.java
new file mode 100644
index 0000000..4679b58
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/dao/PlanDataSetDao.java
@@ -0,0 +1,25 @@
+package com.iailab.module.data.plan.data.dao;
+
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
+import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.iailab.framework.tenant.core.db.dynamic.TenantDS;
+import com.iailab.module.data.plan.data.entity.PlanDataSetEntity;
+import com.iailab.module.data.plan.data.vo.PlanDataSetPageReqVO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月10日
+ */
+@TenantDS
+@Mapper
+public interface PlanDataSetDao extends BaseMapperX<PlanDataSetEntity>  {
+
+    default PageResult<PlanDataSetEntity> selectPage(PlanDataSetPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<PlanDataSetEntity>()
+                .likeIfPresent(PlanDataSetEntity::getName, reqVO.getName())
+                .orderByDesc(PlanDataSetEntity::getCreateTime));
+    }
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/entity/PlanDataSetEntity.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/entity/PlanDataSetEntity.java
new file mode 100644
index 0000000..c2fbfce
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/entity/PlanDataSetEntity.java
@@ -0,0 +1,73 @@
+package com.iailab.module.data.plan.data.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 指标数据集
+ *
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月10日
+ */
+@Data
+@TableName("t_plan_data_set")
+public class PlanDataSetEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id",type = IdType.INPUT)
+    private String id;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
+    /**
+     * 查询语句
+     */
+    private String querySql;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 排序
+     */
+    private Integer sort;
+
+    /**
+     * 创建者
+     */
+    private String creator;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private String updater;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/package-info.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/package-info.java
new file mode 100644
index 0000000..048fad3
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/package-info.java
@@ -0,0 +1 @@
+package com.iailab.module.data.plan.data;
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/service/PlanDataSetService.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/service/PlanDataSetService.java
new file mode 100644
index 0000000..8db1f74
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/service/PlanDataSetService.java
@@ -0,0 +1,29 @@
+package com.iailab.module.data.plan.data.service;
+
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.service.BaseService;
+import com.iailab.module.data.plan.data.entity.PlanDataSetEntity;
+import com.iailab.module.data.plan.data.vo.PlanDataSetPageReqVO;
+import com.iailab.module.data.plan.data.vo.PlanDataSetSaveReqVO;
+
+import java.util.List;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+public interface PlanDataSetService extends BaseService<PlanDataSetEntity> {
+
+    PageResult<PlanDataSetEntity> page(PlanDataSetPageReqVO reqVO);
+
+    void create(PlanDataSetSaveReqVO reqVO);
+
+    void update(PlanDataSetSaveReqVO reqVO);
+
+    PlanDataSetEntity get(String id);
+
+    void delete(String id);
+
+    List<PlanDataSetEntity> list(PlanDataSetPageReqVO reqVO);
+}
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/service/impl/PlanDataSetServiceImpl.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/service/impl/PlanDataSetServiceImpl.java
new file mode 100644
index 0000000..ced27bf
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/service/impl/PlanDataSetServiceImpl.java
@@ -0,0 +1,60 @@
+package com.iailab.module.data.plan.data.service.impl;
+
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.service.impl.BaseServiceImpl;
+import com.iailab.framework.common.util.object.BeanUtils;
+import com.iailab.module.data.plan.data.dao.PlanDataSetDao;
+import com.iailab.module.data.plan.data.entity.PlanDataSetEntity;
+import com.iailab.module.data.plan.data.service.PlanDataSetService;
+import com.iailab.module.data.plan.data.vo.PlanDataSetPageReqVO;
+import com.iailab.module.data.plan.data.vo.PlanDataSetSaveReqVO;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Service
+public class PlanDataSetServiceImpl extends BaseServiceImpl<PlanDataSetDao, PlanDataSetEntity> implements PlanDataSetService {
+
+
+    @Override
+    public PageResult<PlanDataSetEntity> page(PlanDataSetPageReqVO reqVO) {
+        return baseDao.selectPage(reqVO);
+    }
+
+    @Override
+    public List<PlanDataSetEntity> list(PlanDataSetPageReqVO reqVO) {
+        return baseDao.selectList();
+    }
+
+    @Override
+    public void create(PlanDataSetSaveReqVO createReqVO) {
+        PlanDataSetEntity entity = BeanUtils.toBean(createReqVO, PlanDataSetEntity.class);
+        entity.setId(UUID.randomUUID().toString());
+        entity.setCreateTime(new Date());
+        baseDao.insert(entity);
+    }
+
+    @Override
+    public void update(PlanDataSetSaveReqVO updateReqVO) {
+        PlanDataSetEntity entity = BeanUtils.toBean(updateReqVO, PlanDataSetEntity.class);
+        entity.setUpdateTime(new Date());
+        baseDao.updateById(entity);
+    }
+
+    @Override
+    public PlanDataSetEntity get(String id) {
+        return baseDao.selectById(id);
+    }
+
+    @Override
+    public void delete(String id) {
+        baseDao.deleteById(id);
+    }
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetPageReqVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetPageReqVO.java
new file mode 100644
index 0000000..d9108b7
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetPageReqVO.java
@@ -0,0 +1,22 @@
+package com.iailab.module.data.plan.data.vo;
+
+import com.iailab.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月10日
+ */
+@Schema(description = "模型服务 - 计划数据集分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class PlanDataSetPageReqVO extends PageParam {
+
+    @Schema(description = "名称,模糊匹配", example = "")
+    private String name;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetRespVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetRespVO.java
new file mode 100644
index 0000000..8b7075d
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetRespVO.java
@@ -0,0 +1,50 @@
+package com.iailab.module.data.plan.data.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月10日
+ */
+@Schema(description = "数据平台 - 计划数据集 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class PlanDataSetRespVO {
+
+    @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @ExcelProperty("ID")
+    private String id;
+
+    @Schema(description = "名称", example = "")
+    private String name;
+
+    @Schema(description = "数据源", example = "")
+    private String dataSource;
+
+    @Schema(description = "查询语句", example = "")
+    private String querySql;
+
+    @Schema(description = "备注", example = "")
+    private String remark;
+
+    @Schema(description = "排序", example = "")
+    private Integer sort;
+
+    @Schema(description = "创建者", example = "")
+    private String creator;
+
+    @Schema(description = "创建时间", example = "")
+    private Date createTime;
+
+    @Schema(description = "更新者", example = "")
+    private String updater;
+
+    @Schema(description = "更新时间", example = "")
+    private Date updateTime;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetSaveReqVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetSaveReqVO.java
new file mode 100644
index 0000000..02c8dc3
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/data/vo/PlanDataSetSaveReqVO.java
@@ -0,0 +1,34 @@
+package com.iailab.module.data.plan.data.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月10日
+ */
+@Schema(description = "数据平台 - 计划数据集创建/修改 Request VO")
+@Data
+public class PlanDataSetSaveReqVO {
+
+    @Schema(description = "ID")
+    private String id;
+
+    @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "名称不能为空")
+    private String name;
+
+    @Schema(description = "数据源", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "数据源不能为空")
+    private String dataSource;
+
+    @Schema(description = "查询语句", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "查询语句不能为空")
+    private String querySql;
+
+    @Schema(description = "备注")
+    private String remark;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/controller/admin/PlanItemController.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/controller/admin/PlanItemController.java
new file mode 100644
index 0000000..c5a9a0b
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/controller/admin/PlanItemController.java
@@ -0,0 +1,90 @@
+package com.iailab.module.data.plan.item.controller.admin;
+
+import com.iailab.framework.common.pojo.CommonResult;
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.util.object.BeanUtils;
+import com.iailab.framework.common.util.object.ConvertUtils;
+import com.iailab.module.data.plan.item.entity.PlanItemEntity;
+import com.iailab.module.data.plan.item.service.PlanItemService;
+import com.iailab.module.data.plan.item.vo.PlanItemPageReqVO;
+import com.iailab.module.data.plan.item.vo.PlanItemRespVO;
+import com.iailab.module.data.plan.item.vo.PlanItemSaveReqVO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+import java.util.List;
+
+import static com.iailab.framework.common.pojo.CommonResult.success;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Tag(name = "数据平台 - 计划数据项")
+@RestController
+@RequestMapping("/data/plan-item")
+@Validated
+public class PlanItemController {
+
+    @Autowired
+    private PlanItemService planItemService;
+
+    @GetMapping("/page")
+    @Operation(summary = "获取计划项列表", description = "用于【计划项】界面")
+    @PreAuthorize("@ss.hasPermission('data:plan-item:query')")
+    public CommonResult<PageResult<PlanItemRespVO>> page(PlanItemPageReqVO reqVO) {
+        PageResult<PlanItemEntity> page = planItemService.page(reqVO);
+        PageResult<PlanItemRespVO> result = BeanUtils.toBean(page, PlanItemRespVO.class);
+        return success(result);
+    }
+
+    @PostMapping("/create")
+    @Operation(summary = "创建计划项")
+    @PreAuthorize("@ss.hasPermission('data:plan-item:create')")
+    public CommonResult<Boolean> create(@Valid @RequestBody PlanItemSaveReqVO createReqVO) {
+        planItemService.create(createReqVO);
+        return success(true);
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "修改计划项")
+    @PreAuthorize("@ss.hasPermission('data:plan-item:update')")
+    public CommonResult<Boolean> update(@Valid @RequestBody PlanItemSaveReqVO updateReqVO) {
+        planItemService.update(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除计划项")
+    @Parameter(name = "id", description = "计划项编号", required= true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('data:plan-item:delete')")
+    public CommonResult<Boolean> delete(@RequestParam("id") String id) {
+        planItemService.delete(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获取计划项信息")
+    @PreAuthorize("@ss.hasPermission('data:plan-item:query')")
+    public CommonResult<PlanItemRespVO> get(@RequestParam("id") String id) {
+        PlanItemEntity entity = planItemService.get(id);
+        PlanItemRespVO respVO = BeanUtils.toBean(entity, PlanItemRespVO.class);
+        return success(respVO);
+    }
+
+    @GetMapping("/list")
+    @Operation(summary = "获取计划项列表", description = "用于【计划项】界面")
+    @PreAuthorize("@ss.hasPermission('data:plan-item:query')")
+    public CommonResult<List<PlanItemRespVO>> getList(PlanItemPageReqVO reqVO) {
+        List<PlanItemEntity> list = planItemService.list();
+        return success(ConvertUtils.sourceToTarget(list, PlanItemRespVO.class));
+    }
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/controller/package-info.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/controller/package-info.java
new file mode 100644
index 0000000..1ea4db6
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/controller/package-info.java
@@ -0,0 +1 @@
+package com.iailab.module.data.plan.item.controller;
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/dao/PlanItemDao.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/dao/PlanItemDao.java
new file mode 100644
index 0000000..61ba104
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/dao/PlanItemDao.java
@@ -0,0 +1,27 @@
+package com.iailab.module.data.plan.item.dao;
+
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
+import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.iailab.framework.tenant.core.db.dynamic.TenantDS;
+import com.iailab.module.data.plan.item.entity.PlanItemEntity;
+import com.iailab.module.data.plan.item.vo.PlanItemPageReqVO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@TenantDS
+@Mapper
+public interface PlanItemDao extends BaseMapperX<PlanItemEntity> {
+
+    default PageResult<PlanItemEntity> selectPage(PlanItemPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<PlanItemEntity>()
+                .likeIfPresent(PlanItemEntity::getItemNo, reqVO.getItemNo())
+                .likeIfPresent(PlanItemEntity::getItemName, reqVO.getItemName())
+                .eqIfPresent(PlanItemEntity::getItemCategory, reqVO.getItemCategory())
+                .orderByDesc(PlanItemEntity::getCreateTime));
+    }
+}
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/entity/PlanItemEntity.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/entity/PlanItemEntity.java
new file mode 100644
index 0000000..ad0da09
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/entity/PlanItemEntity.java
@@ -0,0 +1,80 @@
+package com.iailab.module.data.plan.item.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Data
+@TableName("t_plan_item")
+public class PlanItemEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id",type = IdType.INPUT)
+    private String id;
+
+    /**
+     * 指标编码
+     */
+    private String itemNo;
+
+    /**
+     * 指标名称
+     */
+    private String itemName;
+
+    /**
+     * 指标分类
+     */
+    private String itemCategory;
+
+    /**
+     * 时间粒度
+     */
+    @TableField(updateStrategy = FieldStrategy.ALWAYS)
+    private String timeGranularity;
+
+    /**
+     * 数据源
+     */
+    private String dataSource;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 状态
+     */
+    private Integer status;
+
+    /**
+     * 创建者
+     */
+    private String creator;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新者
+     */
+    private String updater;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/package-info.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/package-info.java
new file mode 100644
index 0000000..2da888a
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/package-info.java
@@ -0,0 +1 @@
+package com.iailab.module.data.plan.item;
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/service/PlanItemService.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/service/PlanItemService.java
new file mode 100644
index 0000000..4bec74e
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/service/PlanItemService.java
@@ -0,0 +1,31 @@
+package com.iailab.module.data.plan.item.service;
+
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.service.BaseService;
+import com.iailab.module.data.plan.item.entity.PlanItemEntity;
+import com.iailab.module.data.plan.item.vo.PlanItemPageReqVO;
+import com.iailab.module.data.plan.item.vo.PlanItemSaveReqVO;
+
+import java.util.List;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+public interface PlanItemService extends BaseService<PlanItemEntity> {
+
+    PageResult<PlanItemEntity> page(PlanItemPageReqVO reqVO);
+
+    List<PlanItemEntity> list();
+
+    void create(PlanItemSaveReqVO createReqVO);
+
+    void update(PlanItemSaveReqVO updateReqVO);
+
+    PlanItemEntity get(String id);
+
+    PlanItemEntity getInfoByNo(String no);
+
+    void delete(String id);
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/service/impl/PlanItemServiceImpl.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/service/impl/PlanItemServiceImpl.java
new file mode 100644
index 0000000..c3740dd
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/service/impl/PlanItemServiceImpl.java
@@ -0,0 +1,74 @@
+package com.iailab.module.data.plan.item.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.service.impl.BaseServiceImpl;
+import com.iailab.framework.common.util.object.BeanUtils;
+import com.iailab.module.data.ind.item.dao.IndItemDao;
+import com.iailab.module.data.ind.item.entity.IndItemEntity;
+import com.iailab.module.data.ind.item.service.IndItemService;
+import com.iailab.module.data.ind.item.vo.IndItemPageReqVO;
+import com.iailab.module.data.ind.item.vo.IndItemSaveReqVO;
+import com.iailab.module.data.plan.item.dao.PlanItemDao;
+import com.iailab.module.data.plan.item.entity.PlanItemEntity;
+import com.iailab.module.data.plan.item.service.PlanItemService;
+import com.iailab.module.data.plan.item.vo.PlanItemPageReqVO;
+import com.iailab.module.data.plan.item.vo.PlanItemSaveReqVO;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年11月01日
+ */
+@Service
+public class PlanItemServiceImpl extends BaseServiceImpl<PlanItemDao, PlanItemEntity> implements PlanItemService {
+
+    @Override
+    public PageResult<PlanItemEntity> page(PlanItemPageReqVO reqVO) {
+        return baseDao.selectPage(reqVO);
+    }
+
+    @Override
+    public List<PlanItemEntity> list() {
+        QueryWrapper<PlanItemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.orderByDesc("create_time");
+        return baseDao.selectList(queryWrapper);
+    }
+
+    @Override
+    public void create(PlanItemSaveReqVO createReqVO) {
+        PlanItemEntity entity = BeanUtils.toBean(createReqVO, PlanItemEntity.class);
+        entity.setId(UUID.randomUUID().toString());
+        entity.setCreateTime(new Date());
+        baseDao.insert(entity);
+    }
+
+    @Override
+    public void update(PlanItemSaveReqVO updateReqVO) {
+        PlanItemEntity entity = BeanUtils.toBean(updateReqVO, PlanItemEntity.class);
+        entity.setUpdateTime(new Date());
+        baseDao.updateById(entity);
+    }
+
+    @Override
+    public PlanItemEntity get(String id) {
+        return baseDao.selectById(id);
+    }
+
+    @Override
+    public PlanItemEntity getInfoByNo(String no) {
+        QueryWrapper<PlanItemEntity> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("item_no", no);
+        return baseDao.selectOne(queryWrapper);
+    }
+
+    @Override
+    public void delete(String id) {
+        baseDao.deleteById(id);
+    }
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemPageReqVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemPageReqVO.java
new file mode 100644
index 0000000..8fe209d
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemPageReqVO.java
@@ -0,0 +1,28 @@
+package com.iailab.module.data.plan.item.vo;
+
+import com.iailab.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月11日
+ */
+@Schema(description = "数据平台 - 指标项分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class PlanItemPageReqVO extends PageParam {
+
+    @Schema(description = "指标编码", example = "")
+    private String itemNo;
+
+    @Schema(description = "指标名称", example = "")
+    private String itemName;
+
+    @Schema(description = "指标分类", example = "")
+    private String itemCategory;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemRespVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemRespVO.java
new file mode 100644
index 0000000..1ff6e02
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemRespVO.java
@@ -0,0 +1,65 @@
+package com.iailab.module.data.plan.item.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.iailab.module.data.ind.item.vo.IndItemAtomVO;
+import com.iailab.module.data.ind.item.vo.IndItemCalVO;
+import com.iailab.module.data.ind.item.vo.IndItemDerVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月11日
+ */
+@Schema(description = "数据平台 - 指标项 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class PlanItemRespVO {
+
+    @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @ExcelProperty("ID")
+    private String id;
+
+    @Schema(description = "指标编码", example = "")
+    private String itemNo;
+
+    @Schema(description = "指标名称", example = "")
+    private String itemName;
+
+    @Schema(description = "指标类型", example = "")
+    private String itemType;
+
+    @Schema(description = "指标分类", example = "")
+    private String itemCategory;
+
+    @Schema(description = "指标分类", example = "")
+    private String itemCategoryName;
+
+    @Schema(description = "时间粒度", example = "")
+    private String timeGranularity;
+
+    @Schema(description = "数据源", example = "")
+    private String dataSource;
+
+    @Schema(description = "备注", example = "")
+    private String remark;
+
+    @Schema(description = "状态", example = "")
+    private Integer status;
+
+    @Schema(description = "创建者", example = "")
+    private String creator;
+
+    @Schema(description = "创建时间", example = "")
+    private Date createTime;
+
+    @Schema(description = "更新者", example = "")
+    private String updater;
+
+    @Schema(description = "更新时间", example = "")
+    private Date updateTime;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemSaveReqVO.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemSaveReqVO.java
new file mode 100644
index 0000000..c77348f
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/item/vo/PlanItemSaveReqVO.java
@@ -0,0 +1,46 @@
+package com.iailab.module.data.plan.item.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年09月11日
+ */
+@Schema(description = "数据平台 - 指标项创建/修改 Request VO")
+@Data
+public class PlanItemSaveReqVO {
+
+    @Schema(description = "ID")
+    private String id;
+
+    @Schema(description = "编码")
+    private String itemNo;
+
+    @Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "名称不能为空")
+    private String itemName;
+
+    @Schema(description = "指标类型", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "指标类型不能为空")
+    private String itemType;
+
+    @Schema(description = "指标分类", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotNull(message = "指标分类不能为空")
+    private String itemCategory;
+
+    @Schema(description = "时间粒度")
+    private String timeGranularity;
+
+    @Schema(description = "数据源")
+    private String dataSource;
+
+    @Schema(description = "备注")
+    private String remark;
+
+    @Schema(description = "状态(0正常 1停用)")
+    private Integer status;
+}
\ No newline at end of file
diff --git a/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/package-info.java b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/package-info.java
new file mode 100644
index 0000000..9bae177
--- /dev/null
+++ b/iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/plan/package-info.java
@@ -0,0 +1 @@
+package com.iailab.module.data.plan;
\ No newline at end of file

--
Gitblit v1.9.3