Merge pull request #6993 from dataease/pr@dev-v2@refactor_template-manage

Pr@dev v2@refactor template manage
This commit is contained in:
王嘉豪 2023-12-05 09:36:47 +08:00 committed by GitHub
commit 018eb21b7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 482 additions and 255 deletions

View File

@ -21,11 +21,11 @@ public class MybatisPlusGenerator {
/**
* 业务模块例如datasource,dataset,panel等
*/
private static final String busi = "operation";
private static final String busi = "template";
/**
* 这是要生成代码的表名称
*/
private static final String TABLE_NAME = "core_opt_recent";
private static final String TABLE_NAME = "visualization_template_category_map";
/**
* 下面两个配置基本上不用动

View File

@ -12,6 +12,9 @@ import java.util.List;
public interface ExtVisualizationTemplateMapper{
List<TemplateManageDTO> findTemplateList(TemplateManageRequest request);
List<TemplateManageDTO> findBaseTemplateList(@Param("nodeType") String nodeType);
List<TemplateManageDTO> findCategories(TemplateManageRequest request);
List<TemplateManageDTO> findBaseTemplateList();
}

View File

@ -11,6 +11,8 @@ import io.dataease.constant.CommonConstants;
import io.dataease.exception.DEException;
import io.dataease.operation.manage.CoreOptRecentManage;
import io.dataease.system.manage.SysParameterManage;
import io.dataease.template.dao.auto.entity.VisualizationTemplateCategoryMap;
import io.dataease.template.dao.auto.mapper.VisualizationTemplateCategoryMapMapper;
import io.dataease.template.dao.ext.ExtVisualizationTemplateMapper;
import io.dataease.utils.HttpClientConfig;
import io.dataease.utils.HttpClientUtil;
@ -19,6 +21,7 @@ import io.dataease.utils.LogUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.function.Function;
@ -40,6 +43,9 @@ public class TemplateCenterManage {
@Resource
private ExtVisualizationTemplateMapper templateManageMapper;
@Resource
private VisualizationTemplateCategoryMapMapper categoryMapMapper;
/**
* @param templateUrl template url
* @Description Get template file from template market
@ -88,8 +94,8 @@ public class TemplateCenterManage {
private List<TemplateMarketDTO> searchTemplateFromManage() {
try {
List<TemplateManageDTO> manageResult = templateManageMapper.findBaseTemplateList("template");
List<TemplateManageDTO> categories = templateManageMapper.findBaseTemplateList("folder");
List<TemplateManageDTO> manageResult = templateManageMapper.findBaseTemplateList();
List<TemplateManageDTO> categories = templateManageMapper.findCategories(null);
Map<String, String> categoryMap = categories.stream()
.collect(Collectors.toMap(TemplateManageDTO::getId, TemplateManageDTO::getName));
return baseManage2MarketTrans(manageResult, categoryMap);
@ -103,7 +109,12 @@ public class TemplateCenterManage {
List<TemplateMarketDTO> result = new ArrayList<>();
manageResult.stream().forEach(templateManageDTO -> {
templateManageDTO.setCategoryName(categoryMap.get(templateManageDTO.getPid()));
result.add(new TemplateMarketDTO(templateManageDTO));
List<String> categories = templateManageDTO.getCategories();
if(!CollectionUtils.isEmpty(categories)){
List<String> categoryNames = categories.stream().map(categoryId ->categoryMap.get(categoryId)).collect(Collectors.toList());
templateManageDTO.setCategoryNames(categoryNames);
result.add(new TemplateMarketDTO(templateManageDTO));
}
});
return result;
}
@ -178,7 +189,7 @@ public class TemplateCenterManage {
contents.stream().forEach(templateMarketDTO -> {
Long recentUseTime = useTime.get(templateMarketDTO.getId());
templateMarketDTO.setRecentUseTime(recentUseTime == null ? 0 : recentUseTime);
activeCategoriesName.add(templateMarketDTO.getMainCategory());
activeCategoriesName.addAll(templateMarketDTO.getCategoryNames());
});
if (v2BaseResponse != null) {
v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> {
@ -214,7 +225,7 @@ public class TemplateCenterManage {
public List<MarketMetaDataVO> getCategoriesV2() {
List<MarketMetaDataVO> allCategories = new ArrayList<>();
List<TemplateManageDTO> manageCategories = templateManageMapper.findBaseTemplateList("folder");
List<TemplateManageDTO> manageCategories = templateManageMapper.findCategories(null);
List<MarketMetaDataVO> manageCategoriesTrans = manageCategories.stream()
.map(templateCategory -> new MarketMetaDataVO(templateCategory.getId(), templateCategory.getName(), CommonConstants.TEMPLATE_SOURCE.MANAGE))
.collect(Collectors.toList());

View File

@ -8,6 +8,10 @@ import io.dataease.api.template.vo.VisualizationTemplateVO;
import io.dataease.constant.CommonConstants;
import io.dataease.exception.DEException;
import io.dataease.template.dao.auto.entity.VisualizationTemplate;
import io.dataease.template.dao.auto.entity.VisualizationTemplateCategory;
import io.dataease.template.dao.auto.entity.VisualizationTemplateCategoryMap;
import io.dataease.template.dao.auto.mapper.VisualizationTemplateCategoryMapMapper;
import io.dataease.template.dao.auto.mapper.VisualizationTemplateCategoryMapper;
import io.dataease.template.dao.auto.mapper.VisualizationTemplateMapper;
import io.dataease.template.dao.ext.ExtVisualizationTemplateMapper;
import io.dataease.utils.AuthUtils;
@ -37,6 +41,11 @@ public class TemplateManageService implements TemplateManageApi {
@Resource
private VisualizationTemplateMapper templateMapper;
@Resource
private VisualizationTemplateCategoryMapper templateCategoryMapper;
@Resource
private VisualizationTemplateCategoryMapMapper categoryMapMapper;
@Resource
private ExtVisualizationTemplateMapper extTemplateMapper;
@Resource
@ -72,19 +81,6 @@ public class TemplateManageService implements TemplateManageApi {
request.setId(UUID.randomUUID().toString());
request.setCreateTime(System.currentTimeMillis());
request.setCreateBy(AuthUtils.getUser().getUserId().toString());
//如果level 是0第一级指的是分类目录 设置父级为对应的templateType
if (request.getLevel() == 0) {
request.setPid(request.getTemplateType());
String nameCheckResult = this.nameCheck(CommonConstants.OPT_TYPE.INSERT, request.getName(), request.getPid(), null);
if (CommonConstants.CHECK_RESULT.EXIST_ALL.equals(nameCheckResult)) {
DEException.throwException("名称已存在");
}
} else {//模板插入 相同文件夹同名的模板进行覆盖(先删除)
QueryWrapper<VisualizationTemplate> wrapper = new QueryWrapper<>();
wrapper.eq("pid",request.getPid());
wrapper.eq("name",request.getName());
templateMapper.delete(wrapper);
}
if ("template".equals(request.getNodeType())) {
//Store static resource into the server
staticResourceServer.saveFilesToServe(request.getStaticResource());
@ -92,18 +88,52 @@ public class TemplateManageService implements TemplateManageApi {
staticResourceServer.saveSingleFileToServe(snapshotName, request.getSnapshot().replace("data:image/jpeg;base64,", ""));
request.setSnapshot("/" + UPLOAD_URL_PREFIX + '/' + snapshotName);
}
//如果level 是0第一级指的是分类目录 设置父级为对应的templateType
if (request.getLevel() == 0) {
request.setPid(request.getTemplateType());
String nameCheckResult = this.categoryNameCheck(CommonConstants.OPT_TYPE.INSERT, request.getName(), null);
if (CommonConstants.CHECK_RESULT.EXIST_ALL.equals(nameCheckResult)) {
DEException.throwException("名称已存在");
}
VisualizationTemplateCategory templateCategory = new VisualizationTemplateCategory();
BeanUtils.copyBean(templateCategory,request);
templateCategoryMapper.insert(templateCategory);
} else {//模板插入 同名的模板进行覆盖(先删除)
QueryWrapper<VisualizationTemplate> wrapper = new QueryWrapper<>();
wrapper.eq("name",request.getName());
templateMapper.delete(wrapper);
VisualizationTemplate template = new VisualizationTemplate();
BeanUtils.copyBean(template,request);
templateMapper.insert(template);
// 插入分类关系
request.getCategories().forEach(categoryId ->{
VisualizationTemplateCategoryMap categoryMap = new VisualizationTemplateCategoryMap();
categoryMap.setId(UUID.randomUUID().toString());
categoryMap.setCategoryId(categoryId);
categoryMap.setTemplateId(template.getId());
categoryMapMapper.insert(categoryMap);
});
VisualizationTemplate template = new VisualizationTemplate();
BeanUtils.copyBean(template,request);
templateMapper.insert(template);
} else {
String nameCheckResult = this.nameCheck(CommonConstants.OPT_TYPE.UPDATE, request.getName(), request.getPid(), request.getId());
if (CommonConstants.CHECK_RESULT.EXIST_ALL.equals(nameCheckResult)) {
DEException.throwException("名称已存在");
}
VisualizationTemplate template = new VisualizationTemplate();
BeanUtils.copyBean(template,request);
templateMapper.updateById(template);
} else {
if (request.getLevel() == 0) {
String nameCheckResult = this.categoryNameCheck(CommonConstants.OPT_TYPE.UPDATE, request.getName(), request.getId());
if (CommonConstants.CHECK_RESULT.EXIST_ALL.equals(nameCheckResult)) {
DEException.throwException("名称已存在");
}
VisualizationTemplateCategory templateCategory = new VisualizationTemplateCategory();
BeanUtils.copyBean(templateCategory,request);
templateCategoryMapper.updateById(templateCategory);
}else{
String nameCheckResult = this.nameCheck(CommonConstants.OPT_TYPE.UPDATE, request.getName(), request.getId());
if (CommonConstants.CHECK_RESULT.EXIST_ALL.equals(nameCheckResult)) {
DEException.throwException("名称已存在");
}
VisualizationTemplate template = new VisualizationTemplate();
BeanUtils.copyBean(template,request);
templateMapper.updateById(template);
}
}
TemplateManageDTO templateManageDTO = new TemplateManageDTO();
BeanUtils.copyBean(templateManageDTO, request);
@ -112,13 +142,11 @@ public class TemplateManageService implements TemplateManageApi {
}
//名称检查
public String nameCheck(String optType, String name, String pid, String id) {
public String nameCheck(String optType, String name,String id) {
QueryWrapper<VisualizationTemplate> wrapper = new QueryWrapper<>();
if (CommonConstants.OPT_TYPE.INSERT.equals(optType)) {
wrapper.eq("pid",pid);
wrapper.eq("name",name);
} else if (CommonConstants.OPT_TYPE.UPDATE.equals(optType)) {
wrapper.eq("pid",pid);
wrapper.eq("name",name);
wrapper.ne("id",id);
}
@ -129,10 +157,26 @@ public class TemplateManageService implements TemplateManageApi {
return CommonConstants.CHECK_RESULT.EXIST_ALL;
}
}
//名称检查
public String categoryNameCheck(String optType, String name, String id) {
QueryWrapper<VisualizationTemplateCategory> wrapper = new QueryWrapper<>();
if (CommonConstants.OPT_TYPE.INSERT.equals(optType)) {
wrapper.eq("name",name);
} else if (CommonConstants.OPT_TYPE.UPDATE.equals(optType)) {
wrapper.eq("name",name);
wrapper.ne("id",id);
}
List<VisualizationTemplateCategory> templateList = templateCategoryMapper.selectList(wrapper);
if (CollectionUtils.isEmpty(templateList)) {
return CommonConstants.CHECK_RESULT.NONE;
} else {
return CommonConstants.CHECK_RESULT.EXIST_ALL;
}
}
@Override
public String nameCheck(TemplateManageRequest request) {
return nameCheck(request.getOptType(), request.getName(), request.getPid(), request.getId());
return nameCheck(request.getOptType(), request.getName(), request.getId());
}
@Override
public void delete(String id) {
@ -140,6 +184,11 @@ public class TemplateManageService implements TemplateManageApi {
templateMapper.deleteById(id);
}
@Override
public void deleteCategory(String id) {
Assert.notNull(id, "id cannot be null");
templateCategoryMapper.deleteById(id);
}
@Override
public VisualizationTemplateVO findOne(String templateId) {
VisualizationTemplate template = templateMapper.selectById(templateId);
if(template != null){
@ -155,4 +204,8 @@ public class TemplateManageService implements TemplateManageApi {
return extTemplateMapper.findTemplateList(request);
}
@Override
public List<TemplateManageDTO> findCategories(TemplateManageRequest request) {
return extTemplateMapper.findCategories(request);
}
}

View File

@ -1,38 +1,73 @@
DROP TABLE IF EXISTS `visualization_template`;
CREATE TABLE `visualization_template` (
`id` varchar(50) NOT NULL COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名称',
`pid` varchar(255) DEFAULT NULL COMMENT '父级id',
`level` int(10) DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) DEFAULT NULL COMMENT '种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint(13) DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL COMMENT '类型 system 系统内置 self 用户自建 ',
`template_style` longtext COMMENT 'template 样式',
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',
PRIMARY KEY (`id`)
);
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '名称',
`pid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '父级id',
`level` int DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '缩略图',
`template_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '类型 system 系统内置 self 用户自建 ',
`template_style` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT 'template 样式',
`template_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT 'template 数据',
`dynamic_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '预存数据',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模板表';
BEGIN;
INSERT INTO `core_menu`
VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 1, 1, 0);
INSERT INTO `core_menu`
VALUES (20, 15, 2, 'template-setting', 'system/template-setting', 4, 'icon_template', '/template-setting', 0, 1, 1);
COMMIT;
-- ----------------------------
-- Table structure for visualization_template_category
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_category`;
CREATE TABLE `visualization_template_category` (
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '名称',
`pid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '父级id',
`level` int DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '模版种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模板表';
-- ----------------------------
-- Table structure for visualization_template_category_map
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_category_map`;
CREATE TABLE `visualization_template_category_map` (
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
`category_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '名称',
`template_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '父级id',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模板表';
-- ----------------------------
-- Table structure for visualization_template_extend_data
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_extend_data`;
CREATE TABLE `visualization_template_extend_data` (
`id` bigint NOT NULL,
`dv_id` bigint DEFAULT NULL,
`view_id` bigint DEFAULT NULL,
`view_details` longtext,
`copy_from` varchar(255) DEFAULT NULL,
`copy_id` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
`view_details` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
`copy_from` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`copy_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
BEGIN;
INSERT INTO `core_menu`
VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 1, 1, 0);
INSERT INTO `core_menu`
VALUES (30, 0, 1, 'toolbox', null, 7, 'icon_template', '/toolbox', 1, 1, 0);
INSERT INTO `core_menu`
VALUES (31, 30, 2, 'template-setting', 'toolbox/template-setting', 1, 'icon_template', '/template-setting', 0, 1, 1);
COMMIT;
ALTER TABLE `core_opt_recent`
MODIFY COLUMN `resource_id` bigint NULL COMMENT '资源ID' AFTER `id`,

View File

@ -1,22 +1,63 @@
DROP TABLE IF EXISTS `visualization_template`;
CREATE TABLE `visualization_template`
(
`id` varchar(50) NOT NULL COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名称',
`pid` varchar(255) DEFAULT NULL COMMENT '父级id',
`level` int(10) DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) DEFAULT NULL COMMENT '模板种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint(13) DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL COMMENT '模板类型 system 系统内置 self 用户自建 ',
`template_style` longtext COMMENT 'template 样式',
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='模板表';
CREATE TABLE `visualization_template` (
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '名称',
`pid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '父级id',
`level` int DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '模版种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '缩略图',
`template_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '模版类型 system 系统内置 self 用户自建 ',
`template_style` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT 'template 样式',
`template_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT 'template 数据',
`dynamic_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '预存数据',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模板表';
-- ----------------------------
-- Table structure for visualization_template_category
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_category`;
CREATE TABLE `visualization_template_category` (
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '名称',
`pid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '父级id',
`level` int DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '模版种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模板表';
-- ----------------------------
-- Table structure for visualization_template_category_map
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_category_map`;
CREATE TABLE `visualization_template_category_map` (
`id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键',
`category_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '名称',
`template_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '父级id',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='模板表';
-- ----------------------------
-- Table structure for visualization_template_extend_data
-- ----------------------------
DROP TABLE IF EXISTS `visualization_template_extend_data`;
CREATE TABLE `visualization_template_extend_data` (
`id` bigint NOT NULL,
`dv_id` bigint DEFAULT NULL,
`view_id` bigint DEFAULT NULL,
`view_details` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
`copy_from` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`copy_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
BEGIN;
INSERT INTO `core_menu`
@ -27,18 +68,6 @@ INSERT INTO `core_menu`
VALUES (31, 30, 2, 'template-setting', 'toolbox/template-setting', 1, 'icon_template', '/template-setting', 0, 1, 1);
COMMIT;
DROP TABLE IF EXISTS `visualization_template_extend_data`;
CREATE TABLE `visualization_template_extend_data`
(
`id` bigint NOT NULL,
`dv_id` bigint DEFAULT NULL,
`view_id` bigint DEFAULT NULL,
`view_details` longtext,
`copy_from` varchar(255) DEFAULT NULL,
`copy_id` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
ALTER TABLE `core_opt_recent`
MODIFY COLUMN `resource_id` bigint NULL COMMENT '资源ID' AFTER `id`,

View File

@ -7,6 +7,7 @@
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="pid" jdbcType="VARCHAR" property="pid" />
<result column="level" jdbcType="INTEGER" property="level" />
<result column="dv_type" jdbcType="VARCHAR" property="dvType" />
<result column="node_type" jdbcType="VARCHAR" property="nodeType" />
<result column="create_by" jdbcType="VARCHAR" property="createBy" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
@ -23,77 +24,68 @@
<result column="childrenCount" jdbcType="VARCHAR" property="childrenCount"/>
</resultMap>
<resultMap id="BaseResultMapCollectionDTO" type="io.dataease.api.template.dto.TemplateManageDTO"
extends="BaseResultMapDTO">
<collection property="categories" ofType="String">
<result column="category_id" jdbcType="VARCHAR"/>
</collection>
</resultMap>
<sql id="Base_Column_List">
visualization_template.id, visualization_template.`name`, visualization_template.pid, visualization_template.`level`,visualization_template.`dv_type`, visualization_template.node_type, visualization_template.create_by, visualization_template.create_time, visualization_template.template_type, visualization_template.snapshot
vt.id, vt.`name`, vt.pid, vt.`level`,vt.`dv_type`, vt.node_type, vt.create_by, vt.create_time, vt.template_type, vt.snapshot
</sql>
<sql id="Blob_Column_List">
visualization_template.template_style, visualization_template.template_data, visualization_template.dynamic_data
,vt.template_style, vt.template_data, vt.dynamic_data
</sql>
<select id="findBaseTemplateList" resultMap="BaseResultMapDTO">
<select id="findBaseTemplateList" resultMap="BaseResultMapCollectionDTO">
SELECT
<include refid="Base_Column_List" />
vt.id,
vt.`name`,
vt.pid,
vt.`level`,
vt.`dv_type`,
vt.node_type,
vt.create_by,
vt.create_time,
vt.template_type,
vt.SNAPSHOT,
vtcm.category_id
FROM
visualization_template
<where>
<if test="nodeType != null">
and visualization_template.node_type = #{nodeType}
</if>
</where>
order by visualization_template.create_time desc
visualization_template vt
LEFT JOIN visualization_template_category_map vtcm ON vt.id = vtcm.template_id
ORDER BY
vt.create_time DESC
</select>
<select id="findCategories" resultMap="BaseResultMapDTO">
SELECT
id,
`name`,
`name` as lable,
pid,
`level`,
`dv_type`,
node_type,
create_by,
create_time,
template_type,
SNAPSHOT
FROM
visualization_template_category
order by visualization_template_category.create_time desc
</select>
<select id="findTemplateList" resultMap="BaseResultMapDTO">
SELECT
<include refid="Base_Column_List" />
,
<if test='withBlobs == "Y"'>
<include refid="Blob_Column_List" />
,
</if>
visualization_template.NAME AS label,
ifnull(tempCountInfo.childrenCount,0) as childrenCount
FROM
visualization_template
LEFT JOIN (
SELECT
pid,
count( 1 ) AS childrenCount
FROM
visualization_template
WHERE
pid IS NOT NULL
GROUP BY
pid
) tempCountInfo ON visualization_template.id = tempCountInfo.pid
<where>
<if test="name != null">
and visualization_template.name like CONCAT('%', #{name},'%')
</if>
<if test="dvType != null">
and visualization_template.dv_type = #{dvType}
</if>
<if test="nodeType != null">
and visualization_template.node_type = #{nodeType}
</if>
<if test="templateType != null">
and visualization_template.template_type = #{templateType}
</if>
<if test="id != null">
and visualization_template.id = #{id}
</if>
<if test="pid != null">
and visualization_template.pid = #{pid}
</if>
<if test="level != null">
and visualization_template.level = #{level}
</if>
</where>
<if test="sort != null">
order by ${sort}
</if>
<if test="sort == null">
order by visualization_template.create_time desc
</if>
visualization_template vt
LEFT JOIN visualization_template_category_map vtcm on vt.id = vtcm.template_id
where vtcm.category_id=#{categoryId}
order by vt.create_time desc
</select>
</mapper>

View File

@ -13,6 +13,12 @@ export function templateDelete(id) {
})
}
export function deleteCategory(id) {
return request.post({
url: '/templateManage/deleteCategory/' + id
})
}
export function showTemplateList(data) {
return request.post({
url: '/templateManage/templateList',
@ -34,6 +40,14 @@ export function find(data) {
})
}
export function findCategories(data) {
return request.post({
url: '/templateManage/findCategories',
data: data,
loading: true
})
}
export function nameCheck(data) {
return request.post({
url: '/templateManage/nameCheck',

View File

@ -349,27 +349,29 @@ defineExpose({
</el-icon>
</el-tooltip>
<el-dropdown popper-class="menu-outer-dv_popper" trigger="click">
<el-icon class="custom-icon btn" @click.stop>
<Icon name="icon_file-add_outlined" />
</el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="addOperation('newLeaf', null, 'leaf', true)">
<el-icon class="handle-icon">
<Icon :name="dvSvgType"></Icon>
</el-icon>
空白新建
</el-dropdown-item>
<el-dropdown-item @click="addOperation('newFromTemplate', null, 'leaf', true)">
<el-icon class="handle-icon">
<Icon name="dv-use-template"></Icon>
</el-icon>
使用模板新建
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-tooltip :content="newResourceLabel" placement="top" effect="dark">
<el-dropdown popper-class="menu-outer-dv_popper" trigger="hover">
<el-icon class="custom-icon btn" @click="addOperation('newLeaf', null, 'leaf', true)">
<Icon name="icon_file-add_outlined" />
</el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="addOperation('newLeaf', null, 'leaf', true)">
<el-icon class="handle-icon">
<Icon :name="dvSvgType"></Icon>
</el-icon>
空白新建
</el-dropdown-item>
<el-dropdown-item @click="addOperation('newFromTemplate', null, 'leaf', true)">
<el-icon class="handle-icon">
<Icon name="dv-use-template"></Icon>
</el-icon>
使用模板新建
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-tooltip>
</div>
</div>
<el-input

View File

@ -5,10 +5,11 @@
class="de-form-item"
:model="state.templateInfo"
:rules="state.templateInfoRules"
label-position="top"
>
<el-form-item :label="'模板名称'" prop="name">
<div class="flex-template">
<el-input v-model="state.templateInfo.name" clearable size="small" />
<el-input v-model="state.templateInfo.name" clearable />
<el-button style="margin-left: 10px" class="el-icon-upload2" secondary @click="goFile">{{
t('visualization.upload_template')
}}</el-button>
@ -22,8 +23,23 @@
/>
</div>
</el-form-item>
<el-row
v-show="!!state.importTemplateInfo.snapshot"
class="preview"
:style="classBackground"
/>
<el-form-item :label="'选择分类'" prop="categories" style="margin-top: 16px">
<el-select v-model="state.templateInfo.categories" multiple style="width: 100%">
<el-option
v-for="option in templateCategories"
:key="option.id"
:label="option.name"
:value="option.id"
/>
</el-select>
</el-form-item>
</el-form>
<el-row class="preview" :style="classBackground" />
<el-row> </el-row>
<el-row class="de-root-class">
<el-button secondary @click="cancel()">{{ t('commons.cancel') }}</el-button>
<el-button type="primary" @click="saveTemplate()">{{ t('commons.confirm') }}</el-button>
@ -44,10 +60,15 @@ const props = defineProps({
pid: {
type: String,
required: true
},
templateCategories: {
type: Array,
required: true
}
})
const state = reactive({
categories: [],
nameList: [],
importTemplateInfo: {
snapshot: ''
@ -59,12 +80,20 @@ const state = reactive({
message: t('commons.input_content'),
trigger: 'change'
}
],
categories: [
{
required: true,
message: t('commons.input_content'),
trigger: 'change'
}
]
},
recover: false,
templateInfo: {
level: '1',
pid: props.pid,
categories: [],
dvType: 'dashboard',
name: '',
templateStyle: null,
@ -103,26 +132,34 @@ const saveTemplate = () => {
ElMessage.warning(t('chart.template_can_not_empty'))
return false
}
if (!state.templateInfo.categories.length) {
ElMessage.warning('请选择分类')
return false
}
const nameCheckRequest = {
pid: state.templateInfo.pid,
name: state.templateInfo.name,
categories: state.templateInfo.categories,
optType: 'insert'
}
nameCheck(nameCheckRequest).then(response => {
if (response.data.indexOf('exist') > -1) {
const options = {
title: 'commons.prompt',
content: 'system_parameter_setting.to_overwrite_them',
type: 'primary',
cb: () =>
save(state.templateInfo).then(response => {
ElMessage.success('导入成功')
emits('refresh')
emits('closeEditTemplateDialog')
}),
confirmButtonText: t('template.override')
}
handlerConfirm(options)
ElMessage.warning(t('当前模版名称已经存在'))
// const options = {
// title: 'commons.prompt',
// content: 'system_parameter_setting.to_overwrite_them',
// type: 'primary',
// cb: () =>
// save(state.templateInfo).then(response => {
// ElMessage.success('')
// emits('refresh')
// emits('closeEditTemplateDialog')
// }),
// confirmButtonText: t('template.override')
// }
// handlerConfirm(options)
} else {
save(state.templateInfo).then(response => {
ElMessage.success(t('导入成功'))

View File

@ -11,16 +11,6 @@
:description="'没有找到相关内容'"
/>
<ul>
<li
:class="[{ select: state.activeTemplate === '1' }]"
@click="nodeClick({ id: '1', label: '默认分类' })"
>
<el-icon class="de-icon-sense">
<Icon name="scene" />
</el-icon>
<span class="text-template-overflow" :title="'默认分类'">默认分类</span>
</li>
<hr class="custom-line" />
<li
v-for="ele in templateListComputed"
:key="ele.name"
@ -36,10 +26,6 @@
<el-icon class="el-icon-more"><MoreFilled /></el-icon>
<template #dropdown>
<el-dropdown-menu class="de-template-dropdown">
<el-dropdown-item command="import">
<el-icon><Upload /></el-icon>
{{ t('visualization.import') }}
</el-dropdown-item>
<el-dropdown-item command="edit">
<el-icon><EditPen /></el-icon>
{{ t('visualization.rename') }}
@ -53,12 +39,6 @@
</el-dropdown>
</span>
</li>
<li @click="add()">
<el-icon class="de-icon-sense">
<Plus />
</el-icon>
<span class="text-template-overflow">{{ t('visualization.add_category') }}</span>
</li>
</ul>
</div>
</template>
@ -68,12 +48,13 @@ import { useI18n } from '@/hooks/web/useI18n'
import { computed, reactive } from 'vue'
import NoneImage from '@/assets/none.png'
import NothingImage from '@/assets/nothing.png'
import { ElMessageBox } from 'element-plus-secondary'
const { t } = useI18n()
const emits = defineEmits([
'showCurrentTemplate',
'showTemplateEditDialog',
'templateDelete',
'categoryDelete',
'templateEdit',
'templateImport'
])
@ -108,28 +89,30 @@ const clickMore = (type, data) => {
templateEdit(data)
break
case 'delete':
templateDelete(data)
categoryDelete(data)
break
case 'import':
templateImport(data)
break
}
}
const nodeClick = ({ id, label }) => {
const nodeClick = ({ id, name }) => {
state.activeTemplate = id
emits('showCurrentTemplate', id, label)
emits('showCurrentTemplate', id, name)
}
const add = () => {
emits('showTemplateEditDialog', 'new')
}
const templateDelete = template => {
const options = {
title: 'system_parameter_setting.delete_this_category',
content: 'system_parameter_setting.also_be_deleted',
type: 'primary',
cb: () => emits('templateDelete', template.id)
}
handlerConfirm(options)
const categoryDelete = template => {
ElMessageBox.confirm('确定删除该分类吗?', {
tip: '删除后,该分类下的所有模版也将删除。',
confirmButtonType: 'danger',
type: 'warning',
autofocus: false,
showClose: false
}).then(() => {
emits('categoryDelete', template.id)
})
}
const templateEdit = template => {
emits('templateEdit', template)
@ -153,10 +136,10 @@ defineExpose({
position: relative;
ul {
margin: 16px 0 20px 0;
margin: 0px 0 0 0;
padding: 0;
overflow-y: auto;
max-height: calc(100% - 90px);
max-height: 100%;
}
li {

View File

@ -4,6 +4,12 @@
<el-button style="float: right" type="primary" @click="templateImport(state.currentTemplateId)">
{{ t('visualization.import') }}
</el-button>
<el-button
style="float: right; margin-right: 12px"
@click="showTemplateEditDialog('new', null)"
>
添加分类
</el-button>
<el-input
v-model="state.templateFilterText"
:placeholder="'搜索关键字'"
@ -26,8 +32,8 @@
<de-template-list
ref="templateListRef"
:template-type="state.currentTemplateType"
:template-list="state.templateList"
@templateDelete="templateFolderDelete"
:template-list="state.templateCategories"
@categoryDelete="categoryDelete"
@templateEdit="templateEdit"
@showCurrentTemplate="showCurrentTemplate"
@templateImport="templateImport"
@ -100,6 +106,7 @@
<de-template-import
v-if="state.templateDialog.visible"
:pid="state.templateDialog.pid"
:template-categories="state.templateCategories"
@refresh="showCurrentTemplate(state.currentTemplateId, state.currentTemplateLabel)"
@closeEditTemplateDialog="closeEditTemplateDialog"
/>
@ -110,7 +117,7 @@
</template>
<script lang="ts" setup>
import { save, templateDelete, find } from '@/api/template'
import { save, templateDelete, find, findCategories, deleteCategory } from '@/api/template'
import elementResizeDetectorMaker from 'element-resize-detector'
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
@ -168,7 +175,7 @@ const state = reactive({
dialogTitleLabel: '',
currentTemplateLabel: '',
currentTemplateId: '',
templateList: [],
templateCategories: [],
templateMiniWidth: 256,
templateCurWidth: 256,
formType: '',
@ -176,7 +183,8 @@ const state = reactive({
templateDialog: {
title: t('visualization.import_template'),
visible: false,
pid: ''
pid: '',
categories: []
}
})
@ -194,23 +202,11 @@ const nameList = computed(() => {
}
if (nodeType === 'folder') {
return state.templateList.map(ele => ele.label)
return state.templateCategories.map(ele => ele.label)
}
return []
})
const initStyle = () => {
nextTick(() => {
const tree = document.querySelector('.ed-tree')
// 线
const line = document.createElement('hr')
line.classList.add('custom-line')
// 线
tree.firstElementChild.appendChild(line)
})
}
const nameRepeat = value => {
if (!nameList.value) {
return false
@ -251,15 +247,15 @@ const showCurrentTemplate = (pid, label) => {
state.currentTemplateId = pid
state.currentTemplateLabel = label
if (state.currentTemplateId) {
find({ pid: state.currentTemplateId }).then(response => {
find({ categoryId: state.currentTemplateId }).then(response => {
state.currentTemplateShowList = response.data
})
}
}
const templateFolderDelete = id => {
const categoryDelete = id => {
if (id) {
templateDelete(id).then(response => {
deleteCategory(id).then(response => {
ElMessage({
message: t('commons.delete_success'),
type: 'success',
@ -306,16 +302,16 @@ const templateEdit = templateInfo => {
showTemplateEditDialog('edit', templateInfo)
}
const categoryClick = params => {
// do
console.log('categoryClick=' + JSON.stringify(params))
}
const saveTemplateEdit = templateEditForm => {
templateEditFormRef.value.validate(valid => {
if (valid) {
save(templateEditForm).then(response => {
close()
// openMessageSuccess(
// `system_parameter_setting.${
// this.templateEditForm.id ? 'rename_succeeded' : 'added_successfully'
// }`
// )
getTree()
})
} else {
@ -333,24 +329,24 @@ const getTree = () => {
templateType: state.currentTemplateType,
level: '0'
}
find(request).then(res => {
state.templateList = res.data
findCategories(request).then(res => {
state.templateCategories = res.data
showFirst()
})
})
}
const showFirst = () => {
//
if (state.templateList && state.templateList.length > 0) {
if (state.templateCategories && state.templateCategories.length > 0) {
let showFirst = true
state.templateList.forEach(template => {
state.templateCategories.forEach(template => {
if (template.id === state.currentTemplateId) {
showFirst = false
}
})
if (showFirst) {
nextTick().then(() => {
const [obj = {}] = state.templateList
const [obj = {}] = state.templateCategories
templateListRef.value.nodeClick(obj)
})
} else {
@ -382,7 +378,6 @@ onMounted(() => {
state.templateCurWidth = Math.trunc(offsetWidth / curSeparator) - 24 - curSeparator
})
})
initStyle()
})
</script>
@ -403,7 +398,7 @@ onMounted(() => {
background: #fff;
width: 269px;
border-right: 1px solid rgba(31, 35, 41, 0.15);
padding: 24px;
padding: 12px 8px;
}
.de-tabs-right {
@ -471,6 +466,5 @@ onMounted(() => {
.template-search-class {
float: right;
width: 320px;
margin-right: 12px;
}
</style>

View File

@ -17,12 +17,18 @@ public interface TemplateManageApi {
@PostMapping("/delete/{id}")
void delete(@PathVariable String id);
@PostMapping("/deleteCategory/{id}")
void deleteCategory(@PathVariable String id);
@GetMapping("/findOne/{templateId}")
VisualizationTemplateVO findOne(@PathVariable String templateId) throws Exception;
@PostMapping("/find")
List<TemplateManageDTO> find(@RequestBody TemplateManageRequest request);
@PostMapping("/findCategories")
List<TemplateManageDTO> findCategories(@RequestBody TemplateManageRequest request);
@PostMapping("/nameCheck")
String nameCheck(@RequestBody TemplateManageRequest request);

View File

@ -20,5 +20,9 @@ public class TemplateManageDTO extends VisualizationTemplateVO {
private List<TemplateManageDTO> children;
private List<String> categories;
private List<String> categoryNames;
}

View File

@ -8,6 +8,7 @@ import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Data
@NoArgsConstructor
@ -42,10 +43,10 @@ public class TemplateMarketDTO implements Comparable<TemplateMarketDTO> {
this.id = manageDTO.getId();
this.title = manageDTO.getName();
this.mainCategory = manageDTO.getCategoryName();
this.categories = Arrays.asList(new MarketCategoryVO(manageDTO.getCategoryName()));
this.categoryNames = Arrays.asList(manageDTO.getCategoryName());
this.categories = manageDTO.getCategoryNames().stream().map(category->new MarketCategoryVO(category)).collect(Collectors.toList());
this.categoryNames = manageDTO.getCategoryNames();
this.metas = new MarketMetasVO(manageDTO.getSnapshot());
this.templateType = "dataV".equalsIgnoreCase("manageDTO.getTemplateType()") ? "SCREEN" : "PANEL";
this.templateType = "dataV".equalsIgnoreCase(manageDTO.getTemplateType()) ? "SCREEN" : "PANEL";
this.thumbnail = manageDTO.getSnapshot();
this.source = "manage";
if (manageDTO.getRecentUseTime() != null) {

View File

@ -3,6 +3,8 @@ package io.dataease.api.template.request;
import io.dataease.api.template.vo.VisualizationTemplateVO;
import lombok.Data;
import java.util.List;
/**
* Author: wangjiahao
* Date: 2021-03-05
@ -21,7 +23,12 @@ public class TemplateManageRequest extends VisualizationTemplateVO {
private String leafDvType;
private String categoryId;
private List<String> categories;
public TemplateManageRequest() {
}
public TemplateManageRequest(String pid,String dvType) {

View File

@ -0,0 +1,56 @@
package io.dataease.api.template.vo;
import lombok.Data;
/**
* @author : WangJiaHao
* @date : 2023/11/7 13:22
*/
@Data
public class VisualizationTemplateCategoryVO {
/**
* 主键
*/
private String id;
/**
* 名称
*/
private String name;
/**
* 父级id
*/
private String pid;
/**
* 层级
*/
private Integer level;
/**
* 模板种类 dataV or dashboard 目录或者文件夹
*/
private String dvType;
/**
* 节点类型 folder or panel 目录或者文件夹
*/
private String nodeType;
/**
* 创建人
*/
private String createBy;
/**
* 创建时间
*/
private Long createTime;
/**
* 缩略图
*/
private String snapshot;
}