refactor: 使用模板中心创建UI优化

This commit is contained in:
wangjiahao 2023-11-30 00:01:55 +08:00
parent e08d92d1b7
commit 23a3cbd5d0
11 changed files with 234 additions and 60 deletions

View File

@ -92,6 +92,10 @@
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>

View File

@ -51,5 +51,13 @@ public class DataVisualizationConstants {
public static final String COPY = "copy";
}
public static final class TEMPLATE_SOURCE {
//模板市场
public static final String MARKET = "market";
//模板管理
public static final String MANAGE = "manage";
//公共
public static final String PUBLIC = "public";
}
}

View File

@ -1,5 +1,6 @@
package io.dataease.template.manage;
import com.mysql.cj.log.Log;
import io.dataease.api.template.dto.TemplateManageDTO;
import io.dataease.api.template.dto.TemplateManageFileDTO;
import io.dataease.api.template.dto.TemplateMarketDTO;
@ -8,6 +9,7 @@ import io.dataease.api.template.response.*;
import io.dataease.api.template.vo.MarketApplicationSpecVO;
import io.dataease.api.template.vo.MarketMetaDataVO;
import io.dataease.api.template.vo.TemplateCategoryVO;
import io.dataease.constant.CommonConstants;
import io.dataease.exception.DEException;
import io.dataease.operation.manage.CoreOptRecentManage;
import io.dataease.system.manage.SysParameterManage;
@ -71,9 +73,14 @@ public class TemplateCenterManage {
}
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;
try {
String result = marketGet(templateParams.get("template.url") + POSTS_API_V2, null);
MarketTemplateV2BaseResponse postsResult = JsonUtil.parseObject(result, MarketTemplateV2BaseResponse.class);
return postsResult;
} catch (Exception e) {
LogUtil.error(e);
return null;
}
}
public MarketBaseResponse searchTemplate() {
@ -81,7 +88,7 @@ public class TemplateCenterManage {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
return baseResponseV2Trans(templateQuery(templateParams), searchTemplateFromManage(), templateParams.get("template.url"));
} catch (Exception e) {
DEException.throwException(e);
LogUtil.error(e);
}
return null;
}
@ -124,7 +131,7 @@ public class TemplateCenterManage {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
return basePreviewResponseV2Trans(templateQuery(templateParams), searchTemplateFromManage(), templateParams.get("template.url"));
} catch (Exception e) {
DEException.throwException(e);
LogUtil.error(e);
}
return null;
}
@ -133,12 +140,14 @@ public class TemplateCenterManage {
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();
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 (v2BaseResponse != null) {
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"));
}
});
}
// 最近使用排序
Collections.sort(contents);
return new MarketBaseResponse(url, contents);
@ -147,10 +156,16 @@ public class TemplateCenterManage {
private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List<TemplateMarketDTO> contents, String url) {
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
Map<String, String> categoriesMap = getCategoriesBaseV2();
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.stream().forEach(templateMarketDTO -> {
Long recentUseTime = useTime.get(templateMarketDTO.getId());
templateMarketDTO.setRecentUseTime(recentUseTime == null ? 0 : recentUseTime);
});
if (v2BaseResponse != null) {
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()));
});
}
// 最近使用排序
Collections.sort(contents);
return new MarketBaseResponse(url, contents);
@ -167,12 +182,14 @@ public class TemplateCenterManage {
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 (v2BaseResponse != null) {
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()));
}
});
}
manageContents.stream().forEach(templateMarketDTO -> {
if (value.equalsIgnoreCase(templateMarketDTO.getMainCategory())) {
contents.add(templateMarketDTO);
@ -194,8 +211,7 @@ public class TemplateCenterManage {
public List<MarketMetaDataVO> getCategoriesObject() {
List<MarketMetaDataVO> result = getCategoriesV2();
result.add(0, new MarketMetaDataVO("suggest", "推荐"));
result.add(0, new MarketMetaDataVO("recent", "最近使用"));
result.add(0, new MarketMetaDataVO("recent", "最近使用", "public"));
return result;
}
@ -209,13 +225,14 @@ public class TemplateCenterManage {
List<MarketMetaDataVO> allCategories = new ArrayList<>();
List<TemplateManageDTO> manageCategories = templateManageMapper.findBaseTemplateList("folder");
List<MarketMetaDataVO> manageCategoriesTrans = manageCategories.stream()
.map(templateCategory -> new MarketMetaDataVO(templateCategory.getId(), templateCategory.getName()))
.map(templateCategory -> new MarketMetaDataVO(templateCategory.getId(), templateCategory.getName(), CommonConstants.TEMPLATE_SOURCE.MANAGE))
.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());
allCategories.add(0, new MarketMetaDataVO("suggest", "推荐"));
} catch (Exception e) {
LogUtil.error("模板市场分类获取错误", e);
}

View File

@ -242,6 +242,8 @@ public class DataVisualizationServer implements DataVisualizationApi {
dynamicData = visualizationTemplate.getDynamicData();
name = visualizationTemplate.getName();
dvType = visualizationTemplate.getDvType();
// 模板市场记录
coreOptRecentManage.saveOpt(request.getTemplateId(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE,OptConstants.OPT_TYPE.NEW);
} else if (DataVisualizationConstants.NEW_PANEL_FROM.NEW_OUTER_TEMPLATE.equals(newFrom)) {
templateStyle = request.getCanvasStyleData();
templateData = request.getComponentData();

View File

@ -450,17 +450,17 @@ defineExpose({
@finish="resourceOptFinish"
ref="resourceGroupOpt"
/>
<de-resource-create-opt
:cur-canvas-type="curCanvasType"
ref="resourceCreateOpt"
@finish="resourceCreateFinish"
>
</de-resource-create-opt>
<!-- <de-resource-create-opt-v2-->
<!-- <de-resource-create-opt-->
<!-- :cur-canvas-type="curCanvasType"-->
<!-- ref="resourceCreateOpt"-->
<!-- @finish="resourceCreateFinish"-->
<!-- ></de-resource-create-opt-v2>-->
<!-- >-->
<!-- </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

@ -98,7 +98,6 @@
<el-button
style="float: right"
type="primary"
size="small"
@click="templateApply(state.curTemplate)"
>{{ t('visualization.apply_this_template') }}</el-button
>

View File

@ -2,7 +2,10 @@
<div class="testcase-template">
<div class="template-img" :style="classBackground" @click.stop="templateInnerPreview" />
<el-row class="bottom-area"> </el-row>
<el-row class="bottom-area-show">
<el-row
class="bottom-area-show"
:class="{ 'create-area': ['branchCreate', 'create'].includes(props.curPosition) }"
>
<el-row class="demonstration">
{{ template.title }}
</el-row>
@ -33,6 +36,9 @@ const props = defineProps({
return {}
}
},
curPosition: {
type: String
},
baseUrl: {
type: String
},
@ -130,4 +136,7 @@ const templateInnerPreview = e => {
color: deepskyblue;
cursor: pointer;
}
.create-area {
bottom: -38px !important;
}
</style>

View File

@ -3,14 +3,47 @@
class="template-outer-body"
:class="{ 'template-outer-body-padding': outPaddingState }"
v-loading="state.loading"
v-show="state.initReady"
>
<market-preview-v2
v-show="previewModel"
v-show="previewModel === 'marketPreview'"
:preview-id="state.templatePreviewId"
@closePreview="closePreview"
@templateApply="templateApply"
></market-preview-v2>
<el-row v-show="!previewModel" class="main-container">
<el-row v-if="previewModel === 'createPreview'" class="main-container">
<el-row class="market-head">
<el-icon class="custom-back-icon hover-icon" @click="previewModel = 'full'"
><ArrowLeft
/></el-icon>
<span>{{ state.curTemplate.title }} </span>
<el-row class="head-right">
<el-button :disabled="state.curTemplateIndex === 0" style="float: right" @click="preOne"
>上一个</el-button
>
<el-button
:disabled="state.curTemplateIndex === state.curTemplateShowFilter.length - 1"
style="float: right"
@click="nextOne"
>下一个</el-button
>
<el-button
style="float: right"
type="primary"
@click="templateApply(state.curTemplate)"
>{{ t('visualization.apply_this_template') }}</el-button
>
<el-divider class="custom-divider-line" direction="vertical" />
<el-icon class="custom-market-icon hover-icon" @click="close"><Close /></el-icon>
</el-row>
</el-row>
<el-row class="template-area">
<el-row class="img-main-create">
<img style="height: 100%" :src="curTemplateImg" alt="" />
</el-row>
</el-row>
</el-row>
<el-row v-show="previewModel === 'full'" class="main-container">
<el-row class="market-head">
<span>{{ title }} </span>
<el-row class="head-right">
@ -30,7 +63,7 @@
/>
</el-select>
<el-select
v-if="state.curPosition === 'branch'"
v-if="['branchCreate', 'branch'].includes(state.curPosition)"
class="title-type"
v-model="state.templateType"
placeholder="Select"
@ -42,11 +75,10 @@
:value="item.value"
/>
</el-select>
<el-divider
class="custom-divider-line"
v-if="state.curPosition === 'create'"
direction="vertical"
/>
<template v-if="['branchCreate', 'create'].includes(state.curPosition)">
<el-divider class="custom-divider-line" direction="vertical" />
<el-icon class="custom-market-icon hover-icon" @click="close"><Close /></el-icon>
</template>
</el-row>
</el-row>
<el-row class="template-area">
@ -54,7 +86,7 @@
<el-tree
menu
class="custom-market-tree"
:data="state.marketTabs"
:data="categoriesComputed"
:props="state.treeProps"
node-key="label"
default-expand-all
@ -90,6 +122,7 @@
:template="templateItem"
:base-url="state.baseUrl"
:width="state.templateCurWidth"
:cur-position="state.curPosition"
@templateApply="templateApply"
@templatePreview="templatePreview"
/>
@ -122,24 +155,59 @@ 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'
import { imgUrlTrans } from '@/utils/imgUtils'
const { t } = useI18n()
const { wsCache } = useCache()
const route = useRoute()
const previewModel = ref(false)
const title = ref('模版市场')
// full marketPreview createPreview
const previewModel = ref('full')
const emits = defineEmits(['close'])
const close = () => {
emits('close')
}
const title = computed(() => (state.curPosition === 'branch' ? '模板中心' : '使用模版新建'))
const categoriesComputed = computed(() => {
if (state.templateSourceType === 'all') {
return state.marketTabs
} else {
return state.marketTabs.filter(
category => category.source === 'public' || category.source === state.templateSourceType
)
}
})
const curTemplateImg = computed(() => {
if (
state.curTemplate.thumbnail.indexOf('http') > -1 ||
state.curTemplate.thumbnail.indexOf('static-resource') > -1
) {
return imgUrlTrans(state.curTemplate.thumbnail)
} else {
return imgUrlTrans(state.baseUrl + state.curTemplate.thumbnail)
}
})
const outPaddingState = computed(() => {
return state.curPosition === 'branch' && !previewModel.value
return state.curPosition === 'branch' && previewModel.value !== 'marketPreview'
})
const optInit = params => {
state.initReady = false
state.curPosition = params.curPosition
state.templateType = params.templateType
previewModel.value = 'full'
state.pid = params.pid
nextTick(() => {
state.initReady = true
})
}
const state = reactive({
initReady: true,
curPosition: 'branch',
pid: null,
treeProps: {
@ -183,7 +251,7 @@ const state = reactive({
templateSpan: '25%',
previewVisible: false,
templatePreviewId: '',
marketTabs: null,
marketTabs: [],
marketActiveTab: null,
searchText: null,
dvCreateForm: {
@ -203,6 +271,9 @@ const state = reactive({
folderSelectShow: false,
baseUrl: 'https://dataease.io/templates',
currentMarketTemplateShowList: [],
curTemplateShowFilter: [],
curTemplateIndex: 0,
curTemplate: null,
networkStatus: true,
rule: {
name: [
@ -252,7 +323,7 @@ const nodeClick = data => {
initTemplateShow()
}
const closePreview = () => {
previewModel.value = false
previewModel.value = 'full'
}
const initMarketTemplate = async () => {
@ -294,6 +365,20 @@ const normalizer = node => {
}
}
const preOne = () => {
if (state.curTemplateIndex > 0) {
state.curTemplateIndex--
state.curTemplate = state.curTemplateShowFilter[state.curTemplateIndex]
}
}
const nextOne = () => {
if (state.curTemplateIndex < state.curTemplateShowFilter.length - 1) {
state.curTemplateIndex++
state.curTemplate = state.curTemplateShowFilter[state.curTemplateIndex]
}
}
const templateApply = template => {
state.curApplyTemplate = template
state.dvCreateForm.name = template.title
@ -305,7 +390,6 @@ const templateApply = template => {
state.dvCreateForm.newFrom = 'new_inner_template'
state.dvCreateForm.templateId = template.id
}
apply()
}
@ -317,6 +401,7 @@ const apply = () => {
state.loading = true
decompression(state.dvCreateForm)
.then(response => {
state.curApplyTemplate.recentUseTime = Date.now()
state.loading = false
const templateData = response.data
// do create
@ -383,14 +468,19 @@ const templateShow = templateItem => {
}
const templatePreview = previewId => {
state.templatePreviewId = previewId
previewModel.value = true
if (state.curPosition === 'branch') {
//
state.templatePreviewId = previewId
previewModel.value = 'marketPreview'
} else {
state.curTemplateShowFilter = state.currentMarketTemplateShowList.filter(ele => ele.showFlag)
state.curTemplateIndex = state.curTemplateShowFilter.findIndex(temp => temp.id === previewId)
state.curTemplate = state.curTemplateShowFilter[state.curTemplateIndex]
previewModel.value = 'createPreview'
}
}
onMounted(() => {
if (route.params.add === '1') {
title.value = '使用模版新建'
}
previewInit()
initMarketTemplate()
const erd = elementResizeDetectorMaker()
@ -522,7 +612,30 @@ defineExpose({
}
.custom-divider-line {
height: 30px;
height: 16px;
margin-top: 6px;
}
.custom-market-icon {
font-size: 20px;
margin-top: 4px;
cursor: pointer;
}
.custom-back-icon {
font-size: 20px;
cursor: pointer;
margin-right: 8px;
}
.img-main-create {
display: inherit;
justify-content: center;
width: 100%;
background: #0f1114;
overflow-x: auto;
overflow-y: hidden;
height: 100%;
}
</style>

View File

@ -13,6 +13,7 @@ import TemplateBranchItem from '@/views/workbranch/TemplateBranchItem.vue'
import { ElMessage } from 'element-plus-secondary'
import { decompression } from '@/api/visualization/dataVisualization'
import { useCache } from '@/hooks/web/useCache'
import DeResourceCreateOptV2 from '@/views/common/DeResourceCreateOptV2.vue'
const userStore = useUserStoreWithOut()
const interactiveStore = interactiveStoreWithOut()
const permissionStore = usePermissionStoreWithOut()
@ -23,6 +24,7 @@ const busiCountCardList = ref([])
const { wsCache } = useCache()
const { push } = useRouter()
const router = useRouter()
const resourceCreateOpt = ref(null)
const quickCreationList = shallowRef([
{
@ -225,12 +227,11 @@ const toTemplateMarket = () => {
}
const toTemplateMarketAdd = () => {
push({
name: 'template-market',
params: {
add: '1'
}
})
const params = {
curPosition: 'branchCreate',
templateType: 'all'
}
resourceCreateOpt.value.optInit(params)
}
fillCardInfo()
@ -351,6 +352,7 @@ initMarketTemplate()
</div>
<shortcut-table :expand="expandFold === 'expand'" />
</div>
<de-resource-create-opt-v2 ref="resourceCreateOpt"></de-resource-create-opt-v2>
</div>
</template>

View File

@ -1,5 +1,6 @@
package io.dataease.api.template.vo;
import io.dataease.constant.CommonConstants;
import lombok.Data;
import lombok.NoArgsConstructor;
@ -15,9 +16,19 @@ public class MarketMetaDataVO {
private String value;
private String label;
// market 模板中心 manage 模版管理 public 公共
private String source = CommonConstants.TEMPLATE_SOURCE.MARKET;
public MarketMetaDataVO(String value, String label) {
this.label = label;
this.value = value;
this.slug = value;
}
public MarketMetaDataVO(String value, String label,String source) {
this.label = label;
this.value = value;
this.slug = value;
this.source = source;
}
}

View File

@ -79,4 +79,13 @@ public class CommonConstants {
public static final String CHART = "dataset";
}
public static final class TEMPLATE_SOURCE {
//模板市场
public static final String MARKET = "market";
//模板管理
public static final String MANAGE = "manage";
//公共
public static final String PUBLIC = "public";
}
}