mirror of
https://github.com/dataease/dataease.git
synced 2025-02-24 11:32:57 +08:00
commit
03498c9088
@ -1,6 +1,5 @@
|
|||||||
package io.dataease.template.manage;
|
package io.dataease.template.manage;
|
||||||
|
|
||||||
import com.mysql.cj.log.Log;
|
|
||||||
import io.dataease.api.template.dto.TemplateManageDTO;
|
import io.dataease.api.template.dto.TemplateManageDTO;
|
||||||
import io.dataease.api.template.dto.TemplateManageFileDTO;
|
import io.dataease.api.template.dto.TemplateManageFileDTO;
|
||||||
import io.dataease.api.template.dto.TemplateMarketDTO;
|
import io.dataease.api.template.dto.TemplateMarketDTO;
|
||||||
@ -8,7 +7,6 @@ import io.dataease.api.template.dto.TemplateMarketPreviewInfoDTO;
|
|||||||
import io.dataease.api.template.response.*;
|
import io.dataease.api.template.response.*;
|
||||||
import io.dataease.api.template.vo.MarketApplicationSpecVO;
|
import io.dataease.api.template.vo.MarketApplicationSpecVO;
|
||||||
import io.dataease.api.template.vo.MarketMetaDataVO;
|
import io.dataease.api.template.vo.MarketMetaDataVO;
|
||||||
import io.dataease.api.template.vo.TemplateCategoryVO;
|
|
||||||
import io.dataease.constant.CommonConstants;
|
import io.dataease.constant.CommonConstants;
|
||||||
import io.dataease.exception.DEException;
|
import io.dataease.exception.DEException;
|
||||||
import io.dataease.operation.manage.CoreOptRecentManage;
|
import io.dataease.operation.manage.CoreOptRecentManage;
|
||||||
@ -19,11 +17,11 @@ import io.dataease.utils.HttpClientUtil;
|
|||||||
import io.dataease.utils.JsonUtil;
|
import io.dataease.utils.JsonUtil;
|
||||||
import io.dataease.utils.LogUtil;
|
import io.dataease.utils.LogUtil;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,6 +87,7 @@ public class TemplateCenterManage {
|
|||||||
return baseResponseV2Trans(templateQuery(templateParams), searchTemplateFromManage(), templateParams.get("template.url"));
|
return baseResponseV2Trans(templateQuery(templateParams), searchTemplateFromManage(), templateParams.get("template.url"));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error(e);
|
LogUtil.error(e);
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -138,7 +137,9 @@ public class TemplateCenterManage {
|
|||||||
|
|
||||||
private MarketBaseResponse baseResponseV2TransRecommend(MarketTemplateV2BaseResponse v2BaseResponse, String url) {
|
private MarketBaseResponse baseResponseV2TransRecommend(MarketTemplateV2BaseResponse v2BaseResponse, String url) {
|
||||||
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
|
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
|
||||||
Map<String, String> categoriesMap = getCategoriesBaseV2();
|
List<MarketMetaDataVO> categoryVO = getCategoriesV2().stream().filter(node -> !"全部".equalsIgnoreCase(node.getLabel())).collect(Collectors.toList());
|
||||||
|
Map<String, String> categoriesMap = categoryVO.stream()
|
||||||
|
.collect(Collectors.toMap(MarketMetaDataVO::getSlug, MarketMetaDataVO::getLabel));
|
||||||
List<TemplateMarketDTO> contents = new ArrayList<>();
|
List<TemplateMarketDTO> contents = new ArrayList<>();
|
||||||
if (v2BaseResponse != null) {
|
if (v2BaseResponse != null) {
|
||||||
v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> {
|
v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> {
|
||||||
@ -150,25 +151,32 @@ public class TemplateCenterManage {
|
|||||||
}
|
}
|
||||||
// 最近使用排序
|
// 最近使用排序
|
||||||
Collections.sort(contents);
|
Collections.sort(contents);
|
||||||
return new MarketBaseResponse(url, contents);
|
return new MarketBaseResponse(url,categoryVO, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List<TemplateMarketDTO> contents, String url) {
|
private MarketBaseResponse baseResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List<TemplateMarketDTO> contents, String url) {
|
||||||
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
|
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
|
||||||
Map<String, String> categoriesMap = getCategoriesBaseV2();
|
List<MarketMetaDataVO> categoryVO = getCategoriesObject().stream().filter(node -> !"全部".equalsIgnoreCase(node.getLabel())).collect(Collectors.toList());
|
||||||
|
Map<String, String> categoriesMap = categoryVO.stream()
|
||||||
|
.collect(Collectors.toMap(MarketMetaDataVO::getValue, MarketMetaDataVO::getLabel));
|
||||||
|
List<String> activeCategoriesName = new ArrayList<>(Arrays.asList("最近使用","推荐"));
|
||||||
contents.stream().forEach(templateMarketDTO -> {
|
contents.stream().forEach(templateMarketDTO -> {
|
||||||
Long recentUseTime = useTime.get(templateMarketDTO.getId());
|
Long recentUseTime = useTime.get(templateMarketDTO.getId());
|
||||||
templateMarketDTO.setRecentUseTime(recentUseTime == null ? 0 : recentUseTime);
|
templateMarketDTO.setRecentUseTime(recentUseTime == null ? 0 : recentUseTime);
|
||||||
|
activeCategoriesName.add(templateMarketDTO.getMainCategory());
|
||||||
});
|
});
|
||||||
if (v2BaseResponse != null) {
|
if (v2BaseResponse != null) {
|
||||||
v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> {
|
v2BaseResponse.getItems().stream().forEach(marketTemplateV2ItemResult -> {
|
||||||
MarketApplicationSpecVO spec = marketTemplateV2ItemResult.getApplication().getSpec();
|
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()));
|
||||||
|
if(categoriesMap.get(spec.getLabel())!=null){
|
||||||
|
activeCategoriesName.add(categoriesMap.get(spec.getLabel()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 最近使用排序
|
// 最近使用排序
|
||||||
Collections.sort(contents);
|
Collections.sort(contents);
|
||||||
return new MarketBaseResponse(url, contents);
|
return new MarketBaseResponse(url,categoryVO.stream().filter(node->activeCategoriesName.contains(node.getLabel())).collect(Collectors.toList()), contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MarketPreviewBaseResponse basePreviewResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List<TemplateMarketDTO> manageContents, String url) {
|
private MarketPreviewBaseResponse basePreviewResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List<TemplateMarketDTO> manageContents, String url) {
|
||||||
@ -211,7 +219,7 @@ public class TemplateCenterManage {
|
|||||||
|
|
||||||
public List<MarketMetaDataVO> getCategoriesObject() {
|
public List<MarketMetaDataVO> getCategoriesObject() {
|
||||||
List<MarketMetaDataVO> result = getCategoriesV2();
|
List<MarketMetaDataVO> result = getCategoriesV2();
|
||||||
result.add(0, new MarketMetaDataVO("recent", "最近使用", "public"));
|
result.add(0, new MarketMetaDataVO("recent", "最近使用", CommonConstants.TEMPLATE_SOURCE.PUBLIC));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,12 +240,28 @@ public class TemplateCenterManage {
|
|||||||
String resultStr = marketGet(templateParams.get("template.url") + TEMPLATE_META_DATA_URL, null);
|
String resultStr = marketGet(templateParams.get("template.url") + TEMPLATE_META_DATA_URL, null);
|
||||||
MarketMetaDataBaseResponse metaData = JsonUtil.parseObject(resultStr, MarketMetaDataBaseResponse.class);
|
MarketMetaDataBaseResponse metaData = JsonUtil.parseObject(resultStr, MarketMetaDataBaseResponse.class);
|
||||||
allCategories.addAll(metaData.getLabels());
|
allCategories.addAll(metaData.getLabels());
|
||||||
allCategories.add(0, new MarketMetaDataVO("suggest", "推荐"));
|
allCategories.add(0, new MarketMetaDataVO("suggest", "推荐",CommonConstants.TEMPLATE_SOURCE.PUBLIC));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LogUtil.error("模板市场分类获取错误", e);
|
LogUtil.error("模板市场分类获取错误", e);
|
||||||
}
|
}
|
||||||
allCategories.addAll(manageCategoriesTrans);
|
|
||||||
return allCategories;
|
return mergeAndDistinctByLabel(allCategories,manageCategoriesTrans);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<MarketMetaDataVO> mergeAndDistinctByLabel(List<MarketMetaDataVO> list1, List<MarketMetaDataVO> list2) {
|
||||||
|
List<MarketMetaDataVO> mergedList = new ArrayList<>(list1);
|
||||||
|
mergedList.addAll(list2);
|
||||||
|
Map<String, MarketMetaDataVO> marketMetaDataMap = mergedList.stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
MarketMetaDataVO::getLabel,
|
||||||
|
Function.identity(),
|
||||||
|
(existing, replacement) -> {
|
||||||
|
existing.setSource(CommonConstants.TEMPLATE_SOURCE.PUBLIC);
|
||||||
|
return existing;
|
||||||
|
},
|
||||||
|
LinkedHashMap::new
|
||||||
|
));
|
||||||
|
return new ArrayList<>(marketMetaDataMap.values());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,8 +84,10 @@
|
|||||||
<el-row class="template-area">
|
<el-row class="template-area">
|
||||||
<div class="template-left">
|
<div class="template-left">
|
||||||
<el-tree
|
<el-tree
|
||||||
|
v-if="state.treeShow"
|
||||||
menu
|
menu
|
||||||
class="custom-market-tree"
|
class="custom-market-tree"
|
||||||
|
v-model="state.marketActiveTab"
|
||||||
:data="categoriesComputed"
|
:data="categoriesComputed"
|
||||||
:props="state.treeProps"
|
:props="state.treeProps"
|
||||||
node-key="label"
|
node-key="label"
|
||||||
@ -100,33 +102,77 @@
|
|||||||
id="template-show-area"
|
id="template-show-area"
|
||||||
class="template-right"
|
class="template-right"
|
||||||
>
|
>
|
||||||
<el-col class="main-head">
|
<template v-if="state.marketActiveTab !== '推荐'">
|
||||||
<div class="custom-split-line"></div>
|
<el-col class="main-head">
|
||||||
<span v-show="!state.searchText" class="custom-category">{{
|
<div class="custom-split-line"></div>
|
||||||
state.marketActiveTab
|
<span v-show="!state.searchText" class="custom-category">{{
|
||||||
}}</span>
|
state.marketActiveTab
|
||||||
<span v-show="state.searchText" class="custom-search">{{ state.marketActiveTab }}</span>
|
}}</span>
|
||||||
<span v-if="state.searchText" class="custom-search-result"
|
<span v-show="state.searchText" class="custom-search">{{
|
||||||
>的搜索结果是{{ searchResultCount }}个</span
|
state.marketActiveTab
|
||||||
|
}}</span>
|
||||||
|
<span v-if="state.searchText" class="custom-search-result"
|
||||||
|
>的搜索结果是{{ searchResultCount }}个</span
|
||||||
|
>
|
||||||
|
</el-col>
|
||||||
|
<el-col
|
||||||
|
v-for="templateItem in state.currentMarketTemplateShowList"
|
||||||
|
v-show="templateItem.showFlag"
|
||||||
|
:key="templateItem.id"
|
||||||
|
style="float: left; padding: 24px 12px 0; text-align: center; flex: 0"
|
||||||
|
:style="{ width: state.templateSpan }"
|
||||||
>
|
>
|
||||||
</el-col>
|
<template-market-v2-item
|
||||||
<el-col
|
:key="'outer-' + templateItem.id"
|
||||||
v-for="templateItem in state.currentMarketTemplateShowList"
|
:template="templateItem"
|
||||||
v-show="templateItem.showFlag"
|
:base-url="state.baseUrl"
|
||||||
:key="templateItem.id"
|
:width="state.templateCurWidth"
|
||||||
style="float: left; padding: 24px 12px 0; text-align: center; flex: 0"
|
:cur-position="state.curPosition"
|
||||||
:style="{ width: state.templateSpan }"
|
@templateApply="templateApply"
|
||||||
>
|
@templatePreview="templatePreview"
|
||||||
<template-market-v2-item
|
/>
|
||||||
:key="'outer-' + templateItem.id"
|
</el-col>
|
||||||
:template="templateItem"
|
</template>
|
||||||
:base-url="state.baseUrl"
|
|
||||||
:width="state.templateCurWidth"
|
<template v-if="state.marketActiveTab === '推荐'">
|
||||||
:cur-position="state.curPosition"
|
<el-row
|
||||||
@templateApply="templateApply"
|
:key="'full-' + categoryItem.label"
|
||||||
@templatePreview="templatePreview"
|
style="display: inline; margin-bottom: 16px"
|
||||||
/>
|
v-for="categoryItem in categoriesComputed.filter(
|
||||||
</el-col>
|
item => !['最近使用', '推荐'].includes(item.label)
|
||||||
|
)"
|
||||||
|
>
|
||||||
|
<el-col class="main-head">
|
||||||
|
<div class="custom-split-line"></div>
|
||||||
|
<span v-show="!state.searchText" class="custom-category">{{
|
||||||
|
categoryItem.label
|
||||||
|
}}</span>
|
||||||
|
<span v-show="state.searchText" class="custom-search">{{
|
||||||
|
categoryItem.label
|
||||||
|
}}</span>
|
||||||
|
<span v-if="state.searchText" class="custom-search-result"
|
||||||
|
>的搜索结果是{{ fullTemplateShowList(categoryItem.label).length }}个</span
|
||||||
|
>
|
||||||
|
</el-col>
|
||||||
|
<el-col
|
||||||
|
v-for="templateItem in fullTemplateShowList(categoryItem.label)"
|
||||||
|
v-show="templateItem.showFlag"
|
||||||
|
:key="templateItem.id + categoryItem.label"
|
||||||
|
style="float: left; padding: 24px 12px 0; text-align: center; flex: 0"
|
||||||
|
:style="{ width: state.templateSpan }"
|
||||||
|
>
|
||||||
|
<template-market-v2-item
|
||||||
|
:key="'outer-' + templateItem.id"
|
||||||
|
:template="templateItem"
|
||||||
|
:base-url="state.baseUrl"
|
||||||
|
:width="state.templateCurWidth"
|
||||||
|
:cur-position="state.curPosition"
|
||||||
|
@templateApply="templateApply"
|
||||||
|
@templatePreview="templatePreview"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<el-row v-show="state.networkStatus && !state.hasResult" class="template-empty">
|
<el-row v-show="state.networkStatus && !state.hasResult" class="template-empty">
|
||||||
<div style="text-align: center">
|
<div style="text-align: center">
|
||||||
@ -216,6 +262,7 @@ const state = reactive({
|
|||||||
},
|
},
|
||||||
templateType: 'all',
|
templateType: 'all',
|
||||||
templateSourceType: 'all',
|
templateSourceType: 'all',
|
||||||
|
treeShow: true,
|
||||||
templateSourceOptions: [
|
templateSourceOptions: [
|
||||||
{
|
{
|
||||||
value: 'all',
|
value: 'all',
|
||||||
@ -310,7 +357,12 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => state.templateSourceType,
|
() => state.templateSourceType,
|
||||||
value => {
|
value => {
|
||||||
|
state.treeShow = false
|
||||||
initTemplateShow()
|
initTemplateShow()
|
||||||
|
nextTick(() => {
|
||||||
|
state.treeShow = true
|
||||||
|
initStyle()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -331,13 +383,7 @@ const initMarketTemplate = async () => {
|
|||||||
.then(rsp => {
|
.then(rsp => {
|
||||||
state.baseUrl = rsp.data.baseUrl
|
state.baseUrl = rsp.data.baseUrl
|
||||||
state.currentMarketTemplateShowList = rsp.data.contents
|
state.currentMarketTemplateShowList = rsp.data.contents
|
||||||
})
|
state.marketTabs = rsp.data.categories
|
||||||
.catch(() => {
|
|
||||||
state.networkStatus = false
|
|
||||||
})
|
|
||||||
getCategoriesObject()
|
|
||||||
.then(rsp => {
|
|
||||||
state.marketTabs = rsp.data
|
|
||||||
state.marketActiveTab = state.marketTabs[0].label
|
state.marketActiveTab = state.marketTabs[0].label
|
||||||
initStyle()
|
initStyle()
|
||||||
initTemplateShow()
|
initTemplateShow()
|
||||||
@ -419,10 +465,10 @@ const apply = () => {
|
|||||||
const handleClick = item => {
|
const handleClick = item => {
|
||||||
// do handleClick
|
// do handleClick
|
||||||
}
|
}
|
||||||
const initTemplateShow = () => {
|
const initTemplateShow = (activeTab = state.marketActiveTab) => {
|
||||||
let tempHasResult = false
|
let tempHasResult = false
|
||||||
state.currentMarketTemplateShowList.forEach(template => {
|
state.currentMarketTemplateShowList.forEach(template => {
|
||||||
template.showFlag = templateShow(template)
|
template.showFlag = templateShow(template, activeTab)
|
||||||
if (template.showFlag) {
|
if (template.showFlag) {
|
||||||
tempHasResult = true
|
tempHasResult = true
|
||||||
}
|
}
|
||||||
@ -432,22 +478,29 @@ const initTemplateShow = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const templateShow = templateItem => {
|
const fullTemplateShowList = curTab => {
|
||||||
|
state.currentMarketTemplateShowList.forEach(template => {
|
||||||
|
template.showFlag = templateShow(template, curTab)
|
||||||
|
})
|
||||||
|
return state.currentMarketTemplateShowList.filter(ele => ele.showFlag)
|
||||||
|
}
|
||||||
|
|
||||||
|
const templateShow = (templateItem, activeTab) => {
|
||||||
let categoryMarch = false
|
let categoryMarch = false
|
||||||
let searchMarch = false
|
let searchMarch = false
|
||||||
let templateTypeMarch = false
|
let templateTypeMarch = false
|
||||||
let templateSourceTypeMarch = false
|
let templateSourceTypeMarch = false
|
||||||
if (state.marketActiveTab === '最近使用') {
|
if (activeTab === '最近使用') {
|
||||||
if (templateItem.recentUseTime) {
|
if (templateItem.recentUseTime) {
|
||||||
categoryMarch = true
|
categoryMarch = true
|
||||||
}
|
}
|
||||||
} else if (state.marketActiveTab === '推荐') {
|
} else if (activeTab === '推荐') {
|
||||||
if (templateItem.suggest === 'Y') {
|
if (templateItem.suggest === 'Y') {
|
||||||
categoryMarch = true
|
categoryMarch = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
templateItem.categories.forEach(category => {
|
templateItem.categories.forEach(category => {
|
||||||
if (category.name === state.marketActiveTab) {
|
if (category.name === activeTab) {
|
||||||
categoryMarch = true
|
categoryMarch = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -560,7 +613,7 @@ defineExpose({
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
background: rgba(239, 240, 241, 1);
|
background: rgba(239, 240, 241, 1);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 16px 12px;
|
padding: 0 12px 16px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.template-empty {
|
.template-empty {
|
||||||
@ -580,6 +633,7 @@ defineExpose({
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
float: left;
|
float: left;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
margin-top: 16px;
|
||||||
display: inline;
|
display: inline;
|
||||||
.custom-split-line {
|
.custom-split-line {
|
||||||
margin: 4px 8px 0 12px;
|
margin: 4px 8px 0 12px;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package io.dataease.api.template.response;
|
package io.dataease.api.template.response;
|
||||||
|
|
||||||
import io.dataease.api.template.dto.TemplateMarketDTO;
|
import io.dataease.api.template.dto.TemplateMarketDTO;
|
||||||
|
import io.dataease.api.template.vo.MarketMetaDataVO;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -13,16 +14,16 @@ import java.util.List;
|
|||||||
public class MarketBaseResponse {
|
public class MarketBaseResponse {
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
|
|
||||||
|
List<MarketMetaDataVO> categories;
|
||||||
|
|
||||||
private List<TemplateMarketDTO> contents;
|
private List<TemplateMarketDTO> contents;
|
||||||
|
|
||||||
public MarketBaseResponse() {
|
public MarketBaseResponse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MarketBaseResponse(String baseUrl, List<TemplateMarketDTO> contents) {
|
public MarketBaseResponse(String baseUrl, List<MarketMetaDataVO> categories, List<TemplateMarketDTO> contents) {
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
|
this.categories = categories;
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user