forked from github/dataease
Merge pull request #2644 from dataease/pr@dev@feat_panel-template-market
feat(仪表板) :支持在DataEase中查看模板市场模板并且直接应用模板创建仪表板
This commit is contained in:
commit
2af01a0667
@ -41,6 +41,9 @@ public class PanelConstants {
|
||||
// 外部模板新建
|
||||
public static final String NEW_OUTER_TEMPLATE = "new_outer_template";
|
||||
|
||||
// 模板市场新建
|
||||
public static final String NEW_MARKET_TEMPLATE = "new_market_template";
|
||||
|
||||
}
|
||||
|
||||
//仪表板类型
|
||||
|
@ -111,7 +111,9 @@ public interface ParamConstants {
|
||||
FRONT_TIME_OUT("basic.frontTimeOut"),
|
||||
MSG_TIME_OUT("basic.msgTimeOut"),
|
||||
DEFAULT_LOGIN_TYPE("basic.loginType"),
|
||||
OPEN_HOME_PAGE("ui.openHomePage");
|
||||
OPEN_HOME_PAGE("ui.openHomePage"),
|
||||
TEMPLATE_MARKET_ULR("basic.templateMarketUlr"),
|
||||
TEMPLATE_ACCESS_KEY("basic.templateAccessKey");
|
||||
|
||||
private String value;
|
||||
|
||||
|
@ -65,6 +65,12 @@ public class HttpClientUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String url = "http://123.56.8.132:8090/upload/2022/04/%E9%99%88%E7%BA%AA%E5%85%89-%E6%B5%B7%E9%80%9A%E8%AF%81%E5%8A%B5%E6%A1%8C%E9%9D%A2%E4%BA%91%E5%A4%A7%E5%B1%8F-TEMPLATE.DET";
|
||||
|
||||
String info = get(url,null);
|
||||
System.out.println("=="+info);
|
||||
}
|
||||
/**
|
||||
* Get http请求
|
||||
*
|
||||
|
@ -27,6 +27,8 @@ public class PanelGroupRequest extends PanelGroupDTO {
|
||||
private String templateId;
|
||||
@ApiModelProperty("静态文件")
|
||||
private String staticResource;
|
||||
@ApiModelProperty("模板链接")
|
||||
private String templateUrl;
|
||||
|
||||
public PanelGroupRequest() {
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package io.dataease.controller.request.templateMarket;
|
||||
|
||||
import io.dataease.dto.templateMarket.TemplateMarketDTO;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/15
|
||||
* Description:
|
||||
*/
|
||||
public class TemplateMarketSearchRequest extends TemplateMarketDTO {
|
||||
|
||||
}
|
@ -16,5 +16,9 @@ public class BasicInfo implements Serializable {
|
||||
private String openHomePage;
|
||||
@ApiModelProperty("默认登录方式")
|
||||
private Integer loginType = 0;
|
||||
@ApiModelProperty("模板市场链接")
|
||||
private String templateMarketUlr;
|
||||
@ApiModelProperty("模板市场AccessKey")
|
||||
private String templateAccessKey;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package io.dataease.controller.templateMarket;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.dataease.controller.request.templateMarket.TemplateMarketSearchRequest;
|
||||
import io.dataease.dto.templateMarket.MarketBaseResponse;
|
||||
import io.dataease.dto.templateMarket.TemplateMarketDTO;
|
||||
import io.dataease.service.templateMarket.TemplateMarketService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/15
|
||||
* Description:
|
||||
*/
|
||||
@RestController
|
||||
@Api(tags = "系统:模板市场")
|
||||
@ApiSupport(order = 220)
|
||||
@RequestMapping("/template/market")
|
||||
public class TemplateMarketController {
|
||||
|
||||
@Resource
|
||||
private TemplateMarketService marketService;
|
||||
|
||||
|
||||
@ApiOperation("查询模板")
|
||||
@PostMapping("/search")
|
||||
private MarketBaseResponse searchTemplate(@RequestBody TemplateMarketSearchRequest request){
|
||||
return marketService.searchTemplate(request);
|
||||
}
|
||||
|
||||
@ApiOperation("查询分类")
|
||||
@GetMapping("/categories")
|
||||
private List<String> categories(){
|
||||
return marketService.getCategories();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package io.dataease.dto.panel;
|
||||
|
||||
import io.dataease.plugins.common.base.domain.PanelTemplateWithBLOBs;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/14
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class PanelTemplateFileDTO extends PanelTemplateWithBLOBs {
|
||||
|
||||
private String panelStyle;
|
||||
|
||||
private String panelData;
|
||||
|
||||
private String staticResource;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package io.dataease.dto.templateMarket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/15
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class MarketBaseResponse {
|
||||
private String baseUrl;
|
||||
|
||||
private List<TemplateMarketDTO> contents;
|
||||
|
||||
public MarketBaseResponse() {
|
||||
}
|
||||
|
||||
public MarketBaseResponse(String baseUrl, List<TemplateMarketDTO> contents) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.contents = contents;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package io.dataease.dto.templateMarket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/15
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class MarketCategory {
|
||||
private String id;
|
||||
private String name;
|
||||
private String slug;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package io.dataease.dto.templateMarket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/15
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class MarketMetas {
|
||||
private String theme_repo;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package io.dataease.dto.templateMarket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/18
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class TemplateCategory {
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String slug;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package io.dataease.dto.templateMarket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/15
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class TemplateMarketDTO {
|
||||
private String id;
|
||||
private String title;
|
||||
private String status;
|
||||
private String slug;
|
||||
private String editorType;
|
||||
private String summary;
|
||||
private String thumbnail;
|
||||
private Boolean showFlag = true;
|
||||
private List<MarketCategory> categories;
|
||||
private MarketMetas metas;
|
||||
}
|
@ -3,14 +3,12 @@ package io.dataease.service.panel;
|
||||
import com.google.gson.Gson;
|
||||
import io.dataease.auth.annotation.DeCleaner;
|
||||
import io.dataease.commons.constants.*;
|
||||
import io.dataease.commons.utils.AuthUtils;
|
||||
import io.dataease.commons.utils.DeLogUtils;
|
||||
import io.dataease.commons.utils.LogUtil;
|
||||
import io.dataease.commons.utils.TreeUtils;
|
||||
import io.dataease.commons.utils.*;
|
||||
import io.dataease.controller.request.authModel.VAuthModelRequest;
|
||||
import io.dataease.controller.request.dataset.DataSetTableRequest;
|
||||
import io.dataease.controller.request.panel.PanelGroupBaseInfoRequest;
|
||||
import io.dataease.controller.request.panel.PanelGroupRequest;
|
||||
import io.dataease.controller.request.panel.PanelTemplateRequest;
|
||||
import io.dataease.controller.request.panel.PanelViewDetailsRequest;
|
||||
import io.dataease.dto.PanelGroupExtendDataDTO;
|
||||
import io.dataease.dto.SysLogDTO;
|
||||
@ -18,6 +16,7 @@ import io.dataease.dto.authModel.VAuthModelDTO;
|
||||
import io.dataease.dto.chart.ChartViewDTO;
|
||||
import io.dataease.dto.dataset.DataSetTableDTO;
|
||||
import io.dataease.dto.panel.PanelGroupDTO;
|
||||
import io.dataease.dto.panel.PanelTemplateFileDTO;
|
||||
import io.dataease.dto.panel.po.PanelViewInsertDTO;
|
||||
import io.dataease.exception.DataEaseException;
|
||||
import io.dataease.ext.*;
|
||||
@ -389,6 +388,16 @@ public class PanelGroupService {
|
||||
dynamicData = request.getDynamicData();
|
||||
staticResource = request.getStaticResource();
|
||||
mobileLayout = panelViewService.havaMobileLayout(templateData);
|
||||
} else if (PanelConstants.NEW_PANEL_FROM.NEW_MARKET_TEMPLATE.equals(newFrom)){
|
||||
PanelTemplateFileDTO templateFileInfo = getTemplateFromMarket(request.getTemplateUrl());
|
||||
if(templateFileInfo == null){
|
||||
DataEaseException.throwException("Can't find the template's info from market,please check");
|
||||
}
|
||||
templateStyle = templateFileInfo.getPanelStyle();
|
||||
templateData = templateFileInfo.getPanelData();
|
||||
dynamicData = templateFileInfo.getDynamicData();
|
||||
staticResource = templateFileInfo.getStaticResource();
|
||||
mobileLayout = panelViewService.havaMobileLayout(templateData);
|
||||
}
|
||||
Map<String, String> dynamicDataMap = gson.fromJson(dynamicData, Map.class);
|
||||
List<PanelViewInsertDTO> panelViews = new ArrayList<>();
|
||||
@ -583,4 +592,15 @@ public class PanelGroupService {
|
||||
panelGroup.setStatus(request.getStatus());
|
||||
panelGroupMapper.updateByPrimaryKeySelective(panelGroup);
|
||||
}
|
||||
|
||||
|
||||
public PanelTemplateFileDTO getTemplateFromMarket(String templateUrl){
|
||||
if(StringUtils.isNotEmpty(templateUrl)){
|
||||
Gson gson = new Gson();
|
||||
String templateInfo = HttpClientUtil.get(templateUrl,null);
|
||||
return gson.fromJson(templateInfo, PanelTemplateFileDTO.class);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import io.dataease.commons.utils.BeanUtils;
|
||||
import io.dataease.commons.utils.EncryptUtils;
|
||||
import io.dataease.controller.sys.response.BasicInfo;
|
||||
import io.dataease.dto.SystemParameterDTO;
|
||||
import io.dataease.exception.DataEaseException;
|
||||
import io.dataease.plugins.common.base.domain.FileMetadata;
|
||||
import io.dataease.plugins.common.base.domain.SystemParameter;
|
||||
import io.dataease.plugins.common.base.domain.SystemParameterExample;
|
||||
@ -69,6 +70,13 @@ public class SystemParameterService {
|
||||
boolean open = StringUtils.equals("true", param.getParamValue());
|
||||
result.setOpenHomePage(open ? "true" : "false");
|
||||
}
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.TEMPLATE_MARKET_ULR.getValue())) {
|
||||
result.setTemplateMarketUlr(param.getParamValue());
|
||||
}
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.TEMPLATE_ACCESS_KEY.getValue())) {
|
||||
result.setTemplateAccessKey(param.getParamValue());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -270,5 +278,23 @@ public class SystemParameterService {
|
||||
}
|
||||
|
||||
}
|
||||
public BasicInfo templateMarketInfo(){
|
||||
BasicInfo basicInfo = new BasicInfo();
|
||||
List<SystemParameter> result = this.getParamList("basic.template");
|
||||
if(CollectionUtils.isNotEmpty(result)){
|
||||
result.stream().forEach(param -> {
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.TEMPLATE_MARKET_ULR.getValue())) {
|
||||
basicInfo.setTemplateMarketUlr(param.getParamValue());
|
||||
}
|
||||
if (StringUtils.equals(param.getParamKey(), ParamConstants.BASIC.TEMPLATE_ACCESS_KEY.getValue())) {
|
||||
basicInfo.setTemplateAccessKey(param.getParamValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
if(StringUtils.isEmpty(basicInfo.getTemplateMarketUlr())|| StringUtils.isEmpty(basicInfo.getTemplateAccessKey())){
|
||||
DataEaseException.throwException("Please check market setting info");
|
||||
}
|
||||
return basicInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,85 @@
|
||||
package io.dataease.service.templateMarket;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.gson.Gson;
|
||||
import io.dataease.commons.utils.HttpClientConfig;
|
||||
import io.dataease.commons.utils.HttpClientUtil;
|
||||
import io.dataease.controller.request.templateMarket.TemplateMarketSearchRequest;
|
||||
import io.dataease.controller.sys.response.BasicInfo;
|
||||
import io.dataease.dto.panel.PanelTemplateFileDTO;
|
||||
import io.dataease.dto.templateMarket.MarketBaseResponse;
|
||||
import io.dataease.dto.templateMarket.TemplateCategory;
|
||||
import io.dataease.dto.templateMarket.TemplateMarketDTO;
|
||||
import io.dataease.exception.DataEaseException;
|
||||
import io.dataease.service.system.SystemParameterService;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Author: wangjiahao
|
||||
* Date: 2022/7/14
|
||||
* Description: ${userName}
|
||||
*/
|
||||
@Service
|
||||
public class TemplateMarketService {
|
||||
|
||||
private final static String POSTS_API="/api/content/posts?page=0&size=2000";
|
||||
private final static String CATEGORIES_API="/api/content/categories";
|
||||
|
||||
@Resource
|
||||
private SystemParameterService systemParameterService;
|
||||
|
||||
/**
|
||||
* @Description Get template file from template market
|
||||
* @param templateUrl template url
|
||||
*/
|
||||
public PanelTemplateFileDTO getTemplateFromMarket(String templateUrl){
|
||||
if(StringUtils.isNotEmpty(templateUrl)){
|
||||
String sufUrl = systemParameterService.templateMarketInfo().getTemplateMarketUlr();
|
||||
Gson gson = new Gson();
|
||||
String templateInfo = HttpClientUtil.get(sufUrl+templateUrl,null);
|
||||
return gson.fromJson(templateInfo, PanelTemplateFileDTO.class);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description Get info from template market content api
|
||||
* @param url content api url
|
||||
*/
|
||||
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{
|
||||
BasicInfo basicInfo = systemParameterService.templateMarketInfo();
|
||||
String result = marketGet(basicInfo.getTemplateMarketUlr()+POSTS_API,basicInfo.getTemplateAccessKey());
|
||||
List<TemplateMarketDTO> postsResult = JSONObject.parseObject(result).getJSONObject("data").getJSONArray("content").toJavaList(TemplateMarketDTO.class);
|
||||
return new MarketBaseResponse(basicInfo.getTemplateMarketUlr(),postsResult);
|
||||
}catch (Exception e){
|
||||
DataEaseException.throwException(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<String> getCategories(){
|
||||
BasicInfo basicInfo = systemParameterService.templateMarketInfo();
|
||||
String resultStr = marketGet(basicInfo.getTemplateMarketUlr()+CATEGORIES_API,basicInfo.getTemplateAccessKey());
|
||||
List<TemplateCategory> categories = JSONObject.parseObject(resultStr).getJSONArray("data").toJavaList(TemplateCategory.class);
|
||||
if(CollectionUtils.isNotEmpty(categories)){
|
||||
return categories.stream().map(TemplateCategory :: getName).collect(Collectors.toList());
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -36,4 +36,8 @@ ADD COLUMN `phone_prefix` varchar(255) NULL COMMENT '手机号前缀' AFTER `sub
|
||||
INSERT INTO `my_plugin` (`name`, `store`, `free`, `cost`, `category`, `descript`, `version`, `creator`, `load_mybatis`,
|
||||
`install_time`, `module_name`, `ds_type`)
|
||||
VALUES ('Mongo 数据源插件', 'default', '0', '0', 'datasource', 'Mongo 数据源插件', '1.0-SNAPSHOT', 'DATAEASE', '0',
|
||||
'1650765903630', 'mongo-backend', 'mongobi');
|
||||
'1650765903630', 'mongo-backend', 'mongobi');
|
||||
|
||||
|
||||
INSERT INTO `system_parameter` (`param_key`, `param_value`, `type`, `sort`) VALUES ('basic.templateAccessKey', 'dataease', 'text', NULL);
|
||||
INSERT INTO `system_parameter` (`param_key`, `param_value`, `type`, `sort`) VALUES ('basic.templateMarketUlr', 'https://dataease.io/templates', 'text', 4);
|
||||
|
20
frontend/src/api/templateMarket/index.js
Normal file
20
frontend/src/api/templateMarket/index.js
Normal file
@ -0,0 +1,20 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function searchMarket(data) {
|
||||
return request({
|
||||
url: '/template/market/search',
|
||||
method: 'post',
|
||||
loading: true,
|
||||
hideMsg: true,
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function getCategories() {
|
||||
return request({
|
||||
url: '/template/market/categories',
|
||||
method: 'get',
|
||||
hideMsg: true,
|
||||
loading: false
|
||||
})
|
||||
}
|
@ -26,6 +26,7 @@
|
||||
|
||||
<div v-show="!editControlButton" class="toolbar">
|
||||
<div class="panel-info-area">
|
||||
<!--back to panelList-->
|
||||
<svg-icon
|
||||
icon-class="icon_left_outlined"
|
||||
class="toolbar-icon-active icon20 margin-left20"
|
||||
|
5
frontend/src/icons/svg/none_select.svg
Normal file
5
frontend/src/icons/svg/none_select.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="125" height="125" viewBox="0 0 125 125" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="125" height="125" rx="62.5" fill="#EFF0F1"/>
|
||||
<path d="M68.6525 91.3927C67.7195 93.8379 64.2695 93.8652 63.2978 91.4358L47.0339 50.7747C46.0952 48.4287 48.424 46.0985 50.7714 47.0372L91.4296 63.3011C93.8547 64.2714 93.8346 67.7113 91.398 68.6529L74.8998 75.0253L68.6525 91.3942V91.3927ZM65.904 82.4702L69.9836 71.7809C70.1273 71.4047 70.3485 71.0629 70.6328 70.7776C70.9171 70.4923 71.2581 70.27 71.6338 70.1249L82.5042 65.926L54.864 54.8702L65.904 82.4702Z" fill="#BBBFC4"/>
|
||||
<path d="M48.125 32.3125C56.7026 32.3125 63.6859 39.1421 63.9303 47.6607L57.7534 45.1896C57.2462 43.5293 56.3182 42.0284 55.0594 40.8329C53.8006 39.6373 52.2538 38.7878 50.5696 38.3669C48.8853 37.9459 47.1208 37.9679 45.4476 38.4307C43.7743 38.8934 42.2493 39.7812 41.0206 41.0077C39.792 42.2343 38.9016 43.7578 38.436 45.4302C37.9703 47.1027 37.9453 48.8672 38.3634 50.5521C38.7814 52.2371 39.6283 53.7853 40.8217 55.0461C42.0151 56.307 43.5143 57.2376 45.1738 57.7476L47.6463 63.9303C39.1334 63.6773 32.3125 56.6982 32.3125 48.125C32.3125 39.3922 39.3922 32.3125 48.125 32.3125Z" fill="#BBBFC4"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -1495,6 +1495,11 @@ export default {
|
||||
sure_bt: 'Confirm'
|
||||
},
|
||||
panel: {
|
||||
market_network_tips: 'View template Market template requires server and template Market( https://dataease.io/templates ), please check the network... ',
|
||||
enter_name_tips: 'Please enter the name of the panel',
|
||||
name: 'Name',
|
||||
apply_template: 'Apply Template',
|
||||
enter_template_name_tips: 'Please enter the template name...',
|
||||
pic_adaptation: 'Adaptation',
|
||||
pic_equiratio: 'Equiratio',
|
||||
pic_original: 'Original',
|
||||
|
@ -1496,6 +1496,11 @@ export default {
|
||||
sure_bt: '確定'
|
||||
},
|
||||
panel: {
|
||||
market_network_tips: '查看模板市场模板需要服务器与模板市场(https://dataease.io/templates)联通,请检查网络...',
|
||||
enter_name_tips: '请输入仪表板名称',
|
||||
name: '名称',
|
||||
apply_template: '应用模板',
|
||||
enter_template_name_tips: '请输入模板名称...',
|
||||
pic_adaptation: '适应组件',
|
||||
pic_equiratio: '等比适应',
|
||||
pic_original: '原始尺寸',
|
||||
|
@ -1504,6 +1504,11 @@ export default {
|
||||
sure_bt: '确定'
|
||||
},
|
||||
panel: {
|
||||
market_network_tips: '查看模板市场模板需要服务器与模板市场(https://dataease.io/templates)联通,请检查网络...',
|
||||
enter_name_tips: '请输入仪表板名称',
|
||||
name: '名称',
|
||||
apply_template: '应用模板',
|
||||
enter_template_name_tips: '请输入模板名称...',
|
||||
pic_adaptation: '适应组件',
|
||||
pic_equiratio: '等比适应',
|
||||
pic_original: '原始尺寸',
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
<div class="right-menu" style="color: var(--TopTextColor)">
|
||||
<template>
|
||||
|
||||
<span class="hover-effect right-menu-item template-market-item" @click="changeTemplateMarketShow(true)">模板市场</span>
|
||||
<notification class="right-menu-item hover-effect" />
|
||||
<lang-select class="right-menu-item hover-effect" />
|
||||
<div style="height: 100%;padding: 0 8px;" class="right-menu-item hover-effect">
|
||||
@ -43,7 +43,6 @@
|
||||
trigger="click"
|
||||
>
|
||||
<div class="el-dropdown-link" style="display: flex;color: var(--TopTextColor);font-size: 14px; width:100%;">
|
||||
|
||||
<span style="max-width:80px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;">{{ name }}</span>
|
||||
<span><i class="el-icon-arrow-down el-icon--right" /></span>
|
||||
</div>
|
||||
@ -70,6 +69,16 @@
|
||||
</el-dropdown>
|
||||
</div>
|
||||
|
||||
<!--模板市场全屏显示框-->
|
||||
<el-dialog
|
||||
:visible="templateMarketShow"
|
||||
:show-close="false"
|
||||
class="dialog-css"
|
||||
:fullscreen="true"
|
||||
append-to-body="true"
|
||||
>
|
||||
<template-market v-if="templateMarketShow" style="text-align: center" @closeDialog="changeTemplateMarketShow(false)" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
@ -95,9 +104,11 @@ import {
|
||||
import {
|
||||
initTheme
|
||||
} from '@/utils/ThemeUtil'
|
||||
import TemplateMarket from '@/views/panel/templateMarket'
|
||||
export default {
|
||||
name: 'Topbar',
|
||||
components: {
|
||||
TemplateMarket,
|
||||
AppLink,
|
||||
Notification,
|
||||
LangSelect
|
||||
@ -114,7 +125,8 @@ export default {
|
||||
uiInfo: null,
|
||||
logoUrl: null,
|
||||
axiosFinished: false,
|
||||
isPluginLoaded: false
|
||||
isPluginLoaded: false,
|
||||
templateMarketShow: false
|
||||
}
|
||||
},
|
||||
|
||||
@ -357,6 +369,9 @@ export default {
|
||||
},
|
||||
setTopTextActiveInfo(val) {
|
||||
this.loadUiInfo()
|
||||
},
|
||||
changeTemplateMarketShow(isShow) {
|
||||
this.templateMarketShow = isShow
|
||||
}
|
||||
|
||||
}
|
||||
@ -387,5 +402,15 @@ export default {
|
||||
background-color: var(--MainBG);
|
||||
|
||||
}
|
||||
.template-market-item{
|
||||
display: flex;
|
||||
color: var(--MenuActiveBG, #409EFF);
|
||||
font-size: 14px!important;
|
||||
line-height: 38px!important;
|
||||
}
|
||||
|
||||
.dialog-css ::v-deep .el-dialog__header{
|
||||
display: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -354,7 +354,7 @@ export default {
|
||||
watch: {
|
||||
// 切换展示页面后 重新点击一下当前节点
|
||||
'$store.state.panel.mainActiveName': function(newVal, oldVal) {
|
||||
if (newVal === 'PanelMain' && this.lastActiveNode && this.lastActiveNodeData) {
|
||||
if (newVal === 'PanelMain' && this.lastActiveNodeData) {
|
||||
this.activeNodeAndClickOnly(this.lastActiveNodeData)
|
||||
}
|
||||
},
|
||||
@ -369,14 +369,25 @@ export default {
|
||||
this.$refs.panel_list_tree.filter(this.filterText)
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
bus.$off('newPanelFromMarket', this.newPanelFromMarket)
|
||||
},
|
||||
mounted() {
|
||||
this.$store.commit('setComponentData', [])
|
||||
this.$store.commit('setCanvasStyle', DEFAULT_COMMON_CANVAS_STYLE_STRING)
|
||||
this.defaultTree(true)
|
||||
this.tree(true)
|
||||
this.initCache()
|
||||
bus.$on('newPanelFromMarket', this.newPanelFromMarket)
|
||||
},
|
||||
methods: {
|
||||
newPanelFromMarket(panelInfo) {
|
||||
if (panelInfo) {
|
||||
this.defaultTree()
|
||||
this.tree()
|
||||
this.edit(panelInfo, null)
|
||||
}
|
||||
},
|
||||
initCache() {
|
||||
// 初始化时提前加载视图和数据集的缓存
|
||||
this.initLocalStorage.forEach(item => {
|
||||
|
@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<div class="testcase-template">
|
||||
<el-row class="template-img" :style="classBackground" />
|
||||
<el-row class="bottom-area">
|
||||
<el-row>
|
||||
<span class="demonstration">{{ template.title }}</span>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row class="template-button">
|
||||
<el-button size="mini" type="primary" icon="el-icon-view" @click="templatePreview">预览</el-button>
|
||||
<el-button size="mini" type="success" icon="el-icon-files" @click="apply">应用</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TemplateMarketItem',
|
||||
props: {
|
||||
template: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
baseUrl: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
classBackground() {
|
||||
return {
|
||||
background: `url(${this.thumbnailUrl}) no-repeat`,
|
||||
'background-size': `100% 100%`
|
||||
}
|
||||
},
|
||||
thumbnailUrl() {
|
||||
if (this.template.thumbnail.indexOf('http') > -1) {
|
||||
return this.template.thumbnail
|
||||
} else {
|
||||
return this.baseUrl + this.template.thumbnail
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
handleDelete() {
|
||||
|
||||
},
|
||||
apply() {
|
||||
this.$emit('templateApply', this.template)
|
||||
},
|
||||
templatePreview() {
|
||||
this.$emit('templatePreview', this.thumbnailUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.testcase-template {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin: 10px 30px;
|
||||
box-shadow: 0 0 2px 0 rgba(31,31,31,0.15), 0 1px 2px 0 rgba(31,31,31,0.15);
|
||||
border: solid 2px #fff;
|
||||
box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.demonstration {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
color: gray;
|
||||
text-align: center;
|
||||
margin: 10px auto;
|
||||
white-space:nowrap;
|
||||
overflow:hidden;
|
||||
text-overflow:ellipsis;
|
||||
}
|
||||
|
||||
.template-img {
|
||||
background-size: 100% 100%;
|
||||
height: 170px;
|
||||
width: 300px;
|
||||
margin: 0 auto;
|
||||
border: solid 2px #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.template-img:hover {
|
||||
border: solid 1px #4b8fdf;
|
||||
border-radius: 3px;
|
||||
color: deepskyblue;
|
||||
cursor: pointer;
|
||||
}
|
||||
.testcase-template:hover ::v-deep .template-button{
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.template-button {
|
||||
display: none;
|
||||
text-align: center;
|
||||
position:absolute;
|
||||
bottom: 5px;
|
||||
left: 0px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
</style>
|
260
frontend/src/views/panel/templateMarket/index.vue
Normal file
260
frontend/src/views/panel/templateMarket/index.vue
Normal file
@ -0,0 +1,260 @@
|
||||
<template>
|
||||
<el-row>
|
||||
<el-row>
|
||||
<el-col span="4" style="text-align: left">
|
||||
<svg-icon
|
||||
icon-class="icon_left_outlined"
|
||||
class="topbar-icon-active"
|
||||
@click="closeDialog"
|
||||
/>
|
||||
</el-col>
|
||||
<el-col v-if="networkStatus" span="18">
|
||||
<el-row>
|
||||
<el-col span="20">
|
||||
<el-input v-model="searchText" :placeholder="$t('panel.enter_template_name_tips')" clearable="true" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col span="20" style="margin-top: 15px">
|
||||
<el-tabs v-model="marketActiveTab" @tab-click="handleClick">
|
||||
<el-tab-pane v-for="tabItem in marketTabs" :key="tabItem" :label="tabItem" :name="tabItem" />
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row v-if="networkStatus">
|
||||
<el-row v-loading="$store.getters.loadingMap[$store.getters.currentPath]" style="text-align: center;">
|
||||
<template-market-item
|
||||
v-for="(templateItem) in currentMarketTemplateShowList"
|
||||
v-show="templateItem.showFlag"
|
||||
:key="templateItem.id"
|
||||
:template="templateItem"
|
||||
:base-url="baseUrl"
|
||||
@templateApply="templateApply"
|
||||
@templatePreview="templatePreview"
|
||||
/>
|
||||
<el-dialog
|
||||
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
|
||||
:title="$t('panel.apply_template')"
|
||||
:visible.sync="folderSelectShow"
|
||||
width="500px"
|
||||
class="dialog-css"
|
||||
append-to-body="true"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<el-form ref="panelForm" :model="panelForm" label-width="80px">
|
||||
<el-form-item :label="$t('panel.name')">
|
||||
<el-input v-model="panelForm.name" :placeholder="$t('panel.enter_name_tips')" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('commons.folder')">
|
||||
<treeselect
|
||||
v-model="panelForm.pid"
|
||||
:clearable="false"
|
||||
:options="panelGroupList"
|
||||
:normalizer="normalizer"
|
||||
:placeholder="$t('chart.select_group')"
|
||||
:no-children-text="$t('commons.treeselect.no_children_text')"
|
||||
:no-options-text="$t('commons.treeselect.no_options_text')"
|
||||
:no-results-text="$t('commons.treeselect.no_results_text')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer dialog-footer-self">
|
||||
<el-button size="mini" @click="folderSelectShow=false">{{ $t('commons.cancel') }}</el-button>
|
||||
<el-button size="mini" type="primary" :disabled="!panelForm.name || !panelForm.pid" @click="apply">{{ $t('commons.confirm') }}</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!--预览-->
|
||||
<el-dialog top="5vh" width="80%" append-to-body="true" :visible.sync="previewVisible">
|
||||
<img width="100%" :src="templatePreviewUrl" alt="">
|
||||
</el-dialog>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row v-else class="custom-position">
|
||||
{{ $t('panel.market_network_tips') }}
|
||||
</el-row>
|
||||
|
||||
</el-row>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { searchMarket, getCategories } from '@/api/templateMarket'
|
||||
import TemplateMarketItem from '@/views/panel/templateMarket/component/TemplateMarketItem'
|
||||
import { groupTree, panelSave } from '@/api/panel/panel'
|
||||
import bus from '@/utils/bus'
|
||||
import { DEFAULT_COMMON_CANVAS_STYLE_STRING } from '@/views/panel/panel'
|
||||
|
||||
export default {
|
||||
name: 'TemplateMarket',
|
||||
components: { TemplateMarketItem },
|
||||
data() {
|
||||
return {
|
||||
previewVisible: false,
|
||||
templatePreviewUrl: null,
|
||||
marketTabs: null,
|
||||
marketActiveTab: null,
|
||||
searchText: null,
|
||||
panelForm: {
|
||||
name: null,
|
||||
pid: null,
|
||||
nodeType: 'panel',
|
||||
templateUrl: null,
|
||||
newFrom: 'new_market_template',
|
||||
panelType: 'self',
|
||||
panelStyle: JSON.stringify(DEFAULT_COMMON_CANVAS_STYLE_STRING),
|
||||
panelData: '[]'
|
||||
},
|
||||
panelGroupList: [],
|
||||
curApplyTemplate: null,
|
||||
folderSelectShow: false,
|
||||
baseUrl: 'https://dataease.io/templates',
|
||||
currentMarketTemplateShowList: [],
|
||||
networkStatus: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
watch: {
|
||||
marketActiveTab() {
|
||||
this.initTemplateShow()
|
||||
},
|
||||
searchText() {
|
||||
this.initTemplateShow()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initMarketTemplate()
|
||||
this.getGroupTree()
|
||||
},
|
||||
methods: {
|
||||
initMarketTemplate() {
|
||||
searchMarket({}).then(rsp => {
|
||||
this.baseUrl = rsp.data.baseUrl
|
||||
this.currentMarketTemplateShowList = rsp.data.contents
|
||||
}).catch(() => {
|
||||
this.networkStatus = false
|
||||
})
|
||||
getCategories().then(rsp => {
|
||||
this.marketTabs = rsp.data
|
||||
this.marketActiveTab = this.marketTabs[0]
|
||||
}).catch(() => {
|
||||
this.networkStatus = false
|
||||
})
|
||||
},
|
||||
getGroupTree() {
|
||||
groupTree({ nodeType: 'folder' }).then(res => {
|
||||
this.panelGroupList = res.data
|
||||
})
|
||||
},
|
||||
normalizer(node) {
|
||||
// 去掉children=null的属性
|
||||
if (node.children === null || node.children === 'null') {
|
||||
delete node.children
|
||||
}
|
||||
},
|
||||
templateApply(template) {
|
||||
this.curApplyTemplate = template
|
||||
this.panelForm.name = template.title
|
||||
this.panelForm.templateUrl = this.baseUrl + template.metas.theme_repo
|
||||
this.folderSelectShow = true
|
||||
},
|
||||
apply() {
|
||||
if (this.panelForm.name.length > 50) {
|
||||
this.$warning(this.$t('commons.char_can_not_more_50'))
|
||||
return false
|
||||
}
|
||||
|
||||
if (!this.panelForm.templateUrl) {
|
||||
this.$warning('未获取模板下载链接请联系模板市场官方')
|
||||
return false
|
||||
}
|
||||
panelSave(this.panelForm).then(response => {
|
||||
this.$message({
|
||||
message: this.$t('commons.save_success'),
|
||||
type: 'success',
|
||||
showClose: true
|
||||
})
|
||||
this.folderSelectShow = false
|
||||
bus.$emit('newPanelFromMarket', response.data)
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
closeDialog() {
|
||||
this.$emit('closeDialog')
|
||||
},
|
||||
handleClick(item) {
|
||||
|
||||
},
|
||||
initTemplateShow() {
|
||||
this.currentMarketTemplateShowList.forEach(template => {
|
||||
template.showFlag = this.templateShow(template)
|
||||
})
|
||||
},
|
||||
templateShow(templateItem) {
|
||||
let categoryMarch = false
|
||||
let searchMarch = false
|
||||
templateItem.categories.forEach(category => {
|
||||
if (category.name === this.marketActiveTab) {
|
||||
categoryMarch = true
|
||||
}
|
||||
})
|
||||
if (!this.searchText || templateItem.title.indexOf(this.searchText) > -1) {
|
||||
searchMarch = true
|
||||
}
|
||||
return categoryMarch && searchMarch
|
||||
},
|
||||
templatePreview(url) {
|
||||
this.templatePreviewUrl = url
|
||||
this.previewVisible = true
|
||||
},
|
||||
newPanel() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dialog-footer-self{
|
||||
text-align: center;
|
||||
}
|
||||
.search-button-self{
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.topbar-icon-active {
|
||||
cursor: pointer;
|
||||
transition: .1s;
|
||||
border-radius: 3px;
|
||||
font-size: 22px;
|
||||
background-color: rgb(245, 245, 245);
|
||||
|
||||
&:active {
|
||||
color: #000;
|
||||
border-color: #3a8ee6;
|
||||
background-color: red;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(31, 35, 41, 0.1);
|
||||
color: #3a8ee6;
|
||||
}
|
||||
}
|
||||
.custom-position {
|
||||
height: 80vh;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
flex-flow: row nowrap;
|
||||
color: #9ea6b2;
|
||||
}
|
||||
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user