Merge pull request #6915 from dataease/pr@dev-v2@refactor_market

refactor: 模板管理模板市场合并为模板中心
This commit is contained in:
王嘉豪 2023-11-29 13:18:04 +08:00 committed by GitHub
commit b0f079dfe5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 324 additions and 128 deletions

View File

@ -49,7 +49,7 @@ public class ChartDataServer implements ChartDataApi {
@Override
public ChartViewDTO getData(ChartViewDTO chartViewDTO) throws Exception {
try {
// 从模数据获取
// 从模数据获取
if(CommonConstants.VIEW_DATA_FROM.TEMPLATE.equalsIgnoreCase(chartViewDTO.getDataFrom())){
return extendDataManage.getChartDataInfo(chartViewDTO.getId(),chartViewDTO);
}else{

View File

@ -26,7 +26,7 @@ public class OptConstants {
public static final int DATASET = 4;
//数据源
public static final int DATASOURCE = 5;
//
//
public static final int TEMPLATE = 6;
}

View File

@ -37,7 +37,7 @@ public class VisualizationTemplate implements Serializable {
private Integer level;
/**
* 种类 dataV or dashboard 目录或者文件夹
* 种类 dataV or dashboard 目录或者文件夹
*/
private String dvType;
@ -62,7 +62,7 @@ public class VisualizationTemplate implements Serializable {
private String snapshot;
/**
* 类型 system 系统内置 self 用户自建
* 类型 system 系统内置 self 用户自建
*/
private String templateType;

View File

@ -3,6 +3,7 @@ package io.dataease.template.dao.ext;
import io.dataease.api.template.dto.TemplateManageDTO;
import io.dataease.api.template.request.TemplateManageRequest;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -11,5 +12,6 @@ import java.util.List;
public interface ExtVisualizationTemplateMapper{
List<TemplateManageDTO> findTemplateList(TemplateManageRequest request);
List<TemplateManageDTO> findBaseTemplateList(@Param("nodeType") String nodeType);
}

View File

@ -1,5 +1,6 @@
package io.dataease.template.manage;
import io.dataease.api.template.dto.TemplateManageDTO;
import io.dataease.api.template.dto.TemplateManageFileDTO;
import io.dataease.api.template.dto.TemplateMarketDTO;
import io.dataease.api.template.dto.TemplateMarketPreviewInfoDTO;
@ -10,9 +11,11 @@ import io.dataease.api.template.vo.TemplateCategoryVO;
import io.dataease.exception.DEException;
import io.dataease.operation.manage.CoreOptRecentManage;
import io.dataease.system.manage.SysParameterManage;
import io.dataease.template.dao.ext.ExtVisualizationTemplateMapper;
import io.dataease.utils.HttpClientConfig;
import io.dataease.utils.HttpClientUtil;
import io.dataease.utils.JsonUtil;
import io.dataease.utils.LogUtil;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -25,7 +28,7 @@ import java.util.stream.Collectors;
* Author: wangjiahao
*/
@Service
public class TemplateMarketManage {
public class TemplateCenterManage {
private final static String POSTS_API = "/api/content/posts?page=0&size=2000";
@ -40,6 +43,9 @@ public class TemplateMarketManage {
@Resource
private CoreOptRecentManage coreOptRecentManage;
@Resource
private ExtVisualizationTemplateMapper templateManageMapper;
/**
* @param templateUrl template url
* @Description Get template file from template market
@ -64,22 +70,45 @@ public class TemplateMarketManage {
return HttpClientUtil.get(url, config);
}
private MarketTemplateV2BaseResponse templateQuery(Map<String, String> templateParams){
String result = marketGet(templateParams.get("template.url") + POSTS_API_V2, null);
MarketTemplateV2BaseResponse postsResult = JsonUtil.parseObject(result, MarketTemplateV2BaseResponse.class);
return postsResult;
}
private MarketTemplateV2BaseResponse templateQuery(Map<String, String> templateParams) {
String result = marketGet(templateParams.get("template.url") + POSTS_API_V2, null);
MarketTemplateV2BaseResponse postsResult = JsonUtil.parseObject(result, MarketTemplateV2BaseResponse.class);
return postsResult;
}
public MarketBaseResponse searchTemplate() {
try {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
return baseResponseV2Trans(templateQuery(templateParams), templateParams.get("template.url"));
return baseResponseV2Trans(templateQuery(templateParams), searchTemplateFromManage(), templateParams.get("template.url"));
} catch (Exception e) {
DEException.throwException(e);
}
return null;
}
private List<TemplateMarketDTO> searchTemplateFromManage() {
try {
List<TemplateManageDTO> manageResult = templateManageMapper.findBaseTemplateList("template");
List<TemplateManageDTO> categories = templateManageMapper.findBaseTemplateList("folder");
Map<String, String> categoryMap = categories.stream()
.collect(Collectors.toMap(TemplateManageDTO::getId, TemplateManageDTO::getName));
return baseManage2MarketTrans(manageResult, categoryMap);
} catch (Exception e) {
DEException.throwException(e);
}
return null;
}
private List<TemplateMarketDTO> baseManage2MarketTrans(List<TemplateManageDTO> manageResult, Map<String, String> categoryMap) {
List<TemplateMarketDTO> result = new ArrayList<>();
manageResult.stream().forEach(templateManageDTO -> {
templateManageDTO.setCategoryName(categoryMap.get(templateManageDTO.getPid()));
result.add(new TemplateMarketDTO(templateManageDTO));
});
return result;
}
public MarketBaseResponse searchTemplateRecommend() {
try {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
@ -93,7 +122,7 @@ public class TemplateMarketManage {
public MarketPreviewBaseResponse searchTemplatePreview() {
try {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
return basePreviewResponseV2Trans(templateQuery(templateParams), templateParams.get("template.url"));
return basePreviewResponseV2Trans(templateQuery(templateParams), searchTemplateFromManage(), templateParams.get("template.url"));
} catch (Exception e) {
DEException.throwException(e);
}
@ -106,76 +135,57 @@ public class TemplateMarketManage {
List<TemplateMarketDTO> contents = new ArrayList<>();
v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> {
MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec();
if("Y".equalsIgnoreCase(spec.getSuggest())){
contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()),"Y"));
if ("Y".equalsIgnoreCase(spec.getSuggest())) {
contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()), "Y"));
}
});
// 最近使用排序
Collections.sort(contents);
return new MarketBaseResponse(url,contents);
return new MarketBaseResponse(url, contents);
}
private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, String url) {
private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List<TemplateMarketDTO> contents, String url) {
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
Map<String, String> categoriesMap = getCategoriesBaseV2();
List<TemplateMarketDTO> contents = new ArrayList<>();
v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> {
MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec();
contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()),spec.getSuggest()));
contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()), spec.getSuggest()));
});
// 最近使用排序
Collections.sort(contents);
return new MarketBaseResponse(url,contents);
return new MarketBaseResponse(url, contents);
}
private MarketPreviewBaseResponse basePreviewResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, String url) {
private MarketPreviewBaseResponse basePreviewResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List<TemplateMarketDTO> manageContents, String url) {
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
Map<String, String> categoriesMap = getCategoriesBaseV2();
List<String> categories = new ArrayList<>();
List<MarketMetaDataVO> categoryVO = getCategoriesV2();
Map<String, String> categoriesMap = categoryVO.stream()
.collect(Collectors.toMap(MarketMetaDataVO::getSlug, MarketMetaDataVO::getLabel));
List<String> categories = categoryVO.stream().filter(node -> !"全部".equalsIgnoreCase(node.getLabel())).map(MarketMetaDataVO::getLabel)
.collect(Collectors.toList());
List<TemplateMarketPreviewInfoDTO> result = new ArrayList<>();
categoriesMap.forEach((key,value)->{
if(!"全部".equalsIgnoreCase(value)){
categories.add(value);
categoriesMap.forEach((key, value) -> {
if (!"全部".equalsIgnoreCase(value)) {
List<TemplateMarketDTO> contents = new ArrayList<>();
v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> {
MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec();
if(key.equalsIgnoreCase(spec.getLabel())){
contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()),spec.getSuggest()));
if (key.equalsIgnoreCase(spec.getLabel())) {
contents.add(new TemplateMarketDTO(spec.getReadmeName(), spec.getDisplayName(), spec.getScreenshots().get(0).getUrl(), spec.getLinks().get(0).getUrl(), categoriesMap.get(spec.getLabel()), spec.getTemplateType(), useTime.get(spec.getReadmeName()), spec.getSuggest()));
}
});
manageContents.stream().forEach(templateMarketDTO -> {
if (value.equalsIgnoreCase(templateMarketDTO.getMainCategory())) {
contents.add(templateMarketDTO);
}
});
Collections.sort(contents);
result.add(new TemplateMarketPreviewInfoDTO(value,contents));
result.add(new TemplateMarketPreviewInfoDTO(value, contents));
}
});
// 最近使用排序
return new MarketPreviewBaseResponse(url,categories,result);
return new MarketPreviewBaseResponse(url, categories, result);
}
public MarketBaseResponse searchTemplateV1() {
try {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
String result = marketGet(templateParams.get("template.url") + POSTS_API, templateParams.get("template.accessKey"));
MarketTemplateBaseResponse postsResult = JsonUtil.parseObject(result, MarketTemplateBaseResponse.class);
MarketBaseResponse response = new MarketBaseResponse(templateParams.get("template.url"), postsResult.getData().getContent());
return response;
} catch (Exception e) {
DEException.throwException(e);
}
return null;
}
public List<String> getCategoriesV1() {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
String resultStr = marketGet(templateParams.get("template.url") + CATEGORIES_API, templateParams.get("template.accessKey"));
MarketCategoryBaseResponse categoryBaseResponse = JsonUtil.parseObject(resultStr, MarketCategoryBaseResponse.class);
List<TemplateCategoryVO> categories = categoryBaseResponse.getData();
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;
}
}
public List<String> getCategories() {
return getCategoriesV2().stream().map(MarketMetaDataVO::getLabel)
@ -196,10 +206,21 @@ public class TemplateMarketManage {
}
public List<MarketMetaDataVO> getCategoriesV2() {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
String resultStr = marketGet(templateParams.get("template.url") + TEMPLATE_META_DATA_URL, null);
MarketMetaDataBaseResponse metaData = JsonUtil.parseObject(resultStr, MarketMetaDataBaseResponse.class);
List<MarketMetaDataVO> categories = metaData.getLabels();
return categories;
List<MarketMetaDataVO> allCategories = new ArrayList<>();
List<TemplateManageDTO> manageCategories = templateManageMapper.findBaseTemplateList("folder");
List<MarketMetaDataVO> manageCategoriesTrans = manageCategories.stream()
.map(templateCategory -> new MarketMetaDataVO(templateCategory.getId(), templateCategory.getName()))
.collect(Collectors.toList());
try {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
String resultStr = marketGet(templateParams.get("template.url") + TEMPLATE_META_DATA_URL, null);
MarketMetaDataBaseResponse metaData = JsonUtil.parseObject(resultStr, MarketMetaDataBaseResponse.class);
allCategories.addAll(metaData.getLabels());
} catch (Exception e) {
LogUtil.error("模板市场分类获取错误", e);
}
allCategories.addAll(manageCategoriesTrans);
return allCategories;
}
}

View File

@ -4,7 +4,7 @@ import io.dataease.api.template.TemplateMarketApi;
import io.dataease.api.template.response.MarketBaseResponse;
import io.dataease.api.template.response.MarketPreviewBaseResponse;
import io.dataease.api.template.vo.MarketMetaDataVO;
import io.dataease.template.manage.TemplateMarketManage;
import io.dataease.template.manage.TemplateCenterManage;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@ -20,28 +20,28 @@ import java.util.List;
public class TemplateMarketService implements TemplateMarketApi {
@Resource
private TemplateMarketManage templateMarketManage;
private TemplateCenterManage templateCenterManage;
@Override
public MarketBaseResponse searchTemplate() {
return templateMarketManage.searchTemplate();
return templateCenterManage.searchTemplate();
}
@Override
public MarketBaseResponse searchTemplateRecommend() {
return templateMarketManage.searchTemplateRecommend();
return templateCenterManage.searchTemplateRecommend();
}
@Override
public MarketPreviewBaseResponse searchTemplatePreview() {
return templateMarketManage.searchTemplatePreview();
return templateCenterManage.searchTemplatePreview();
}
@Override
public List<String> categories() {
return templateMarketManage.getCategories();
return templateCenterManage.getCategories();
}
@Override
public List<MarketMetaDataVO> categoriesObject() {
return templateMarketManage.getCategoriesObject();
return templateCenterManage.getCategoriesObject();
}
}

View File

@ -11,7 +11,6 @@ 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;
@ -26,7 +25,7 @@ import io.dataease.template.dao.auto.entity.VisualizationTemplate;
import io.dataease.template.dao.auto.entity.VisualizationTemplateExtendData;
import io.dataease.template.dao.auto.mapper.VisualizationTemplateExtendDataMapper;
import io.dataease.template.dao.auto.mapper.VisualizationTemplateMapper;
import io.dataease.template.manage.TemplateMarketManage;
import io.dataease.template.manage.TemplateCenterManage;
import io.dataease.utils.AuthUtils;
import io.dataease.utils.BeanUtils;
import io.dataease.utils.IDUtils;
@ -73,7 +72,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
private VisualizationTemplateMapper templateMapper;
@Resource
private TemplateMarketManage templateMarketManage;
private TemplateCenterManage templateCenterManage;
@Resource
private StaticResourceServer staticResourceServer;
@ -251,7 +250,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
name = request.getName();
dvType = request.getType();
} else if (DataVisualizationConstants.NEW_PANEL_FROM.NEW_MARKET_TEMPLATE.equals(newFrom)) {
TemplateManageFileDTO templateFileInfo = templateMarketManage.getTemplateFromMarket(request.getTemplateUrl());
TemplateManageFileDTO templateFileInfo = templateCenterManage.getTemplateFromMarket(request.getTemplateUrl());
if (templateFileInfo == null) {
DEException.throwException("Can't find the template's info from market,please check");
}
@ -261,7 +260,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
staticResource = templateFileInfo.getStaticResource();
name = templateFileInfo.getName();
dvType = templateFileInfo.getDvType();
// 市场记录
// 市场记录
coreOptRecentManage.saveOpt(request.getResourceName(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE,OptConstants.OPT_TYPE.NEW);
}
// 解析动态数据
@ -286,7 +285,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
extendDataInfo.put(newViewId, extendDataDTO);
templateData = templateData.replaceAll(originViewId, newViewId.toString());
canvasViewInfo.put(chartView.getId(), chartView);
//插入模数据 此处预先插入减少数据交互量
//插入模数据 此处预先插入减少数据交互量
VisualizationTemplateExtendData extendData = new VisualizationTemplateExtendData();
templateExtendDataMapper.insert(BeanUtils.copyBean(extendData, extendDataDTO));
}

View File

@ -4,12 +4,12 @@ CREATE TABLE `visualization_template` (
`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 目录或者文件夹',
`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_type` varchar(255) DEFAULT NULL COMMENT '类型 system 系统内置 self 用户自建 ',
`template_style` longtext COMMENT 'template 样式',
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',

View File

@ -5,12 +5,12 @@ CREATE TABLE `visualization_template`
`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 目录或者文件夹',
`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_type` varchar(255) DEFAULT NULL COMMENT '类型 system 系统内置 self 用户自建 ',
`template_style` longtext COMMENT 'template 样式',
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',

View File

@ -30,6 +30,19 @@
visualization_template.template_style, visualization_template.template_data, visualization_template.dynamic_data
</sql>
<select id="findBaseTemplateList" resultMap="BaseResultMapDTO">
SELECT
<include refid="Base_Column_List" />
FROM
visualization_template
<where>
<if test="nodeType != null">
and visualization_template.node_type = #{nodeType}
</if>
</where>
order by visualization_template.create_time desc
</select>
<select id="findTemplateList" resultMap="BaseResultMapDTO">
SELECT
<include refid="Base_Column_List" />

View File

@ -12,7 +12,7 @@ const backToMain = () => {
<el-header class="header-flex system-header">
<Icon className="logo" name="logo"></Icon>
<el-divider direction="vertical" />
<span class="system">版市场</span>
<span class="system">板中心</span>
<div class="operate-setting">
<span @click="backToMain" class="work-bar flex-align-center">
<el-icon>

View File

@ -105,7 +105,7 @@ export default {
placeholder: '点击选择文件',
defaultTip: '仅支持xlsx、xls格式的文件',
errorTip: '上传失败:文件中存在不合规数据,如需查看详情,',
downTip: '下载模',
downTip: '下载模',
uploadAgain: '再次上传',
backUserGrid: '返回用户列表',
sure: '确定',
@ -114,7 +114,7 @@ export default {
limitMsg: '文件最大10M',
suffixMsg: '只支持.xlsx|.xls结尾的文件',
exceedMsg: '只能上传一个文件',
templateError: '用户模错误',
templateError: '用户模错误',
first_please: '请先',
fill_and_upload: ',按要求填写后上传',
import: '导入'
@ -1534,7 +1534,7 @@ export default {
not_cover: '不覆盖',
import_mode: '导入模式',
import_module: '导入模块',
please_fill_in_the_template: '请填写模内容',
please_fill_in_the_template: '请填写模内容',
cut_back_old_version: '切回旧版',
cut_back_new_version: '切回新版',
comment: '评论',

View File

@ -5,7 +5,7 @@
<Icon class-name="item-icon" name="dv-up-arrow" />
<div>
<el-button style="opacity: 1 !important" type="warning" size="mini" round>
<span style="font-weight: bold; opacity: 1"> 当前为模视图请更换数据集...</span>
<span style="font-weight: bold; opacity: 1"> 当前为模视图请更换数据集...</span>
</el-button>
</div>
</div>

View File

@ -1,7 +1,7 @@
<template>
<el-dialog
class="create-dialog"
title="从模新建"
title="从模新建"
v-model="state.dialogShow"
width="700"
:before-close="close"

View File

@ -0,0 +1,46 @@
<template>
<el-dialog
class="market-create-dialog"
v-model="state.dialogShow"
width="90vw"
height="90vh"
:before-close="close"
@submit.prevent
>
<template-market ref="templateMarketCreateRef" @close="close"></template-market>
</el-dialog>
</template>
<script setup lang="ts">
import TemplateMarket from '@/views/template-market/index.vue'
import { nextTick, onMounted, reactive, ref } from 'vue'
const templateMarketCreateRef = ref(null)
const state = reactive({
dialogShow: false
})
const close = () => {
state.dialogShow = false
}
const optInit = param => {
state.dialogShow = true
nextTick(() => {
templateMarketCreateRef.value.optInit(param)
})
}
defineExpose({
optInit
})
</script>
<style lang="less">
.market-create-dialog {
.ed-dialog__body {
padding: 0 !important;
}
.ed-dialog__header {
display: none !important;
}
}
</style>

View File

@ -15,6 +15,7 @@ import router from '@/router'
import { useI18n } from '@/hooks/web/useI18n'
import _ from 'lodash'
import DeResourceCreateOpt from '@/views/common/DeResourceCreateOpt.vue'
import DeResourceCreateOptV2 from '@/views/common/DeResourceCreateOptV2.vue'
import { useCache } from '@/hooks/web/useCache'
const { wsCache } = useCache()
@ -112,7 +113,7 @@ state.resourceTypeList = [
command: 'newLeaf'
},
{
label: '使用模新建',
label: '使用模新建',
svgName: 'dv-use-template',
command: 'newFromTemplate'
},
@ -251,9 +252,15 @@ const addOperation = (
window.open(baseUrl, '_blank')
}
} else if (cmd === 'newFromTemplate') {
state.templateCreatePid = data?.id
// newFromTemplate
resourceCreateOpt.value.optInit()
// state.templateCreatePid = data?.id
// // newFromTemplate
// resourceCreateOpt.value.optInit()
const params = {
curPosition: 'create',
pid: data?.id,
templateType: curCanvasType.value === 'dataV' ? 'SCREEN' : 'PANEL'
}
resourceCreateOpt.value.optInit(params)
} else {
resourceGroupOpt.value.optInit(nodeType, data || {}, cmd, parentSelect)
}
@ -358,7 +365,7 @@ defineExpose({
<el-icon class="handle-icon">
<Icon name="dv-use-template"></Icon>
</el-icon>
使用模新建
使用模新建
</el-dropdown-item>
</el-dropdown-menu>
</template>
@ -449,6 +456,11 @@ defineExpose({
@finish="resourceCreateFinish"
>
</de-resource-create-opt>
<!-- <de-resource-create-opt-v2-->
<!-- :cur-canvas-type="curCanvasType"-->
<!-- ref="resourceCreateOpt"-->
<!-- @finish="resourceCreateFinish"-->
<!-- ></de-resource-create-opt-v2>-->
</el-scrollbar>
</div>
</template>

View File

@ -67,7 +67,7 @@ onMounted(() => {
dataInitState.value = false
nextTick(() => {
dvMainStore.createInit('dashboard', null, pid)
//
//
if (createType === 'template') {
const deTemplateDataStr = wsCache.get(`de-template-data`)
const deTemplateData = JSON.parse(deTemplateDataStr)

View File

@ -128,7 +128,7 @@ watch(
>PDF</el-dropdown-item
>
<el-dropdown-item style="width: 118px" @click="downloadAsAppTemplate('template')"
></el-dropdown-item
></el-dropdown-item
>
<el-dropdown-item @click="download('img')">{{
t('chart.image')

View File

@ -197,7 +197,7 @@ onMounted(() => {
state.canvasInitStatus = true
dvMainStore.setDataPrepareState(true)
snapshotStore.recordSnapshotCache('renderChart')
//
//
if (createType === 'template') {
const deTemplateDataStr = wsCache.get(`de-template-data`)
const deTemplateData = JSON.parse(deTemplateDataStr)

View File

@ -82,7 +82,7 @@
<div style="text-align: center">
<Icon name="no_result" style="margin-bottom: 16px; font-size: 75px"></Icon>
<br />
<span>没有找到相关模</span>
<span>没有找到相关模</span>
</div>
</el-row>
</el-row>
@ -105,7 +105,7 @@
</div>
</el-row>
<el-row class="img-main">
<img style="height: 100%" :src="state.templatePreviewUrl" alt="" />
<img style="height: 100%" :src="imgUrlTrans(state.templatePreviewUrl)" alt="" />
</el-row>
</el-col>
</el-row>
@ -118,6 +118,8 @@ import { onMounted, reactive, watch, ref } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import TemplateMarketPreviewItem from '@/views/template-market/component/TemplateMarketPreviewItem.vue'
import { deepCopy } from '@/utils/utils'
import { imgUrlTrans } from '@/utils/imgUtils'
const { t } = useI18n()
const props = defineProps({
@ -264,7 +266,10 @@ const templateShow = templateItem => {
const previewTemplate = template => {
state.curTemplate = template
if (template.thumbnail.indexOf('http') > -1) {
if (
template.thumbnail.indexOf('http') > -1 ||
template.thumbnail.indexOf('static-resource') > -1
) {
state.templatePreviewUrl = template.thumbnail
} else {
state.templatePreviewUrl = state.baseUrl + template.thumbnail

View File

@ -43,7 +43,10 @@ const classBackground = computed(() => {
})
const thumbnailUrl = computed(() => {
if (props.template.thumbnail.indexOf('http') > -1) {
if (
props.template.thumbnail.indexOf('http') > -1 ||
props.template.thumbnail.indexOf('static-resource') > -1
) {
return props.template.thumbnail
} else {
return props.baseUrl + props.template.thumbnail

View File

@ -51,7 +51,10 @@ const classBackground = computed(() => {
})
const thumbnailUrl = computed(() => {
if (props.template.thumbnail.indexOf('http') > -1) {
if (
props.template.thumbnail.indexOf('http') > -1 ||
props.template.thumbnail.indexOf('static-resource') > -1
) {
return props.template.thumbnail
} else {
return props.baseUrl + props.template.thumbnail

View File

@ -1,7 +1,7 @@
<template>
<el-row
class="template-outer-body"
:class="{ 'template-outer-body-padding': !previewModel }"
:class="{ 'template-outer-body-padding': outPaddingState }"
v-loading="state.loading"
>
<market-preview-v2
@ -12,20 +12,27 @@
></market-preview-v2>
<el-row v-show="!previewModel" class="main-container">
<el-row class="market-head">
<span>版市场 </span>
<span>板中心 </span>
<el-row class="head-right">
<el-input
class="title-search"
v-model="state.searchText"
prefix-icon="Search"
size="small"
:placeholder="t('visualization.enter_template_name_tips')"
:clearable="true"
/>
<el-select class="title-type" v-model="state.templateSourceType" placeholder="Select">
<el-option
v-for="item in state.templateSourceOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select
v-if="state.curPosition === 'branch'"
class="title-type"
v-model="state.templateType"
size="small"
placeholder="Select"
>
<el-option
@ -35,12 +42,18 @@
:value="item.value"
/>
</el-select>
<el-divider
class="custom-divider-line"
v-if="state.curPosition === 'create'"
direction="vertical"
/>
</el-row>
</el-row>
<el-row class="template-area">
<div class="template-left">
<el-tree
menu
class="custom-market-tree"
:data="state.marketTabs"
:props="state.treeProps"
node-key="label"
@ -86,7 +99,7 @@
<div style="text-align: center">
<Icon name="no_result" style="margin-bottom: 16px; font-size: 75px"></Icon>
<br />
<span>没有找到相关模</span>
<span>没有找到相关模</span>
</div>
</el-row>
<el-row v-show="!state.networkStatus" class="template-empty">
@ -107,17 +120,45 @@ import { decompression } from '@/api/visualization/dataVisualization'
import { useCache } from '@/hooks/web/useCache'
import TemplateMarketV2Item from '@/views/template-market/component/TemplateMarketV2Item.vue'
import MarketPreviewV2 from '@/views/template-market/component/MarketPreviewV2.vue'
import { propTypes } from '@/utils/propTypes'
const { t } = useI18n()
const { wsCache } = useCache()
const previewModel = ref(false)
const outPaddingState = computed(() => {
return state.curPosition === 'branch' && !previewModel.value
})
const optInit = params => {
state.curPosition = params.curPosition
state.templateType = params.templateType
state.pid = params.pid
}
const state = reactive({
curPosition: 'branch',
pid: null,
treeProps: {
value: 'label',
label: 'label'
},
templateType: 'all',
templateSourceType: 'all',
templateSourceOptions: [
{
value: 'all',
label: '全部来源'
},
{
value: 'market',
label: '模板市场'
},
{
value: 'manage',
label: '模板管理'
}
],
templateTypeOptions: [
{
value: 'all',
@ -134,7 +175,7 @@ const state = reactive({
],
loading: false,
hasResult: true,
templateMiniWidth: 270,
templateMiniWidth: 250,
templateCurWidth: 310,
templateSpan: '25%',
previewVisible: false,
@ -149,6 +190,7 @@ const state = reactive({
nodeType: 'panel',
templateUrl: null,
newFrom: 'new_market_template',
templateId: null,
panelType: 'self',
panelStyle: {},
panelData: '[]'
@ -191,6 +233,13 @@ watch(
}
)
watch(
() => state.templateSourceType,
value => {
initTemplateShow()
}
)
const searchResultCount = computed(
() => state.currentMarketTemplateShowList.filter(template => template.showFlag).length
)
@ -226,7 +275,7 @@ const initMarketTemplate = async () => {
const initStyle = () => {
nextTick(() => {
const tree = document.querySelector('.ed-tree')
const tree = document.querySelector('.custom-market-tree')
// 线
const line = document.createElement('hr')
line.classList.add('custom-line')
@ -245,13 +294,20 @@ const normalizer = node => {
const templateApply = template => {
state.curApplyTemplate = template
state.dvCreateForm.name = template.title
state.dvCreateForm.templateUrl = template.metas.theme_repo
state.dvCreateForm.resourceName = template.id
if (template.source === 'market') {
state.dvCreateForm.newFrom = 'new_market_template'
state.dvCreateForm.templateUrl = template.metas.theme_repo
state.dvCreateForm.resourceName = template.id
} else {
state.dvCreateForm.newFrom = 'new_inner_template'
state.dvCreateForm.templateId = template.id
}
apply()
}
const apply = () => {
if (!state.dvCreateForm.templateUrl) {
if (state.dvCreateForm.newFrom === 'new_market_template' && !state.dvCreateForm.templateUrl) {
ElMessage.warning('未获取模板下载链接请联系模板市场官方')
return false
}
@ -292,6 +348,7 @@ const templateShow = templateItem => {
let categoryMarch = false
let searchMarch = false
let templateTypeMarch = false
let templateSourceTypeMarch = false
if (state.marketActiveTab === '最近使用') {
if (templateItem.recentUseTime) {
categoryMarch = true
@ -315,7 +372,11 @@ const templateShow = templateItem => {
if (state.templateType === 'all' || templateItem.templateType === state.templateType) {
templateTypeMarch = true
}
return categoryMarch && searchMarch && templateTypeMarch
if (state.templateSourceType === 'all' || templateItem.source === state.templateSourceType) {
templateSourceTypeMarch = true
}
return categoryMarch && searchMarch && templateTypeMarch && templateSourceTypeMarch
}
const templatePreview = previewId => {
@ -348,6 +409,10 @@ const previewInit = () => {
wsCache.delete('template-preview-id')
}
}
defineExpose({
optInit
})
</script>
<style lang="less" scoped>
@ -449,6 +514,10 @@ const previewInit = () => {
margin-right: 8px;
}
}
.custom-divider-line {
height: 30px;
}
</style>
<style lang="less">

View File

@ -6,7 +6,7 @@
:model="state.templateInfo"
:rules="state.templateInfoRules"
>
<el-form-item :label="'模名称'" prop="name">
<el-form-item :label="'模名称'" prop="name">
<div class="flex-template">
<el-input v-model="state.templateInfo.name" clearable size="small" />
<el-button style="margin-left: 10px" class="el-icon-upload2" secondary @click="goFile">{{

View File

@ -1,6 +1,6 @@
<template>
<div class="template-head">
<p class="router-title">管理</p>
<p class="router-title">管理</p>
<el-button style="float: right" type="primary" @click="templateImport(state.currentTemplateId)">
{{ t('visualization.import') }}
</el-button>
@ -49,7 +49,7 @@
<el-empty
v-if="!state.currentTemplateShowList.length"
:image="NoneImage"
:description="'暂无模'"
:description="'暂无模'"
/>
<div v-show="state.currentTemplateId !== ''" id="template-box" class="template-box">
<de-template-item
@ -287,7 +287,7 @@ const showTemplateEditDialog = (type, templateInfo) => {
state.formType = type
if (type === 'edit') {
state.templateEditForm = JSON.parse(JSON.stringify(templateInfo))
state.dialogTitle = state.templateEditForm['nodeType'] === 'folder' ? '编辑分类' : '编辑模'
state.dialogTitle = state.templateEditForm['nodeType'] === 'folder' ? '编辑分类' : '编辑模'
state.originName = state.templateEditForm['label']
} else {
state.dialogTitle = t('visualization.add_category')
@ -298,7 +298,7 @@ const showTemplateEditDialog = (type, templateInfo) => {
level: 0
}
}
state.dialogTitleLabel = state.templateEditForm['nodeType'] === 'folder' ? '分类名称' : '模名称'
state.dialogTitleLabel = state.templateEditForm['nodeType'] === 'folder' ? '分类名称' : '模名称'
state.editTemplate = true
}

View File

@ -43,9 +43,10 @@ const classBackground = computed(() => {
})
const thumbnailUrl = computed(() => {
if (props.template.thumbnail.indexOf('http') > -1) {
return props.template.thumbnail
} else {
if (
props.template.thumbnail.indexOf('http') > -1 ||
props.template.thumbnail.indexOf('static-resource') > -1
) else {
return props.baseUrl + props.template.thumbnail
}
})

View File

@ -66,7 +66,7 @@ const tabBtnList = [
value: 'SCREEN'
},
{
name: '应用模',
name: '应用模',
value: 'APP'
}
]
@ -285,7 +285,7 @@ initMarketTemplate()
<div class="template-market-dashboard">
<div class="template-market">
<div class="label">
版市场
板中心
<div class="expand-all">
<button class="all flex-center" @click="toTemplateMarket">查看全部</button>
<el-divider direction="vertical" />
@ -322,7 +322,7 @@ initMarketTemplate()
<div style="text-align: center">
<Icon name="no_result" class="no-result"></Icon>
<br />
<span class="no-result-tips">没有找到相关模</span>
<span class="no-result-tips">没有找到相关模</span>
</div>
</el-row>
<el-row v-show="!state.networkStatus" class="template-empty">

View File

@ -14,6 +14,10 @@ public class TemplateManageDTO extends VisualizationTemplateVO {
private Integer childrenCount;
private String categoryName;
private Long recentUseTime;
private List<TemplateManageDTO> children;

View File

@ -4,9 +4,6 @@ import io.dataease.api.template.vo.MarketCategoryVO;
import io.dataease.api.template.vo.MarketMetasVO;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.ArrayUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -28,11 +25,30 @@ public class TemplateMarketDTO implements Comparable<TemplateMarketDTO> {
private Long recentUseTime = 0L;
private String templateType;
// 模板来源 market = 模板市场manage=模板管理
private String source = "market";
private List<MarketCategoryVO> categories;
private String mainCategory;
private MarketMetasVO metas;
public TemplateMarketDTO(String id, String title, String themeRepo, String templateUrl, String categoryName, String templateType, Long recentUseTime,String suggest) {
public TemplateMarketDTO(TemplateManageDTO manageDTO) {
this.id = manageDTO.getId();
this.title = manageDTO.getName();
this.mainCategory = manageDTO.getCategoryName();
this.categories = Arrays.asList(new MarketCategoryVO(manageDTO.getCategoryName()), new MarketCategoryVO("全部"));
this.metas = new MarketMetasVO(manageDTO.getSnapshot());
this.templateType = "dataV".equalsIgnoreCase("manageDTO.getTemplateType()") ? "SCREEN" : "PANEL";
this.thumbnail = manageDTO.getSnapshot();
this.source = "manage";
if (manageDTO.getRecentUseTime() != null) {
this.recentUseTime = manageDTO.getRecentUseTime();
}
}
public TemplateMarketDTO(String id, String title, String themeRepo, String templateUrl, String categoryName, String templateType, Long recentUseTime, String suggest) {
this.id = id;
this.title = title;
this.categories = Arrays.asList(new MarketCategoryVO(categoryName), new MarketCategoryVO("全部"));
@ -42,8 +58,8 @@ public class TemplateMarketDTO implements Comparable<TemplateMarketDTO> {
if (recentUseTime != null) {
this.recentUseTime = recentUseTime;
}
if("Y".equalsIgnoreCase(suggest)){
this.suggest="Y";
if ("Y".equalsIgnoreCase(suggest)) {
this.suggest = "Y";
}
}

View File

@ -17,5 +17,7 @@ public class MarketMetaDataVO {
public MarketMetaDataVO(String value, String label) {
this.label = label;
this.value = value;
this.slug = value;
}
}

View File

@ -30,7 +30,7 @@ public class VisualizationTemplateVO {
private Integer level;
/**
* 种类 dataV or dashboard 目录或者文件夹
* 种类 dataV or dashboard 目录或者文件夹
*/
private String dvType;
@ -55,7 +55,7 @@ public class VisualizationTemplateVO {
private String snapshot;
/**
* 类型 system 系统内置 self 用户自建
* 类型 system 系统内置 self 用户自建
*/
private String templateType;

View File

@ -66,7 +66,7 @@ public interface DataVisualizationApi {
String findDvType(@PathVariable("dvId")Long dvId);
/**
* 从模版解压可视化资源 模版来源包括 模版市场内部模版管理
* 从模板解压可视化资源 模板来源包括 模板市场内部模板管理
*
* @return
*/
@ -74,7 +74,7 @@ public interface DataVisualizationApi {
DataVisualizationVO decompression(@RequestBody DataVisualizationBaseRequest request) throws Exception;
/**
* 从模版解压可视化资源 模版来源包括本地上传
* 从模板解压可视化资源 模板来源包括本地上传
*
* @return
*/

View File

@ -125,7 +125,7 @@ public class DataVisualizationVO implements Serializable {
private Map<Long, ChartViewDTO> canvasViewInfo = new HashMap<>();
/**
* 视图模数据
* 视图模数据
*/
private Map<Long, VisualizationTemplateExtendDataDTO> extendDataInfo = new HashMap<>();