feat: 模版市场

This commit is contained in:
wangjiahao
2023-11-10 08:39:42 +08:00
parent bf8cd7e593
commit 2d864eea23
30 changed files with 791 additions and 93 deletions

View File

@@ -14,7 +14,7 @@ public class MybatisPlusGenerator {
* 第一 我嫌麻烦
* 第二 后面配置会放到nacos读起来更麻烦了
*/
private static final String url = "jdbc:mysql://39.98.78.97:3306/dataease?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false";
private static final String url = "jdbc:mysql://127.0.0.1:3306/de_standalone?autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false";
private static final String username = "root";
private static final String password = "Password123@mysql";
@@ -25,7 +25,7 @@ public class MybatisPlusGenerator {
/**
* 这是要生成代码的表名称
*/
private static final String TABLE_NAME = "visualization_template";
private static final String TABLE_NAME = "visualization_template_extend_data";
/**
* 下面两个配置基本上不用动

View File

@@ -1,6 +1,24 @@
package io.dataease.commons.constants;
public class DataVisualizationConstants {
//新建仪表板来源
public static final class NEW_PANEL_FROM {
// 直接新建
public static final String NEW = "new";
// 内部模板新建
public static final String NEW_INNER_TEMPLATE = "new_inner_template";
// 外部模板新建
public static final String NEW_OUTER_TEMPLATE = "new_outer_template";
// 模板市场新建
public static final String NEW_MARKET_TEMPLATE = "new_market_template";
}
//删除标志
public static final class DELETE_FLAG {
//已删除

View File

@@ -7,8 +7,12 @@ import io.dataease.utils.IDUtils;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
public class SysParameterManage {
@@ -57,4 +61,14 @@ public class SysParameterManage {
QueryWrapper<CoreSysSetting> queryWrapper = new QueryWrapper<>();
return coreSysSettingMapper.selectList(queryWrapper);
}
public Map<String,String> groupVal(String groupKey) {
QueryWrapper<CoreSysSetting> queryWrapper = new QueryWrapper<>();
queryWrapper.likeLeft("pkey", groupKey);
List<CoreSysSetting> sysSettings = coreSysSettingMapper.selectList(queryWrapper);
if (!CollectionUtils.isEmpty(sysSettings)) {
return sysSettings.stream().collect(Collectors.toMap(CoreSysSetting::getPkey, CoreSysSetting::getPval));
}
return null;
}
}

View File

@@ -0,0 +1,90 @@
package io.dataease.template.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author fit2cloud
* @since 2023-11-10
*/
@TableName("visualization_template_extend_data")
public class VisualizationTemplateExtendData implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Long dvId;
private Long viewId;
private String viewDetails;
private String copyFrom;
private String copyId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getDvId() {
return dvId;
}
public void setDvId(Long dvId) {
this.dvId = dvId;
}
public Long getViewId() {
return viewId;
}
public void setViewId(Long viewId) {
this.viewId = viewId;
}
public String getViewDetails() {
return viewDetails;
}
public void setViewDetails(String viewDetails) {
this.viewDetails = viewDetails;
}
public String getCopyFrom() {
return copyFrom;
}
public void setCopyFrom(String copyFrom) {
this.copyFrom = copyFrom;
}
public String getCopyId() {
return copyId;
}
public void setCopyId(String copyId) {
this.copyId = copyId;
}
@Override
public String toString() {
return "VisualizationTemplateExtendData{" +
"id = " + id +
", dvId = " + dvId +
", viewId = " + viewId +
", viewDetails = " + viewDetails +
", copyFrom = " + copyFrom +
", copyId = " + copyId +
"}";
}
}

View File

@@ -0,0 +1,18 @@
package io.dataease.template.dao.auto.mapper;
import io.dataease.template.dao.auto.entity.VisualizationTemplateExtendData;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author fit2cloud
* @since 2023-11-10
*/
@Mapper
public interface VisualizationTemplateExtendDataMapper extends BaseMapper<VisualizationTemplateExtendData> {
}

View File

@@ -0,0 +1,87 @@
package io.dataease.template.manage;
import com.fasterxml.jackson.core.type.TypeReference;
import io.dataease.api.template.dto.TemplateManageFileDTO;
import io.dataease.api.template.dto.TemplateMarketDTO;
import io.dataease.api.template.request.TemplateMarketSearchRequest;
import io.dataease.api.template.response.MarketBaseResponse;
import io.dataease.api.template.vo.TemplateCategoryVO;
import io.dataease.exception.DEException;
import io.dataease.system.manage.SysParameterManage;
import io.dataease.utils.HttpClientConfig;
import io.dataease.utils.HttpClientUtil;
import io.dataease.utils.JsonUtil;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Author: wangjiahao
*/
@Service
public class TemplateMarketManage {
private final static String POSTS_API = "/api/content/posts?page=0&size=2000";
private final static String CATEGORIES_API = "/api/content/categories";
@Resource
private SysParameterManage sysParameterManage;
/**
* @param templateUrl template url
* @Description Get template file from template market
*/
public TemplateManageFileDTO getTemplateFromMarket(String templateUrl) {
if (StringUtils.isNotEmpty(templateUrl)) {
String sufUrl = sysParameterManage.groupVal("template.").get("template.url");
String templateInfo = HttpClientUtil.get(sufUrl + templateUrl, null);
return JsonUtil.parseObject(templateInfo,TemplateManageFileDTO.class);
} else {
return null;
}
}
/**
* @param url content api url
* @Description Get info from template market content api
*/
public String marketGet(String url, String accessKey) {
HttpClientConfig config = new HttpClientConfig();
config.addHeader("API-Authorization", accessKey);
return HttpClientUtil.get(url, config);
}
public MarketBaseResponse searchTemplate(TemplateMarketSearchRequest request) {
try {
Map<String,String> templateParams = sysParameterManage.groupVal("template.");
String result = marketGet(templateParams.get("template.url") + POSTS_API, templateParams.get("template.accessKey"));
TypeReference<List<TemplateMarketDTO>> market = new TypeReference<>() {
};
List<TemplateMarketDTO> postsResult = JsonUtil.parseList(result,market);
return new MarketBaseResponse(templateParams.get("template.url"), postsResult);
} catch (Exception e) {
DEException.throwException(e);
}
return null;
}
public List<String> getCategories() {
Map<String,String> templateParams = sysParameterManage.groupVal("template.");
String resultStr = marketGet(templateParams.get("template.url") + CATEGORIES_API, templateParams.get("template.accessKey"));
TypeReference<List<TemplateCategoryVO>> market = new TypeReference<>() {
};
List<TemplateCategoryVO> categories = JsonUtil.parseList(resultStr,market);
if (CollectionUtils.isNotEmpty(categories)) {
return categories.stream().filter(item -> !"应用系列".equals(item.getName())).sorted(Comparator.comparing(TemplateCategoryVO::getPriority)).map(TemplateCategoryVO::getName).collect(Collectors.toList());
} else {
return null;
}
}
}

View File

@@ -1,6 +1,7 @@
package io.dataease.template.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.dataease.api.template.TemplateManageApi;
import io.dataease.api.template.dto.TemplateManageDTO;
import io.dataease.api.template.request.TemplateManageRequest;
import io.dataease.api.template.vo.VisualizationTemplateVO;
@@ -17,6 +18,8 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Optional;
@@ -28,7 +31,9 @@ import static io.dataease.constant.StaticResourceConstants.UPLOAD_URL_PREFIX;
* @author : WangJiaHao
* @date : 2023/11/7 13:29
*/
public class TemplateManageService {
@RestController
@RequestMapping("/templateManage")
public class TemplateManageService implements TemplateManageApi {
@Resource
private VisualizationTemplateMapper templateMapper;
@@ -37,6 +42,7 @@ public class TemplateManageService {
@Resource
private StaticResourceServer staticResourceServer;
@Override
public List<TemplateManageDTO> templateList(TemplateManageRequest request) {
request.setWithBlobs("N");
List<TemplateManageDTO> templateList = extTemplateMapper.findTemplateList(request);
@@ -58,7 +64,9 @@ public class TemplateManageService {
return extTemplateMapper.findTemplateList(request);
}
@Transactional
@Override
public TemplateManageDTO save(TemplateManageRequest request) {
if (StringUtils.isEmpty(request.getId())) {
request.setId(UUID.randomUUID().toString());
@@ -121,17 +129,17 @@ public class TemplateManageService {
return CommonConstants.CHECK_RESULT.EXIST_ALL;
}
}
@Override
public String nameCheck(TemplateManageRequest request) {
return nameCheck(request.getOptType(), request.getName(), request.getPid(), request.getId());
}
@Override
public void delete(String id) {
Assert.notNull(id, "id cannot be null");
templateMapper.deleteById(id);
}
@Override
public VisualizationTemplateVO findOne(String panelId) {
VisualizationTemplate template = templateMapper.selectById(panelId);
if(template != null){
@@ -142,7 +150,7 @@ public class TemplateManageService {
return null;
}
}
@Override
public List<TemplateManageDTO> find(TemplateManageRequest request) {
return extTemplateMapper.findTemplateList(request);
}

View File

@@ -3,22 +3,29 @@ package io.dataease.visualization.server;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.dataease.api.chart.dto.ChartViewDTO;
import io.dataease.api.template.dto.TemplateManageFileDTO;
import io.dataease.api.visualization.DataVisualizationApi;
import io.dataease.api.visualization.request.DataVisualizationBaseRequest;
import io.dataease.api.visualization.request.VisualizationWorkbranchQueryRequest;
import io.dataease.api.visualization.vo.DataVisualizationVO;
import io.dataease.api.visualization.vo.VisualizationResourceVO;
import io.dataease.chart.dao.auto.entity.CoreChartView;
import io.dataease.chart.dao.auto.mapper.CoreChartViewMapper;
import io.dataease.chart.manage.ChartDataManage;
import io.dataease.chart.manage.ChartViewManege;
import io.dataease.commons.constants.DataVisualizationConstants;
import io.dataease.constant.CommonConstants;
import io.dataease.exception.DEException;
import io.dataease.license.config.XpackInteract;
import io.dataease.model.BusiNodeRequest;
import io.dataease.model.BusiNodeVO;
import io.dataease.template.dao.auto.entity.VisualizationTemplate;
import io.dataease.template.dao.auto.mapper.VisualizationTemplateMapper;
import io.dataease.template.manage.TemplateMarketManage;
import io.dataease.utils.AuthUtils;
import io.dataease.utils.BeanUtils;
import io.dataease.utils.IDUtils;
import io.dataease.utils.JsonUtil;
import io.dataease.visualization.dao.auto.entity.DataVisualizationInfo;
import io.dataease.visualization.dao.auto.mapper.DataVisualizationInfoMapper;
import io.dataease.visualization.dao.ext.mapper.ExtDataVisualizationMapper;
@@ -29,7 +36,10 @@ import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -54,6 +64,16 @@ public class DataVisualizationServer implements DataVisualizationApi {
@Resource
private ChartDataManage chartDataManage;
@Resource
private VisualizationTemplateMapper templateMapper;
@Resource
private TemplateMarketManage templateMarketManage;
@Resource
private StaticResourceServer staticResourceServer;
@Override
@XpackInteract(value = "dataVisualizationServer", original = true)
public DataVisualizationVO findById(Long dvId,String busiFlag) {
@@ -195,6 +215,74 @@ public class DataVisualizationServer implements DataVisualizationApi {
return extDataVisualizationMapper.findDvType(dvId);
}
@Override
public DataVisualizationVO decompression(DataVisualizationBaseRequest request) throws Exception {
Long newDvId = IDUtils.snowID();
String newFrom = request.getNewFrom();
String templateStyle = null;
String templateData = null;
String dynamicData = null;
String staticResource = null;
String name = null;
String dvType = null;
//内部模板新建
if (DataVisualizationConstants.NEW_PANEL_FROM.NEW_INNER_TEMPLATE.equals(newFrom)) {
VisualizationTemplate visualizationTemplate = templateMapper.selectById(request.getTemplateId());
templateStyle = visualizationTemplate.getTemplateStyle();
templateData = visualizationTemplate.getTemplateData();
dynamicData = visualizationTemplate.getDynamicData();
name = visualizationTemplate.getName();
dvType = visualizationTemplate.getDvType();
} else if (DataVisualizationConstants.NEW_PANEL_FROM.NEW_OUTER_TEMPLATE.equals(newFrom)) {
templateStyle = request.getCanvasStyleData();
templateData = request.getCanvasStyleData();
dynamicData = request.getDynamicData();
staticResource = request.getStaticResource();
name = request.getName();
dvType = request.getType();
} else if (DataVisualizationConstants.NEW_PANEL_FROM.NEW_MARKET_TEMPLATE.equals(newFrom)) {
TemplateManageFileDTO templateFileInfo = templateMarketManage.getTemplateFromMarket(request.getTemplateUrl());
if (templateFileInfo == null) {
DEException.throwException("Can't find the template's info from market,please check");
}
templateStyle = templateFileInfo.getCanvasStyleData();
templateData = templateFileInfo.getComponentData();
dynamicData = templateFileInfo.getDynamicData();
staticResource = templateFileInfo.getStaticResource();
name = request.getName();
dvType = request.getType();
}
// 解析动态数据
Map<String, String> dynamicDataMap = JsonUtil.parseObject(dynamicData, Map.class);
List<ChartViewDTO> chartViews = new ArrayList<>();
Map<Long,ChartViewDTO> canvasViewInfo = new HashMap<>();
// List<PanelGroupExtendDataDTO> viewsData = new ArrayList<>();
for (Map.Entry<String, String> entry : dynamicDataMap.entrySet()) {
String originViewId = entry.getKey();
String originViewData = entry.getValue();
ChartViewDTO chartView = JsonUtil.parseObject(originViewData, ChartViewDTO.class);
Long newViewId = IDUtils.snowID();
chartView.setId(newViewId);
chartView.setSceneId(newDvId);
chartView.setDataFrom(CommonConstants.VIEW_DATA_FROM.TEMPLATE);
// 数据处理 1.替换viewId 2.加入panelView 数据(数据来源为template) 3.加入模板view data数据
// viewsData.add(new PanelGroupExtendDataDTO(newPanelId, newViewId, originViewData));
templateData = templateData.replaceAll(originViewId, newViewId.toString());
chartViewManege.save(chartView);
canvasViewInfo.put(chartView.getId(),chartView);
}
request.setComponentData(templateData);
request.setCanvasStyleData(templateStyle);
//Store static resource into the server
staticResourceServer.saveFilesToServe(staticResource);
return new DataVisualizationVO(newDvId,name,dvType,templateStyle,templateData,canvasViewInfo);
}
@Override
public DataVisualizationVO decompressionLocalFile(MultipartFile file) {
return null;
}
@Override
public void nameCheck(DataVisualizationBaseRequest request) {

View File

@@ -14,4 +14,22 @@ CREATE TABLE `visualization_template` (
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',
PRIMARY KEY (`id`)
);
);
BEGIN;
INSERT INTO `core_menu`
VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 0, 1, 0);
INSERT INTO `core_menu`
VALUES (20, 15, 2, 'template-setting', 'system/template-setting', 4, '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`)
);

View File

@@ -23,4 +23,15 @@ INSERT INTO `core_menu`
VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 0, 1, 0);
INSERT INTO `core_menu`
VALUES (20, 15, 2, 'template-setting', 'system/template-setting', 4, 'icon_template', '/template-setting', 0, 1, 1);
COMMIT;
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`)
);

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.dataease.template.dao.ext.ExtVisualizationTemplateMapper">
<resultMap id="BaseResultMap" type="io.dataease.api.template.vo.VisualizationTemplateVO">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="pid" jdbcType="VARCHAR" property="pid" />
<result column="level" jdbcType="INTEGER" property="level" />
<result column="node_type" jdbcType="VARCHAR" property="nodeType" />
<result column="create_by" jdbcType="VARCHAR" property="createBy" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="template_type" jdbcType="VARCHAR" property="templateType" />
<result column="snapshot" jdbcType="LONGVARCHAR" property="snapshot" />
<result column="template_style" jdbcType="LONGVARCHAR" property="templateStyle" />
<result column="template_data" jdbcType="LONGVARCHAR" property="templateData" />
<result column="dynamic_data" jdbcType="LONGVARCHAR" property="dynamicData" />
</resultMap>
<resultMap id="BaseResultMapDTO" type="io.dataease.api.template.dto.TemplateManageDTO"
extends="BaseResultMap">
<result column="label" jdbcType="VARCHAR" property="label"/>
<result column="childrenCount" jdbcType="VARCHAR" property="childrenCount"/>
</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
</sql>
<sql id="Blob_Column_List">
visualization_template.template_style, visualization_template.template_data, visualization_template.dynamic_data
</sql>
<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>
</select>
</mapper>