Merge branch 'dev-v2' into pr@dev-v2_dzz

This commit is contained in:
dataeaseShu 2023-12-04 11:18:15 +08:00
commit e15524b460
59 changed files with 828 additions and 298 deletions

View File

@ -16,7 +16,7 @@
DataEase 是开源的数据可视化分析工具帮助用户快速分析数据并洞察业务趋势从而实现业务的改进与优化。DataEase 支持丰富的数据源连接,能够通过拖拉拽方式快速制作图表,并可以方便的与他人分享。
<p align="center">
<img src="https://github.com/dataease/dataease/assets/41712985/ce8db032-227a-41e2-b45c-279007bd4ae3" alt="DataEase 概览图" border="0" />
<img src="https://github.com/dataease/dataease/assets/41712985/f951e258-a328-43a9-aa37-ee470d37ed63" alt="DataEase 概览图" border="0" />
</p>
**DataEase 的优势:**

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>core</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -92,6 +92,10 @@
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>

View File

@ -1106,11 +1106,11 @@ public class ChartDataBuild {
break;
}
if (originStr.length() >= columnPermissionItem.getDesensitizationRule().getM() && originStr.length() >= columnPermissionItem.getDesensitizationRule().getN()) {
desensitizationStr = "***" + StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***";
desensitizationStr = StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, columnPermissionItem.getDesensitizationRule().getN()) + "***";
break;
}
if (originStr.length() >= columnPermissionItem.getDesensitizationRule().getM() && originStr.length() < columnPermissionItem.getDesensitizationRule().getN()) {
desensitizationStr = "***" + StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, originStr.length());
desensitizationStr = StringUtils.substring(originStr, columnPermissionItem.getDesensitizationRule().getM() - 1, originStr.length());
}
break;
default:

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

@ -33,14 +33,20 @@ import io.dataease.datasource.request.DatasourceRequest;
import io.dataease.engine.constant.SQLConstants;
import io.dataease.exception.DEException;
import io.dataease.i18n.Translator;
import io.dataease.job.sechedule.CheckDsStatusJob;
import io.dataease.job.sechedule.ScheduleManager;
import io.dataease.license.config.XpackInteract;
import io.dataease.model.BusiNodeRequest;
import io.dataease.model.BusiNodeVO;
import io.dataease.system.dao.auto.entity.CoreSysSetting;
import io.dataease.system.manage.CoreUserManage;
import io.dataease.utils.*;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
@ -85,7 +91,8 @@ public class DatasourceServer implements DatasourceApi {
@Resource
private DatasetDataManage datasetDataManage;
@Resource
private ScheduleManager scheduleManager;
@Resource
private CoreUserManage coreUserManage;
@ -260,7 +267,7 @@ public class DatasourceServer implements DatasourceApi {
try {
datasourceSyncManage.createEngineTable(datasourceRequest.getTable(), tableFields);
} catch (Exception e) {
DEException.throwException("Failed to create table " + datasourceRequest.getTable());
DEException.throwException("Failed to create table " + datasourceRequest.getTable() + ", " + e.getMessage());
}
}
commonThreadPool.addTask(() -> {
@ -402,7 +409,7 @@ public class DatasourceServer implements DatasourceApi {
try {
datasourceSyncManage.createEngineTable(toCreateTable, ApiUtils.getTableFields(datasourceRequest));
} catch (Exception e) {
DEException.throwException("Failed to create table " + toCreateTable);
DEException.throwException("Failed to create table " + toCreateTable + ", " + e.getMessage());
}
}
datasourceSyncManage.deleteSchedule(datasourceTaskServer.selectByDSId(dataSourceDTO.getId()));
@ -418,7 +425,7 @@ public class DatasourceServer implements DatasourceApi {
try {
datasourceSyncManage.dropEngineTable(deleteTable);
} catch (Exception e) {
DEException.throwException("Failed to drop table " + deleteTable);
DEException.throwException("Failed to drop table " + deleteTable + ", " + e.getMessage());
}
}
for (String toCreateTable : toCreateTables) {
@ -426,7 +433,7 @@ public class DatasourceServer implements DatasourceApi {
try {
datasourceSyncManage.createEngineTable(toCreateTable, ExcelUtils.getTableFields(datasourceRequest));
} catch (Exception e) {
DEException.throwException("Failed to create table " + toCreateTable);
DEException.throwException("Failed to create table " + toCreateTable + ", " + e.getMessage());
}
}
datasourceSyncManage.extractExcelData(requestDatasource, "all_scope");
@ -605,6 +612,31 @@ public class DatasourceServer implements DatasourceApi {
return validate(coreDatasource);
}
public void addJob(List<CoreSysSetting> sysSettings) {
String type = "minute";
String interval = "30";
for (CoreSysSetting sysSetting : sysSettings) {
if (sysSetting.getPkey().equalsIgnoreCase("basic.dsExecuteTime")) {
type = sysSetting.getPval();
}
if (sysSetting.getPkey().equalsIgnoreCase("basic.dsIntervalTime")) {
interval = sysSetting.getPval();
}
}
String cron = "";
switch (type) {
case "hour":
cron = "0 0 0/hour * * ? *".replace("hour", interval.toString());
break;
default:
cron = "0 0/minute * * * ? *".replace("minute", interval.toString());
}
scheduleManager.addOrUpdateCronJob(new JobKey("Datasource", "check_status"),
new TriggerKey("Datasource", "check_status"),
CheckDsStatusJob.class,
cron, new Date(System.currentTimeMillis()), null, new JobDataMap());
}
private DatasourceDTO validate(CoreDatasource coreDatasource) {
checkDatasourceStatus(coreDatasource);
DatasourceDTO datasourceDTO = new DatasourceDTO();

View File

@ -0,0 +1,27 @@
package io.dataease.job.sechedule;
import io.dataease.datasource.server.DatasourceServer;
import io.dataease.utils.CommonBeanFactory;
import io.dataease.utils.LogUtil;
import jakarta.annotation.Resource;
import org.quartz.*;
import org.springframework.stereotype.Component;
@Component
public class CheckDsStatusJob implements Job {
@Resource
private DatasourceServer datasourceServer;
public CheckDsStatusJob() {
datasourceServer = (DatasourceServer) CommonBeanFactory.getBean(DatasourceServer.class);
}
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LogUtil.info("Begin to check ds status...");
datasourceServer.updateDatasourceStatus();
}
}

View File

@ -18,9 +18,4 @@ public class Schedular {
datasourceServer.updateStopJobStatus();
}
@QuartzScheduled(cron = "0 0/30 * * * ?")
public void updateDatasourceStatus() {
datasourceServer.updateDatasourceStatus();
}
}

View File

@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/license")
public class LicenseServer implements LicenseApi {
private static final String product = "DataEase";
private static final String product = "DataEase v2";
@Resource
private CoreLicManage coreLicManage;

View File

@ -6,6 +6,8 @@ import io.dataease.datasource.provider.CalciteProvider;
import io.dataease.datasource.server.DatasourceServer;
import io.dataease.datasource.server.DatasourceTaskServer;
import io.dataease.datasource.server.EngineServer;
import io.dataease.system.dao.auto.entity.CoreSysSetting;
import io.dataease.system.manage.SysParameterManage;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.event.ApplicationReadyEvent;
@ -29,6 +31,8 @@ public class DataSourceInitStartListener implements ApplicationListener<Applicat
private CalciteProvider calciteProvider;
@Resource
private EngineServer engineServer;
@Resource
private SysParameterManage sysParameterManage;
@Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
@ -62,6 +66,14 @@ public class DataSourceInitStartListener implements ApplicationListener<Applicat
e.printStackTrace();
}
}
try {
List<CoreSysSetting> coreSysSettings = sysParameterManage.groupList("basic.");
datasourceServer.addJob(coreSysSettings);
}catch (Exception e){
e.printStackTrace();
}
}

View File

@ -2,6 +2,7 @@ package io.dataease.system.manage;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.dataease.api.system.vo.SettingItemVO;
import io.dataease.datasource.server.DatasourceServer;
import io.dataease.license.config.XpackInteract;
import io.dataease.system.dao.auto.entity.CoreSysSetting;
import io.dataease.system.dao.auto.mapper.CoreSysSettingMapper;
@ -31,6 +32,8 @@ public class SysParameterManage {
@Resource
private ExtCoreSysSettingMapper extCoreSysSettingMapper;
@Resource
private DatasourceServer datasourceServer;
public String singleVal(String key) {
QueryWrapper<CoreSysSetting> queryWrapper = new QueryWrapper<>();
@ -100,6 +103,7 @@ public class SysParameterManage {
return sysSetting;
}).collect(Collectors.toList());
extCoreSysSettingMapper.saveBatch(sysSettings);
datasourceServer.addJob(sysSettings);
}

View File

@ -7,7 +7,7 @@ import io.dataease.api.template.dto.TemplateMarketPreviewInfoDTO;
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;
@ -17,11 +17,11 @@ 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;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@ -29,14 +29,8 @@ import java.util.stream.Collectors;
*/
@Service
public class TemplateCenterManage {
private final static String POSTS_API = "/api/content/posts?page=0&size=2000";
private final static String POSTS_API_V2 = "/apis/api.store.halo.run/v1alpha1/applications?keyword=&priceMode=&sort=latestReleaseTimestamp%2Cdesc&type=THEME&deVersion=V2&templateType=&label=&page=1&size=2000";
private final static String CATEGORIES_API = "/api/content/categories";
private final static String TEMPLATE_META_DATA_URL = "/upload/meta_data.json";
@Resource
private SysParameterManage sysParameterManage;
@ -71,9 +65,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 +80,8 @@ 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);
e.printStackTrace();
}
return null;
}
@ -121,69 +121,77 @@ public class TemplateCenterManage {
public MarketPreviewBaseResponse searchTemplatePreview() {
try {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
return basePreviewResponseV2Trans(templateQuery(templateParams), searchTemplateFromManage(), templateParams.get("template.url"));
MarketBaseResponse baseContentRsp = searchTemplate();
List<MarketMetaDataVO> categories = baseContentRsp.getCategories().stream().filter(category -> !"最近使用".equals(category.getLabel())).collect(Collectors.toList());
List<TemplateMarketDTO> contents = baseContentRsp.getContents();
List<TemplateMarketPreviewInfoDTO> previewContents = new ArrayList<>();
categories.forEach(category -> {
if ("推荐".equals(category.getLabel())) {
previewContents.add(new TemplateMarketPreviewInfoDTO(category, contents.stream().filter(template -> "Y".equals(template.getSuggest())).collect(Collectors.toList())));
} else {
previewContents.add(new TemplateMarketPreviewInfoDTO(category, contents.stream().filter(template -> checkCategoryMatch(template, category.getLabel())).collect(Collectors.toList())));
}
});
return new MarketPreviewBaseResponse(baseContentRsp.getBaseUrl(), categories.stream().map(MarketMetaDataVO::getLabel)
.collect(Collectors.toList()), previewContents);
} catch (Exception e) {
DEException.throwException(e);
LogUtil.error(e);
}
return null;
}
private Boolean checkCategoryMatch(TemplateMarketDTO template, String categoryNameMatch) {
try {
return template.getCategories().stream()
.anyMatch(category -> categoryNameMatch.equals(category.getName()));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private MarketBaseResponse baseResponseV2TransRecommend(MarketTemplateV2BaseResponse v2BaseResponse, String url) {
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<>();
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);
return new MarketBaseResponse(url, categoryVO, contents);
}
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()));
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 -> {
Long recentUseTime = useTime.get(templateMarketDTO.getId());
templateMarketDTO.setRecentUseTime(recentUseTime == null ? 0 : recentUseTime);
activeCategoriesName.add(templateMarketDTO.getMainCategory());
});
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()));
if (categoriesMap.get(spec.getLabel()) != null) {
activeCategoriesName.add(categoriesMap.get(spec.getLabel()));
}
});
}
// 最近使用排序
Collections.sort(contents);
return new MarketBaseResponse(url, contents);
}
private MarketPreviewBaseResponse basePreviewResponseV2Trans(MarketTemplateV2BaseResponse v2BaseResponse, List<TemplateMarketDTO> manageContents, String url) {
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
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)) {
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()));
}
});
manageContents.stream().forEach(templateMarketDTO -> {
if (value.equalsIgnoreCase(templateMarketDTO.getMainCategory())) {
contents.add(templateMarketDTO);
}
});
Collections.sort(contents);
result.add(new TemplateMarketPreviewInfoDTO(value, contents));
}
});
// 最近使用排序
return new MarketPreviewBaseResponse(url, categories, result);
return new MarketBaseResponse(url, categoryVO.stream().filter(node -> activeCategoriesName.contains(node.getLabel())).collect(Collectors.toList()), contents);
}
@ -194,8 +202,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", "最近使用", CommonConstants.TEMPLATE_SOURCE.PUBLIC));
return result;
}
@ -209,18 +216,35 @@ 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", "推荐", CommonConstants.TEMPLATE_SOURCE.PUBLIC));
} catch (Exception 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());
}
}

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

@ -4,7 +4,7 @@ spring:
username: root
password: 123456
messages:
basename: i18n/core,i18n/permissions
basename: i18n/lic,i18n/core,i18n/permissions
flyway:
enabled: true
table: de_standalone_version

View File

@ -36,4 +36,7 @@ CREATE TABLE `visualization_template_extend_data` (
ALTER TABLE `core_opt_recent`
MODIFY COLUMN `resource_id` bigint NULL COMMENT '资源ID' AFTER `id`,
ADD COLUMN `resource_name` varchar(255) NULL COMMENT '资源名称' AFTER `resource_id`;
ADD COLUMN `resource_name` varchar(255) NULL COMMENT '资源名称' AFTER `resource_id`;
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (7, 'template.url', 'https://templates-de.fit2cloud.com', 'text', 0);
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (8, 'template.accessKey', 'dataease', 'text', 1);

View File

@ -22,7 +22,9 @@ BEGIN;
INSERT INTO `core_menu`
VALUES (19, 0, 2, 'template-market', 'template-market', 4, NULL, '/template-market', 1, 1, 0);
INSERT INTO `core_menu`
VALUES (20, 15, 2, 'template-setting', 'system/template-setting', 4, 'icon_template', '/template-setting', 0, 1, 1);
VALUES (30, 0, 1, 'toolbox', null, 7, 'icon_template', '/toolbox', 1, 1, 0);
INSERT INTO `core_menu`
VALUES (31, 30, 2, 'template-setting', 'toolbox/template-setting', 1, 'icon_template', '/template-setting', 0, 1, 1);
COMMIT;
DROP TABLE IF EXISTS `visualization_template_extend_data`;
@ -52,6 +54,10 @@ CREATE TABLE `core_area_custom`
);
BEGIN;
INSERT INTO `core_sys_setting` VALUES (1, 'basic.dsIntervalTime', '6', 'text', 2);
INSERT INTO `core_sys_setting` VALUES (2, 'basic.dsExecuteTime', 'minute', 'text', 3);
INSERT INTO `core_sys_setting`
VALUES (1, 'basic.dsIntervalTime', '6', 'text', 2);
INSERT INTO `core_sys_setting`
VALUES (2, 'basic.dsExecuteTime', 'minute', 'text', 3);
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (7, 'template.url', 'https://templates-de.fit2cloud.com', 'text', 0);
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (8, 'template.accessKey', 'dataease', 'text', 1);
COMMIT;

View File

@ -83,6 +83,11 @@
<value-type>java.lang.Integer</value-type>
</cache>
<cache alias="user_echelon" uses-template="common-cache">
<key-type>java.lang.String</key-type>
<value-type>java.util.List</value-type>
</cache>
<cache alias="role_busi_pers_interactive" uses-template="common-cache">
<key-type>java.lang.String</key-type>
<value-type>java.util.List</value-type>
@ -130,17 +135,17 @@
</resources>
</cache>
<cache alias="core_menu_cache">
<cache alias="core_menu_cache" uses-template="common-cache">
<key-type>java.lang.String</key-type>
<value-type>java.util.List</value-type>
<expiry>
<!--<expiry>
<none/>
</expiry>
<resources>
<heap unit="entries">20</heap>
<offheap unit="MB">2</offheap>
<disk unit="MB" persistent="true">5</disk>
</resources>
</resources>-->
</cache>
</config>

View File

@ -26,6 +26,6 @@ export default {
}
}
},
sourcemap: false
sourcemap: true
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>core</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -21,7 +21,7 @@
<build>
<plugins>
<plugin>
<!--<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.2.0</version>
@ -38,13 +38,14 @@
</fileset>
</filesets>
</configuration>
</plugin>
</plugin>-->
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend-maven-plugin.version}</version>
<executions>
<execution>
<!--首次打包需要放开-->
<!--<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
@ -53,9 +54,9 @@
<nodeVersion>v16.15.0</nodeVersion>
<npmVersion>8.5.5</npmVersion>
</configuration>
</execution>
<execution>
</execution>-->
<!--前端组件有更新需要放开-->
<!--<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
@ -63,7 +64,7 @@
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
</execution>-->
<execution>
<id>npm run build</id>

View File

@ -116,10 +116,10 @@ service.interceptors.response.use(
response: AxiosResponse<any> & { config: InternalAxiosRequestConfig & { loading?: boolean } }
) => {
executeVersionHandler(response)
if (response.headers['x-de-refresh-token']) {
/* if (response.headers['x-de-refresh-token']) {
wsCache.set('user.token', response.headers['x-de-refresh-token'])
wsCache.set('user.exp', new Date().getTime() + 90000)
}
} */
if (response.headers['x-de-link-token']) {
linkStore.setLinkToken(response.headers['x-de-link-token'])
}

View File

@ -7,6 +7,7 @@ import HeaderMenuItem from './HeaderMenuItem.vue'
import { Icon } from '@/components/icon-custom'
import { ElHeader, ElMenu } from 'element-plus-secondary'
import SystemCfg from './SystemCfg.vue'
import ToolboxCfg from './ToolboxCfg.vue'
import { useRouter, useRoute } from 'vue-router'
import TopDoc from '@/layout/components/TopDoc.vue'
import AccountOperator from '@/layout/components/AccountOperator.vue'
@ -26,6 +27,7 @@ const permissionStore = usePermissionStore()
const routers: any[] = formatRoute(permissionStore.getRoutersNotHidden as AppCustomRouteRecordRaw[])
const showSystem = ref(false)
const showToolbox = ref(false)
const handleSelect = (index: string) => {
//
if (isExternal(index)) {
@ -37,8 +39,12 @@ const handleSelect = (index: string) => {
const initShowSystem = () => {
showSystem.value = permissionStore.getRouters.some(route => route.path === '/system')
}
const initShowToolbox = () => {
showToolbox.value = permissionStore.getRouters.some(route => route.path === '/toolbox')
}
onMounted(() => {
initShowSystem()
initShowToolbox()
})
</script>
@ -56,6 +62,7 @@ onMounted(() => {
</el-menu>
<div class="operate-setting" v-if="!desktop">
<XpackComponent jsname="c3dpdGNoZXI=" />
<ToolboxCfg v-if="showToolbox" />
<TopDoc />
<SystemCfg v-if="showSystem" />
<AccountOperator />

View File

@ -2,7 +2,11 @@
import { ElHeader } from 'element-plus-secondary'
import { useRouter } from 'vue-router'
import AccountOperator from '@/layout/components/AccountOperator.vue'
import { propTypes } from '@/utils/propTypes'
const { push } = useRouter()
const props = defineProps({
title: propTypes.string.def('系统设置')
})
const backToMain = () => {
push('/workbranch/index')
}
@ -12,7 +16,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">{{ props.title || '系统设置' }}</span>
<div class="operate-setting">
<span @click="backToMain" class="work-bar flex-align-center">
<el-icon>

View File

@ -0,0 +1,34 @@
<script lang="ts" setup>
import { useRouter } from 'vue-router'
const { push, resolve } = useRouter()
const redirectUser = () => {
const toolboxMenu = resolve('/toolbox')
const kidPath = toolboxMenu.matched[0].children[0].path
push(`${toolboxMenu.path}/${kidPath}`)
}
</script>
<template>
<el-tooltip class="box-item" effect="dark" content="工具箱" placement="top">
<div class="sys-setting">
<el-icon @click="redirectUser">
<Icon class="icon-setting" name="sys-tools" />
</el-icon>
</div>
</el-tooltip>
</template>
<style lang="less" scoped>
.sys-setting {
margin: 0 0 0 10px;
padding: 5px;
height: 28px;
width: 28px;
border-radius: 4px;
overflow: hidden;
cursor: pointer;
&:hover {
background-color: #1e2738;
}
}
</style>

View File

@ -7,23 +7,28 @@ import Menu from './components/Menu.vue'
import Main from './components/Main.vue'
import { ElContainer } from 'element-plus-secondary'
import { useRoute } from 'vue-router'
import HeaderTemplateMarket from '@/layout/components/HeaderTemplateMarket.vue'
const route = useRoute()
const systemMenu = computed(() => route.path.includes('system'))
const settingMenu = computed(() => route.path.includes('sys-setting'))
const templateMarketMenu = computed(() => route.path.includes('template-market'))
const marketMenu = computed(() => route.path.includes('template-market'))
const toolboxMenu = computed(() => route.path.includes('toolbox'))
</script>
<template>
<div class="common-layout">
<header-template-market v-if="templateMarketMenu"></header-template-market>
<HeaderSystem v-else-if="settingMenu"></HeaderSystem>
<HeaderSystem
v-if="settingMenu || marketMenu || toolboxMenu"
:title="toolboxMenu ? '工具箱' : marketMenu ? '模板中心' : ''"
/>
<Header v-else></Header>
<el-container class="layout-container">
<Sidebar v-if="systemMenu || settingMenu" class="layout-sidebar">
<Sidebar v-if="systemMenu || settingMenu || toolboxMenu" class="layout-sidebar">
<Menu style="height: 100%"></Menu>
</Sidebar>
<Main class="layout-main" :class="{ 'with-sider': systemMenu || settingMenu }"></Main>
<Main
class="layout-main"
:class="{ 'with-sider': systemMenu || settingMenu || toolboxMenu }"
></Main>
</el-container>
</div>
</template>

View File

@ -90,7 +90,7 @@ const validateHandler = (param, success) => {
}
const getLicense = result => {
if (result.status === 'valid') {
tipsSuffix.value = result.edition === 'Embedded' ? '套' : '个账号'
tipsSuffix.value = result?.license?.edition === 'Embedded' ? '套' : '个账号'
}
return {
status: result.status,

View File

@ -176,8 +176,16 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
const areaColors = [...colors, ...colors]
let areaStyle
if (customAttr.basicStyle.gradient) {
areaStyle = () => {
const ele = areaColors.shift()
const colorMap = new Map()
areaStyle = item => {
let ele
const key = `${item.field}-${item.category}`
if (colorMap.has(key)) {
ele = colorMap.get(key)
} else {
ele = areaColors.shift()
colorMap.set(key, ele)
}
if (ele) {
return {
fill: setGradientColor(hexColorToRGBA(ele, alpha), true, 270)

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

@ -1,6 +1,6 @@
<template>
<div class="info-template-container">
<div class="info-template-header">
<div v-if="!props.hideHead" class="info-template-header">
<div class="info-template-title">
<span>{{ curTitle }}</span>
</div>
@ -24,19 +24,50 @@
<div class="info-item-content">
<div class="info-item-pwd" v-if="item.type === 'pwd'">
<span>{{ pwdItem[item.pkey]['hidden'] ? '********' : item.pval }}</span>
<el-tooltip effect="dark" content="新页面预览" placement="top">
<el-icon
class="hover-icon hover-icon-in-table switch-pwd-icon"
@click="switchPwd(item.pkey)"
>
<Icon :name="pwdItem[item.pkey]['hidden'] ? 'eye' : 'eye-open'"></Icon>
</el-icon>
<el-tooltip
v-if="props.copyList.includes(item.pkey)"
effect="dark"
:content="t('common.copy')"
placement="top"
>
<el-button text @click="copyVal(item.pval)" class="setting-tip-btn">
<template #icon>
<Icon name="de-copy"></Icon>
</template>
</el-button>
</el-tooltip>
<el-tooltip
effect="dark"
:content="pwdItem[item.pkey]['hidden'] ? '点击隐藏' : '点击显示'"
placement="top"
>
<el-button text @click="switchPwd(item.pkey)" class="setting-tip-btn">
<template #icon>
<Icon :name="pwdItem[item.pkey]['hidden'] ? 'eye' : 'eye-open'"></Icon>
</template>
</el-button>
</el-tooltip>
</div>
<span v-else-if="item.pkey.includes('basic.dsIntervalTime')">
<span>{{ item.pval + ' ' + executeTime + '执行一次' }}</span>
</span>
<span v-else>{{ item.pval }}</span>
<span v-else>
<span>{{ item.pval }}</span>
<el-tooltip
v-if="props.copyList.includes(item.pkey)"
effect="dark"
:content="t('common.copy')"
placement="top"
>
<el-button text @click="copyVal(item.pval)" class="setting-tip-btn">
<template #icon>
<Icon name="de-copy"></Icon>
</template>
</el-button>
</el-tooltip>
</span>
</div>
</div>
</div>
@ -46,6 +77,9 @@
import { ref, defineProps, PropType, computed } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { SettingRecord, ToolTipRecord } from './SettingTemplate'
import useClipboard from 'vue-clipboard3'
import { ElMessage } from 'element-plus-secondary'
const { toClipboard } = useClipboard()
const { t } = useI18n()
const props = defineProps({
settingKey: {
@ -63,13 +97,28 @@ const props = defineProps({
settingTitle: {
type: String,
default: '基础设置'
},
hideHead: {
type: Boolean,
default: false
},
copyList: {
type: Array as PropType<string[]>,
default: () => []
}
})
const executeTime = ref('0分0秒')
const curTitle = computed(() => {
return props.settingTitle
})
const copyVal = async val => {
try {
await toClipboard(val)
ElMessage.success(t('common.copy_success'))
} catch (e) {
ElMessage.warning(t('common.copy_unsupported'), e)
}
}
const loadList = () => {
settingList.value = []
if (props.settingData?.length) {
@ -133,6 +182,11 @@ formatLabel()
</script>
<style lang="less" scope>
.setting-tip-btn {
height: 22px !important;
line-height: 22px !important;
margin-left: 2px !important;
}
.info-template-container {
padding: 24px;
.info-template-header {

View File

@ -0,0 +1,113 @@
<template>
<el-col class="main-head">
<div class="custom-split-line"></div>
<span v-show="!searchText" class="custom-category">{{ label }}</span>
<span v-show="searchText" class="custom-search">{{ label }}</span>
<span v-if="searchText" class="custom-search-result">的搜索结果是{{ searchResult }}</span>
</el-col>
<el-col
v-for="(templateItem, index) in fullTemplateShowList"
v-show="showFlagCheck(templateItem)"
:key="templateItem.id + label"
style="float: left; padding: 24px 12px 0; text-align: center; flex: 0"
:style="{ width: templateSpan }"
>
<template-market-v2-item
:key="index"
:template="templateItem"
:base-url="baseUrl"
:width="templateCurWidth"
:cur-position="curPosition"
@templateApply="templateApply"
@templatePreview="templatePreview"
/>
</el-col>
</template>
<script setup lang="ts">
import TemplateMarketV2Item from '@/views/template-market/component/TemplateMarketV2Item.vue'
import { computed } from 'vue'
const emits = defineEmits(['templateApply', 'templatePreview'])
const templateApply = params => {
emits('templateApply', params)
}
const templatePreview = params => {
emits('templatePreview', params)
}
const searchResult = computed(
() => props.fullTemplateShowList.filter(item => showFlagCheck(item)).length
)
const showFlagCheck = template => {
if (!template.categoryNames) {
console.log('===templateTest' + JSON.stringify(template))
}
return template.showFlag && template.categoryNames?.includes(props.label)
}
const props = defineProps({
searchText: {
type: String
},
baseUrl: {
type: String
},
templateCurWidth: {
type: Number
},
curPosition: {
type: String
},
templateSpan: {
type: String
},
label: {
type: String
},
fullTemplateShowList: {
type: Array,
default: () => []
}
})
</script>
<style lang="less" scoped>
.main-head {
width: 100%;
float: left;
height: 24px;
margin-top: 16px;
display: inline;
.custom-split-line {
margin: 4px 8px 0 12px;
width: 2px;
height: 16px;
background: rgba(51, 112, 255, 1);
float: left;
}
.custom-category {
float: left;
font-weight: 500;
font-size: 16px;
color: rgba(31, 35, 41, 1);
}
.custom-search {
float: left;
font-weight: 500;
font-size: 16px;
color: rgba(51, 112, 255, 1);
margin-right: 8px;
}
.custom-search-result {
float: left;
font-weight: 500;
font-size: 16px;
color: rgba(31, 35, 41, 1);
margin-right: 8px;
}
}
</style>

View File

@ -23,7 +23,6 @@
<el-row class="margin-top16 search-area">
<el-input
v-model="state.searchText"
size="small"
prefix-icon="Search"
class="title-name-search"
:placeholder="t('visualization.enter_template_name_tips')"
@ -36,15 +35,24 @@
><Filter
/></el-icon>
</el-row>
<el-row v-show="state.extFilterActive">
<el-select v-model="state.templateType" style="margin-top: 8px" placeholder="请选择">
<el-option
v-for="item in state.templateTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-row>
<el-row v-show="state.extFilterActive">
<el-select
v-model="state.templateType"
class="margin-top16"
size="small"
v-model="state.templateSourceType"
style="margin-top: 8px"
placeholder="请选择"
>
<el-option
v-for="item in state.templateTypeOptions"
v-for="item in state.templateSourceOptions"
:key="item.value"
:label="item.label"
:value="item.value"
@ -63,9 +71,10 @@
<el-collapse-item
themes="light"
v-for="(categoryTemplate, index) in state.marketTemplatePreviewShowList"
:name="categoryTemplate['categoryType']"
v-show="categoryTemplate['showFlag']"
:name="categoryTemplate['category'].label"
:key="index"
:title="categoryTemplate['categoryType']"
:title="categoryTemplate['category'].label"
>
<template-market-preview-item
v-for="templateItem in categoryTemplate['contents']"
@ -98,7 +107,6 @@
<el-button
style="float: right"
type="primary"
size="small"
@click="templateApply(state.curTemplate)"
>{{ t('visualization.apply_this_template') }}</el-button
>
@ -126,6 +134,10 @@ const props = defineProps({
previewId: {
type: String,
default: null
},
templateShowList: {
type: Array,
default: () => []
}
})
@ -149,6 +161,21 @@ const state = reactive({
categories: [],
networkStatus: true,
curTemplate: null,
templateSourceType: 'all',
templateSourceOptions: [
{
value: 'all',
label: '全部来源'
},
{
value: 'market',
label: '模板市场'
},
{
value: 'manage',
label: '模板管理'
}
],
templateType: 'all',
templateTypeOptions: [
{
@ -193,6 +220,13 @@ watch(
}
)
watch(
() => state.templateSourceType,
value => {
initTemplateShow()
}
)
const initMarketTemplate = () => {
searchMarketPreview()
.then(rsp => {
@ -242,6 +276,7 @@ const handleClick = item => {
const initTemplateShow = () => {
state.hasResult = false
state.marketTemplatePreviewShowList.forEach(categoryTemplates => {
categoryTemplates.showFlag = categoryShow(categoryTemplates.category.source)
categoryTemplates.contents.forEach(template => {
template.showFlag = templateShow(template)
if (template.showFlag) {
@ -252,16 +287,28 @@ const initTemplateShow = () => {
activeCategories.value = deepCopy(state.categories)
}
const categoryShow = sourceMatch => {
return (
state.templateSourceType === 'all' ||
sourceMatch === state.templateSourceType ||
sourceMatch === 'public'
)
}
const templateShow = templateItem => {
let templateTypeMarch = false
let searchMarch = false
let templateSourceTypeMarch = false
if (state.templateType === 'all' || templateItem.templateType === state.templateType) {
templateTypeMarch = true
}
if (!state.searchText || templateItem.title.indexOf(state.searchText) > -1) {
searchMarch = true
}
return templateTypeMarch && searchMarch
if (state.templateSourceType === 'all' || templateItem.source === state.templateSourceType) {
templateSourceTypeMarch = true
}
return templateTypeMarch && searchMarch && templateSourceTypeMarch
}
const previewTemplate = template => {

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,19 +75,20 @@
: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">
<div class="template-left">
<el-tree
v-if="state.treeShow"
menu
class="custom-market-tree"
:data="state.marketTabs"
v-model="state.marketActiveTab"
:data="categoriesComputed"
:props="state.treeProps"
node-key="label"
default-expand-all
@ -68,32 +102,39 @@
id="template-show-area"
class="template-right"
>
<el-col class="main-head">
<div class="custom-split-line"></div>
<span v-show="!state.searchText" class="custom-category">{{
state.marketActiveTab
}}</span>
<span v-show="state.searchText" class="custom-search">{{ 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 }"
>
<template-market-v2-item
:key="'outer-' + templateItem.id"
:template="templateItem"
<el-row v-show="state.marketActiveTab !== '推荐'">
<category-template-v2
:search-text="state.searchText"
:label="state.marketActiveTab"
:full-template-show-list="state.currentMarketTemplateShowList"
:template-span="state.templateSpan"
:base-url="state.baseUrl"
:width="state.templateCurWidth"
:template-cur-width="state.templateCurWidth"
:cur-position="state.curPosition"
@templateApply="templateApply"
@templatePreview="templatePreview"
/>
</el-col>
></category-template-v2>
</el-row>
<el-row v-show="state.marketActiveTab === '推荐'">
<el-row
style="display: inline; width: 100%; margin-bottom: 16px"
v-for="(categoryItem, index) in categoriesComputed"
:key="index"
>
<category-template-v2
v-if="categoryItem.label !== '最近使用'"
:search-text="state.searchText"
:label="categoryItem.label"
:full-template-show-list="state.currentMarketTemplateShowList"
:template-span="state.templateSpan"
:base-url="state.baseUrl"
:template-cur-width="state.templateCurWidth"
:cur-position="state.curPosition"
@templateApply="templateApply"
@templatePreview="templatePreview"
></category-template-v2>
</el-row>
</el-row>
</div>
<el-row v-show="state.networkStatus && !state.hasResult" class="template-empty">
<div style="text-align: center">
@ -111,35 +152,32 @@
</template>
<script setup lang="ts">
import { getCategoriesObject, searchMarket } from '@/api/templateMarket'
import { searchMarket } from '@/api/templateMarket'
import elementResizeDetectorMaker from 'element-resize-detector'
import { nextTick, reactive, watch, onMounted, ref, computed } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { useRoute } from 'vue-router'
import { ElMessage } from 'element-plus-secondary'
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'
import { imgUrlTrans } from '@/utils/imgUtils'
import { deepCopy } from '@/utils/utils'
import CategoryTemplateV2 from '@/views/template-market/component/CategoryTemplateV2.vue'
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 outPaddingState = computed(() => {
return state.curPosition === 'branch' && !previewModel.value
})
const optInit = params => {
state.curPosition = params.curPosition
state.templateType = params.templateType
state.pid = params.pid
const close = () => {
emits('close')
}
const title = computed(() => (state.curPosition === 'branch' ? '模板中心' : '使用模版新建'))
const state = reactive({
initReady: true,
curPosition: 'branch',
pid: null,
treeProps: {
@ -148,6 +186,7 @@ const state = reactive({
},
templateType: 'all',
templateSourceType: 'all',
treeShow: true,
templateSourceOptions: [
{
value: 'all',
@ -183,7 +222,7 @@ const state = reactive({
templateSpan: '25%',
previewVisible: false,
templatePreviewId: '',
marketTabs: null,
marketTabs: [],
marketActiveTab: null,
searchText: null,
dvCreateForm: {
@ -203,6 +242,9 @@ const state = reactive({
folderSelectShow: false,
baseUrl: 'https://dataease.io/templates',
currentMarketTemplateShowList: [],
curTemplateShowFilter: [],
curTemplateIndex: 0,
curTemplate: null,
networkStatus: true,
rule: {
name: [
@ -222,6 +264,44 @@ const state = reactive({
}
})
const categoriesComputed = computed(() => {
let result
if (state.templateSourceType === 'all') {
result = state.marketTabs
} else {
result = state.marketTabs.filter(
category => category.source === 'public' || category.source === state.templateSourceType
)
}
console.log('categoriesComputed=' + JSON.stringify(result))
return result
})
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 !== '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
})
}
watch(
() => state.searchText,
value => {
@ -239,20 +319,21 @@ watch(
watch(
() => state.templateSourceType,
value => {
state.treeShow = false
initTemplateShow()
nextTick(() => {
state.treeShow = true
initStyle()
})
}
)
const searchResultCount = computed(
() => state.currentMarketTemplateShowList.filter(template => template.showFlag).length
)
const nodeClick = data => {
state.marketActiveTab = data.label
initTemplateShow()
}
const closePreview = () => {
previewModel.value = false
previewModel.value = 'full'
}
const initMarketTemplate = async () => {
@ -260,13 +341,7 @@ const initMarketTemplate = async () => {
.then(rsp => {
state.baseUrl = rsp.data.baseUrl
state.currentMarketTemplateShowList = rsp.data.contents
})
.catch(() => {
state.networkStatus = false
})
getCategoriesObject()
.then(rsp => {
state.marketTabs = rsp.data
state.marketTabs = rsp.data.categories
state.marketActiveTab = state.marketTabs[0].label
initStyle()
initTemplateShow()
@ -294,6 +369,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 +394,6 @@ const templateApply = template => {
state.dvCreateForm.newFrom = 'new_inner_template'
state.dvCreateForm.templateId = template.id
}
apply()
}
@ -317,6 +405,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
@ -348,26 +437,9 @@ const initTemplateShow = () => {
}
const templateShow = templateItem => {
let categoryMarch = false
let searchMarch = false
let templateTypeMarch = false
let templateSourceTypeMarch = false
if (state.marketActiveTab === '最近使用') {
if (templateItem.recentUseTime) {
categoryMarch = true
}
} else if (state.marketActiveTab === '推荐') {
if (templateItem.suggest === 'Y') {
categoryMarch = true
}
} else {
templateItem.categories.forEach(category => {
if (category.name === state.marketActiveTab) {
categoryMarch = true
}
})
}
if (!state.searchText || templateItem.title.indexOf(state.searchText) > -1) {
searchMarch = true
}
@ -379,18 +451,26 @@ const templateShow = templateItem => {
if (state.templateSourceType === 'all' || templateItem.source === state.templateSourceType) {
templateSourceTypeMarch = true
}
return categoryMarch && searchMarch && templateTypeMarch && templateSourceTypeMarch
return searchMarch && templateTypeMarch && templateSourceTypeMarch
}
const templatePreview = previewId => {
state.templatePreviewId = previewId
previewModel.value = true
if (state.curPosition === 'branch') {
//
state.templatePreviewId = previewId
previewModel.value = 'marketPreview'
} else {
state.curTemplateShowFilter =
state.marketActiveTab === '推荐'
? state.currentMarketTemplateShowList
: 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()
@ -470,7 +550,7 @@ defineExpose({
height: 100%;
background: rgba(239, 240, 241, 1);
overflow-y: auto;
padding: 16px 12px;
padding: 0 12px 16px 12px;
}
.template-empty {
@ -490,6 +570,7 @@ defineExpose({
width: 100%;
float: left;
height: 24px;
margin-top: 16px;
display: inline;
.custom-split-line {
margin: 4px 8px 0 12px;
@ -522,7 +603,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

@ -336,9 +336,8 @@ const getEmptyDesc = (): string => {
padding: 8px 24px 0 24px;
background: #fff;
border-radius: 4px;
// height: calc(100% - 280px);
// margin-top: 16px;
height: 100%;
height: calc(100% - 280px);
margin-top: 16px;
.select-type-list {
width: 104px;

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

@ -5,7 +5,7 @@
<parent>
<artifactId>dataease</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -1 +1 @@
Subproject commit 6d3d203321dce09f2fee101af80345bd30536ced
Subproject commit 438f36fc4b459721ae0d88e365e4982f35fa1600

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>io.dataease</groupId>
<artifactId>dataease</artifactId>
<version>${dataease.version}</version>
<version>2.1.0</version>
<packaging>pom</packaging>
<modules>
@ -13,7 +13,7 @@
</modules>
<properties>
<dataease.version>2.0.0</dataease.version>
<dataease.version>2.1.0</dataease.version>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud-alibaba.version>2022.0.0.0-RC1</spring-cloud-alibaba.version>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>api</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -1,5 +1,6 @@
package io.dataease.api.lark.api;
import io.dataease.api.lark.dto.LarkEnableEditor;
import io.dataease.api.lark.dto.LarkTokenRequest;
import io.dataease.api.lark.vo.LarkInfoVO;
import io.dataease.api.lark.dto.LarkSettingCreator;
@ -18,4 +19,7 @@ public interface LarkApi {
@PostMapping("/token")
String larkToken(@RequestBody LarkTokenRequest request);
@PostMapping("/switchEnable")
void switchEnable(@RequestBody LarkEnableEditor editor);
}

View File

@ -0,0 +1,11 @@
package io.dataease.api.lark.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class LarkEnableEditor implements Serializable {
private boolean enable;
}

View File

@ -4,6 +4,8 @@ import io.dataease.api.template.vo.MarketCategoryVO;
import io.dataease.api.template.vo.MarketMetasVO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -30,6 +32,8 @@ public class TemplateMarketDTO implements Comparable<TemplateMarketDTO> {
private String source = "market";
private List<MarketCategoryVO> categories;
private List<String> categoryNames;
private String mainCategory;
private MarketMetasVO metas;
@ -38,7 +42,8 @@ public class TemplateMarketDTO implements Comparable<TemplateMarketDTO> {
this.id = manageDTO.getId();
this.title = manageDTO.getName();
this.mainCategory = manageDTO.getCategoryName();
this.categories = Arrays.asList(new MarketCategoryVO(manageDTO.getCategoryName()), new MarketCategoryVO("全部"));
this.categories = Arrays.asList(new MarketCategoryVO(manageDTO.getCategoryName()));
this.categoryNames = Arrays.asList(manageDTO.getCategoryName());
this.metas = new MarketMetasVO(manageDTO.getSnapshot());
this.templateType = "dataV".equalsIgnoreCase("manageDTO.getTemplateType()") ? "SCREEN" : "PANEL";
this.thumbnail = manageDTO.getSnapshot();
@ -51,15 +56,20 @@ public class TemplateMarketDTO implements Comparable<TemplateMarketDTO> {
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("全部"));
this.metas = new MarketMetasVO(templateUrl);
this.thumbnail = themeRepo;
this.templateType = templateType;
this.categories = new ArrayList<>(Arrays.asList(new MarketCategoryVO(categoryName))) ;
this.categoryNames = new ArrayList<>(Arrays.asList(categoryName)) ;
if (recentUseTime != null) {
this.recentUseTime = recentUseTime;
this.categories.add(new MarketCategoryVO("最近使用"));
this.categoryNames.add("最近使用");
}
if ("Y".equalsIgnoreCase(suggest)) {
this.suggest = "Y";
this.categories.add(new MarketCategoryVO("推荐"));
this.categoryNames.add("推荐");
}
}

View File

@ -1,5 +1,6 @@
package io.dataease.api.template.dto;
import io.dataease.api.template.vo.MarketMetaDataVO;
import lombok.Data;
import lombok.NoArgsConstructor;
@ -13,12 +14,14 @@ import java.util.List;
@NoArgsConstructor
public class TemplateMarketPreviewInfoDTO {
private String categoryType;
private MarketMetaDataVO category;
private Boolean showFlag = true;
List<TemplateMarketDTO> contents;
public TemplateMarketPreviewInfoDTO(String categoryType, List<TemplateMarketDTO> contents) {
this.categoryType = categoryType;
public TemplateMarketPreviewInfoDTO(MarketMetaDataVO category, List<TemplateMarketDTO> contents) {
this.category = category;
this.contents = contents;
}
}

View File

@ -1,6 +1,7 @@
package io.dataease.api.template.response;
import io.dataease.api.template.dto.TemplateMarketDTO;
import io.dataease.api.template.vo.MarketMetaDataVO;
import lombok.Data;
import java.util.List;
@ -13,16 +14,16 @@ import java.util.List;
public class MarketBaseResponse {
private String baseUrl;
List<MarketMetaDataVO> categories;
private List<TemplateMarketDTO> contents;
public MarketBaseResponse() {
}
public MarketBaseResponse(String baseUrl, List<TemplateMarketDTO> contents) {
public MarketBaseResponse(String baseUrl, List<MarketMetaDataVO> categories, List<TemplateMarketDTO> contents) {
this.baseUrl = baseUrl;
this.categories = categories;
this.contents = contents;
}
}

View File

@ -2,7 +2,9 @@ package io.dataease.api.template.response;
import io.dataease.api.template.dto.TemplateMarketDTO;
import io.dataease.api.template.dto.TemplateMarketPreviewInfoDTO;
import io.dataease.api.template.vo.MarketMetaDataVO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@ -11,6 +13,7 @@ import java.util.List;
* @date : 2023/11/6 17:43
*/
@Data
@NoArgsConstructor
public class MarketPreviewBaseResponse {
private String baseUrl;
@ -18,9 +21,6 @@ public class MarketPreviewBaseResponse {
private List<TemplateMarketPreviewInfoDTO> contents;
public MarketPreviewBaseResponse() {
}
public MarketPreviewBaseResponse(String baseUrl, List<String> categories, List<TemplateMarketPreviewInfoDTO> contents) {
this.baseUrl = baseUrl;
this.categories = categories;

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

@ -5,7 +5,7 @@
<parent>
<artifactId>api</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -9,6 +9,7 @@ import io.dataease.auth.DePermit;
import io.dataease.auth.vo.TokenVO;
import io.dataease.model.KeywordRequest;
import io.dataease.request.BaseGridRequest;
import io.swagger.v3.oas.annotations.Hidden;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@ -66,6 +67,7 @@ public interface UserApi {
@PostMapping("/byCurOrg")
List<UserItem> byCurOrg(@RequestBody KeywordRequest request);
@Hidden
@GetMapping("/userCount")
int userCount();
@ -100,5 +102,7 @@ public interface UserApi {
@PostMapping("/modifyPwd")
void modifyPwd(@RequestBody ModifyPwdRequest request);
@Hidden
@GetMapping("/firstEchelon/{limit}")
List<Long> firstEchelon(@PathVariable("limit") Long limit);
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>sdk</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -18,21 +18,12 @@
</modules>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--<dependency>
<groupId>io.dataease</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>-->
</dependency>
<dependency>
<groupId>io.dataease</groupId>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>sdk</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -9,6 +9,7 @@ import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.util.Objects;
public class TokenFilter implements Filter {
@ -35,13 +36,13 @@ public class TokenFilter implements Filter {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
String refreshToken = null;
/*String refreshToken = null;
if (StringUtils.isNotBlank(refreshToken = ServletUtils.request().getHeader(AuthConstant.REFRESH_TOKEN_KEY))) {
ServletUtils.response().addHeader(AuthConstant.REFRESH_TOKEN_KEY, refreshToken);
}
}*/
String executeVersion = null;
if (StringUtils.isNotBlank(executeVersion = VersionUtil.getRandomVersion())) {
ServletUtils.response().addHeader(AuthConstant.DE_EXECUTE_VERSION, executeVersion);
Objects.requireNonNull(ServletUtils.response()).addHeader(AuthConstant.DE_EXECUTE_VERSION, executeVersion);
}
String linkToken = ServletUtils.getHead(AuthConstant.LINK_TOKEN_KEY);
if (StringUtils.isNotBlank(linkToken)) {

View File

@ -37,6 +37,7 @@ public class CorsInterceptor implements HandlerInterceptor {
public void addOriginList() {
busiOriginList.clear();
String className = "io.dataease.api.permissions.embedded.api.EmbeddedApi";
String methodName = "domainList";
if (ObjectUtils.isEmpty(aClass)) {
@ -54,10 +55,8 @@ public class CorsInterceptor implements HandlerInterceptor {
if (ObjectUtils.isNotEmpty(result)) {
List<String> list = (List<String>) result;
if (CollectionUtils.isNotEmpty(list)) {
List<String> strings = list.stream().filter(item -> !busiOriginList.contains(item)).toList();
busiOriginList.addAll(strings);
busiOriginList.addAll(list.stream().distinct().toList());
}
}
}
}

View File

@ -13,7 +13,7 @@ public class AuthConstant {
public final static String DE_API_PREFIX = "/de2api";
public final static String REFRESH_TOKEN_KEY = "X-DE-REFRESH-TOKEN";
// public final static String REFRESH_TOKEN_KEY = "X-DE-REFRESH-TOKEN";
public final static String USER_IMPORT_ERROR_KEY = "USER-IMPORT-ERROR-KEY";

View File

@ -3,6 +3,7 @@ package io.dataease.constant;
public class CacheConstant {
public static class UserCacheConstant {
public static final String USER_COUNT_CACHE = "user_count";
public static final String USER_ECHELON_CACHE = "user_echelon";
public static final String LOGIN_USER_CACHE = "login_user_cache";
public static final String USER_ROLES_CACHE = "user_roles";
public static final String USER_BUSI_PERS_CACHE = "user_busi_pers";

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";
}
}

View File

@ -29,7 +29,7 @@ public class AuthUtils {
}
public static boolean isSysAdmin(Long userId) {
return userId == SYS_ADMIN_UID;
return userId.equals(SYS_ADMIN_UID);
}

View File

@ -1,16 +1,12 @@
package io.dataease.utils;
import io.dataease.constant.AuthConstant;
import io.dataease.result.ResultMessage;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.IOException;
public class ServletUtils {
public static HttpServletRequest request() {
@ -38,6 +34,7 @@ public class ServletUtils {
public static String getXUserinfo() {
return getHead(AuthConstant.OIDC_X_USER);
}
public static String getCasUser() {
return getHead(AuthConstant.CAS_X_USER);
}
@ -46,25 +43,5 @@ public class ServletUtils {
return true;
}
public static void writeResult(ResultMessage resultMessage) {
HttpServletResponse response = response();
if (ObjectUtils.isEmpty(response)) return;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
ServletOutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.print(JsonUtil.toJSONString(resultMessage).toString());
} catch (IOException ex) {
LogUtil.error(ex.getMessage());
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}

View File

@ -28,8 +28,7 @@ public class TokenUtils {
if (StringUtils.length(token) < 100) {
DEException.throwException("token is invalid");
}
TokenUserBO tokenUserBO = userBOByToken(token);
return tokenUserBO;
return userBOByToken(token);
}
public static TokenUserBO validateLinkToken(String linkToken) {

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>sdk</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>dataease</artifactId>
<groupId>io.dataease</groupId>
<version>2.0.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>