diff --git a/core/backend/src/main/java/io/dataease/auth/aop/DeRateLimiterHandler.java b/core/backend/src/main/java/io/dataease/auth/aop/DeRateLimiterHandler.java index 8bd16ddae3..a7eb290858 100644 --- a/core/backend/src/main/java/io/dataease/auth/aop/DeRateLimiterHandler.java +++ b/core/backend/src/main/java/io/dataease/auth/aop/DeRateLimiterHandler.java @@ -1,10 +1,10 @@ package io.dataease.auth.aop; -import cn.hutool.core.util.StrUtil; import io.dataease.auth.annotation.DeRateLimiter; import io.dataease.auth.service.DeLimitService; import io.dataease.commons.utils.IPUtils; import io.dataease.commons.utils.ServletUtils; +import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @@ -34,8 +34,8 @@ public class DeRateLimiterHandler { DeRateLimiter rateLimiter = AnnotationUtils.findAnnotation(method, DeRateLimiter.class); if (rateLimiter != null) { String key = rateLimiter.key(); - if (StrUtil.isBlank(key)) { - key = method.getDeclaringClass().getName() + StrUtil.DOT + method.getName(); + if (StringUtils.isBlank(key)) { + key = method.getDeclaringClass().getName() + "." + method.getName(); } key = key + SEPARATOR + IPUtils.get(); diff --git a/core/backend/src/main/java/io/dataease/auth/aop/SqlInjectAop.java b/core/backend/src/main/java/io/dataease/auth/aop/SqlInjectAop.java index 57a3354d76..bc03f68915 100644 --- a/core/backend/src/main/java/io/dataease/auth/aop/SqlInjectAop.java +++ b/core/backend/src/main/java/io/dataease/auth/aop/SqlInjectAop.java @@ -1,10 +1,10 @@ package io.dataease.auth.aop; -import cn.hutool.core.util.ArrayUtil; import io.dataease.auth.annotation.SqlInjectValidator; import io.dataease.plugins.common.exception.DataEaseException; import io.dataease.plugins.common.request.KeywordRequest; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; @@ -56,7 +56,7 @@ public class SqlInjectAop { } private boolean isIllegal(String[] value, List orderList) { - if (CollectionUtils.isEmpty(orderList) || ArrayUtil.isEmpty(value)) return false; + if (CollectionUtils.isEmpty(orderList) || ArrayUtils.isEmpty(value)) return false; Set wordList = Arrays.stream(value).collect(Collectors.toSet()); wordList.add("asc"); wordList.add("desc"); diff --git a/core/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java b/core/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java index 5f42f3e712..fa601256de 100644 --- a/core/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java +++ b/core/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java @@ -1,6 +1,5 @@ package io.dataease.auth.filter; -import cn.hutool.core.util.ArrayUtil; import io.dataease.auth.entity.SysUserEntity; import io.dataease.auth.entity.TokenInfo; import io.dataease.auth.service.AuthUserService; @@ -9,6 +8,7 @@ import io.dataease.commons.license.DefaultLicenseService; import io.dataease.commons.license.F2CLicenseResponse; import io.dataease.commons.utils.CommonBeanFactory; import io.dataease.commons.utils.LogUtil; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.web.filter.AccessControlFilter; @@ -66,7 +66,7 @@ public class F2CDocFilter extends AccessControlFilter { String authorization = request.getHeader("Authorization"); if (StringUtils.isBlank(authorization)) { Cookie[] cookies = request.getCookies(); - if (ArrayUtil.isNotEmpty(cookies)) { + if (ArrayUtils.isNotEmpty(cookies)) { Cookie cookie = Arrays.stream(cookies).filter(item -> StringUtils.equals(item.getName(), "Authorization")).findFirst().orElse(null); if (ObjectUtils.isNotEmpty(cookie) && StringUtils.isNotBlank(cookie.getValue())) { authorization = cookie.getValue(); diff --git a/core/backend/src/main/java/io/dataease/auth/filter/F2CLinkFilter.java b/core/backend/src/main/java/io/dataease/auth/filter/F2CLinkFilter.java index 06df3bed1c..293df95028 100644 --- a/core/backend/src/main/java/io/dataease/auth/filter/F2CLinkFilter.java +++ b/core/backend/src/main/java/io/dataease/auth/filter/F2CLinkFilter.java @@ -1,12 +1,12 @@ package io.dataease.auth.filter; -import cn.hutool.core.util.ObjectUtil; import com.auth0.jwt.JWT; import com.auth0.jwt.interfaces.DecodedJWT; import io.dataease.auth.util.JWTUtils; import io.dataease.auth.util.LinkUtil; import io.dataease.commons.utils.LogUtil; import io.dataease.plugins.common.base.domain.PanelLink; +import org.apache.commons.lang3.ObjectUtils; import org.apache.shiro.web.filter.authc.AnonymousFilter; import javax.servlet.ServletRequest; @@ -26,7 +26,7 @@ public class F2CLinkFilter extends AnonymousFilter { String resourceId = jwt.getClaim("resourceId").asString(); Long userId = jwt.getClaim("userId").asLong(); PanelLink panelLink = LinkUtil.queryLink(resourceId, userId); - if (ObjectUtil.isEmpty(panelLink)) return false; + if (ObjectUtils.isEmpty(panelLink)) return false; String pwd; if (!panelLink.getEnablePwd()) { panelLink.setPwd("dataease"); diff --git a/core/backend/src/main/java/io/dataease/commons/filter/HtmlResourceFilter.java b/core/backend/src/main/java/io/dataease/commons/filter/HtmlResourceFilter.java new file mode 100644 index 0000000000..1e674bb0c1 --- /dev/null +++ b/core/backend/src/main/java/io/dataease/commons/filter/HtmlResourceFilter.java @@ -0,0 +1,40 @@ +package io.dataease.commons.filter; + +import org.springframework.core.Ordered; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class HtmlResourceFilter implements Filter, Ordered { + + @Override + public int getOrder() { + return 99; + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + Filter.super.init(filterConfig); + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; + // 禁用缓存 + httpResponse.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache"); + httpResponse.setHeader("Cache", "no-cache"); + httpResponse.setHeader(HttpHeaders.PRAGMA, "no-cache"); + httpResponse.setHeader(HttpHeaders.EXPIRES, "0"); + // 继续执行过滤器链 + filterChain.doFilter(servletRequest, httpResponse); + } + + @Override + public void destroy() { + Filter.super.destroy(); + } +} diff --git a/core/backend/src/main/java/io/dataease/commons/utils/BeanUtils.java b/core/backend/src/main/java/io/dataease/commons/utils/BeanUtils.java index aaf54f32b8..db69f72113 100644 --- a/core/backend/src/main/java/io/dataease/commons/utils/BeanUtils.java +++ b/core/backend/src/main/java/io/dataease/commons/utils/BeanUtils.java @@ -2,7 +2,10 @@ package io.dataease.commons.utils; import org.apache.commons.lang3.StringUtils; +import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; public class BeanUtils { @@ -65,4 +68,19 @@ public class BeanUtils { return null; } } + + public static Map bean2Map(Object bean) { + Map result = new HashMap<>(); + Class aClass = bean.getClass(); + Field[] fields = aClass.getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + try { + result.put(field.getName(), field.get(bean)); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + return result; + } } diff --git a/core/backend/src/main/java/io/dataease/commons/utils/DatasetUtils.java b/core/backend/src/main/java/io/dataease/commons/utils/DatasetUtils.java index 35b97fd3bb..82f9007c8d 100644 --- a/core/backend/src/main/java/io/dataease/commons/utils/DatasetUtils.java +++ b/core/backend/src/main/java/io/dataease/commons/utils/DatasetUtils.java @@ -1,6 +1,6 @@ package io.dataease.commons.utils; -import io.dataease.dto.dataset.union.UnionDTO; +import io.dataease.plugins.common.dto.dataset.union.UnionDTO; import org.apache.commons.collections4.CollectionUtils; import java.util.List; diff --git a/core/backend/src/main/java/io/dataease/commons/utils/ExcelUtils.java b/core/backend/src/main/java/io/dataease/commons/utils/ExcelUtils.java index 9042a20b01..7e29baa017 100644 --- a/core/backend/src/main/java/io/dataease/commons/utils/ExcelUtils.java +++ b/core/backend/src/main/java/io/dataease/commons/utils/ExcelUtils.java @@ -1,23 +1,20 @@ package io.dataease.commons.utils; +import io.dataease.commons.model.excel.ExcelSheetModel; +import io.dataease.plugins.common.util.FileUtil; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; + import java.io.BufferedOutputStream; import java.io.File; - -import cn.hutool.core.io.FileUtil; -import io.dataease.commons.model.excel.ExcelSheetModel; - +import java.io.FileOutputStream; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; - -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; - public class ExcelUtils { private static final String suffix = ".xlsx"; @@ -78,10 +75,11 @@ public class ExcelUtils { folderPath += Thread.currentThread().getId() + "/"; if (!FileUtil.exist(folderPath)) { - FileUtil.mkdir(folderPath); + new File(folderPath).mkdirs(); } File result = new File(folderPath + realFileName.get()); - BufferedOutputStream outputStream = FileUtil.getOutputStream(result); + FileOutputStream fos = new FileOutputStream(result); + BufferedOutputStream outputStream = new BufferedOutputStream(fos); try { wb.write(outputStream); } catch (Exception e) { diff --git a/core/backend/src/main/java/io/dataease/commons/utils/ExcelXlsReader.java b/core/backend/src/main/java/io/dataease/commons/utils/ExcelXlsReader.java index 6b0a0dfd22..089c0dc378 100644 --- a/core/backend/src/main/java/io/dataease/commons/utils/ExcelXlsReader.java +++ b/core/backend/src/main/java/io/dataease/commons/utils/ExcelXlsReader.java @@ -1,6 +1,6 @@ package io.dataease.commons.utils; -import io.dataease.dto.dataset.ExcelSheetData; +import io.dataease.plugins.common.dto.dataset.ExcelSheetData; import io.dataease.i18n.Translator; import io.dataease.plugins.common.dto.datasource.TableField; import org.apache.poi.hssf.eventusermodel.*; @@ -331,6 +331,11 @@ public class ExcelXlsReader implements HSSFListener { if (flag && curRow != 0) { //该行不为空行且该行不是第一行,发送(第一行为列名,不需要) if (!totalSheets.stream().map(ExcelSheetData::getExcelLabel).collect(Collectors.toList()).contains(sheetName)) { + if(cellList.size() < fields.size()){ + for (int i = 0; i < fields.size() - cellList.size(); i++) { + cellList.add(""); + } + } ExcelSheetData excelSheetData = new ExcelSheetData(); excelSheetData.setData(new ArrayList<>(data)); excelSheetData.setExcelLabel(sheetName); @@ -370,6 +375,9 @@ public class ExcelXlsReader implements HSSFListener { private String checkType(String str, int thisColumn) { + if (str.length() > 19) { + return "TEXT"; + } String type = null; try { double d = Double.valueOf(str); diff --git a/core/backend/src/main/java/io/dataease/commons/utils/StaticResourceUtils.java b/core/backend/src/main/java/io/dataease/commons/utils/StaticResourceUtils.java index dabb38a92e..8945489f55 100644 --- a/core/backend/src/main/java/io/dataease/commons/utils/StaticResourceUtils.java +++ b/core/backend/src/main/java/io/dataease/commons/utils/StaticResourceUtils.java @@ -1,17 +1,17 @@ package io.dataease.commons.utils; -import static io.dataease.commons.constants.StaticResourceConstants.*; - -import cn.hutool.core.codec.Base64Encoder; import io.dataease.plugins.common.exception.DataEaseException; import org.apache.commons.lang3.StringUtils; import org.springframework.lang.NonNull; import org.springframework.util.Assert; +import org.springframework.util.Base64Utils; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import static io.dataease.commons.constants.StaticResourceConstants.*; + /** * Author: wangjiahao * Date: 2022/4/24 @@ -19,7 +19,7 @@ import java.io.InputStream; */ public class StaticResourceUtils { - private final static String FILE_BASE_PATH = USER_HOME+ FILE_SEPARATOR+UPLOAD_URL_PREFIX; + private final static String FILE_BASE_PATH = USER_HOME + FILE_SEPARATOR + UPLOAD_URL_PREFIX; private static final String FILE_NAME_REGEX_PATTERN = "^[A-Za-z0-9.-]{1,255}$"; @@ -69,12 +69,11 @@ public class StaticResourceUtils { } /** - * - * @param imgFile local storage path + * @param imgFile local storage path * @return */ public static String getImgFileToBase64(String imgFile) { - if(!validateStringFilenameUsingRegex(imgFile)){ + if (!validateStringFilenameUsingRegex(imgFile)) { DataEaseException.throwException("Illegal File Name"); } //Convert the picture file into byte array and encode it with Base64 @@ -82,7 +81,7 @@ public class StaticResourceUtils { byte[] buffer = null; //Read picture byte array try { - inputStream = new FileInputStream(FILE_BASE_PATH+FILE_SEPARATOR+imgFile); + inputStream = new FileInputStream(FILE_BASE_PATH + FILE_SEPARATOR + imgFile); int count = 0; while (count == 0) { count = inputStream.available(); @@ -91,9 +90,9 @@ public class StaticResourceUtils { inputStream.read(buffer); } catch (IOException e) { LogUtil.error(e); - }catch (Exception e){ + } catch (Exception e) { LogUtil.error(e); - }finally { + } finally { if (inputStream != null) { try { // Close InputStream @@ -104,10 +103,9 @@ public class StaticResourceUtils { } } // Encode byte array as Base64 - if(buffer!=null){ - - return Base64Encoder.encode(buffer); - }else{ + if (buffer != null) { + return Base64Utils.encodeToString(buffer); + } else { return null; } } diff --git a/core/backend/src/main/java/io/dataease/controller/dataset/DataSetTableFieldController.java b/core/backend/src/main/java/io/dataease/controller/dataset/DataSetTableFieldController.java index 235a6ad6be..6d9a734bf9 100644 --- a/core/backend/src/main/java/io/dataease/controller/dataset/DataSetTableFieldController.java +++ b/core/backend/src/main/java/io/dataease/controller/dataset/DataSetTableFieldController.java @@ -1,9 +1,9 @@ package io.dataease.controller.dataset; -import cn.hutool.core.collection.CollectionUtil; import com.auth0.jwt.JWT; import com.auth0.jwt.interfaces.DecodedJWT; import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import com.google.gson.Gson; import io.dataease.auth.annotation.DePermission; import io.dataease.auth.annotation.DePermissions; import io.dataease.auth.filter.F2CLinkFilter; @@ -12,6 +12,7 @@ import io.dataease.commons.constants.ResourceAuthLevel; import io.dataease.controller.request.dataset.DataSetTableRequest; import io.dataease.controller.request.dataset.MultFieldValuesRequest; import io.dataease.controller.response.DatasetTableField4Type; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; import io.dataease.dto.dataset.DatasetTableFieldDTO; import io.dataease.i18n.Translator; import io.dataease.plugins.common.base.domain.DatasetTable; @@ -21,7 +22,7 @@ import io.dataease.plugins.common.exception.DataEaseException; import io.dataease.plugins.datasource.entity.Dateformat; import io.dataease.plugins.datasource.query.QueryProvider; import io.dataease.plugins.xpack.auth.dto.request.ColumnPermissionItem; -import io.dataease.provider.ProviderFactory; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.service.dataset.DataSetFieldService; import io.dataease.service.dataset.DataSetTableFieldsService; import io.dataease.service.dataset.DataSetTableService; @@ -30,6 +31,7 @@ import io.dataease.service.datasource.DatasourceService; import io.dataease.service.engine.EngineService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -108,6 +110,8 @@ public class DataSetTableFieldController { DatasetTableField datasetTableField = DatasetTableField.builder().build(); datasetTableField.setTableId(tableId); datasetTableField.setGroupType("d"); + DatasetTable datasetTable = dataSetTableService.get(tableId); + DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class); List dimensionList = new ArrayList<>(); dataSetTableFieldsService.list(datasetTableField).forEach(o -> { DatasetTableFieldDTO datasetTableFieldDTO = new DatasetTableFieldDTO(); @@ -118,6 +122,9 @@ public class DataSetTableFieldController { deTypeCascader.add(datasetTableFieldDTO.getDateFormatType()); } datasetTableFieldDTO.setDeTypeCascader(deTypeCascader); + if (dataTableInfoDTO.isSetKey() && dataTableInfoDTO.getKeys().contains(datasetTableFieldDTO.getOriginName())){ + datasetTableFieldDTO.setKey(true); + } dimensionList.add(datasetTableFieldDTO); }); @@ -133,6 +140,9 @@ public class DataSetTableFieldController { deTypeCascader.add(datasetTableFieldDTO.getDateFormatType()); } datasetTableFieldDTO.setDeTypeCascader(deTypeCascader); + if (dataTableInfoDTO.isSetKey() && dataTableInfoDTO.getKeys().contains(datasetTableFieldDTO.getOriginName())){ + datasetTableFieldDTO.setKey(true); + } quotaList.add(datasetTableFieldDTO); }); @@ -187,6 +197,16 @@ public class DataSetTableFieldController { return dataSetTableFieldsService.save(datasetTableField); } + @DePermission(type = DePermissionType.DATASET, value = "tableId", level = ResourceAuthLevel.DATASET_LEVEL_MANAGE) + @ApiOperation("设置主键") + @PostMapping("saveKey") + public void saveKey(@RequestBody DatasetTableFieldDTO datasetTableField) throws Exception { + DatasetTable datasetTable = dataSetTableService.get(datasetTableField.getTableId()); + if (datasetTable.getMode() == 1) { + dataSetTableService.saveKey(datasetTable, datasetTableField); + } + } + @DePermissions(value = { @DePermission(type = DePermissionType.DATASET, level = ResourceAuthLevel.DATASET_LEVEL_MANAGE, paramIndex = 1) }) @@ -215,7 +235,7 @@ public class DataSetTableFieldController { List results = new ArrayList<>(); for (String fieldId : multFieldValuesRequest.getFieldIds()) { List fieldValues = dataSetFieldService.fieldValues(fieldId, multFieldValuesRequest.getSort(), multFieldValuesRequest.getUserId(), true, false, multFieldValuesRequest.getKeyword()); - if (CollectionUtil.isNotEmpty(fieldValues)) { + if (CollectionUtils.isNotEmpty(fieldValues)) { results.addAll(fieldValues); } @@ -248,7 +268,7 @@ public class DataSetTableFieldController { List results = new ArrayList<>(); for (String fieldId : multFieldValuesRequest.getFieldIds()) { List fieldValues = dataSetFieldService.fieldValues(fieldId, multFieldValuesRequest.getUserId(), false, true); - if (CollectionUtil.isNotEmpty(fieldValues)) { + if (CollectionUtils.isNotEmpty(fieldValues)) { results.addAll(fieldValues); } diff --git a/core/backend/src/main/java/io/dataease/controller/panel/server/LinkServer.java b/core/backend/src/main/java/io/dataease/controller/panel/server/LinkServer.java index e23d9981bf..30acef6006 100644 --- a/core/backend/src/main/java/io/dataease/controller/panel/server/LinkServer.java +++ b/core/backend/src/main/java/io/dataease/controller/panel/server/LinkServer.java @@ -5,16 +5,17 @@ import com.auth0.jwt.interfaces.DecodedJWT; import io.dataease.auth.filter.F2CLinkFilter; import io.dataease.commons.constants.SysLogConstants; import io.dataease.commons.utils.DeLogUtils; -import io.dataease.plugins.common.base.domain.PanelGroupWithBLOBs; -import io.dataease.plugins.common.base.domain.PanelLink; import io.dataease.controller.panel.api.LinkApi; import io.dataease.controller.request.chart.ChartExtRequest; import io.dataease.controller.request.panel.link.*; import io.dataease.dto.panel.link.GenerateDto; import io.dataease.dto.panel.link.ValidateDto; +import io.dataease.plugins.common.base.domain.PanelGroupWithBLOBs; +import io.dataease.plugins.common.base.domain.PanelLink; import io.dataease.service.chart.ChartViewService; import io.dataease.service.panel.PanelLinkService; import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -25,6 +26,7 @@ import org.springframework.web.context.request.ServletRequestAttributes; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.Map; @RestController @@ -65,22 +67,32 @@ public class LinkServer implements LinkApi { @Override public ValidateDto validate(@RequestBody LinkValidateRequest request) throws Exception { String link = request.getLink(); - link = URLDecoder.decode(link, "UTF-8"); + link = URLDecoder.decode(link, StandardCharsets.UTF_8); String json = panelLinkService.decryptParam(link); - + String[] jsonArray = json.split(","); + String uuid = null; + int len = jsonArray.length; + if (len > 1) { + uuid = jsonArray[1]; + } String user = request.getUser(); - user = URLDecoder.decode(user, "UTF-8"); + user = URLDecoder.decode(user, StandardCharsets.UTF_8); user = panelLinkService.decryptParam(user); ValidateDto dto = new ValidateDto(); dto.setUserId(user); - String resourceId = json; + String resourceId = jsonArray[0]; PanelLink one = panelLinkService.findOne(resourceId, Long.valueOf(user)); dto.setResourceId(resourceId); if (ObjectUtils.isEmpty(one)) { dto.setValid(false); return dto; } + String mappingUuid = panelLinkService.getMappingUuid(one); + if (!StringUtils.equals(uuid, mappingUuid)) { + dto.setValid(false); + return dto; + } dto.setValid(one.getValid()); dto.setEnablePwd(one.getEnablePwd()); dto.setPassPwd(panelLinkService.validateHeads(one)); @@ -94,8 +106,8 @@ public class LinkServer implements LinkApi { } @Override - public Object resourceDetail(@PathVariable String resourceId,@PathVariable String userId) { - return panelLinkService.resourceInfo(resourceId,userId); + public Object resourceDetail(@PathVariable String resourceId, @PathVariable String userId) { + return panelLinkService.resourceInfo(resourceId, userId); } @Override @@ -125,7 +137,7 @@ public class LinkServer implements LinkApi { operateType = SysLogConstants.OPERATE_TYPE.MB_VIEW; } if (ObjectUtils.isEmpty(userId)) return; - PanelGroupWithBLOBs panelGroupWithBLOBs = panelLinkService.resourceInfo(panelId,String.valueOf(userId)); + PanelGroupWithBLOBs panelGroupWithBLOBs = panelLinkService.resourceInfo(panelId, String.valueOf(userId)); String pid = panelGroupWithBLOBs.getPid(); DeLogUtils.save(operateType, SysLogConstants.SOURCE_TYPE.LINK, panelId, pid, userId, SysLogConstants.SOURCE_TYPE.USER); } diff --git a/core/backend/src/main/java/io/dataease/controller/request/dataset/DataSetTableRequest.java b/core/backend/src/main/java/io/dataease/controller/request/dataset/DataSetTableRequest.java index bb19bc50d6..f8ca7fe9b5 100644 --- a/core/backend/src/main/java/io/dataease/controller/request/dataset/DataSetTableRequest.java +++ b/core/backend/src/main/java/io/dataease/controller/request/dataset/DataSetTableRequest.java @@ -1,6 +1,6 @@ package io.dataease.controller.request.dataset; -import io.dataease.dto.dataset.ExcelSheetData; +import io.dataease.plugins.common.dto.dataset.ExcelSheetData; import io.dataease.plugins.common.base.domain.DatasetTable; import io.dataease.plugins.common.dto.datasource.TableField; import io.swagger.annotations.ApiModelProperty; diff --git a/core/backend/src/main/java/io/dataease/dto/chart/ChartViewDTO.java b/core/backend/src/main/java/io/dataease/dto/chart/ChartViewDTO.java index b0affa8cfd..635da3b188 100644 --- a/core/backend/src/main/java/io/dataease/dto/chart/ChartViewDTO.java +++ b/core/backend/src/main/java/io/dataease/dto/chart/ChartViewDTO.java @@ -46,5 +46,4 @@ public class ChartViewDTO extends ChartViewWithBLOBs { private long totalItems; private int datasetMode; private String datasourceType; - private Boolean aggregate; } diff --git a/core/backend/src/main/java/io/dataease/dto/dataset/DatasetTableFieldDTO.java b/core/backend/src/main/java/io/dataease/dto/dataset/DatasetTableFieldDTO.java index f1455ae21d..6ab3bba14a 100644 --- a/core/backend/src/main/java/io/dataease/dto/dataset/DatasetTableFieldDTO.java +++ b/core/backend/src/main/java/io/dataease/dto/dataset/DatasetTableFieldDTO.java @@ -9,4 +9,5 @@ import java.util.List; public class DatasetTableFieldDTO extends DatasetTableField { private String jsonPath; private List deTypeCascader; + private boolean isKey; } diff --git a/core/backend/src/main/java/io/dataease/dto/dataset/ExcelFileData.java b/core/backend/src/main/java/io/dataease/dto/dataset/ExcelFileData.java index e6527d0ca7..2b3454769b 100644 --- a/core/backend/src/main/java/io/dataease/dto/dataset/ExcelFileData.java +++ b/core/backend/src/main/java/io/dataease/dto/dataset/ExcelFileData.java @@ -1,5 +1,6 @@ package io.dataease.dto.dataset; +import io.dataease.plugins.common.dto.dataset.ExcelSheetData; import io.swagger.annotations.ApiModelProperty; import lombok.Data; diff --git a/core/backend/src/main/java/io/dataease/ext/ExtChartViewMapper.xml b/core/backend/src/main/java/io/dataease/ext/ExtChartViewMapper.xml index d7ab36aeab..79c8627399 100644 --- a/core/backend/src/main/java/io/dataease/ext/ExtChartViewMapper.xml +++ b/core/backend/src/main/java/io/dataease/ext/ExtChartViewMapper.xml @@ -309,7 +309,8 @@ `is_plugin`, `senior`, `data_from`, - `view_fields`) + `view_fields`, + `_aggregate`) SELECT #{newChartId}, GET_CHART_VIEW_COPY_NAME(#{oldChartId}, #{panelId}) as `name`, #{panelId}, @@ -338,7 +339,8 @@ `is_plugin`, `senior`, `data_from`, - `view_fields` + `view_fields`, + `_aggregate` FROM chart_view WHERE id = #{oldChartId} diff --git a/core/backend/src/main/java/io/dataease/ext/MobileDirMapper.xml b/core/backend/src/main/java/io/dataease/ext/MobileDirMapper.xml index f9e61ff465..5351063b1d 100644 --- a/core/backend/src/main/java/io/dataease/ext/MobileDirMapper.xml +++ b/core/backend/src/main/java/io/dataease/ext/MobileDirMapper.xml @@ -3,17 +3,15 @@ - - - - diff --git a/core/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java b/core/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java index 08e80276be..6e2489c1ca 100644 --- a/core/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java +++ b/core/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java @@ -1,6 +1,5 @@ package io.dataease.job.sechedule.strategy.impl; -import cn.hutool.core.io.FileUtil; import io.dataease.auth.entity.SysUserEntity; import io.dataease.auth.entity.TokenInfo; import io.dataease.auth.service.AuthUserService; @@ -16,6 +15,7 @@ import io.dataease.job.sechedule.strategy.TaskHandler; import io.dataease.plugins.common.base.domain.SysUserAssist; import io.dataease.plugins.common.entity.GlobalTaskEntity; import io.dataease.plugins.common.entity.GlobalTaskInstance; +import io.dataease.plugins.common.util.FileUtil; import io.dataease.plugins.common.util.SpringContextUtil; import io.dataease.plugins.xpack.dingtalk.dto.entity.DingtalkMsgResult; import io.dataease.plugins.xpack.dingtalk.service.DingtalkXpackService; diff --git a/core/backend/src/main/java/io/dataease/map/service/MapService.java b/core/backend/src/main/java/io/dataease/map/service/MapService.java index a4cdc01bb0..47dd134363 100644 --- a/core/backend/src/main/java/io/dataease/map/service/MapService.java +++ b/core/backend/src/main/java/io/dataease/map/service/MapService.java @@ -1,7 +1,6 @@ package io.dataease.map.service; -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.io.FileUtil; + import io.dataease.commons.utils.CommonBeanFactory; import io.dataease.listener.util.CacheUtils; import io.dataease.map.dto.entity.AreaEntity; @@ -10,6 +9,8 @@ import io.dataease.map.utils.MapUtils; import io.dataease.plugins.common.base.domain.AreaMappingGlobal; import io.dataease.plugins.common.base.domain.AreaMappingGlobalExample; import io.dataease.plugins.common.exception.DataEaseException; +import io.dataease.plugins.common.util.FileUtil; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.Cacheable; @@ -50,7 +51,7 @@ public class MapService { return areaEntity.getChildren(); } - if (CollectionUtil.isNotEmpty(areaEntity.getChildren())) { + if (CollectionUtils.isNotEmpty(areaEntity.getChildren())) { List areaEntities = entitiesByPid(areaEntity.getChildren(), pid); if (null != areaEntities) { return areaEntities; @@ -96,7 +97,7 @@ public class MapService { Set sets = nodes.stream().flatMap(node -> codesByNode(node, pLevel).stream()).collect(Collectors.toSet()); sets.forEach(code -> { String countryCode = code.substring(0, 3); - String path = rootGeoPath + "/full/" + countryCode + "/" + code +"_full.json"; + String path = rootGeoPath + "/full/" + countryCode + "/" + code + "_full.json"; if (FileUtil.exist(path)) { FileUtil.del(path); } @@ -107,19 +108,19 @@ public class MapService { Set sets = new TreeSet<>(); if (pLevel == 2) { - if(StringUtils.isNotBlank(node.getProvinceCode())) sets.add(node.getProvinceCode()); - if(StringUtils.isNotBlank(node.getCityCode())) sets.add(node.getCityCode()); - if(StringUtils.isNotBlank(node.getCountyCode())) sets.add(node.getCountyCode()); + if (StringUtils.isNotBlank(node.getProvinceCode())) sets.add(node.getProvinceCode()); + if (StringUtils.isNotBlank(node.getCityCode())) sets.add(node.getCityCode()); + if (StringUtils.isNotBlank(node.getCountyCode())) sets.add(node.getCountyCode()); } else if (pLevel == 3) { - if(StringUtils.isNotBlank(node.getCityCode())) sets.add(node.getCityCode()); - if(StringUtils.isNotBlank(node.getCountyCode())) sets.add(node.getCountyCode()); + if (StringUtils.isNotBlank(node.getCityCode())) sets.add(node.getCityCode()); + if (StringUtils.isNotBlank(node.getCountyCode())) sets.add(node.getCountyCode()); } else if (pLevel == 4) { - if(StringUtils.isNotBlank(node.getCountyCode())) sets.add(node.getCountyCode()); + if (StringUtils.isNotBlank(node.getCountyCode())) sets.add(node.getCountyCode()); } else { - if(StringUtils.isNotBlank(node.getCountryCode())) sets.add(node.getCountryCode()); - if(StringUtils.isNotBlank(node.getProvinceCode())) sets.add(node.getProvinceCode()); - if(StringUtils.isNotBlank(node.getCityCode())) sets.add(node.getCityCode()); - if(StringUtils.isNotBlank(node.getCountyCode())) sets.add(node.getCountyCode()); + if (StringUtils.isNotBlank(node.getCountryCode())) sets.add(node.getCountryCode()); + if (StringUtils.isNotBlank(node.getProvinceCode())) sets.add(node.getProvinceCode()); + if (StringUtils.isNotBlank(node.getCityCode())) sets.add(node.getCityCode()); + if (StringUtils.isNotBlank(node.getCountyCode())) sets.add(node.getCountyCode()); } return sets; } @@ -132,7 +133,7 @@ public class MapService { AreaMappingGlobalExample example = new AreaMappingGlobalExample(); AreaMappingGlobal curRoot = new AreaMappingGlobal(); List nodes = null; - if(pLevel == 0) { + if (pLevel == 0) { nodes = MapUtils.selectByExample(example); MapUtils.deleteByExample(example); delFileByNodes(nodes, pLevel); @@ -147,7 +148,7 @@ public class MapService { MapUtils.deleteByExample(example); example.clear(); example.createCriteria().andCountryCodeEqualTo(pCode); - if (!MapUtils.exampleExist(example) && CollectionUtil.isNotEmpty(nodes)) { + if (!MapUtils.exampleExist(example) && CollectionUtils.isNotEmpty(nodes)) { AreaMappingGlobal template = nodes.get(0); curRoot.setCountryCode(template.getCountryCode()); curRoot.setCountryName(template.getCountryName()); @@ -163,7 +164,7 @@ public class MapService { example.clear(); example.createCriteria().andProvinceCodeEqualTo(pCode); - if (!MapUtils.exampleExist(example) && CollectionUtil.isNotEmpty(nodes)) { + if (!MapUtils.exampleExist(example) && CollectionUtils.isNotEmpty(nodes)) { AreaMappingGlobal template = nodes.get(0); curRoot.setCountryCode(template.getCountryCode()); curRoot.setCountryName(template.getCountryName()); @@ -180,7 +181,7 @@ public class MapService { example.clear(); example.createCriteria().andProvinceCodeEqualTo(pCode); - if (!MapUtils.exampleExist(example) && CollectionUtil.isNotEmpty(nodes)) { + if (!MapUtils.exampleExist(example) && CollectionUtils.isNotEmpty(nodes)) { AreaMappingGlobal template = nodes.get(0); curRoot.setCountryCode(template.getCountryCode()); curRoot.setCountryName(template.getCountryName()); @@ -205,14 +206,15 @@ public class MapService { DataEaseException.throwException("only json file supported"); } } + @Transactional - public void saveMapNode(MapNodeRequest request, MultipartFile file) throws Exception{ + public void saveMapNode(MapNodeRequest request, MultipartFile file) throws Exception { validateFile(file); String pCode = request.getPcode(); Integer plevel = request.getPlevel(); String code = request.getCode(); - if(StringUtils.isBlank(code)) { + if (StringUtils.isBlank(code)) { String newAreaCode = generateAreaCode(pCode); request.setCode(newAreaCode); } @@ -222,19 +224,17 @@ public class MapService { if (plevel == 1) { example.createCriteria().andCountryCodeEqualTo(code); - } - else if (plevel == 2) { + } else if (plevel == 2) { example.createCriteria().andCountryCodeEqualTo(pCode).andProvinceCodeEqualTo(code); - } - else if (plevel == 3) { + } else if (plevel == 3) { example.createCriteria().andProvinceCodeEqualTo(pCode).andCityCodeEqualTo(code); - }else if (plevel == 4) { + } else if (plevel == 4) { example.createCriteria().andCityCodeEqualTo(pCode).andCountyCodeEqualTo(code); } else { DataEaseException.throwException("只支持3级行政区"); } List lists = MapUtils.selectByExample(example); - if (CollectionUtil.isNotEmpty(lists)) { + if (CollectionUtils.isNotEmpty(lists)) { DataEaseException.throwException("区域代码已存在"); } @@ -243,27 +243,26 @@ public class MapService { if (plevel == 1) { pExample.createCriteria().andCountryCodeIsNull().andProvinceCodeIsNull().andCityCodeIsNull().andCountyCodeIsNull(); List existLists = MapUtils.selectByExample(pExample); - if (CollectionUtil.isNotEmpty(existLists)) { + if (CollectionUtils.isNotEmpty(existLists)) { AreaMappingGlobal node = existLists.get(0); node.setCountryCode(code); node.setCountryName(request.getName()); MapUtils.update(node); - }else { + } else { AreaMappingGlobal node = new AreaMappingGlobal(); node.setCountryCode(code); node.setCountryName(request.getName()); MapUtils.addNode(node); } - } - else if (plevel == 2) { + } else if (plevel == 2) { pExample.createCriteria().andCountryCodeEqualTo(pCode).andProvinceCodeIsNull().andCityCodeIsNull().andCountyCodeIsNull(); List existLists = MapUtils.selectByExample(pExample); - if (CollectionUtil.isNotEmpty(existLists)) { + if (CollectionUtils.isNotEmpty(existLists)) { AreaMappingGlobal node = existLists.get(0); node.setProvinceCode(code); node.setProvinceName(request.getName()); MapUtils.update(node); - }else { + } else { AreaMappingGlobal country = country(pCode); AreaMappingGlobal node = new AreaMappingGlobal(); node.setCountryCode(pCode); @@ -272,16 +271,15 @@ public class MapService { node.setProvinceName(request.getName()); MapUtils.addNode(node); } - } - else if (plevel == 3) { + } else if (plevel == 3) { pExample.createCriteria().andProvinceCodeEqualTo(pCode).andCityCodeIsNull(); List existLists = MapUtils.selectByExample(pExample); - if (CollectionUtil.isNotEmpty(existLists)) { + if (CollectionUtils.isNotEmpty(existLists)) { AreaMappingGlobal node = existLists.get(0); node.setCityCode(code); node.setCityName(request.getName()); MapUtils.update(node); - }else { + } else { AreaMappingGlobal province = province(pCode); AreaMappingGlobal node = new AreaMappingGlobal(); node.setCountryCode(province.getCountryCode()); @@ -295,12 +293,12 @@ public class MapService { } else if (plevel == 4) { pExample.createCriteria().andCountryCodeEqualTo(pCode).andCountyCodeIsNull(); List existLists = MapUtils.selectByExample(pExample); - if (CollectionUtil.isNotEmpty(existLists)) { + if (CollectionUtils.isNotEmpty(existLists)) { AreaMappingGlobal node = existLists.get(0); node.setCountyCode(code); node.setCountyName(request.getName()); MapUtils.update(node); - }else { + } else { AreaMappingGlobal city = city(pCode); AreaMappingGlobal node = new AreaMappingGlobal(); node.setCountryCode(city.getCountryCode()); @@ -320,7 +318,7 @@ public class MapService { CacheUtils.removeAll("sys_map_areas_global"); } - public void uploadMapFile(MultipartFile file, String areaCode) throws Exception{ + public void uploadMapFile(MultipartFile file, String areaCode) throws Exception { String countryCode = areaCode.substring(0, 3); String dir = rootGeoPath + "full/" + countryCode + "/"; @@ -329,7 +327,7 @@ public class MapService { fileDir.mkdirs(); } - String targetPath = dir + areaCode+"_full.json"; + String targetPath = dir + areaCode + "_full.json"; File target = new File(targetPath); file.transferTo(target); } diff --git a/core/backend/src/main/java/io/dataease/map/service/MapTransferService.java b/core/backend/src/main/java/io/dataease/map/service/MapTransferService.java index 4faebd8bc6..f6d25e2285 100644 --- a/core/backend/src/main/java/io/dataease/map/service/MapTransferService.java +++ b/core/backend/src/main/java/io/dataease/map/service/MapTransferService.java @@ -1,12 +1,13 @@ package io.dataease.map.service; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.util.ArrayUtil; + import com.google.gson.Gson; import io.dataease.plugins.common.base.domain.ChartView; import io.dataease.plugins.common.base.domain.ChartViewExample; import io.dataease.plugins.common.base.domain.ChartViewWithBLOBs; import io.dataease.plugins.common.base.mapper.ChartViewMapper; +import io.dataease.plugins.common.util.FileUtil; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; @@ -72,7 +73,7 @@ public class MapTransferService { String chinaRootPath = geoPath + FULL_KEY + FILE_SEPARATOR; File chinaRootDir = new File(chinaRootPath); File[] files = chinaRootDir.listFiles(); - if (ArrayUtil.isEmpty(files)) return; + if (ArrayUtils.isEmpty(files)) return; Map> listMap = Arrays.stream(files).filter(FileUtil::isFile).collect(Collectors.groupingBy(this::fileType)); if (ObjectUtils.isEmpty(listMap)) return; moveFiles(listMap, BORDER_KEY); diff --git a/core/backend/src/main/java/io/dataease/map/utils/HttpUtils.java b/core/backend/src/main/java/io/dataease/map/utils/HttpUtils.java deleted file mode 100644 index 52f26f38b2..0000000000 --- a/core/backend/src/main/java/io/dataease/map/utils/HttpUtils.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.dataease.map.utils; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.http.HttpUtil; -import cn.hutool.json.JSONUtil; -import io.dataease.map.dto.request.MapRequest; -import io.dataease.map.dto.response.MapResponse; - - -import java.util.Map; - -public class HttpUtils { - - private static final String url = "https://restapi.amap.com/v3/config/district"; - - - private static final String key = "a5d10d5d05a3a0868cec67c4d66cf025"; - private static final String extensions = "all"; - private static final Integer subdistrict = 0; - - - - public static MapResponse get(MapRequest request){ - request.setKey(key); - request.setExtensions(extensions); - request.setSubdistrict(subdistrict); - Map param = BeanUtil.beanToMap(request); - - String s = HttpUtil.get(url, param); - MapResponse mapResponse = JSONUtil.toBean(s, MapResponse.class); - return mapResponse; - } - - public static MapResponse get(String code) { - MapRequest request = MapRequest.builder().keywords(code).build(); - return get(request); - } - - -} diff --git a/core/backend/src/main/java/io/dataease/map/utils/MapUtils.java b/core/backend/src/main/java/io/dataease/map/utils/MapUtils.java index 4a5f664956..6621cd46e5 100644 --- a/core/backend/src/main/java/io/dataease/map/utils/MapUtils.java +++ b/core/backend/src/main/java/io/dataease/map/utils/MapUtils.java @@ -1,6 +1,5 @@ package io.dataease.map.utils; -import cn.hutool.core.util.StrUtil; import io.dataease.map.dto.entity.AreaEntity; import io.dataease.map.dto.entity.Constants; import io.dataease.plugins.common.base.domain.AreaMapping; @@ -84,7 +83,7 @@ public class MapUtils { String city_code = map.getCityCode(); String county_code = map.getCountyCode(); // 是否是跨级直辖 - Boolean isCrossLevel = StrUtil.equals(province_code, city_code) && !StrUtil.equals(province_code, "156710000"); + Boolean isCrossLevel = StringUtils.equals(province_code, city_code) && !StringUtils.equals(province_code, "156710000"); if (!countryMap.containsKey(country_code)) { String country_name = map.getCountryName(); @@ -154,7 +153,7 @@ public class MapUtils { county_code = formatCode(county_code); // 是否是跨级直辖 - Boolean isCrossLevel = StrUtil.equals(province_code, city_code) && !StrUtil.equals(province_code, "710000"); + Boolean isCrossLevel = StringUtils.equals(province_code, city_code) && !StringUtils.equals(province_code, "710000"); if (!provinceMap.containsKey(province_code)) { String province_name = map.get(Constants.PROVINCE_NAME).toString(); diff --git a/core/backend/src/main/java/io/dataease/plugins/server/CasServer.java b/core/backend/src/main/java/io/dataease/plugins/server/CasServer.java index 087ec8fb15..54fb4798c2 100644 --- a/core/backend/src/main/java/io/dataease/plugins/server/CasServer.java +++ b/core/backend/src/main/java/io/dataease/plugins/server/CasServer.java @@ -1,6 +1,5 @@ package io.dataease.plugins.server; -import cn.hutool.core.util.RandomUtil; import io.dataease.auth.entity.SysUserEntity; import io.dataease.auth.entity.TokenInfo; import io.dataease.auth.service.AuthUserService; @@ -14,6 +13,7 @@ import io.dataease.i18n.Translator; import io.dataease.service.sys.SysUserService; import io.dataease.service.system.SystemParameterService; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.jasig.cas.client.authentication.AttributePrincipal; import org.jasig.cas.client.util.AssertionHolder; @@ -67,7 +67,7 @@ public class CasServer { sysUserEntity = authUserService.getCasUserByName(name); } if (null == sysUserEntity) { - String s = RandomUtil.randomString(6); + String s = RandomStringUtils.randomAlphanumeric(6); String email = s + "@xxx.com"; sysUserService.validateCasUser(name); sysUserService.saveCASUser(name, email); diff --git a/core/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java b/core/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java index e287985468..991568c301 100644 --- a/core/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java +++ b/core/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java @@ -1,7 +1,6 @@ package io.dataease.plugins.server; -import cn.hutool.core.collection.CollectionUtil; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import io.dataease.auth.annotation.DeLog; @@ -30,6 +29,7 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; +import org.apache.commons.collections4.CollectionUtils; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -190,7 +190,7 @@ public class XDeptServer { @PostMapping("/unBindUser") public void unBindUser(@RequestBody XpackDeptBindRequest request) { DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); - if (CollectionUtil.isEmpty(request.getUserIds())) { + if (CollectionUtils.isEmpty(request.getUserIds())) { DataEaseException.throwException("userIds can not be empty"); } request.getUserIds().forEach(userId -> { diff --git a/core/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java b/core/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java index 32ec9d0352..f5569f2062 100644 --- a/core/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java +++ b/core/backend/src/main/java/io/dataease/plugins/server/XEmailTaskServer.java @@ -1,7 +1,5 @@ package io.dataease.plugins.server; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.util.ArrayUtil; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import io.dataease.auth.annotation.DeRateLimiter; @@ -22,8 +20,11 @@ import io.dataease.plugins.xpack.email.dto.response.XpackTaskInstanceDTO; import io.dataease.plugins.xpack.email.service.EmailXpackService; import io.dataease.service.ScheduleService; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ByteArrayResource; @@ -35,10 +36,10 @@ import org.springframework.web.util.HtmlUtils; import springfox.documentation.annotations.ApiIgnore; import javax.annotation.Resource; -import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; -import java.io.*; +import java.io.OutputStream; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -179,7 +180,7 @@ public class XEmailTaskServer { Object object = future.get(); if (ObjectUtils.isNotEmpty(object)) { bytes = (byte[]) object; - if (ArrayUtil.isNotEmpty(bytes)) { + if (ArrayUtils.isNotEmpty(bytes)) { String fileName = request.getPanelId() + ".pdf"; ByteArrayResource bar = new ByteArrayResource(bytes); HttpHeaders headers = new HttpHeaders(); @@ -217,7 +218,7 @@ public class XEmailTaskServer { Object object = future.get(); if (ObjectUtils.isNotEmpty(object)) { bytes = (byte[]) object; - if (ArrayUtil.isNotEmpty(bytes)) { + if (ArrayUtils.isNotEmpty(bytes)) { String fileName = request.getPanelId() + ".jpeg"; ByteArrayResource bar = new ByteArrayResource(bytes); HttpHeaders headers = new HttpHeaders(); @@ -340,35 +341,52 @@ public class XEmailTaskServer { Pager> listPager = instancesGrid(0, 0, request); List instanceDTOS = listPager.getListObject(); ExcelSheetModel excelSheetModel = excelSheetModel(instanceDTOS); - List sheetModels = new ArrayList<>(); - sheetModels.add(excelSheetModel); - File file = ExcelUtils.exportExcel(sheetModels, null, null); - InputStream inputStream = new FileInputStream(file); HttpServletResponse response = ServletUtils.response(); + OutputStream outputStream = response.getOutputStream(); try { - String filename = file.getName(); - response.reset(); - response.addHeader("Access-Control-Allow-Origin", "*"); - response.setContentType("application/octet-stream;charset=UTF-8"); - response.addHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(filename, "UTF-8")); - ServletOutputStream outputStream = response.getOutputStream(); - byte[] buff = new byte[1024]; - BufferedInputStream bis = null; - // 读取文件 - bis = new BufferedInputStream(inputStream); - int i = bis.read(buff); - while (i != -1) { - outputStream.write(buff, 0, buff.length); - outputStream.flush(); - i = bis.read(buff); + Workbook wb = new SXSSFWorkbook(); + Sheet detailsSheet = wb.createSheet(excelSheetModel.getSheetName()); + CellStyle cellStyle = wb.createCellStyle(); + Font font = wb.createFont(); + //设置字体大小 + font.setFontHeightInPoints((short) 12); + //设置字体加粗 + font.setBold(true); + //给字体设置样式 + cellStyle.setFont(font); + //设置单元格背景颜色 + cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + //设置单元格填充样式(使用纯色背景颜色填充) + cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + List> details = null; + if (CollectionUtils.isNotEmpty(details = excelSheetModel.getData())) { + details.add(0, excelSheetModel.getHeads()); + for (int i = 0; i < details.size(); i++) { + Row row = detailsSheet.createRow(i); + List rowData = details.get(i); + if (rowData != null) { + for (int j = 0; j < rowData.size(); j++) { + Cell cell = row.createCell(j); + cell.setCellValue(rowData.get(j)); + if (i == 0) {// 头部 + detailsSheet.setColumnWidth(j, 255 * 20); + cell.setCellStyle(cellStyle); + } + } + } + } } + + response.setContentType("application/vnd.ms-excel"); + //文件名称 + String fileName = excelSheetModel.getSheetName(); + String encodeFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8); + response.setHeader("Content-disposition", "attachment;filename=" + encodeFileName + ".xlsx"); + wb.write(outputStream); + outputStream.flush(); outputStream.close(); - inputStream.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } finally { - if (file.exists()) - FileUtil.del(file); + } catch (Exception e) { + DataEaseException.throwException(e); } } diff --git a/core/backend/src/main/java/io/dataease/provider/DDLProviderImpl.java b/core/backend/src/main/java/io/dataease/provider/DDLProviderImpl.java index 4c42a3ce7b..1bf8afda8d 100644 --- a/core/backend/src/main/java/io/dataease/provider/DDLProviderImpl.java +++ b/core/backend/src/main/java/io/dataease/provider/DDLProviderImpl.java @@ -2,6 +2,8 @@ package io.dataease.provider; import io.dataease.plugins.common.base.domain.DatasetTableField; import io.dataease.plugins.common.base.domain.Datasource; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; +import io.dataease.plugins.datasource.provider.DDLProvider; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; @@ -30,7 +32,7 @@ public class DDLProviderImpl extends DDLProvider { } @Override - public String createTableSql(String name, List datasetTableFields, Datasource engine, String version) { + public String createTableSql(DataTableInfoDTO dataTableInfoDTO, String name, List datasetTableFields, Datasource engine, String version) { return null; } diff --git a/core/backend/src/main/java/io/dataease/provider/datasource/ApiProvider.java b/core/backend/src/main/java/io/dataease/provider/datasource/ApiProvider.java index 439c538a0b..65ac06f5ff 100644 --- a/core/backend/src/main/java/io/dataease/provider/datasource/ApiProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/datasource/ApiProvider.java @@ -11,15 +11,17 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.gson.JsonObject; +import io.dataease.commons.utils.CommonBeanFactory; import io.dataease.dto.dataset.DatasetTableFieldDTO; import io.dataease.plugins.common.dto.datasource.TableDesc; import io.dataease.plugins.common.dto.datasource.TableField; +import io.dataease.plugins.common.exception.DataEaseException; import io.dataease.plugins.common.request.datasource.DatasourceRequest; import io.dataease.plugins.datasource.entity.Status; import io.dataease.plugins.datasource.provider.Provider; import com.jayway.jsonpath.JsonPath; -import io.dataease.commons.utils.HttpClientConfig; -import io.dataease.commons.utils.HttpClientUtil; +import io.dataease.plugins.common.util.HttpClientConfig; +import io.dataease.plugins.common.util.HttpClientUtil; import io.dataease.controller.request.datasource.ApiDefinition; import io.dataease.controller.request.datasource.ApiDefinitionRequest; @@ -245,9 +247,9 @@ public class ApiProvider extends Provider { rootPath = "$[*]"; JsonNode jsonArray = null; try { - jsonArray = new ObjectMapper().readTree(response); + jsonArray = CommonBeanFactory.getBean(ObjectMapper.class).readTree(response); } catch (Exception e) { - e.printStackTrace(); + DataEaseException.throwException(e.getMessage()); } for (Object o : jsonArray) { handleStr(apiDefinition, o.toString(), fields, rootPath); diff --git a/core/backend/src/main/java/io/dataease/provider/datasource/EsProvider.java b/core/backend/src/main/java/io/dataease/provider/datasource/EsProvider.java index c4518f15a8..a9a8e2d567 100644 --- a/core/backend/src/main/java/io/dataease/provider/datasource/EsProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/datasource/EsProvider.java @@ -2,8 +2,8 @@ package io.dataease.provider.datasource; import com.google.gson.Gson; import com.google.gson.JsonParser; -import io.dataease.commons.utils.HttpClientConfig; -import io.dataease.commons.utils.HttpClientUtil; +import io.dataease.plugins.common.util.HttpClientConfig; +import io.dataease.plugins.common.util.HttpClientUtil; import io.dataease.controller.request.datasource.es.EsResponse; import io.dataease.controller.request.datasource.es.Request; import io.dataease.controller.request.datasource.es.RequestWithCursor; diff --git a/core/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java b/core/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java index 5238f3d664..d65859da8e 100644 --- a/core/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java @@ -5,7 +5,6 @@ import com.alibaba.druid.pool.DruidPooledConnection; import com.google.gson.Gson; import io.dataease.commons.utils.LogUtil; import io.dataease.dto.datasource.*; - import io.dataease.i18n.Translator; import io.dataease.plugins.common.base.domain.Datasource; import io.dataease.plugins.common.base.domain.DeDriver; @@ -21,8 +20,8 @@ import io.dataease.plugins.datasource.entity.JdbcConfiguration; import io.dataease.plugins.datasource.entity.Status; import io.dataease.plugins.datasource.provider.DefaultJdbcProvider; import io.dataease.plugins.datasource.provider.ExtendedJdbcClassLoader; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.plugins.datasource.query.QueryProvider; -import io.dataease.provider.ProviderFactory; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -105,6 +104,42 @@ public class JdbcProvider extends DefaultJdbcProvider { OracleConfiguration oracleConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), OracleConfiguration.class); schemaPattern = oracleConfiguration.getSchema(); } + + //获取主键 + ResultSet primaryKeys = databaseMetaData.getPrimaryKeys(null, schemaPattern, tableNamePattern); + Set primaryKeySet = new HashSet<>(); + while (primaryKeys.next()) { + String tableName = primaryKeys.getString("TABLE_NAME"); + String database; + String schema = primaryKeys.getString("TABLE_SCHEM"); + if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name()) || datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.ck.name()) + || datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.impala.name())) { + database = primaryKeys.getString("TABLE_SCHEM"); + } else { + database = primaryKeys.getString("TABLE_CAT"); + } + //获取主键的名称 + if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name())) { + if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDsSchema(datasourceRequest))) { + primaryKeySet.add(primaryKeys.getString("COLUMN_NAME")); + } + } else if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name())) { + if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest)) && schema.equalsIgnoreCase(getDsSchema(datasourceRequest))) { + primaryKeySet.add(primaryKeys.getString("COLUMN_NAME")); + } + } else { + if (database != null) { + if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) { + primaryKeySet.add(primaryKeys.getString("COLUMN_NAME")); + } + } else { + if (tableName.equals(datasourceRequest.getTable())) { + primaryKeySet.add(primaryKeys.getString("COLUMN_NAME")); + } + } + } + } + ResultSet resultSet = databaseMetaData.getColumns(null, schemaPattern, tableNamePattern, "%"); while (resultSet.next()) { String tableName = resultSet.getString("TABLE_NAME"); @@ -118,23 +153,23 @@ public class JdbcProvider extends DefaultJdbcProvider { } if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.pg.name())) { if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDsSchema(datasourceRequest))) { - TableField tableField = getTableFiled(resultSet, datasourceRequest); + TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet); list.add(tableField); } } else if (datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name())) { if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest)) && schema.equalsIgnoreCase(getDsSchema(datasourceRequest))) { - TableField tableField = getTableFiled(resultSet, datasourceRequest); + TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet); list.add(tableField); } } else { if (database != null) { if (tableName.equals(datasourceRequest.getTable()) && database.equalsIgnoreCase(getDatabase(datasourceRequest))) { - TableField tableField = getTableFiled(resultSet, datasourceRequest); + TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet); list.add(tableField); } } else { if (tableName.equals(datasourceRequest.getTable())) { - TableField tableField = getTableFiled(resultSet, datasourceRequest); + TableField tableField = getTableFiled(resultSet, datasourceRequest, primaryKeySet); list.add(tableField); } } @@ -156,7 +191,7 @@ public class JdbcProvider extends DefaultJdbcProvider { return list; } - private TableField getTableFiled(ResultSet resultSet, DatasourceRequest datasourceRequest) throws SQLException { + private TableField getTableFiled(ResultSet resultSet, DatasourceRequest datasourceRequest, Set primaryKeySet) throws SQLException { TableField tableField = new TableField(); String colName = resultSet.getString("COLUMN_NAME"); tableField.setFieldName(colName); @@ -197,6 +232,14 @@ public class JdbcProvider extends DefaultJdbcProvider { if (StringUtils.isNotEmpty(tableField.getFieldType()) && tableField.getFieldType().equalsIgnoreCase("DECIMAL")) { tableField.setAccuracy(Integer.valueOf(resultSet.getString("DECIMAL_DIGITS"))); } + + if (primaryKeySet.contains(colName)) { + tableField.setPrimaryKey(true); + } + if (StringUtils.equalsIgnoreCase(resultSet.getString("IS_NULLABLE"), "NO")) { + tableField.setNotNull(true); + } + return tableField; } @@ -295,7 +338,7 @@ public class JdbcProvider extends DefaultJdbcProvider { break; case Types.NUMERIC: BigDecimal bigDecimal = rs.getBigDecimal(j + 1); - row[j] = bigDecimal == null ? null: bigDecimal.toString(); + row[j] = bigDecimal == null ? null : bigDecimal.toString(); break; default: if (metaData.getColumnTypeName(j + 1).toLowerCase().equalsIgnoreCase("blob")) { @@ -538,7 +581,7 @@ public class JdbcProvider extends DefaultJdbcProvider { driverClassName = defaultDriver; jdbcClassLoader = extendedJdbcClassLoader; for (DataSourceType value : SpringContextUtil.getApplicationContext().getBeansOfType(DataSourceType.class).values()) { - if(value.getType().equalsIgnoreCase(datasourceRequest.getDatasource().getType())){ + if (value.getType().equalsIgnoreCase(datasourceRequest.getDatasource().getType())) { surpportVersions = value.getSurpportVersions(); } } @@ -563,10 +606,11 @@ public class JdbcProvider extends DefaultJdbcProvider { Thread.currentThread().setContextClassLoader(classLoader); } - if(StringUtils.isNotEmpty(surpportVersions) && surpportVersions.split(",").length > 0){ - if(! Arrays.asList(surpportVersions.split(",")).contains(String.valueOf(conn.getMetaData().getDatabaseMajorVersion()))){ + if (StringUtils.isNotEmpty(surpportVersions) && surpportVersions.split(",").length > 0) { + if (!Arrays.asList(surpportVersions.split(",")).contains(String.valueOf(conn.getMetaData().getDatabaseMajorVersion()))) { DataEaseException.throwException("当前驱动不支持此版本!"); - }; + } + ; } return conn; } @@ -698,7 +742,7 @@ public class JdbcProvider extends DefaultJdbcProvider { throw new Exception(Translator.get("i18n_schema_is_empty")); } return "select table_name, owner, comments from all_tab_comments where owner='" + oracleConfiguration.getSchema() + "' AND table_type = 'TABLE'"; - case pg: + case pg: PgConfiguration pgConfiguration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), PgConfiguration.class); if (StringUtils.isEmpty(pgConfiguration.getSchema())) { throw new Exception(Translator.get("i18n_schema_is_empty")); @@ -821,58 +865,58 @@ public class JdbcProvider extends DefaultJdbcProvider { case StarRocks: MysqlConfiguration mysqlConfiguration = new Gson().fromJson(datasource.getConfiguration(), MysqlConfiguration.class); mysqlConfiguration.getJdbc(); - if(!mysqlConfiguration.getDataBase().matches("^[ 0-9a-zA-Z_.-]{1,}$")){ + if (!mysqlConfiguration.getDataBase().matches("^[ 0-9a-zA-Z_.-]{1,}$")) { throw new Exception("Invalid database name"); } break; case redshift: RedshiftConfiguration redshiftConfiguration = new Gson().fromJson(datasource.getConfiguration(), RedshiftConfiguration.class); - if(redshiftConfiguration.getDataBase().length() > 64 || redshiftConfiguration.getDataBase().length() < 1){ + if (redshiftConfiguration.getDataBase().length() > 64 || redshiftConfiguration.getDataBase().length() < 1) { throw new Exception("Invalid database name"); } - if(!redshiftConfiguration.getDataBase().matches("^[a-z][a-z0-9_+.@-]*$")){ + if (!redshiftConfiguration.getDataBase().matches("^[a-z][a-z0-9_+.@-]*$")) { throw new Exception("Invalid database name"); } break; case sqlServer: SqlServerConfiguration sqlServerConfiguration = new Gson().fromJson(datasource.getConfiguration(), SqlServerConfiguration.class); - if(!sqlServerConfiguration.getDataBase().matches("^[0-9a-zA-Z-_.\u4E00-\u9FA5\u8FBD-\u9FBB\uFA0E-\uFA29\u2e80-\u9fff]{1,}$")){ + if (!sqlServerConfiguration.getDataBase().matches("^[0-9a-zA-Z-_.\u4E00-\u9FA5\u8FBD-\u9FBB\uFA0E-\uFA29\u2e80-\u9fff]{1,}$")) { throw new Exception("Invalid database name"); } break; case pg: PgConfiguration pgConfiguration = new Gson().fromJson(datasource.getConfiguration(), PgConfiguration.class); - if(!pgConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){ + if (!pgConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) { throw new Exception("Invalid database name"); } break; case oracle: OracleConfiguration oracleConfiguration = new Gson().fromJson(datasource.getConfiguration(), OracleConfiguration.class); - if(!oracleConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$") && !oracleConfiguration.getConnectionType().equalsIgnoreCase("serviceName")){ + if (!oracleConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$") && !oracleConfiguration.getConnectionType().equalsIgnoreCase("serviceName")) { throw new Exception("Invalid database name"); } break; case mongo: MongodbConfiguration mongodbConfiguration = new Gson().fromJson(datasource.getConfiguration(), MongodbConfiguration.class); - if(!mongodbConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){ + if (!mongodbConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) { throw new Exception("Invalid database name"); } break; case impala: ImpalaConfiguration impalaConfiguration = new Gson().fromJson(datasource.getConfiguration(), ImpalaConfiguration.class); - if(!impalaConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){ + if (!impalaConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) { throw new Exception("Invalid database name"); } break; case hive: HiveConfiguration hiveConfiguration = new Gson().fromJson(datasource.getConfiguration(), HiveConfiguration.class); - if(!hiveConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){ + if (!hiveConfiguration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) { throw new Exception("Invalid database name"); } break; case db2: Db2Configuration db2Configuration = new Gson().fromJson(datasource.getConfiguration(), Db2Configuration.class); - if(!db2Configuration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")){ + if (!db2Configuration.getDataBase().matches("^[0-9a-zA-Z_]{1,}$")) { throw new Exception("Invalid database name"); } break; diff --git a/core/backend/src/main/java/io/dataease/provider/engine/doris/DorisDDLProvider.java b/core/backend/src/main/java/io/dataease/provider/engine/doris/DorisDDLProvider.java index 3fd4ca4802..79378adcc3 100644 --- a/core/backend/src/main/java/io/dataease/provider/engine/doris/DorisDDLProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/engine/doris/DorisDDLProvider.java @@ -1,14 +1,18 @@ package io.dataease.provider.engine.doris; import com.google.gson.Gson; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; import io.dataease.plugins.common.base.domain.DatasetTableField; import io.dataease.plugins.common.base.domain.Datasource; import io.dataease.commons.utils.TableUtils; import io.dataease.dto.datasource.DorisConfiguration; import io.dataease.provider.DDLProviderImpl; +import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * @Author gin @@ -18,8 +22,8 @@ import java.util.List; public class DorisDDLProvider extends DDLProviderImpl { private static final String creatTableSql = "CREATE TABLE IF NOT EXISTS `TABLE_NAME`" + "Column_Fields" + - "UNIQUE KEY(dataease_uuid)\n" + - "DISTRIBUTED BY HASH(dataease_uuid) BUCKETS BUCKETS_NUM\n" + + "UNIQUE KEY(`UNIQUE_KEY`)\n" + + "DISTRIBUTED BY HASH(`DISTRIBUTED_BY_HASH`) BUCKETS BUCKETS_NUM\n" + "PROPERTIES(\"replication_num\" = \"ReplicationNum\");"; @Override @@ -38,22 +42,55 @@ public class DorisDDLProvider extends DDLProviderImpl { } @Override - public String replaceTable(String name){ - return "ALTER TABLE DORIS_TABLE REPLACE WITH TABLE DORIS_TMP_TABLE PROPERTIES('swap' = 'false')" - .replace("DORIS_TABLE", name).replace("DORIS_TMP_TABLE", TableUtils.tmpName(name)); + public String replaceTable(String name) { + return "ALTER TABLE DORIS_TABLE REPLACE WITH TABLE DORIS_TMP_TABLE PROPERTIES('swap' = 'false')" + .replace("DORIS_TABLE", name).replace("DORIS_TMP_TABLE", TableUtils.tmpName(name)); } @Override - public String createTableSql(String tableName, List datasetTableFields, Datasource engine, String version) { + public String createTableSql(DataTableInfoDTO dataTableInfoDTO, String tableName, List datasetTableFields, Datasource engine, String version) { DorisConfiguration dorisConfiguration = new Gson().fromJson(engine.getConfiguration(), DorisConfiguration.class); - String dorisTableColumnSql = createDorisTableColumnSql(datasetTableFields, version); - return creatTableSql.replace("TABLE_NAME", tableName).replace("Column_Fields", dorisTableColumnSql) + + String sql = creatTableSql.replace("TABLE_NAME", tableName) .replace("BUCKETS_NUM", dorisConfiguration.getBucketNum().toString()) .replace("ReplicationNum", dorisConfiguration.getReplicationNum().toString()); + if (dataTableInfoDTO.isSetKey() && CollectionUtils.isNotEmpty(dataTableInfoDTO.getKeys())) { + List keys = new ArrayList<>(); + for (int i = 0; i < dataTableInfoDTO.getKeys().size(); i++) { + for (DatasetTableField datasetTableField : datasetTableFields) { + if (datasetTableField.getOriginName().equalsIgnoreCase(dataTableInfoDTO.getKeys().get(i))) { + keys.add(datasetTableField.getDataeaseName()); + } + } + } + sql = sql.replace("`UNIQUE_KEY`", "`" + String.join("`, `", keys) + "`") + .replace("DISTRIBUTED_BY_HASH", keys.get(0)).replace("Column_Fields", createDorisTableColumnSql(datasetTableFields, version, keys)); + } else { + if (!datasetTableFields.stream().map(DatasetTableField::getDataeaseName).collect(Collectors.toList()).contains("dataease_uuid")) { + List tempList = new ArrayList<>(); + DatasetTableField datasetTableField = new DatasetTableField(); + datasetTableField.setDeExtractType(0); + datasetTableField.setType("String"); + datasetTableField.setDeType(0); + datasetTableField.setDataeaseName("dataease_uuid"); + datasetTableField.setOriginName("dataease_uuid"); + datasetTableField.setSize(50); + tempList.add(0, datasetTableField); + for (int i = 0; i < datasetTableFields.size(); i++) { + tempList.add(datasetTableFields.get(i)); + } + sql = sql.replace("UNIQUE_KEY", "dataease_uuid").replace("DISTRIBUTED_BY_HASH", "dataease_uuid").replace("Column_Fields", createDorisTableColumnSql(tempList, version, null)); + } else { + sql = sql.replace("UNIQUE_KEY", "dataease_uuid").replace("DISTRIBUTED_BY_HASH", "dataease_uuid").replace("Column_Fields", createDorisTableColumnSql(datasetTableFields, version, null)); + } + + } + + return sql; } - private String createDorisTableColumnSql(final List datasetTableFields, String version) { - StringBuilder Column_Fields = new StringBuilder("dataease_uuid varchar(50), `"); + private String createDorisTableColumnSql(final List datasetTableFields, String version, List keys) { + StringBuilder Column_Fields = new StringBuilder("`"); for (DatasetTableField datasetTableField : datasetTableFields) { Column_Fields.append(datasetTableField.getDataeaseName()).append("` "); Integer size = datasetTableField.getSize() * 3; @@ -62,26 +99,30 @@ public class DorisDDLProvider extends DDLProviderImpl { } switch (datasetTableField.getDeExtractType()) { case 0: - Column_Fields.append("STRING".replace("length", String.valueOf(size))).append(",`"); + if (size <= 65533 || (keys != null && keys.contains(datasetTableField.getDataeaseName()))) { + Column_Fields.append("VARCHAR(length)".replace("length", String.valueOf(size))).append(",`"); + } else { + Column_Fields.append("STRING".replace("length", String.valueOf(size))).append(",`"); + } break; case 1: - size = size < 50? 50 : size; - Column_Fields.append("STRING".replace("length", String.valueOf(size))).append(",`"); + Column_Fields.append("DATETIME").append(",`"); break; case 2: Column_Fields.append("bigint").append(",`"); break; case 3: - if(datasetTableField.getType().equalsIgnoreCase("DECIMAL") && datasetTableField.getAccuracy() != 0){ - if(Integer.valueOf(version.split("5.7.")[1]) < 99){ - Column_Fields.append("DECIMAL(" + datasetTableField.getSize() + "," + datasetTableField.getAccuracy() + ")").append(",`"); - }else { - Column_Fields.append("DecimalV3(" + datasetTableField.getSize() + "," + datasetTableField.getAccuracy() + ")").append(",`"); - } + if (datasetTableField.getType().equalsIgnoreCase("DECIMAL") && datasetTableField.getAccuracy() != 0) { + if (Integer.valueOf(version.split("5.7.")[1]) < 99) { + Integer p = datasetTableField.getAccuracy() > 9 ? 9 : datasetTableField.getAccuracy(); + Column_Fields.append("DECIMAL(" + datasetTableField.getSize() + "," + p + ")").append(",`"); + } else { + Column_Fields.append("DecimalV3(" + datasetTableField.getSize() + "," + datasetTableField.getAccuracy() + ")").append(",`"); + } - }else { - Column_Fields.append("DOUBLE").append(",`"); - } + } else { + Column_Fields.append("DECIMAL(27,8)").append(",`"); + } break; case 4: Column_Fields.append("TINYINT(length)".replace("length", String.valueOf(size))).append(",`"); diff --git a/core/backend/src/main/java/io/dataease/provider/engine/mysql/MysqlDDLProvider.java b/core/backend/src/main/java/io/dataease/provider/engine/mysql/MysqlDDLProvider.java index f1418aa5c4..61790adbf3 100644 --- a/core/backend/src/main/java/io/dataease/provider/engine/mysql/MysqlDDLProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/engine/mysql/MysqlDDLProvider.java @@ -1,5 +1,6 @@ package io.dataease.provider.engine.mysql; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; import io.dataease.plugins.common.base.domain.DatasetTableField; import io.dataease.plugins.common.base.domain.Datasource; import io.dataease.commons.utils.TableUtils; @@ -71,7 +72,7 @@ public class MysqlDDLProvider extends DDLProviderImpl { } @Override - public String createTableSql(String tableName, List datasetTableFields, Datasource engine, String version) { + public String createTableSql(DataTableInfoDTO dataTableInfoDTO, String tableName, List datasetTableFields, Datasource engine, String version) { String dorisTableColumnSql = createDorisTableColumnSql(datasetTableFields); return creatTableSql.replace("TABLE_NAME", tableName).replace("Column_Fields", dorisTableColumnSql); } diff --git a/core/backend/src/main/java/io/dataease/provider/query/es/EsQueryProvider.java b/core/backend/src/main/java/io/dataease/provider/query/es/EsQueryProvider.java index cf415b8b5e..fec8ac0107 100644 --- a/core/backend/src/main/java/io/dataease/provider/query/es/EsQueryProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/query/es/EsQueryProvider.java @@ -1620,7 +1620,7 @@ public class EsQueryProvider extends QueryProvider { "{\"dateformat\": \"yyyy/MMdd\"},\n" + "{\"dateformat\": \"yyyy-MM-dd\"},\n" + "{\"dateformat\": \"yyyyMMdd HH:mm:ss\"},\n" + - "{\"dateformat\": \"yyyy/MMdd HH:mm:ss\"},\n" + + "{\"dateformat\": \"yyyy/MM/dd HH:mm:ss\"},\n" + "{\"dateformat\": \"yyyy-MM-dd HH:mm:ss\"}\n" + "]", Dateformat.class); } diff --git a/core/backend/src/main/java/io/dataease/provider/query/mysql/MysqlQueryProvider.java b/core/backend/src/main/java/io/dataease/provider/query/mysql/MysqlQueryProvider.java index 6fa4e26026..50b3ffe3a8 100644 --- a/core/backend/src/main/java/io/dataease/provider/query/mysql/MysqlQueryProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/query/mysql/MysqlQueryProvider.java @@ -70,6 +70,8 @@ public class MysqlQueryProvider extends QueryProvider { case "TIME": case "YEAR": case "DATETIME": + case "DATEV2": + case "DATETIMEV2": case "TIMESTAMP": return 1;// 时间 case "INT": diff --git a/core/backend/src/main/java/io/dataease/provider/query/sqlserver/SqlserverQueryProvider.java b/core/backend/src/main/java/io/dataease/provider/query/sqlserver/SqlserverQueryProvider.java index 8021fe0c21..a8ef351f45 100644 --- a/core/backend/src/main/java/io/dataease/provider/query/sqlserver/SqlserverQueryProvider.java +++ b/core/backend/src/main/java/io/dataease/provider/query/sqlserver/SqlserverQueryProvider.java @@ -73,6 +73,7 @@ public class SqlserverQueryProvider extends QueryProvider { case "DATETIME": case "DATETIME2": case "DATETIMEOFFSET": + case "SMALLDATETIME": return DeTypeConstants.DE_TIME;// 时间 case "INT": case "MEDIUMINT": @@ -84,6 +85,7 @@ public class SqlserverQueryProvider extends QueryProvider { case "DOUBLE": case "DECIMAL": case "MONEY": + case "REAL": case "NUMERIC": return DeTypeConstants.DE_FLOAT;// 浮点 case "BIT": @@ -437,10 +439,10 @@ public class SqlserverQueryProvider extends QueryProvider { @Override public String getSQLTableInfo(String table, List xAxis, FilterTreeObj fieldCustomFilter, List rowPermissionsTree, List extFilterRequestList, Datasource ds, ChartViewWithBLOBs view) { - return originTableInfo(table, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, true); + return originTableInfo(table, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, true, false); } - public String originTableInfo(String table, List xAxis, FilterTreeObj fieldCustomFilter, List rowPermissionsTree, List extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, boolean needOrder, boolean needResultCount) { + public String originTableInfo(String table, List xAxis, FilterTreeObj fieldCustomFilter, List rowPermissionsTree, List extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, boolean needOrder, boolean needResultCount, boolean ignoreOrder) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(SqlServerSQLConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) @@ -494,13 +496,15 @@ public class SqlserverQueryProvider extends QueryProvider { groups.addAll(xFields); // 外层再次套sql List orders = new ArrayList<>(); - orders.addAll(xOrders); - if (needOrder && CollectionUtils.isEmpty(xOrders)) { - orders.add(SQLObj.builder() - .orderField(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, 0)) - .orderAlias(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, 0)) - .orderDirection("ASC") - .build()); + if (!ignoreOrder) { + orders.addAll(xOrders); + if (needOrder && CollectionUtils.isEmpty(xOrders)) { + orders.add(SQLObj.builder() + .orderField(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, 0)) + .orderAlias(String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, 0)) + .orderDirection("ASC") + .build()); + } } STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE); @@ -526,8 +530,8 @@ public class SqlserverQueryProvider extends QueryProvider { return st.render(); } - public String originSQLAsTmpTableInfo(String sql, List xAxis, FilterTreeObj fieldCustomFilter, List rowPermissionsTree, List extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, boolean needOrder) { - return originTableInfo("(" + sqlFix(sql) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, null, view, needOrder, true); + public String originSQLAsTmpTableInfo(String sql, List xAxis, FilterTreeObj fieldCustomFilter, List rowPermissionsTree, List extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, boolean needOrder, boolean ignoreOrder) { + return originTableInfo("(" + sqlFix(sql) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, null, view, needOrder, true, ignoreOrder); } public String getSQLWithPage(boolean isTable, String sql, List xAxis, FilterTreeObj fieldCustomFilter, List rowPermissionsTree, List extFilterRequestList, Datasource ds, ChartViewWithBLOBs view, PageInfo pageInfo) { @@ -541,9 +545,9 @@ public class SqlserverQueryProvider extends QueryProvider { boolean isPage = (pageInfo.getGoPage() != null && pageInfo.getPageSize() != null); String limit = (isPage ? " OFFSET " + (pageInfo.getGoPage() - 1) * pageInfo.getPageSize() + " ROW FETCH NEXT " + pageInfo.getPageSize() + " ROW ONLY " : ""); if (isTable) { - return originTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, !isPage) + limit; + return originTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, !isPage, false) + limit; } else { - return originTableInfo("(" + sqlFix(sql) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, !isPage) + limit; + return originTableInfo("(" + sqlFix(sql) + ")", xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, true, !isPage, false) + limit; } } } @@ -1788,9 +1792,9 @@ public class SqlserverQueryProvider extends QueryProvider { @Override public String getResultCount(boolean isTable, String sql, List xAxis, FilterTreeObj fieldCustomFilter, List rowPermissionsTree, List extFilterRequestList, Datasource ds, ChartViewWithBLOBs view) { if (isTable) { - return "SELECT COUNT(*) AS count from (" + originTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, false, true) + ") COUNT_TEMP"; + return "SELECT COUNT(*) AS count from (" + originTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, false, true, true) + ") COUNT_TEMP"; } else { - return "SELECT COUNT(*) AS count from (" + originSQLAsTmpTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, false) + ") COUNT_TEMP"; + return "SELECT COUNT(*) AS count from (" + originSQLAsTmpTableInfo(sql, xAxis, fieldCustomFilter, rowPermissionsTree, extFilterRequestList, ds, view, false, true) + ") COUNT_TEMP"; } } } diff --git a/core/backend/src/main/java/io/dataease/service/chart/ChartViewService.java b/core/backend/src/main/java/io/dataease/service/chart/ChartViewService.java index 0716e5355f..e55fde67d7 100644 --- a/core/backend/src/main/java/io/dataease/service/chart/ChartViewService.java +++ b/core/backend/src/main/java/io/dataease/service/chart/ChartViewService.java @@ -1,6 +1,5 @@ package io.dataease.service.chart; -import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; @@ -19,7 +18,6 @@ import io.dataease.controller.response.DataSetDetail; import io.dataease.dto.chart.*; import io.dataease.dto.dataset.DataSetTableDTO; import io.dataease.dto.dataset.DataSetTableUnionDTO; -import io.dataease.dto.dataset.DataTableInfoDTO; import io.dataease.ext.ExtChartGroupMapper; import io.dataease.ext.ExtChartViewMapper; import io.dataease.ext.ExtPanelGroupExtendDataMapper; @@ -36,6 +34,7 @@ import io.dataease.plugins.common.constants.datasource.SQLConstants; import io.dataease.plugins.common.dto.chart.ChartFieldCompareDTO; import io.dataease.plugins.common.dto.chart.ChartFieldCustomFilterDTO; import io.dataease.plugins.common.dto.chart.ChartViewFieldDTO; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; import io.dataease.plugins.common.dto.dataset.SqlVariableDetails; import io.dataease.plugins.common.exception.DataEaseException; import io.dataease.plugins.common.request.chart.ChartExtFilterRequest; @@ -45,12 +44,12 @@ import io.dataease.plugins.common.request.permission.DataSetRowPermissionsTreeDT import io.dataease.plugins.common.util.SpringContextUtil; import io.dataease.plugins.datasource.entity.PageInfo; import io.dataease.plugins.datasource.provider.Provider; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.plugins.datasource.query.QueryProvider; import io.dataease.plugins.view.entity.*; import io.dataease.plugins.view.entity.filter.PluginFilterTreeObj; import io.dataease.plugins.view.service.ViewPluginService; import io.dataease.plugins.xpack.auth.dto.request.ColumnPermissionItem; -import io.dataease.provider.ProviderFactory; import io.dataease.provider.query.SQLUtils; import io.dataease.service.chart.util.ChartDataBuild; import io.dataease.service.dataset.*; @@ -66,6 +65,7 @@ import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.Assert; import javax.annotation.Resource; import java.lang.reflect.Type; @@ -1058,9 +1058,10 @@ public class ChartViewService { }); xAxis.addAll(xAxisExtList); } + fieldMap.put("xAxis", xAxis); + fieldMap.put("xAxisExt", xAxisExt); fieldMap.put("extStack", extStack); fieldMap.put("extBubble", extBubble); - fieldMap.put("xAxis", xAxis); fieldMap.put("yAxis", yAxis); PluginViewParam pluginViewParam = buildPluginParam(fieldMap, fieldCustomFilter, extFilterList, ds, table, view, rowPermissionsTree, chartExtRequest); String sql = pluginViewSql(pluginViewParam, view); diff --git a/core/backend/src/main/java/io/dataease/service/chart/ViewPluginBaseServiceImpl.java b/core/backend/src/main/java/io/dataease/service/chart/ViewPluginBaseServiceImpl.java index 3e3800ca44..75a6d3e469 100644 --- a/core/backend/src/main/java/io/dataease/service/chart/ViewPluginBaseServiceImpl.java +++ b/core/backend/src/main/java/io/dataease/service/chart/ViewPluginBaseServiceImpl.java @@ -1,13 +1,12 @@ package io.dataease.service.chart; -import cn.hutool.core.util.ReflectUtil; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import io.dataease.commons.model.PluginViewSetImpl; import io.dataease.commons.utils.TableUtils; import io.dataease.controller.request.chart.ChartExtRequest; import io.dataease.dto.dataset.DataSetTableUnionDTO; -import io.dataease.dto.dataset.DataTableInfoDTO; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; import io.dataease.plugins.common.base.domain.ChartViewWithBLOBs; import io.dataease.plugins.common.base.domain.DatasetTableField; import io.dataease.plugins.common.base.domain.Datasource; @@ -25,7 +24,7 @@ import io.dataease.plugins.datasource.query.QueryProvider; import io.dataease.plugins.view.entity.*; import io.dataease.plugins.view.entity.filter.PluginFilterTreeObj; import io.dataease.plugins.view.service.ViewPluginBaseService; -import io.dataease.provider.ProviderFactory; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.service.dataset.DataSetTableService; import io.dataease.service.dataset.DataSetTableUnionService; import org.apache.commons.lang3.ObjectUtils; @@ -33,6 +32,7 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import org.springframework.util.ReflectionUtils; import javax.annotation.Resource; import java.lang.reflect.Method; @@ -232,7 +232,7 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService { Method method = declaredMethods[i]; if (StringUtils.equals(method.getName(), methodName)) { method.setAccessible(true); - return ReflectUtil.invoke(queryProvider, method, args); + return ReflectionUtils.invokeMethod(method, queryProvider, args); } } return null; @@ -240,11 +240,10 @@ public class ViewPluginBaseServiceImpl implements ViewPluginBaseService { private Object execProviderMethod(QueryProvider queryProvider, String methodName, Object... args) { Method[] declaredMethods = queryProvider.getClass().getDeclaredMethods(); - for (int i = 0; i < declaredMethods.length; i++) { - Method method = declaredMethods[i]; + for (Method method : declaredMethods) { if (StringUtils.equals(method.getName(), methodName)) { method.setAccessible(true); - return ReflectUtil.invoke(queryProvider, method, args); + return ReflectionUtils.invokeMethod(method, queryProvider, args); } } return null; diff --git a/core/backend/src/main/java/io/dataease/service/chart/build/NumberRangeBuild.java b/core/backend/src/main/java/io/dataease/service/chart/build/NumberRangeBuild.java index abcec34ca9..b3075f70b3 100644 --- a/core/backend/src/main/java/io/dataease/service/chart/build/NumberRangeBuild.java +++ b/core/backend/src/main/java/io/dataease/service/chart/build/NumberRangeBuild.java @@ -1,16 +1,13 @@ package io.dataease.service.chart.build; -import cn.hutool.core.collection.CollectionUtil; import io.dataease.dto.chart.FilterParamTO; import io.dataease.service.chart.FilterBuildTemplate; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; @Service("numberRangeWidget") public class NumberRangeBuild extends FilterBuildTemplate { diff --git a/core/backend/src/main/java/io/dataease/service/chart/build/SelectBuild.java b/core/backend/src/main/java/io/dataease/service/chart/build/SelectBuild.java index 079b4253b8..c5662fefd5 100644 --- a/core/backend/src/main/java/io/dataease/service/chart/build/SelectBuild.java +++ b/core/backend/src/main/java/io/dataease/service/chart/build/SelectBuild.java @@ -1,6 +1,6 @@ package io.dataease.service.chart.build; -import cn.hutool.core.bean.BeanUtil; +import io.dataease.commons.utils.BeanUtils; import io.dataease.commons.utils.LogUtil; import io.dataease.controller.dataset.DataSetTableFieldController; import io.dataease.controller.request.dataset.MultFieldValuesRequest; @@ -74,7 +74,7 @@ public class SelectBuild extends FilterBuildTemplate { MultFieldValuesRequest request = new MultFieldValuesRequest(); request.setFieldIds(Arrays.stream(attrs.get("fieldId").toString().split(",")).collect(Collectors.toList())); if (ObjectUtils.isNotEmpty(attrs.get("sort"))) { - DeSortDTO sort = BeanUtil.copyProperties(attrs.get("sort"), DeSortDTO.class); + DeSortDTO sort = BeanUtils.copyBean(new DeSortDTO(), attrs.get("sort")); request.setSort(sort); } List list = null; diff --git a/core/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java b/core/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java index a214d94f28..012d1eac9a 100644 --- a/core/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java +++ b/core/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java @@ -1,12 +1,12 @@ package io.dataease.service.chart.util; -import cn.hutool.core.util.ArrayUtil; import io.dataease.controller.request.chart.ChartDrillRequest; import io.dataease.dto.chart.*; import io.dataease.plugins.common.base.domain.ChartViewWithBLOBs; import io.dataease.plugins.common.dto.chart.ChartViewFieldDTO; import io.dataease.plugins.xpack.auth.dto.request.ColumnPermissionItem; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; @@ -1049,7 +1049,7 @@ public class ChartDataBuild { Map map = transTableNormal(fields, null, data, desensitizationList); List> tableRow = (List>) map.get("tableRow"); final int xEndIndex = detailIndex; - Map> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> ArrayUtil.join(ArrayUtil.sub(item, 0, xEndIndex), "-de-", "(", ")"))); + Map> groupDataList = detailData.stream().collect(Collectors.groupingBy(item -> StringUtils.join(ArrayUtils.subarray(item, 0, xEndIndex), "-de-", "(", ")"))); tableRow.forEach(row -> { String key = xAxis.stream().map(x -> String.format(format, row.get(x.getDataeaseName()).toString())).collect(Collectors.joining("-de-")); @@ -1087,6 +1087,7 @@ public class ChartDataBuild { List fields = new ArrayList<>(); List yfields = new ArrayList<>(); if (CollectionUtils.isNotEmpty(fieldMap.get("xAxis"))) fields.addAll(fieldMap.get("xAxis")); + if (CollectionUtils.isNotEmpty(fieldMap.get("xAxisExt"))) fields.addAll(fieldMap.get("xAxisExt")); for (Map.Entry> entry : fieldMap.entrySet()) { if (StringUtils.equalsAny(entry.getKey(), keys)) { @@ -1130,7 +1131,7 @@ public class ChartDataBuild { if (StringUtils.isEmpty(originStr) || originStr.length() <= columnPermissionItem.getDesensitizationRule().getM() + columnPermissionItem.getDesensitizationRule().getN() + 1) { desensitizationStr = String.join("", Collections.nCopies(columnPermissionItem.getDesensitizationRule().getM(), "X")) + "***" + String.join("", Collections.nCopies(columnPermissionItem.getDesensitizationRule().getN(), "X")); } else { - desensitizationStr = StringUtils.substring(originStr, 0, columnPermissionItem.getDesensitizationRule().getM()) + "***" + StringUtils.substring(originStr, originStr.length() - columnPermissionItem.getDesensitizationRule().getN() - 1, originStr.length() - 1); + desensitizationStr = StringUtils.substring(originStr, 0, columnPermissionItem.getDesensitizationRule().getM()) + "***" + StringUtils.substring(originStr, originStr.length() - columnPermissionItem.getDesensitizationRule().getN() - 1, originStr.length()); } break; case RetainMToN: diff --git a/core/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java b/core/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java index 2a04280eb9..4e66473900 100644 --- a/core/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java +++ b/core/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java @@ -26,9 +26,12 @@ import io.dataease.controller.request.dataset.DataSetTaskRequest; import io.dataease.controller.response.DataSetDetail; import io.dataease.dto.SysLogDTO; import io.dataease.dto.dataset.*; -import io.dataease.dto.dataset.union.UnionDTO; -import io.dataease.dto.dataset.union.UnionItemDTO; -import io.dataease.dto.dataset.union.UnionParamDTO; +import io.dataease.plugins.common.dto.dataset.DataTableInfoCustomUnion; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; +import io.dataease.plugins.common.dto.dataset.ExcelSheetData; +import io.dataease.plugins.common.dto.dataset.union.UnionDTO; +import io.dataease.plugins.common.dto.dataset.union.UnionItemDTO; +import io.dataease.plugins.common.dto.dataset.union.UnionParamDTO; import io.dataease.ext.ExtDataSetGroupMapper; import io.dataease.ext.ExtDataSetTableMapper; import io.dataease.ext.UtilMapper; @@ -50,8 +53,8 @@ import io.dataease.plugins.common.util.ClassloaderResponsity; import io.dataease.plugins.datasource.provider.Provider; import io.dataease.plugins.datasource.query.QueryProvider; import io.dataease.plugins.xpack.auth.dto.request.ColumnPermissionItem; -import io.dataease.provider.DDLProvider; -import io.dataease.provider.ProviderFactory; +import io.dataease.plugins.datasource.provider.DDLProvider; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.provider.datasource.JdbcProvider; import io.dataease.service.chart.util.ChartDataBuild; import io.dataease.service.datasource.DatasourceService; @@ -179,6 +182,25 @@ public class DataSetTableService { return list; } + public void saveKey(DatasetTable datasetTable, DatasetTableFieldDTO datasetTableField) { + DataTableInfoDTO dt = new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class); + if (datasetTableField.isKey()) { + dt.getKeys().add(datasetTableField.getOriginName()); + } else { + dt.getKeys().remove(datasetTableField.getOriginName()); + } + if (CollectionUtils.isNotEmpty(dt.getKeys())) { + dt.setSetKey(true); + } else { + dt.setSetKey(false); + } + DatasetTable record = new DatasetTable(); + record.setInfo(new Gson().toJson(dt)); + DatasetTableExample example = new DatasetTableExample(); + example.createCriteria().andIdEqualTo(datasetTable.getId()); + datasetTableMapper.updateByExampleSelective(record, example); + } + private void extractData(DataSetTableRequest datasetTable) throws Exception { if (datasetTable.getMode() == 1 && StringUtils.isNotEmpty(datasetTable.getSyncType()) && datasetTable.getSyncType().equalsIgnoreCase("sync_now")) { DataSetTaskRequest dataSetTaskRequest = new DataSetTaskRequest(); @@ -234,6 +256,8 @@ public class DataSetTableService { }); DataTableInfoDTO info = new DataTableInfoDTO(); info.setExcelSheetDataList(excelSheetDataList); + info.setKeys(excelSheetDataList.get(0).getKeys()); + info.setSetKey(excelSheetDataList.get(0).isSetKey()); sheetTable.setInfo(new Gson().toJson(info)); datasetTableMapper.insert(sheetTable); sysAuthService.copyAuth(sheetTable.getId(), SysAuthConstants.AUTH_SOURCE_TYPE_DATASET); @@ -263,6 +287,8 @@ public class DataSetTableService { excelSheetDataList.add(sheet); DataTableInfoDTO info = new DataTableInfoDTO(); info.setExcelSheetDataList(excelSheetDataList); + info.setKeys(sheet.getKeys()); + info.setSetKey(sheet.isSetKey()); sheetTable.setInfo(new Gson().toJson(info)); datasetTableMapper.insert(sheetTable); sysAuthService.copyAuth(sheetTable.getId(), SysAuthConstants.AUTH_SOURCE_TYPE_DATASET); @@ -296,6 +322,8 @@ public class DataSetTableService { excelSheetDataList.add(sheet); } DataTableInfoDTO info = new DataTableInfoDTO(); + info.setKeys(datasetTable.getSheets().get(0).getKeys()); + info.setSetKey(datasetTable.getSheets().get(0).isSetKey()); info.setExcelSheetDataList(excelSheetDataList); datasetTable.setInfo(new Gson().toJson(info)); datasetTableMapper.updateByPrimaryKeySelective(datasetTable); @@ -1033,7 +1061,7 @@ public class DataSetTableService { } public String removeVariables(final String sql, String dsType) throws Exception { - String tmpSql = sql; + String tmpSql = sql.replaceAll("(?m)^\\s*$[\n\r]{0,}", ""); Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(tmpSql); boolean hasVariables = false; @@ -1275,6 +1303,15 @@ public class DataSetTableService { List fields = result.get("fieldList"); String[] fieldArray = fields.stream().map(TableField::getFieldName).toArray(String[]::new); checkIsRepeat(fieldArray); + + if (!realData && dataTableInfo.isSetKey()) { + for (String key : dataTableInfo.getKeys()) { + if (!fields.stream().map(TableField::getFieldName).collect(Collectors.toList()).contains(key)) { + DataEaseException.throwException(Translator.get("i18n_dont_contain_key") + key); + } + } + } + List> jsonArray = new ArrayList<>(); if (CollectionUtils.isNotEmpty(data)) { jsonArray = data.stream().map(ele -> { @@ -2739,7 +2776,7 @@ public class DataSetTableService { @Override public void visit(InExpression inExpression) { - if (inExpression.getRightExpression() != null && hasVariable(inExpression.getRightExpression().toString()) && inExpression.getRightExpression() instanceof ParenthesedExpressionList) { + if (inExpression.getRightExpression() != null && hasVariable(inExpression.getRightExpression().toString()) && !(inExpression.getRightExpression() instanceof ParenthesedSelect)) { stringBuilder.append(SubstitutedSql); return; } @@ -2929,6 +2966,9 @@ public class DataSetTableService { } private String cellType(String value) { + if (value.length() > 19) { + return "TEXT"; + } try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf.parse(value); diff --git a/core/backend/src/main/java/io/dataease/service/dataset/DataSetTableTaskLogService.java b/core/backend/src/main/java/io/dataease/service/dataset/DataSetTableTaskLogService.java index a56910fa00..8a4c17f48d 100644 --- a/core/backend/src/main/java/io/dataease/service/dataset/DataSetTableTaskLogService.java +++ b/core/backend/src/main/java/io/dataease/service/dataset/DataSetTableTaskLogService.java @@ -1,6 +1,5 @@ package io.dataease.service.dataset; -import cn.hutool.core.date.DateUtil; import io.dataease.commons.constants.ParamConstants; import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.ServletUtils; @@ -14,6 +13,7 @@ import io.dataease.plugins.common.base.domain.DatasetTableTaskLogExample; import io.dataease.plugins.common.base.mapper.DatasetTableTaskLogMapper; import io.dataease.plugins.common.base.mapper.DatasetTableTaskMapper; import io.dataease.plugins.common.exception.DataEaseException; +import io.dataease.plugins.common.util.GlobalDateUtils; import io.dataease.service.system.SystemParameterService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -79,8 +79,12 @@ public class DataSetTableTaskLogService { String[] row = new String[5]; row[0] = item.getName(); row[1] = item.getDatasetName(); - row[2] = DateUtil.formatDateTime(new Date(item.getStartTime())); - row[3] = item.getEndTime() != null ? DateUtil.formatDateTime(new Date(item.getEndTime())) : ""; + try { + row[2] = GlobalDateUtils.getTimeString(item.getStartTime()); + row[3] = item.getEndTime() != null ? GlobalDateUtils.getTimeString(item.getEndTime()) : ""; + } catch (Exception e) { + throw new RuntimeException(e); + } row[4] = Translator.get("I18N_TASK_LOG_" + item.getStatus().toUpperCase()); return row; }).collect(Collectors.toList()); diff --git a/core/backend/src/main/java/io/dataease/service/dataset/ExtractDataService.java b/core/backend/src/main/java/io/dataease/service/dataset/ExtractDataService.java index 6568f9d859..9e69f6618c 100644 --- a/core/backend/src/main/java/io/dataease/service/dataset/ExtractDataService.java +++ b/core/backend/src/main/java/io/dataease/service/dataset/ExtractDataService.java @@ -6,8 +6,8 @@ import io.dataease.commons.constants.*; import io.dataease.commons.model.AuthURD; import io.dataease.commons.utils.*; import io.dataease.controller.request.datasource.ApiDefinition; -import io.dataease.dto.dataset.DataTableInfoDTO; -import io.dataease.dto.dataset.ExcelSheetData; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; +import io.dataease.plugins.common.dto.dataset.ExcelSheetData; import io.dataease.dto.datasource.*; import io.dataease.ext.ExtChartViewMapper; import io.dataease.listener.util.CacheUtils; @@ -21,8 +21,8 @@ import io.dataease.plugins.common.request.datasource.DatasourceRequest; import io.dataease.plugins.datasource.entity.JdbcConfiguration; import io.dataease.plugins.datasource.provider.Provider; import io.dataease.plugins.datasource.query.QueryProvider; -import io.dataease.provider.DDLProvider; -import io.dataease.provider.ProviderFactory; +import io.dataease.plugins.datasource.provider.DDLProvider; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.provider.datasource.JdbcProvider; import io.dataease.service.datasource.DatasourceService; import io.dataease.service.engine.EngineService; @@ -191,8 +191,8 @@ public class ExtractDataService { switch (updateType) { case all_scope: // 全量更新 try { - createEngineTable(TableUtils.tableName(datasetTableId), datasetTableFields); - createEngineTable(TableUtils.tmpName(TableUtils.tableName(datasetTableId)), datasetTableFields); + createEngineTable(datasetTable.getInfo(), TableUtils.tableName(datasetTableId), datasetTableFields); + createEngineTable(datasetTable.getInfo(), TableUtils.tmpName(TableUtils.tableName(datasetTableId)), datasetTableFields); Long execTime = System.currentTimeMillis(); if (!engineService.isSimpleMode()) { generateTransFile("all_scope", datasetTable, datasource, datasetTableFields, null); @@ -205,7 +205,7 @@ public class ExtractDataService { saveSuccessLog(datasetTableTaskLog, false); updateTableStatus(datasetTableId, JobStatus.Completed, execTime); if (ops.equalsIgnoreCase("替换")) { - List oldFields = getDatasetTableFields(datasetTable.getId()); + List oldFields = getDatasetTableFields(datasetTable); List toAdd = new ArrayList<>(); List toDelete = new ArrayList<>(); for (DatasetTableField oldField : oldFields) { @@ -235,6 +235,7 @@ public class ExtractDataService { toDelete.forEach(datasetTableField -> dataSetTableFieldsService.delete(datasetTableField.getId())); } } catch (Exception e) { + e.printStackTrace(); saveErrorLog(datasetTableTaskLog, e, false); updateTableStatus(datasetTableId, JobStatus.Error, null); dropDorisTable(TableUtils.tmpName(TableUtils.tableName(datasetTableId))); @@ -311,15 +312,15 @@ public class ExtractDataService { } else { datasource.setType(datasetTable.getType()); } - List datasetTableFields = getDatasetTableFields(datasetTable.getId()); + List datasetTableFields = getDatasetTableFields(datasetTable); boolean msg = false; JobStatus lastExecStatus = JobStatus.Completed; Long execTime = null; switch (updateType) { case all_scope: // 全量更新 try { - createEngineTable(TableUtils.tableName(datasetTableId), datasetTableFields); - createEngineTable(TableUtils.tmpName(TableUtils.tableName(datasetTableId)), datasetTableFields); + createEngineTable(datasetTable.getInfo(), TableUtils.tableName(datasetTableId), datasetTableFields); + createEngineTable(datasetTable.getInfo(), TableUtils.tmpName(TableUtils.tableName(datasetTableId)), datasetTableFields); execTime = System.currentTimeMillis(); extractData(datasetTable, datasource, datasetTableFields, "all_scope", null); replaceTable(TableUtils.tableName(datasetTableId)); @@ -421,8 +422,13 @@ public class ExtractDataService { } - public List getDatasetTableFields(String datasetTableId) { - List datasetTableFields = dataSetTableFieldsService.list(DatasetTableField.builder().tableId(datasetTableId).build()); + public List getDatasetTableFields(DatasetTable datasetTable) { + List datasetTableFields = dataSetTableFieldsService.list(DatasetTableField.builder().tableId(datasetTable.getId()).build()); + return sortDatasetTableFields(datasetTable, datasetTableFields); + } + + private List sortDatasetTableFields(DatasetTable datasetTable, List datasetTableFields) { + DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class); datasetTableFields = datasetTableFields.stream().filter(datasetTableField -> datasetTableField.getExtField() == 0).collect(Collectors.toList()); datasetTableFields.sort((o1, o2) -> { if (o1.getColumnIndex() == null) { @@ -433,7 +439,20 @@ public class ExtractDataService { } return o1.getColumnIndex().compareTo(o2.getColumnIndex()); }); - return datasetTableFields; + List orderKeyDatasetTableFields = new ArrayList<>(); + for (int i = 0; i < dataTableInfoDTO.getKeys().size(); i++) { + for (DatasetTableField datasetTableField : datasetTableFields) { + if (datasetTableField.getOriginName().equalsIgnoreCase(dataTableInfoDTO.getKeys().get(i))) { + orderKeyDatasetTableFields.add(datasetTableField); + } + } + } + for (DatasetTableField datasetTableField : datasetTableFields) { + if (!dataTableInfoDTO.getKeys().contains(datasetTableField.getOriginName())) { + orderKeyDatasetTableFields.add(datasetTableField); + } + } + return orderKeyDatasetTableFields; } private void extractData(DatasetTable datasetTable, Datasource datasource, List datasetTableFields, String extractType, String selectSQL) throws Exception { @@ -461,9 +480,10 @@ public class ExtractDataService { } private void extractApiData(DatasetTable datasetTable, Datasource datasource, List datasetTableFields, String extractType) throws Exception { + DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class); List lists = new Gson().fromJson(datasource.getConfiguration(), new TypeToken>() { }.getType()); - lists = lists.stream().filter(item -> item.getName().equalsIgnoreCase(new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class).getTable())).collect(Collectors.toList()); + lists = lists.stream().filter(item -> item.getName().equalsIgnoreCase(dataTableInfoDTO.getTable())).collect(Collectors.toList()); if (CollectionUtils.isEmpty(lists)) { throw new Exception("未找到API数据表"); } @@ -483,8 +503,7 @@ public class ExtractDataService { Datasource engine = engineService.getDeEngine(); DorisConfiguration dorisConfiguration = new Gson().fromJson(engine.getConfiguration(), DorisConfiguration.class); - String columns = datasetTableFields.stream().map(DatasetTableField::getDataeaseName).collect(Collectors.joining(",")) + ",dataease_uuid"; - + String columns = "dataease_uuid, " + datasetTableFields.stream().map(DatasetTableField::getDataeaseName).collect(Collectors.joining(",")); String dataFile = null; String script = null; String streamLoadScript = ""; @@ -503,15 +522,16 @@ public class ExtractDataService { script = String.format(streamLoadScript, dorisConfiguration.getUsername(), dorisConfiguration.getPassword(), System.currentTimeMillis(), separator, columns, "APPEND", dataFile, dorisConfiguration.getHost(), dorisConfiguration.getHttpPort(), dorisConfiguration.getDataBase(), TableUtils.tableName(datasetTable.getId()), dataFile); break; } - - BufferedWriter bw = new BufferedWriter(new FileWriter(dataFile)); for (String[] strings : dataList) { String content = ""; for (int i = 0; i < strings.length; i++) { - content = content + strings[i] + separator; + content = i != strings.length - 1 ? content + strings[i] + separator : content + strings[i]; + } + boolean isSetKey = dataTableInfoDTO.isSetKey() && CollectionUtils.isNotEmpty(dataTableInfoDTO.getKeys()); + if (!isSetKey) { + content = Md5Utils.md5(content) + separator + content; } - content = content + Md5Utils.md5(content); bw.write(content); bw.newLine(); } @@ -547,8 +567,8 @@ public class ExtractDataService { } catch (Exception e) { throw e; } finally { - File deleteFile = new File(root_path + datasetTable.getId() + ".sh"); - FileUtils.forceDelete(deleteFile); +// File deleteFile = new File(root_path + datasetTable.getId() + ".sh"); +// FileUtils.forceDelete(deleteFile); } } @@ -641,7 +661,8 @@ public class ExtractDataService { dataSetTableTaskLogService.save(datasetTableTaskLog, hasTask); } - public void createEngineTable(String tableName, List datasetTableFields) throws Exception { + public void createEngineTable(String datasetTableInfo, String tableName, List datasetTableFields) throws Exception { + DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(datasetTableInfo, DataTableInfoDTO.class); Datasource engine = engineService.getDeEngine(); JdbcProvider jdbcProvider = CommonBeanFactory.getBean(JdbcProvider.class); DatasourceRequest datasourceRequest = new DatasourceRequest(); @@ -649,7 +670,7 @@ public class ExtractDataService { datasourceRequest.setQuery("SELECT VERSION()"); String version = jdbcProvider.getData(datasourceRequest).get(0)[0]; DDLProvider ddlProvider = ProviderFactory.getDDLProvider(engine.getType()); - datasourceRequest.setQuery(ddlProvider.createTableSql(tableName, datasetTableFields, engine, version)); + datasourceRequest.setQuery(ddlProvider.createTableSql(dataTableInfoDTO, tableName, datasetTableFields, engine, version)); jdbcProvider.exec(datasourceRequest); } @@ -873,7 +894,13 @@ public class ExtractDataService { String script = null; Datasource dorisDatasource = engineService.getDeEngine(); DorisConfiguration dorisConfiguration = new Gson().fromJson(dorisDatasource.getConfiguration(), DorisConfiguration.class); - String columns = columnFields + ",dataease_uuid"; + DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class); + String columns = columnFields; + + if (!(dataTableInfoDTO.isSetKey() && CollectionUtils.isNotEmpty(dataTableInfoDTO.getKeys()))) { + columns = columnFields + ",dataease_uuid"; + } + String streamLoadScript = ""; if (kettleFilesKeep) { streamLoadScript = shellScript; @@ -961,6 +988,8 @@ public class ExtractDataService { if (engineService.isSimpleMode()) { return; } + DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class); + boolean isSetKey = dataTableInfoDTO.isSetKey() && CollectionUtils.isNotEmpty(dataTableInfoDTO.getKeys()); TransMeta transMeta = new TransMeta(); String outFile = null; DatasourceTypes datasourceType = DatasourceTypes.valueOf(datasource.getType()); @@ -988,21 +1017,21 @@ public class ExtractDataService { } transMeta.addDatabase(dataMeta); inputSteps = inputStep(transMeta, selectSQL, mysqlConfiguration); - udjcStep = udjc(datasetTableFields, DatasourceTypes.mysql, mysqlConfiguration); + udjcStep = udjc(datasetTableFields, DatasourceTypes.mysql, mysqlConfiguration, isSetKey); break; case sqlServer: SqlServerConfiguration sqlServerConfiguration = new Gson().fromJson(datasource.getConfiguration(), SqlServerConfiguration.class); dataMeta = new DatabaseMeta("db", "MSSQLNATIVE", "Native", sqlServerConfiguration.getHost().trim(), sqlServerConfiguration.getDataBase(), sqlServerConfiguration.getPort().toString(), sqlServerConfiguration.getUsername(), sqlServerConfiguration.getPassword()); transMeta.addDatabase(dataMeta); inputSteps = inputStep(transMeta, selectSQL, sqlServerConfiguration); - udjcStep = udjc(datasetTableFields, DatasourceTypes.sqlServer, sqlServerConfiguration); + udjcStep = udjc(datasetTableFields, DatasourceTypes.sqlServer, sqlServerConfiguration, isSetKey); break; case pg: PgConfiguration pgConfiguration = new Gson().fromJson(datasource.getConfiguration(), PgConfiguration.class); dataMeta = new DatabaseMeta("db", "POSTGRESQL", "Native", pgConfiguration.getHost().trim(), pgConfiguration.getDataBase(), pgConfiguration.getPort().toString(), pgConfiguration.getUsername(), pgConfiguration.getPassword()); transMeta.addDatabase(dataMeta); inputSteps = inputStep(transMeta, selectSQL, pgConfiguration); - udjcStep = udjc(datasetTableFields, DatasourceTypes.pg, pgConfiguration); + udjcStep = udjc(datasetTableFields, DatasourceTypes.pg, pgConfiguration, isSetKey); break; case oracle: OracleConfiguration oracleConfiguration = new Gson().fromJson(datasource.getConfiguration(), OracleConfiguration.class); @@ -1014,7 +1043,7 @@ public class ExtractDataService { } transMeta.addDatabase(dataMeta); inputSteps = inputStep(transMeta, selectSQL, oracleConfiguration); - udjcStep = udjc(datasetTableFields, DatasourceTypes.oracle, oracleConfiguration); + udjcStep = udjc(datasetTableFields, DatasourceTypes.oracle, oracleConfiguration, isSetKey); break; case ck: CHConfiguration chConfiguration = new Gson().fromJson(datasource.getConfiguration(), CHConfiguration.class); @@ -1022,7 +1051,7 @@ public class ExtractDataService { dataMeta.setDatabaseType("Clickhouse"); transMeta.addDatabase(dataMeta); inputSteps = inputStep(transMeta, selectSQL, chConfiguration); - udjcStep = udjc(datasetTableFields, DatasourceTypes.ck, chConfiguration); + udjcStep = udjc(datasetTableFields, DatasourceTypes.ck, chConfiguration, isSetKey); break; case db2: Db2Configuration db2Configuration = new Gson().fromJson(datasource.getConfiguration(), Db2Configuration.class); @@ -1030,11 +1059,11 @@ public class ExtractDataService { dataMeta.setDatabaseType("DB2"); transMeta.addDatabase(dataMeta); inputSteps = inputStep(transMeta, selectSQL, db2Configuration); - udjcStep = udjc(datasetTableFields, DatasourceTypes.db2, db2Configuration); + udjcStep = udjc(datasetTableFields, DatasourceTypes.db2, db2Configuration, isSetKey); break; case excel: - inputSteps = excelInputStep(datasetTable.getInfo(), datasetTableFields); - udjcStep = udjc(datasetTableFields, DatasourceTypes.excel, null); + inputSteps = excelInputStep(datasetTable.getInfo(), datasetTableFields, false); + udjcStep = udjc(datasetTableFields, DatasourceTypes.excel, null, false); default: break; } @@ -1059,7 +1088,7 @@ public class ExtractDataService { break; } - outputStep = outputStep(outFile, datasetTableFields, datasource); + outputStep = outputStep(outFile, datasetTableFields, datasource, isSetKey); for (StepMeta inputStep : inputSteps) { TransHopMeta hi1 = new TransHopMeta(inputStep, udjcStep); @@ -1119,7 +1148,7 @@ public class ExtractDataService { return inputSteps; } - private List excelInputStep(String Info, List datasetTableFields) { + private List excelInputStep(String Info, List datasetTableFields, boolean isSetKey) { List inputSteps = new ArrayList<>(); DataTableInfoDTO dataTableInfoDTO = new Gson().fromJson(Info, DataTableInfoDTO.class); List excelSheetDataList = dataTableInfoDTO.getExcelSheetDataList(); @@ -1130,14 +1159,14 @@ public class ExtractDataService { for (ExcelSheetData excelSheetData : excelSheetDataList) { StepMeta fromStep = null; String suffix = excelSheetData.getPath().substring(excelSheetDataList.get(0).getPath().lastIndexOf(".") + 1); - + Integer fileInputFields = datasetTableFields.size(); if (StringUtils.equalsIgnoreCase(suffix, "csv")) { CsvInputMeta csvInputMeta = new CsvInputMeta(); csvInputMeta.setFilename(excelSheetData.getPath()); csvInputMeta.setHeaderPresent(true); csvInputMeta.setBufferSize("10000"); csvInputMeta.setDelimiter(","); - TextFileInputField[] fields = new TextFileInputField[datasetTableFields.size()]; + TextFileInputField[] fields = new TextFileInputField[fileInputFields]; for (int i = 0; i < datasetTableFields.size(); i++) { TextFileInputField field = new TextFileInputField(); field.setName(datasetTableFields.get(i).getDataeaseName()); @@ -1176,7 +1205,7 @@ public class ExtractDataService { excelInputMeta.setFileRequired(filesRequired.toArray(new String[filesRequired.size()])); excelInputMeta.setStartsWithHeader(true); excelInputMeta.setIgnoreEmptyRows(true); - ExcelInputField[] fields = new ExcelInputField[datasetTableFields.size()]; + ExcelInputField[] fields = new ExcelInputField[fileInputFields]; for (int i = 0; i < datasetTableFields.size(); i++) { ExcelInputField field = new ExcelInputField(); field.setName(datasetTableFields.get(i).getDataeaseName()); @@ -1199,30 +1228,32 @@ public class ExtractDataService { return inputSteps; } - private StepMeta outputStep(String dorisOutputTable, List datasetTableFields, Datasource datasource) { + private StepMeta outputStep(String dorisOutputTable, List datasetTableFields, Datasource datasource, boolean isSetKey) { TextFileOutputMeta textFileOutputMeta = new TextFileOutputMeta(); textFileOutputMeta.setEncoding("UTF-8"); textFileOutputMeta.setHeaderEnabled(false); textFileOutputMeta.setFilename(root_path + dorisOutputTable); textFileOutputMeta.setSeparator(separator); textFileOutputMeta.setExtension(extension); + Integer fieldSize = isSetKey ? datasetTableFields.size() : datasetTableFields.size() + 1; if (datasource.getType().equalsIgnoreCase(DatasourceTypes.oracle.name())) { - TextFileField[] outputFields = new TextFileField[datasetTableFields.size() + 1]; + TextFileField[] outputFields = new TextFileField[fieldSize]; for (int i = 0; i < datasetTableFields.size(); i++) { TextFileField textFileField = new TextFileField(); textFileField.setName(datasetTableFields.get(i).getOriginName()); textFileField.setType("String"); outputFields[i] = textFileField; } - TextFileField textFileField = new TextFileField(); - textFileField.setName("dataease_uuid"); - textFileField.setType("String"); - outputFields[datasetTableFields.size()] = textFileField; - + if(!isSetKey){ + TextFileField textFileField = new TextFileField(); + textFileField.setName("dataease_uuid"); + textFileField.setType("String"); + outputFields[datasetTableFields.size()] = textFileField; + } textFileOutputMeta.setOutputFields(outputFields); } else if (datasource.getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name()) || datasource.getType().equalsIgnoreCase(DatasourceTypes.pg.name()) || datasource.getType().equalsIgnoreCase(DatasourceTypes.mysql.name())) { - TextFileField[] outputFields = new TextFileField[datasetTableFields.size() + 1]; + TextFileField[] outputFields = new TextFileField[fieldSize]; for (int i = 0; i < datasetTableFields.size(); i++) { TextFileField textFileField = new TextFileField(); textFileField.setName(datasetTableFields.get(i).getDataeaseName()); @@ -1235,14 +1266,15 @@ public class ExtractDataService { outputFields[i] = textFileField; } - TextFileField textFileField = new TextFileField(); - textFileField.setName("dataease_uuid"); - textFileField.setType("String"); - outputFields[datasetTableFields.size()] = textFileField; - + if(!isSetKey){ + TextFileField textFileField = new TextFileField(); + textFileField.setName("dataease_uuid"); + textFileField.setType("String"); + outputFields[datasetTableFields.size()] = textFileField; + } textFileOutputMeta.setOutputFields(outputFields); } else if (datasource.getType().equalsIgnoreCase(DatasourceTypes.excel.name())) { - TextFileField[] outputFields = new TextFileField[datasetTableFields.size() + 1]; + TextFileField[] outputFields = new TextFileField[fieldSize]; for (int i = 0; i < datasetTableFields.size(); i++) { TextFileField textFileField = new TextFileField(); textFileField.setName(datasetTableFields.get(i).getDataeaseName()); @@ -1255,11 +1287,12 @@ public class ExtractDataService { outputFields[i] = textFileField; } - TextFileField textFileField = new TextFileField(); - textFileField.setName("dataease_uuid"); - textFileField.setType("String"); - outputFields[datasetTableFields.size()] = textFileField; - + if(!isSetKey){ + TextFileField textFileField = new TextFileField(); + textFileField.setName("dataease_uuid"); + textFileField.setType("String"); + outputFields[datasetTableFields.size()] = textFileField; + } textFileOutputMeta.setOutputFields(outputFields); } else { textFileOutputMeta.setOutputFields(new TextFileField[0]); @@ -1271,7 +1304,7 @@ public class ExtractDataService { return outputStep; } - private StepMeta udjc(List datasetTableFields, DatasourceTypes datasourceType, JdbcConfiguration jdbcConfiguration) { + private StepMeta udjc(List datasetTableFields, DatasourceTypes datasourceType, JdbcConfiguration jdbcConfiguration, boolean isSetKey) { StringBuilder handleBinaryTypeCode = new StringBuilder(); String excelCompletion = ""; @@ -1280,15 +1313,20 @@ public class ExtractDataService { handleBinaryTypeCode.append("\n").append(handleBinaryType.replace("FIELD", datasetTableField.getDataeaseName())); } } - UserDefinedJavaClassMeta userDefinedJavaClassMeta = new UserDefinedJavaClassMeta(); List fields = new ArrayList<>(); - UserDefinedJavaClassMeta.FieldInfo fieldInfo = new UserDefinedJavaClassMeta.FieldInfo("dataease_uuid", ValueMetaInterface.TYPE_STRING, -1, -1); - fields.add(fieldInfo); + if (!isSetKey) { + UserDefinedJavaClassMeta.FieldInfo fieldInfo = new UserDefinedJavaClassMeta.FieldInfo("dataease_uuid", ValueMetaInterface.TYPE_STRING, -1, -1); + fields.add(fieldInfo); + } userDefinedJavaClassMeta.setFieldInfo(fields); List definitions = new ArrayList<>(); String tmp_code = code.replace("handleWraps", handleWraps).replace("handleBinaryType", handleBinaryTypeCode.toString()); - + if (isSetKey) { + tmp_code = tmp_code.replace("handleDataease_uuid", ""); + } else { + tmp_code = tmp_code.replace("handleDataease_uuid", handleDataease_uuid); + } String Column_Fields; if (datasourceType.equals(DatasourceTypes.oracle) || datasourceType.equals(DatasourceTypes.db2)) { @@ -1323,7 +1361,7 @@ public class ExtractDataService { String handleMysqlBIGINTUNSIGNEDStr = ""; if (datasourceType.equals(DatasourceTypes.mysql)) { for (DatasetTableField datasetTableField : datasetTableFields) { - if(datasetTableField.getType().equalsIgnoreCase("BIGINT UNSIGNED")){ + if (datasetTableField.getType().equalsIgnoreCase("BIGINT UNSIGNED")) { handleMysqlBIGINTUNSIGNEDStr = handleMysqlBIGINTUNSIGNEDStr + handleMysqlBIGINTUNSIGNED.replace("BIGINTUNSIGNEDFIELD", datasetTableField.getDataeaseName()) + "; \n"; } } @@ -1441,12 +1479,14 @@ public class ExtractDataService { " get(Fields.Out, filed).setValue(r, tmp);\n" + " } \n"; + private final static String handleDataease_uuid = "get(Fields.Out, \"dataease_uuid\").setValue(r, md5)"; private final static String handleCharset = "\tif(tmp != null && Arrays.asList(\"varcharFields\".split(\",\")).contains(filed)){\n" + " \t\t\ttry {\n" + "\t\t\t\tget(Fields.Out, filed).setValue(r, new String(tmp.getBytes(\"Datasource_Charset\"), \"Target_Charset\"));\n" + " \t\t}catch (Exception e){}\n" + "\t\t}"; + private final static String code = "import org.pentaho.di.core.row.ValueMetaInterface;\n" + "import java.util.List;\n" + "import java.io.File;\n" + @@ -1486,7 +1526,7 @@ public class ExtractDataService { " }\n" + "\n" + " String md5 = md5(str);\n" + - " get(Fields.Out, \"dataease_uuid\").setValue(r, md5);\n" + + " handleDataease_uuid ;\n" + "\n" + " putRow(data.outputRowMeta, r);\n" + "\n" + diff --git a/core/backend/src/main/java/io/dataease/service/dataset/impl/direct/DirectFieldService.java b/core/backend/src/main/java/io/dataease/service/dataset/impl/direct/DirectFieldService.java index a42b0058cd..ec4551238e 100644 --- a/core/backend/src/main/java/io/dataease/service/dataset/impl/direct/DirectFieldService.java +++ b/core/backend/src/main/java/io/dataease/service/dataset/impl/direct/DirectFieldService.java @@ -1,14 +1,12 @@ package io.dataease.service.dataset.impl.direct; -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.ArrayUtil; import com.google.gson.Gson; import io.dataease.commons.model.BaseTreeNode; import io.dataease.commons.utils.BeanUtils; import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.TreeUtils; import io.dataease.dto.dataset.DataSetTableUnionDTO; -import io.dataease.dto.dataset.DataTableInfoDTO; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; import io.dataease.dto.dataset.DeSortDTO; import io.dataease.i18n.Translator; import io.dataease.plugins.common.base.domain.DatasetTable; @@ -23,11 +21,12 @@ import io.dataease.plugins.common.request.permission.DataSetRowPermissionsTreeDT import io.dataease.plugins.datasource.provider.Provider; import io.dataease.plugins.datasource.query.QueryProvider; import io.dataease.plugins.xpack.auth.dto.request.ColumnPermissionItem; -import io.dataease.provider.ProviderFactory; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.service.dataset.*; import io.dataease.service.datasource.DatasourceService; import io.dataease.service.engine.EngineService; -import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -81,15 +80,14 @@ public class DirectFieldService implements DataSetFieldService { @Override public List chineseSort(List list, DeSortDTO sortDTO) throws Exception { - if (ObjectUtils.isEmpty(sortDTO) || CollectionUtil.isEmpty(list)) return list; + if (ObjectUtils.isEmpty(sortDTO) || CollectionUtils.isEmpty(list)) return list; String sort = sortDTO.getSort(); if (!StringUtils.equals(sort, "chinese")) { return list; } String id = sortDTO.getId(); String sortStr = StringUtils.equalsIgnoreCase("chineseDesc", id) ? "desc" : "asc"; - - return CollectionUtil.sort(list, (v1, v2) -> { + list.sort((v1, v2) -> { Collator instance = Collator.getInstance(Locale.CHINESE); if (ObjectUtils.isEmpty(v1) || ObjectUtils.isEmpty(v2)) return 0; if (StringUtils.equals("desc", sortStr)) { @@ -97,6 +95,7 @@ public class DirectFieldService implements DataSetFieldService { } return instance.compare(v1, v2); }); + return list; } @@ -225,7 +224,7 @@ public class DirectFieldService implements DataSetFieldService { } Set pkSet = new HashSet<>(); if (CollectionUtils.isNotEmpty(rows) && existExtSortField && originSize > 0) { - rows = rows.stream().map(row -> ArrayUtil.sub(row, 0, originSize)).collect(Collectors.toList()); + rows = rows.stream().map(row -> ArrayUtils.subarray(row, 0, originSize)).collect(Collectors.toList()); } List treeNodes = rows.stream().map(row -> buildTreeNode(row, pkSet)).flatMap(Collection::stream).collect(Collectors.toList()); List tree = TreeUtils.mergeDuplicateTree(treeNodes, TreeUtils.DEFAULT_ROOT); diff --git a/core/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java b/core/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java index d7949eb87d..631993b57f 100644 --- a/core/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java +++ b/core/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java @@ -21,7 +21,7 @@ import io.dataease.controller.request.datasource.ApiDefinition; import io.dataease.controller.sys.response.BasicInfo; import io.dataease.dto.DatasourceDTO; import io.dataease.dto.TaskInstance; -import io.dataease.dto.dataset.DataTableInfoDTO; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; import io.dataease.dto.datasource.DBTableDTO; import io.dataease.dto.datasource.MysqlConfiguration; import io.dataease.ext.ExtDataSourceMapper; @@ -44,7 +44,7 @@ import io.dataease.plugins.common.util.SpringContextUtil; import io.dataease.plugins.datasource.entity.JdbcConfiguration; import io.dataease.plugins.datasource.entity.Status; import io.dataease.plugins.datasource.provider.Provider; -import io.dataease.provider.ProviderFactory; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.provider.datasource.ApiProvider; import io.dataease.service.ScheduleService; import io.dataease.service.dataset.DataSetGroupService; @@ -53,8 +53,6 @@ import io.dataease.service.sys.SysAuthService; import io.dataease.service.system.SystemParameterService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.zookeeper.data.Stat; -import org.mozilla.javascript.EcmaError; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.data.redis.core.RedisTemplate; @@ -520,8 +518,7 @@ public class DatasourceService { } public ApiDefinition checkApiDatasource(ApiDefinition apiDefinition) throws Exception { - BasicInfo basicInfo = systemParameterService.basicInfo(); - String response = ApiProvider.execHttpRequest(apiDefinition, StringUtils.isNotBlank(basicInfo.getFrontTimeOut()) ? Integer.parseInt(basicInfo.getFrontTimeOut()) : 10); + String response = ApiProvider.execHttpRequest(apiDefinition, apiDefinition.getApiQueryTimeout() == null || apiDefinition.getApiQueryTimeout() <= 0 ? 30 : apiDefinition.getApiQueryTimeout()); return ApiProvider.checkApiDefinition(apiDefinition, response); } diff --git a/core/backend/src/main/java/io/dataease/service/datasource/DriverService.java b/core/backend/src/main/java/io/dataease/service/datasource/DriverService.java index 5af54aac18..0c71929d91 100644 --- a/core/backend/src/main/java/io/dataease/service/datasource/DriverService.java +++ b/core/backend/src/main/java/io/dataease/service/datasource/DriverService.java @@ -1,6 +1,5 @@ package io.dataease.service.datasource; -import cn.hutool.core.collection.CollectionUtil; import com.google.gson.Gson; import io.dataease.commons.constants.SysLogConstants; import io.dataease.commons.utils.BeanUtils; @@ -16,7 +15,8 @@ import io.dataease.plugins.common.base.mapper.DeDriverMapper; import io.dataease.plugins.datasource.entity.JdbcConfiguration; import io.dataease.plugins.datasource.provider.DefaultJdbcProvider; import io.dataease.plugins.datasource.provider.ExtendedJdbcClassLoader; -import io.dataease.provider.ProviderFactory; +import io.dataease.plugins.datasource.provider.ProviderFactory; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,7 +27,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Modifier; -import java.net.URL; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -81,7 +80,7 @@ public class DriverService { } DeDriverExample example = new DeDriverExample(); example.createCriteria().andNameEqualTo(deDriver.getName()); - if(CollectionUtil.isNotEmpty(deDriverMapper.selectByExampleWithBLOBs(example))){ + if(CollectionUtils.isNotEmpty(deDriverMapper.selectByExampleWithBLOBs(example))){ throw new RuntimeException(Translator.get("I18N_DRIVER_REPEAT_NAME")); } deDriver.setCreateTime(System.currentTimeMillis()); @@ -147,7 +146,7 @@ public class DriverService { DeDriverDetailsExample deDriverDetailsExample = new DeDriverDetailsExample(); deDriverDetailsExample.createCriteria().andDeDriverIdEqualTo(driverId).andFileNameEqualTo(filename); - if(CollectionUtil.isNotEmpty(deDriverDetailsMapper.selectByExample(deDriverDetailsExample))){ + if(CollectionUtils.isNotEmpty(deDriverDetailsMapper.selectByExample(deDriverDetailsExample))){ throw new Exception("A file with the same name already exists:" + filename); } diff --git a/core/backend/src/main/java/io/dataease/service/engine/EngineService.java b/core/backend/src/main/java/io/dataease/service/engine/EngineService.java index 3b4a5bfcfa..7b82c0a7e3 100644 --- a/core/backend/src/main/java/io/dataease/service/engine/EngineService.java +++ b/core/backend/src/main/java/io/dataease/service/engine/EngineService.java @@ -5,8 +5,8 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import io.dataease.commons.utils.BeanUtils; -import io.dataease.commons.utils.HttpClientConfig; -import io.dataease.commons.utils.HttpClientUtil; +import io.dataease.plugins.common.util.HttpClientConfig; +import io.dataease.plugins.common.util.HttpClientUtil; import io.dataease.controller.ResultHolder; import io.dataease.dto.datasource.DorisConfiguration; import io.dataease.dto.datasource.MysqlConfiguration; @@ -17,7 +17,7 @@ import io.dataease.plugins.common.base.domain.DeEngineExample; import io.dataease.plugins.common.base.mapper.DeEngineMapper; import io.dataease.plugins.common.request.datasource.DatasourceRequest; import io.dataease.plugins.datasource.provider.Provider; -import io.dataease.provider.ProviderFactory; +import io.dataease.plugins.datasource.provider.ProviderFactory; import io.dataease.service.datasource.DatasourceService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; diff --git a/core/backend/src/main/java/io/dataease/service/kettle/KettleService.java b/core/backend/src/main/java/io/dataease/service/kettle/KettleService.java index 523d8e5b18..06397476a3 100644 --- a/core/backend/src/main/java/io/dataease/service/kettle/KettleService.java +++ b/core/backend/src/main/java/io/dataease/service/kettle/KettleService.java @@ -1,8 +1,8 @@ package io.dataease.service.kettle; import com.google.gson.Gson; -import io.dataease.commons.utils.HttpClientConfig; -import io.dataease.commons.utils.HttpClientUtil; +import io.dataease.plugins.common.util.HttpClientConfig; +import io.dataease.plugins.common.util.HttpClientUtil; import io.dataease.controller.ResultHolder; import io.dataease.dto.KettleDTO; import io.dataease.plugins.common.base.domain.DeEngine; diff --git a/core/backend/src/main/java/io/dataease/service/panel/PanelAppTemplateService.java b/core/backend/src/main/java/io/dataease/service/panel/PanelAppTemplateService.java index 64fa7895b8..4d89a21889 100644 --- a/core/backend/src/main/java/io/dataease/service/panel/PanelAppTemplateService.java +++ b/core/backend/src/main/java/io/dataease/service/panel/PanelAppTemplateService.java @@ -280,8 +280,8 @@ public class PanelAppTemplateService { public void createDorisTable(List datasetTablesInfo) throws Exception { for (DatasetTable datasetTable : datasetTablesInfo) { if (1 == datasetTable.getMode() && !(DatasetType.CUSTOM.name().equalsIgnoreCase(datasetTable.getType()) || DatasetType.UNION.name().equalsIgnoreCase(datasetTable.getType()))) { - List fields = extractDataService.getDatasetTableFields(datasetTable.getId()); - extractDataService.createEngineTable(TableUtils.tableName(datasetTable.getId()), fields); + List fields = extractDataService.getDatasetTableFields(datasetTable); + extractDataService.createEngineTable(datasetTable.getInfo(), TableUtils.tableName(datasetTable.getId()), fields); } } } diff --git a/core/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java b/core/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java index d69e2a34d1..8ce3b1fcd8 100644 --- a/core/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java +++ b/core/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java @@ -1,6 +1,5 @@ package io.dataease.service.panel; -import cn.hutool.core.util.ArrayUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; @@ -21,7 +20,7 @@ import io.dataease.dto.chart.ChartViewDTO; import io.dataease.dto.dataset.DataSetGroupDTO; import io.dataease.dto.dataset.DataSetTableDTO; import io.dataease.dto.dataset.DataSetTaskDTO; -import io.dataease.dto.dataset.DataTableInfoDTO; +import io.dataease.plugins.common.dto.dataset.DataTableInfoDTO; import io.dataease.dto.panel.PanelExport2App; import io.dataease.dto.panel.PanelGroupDTO; import io.dataease.dto.panel.PanelTemplateFileDTO; @@ -33,12 +32,14 @@ import io.dataease.plugins.common.base.domain.*; import io.dataease.plugins.common.base.mapper.*; import io.dataease.plugins.common.constants.DeTypeConstants; import io.dataease.plugins.common.exception.DataEaseException; +import io.dataease.plugins.common.util.HttpClientUtil; import io.dataease.service.chart.ChartViewService; import io.dataease.service.dataset.DataSetGroupService; import io.dataease.service.dataset.DataSetTableService; import io.dataease.service.staticResource.StaticResourceService; import io.dataease.service.sys.SysAuthService; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; @@ -46,10 +47,10 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.pentaho.di.core.util.UUIDUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; @@ -143,6 +144,9 @@ public class PanelGroupService { @Resource private DatasourceMapper datasourceMapper; + @Value("${export.views.limit:100000}") + private Long limit; + public List tree(PanelGroupRequest panelGroupRequest) { String userId = String.valueOf(AuthUtils.getUser().getUserId()); panelGroupRequest.setUserId(userId); @@ -685,7 +689,7 @@ public class PanelGroupService { Boolean mergeHead = false; ViewDetailField[] detailFields = request.getDetailFields(); - if (ArrayUtil.isNotEmpty(detailFields)) { + if (ArrayUtils.isNotEmpty(detailFields)) { cellStyle.setBorderTop(BorderStyle.THIN); cellStyle.setBorderRight(BorderStyle.THIN); cellStyle.setBorderBottom(BorderStyle.THIN); @@ -1162,8 +1166,8 @@ public class PanelGroupService { try { List excelHeaderKeys = request.getExcelHeaderKeys(); ChartExtRequest componentFilterInfo = request.getComponentFilterInfo(); - componentFilterInfo.setGoPage(1l); - componentFilterInfo.setPageSize(1000000l); + componentFilterInfo.setGoPage(1L); + componentFilterInfo.setPageSize(limit); componentFilterInfo.setExcelExportFlag(true); componentFilterInfo.setProxy(request.getProxy()); componentFilterInfo.setUser(request.getUserId()); diff --git a/core/backend/src/main/java/io/dataease/service/panel/PanelLinkService.java b/core/backend/src/main/java/io/dataease/service/panel/PanelLinkService.java index d9baa4281c..4641f98315 100644 --- a/core/backend/src/main/java/io/dataease/service/panel/PanelLinkService.java +++ b/core/backend/src/main/java/io/dataease/service/panel/PanelLinkService.java @@ -4,7 +4,10 @@ import io.dataease.auth.config.RsaProperties; import io.dataease.auth.util.JWTUtils; import io.dataease.auth.util.RsaUtil; import io.dataease.commons.constants.SysLogConstants; -import io.dataease.commons.utils.*; +import io.dataease.commons.utils.AuthUtils; +import io.dataease.commons.utils.CodingUtil; +import io.dataease.commons.utils.DeLogUtils; +import io.dataease.commons.utils.ServletUtils; import io.dataease.controller.request.panel.link.EnablePwdRequest; import io.dataease.controller.request.panel.link.LinkRequest; import io.dataease.controller.request.panel.link.OverTimeRequest; @@ -127,6 +130,16 @@ public class PanelLinkService { } } + public String getMappingUuid(PanelLink link) { + String resourceId = link.getResourceId(); + Long userId = link.getUserId(); + PanelLinkMappingExample example = new PanelLinkMappingExample(); + example.createCriteria().andResourceIdEqualTo(resourceId).andUserIdEqualTo(userId); + List mappings = panelLinkMappingMapper.selectByExample(example); + if (CollectionUtils.isNotEmpty(mappings)) return mappings.get(0).getUuid(); + return null; + } + @Transactional public GenerateDto currentGenerate(String resourceId) { PanelLink one = findOne(resourceId, AuthUtils.getUser().getUserId()); @@ -143,14 +156,17 @@ public class PanelLinkService { PanelLinkMappingExample example = new PanelLinkMappingExample(); example.createCriteria().andResourceIdEqualTo(resourceId).andUserIdEqualTo(AuthUtils.getUser().getUserId()); List mappings = panelLinkMappingMapper.selectByExample(example); + PanelLinkMapping mapping = null; if (CollectionUtils.isEmpty(mappings)) { - PanelLinkMapping mapping = new PanelLinkMapping(); + mapping = new PanelLinkMapping(); mapping.setResourceId(resourceId); mapping.setUserId(AuthUtils.getUser().getUserId()); mapping.setUuid(CodingUtil.shortUuid()); panelLinkMappingMapper.insert(mapping); + } else { + mapping = mappings.get(0); } - return convertDto(one); + return convertDto(one, mapping.getUuid()); } public void deleteByResourceId(String resourceId) { @@ -177,20 +193,24 @@ public class PanelLinkService { return null; } - private String buildLinkParam(PanelLink link) { - String linkParam = encrypt(link.getResourceId()); + private String buildLinkParam(PanelLink link, String uuid) { + String resourceId = link.getResourceId(); + if (StringUtils.isNotBlank(uuid)) { + resourceId += ("," + uuid); + } + String linkParam = encrypt(resourceId); if (link.getUserId() != null) { linkParam = linkParam + USERPARAM + encrypt(link.getUserId().toString()); } return linkParam; } - private GenerateDto convertDto(PanelLink link) { + private GenerateDto convertDto(PanelLink link, String uuid) { GenerateDto result = new GenerateDto(); result.setValid(link.getValid()); result.setEnablePwd(link.getEnablePwd()); result.setPwd(link.getPwd()); - result.setUri(BASEURL + buildLinkParam(link)); + result.setUri(BASEURL + buildLinkParam(link, uuid)); result.setOverTime(link.getOverTime()); return result; } @@ -237,8 +257,8 @@ public class PanelLinkService { return pass; } - public PanelGroupDTO resourceInfo(String resourceId,String userId) { - PanelGroupDTO result = extPanelGroupMapper.findOneWithPrivileges(resourceId,userId); + public PanelGroupDTO resourceInfo(String resourceId, String userId) { + PanelGroupDTO result = extPanelGroupMapper.findOneWithPrivileges(resourceId, userId); result.setWatermarkInfo(panelWatermarkMapper.selectByPrimaryKey("system_default")); return result; } @@ -261,7 +281,7 @@ public class PanelLinkService { if (StringUtils.isNotBlank(mapping.getUuid())) { one.setResourceId("error-resource-id"); } - return convertDto(one).getUri(); + return convertDto(one, mapping.getUuid()).getUri(); } public String getUrlByUuid(String uuid) { @@ -271,12 +291,12 @@ public class PanelLinkService { if (CollectionUtils.isEmpty(mappings)) { PanelLink panelLink = new PanelLink(); panelLink.setResourceId("error-resource-id"); - return BASEURL + buildLinkParam(panelLink); + return BASEURL + buildLinkParam(panelLink, null); } PanelLinkMapping mapping = mappings.get(0); String resourceId = mapping.getResourceId(); Long userId = mapping.getUserId(); PanelLink one = findOne(resourceId, userId); - return convertDto(one).getUri(); + return convertDto(one, uuid).getUri(); } } diff --git a/core/backend/src/main/java/io/dataease/service/staticResource/StaticResourceService.java b/core/backend/src/main/java/io/dataease/service/staticResource/StaticResourceService.java index 33518fd5d4..2973d7fa9c 100644 --- a/core/backend/src/main/java/io/dataease/service/staticResource/StaticResourceService.java +++ b/core/backend/src/main/java/io/dataease/service/staticResource/StaticResourceService.java @@ -1,16 +1,16 @@ package io.dataease.service.staticResource; -import cn.hutool.core.codec.Base64Decoder; -import cn.hutool.core.collection.CollectionUtil; import com.google.gson.Gson; import io.dataease.commons.utils.FileUtils; import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.StaticResourceUtils; import io.dataease.controller.request.resource.StaticResourceRequest; import io.dataease.plugins.common.exception.DataEaseException; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.util.Assert; +import org.springframework.util.Base64Utils; import org.springframework.util.FileCopyUtils; import org.springframework.web.multipart.MultipartFile; @@ -93,7 +93,7 @@ public class StaticResourceService { } else { if (StringUtils.isNotEmpty(content)) { Files.createFile(uploadPath); - FileCopyUtils.copy(Base64Decoder.decode(content), Files.newOutputStream(uploadPath)); + FileCopyUtils.copy(Base64Utils.decodeFromString(content), Files.newOutputStream(uploadPath)); } } } catch (Exception e) { @@ -103,7 +103,7 @@ public class StaticResourceService { public Map findResourceAsBase64(StaticResourceRequest resourceRequest) { Map result = new HashMap<>(); - if (CollectionUtil.isNotEmpty(resourceRequest.getResourcePathList())) { + if (CollectionUtils.isNotEmpty(resourceRequest.getResourcePathList())) { for (String path : resourceRequest.getResourcePathList()) { String value = StaticResourceUtils.getImgFileToBase64(path.substring(path.lastIndexOf("/") + 1, path.length())); result.put(path, value); diff --git a/core/backend/src/main/java/io/dataease/service/sys/PluginService.java b/core/backend/src/main/java/io/dataease/service/sys/PluginService.java index 2149351c68..2bf1499468 100644 --- a/core/backend/src/main/java/io/dataease/service/sys/PluginService.java +++ b/core/backend/src/main/java/io/dataease/service/sys/PluginService.java @@ -1,13 +1,8 @@ package io.dataease.service.sys; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.util.ZipUtil; import com.google.gson.Gson; import io.dataease.commons.constants.AuthConstants; -import io.dataease.commons.utils.CodingUtil; -import io.dataease.commons.utils.DeFileUtils; -import io.dataease.commons.utils.IPUtils; -import io.dataease.commons.utils.LogUtil; +import io.dataease.commons.utils.*; import io.dataease.dto.MyPluginDTO; import io.dataease.ext.ExtSysPluginMapper; import io.dataease.i18n.Translator; @@ -16,6 +11,7 @@ import io.dataease.plugins.common.base.domain.MyPlugin; import io.dataease.plugins.common.base.mapper.MyPluginMapper; import io.dataease.plugins.common.exception.DataEaseException; import io.dataease.plugins.common.request.KeywordRequest; +import io.dataease.plugins.common.util.FileUtil; import io.dataease.plugins.config.LoadjarUtil; import io.dataease.plugins.entity.PluginOperate; import io.dataease.service.datasource.DatasourceService; @@ -84,7 +80,7 @@ public class PluginService { //2.解压目标文件dest 得到plugin.json和jar String folder = pluginDir + "folder/"; try { - ZipUtil.unzip(dest.getAbsolutePath(), folder); + ZipUtils.unZipIt(dest.getAbsolutePath(), folder); } catch (Exception e) { DeFileUtils.deleteFile(pluginDir + "temp/"); DeFileUtils.deleteFile(folder); diff --git a/core/backend/src/main/java/io/dataease/service/sys/log/LogService.java b/core/backend/src/main/java/io/dataease/service/sys/log/LogService.java index 6458764dc3..7eae10b141 100644 --- a/core/backend/src/main/java/io/dataease/service/sys/log/LogService.java +++ b/core/backend/src/main/java/io/dataease/service/sys/log/LogService.java @@ -1,7 +1,6 @@ package io.dataease.service.sys.log; -import cn.hutool.core.date.DateUtil; import com.google.gson.Gson; import io.dataease.auth.api.dto.CurrentUserDto; import io.dataease.commons.constants.ParamConstants; @@ -20,6 +19,7 @@ import io.dataease.plugins.common.base.domain.SysLogExample; import io.dataease.plugins.common.base.domain.SysLogWithBLOBs; import io.dataease.plugins.common.base.mapper.SysLogMapper; import io.dataease.plugins.common.exception.DataEaseException; +import io.dataease.plugins.common.util.GlobalDateUtils; import io.dataease.service.system.SystemParameterService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; @@ -265,7 +265,12 @@ public class LogService { row[1] = logManager.detailInfo(item); row[2] = item.getNickName(); row[3] = item.getIp(); - row[4] = DateUtil.formatDateTime(new Date(item.getTime())); + // row[4] = DateUtil.formatDateTime(new Date(item.getTime())); + try { + row[4] = GlobalDateUtils.getTimeString(item.getTime()); + } catch (Exception e) { + throw new RuntimeException(e); + } return row; }).collect(Collectors.toList()); String[] headArr = {"操作类型", "详情", "用户", "IP地址", "时间"}; diff --git a/core/backend/src/main/java/io/dataease/service/system/EmailService.java b/core/backend/src/main/java/io/dataease/service/system/EmailService.java index e9c56b76b6..dd27d90019 100644 --- a/core/backend/src/main/java/io/dataease/service/system/EmailService.java +++ b/core/backend/src/main/java/io/dataease/service/system/EmailService.java @@ -1,8 +1,6 @@ package io.dataease.service.system; -import cn.hutool.core.util.ArrayUtil; import io.dataease.commons.constants.ParamConstants; - import io.dataease.commons.utils.CommonBeanFactory; import io.dataease.commons.utils.EncryptUtils; import io.dataease.commons.utils.LogUtil; @@ -13,6 +11,7 @@ import io.dataease.plugins.common.base.domain.SystemParameterExample; import io.dataease.plugins.common.base.mapper.SystemParameterMapper; import io.dataease.plugins.common.exception.DataEaseException; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.mail.javamail.JavaMailSenderImpl; @@ -85,7 +84,7 @@ public class EmailService { public void sendPdfWithFiles(String to, String title, String content, byte[] bytes, List files) { - if (ArrayUtil.isEmpty(bytes)) { + if (ArrayUtils.isEmpty(bytes)) { send(to, title, content); return; } @@ -118,7 +117,7 @@ public class EmailService { if (StringUtils.isBlank(to)) return; - if (ArrayUtil.isEmpty(bytes)) { + if (ArrayUtils.isEmpty(bytes)) { send(to, title, content); return; } diff --git a/core/backend/src/main/java/io/dataease/service/templateMarket/TemplateMarketService.java b/core/backend/src/main/java/io/dataease/service/templateMarket/TemplateMarketService.java index e66ad1c4cc..e86b40d7cb 100644 --- a/core/backend/src/main/java/io/dataease/service/templateMarket/TemplateMarketService.java +++ b/core/backend/src/main/java/io/dataease/service/templateMarket/TemplateMarketService.java @@ -2,8 +2,8 @@ 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.plugins.common.util.HttpClientConfig; +import io.dataease.plugins.common.util.HttpClientUtil; import io.dataease.controller.request.templateMarket.TemplateMarketSearchRequest; import io.dataease.controller.sys.response.BasicInfo; import io.dataease.dto.panel.PanelTemplateFileDTO; diff --git a/core/backend/src/main/java/io/dataease/service/wizard/ReptileService.java b/core/backend/src/main/java/io/dataease/service/wizard/ReptileService.java index 9cc8e59a49..b5be9f4380 100644 --- a/core/backend/src/main/java/io/dataease/service/wizard/ReptileService.java +++ b/core/backend/src/main/java/io/dataease/service/wizard/ReptileService.java @@ -1,7 +1,7 @@ package io.dataease.service.wizard; -import io.dataease.commons.utils.HttpClientConfig; -import io.dataease.commons.utils.HttpClientUtil; +import io.dataease.plugins.common.util.HttpClientConfig; +import io.dataease.plugins.common.util.HttpClientUtil; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; diff --git a/core/backend/src/main/resources/application.properties b/core/backend/src/main/resources/application.properties index fb50ef16d8..1683cb9987 100644 --- a/core/backend/src/main/resources/application.properties +++ b/core/backend/src/main/resources/application.properties @@ -32,6 +32,9 @@ knife4j.setting.enableOpenApi=false knife4j.setting.enableAfterScript=false version=@project.version@ logging.file.path=/opt/dataease/logs/${spring.application.name} +logging.file.history=30 +logging.file.size=50MB + # view spring.resources.static-locations=classpath:/templates/,classpath:/static/ # flyway enable @@ -77,6 +80,7 @@ server.compression.min-response-size=1024 server.servlet.context-parameters.configurationStrategy=SYSTEM_PROPERTIES server.servlet.session.cookie.http-only=true server.servlet.session.tracking-modes=cookie +spring.jackson.parser.allow-numeric-leading-zeros=true diff --git a/core/backend/src/main/resources/db/migration/V60__1.18.15.sql b/core/backend/src/main/resources/db/migration/V60__1.18.15.sql index 3d7b45abd3..f27d7860b5 100644 --- a/core/backend/src/main/resources/db/migration/V60__1.18.15.sql +++ b/core/backend/src/main/resources/db/migration/V60__1.18.15.sql @@ -1,9 +1,12 @@ - ALTER TABLE `datasource` +ALTER TABLE `datasource` ADD COLUMN `version` varchar(255) NULL COMMENT '版本' AFTER `status`; - ALTER TABLE `sys_auth` - MODIFY COLUMN `auth_details` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '授权明细' AFTER `auth_time`; +ALTER TABLE `sys_auth` + MODIFY COLUMN `auth_details` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '授权明细' AFTER `auth_time`; - ALTER TABLE `sys_auth_detail` - MODIFY COLUMN `privilege_type` int(6) NULL DEFAULT NULL COMMENT '权限类型:1 使用/查看 3 导出/管理 5 仪表板管理 15 授权' AFTER `privilege_name`, - MODIFY COLUMN `privilege_value` int(6) NULL DEFAULT NULL COMMENT '权限值:1 可用 0 不可用' AFTER `privilege_type`; +ALTER TABLE `sys_auth_detail` + MODIFY COLUMN `privilege_type` int(6) NULL DEFAULT NULL COMMENT '权限类型:1 使用/查看 3 导出/管理 5 仪表板管理 15 授权' AFTER `privilege_name`, + MODIFY COLUMN `privilege_value` int(6) NULL DEFAULT NULL COMMENT '权限值:1 可用 0 不可用' AFTER `privilege_type`; + +ALTER TABLE `sys_task_email` + MODIFY COLUMN `groups` longtext NULL COMMENT '群聊' AFTER `view_data_range`; \ No newline at end of file diff --git a/core/backend/src/main/resources/i18n/messages_en_US.properties b/core/backend/src/main/resources/i18n/messages_en_US.properties index 2fee75cb4d..7648cb59c8 100644 --- a/core/backend/src/main/resources/i18n/messages_en_US.properties +++ b/core/backend/src/main/resources/i18n/messages_en_US.properties @@ -94,6 +94,7 @@ i18n_sql_delete_not_matching=The data column of incremental delete SQL does not i18n_cst_ds_tb_or_field_deleted=Custom dataset union data is deleted or field changed,can not display i18n_no_all_delete_privilege_folder=This folder have sources which have no manage or view privilege,Can Not Be Deleted. i18n_excel_field_repeat=Duplicate fields exist: +i18n_dont_contain_key=The current SQL doesn't include this key: i18n_schema_is_empty=Database schema is empty \u7AD9\u5185\u6D88\u606F=Messages Center \u6240\u6709\u6D88\u606F=All Messages diff --git a/core/backend/src/main/resources/i18n/messages_zh_CN.properties b/core/backend/src/main/resources/i18n/messages_zh_CN.properties index 7a5e436e86..5a01acb2cf 100644 --- a/core/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/core/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -94,6 +94,7 @@ i18n_sql_delete_not_matching=\u589E\u91CF\u5220\u9664 SQL \u7684\u6570\u636E\u52 i18n_cst_ds_tb_or_field_deleted=\u81EA\u5B9A\u4E49\u6570\u636E\u96C6\u6240\u5173\u8054\u6570\u636E\u88AB\u5220\u9664\u6216\u5B57\u6BB5\u53D1\u751F\u53D8\u5316\uFF0C\u65E0\u6CD5\u6B63\u5E38\u663E\u793A i18n_no_all_delete_privilege_folder=\u8BE5\u76EE\u5F55\u4E0B\u5B58\u5728\u6CA1\u6709\u7BA1\u7406\u6743\u9650\u6216\u67E5\u770B\u6743\u9650\u7684\u8D44\u6E90\uFF0C\u65E0\u6CD5\u5220\u9664 i18n_excel_field_repeat=\u5B58\u5728\u91CD\u590D\u5B57\u6BB5\uFF1A +i18n_dont_contain_key=\u5f53\u524d\u7684sql\u4e0d\u5305\u542b\u8fd9\u4e2a\u952e\uff1a i18n_schema_is_empty=\u6570\u636E\u5E93 Schema \u4E3A\u7A7A \u7AD9\u5185\u6D88\u606F=\u6D88\u606F\u4E2D\u5FC3 \u6240\u6709\u6D88\u606F=\u6240\u6709\u6D88\u606F diff --git a/core/backend/src/main/resources/i18n/messages_zh_TW.properties b/core/backend/src/main/resources/i18n/messages_zh_TW.properties index 1489026291..07f7382d4d 100644 --- a/core/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/core/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -94,6 +94,7 @@ i18n_sql_delete_not_matching=\u589E\u91CF\u522A\u9664 sql \u7684\u6578\u64DA\u52 i18n_cst_ds_tb_or_field_deleted=\u81EA\u5B9A\u7FA9\u6578\u64DA\u96C6\u6240\u95DC\u806F\u6578\u64DA\u88AB\u522A\u9664\u6216\u5B57\u6BB5\u767C\u751F\u8B8A\u5316\uFF0C\u7121\u6CD5\u6B63\u5E38\u986F\u793A i18n_no_all_delete_privilege_folder=\u8A72\u76EE\u9304\u4E0B\u5B58\u5728\u6C92\u6709\u7BA1\u7406\u6B0A\u9650\u6216\u67E5\u770B\u6B0A\u9650\u7684\u8CC7\u6E90\uFF0C\u7121\u6CD5\u522A\u9664 i18n_excel_field_repeat=\u5B58\u5728\u91CD\u5FA9\u5B57\u6BB5\uFF1A +i18n_dont_contain_key=\u7576\u524d\u7684sql\u4e0d\u5305\u542b\u9019\u500b\u9375\uff1a i18n_schema_is_empty=\u6578\u64DA\u5EAB Schema \u70BA\u7A7A \u7AD9\u5185\u6D88\u606F=\u6D88\u606F\u4E2D\u5FC3 \u6240\u6709\u6D88\u606F=\u6240\u6709\u6D88\u606F diff --git a/core/backend/src/main/resources/logback.xml b/core/backend/src/main/resources/logback.xml index c581df7eeb..54b22c9778 100644 --- a/core/backend/src/main/resources/logback.xml +++ b/core/backend/src/main/resources/logback.xml @@ -19,10 +19,10 @@ ${logging.file.path}/history/debug.%d{yyyyMMdd}-%i.log - 30 + ${logging.file.history} - 50MB + ${logging.file.size} @@ -40,10 +40,10 @@ ${logging.file.path}/history/info.%d{yyyyMMdd}-%i.log - 30 + ${logging.file.history} - 50MB + ${logging.file.size} @@ -64,10 +64,10 @@ ${logging.file.path}/history/error.%d{yyyyMMdd}-%i.log - 30 + ${logging.file.history} - 50MB + ${logging.file.size} @@ -87,10 +87,10 @@ ${logging.file.path}/history/warn.%d{yyyyMMdd}-%i.log - 30 + ${logging.file.history} - 50MB + ${logging.file.size} diff --git a/core/frontend/package.json b/core/frontend/package.json index 89d45c3b37..62bd8cfb8f 100644 --- a/core/frontend/package.json +++ b/core/frontend/package.json @@ -1,6 +1,6 @@ { "name": "dataease", - "version": "1.18.14", + "version": "1.18.15", "description": "dataease front", "private": true, "scripts": { diff --git a/core/frontend/src/api/chart/chart.js b/core/frontend/src/api/chart/chart.js index f812769b75..dea06f253f 100644 --- a/core/frontend/src/api/chart/chart.js +++ b/core/frontend/src/api/chart/chart.js @@ -28,7 +28,7 @@ export function getChartTree(data) { }) } -export function chartCopy(id, panelId) { +export async function chartCopy(id, panelId) { return request({ url: '/chart/view/chartCopy/' + id + '/' + panelId, method: 'post', @@ -36,7 +36,7 @@ export function chartCopy(id, panelId) { }) } -export function chartBatchCopy(params, panelId) { +export async function chartBatchCopy(params, panelId) { return request({ url: '/chart/view/chartBatchCopy/' + panelId, method: 'post', diff --git a/core/frontend/src/components/canvas/components/TextAttr.vue b/core/frontend/src/components/canvas/components/TextAttr.vue index 10580991ca..3927cb7f25 100644 --- a/core/frontend/src/components/canvas/components/TextAttr.vue +++ b/core/frontend/src/components/canvas/components/TextAttr.vue @@ -81,7 +81,7 @@ > @@ -105,7 +105,7 @@ > @@ -129,7 +129,7 @@ > @@ -154,7 +154,7 @@ > @@ -178,7 +178,7 @@ > @@ -202,7 +202,7 @@ > @@ -227,7 +227,7 @@ > @@ -253,7 +253,7 @@
@@ -275,7 +275,7 @@
@@ -298,7 +298,7 @@
@@ -466,34 +466,34 @@ export default { initFontSize: 12, initActiveFontSize: 18, miniFontSize: 12, - maxFontSize: 256, + maxFontSize: 48, textAlignOptions: [ { - icon: 'iconfont icon-juzuo', + icon: 'iconfont iconfont-custom icon-juzuo', tooltip: this.$t('panel.text_align_left'), label: 'left' }, { - icon: 'iconfont icon-align-center', + icon: 'iconfont iconfont-custom icon-align-center', tooltip: this.$t('panel.text_align_center'), label: 'center' }, { - icon: 'iconfont icon-juyou', + icon: 'iconfont iconfont-custom icon-juyou', tooltip: this.$t('panel.text_align_right'), label: 'right' } ], lineStyle: [{ - icon: 'iconfont icon-solid_line', + icon: 'iconfont iconfont-custom icon-solid_line', value: 'solid', label: '实线' }, { - icon: 'iconfont icon-xuxian', + icon: 'iconfont iconfont-custom icon-xuxian', value: 'dashed', label: '虚线' }, { - icon: 'iconfont icon-dianxian', + icon: 'iconfont iconfont-custom icon-dianxian', value: 'dotted', label: '点线' }], @@ -802,4 +802,9 @@ export default { -moz-appearance: textfield !important; } +div { + line-height: 24px; + font-size: 16px; +} + diff --git a/core/frontend/src/components/canvas/components/editor/CanvasOptBar.vue b/core/frontend/src/components/canvas/components/editor/CanvasOptBar.vue index d81fb40174..521b199f0b 100644 --- a/core/frontend/src/components/canvas/components/editor/CanvasOptBar.vue +++ b/core/frontend/src/components/canvas/components/editor/CanvasOptBar.vue @@ -9,7 +9,7 @@ v-if="isPublicLink" ref="widget-div" class="function-div" - :class="functionClass" + :class="[{['function-back-div']: backToTopBtn},functionClass]" > {{ $t('panel.down') }} @@ -48,15 +48,8 @@ style="width: 12px;height: 12px" :icon-class="fullscreenState?'public_fullscreen_exit':'public_fullscreen'" />{{ fullscreenState?$t('panel.fullscreen_exit'): $t('panel.fullscreen_preview') }} - {{ $t('panel.back_to_top') }}
-
{{ $t('panel.back_to_top') }}
+
@@ -106,7 +109,7 @@ export default { }, computed: { isPcTerminal() { - return this.terminal === 'PC' + return this.terminal === 'pc' }, functionClass() { let result = 'function-light' @@ -131,7 +134,7 @@ export default { return this.$route.query.fromLink === 'true' }, containerClass() { - return this.isPublicLink ? 'trans-pc' : 'bar-main' + return this.isPublicLink && this.isPcTerminal ? 'trans-pc' : 'bar-main' }, ...mapState([ 'componentData' @@ -181,7 +184,10 @@ export default { window.location.reload() return false } else { - this.$router.back(-1) + const parentUrl = localStorage.getItem('beforeJumpUrl') + localStorage.removeItem('beforeJumpUrl') + window.location.href = parentUrl + window.location.reload() } }, exportPDF() { @@ -293,4 +299,14 @@ export default { } } + .link-public { + top: -49px; + right: 8px; + opacity: 0.8; + position: absolute; + } + + .function-back-div { + right: 100px!important; + } diff --git a/core/frontend/src/components/canvas/components/editor/ComponentWrapper.vue b/core/frontend/src/components/canvas/components/editor/ComponentWrapper.vue index dc72d49103..f21f974610 100644 --- a/core/frontend/src/components/canvas/components/editor/ComponentWrapper.vue +++ b/core/frontend/src/components/canvas/components/editor/ComponentWrapper.vue @@ -149,6 +149,10 @@ export default { isRelation: { type: Boolean, default: false + }, + userId: { + type: String, + require: false } }, data() { diff --git a/core/frontend/src/components/canvas/components/editor/LinkageField.vue b/core/frontend/src/components/canvas/components/editor/LinkageField.vue index d70fdc6bbe..0dc4dc7b73 100644 --- a/core/frontend/src/components/canvas/components/editor/LinkageField.vue +++ b/core/frontend/src/components/canvas/components/editor/LinkageField.vue @@ -184,10 +184,15 @@ export default { // 初始化映射关系 如果当前是相同的数据集且没有关联关系,则自动补充映射关系 checkSameDataSet(this.curLinkageView.propValue.viewId, this.element.propValue.viewId).then(res => { const chartDetails = JSON.parse(this.panelViewDetailsInfo[this.curLinkageView.propValue.viewId]) - const curCheckAllAxisStr = chartDetails.xaxis + chartDetails.xaxisExt + chartDetails.yaxis + chartDetails.yaxisExt + let curCheckAllAxisStr = chartDetails.xaxis + chartDetails.xaxisExt + chartDetails.yaxis + chartDetails.yaxisExt + if (chartDetails.type === 'bar-time-range') { + curCheckAllAxisStr = chartDetails.xaxis + chartDetails.yaxis + chartDetails.yaxisExt + } const targetChartDetails = JSON.parse(this.panelViewDetailsInfo[this.element.propValue.viewId]) - const targetCheckAllAxisStr = targetChartDetails.xaxis + targetChartDetails.xaxisExt + targetChartDetails.yaxis + targetChartDetails.yaxisExt - + let targetCheckAllAxisStr = targetChartDetails.xaxis + targetChartDetails.xaxisExt + targetChartDetails.yaxis + targetChartDetails.yaxisExt + if (targetChartDetails.type === 'bar-time-range') { + targetCheckAllAxisStr = targetChartDetails.xaxis + targetChartDetails.yaxis + targetChartDetails.yaxisExt + } if (res.data === 'YES' && this.linkageInfo.linkageFields.length === 0) { this.sourceLinkageInfo.targetViewFields.forEach(item => { if (curCheckAllAxisStr.includes(item.id) && targetCheckAllAxisStr.includes(item.id)) { diff --git a/core/frontend/src/components/canvas/components/editor/Preview.vue b/core/frontend/src/components/canvas/components/editor/Preview.vue index 1cbca01509..5868dc1b7f 100644 --- a/core/frontend/src/components/canvas/components/editor/Preview.vue +++ b/core/frontend/src/components/canvas/components/editor/Preview.vue @@ -116,15 +116,39 @@ v-if="chartDetailsVisible" style="position: absolute;right: 70px;top:15px" > - - {{ $t('chart.export_img') }} - + + + 导出分辨率 + + + + + + + + {{ $t('chart.export_img') }} + + + { + this.$refs['userViewDialog-canvas-main'].exportViewImg(this.pixel, () => { this.imageDownloading = false }) }, @@ -785,6 +854,7 @@ export default { canvasScroll() { // 当滚动距离超过 100px 时显示返回顶部按钮,否则隐藏按钮 this.backToTopBtnShow = this.$refs[this.previewOutRefId].scrollTop > 200 + console.log('top=' + this.$refs[this.previewOutRefId].scrollTop + ';this.backToTopBtnShow=' + this.backToTopBtnShow) bus.$emit('onScroll') }, initListen() { diff --git a/core/frontend/src/components/canvas/customComponent/DeRichText.vue b/core/frontend/src/components/canvas/customComponent/DeRichText.vue index 613b543495..e6f3378267 100644 --- a/core/frontend/src/components/canvas/customComponent/DeRichText.vue +++ b/core/frontend/src/components/canvas/customComponent/DeRichText.vue @@ -175,7 +175,8 @@ export default { const range = document.createRange() const sel = window.getSelection() if (myDiv.childNodes) { - range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1], 1) + range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1] + .childNodes[myDiv.childNodes[myDiv.childNodes.length - 1].childNodes.length - 1], 1) range.collapse(false) sel.removeAllRanges() sel.addRange(range) diff --git a/core/frontend/src/components/canvas/customComponent/DeRichTextView.vue b/core/frontend/src/components/canvas/customComponent/DeRichTextView.vue index 78598a00e8..fba9a5c46d 100644 --- a/core/frontend/src/components/canvas/customComponent/DeRichTextView.vue +++ b/core/frontend/src/components/canvas/customComponent/DeRichTextView.vue @@ -250,7 +250,9 @@ export default { const range = document.createRange() const sel = window.getSelection() if (myDiv.childNodes) { - range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1], 1) + range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1] + .childNodes[myDiv.childNodes[myDiv.childNodes.length - 1].childNodes.length - 1], + myDiv.childNodes[myDiv.childNodes.length - 1].childNodes[myDiv.childNodes[myDiv.childNodes.length - 1].childNodes.length - 1].length) range.collapse(false) sel.removeAllRanges() sel.addRange(range) diff --git a/core/frontend/src/components/canvas/customComponent/UserView.vue b/core/frontend/src/components/canvas/customComponent/UserView.vue index e24a7da4f5..c0ddd49f96 100644 --- a/core/frontend/src/components/canvas/customComponent/UserView.vue +++ b/core/frontend/src/components/canvas/customComponent/UserView.vue @@ -154,15 +154,39 @@ v-if="chartDetailsVisible" style="position: absolute;right: 70px;top:15px" > - - {{ $t('chart.export_img') }} - + + + 导出分辨率 + + + + + + + + {{ $t('chart.export_img') }} + + + @@ -318,6 +343,10 @@ export default { type: String, require: false, default: 'preview' + }, + userId: { + type: String, + require: false } }, data() { @@ -367,7 +396,44 @@ export default { show: 0 }, view: {}, - cancelTime: null + cancelTime: null, + pixelOptions: [ + { + label: 'Windows(16:9)', + options: [ + { + value: '1920 * 1080', + label: '1920 * 1080' + }, + { + value: '1600 * 900', + label: '1600 * 900' + }, + { + value: '1280 * 720', + label: '1280 * 720' + } + ] + }, + { + label: 'MacOS(16:10)', + options: [ + { + value: '2560 * 1600', + label: '2560 * 1600' + }, + { + value: '1920 * 1200', + label: '1920 * 1200' + }, + { + value: '1680 * 1050', + label: '1680 * 1050' + } + ] + } + ], + pixel: '1280 * 720' } }, @@ -685,7 +751,7 @@ export default { }, exportViewImg() { this.imageDownloading = true - this.$refs['userViewDialog'].exportViewImg(() => { + this.$refs['userViewDialog'].exportViewImg(this.pixel, () => { this.imageDownloading = false }) }, @@ -786,10 +852,9 @@ export default { param.viewId && param.viewId === this.element.propValue.viewId && this.getDataEdit(param) }, clearPanelLinkage(param) { - console.log('clear linkage') if (param.viewId === 'all' || param.viewId === this.element.propValue.viewId) { try { - // do nothing + this.$refs[this.element.propValue.id]?.clearLinkage?.() } catch (e) { console.error('reDrawView-error:', this.element.propValue.id) } @@ -1110,7 +1175,7 @@ export default { } }) } - if (!jumpInfo) { + if (!jumpInfo && !this.chart.type.includes('table')) { for (let i = param.dimensionList.length - 1; i >= 0; i--) { dimension = param.dimensionList[i] sourceInfo = param.viewId + '#' + dimension.id diff --git a/core/frontend/src/components/canvas/customComponent/UserViewDialog.vue b/core/frontend/src/components/canvas/customComponent/UserViewDialog.vue index 52fdbf2d85..417294cd07 100644 --- a/core/frontend/src/components/canvas/customComponent/UserViewDialog.vue +++ b/core/frontend/src/components/canvas/customComponent/UserViewDialog.vue @@ -13,7 +13,6 @@ >
@@ -23,6 +22,7 @@ > @@ -90,6 +96,8 @@ import LabelNormalText from '@/views/chart/components/normal/LabelNormalText' import html2canvas from 'html2canvasde' import { hexColorToRGBA } from '@/views/chart/chart/util' import { deepCopy, exportExcelDownload, exportImg, imgUrlTrans } from '@/components/canvas/utils/utils' +import { activeWatermark } from '@/components/canvas/tools/watermark' +import { proxyUserLoginInfo, userLoginInfo } from '@/api/systemInfo/userLogin' export default { name: 'UserViewDialog', @@ -116,6 +124,10 @@ export default { openType: { type: String, default: 'details' + }, + userId: { + type: String, + require: false } }, @@ -126,7 +138,8 @@ export default { lastMapChart: null, linkLoading: false, exporting: false, - exportLoading: false + exportLoading: false, + pixel: '1280 * 720' } }, computed: { @@ -144,6 +157,13 @@ export default { }, customStyle() { let style = {} + if (this.exporting) { + const bashStyle = this.pixel.split(' * ') + style = { + width: bashStyle[0] + 'px!important', + height: bashStyle[1] + 'px!important' + } + } if (this.canvasStyleData.openCommonStyle) { if (this.canvasStyleData.panel.backgroundType === 'image' && this.canvasStyleData.panel.imageUrl) { style = { @@ -244,8 +264,22 @@ export default { this.element = deepCopy(this.curComponent) }, mounted() { + this.initWatermark() }, methods: { + initWatermark(waterDomId = 'chartCanvas') { + if (this.panelInfo.watermarkInfo) { + if (this.userInfo) { + activeWatermark(this.panelInfo.watermarkInfo.settingContent, this.userInfo, waterDomId, 'canvas-main', this.panelInfo.watermarkOpen, 'de-watermark-view') + } else { + const method = this.userId ? proxyUserLoginInfo : userLoginInfo + method().then(res => { + this.userInfo = res.data + activeWatermark(this.panelInfo.watermarkInfo.settingContent, this.userInfo, waterDomId, 'canvas-main', this.panelInfo.watermarkOpen, 'de-watermark-view') + }) + } + } + }, exportExcel(callBack) { const _this = this if (this.isOnlyDetails) { @@ -261,13 +295,17 @@ export default { } } }, - exportViewImg(callback) { + exportViewImg(pixel, callback) { + this.pixel = pixel this.exportLoading = true this.$nextTick(() => { this.exporting = true + this.resizeChart() setTimeout(() => { + this.initWatermark() exportImg(this.chart.name, (params) => { this.exporting = false + this.resizeChart() setTimeout(() => { this.exportLoading = false }, 500) @@ -286,6 +324,13 @@ export default { renderComponent() { return this.chart.render + }, + resizeChart() { + if (this.$refs[this.element.propValue.id]) { + this.chart.isPlugin + ? this.$refs[this.element.propValue.id].callPluginInner({ methodName: 'chartResize' }) + : this.$refs[this.element.propValue.id].chartResize() + } } } } @@ -320,8 +365,8 @@ export default { background-size: 100% 100% !important; } .canvas-class-exporting { - width: 1080px!important; - height: 560px!important; + width: 1980px!important; + height: 860px!important; } .abs-container { diff --git a/core/frontend/src/components/canvas/customComponent/UserViewMobileDialog.vue b/core/frontend/src/components/canvas/customComponent/UserViewMobileDialog.vue index 50d142f3e3..cf8762fe8d 100644 --- a/core/frontend/src/components/canvas/customComponent/UserViewMobileDialog.vue +++ b/core/frontend/src/components/canvas/customComponent/UserViewMobileDialog.vue @@ -6,6 +6,7 @@ class="full-div" >
@@ -70,6 +71,8 @@ import ChartComponentS2 from '@/views/chart/components/ChartComponentS2' import PluginCom from '@/views/system/plugin/PluginCom' import { deepCopy, imgUrlTrans } from '@/components/canvas/utils/utils' import { hexColorToRGBA } from '@/views/chart/chart/util' +import {activeWatermark} from "@/components/canvas/tools/watermark"; +import {proxyUserLoginInfo, userLoginInfo} from "@/api/systemInfo/userLogin"; export default { name: 'UserViewMobileDialog', components: { ChartComponentS2, LabelNormalText, DeContainer, DeMainContainer, ChartComponentG2, ChartComponent, TableNormal, LabelNormal, PluginCom }, @@ -81,6 +84,10 @@ export default { chartTable: { type: Object, default: null + }, + userId: { + type: String, + require: false } }, @@ -180,6 +187,19 @@ export default { this.element = deepCopy(this.curComponent) }, methods: { + initWatermark(waterDomId = 'chartCanvas') { + if (this.panelInfo.watermarkInfo) { + if (this.userInfo) { + activeWatermark(this.panelInfo.watermarkInfo.settingContent, this.userInfo, waterDomId, 'canvas-main', this.panelInfo.watermarkOpen, 'de-watermark-view') + } else { + const method = this.userId ? proxyUserLoginInfo : userLoginInfo + method().then(res => { + this.userInfo = res.data + activeWatermark(this.panelInfo.watermarkInfo.settingContent, this.userInfo, waterDomId, 'canvas-main', this.panelInfo.watermarkOpen, 'de-watermark-view') + }) + } + } + }, renderComponent() { return this.chart.render diff --git a/core/frontend/src/components/canvas/customComponent/component-list.js b/core/frontend/src/components/canvas/customComponent/component-list.js index 08146c3716..dfc5e1e420 100644 --- a/core/frontend/src/components/canvas/customComponent/component-list.js +++ b/core/frontend/src/components/canvas/customComponent/component-list.js @@ -383,8 +383,8 @@ const list = [ mobileStyle: BASE_MOBILE_STYLE, hyperlinks: HYPERLINKS, style: { - width: 200, - height: 200, + width: 400, + height: 400, borderStyle: 'solid', borderWidth: 0, borderColor: '#000000', diff --git a/core/frontend/src/components/canvas/store/copy.js b/core/frontend/src/components/canvas/store/copy.js index 6232614813..75a8e22fc5 100644 --- a/core/frontend/src/components/canvas/store/copy.js +++ b/core/frontend/src/components/canvas/store/copy.js @@ -91,6 +91,7 @@ export default { component['canvasId'] = 'canvas-main' component['canvasPid'] = '0' state.copyData = { + dataFrom: 'multiplexing', data: component, index: index } @@ -107,10 +108,17 @@ export default { state.isCut = false }, - paste(state, needAdaptor) { + async paste(state, needAdaptor) { if (!state.copyData) { return } + let targetComponentData + + if (state.copyData.dataFrom === 'multiplexing') { + targetComponentData = state.previewComponentData + } else { + targetComponentData = state.componentData + } const data = state.copyData.data // 仪表板复制的组件默认不在移动端部署中mobileSelected = false data.mobileSelected = false @@ -118,7 +126,6 @@ export default { data.style.top = Number(data.style.top) + 20 data.style.left = Number(data.style.left) + 20 } - data.id = generateID() // 如果是用户视图 测先进行底层复制 if (data.type === 'view') { chartCopy(data.propValue.viewId, state.panel.panelInfo.id).then(res => { @@ -137,6 +144,7 @@ export default { store.commit('addComponent', { component: newView }) }) } else if (data.type === 'de-tabs') { + const newTabComponents = [] const sourceAndTargetIds = {} const newCop = deepCopy(data) newCop.id = uuid.v1() @@ -149,14 +157,35 @@ export default { if (item.content.filters && item.content.filters.length) { item.content.filters = [] } + } else if (item.content && item.content.type === 'canvas') { + const oldTabCanvasId = data.id + '-' + item.name + const newTabCanvasId = newCop.id + '-' + item.name + targetComponentData.forEach(component => { + if (component.canvasId === oldTabCanvasId) { + const newTabCop = deepCopy(component) + newTabCop.id = uuid.v1() + newTabCop.canvasId = newTabCanvasId + if (component.component === 'user-view') { + newTabCop.propValue.viewId = uuid.v1() + sourceAndTargetIds[component.propValue.viewId] = newTabCop.propValue.viewId + } + if (needAdaptor && store.state.multiplexingStyleAdapt) { + adaptCurThemeCommonStyle(newTabCop, 'copy') + } + newTabComponents.push(newTabCop) + } + }) } }) - chartBatchCopy({ 'sourceAndTargetIds': sourceAndTargetIds }, state.panel.panelInfo.id).then((rsp) => { + await chartBatchCopy({ 'sourceAndTargetIds': sourceAndTargetIds }, state.panel.panelInfo.id).then((rsp) => { if (needAdaptor && store.state.multiplexingStyleAdapt) { adaptCurThemeCommonStyle(newCop, 'copy') } store.commit('addComponent', { component: newCop }) }) + if (newTabComponents) { + store.commit('addBatchComponent', newTabComponents) + } } else { const newCop = deepCopy(data) newCop.id = uuid.v1() diff --git a/core/frontend/src/components/canvas/tools/watermark.js b/core/frontend/src/components/canvas/tools/watermark.js index a70aa07757..a606127a74 100644 --- a/core/frontend/src/components/canvas/tools/watermark.js +++ b/core/frontend/src/components/canvas/tools/watermark.js @@ -1,6 +1,6 @@ // 动态创建水印元素的封装函数 -export function watermark(settings, domId) { +export function watermark(settings, domId, watermarkDomId = 'de-watermark-server') { const watermarkDom = document.getElementById(domId) // 默认设置 const defaultSettings = { @@ -85,7 +85,7 @@ export function watermark(settings, domId) { oTemp.appendChild(mask_div) } } - oTemp.setAttribute('id', 'de-watermark-server') + oTemp.setAttribute('id', watermarkDomId) watermarkDom.appendChild(oTemp) } @@ -109,9 +109,9 @@ export function getNow() { return time } -export function activeWatermark(watermarkForm, userLoginInfo, domId, canvasId, watermarkOpen) { +export function activeWatermark(watermarkForm, userLoginInfo, domId, canvasId, watermarkOpen, watermarkDomId = 'de-watermark-server') { // 清理历史水印 - const historyWatermarkDom = document.getElementById('de-watermark-server') + const historyWatermarkDom = document.getElementById(watermarkDomId) if (historyWatermarkDom) { historyWatermarkDom.remove() } @@ -148,7 +148,7 @@ export function activeWatermark(watermarkForm, userLoginInfo, domId, canvasId, w watermark_y_space: watermarkForm.watermark_y_space, watermark_fontsize: watermarkForm.watermark_fontsize + 'px' } - watermark(settings, domId) + watermark(settings, domId, watermarkDomId) } export default { watermark, getNow, activeWatermark } diff --git a/core/frontend/src/components/canvas/utils/utils.js b/core/frontend/src/components/canvas/utils/utils.js index 19ed237940..4e6d3ce266 100644 --- a/core/frontend/src/components/canvas/utils/utils.js +++ b/core/frontend/src/components/canvas/utils/utils.js @@ -85,6 +85,7 @@ export function panelInit(componentData, componentStyle) { } export function panelDataPrepare(componentData, componentStyle, callback) { + store.commit('initPanelViewDetailsInfo') // style初始化 componentStyle.autoSizeAdaptor = (componentStyle.autoSizeAdaptor === undefined ? true : componentStyle.autoSizeAdaptor) componentStyle.refreshTime = (componentStyle.refreshTime || 5) @@ -226,6 +227,11 @@ export function checkViewTitle(opt, id, tile) { export function exportImg(imgName, callback) { const canvasID = document.getElementById('chartCanvas') const a = document.createElement('a') + // 保存原始的设备像素比值 + const originalDPR = window.devicePixelRatio + + // 将设备像素比设置为1 + window.devicePixelRatio = 1 html2canvas(canvasID).then(canvas => { const dom = document.body.appendChild(canvas) dom.style.display = 'none' @@ -238,8 +244,10 @@ export function exportImg(imgName, callback) { a.click() URL.revokeObjectURL(blob) document.body.removeChild(a) + window.devicePixelRatio = originalDPR callback() }).catch(() => { + window.devicePixelRatio = originalDPR callback() }) } diff --git a/core/frontend/src/components/widget/deWidget/DeSelect.vue b/core/frontend/src/components/widget/deWidget/DeSelect.vue index 94f7eabab2..3baf0596a6 100644 --- a/core/frontend/src/components/widget/deWidget/DeSelect.vue +++ b/core/frontend/src/components/widget/deWidget/DeSelect.vue @@ -554,6 +554,7 @@ export default { if (this.isCustomSortWidget && this.element.options.attrs?.sort?.sort === 'custom') { tempData = mergeCustomSortOption(this.element.options.attrs.sort.list, tempData) } + this.filterInvalidValue(tempData) return tempData.map(item => { return { id: item, @@ -561,6 +562,20 @@ export default { } }) }, + filterInvalidValue(data) { + if (this.value === null) { + return + } + if (!data.length) { + this.value = null + return + } + if (this.element.options.attrs.multiple) { + this.value = this.value.filter(item => data.includes(item)) + } else { + this.value = data.includes(this.value) ? this.value : null + } + }, setOptionWidth(event) { this.onFocus = true // 下拉框弹出时,设置弹框的宽度 diff --git a/core/frontend/src/components/widget/deWidget/DeTabs.vue b/core/frontend/src/components/widget/deWidget/DeTabs.vue index 3d2d2f35ba..f4fa0121e2 100644 --- a/core/frontend/src/components/widget/deWidget/DeTabs.vue +++ b/core/frontend/src/components/widget/deWidget/DeTabs.vue @@ -74,7 +74,7 @@ />
{ if (this.element.options.tabList.length > 1) { const containerDom = document.getElementById('tab-' + this.element.options.tabList[this.element.options.tabList.length - 1].name) - this.tabsAreaScroll = containerDom.parentNode.scrollWidth > containerDom.parentNode.parentNode.scrollWidth + this.tabsAreaScroll = containerDom.parentNode.scrollWidth >= containerDom.parentNode.parentNode.scrollWidth } else { this.tabsAreaScroll = false } diff --git a/core/frontend/src/components/widget/serviceImpl/NumberSelectGridServiceImpl.js b/core/frontend/src/components/widget/serviceImpl/NumberSelectGridServiceImpl.js index 986e130e91..1fcc97608e 100644 --- a/core/frontend/src/components/widget/serviceImpl/NumberSelectGridServiceImpl.js +++ b/core/frontend/src/components/widget/serviceImpl/NumberSelectGridServiceImpl.js @@ -13,6 +13,7 @@ const dialogPanel = { multiple: false, placeholder: 'denumbergridselect.placeholder', viewIds: [], + parameters: [], data: [], key: 'id', label: 'text', diff --git a/core/frontend/src/lang/en.js b/core/frontend/src/lang/en.js index d5b09590f6..d9b403bccf 100644 --- a/core/frontend/src/lang/en.js +++ b/core/frontend/src/lang/en.js @@ -382,6 +382,7 @@ export default { thumbnail: 'thumbnail', confirm_delete: 'Confirm delete', delete_this_dashboard: 'Are you sure to delete this dashboard?', + cancel_this_dashboard: 'Are you sure to cancel this default dashboard?', delete_this_folder: 'Are you sure to delete this folder?', confirm_stop: 'Confirm stop', stop_success: 'Stop success', @@ -840,6 +841,7 @@ export default { empty_msg: 'If empty then default value is 30 days', front_error: 'Valid range [0 - 300]', // 修改了提示信息 msg_error: 'Valid range [1 - 365]', + log_live_time_error: 'Valid range [1 - 4000]', limit_times_error: 'Valid range [1 - 100]', relieve_times_error: 'Valid range [1 - 100]', SMTP_port: 'SMTP Port', @@ -1111,6 +1113,7 @@ export default { asc: 'Ascending Order', desc: 'Descending Order', sort: 'Sort', + default: 'Default', filter: 'Filter', is_set: 'Is Set', none: 'None', @@ -1874,7 +1877,11 @@ export default { tip6: 'Use the functions supported by the database type corresponding to the dataset. The syntax is the same as that of the corresponding database', tip7: 'For example, date format: MySQL uses DATE_ FORMAT(date,format); Oracle uses TO_ DATE(X,[,fmt])', tip8: 'Non direct connection mode data set, use Doris database functions, refer to Doris official website' - } + }, + set_key: 'Set Primary Key', + change_to_key: 'Set as primary key', + selecet_key: 'Select primary key', + no_set_key: 'No primary key set' }, driver: { driver: 'Driver', @@ -2054,6 +2061,7 @@ export default { back_parent: 'Back to previous' }, panel: { + app_export_tips: 'In the current dashboard, [{0}] belongs to a template view and cannot be exported. Please set up the dataset first!', required_tips: 'Cannot be empty!', filter_no_select: 'Filter components do not need to be selected', first_item: 'First item', diff --git a/core/frontend/src/lang/tw.js b/core/frontend/src/lang/tw.js index dc821f49a1..f93ed158c5 100644 --- a/core/frontend/src/lang/tw.js +++ b/core/frontend/src/lang/tw.js @@ -382,6 +382,7 @@ export default { thumbnail: '縮略圖', confirm_delete: '確認刪除', delete_this_dashboard: '確認删除該儀錶板嗎?', + cancel_this_dashboard: '確認取消該默认儀錶板嗎?', delete_this_folder: '確認删除該目錄嗎?', confirm_stop: '確認停止', stop_success: '停止成功', @@ -839,6 +840,7 @@ export default { empty_msg: '為空則默認取值30天', front_error: '請填寫0-300正整數', // 修改了提示信息 msg_error: '請填寫1-365正整數', + log_live_time_error: '請填寫1-4000正整數', limit_times_error: '請填寫1-100正整數', relieve_times_error: '請填寫1-100正整數', SMTP_port: 'SMTP端口', @@ -1111,6 +1113,7 @@ export default { asc: '升序', desc: '降序', sort: '排序', + default: '默認', filter: '過濾', is_set: '已設定', none: '無', @@ -1866,7 +1869,11 @@ export default { tip6: '使用數據集對應數據庫類型所支持的函數,語法同對應數據庫', tip7: '如日期格式化:MySQL使用DATE_FORMAT(date,format);Oracle使用TO_DATE(X,[,fmt])', tip8: '非直連模式數據集,使用Doris數據庫函數,可參考Doris官網' - } + }, + set_key: '設定主鍵', + change_to_key: '設定為主鍵', + selecet_key: '選擇主鍵', + no_set_key: '未設定主鍵' }, driver: { driver: '驅動', @@ -2046,6 +2053,7 @@ export default { back_parent: '返回上一級' }, panel: { + app_export_tips: '當前儀表板中[{0}]屬於模板視圖,無法導出,請先設置數據集!', required_tips: '必填項不能爲空!', filter_no_select: '過濾組件無需選擇', first_item: '首項', diff --git a/core/frontend/src/lang/zh.js b/core/frontend/src/lang/zh.js index 85eac6ce96..1232d29d2f 100644 --- a/core/frontend/src/lang/zh.js +++ b/core/frontend/src/lang/zh.js @@ -381,6 +381,7 @@ export default { thumbnail: '缩略图', confirm_delete: '确认删除', delete_this_dashboard: '确认删除该仪表板吗?', + cancel_this_dashboard: '确认取消该默认仪表板吗?', delete_this_folder: '确认删除该目录吗?', confirm_stop: '确认停止', stop_success: '停止成功', @@ -934,7 +935,8 @@ export default { edit_classification: '编辑分类', classification_name: '分类名称', by_event_details: '通过事件详情搜索', - password_input_error: '原始密码输入错误' + password_input_error: '原始密码输入错误', + log_live_time_error: '请填写1-4000整数' }, chart: { empty_hide: '隐藏空值', @@ -1110,6 +1112,7 @@ export default { asc: '升序', desc: '降序', sort: '排序', + default: '默认', filter: '过滤', is_set: '已设置', none: '无', @@ -1866,7 +1869,11 @@ export default { tip6: '使用数据集对应数据库类型所支持的函数,语法同对应数据库', tip7: '如日期格式化:MySQL使用DATE_FORMAT(date,format);Oracle使用TO_DATE(X,[,fmt])', tip8: '非直连模式数据集,使用Doris数据库函数,可参考Doris官网' - } + }, + set_key: '设置主键', + change_to_key: '设置为主键', + selecet_key: '选择主键', + no_set_key: '未设置主键' }, driver: { driver: '驱动', @@ -2049,6 +2056,7 @@ export default { back_parent: '返回上一级' }, panel: { + app_export_tips: '当前仪表板中[{0}]属于模版视图,无法导出,请先设置数据集!', required_tips: '必填项不能为空!', filter_no_select: '过滤组件无需选择', first_item: '首项', diff --git a/core/frontend/src/main.js b/core/frontend/src/main.js index dc12881242..5ec48c4daa 100644 --- a/core/frontend/src/main.js +++ b/core/frontend/src/main.js @@ -32,7 +32,9 @@ import '@/utils/DateUtil' import draggable from 'vuedraggable' import deWebsocket from '@/websocket' import { GaodeMap } from '@antv/l7-maps' +import { Mix } from '@antv/g2plot' import * as echarts from 'echarts' +import { clear } from 'size-sensor' import UmyUi from 'umy-ui' // 全屏插件 import fullscreen from 'vue-fullscreen' @@ -58,6 +60,8 @@ Vue.prototype.$api = api Vue.prototype.$echarts = echarts Vue.prototype.$gaodeMap = GaodeMap +Vue.prototype.$Mix = Mix +Vue.prototype.$G2SizeSensorClear = clear Vue.use(UmyUi) diff --git a/core/frontend/src/mobile/main.js b/core/frontend/src/mobile/main.js index 8801d4afd3..edb130855b 100644 --- a/core/frontend/src/mobile/main.js +++ b/core/frontend/src/mobile/main.js @@ -31,6 +31,8 @@ import '@/utils/DateUtil' import draggable from 'vuedraggable' import deWebsocket from '@/websocket' import { GaodeMap } from '@antv/l7-maps' +import { Mix } from '@antv/g2plot' +import { clear } from 'size-sensor' import * as echarts from 'echarts' import UmyUi from 'umy-ui' // 全屏插件 @@ -57,6 +59,8 @@ Vue.prototype.$api = api Vue.prototype.$echarts = echarts Vue.prototype.$gaodeMap = GaodeMap +Vue.prototype.$Mix = Mix +Vue.prototype.$G2SizeSensorClear = clear Vue.use(UmyUi) diff --git a/core/frontend/src/store/index.js b/core/frontend/src/store/index.js index d8ee5e643f..433c78b878 100644 --- a/core/frontend/src/store/index.js +++ b/core/frontend/src/store/index.js @@ -275,6 +275,9 @@ const data = { setMobileComponentData(state, mobileComponentData = []) { Vue.set(state, 'mobileComponentData', mobileComponentData) }, + addBatchComponent(state, components = []) { + state.componentData.push(...components) + }, addComponent(state, { component, index }) { if (index !== undefined) { state.componentData.splice(index, 0, component) @@ -841,6 +844,9 @@ const data = { customAttr: {} } }, + initPanelViewDetailsInfo(state) { + state.panelViewDetailsInfo = {} + }, initCanvas(state) { this.commit('initCanvasBase') state.isInEditor = true diff --git a/core/frontend/src/styles/deicon/demo_index.html b/core/frontend/src/styles/deicon/demo_index.html index ce0939bfac..0fde073f21 100644 --- a/core/frontend/src/styles/deicon/demo_index.html +++ b/core/frontend/src/styles/deicon/demo_index.html @@ -55,9 +55,9 @@
  • - +
    返回顶部
    -
    &#xe667;
    +
    &#xe63f;
  • @@ -828,9 +828,9 @@
    @font-face {
       font-family: 'iconfont';
    -  src: url('iconfont.woff2?t=1705486315942') format('woff2'),
    -       url('iconfont.woff?t=1705486315942') format('woff'),
    -       url('iconfont.ttf?t=1705486315942') format('truetype');
    +  src: url('iconfont.woff2?t=1706079293312') format('woff2'),
    +       url('iconfont.woff?t=1706079293312') format('woff'),
    +       url('iconfont.ttf?t=1706079293312') format('truetype');
     }
     

    第二步:定义使用 iconfont 的样式

    diff --git a/core/frontend/src/styles/deicon/iconfont.css b/core/frontend/src/styles/deicon/iconfont.css index 84e2f644f9..4a9d18eb03 100644 --- a/core/frontend/src/styles/deicon/iconfont.css +++ b/core/frontend/src/styles/deicon/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 2459092 */ - src: url('iconfont.woff2?t=1705486315942') format('woff2'), - url('iconfont.woff?t=1705486315942') format('woff'), - url('iconfont.ttf?t=1705486315942') format('truetype'); + src: url('iconfont.woff2?t=1706079293312') format('woff2'), + url('iconfont.woff?t=1706079293312') format('woff'), + url('iconfont.ttf?t=1706079293312') format('truetype'); } .iconfont { @@ -14,7 +14,7 @@ } .icon-back-top:before { - content: "\e667"; + content: "\e63f"; } .icon-adaptor:before { diff --git a/core/frontend/src/styles/deicon/iconfont.js b/core/frontend/src/styles/deicon/iconfont.js index 250ab59f90..3e7bdbb09e 100644 --- a/core/frontend/src/styles/deicon/iconfont.js +++ b/core/frontend/src/styles/deicon/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_2459092='',function(a){var l=(l=document.getElementsByTagName("script"))[l.length-1],c=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var h,i,t,v,o,z=function(l,c){c.parentNode.insertBefore(l,c)};if(c&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}h=function(){var l,c=document.createElement("div");c.innerHTML=a._iconfont_svg_string_2459092,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(l=document.body).firstChild?z(c,l.firstChild):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),h()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(t=h,v=a.document,o=!1,p(),v.onreadystatechange=function(){"complete"==v.readyState&&(v.onreadystatechange=null,m())})}function m(){o||(o=!0,t())}function p(){try{v.documentElement.doScroll("left")}catch(l){return void setTimeout(p,50)}m()}}(window); \ No newline at end of file +window._iconfont_svg_string_2459092='',function(a){var l=(l=document.getElementsByTagName("script"))[l.length-1],c=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var h,i,t,v,o,z=function(l,c){c.parentNode.insertBefore(l,c)};if(c&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}h=function(){var l,c=document.createElement("div");c.innerHTML=a._iconfont_svg_string_2459092,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(l=document.body).firstChild?z(c,l.firstChild):l.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),h()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(t=h,v=a.document,o=!1,p(),v.onreadystatechange=function(){"complete"==v.readyState&&(v.onreadystatechange=null,m())})}function m(){o||(o=!0,t())}function p(){try{v.documentElement.doScroll("left")}catch(l){return void setTimeout(p,50)}m()}}(window); \ No newline at end of file diff --git a/core/frontend/src/styles/deicon/iconfont.json b/core/frontend/src/styles/deicon/iconfont.json index 019fb540b1..b68b3d8db4 100644 --- a/core/frontend/src/styles/deicon/iconfont.json +++ b/core/frontend/src/styles/deicon/iconfont.json @@ -6,11 +6,11 @@ "description": "", "glyphs": [ { - "icon_id": "831197", + "icon_id": "8224825", "name": "返回顶部", "font_class": "back-top", - "unicode": "e667", - "unicode_decimal": 58983 + "unicode": "e63f", + "unicode_decimal": 58943 }, { "icon_id": "34289857", diff --git a/core/frontend/src/styles/deicon/iconfont.ttf b/core/frontend/src/styles/deicon/iconfont.ttf index 05c72cfad0..5f98b4141f 100644 Binary files a/core/frontend/src/styles/deicon/iconfont.ttf and b/core/frontend/src/styles/deicon/iconfont.ttf differ diff --git a/core/frontend/src/styles/deicon/iconfont.woff b/core/frontend/src/styles/deicon/iconfont.woff index 88c252e4fe..e2c7751ddd 100644 Binary files a/core/frontend/src/styles/deicon/iconfont.woff and b/core/frontend/src/styles/deicon/iconfont.woff differ diff --git a/core/frontend/src/styles/deicon/iconfont.woff2 b/core/frontend/src/styles/deicon/iconfont.woff2 index d65d7dc63c..9646cb562d 100644 Binary files a/core/frontend/src/styles/deicon/iconfont.woff2 and b/core/frontend/src/styles/deicon/iconfont.woff2 differ diff --git a/core/frontend/src/styles/index.scss b/core/frontend/src/styles/index.scss index 2607a2dcb7..13e05fbb47 100644 --- a/core/frontend/src/styles/index.scss +++ b/core/frontend/src/styles/index.scss @@ -170,7 +170,7 @@ div:focus { padding-right: 50px !important; } -.de-tabs { +.de-tabs-component { .el-tabs__header { margin: 0 0 0 0 !important; } @@ -1765,4 +1765,4 @@ div:focus { .el-table__fixed-right::before { display: none; -} \ No newline at end of file +} diff --git a/core/frontend/src/views/chart/chart/bar/bar_antv.js b/core/frontend/src/views/chart/chart/bar/bar_antv.js index 4cea5a2f12..2b848d7908 100644 --- a/core/frontend/src/views/chart/chart/bar/bar_antv.js +++ b/core/frontend/src/views/chart/chart/bar/bar_antv.js @@ -271,7 +271,6 @@ export function timeRangeBarOptionAntV(plot, container, chart, action) { const label = getLabel(chart) if (label && !ifAggregate) { label.layout = [ - { type: 'interval-adjust-position' }, { type: 'interval-hide-overlap' }, { type: 'limit-in-plot', cfg: { action: 'hide' }} ] @@ -296,6 +295,11 @@ export function timeRangeBarOptionAntV(plot, container, chart, action) { // config const slider = getSlider(chart) const analyse = getAnalyse(chart) + + data.forEach(d => { + d.tempId = (Math.random() * 10000000).toString() + }) + // options const options = { theme: theme, @@ -364,7 +368,9 @@ export function timeRangeBarOptionAntV(plot, container, chart, action) { type: 'time', min: minTime, max: maxTime, - mask: 'YYYY-MM-DD HH:mm:ss', + mask: 'YYYY-MM-DD HH:mm:ss' + }, + tempId: { key: true } } @@ -373,7 +379,9 @@ export function timeRangeBarOptionAntV(plot, container, chart, action) { values: { min: minNumber, max: maxNumber, - mask: 'YYYY-MM-DD HH:mm:ss', + mask: 'YYYY-MM-DD HH:mm:ss' + }, + tempId: { key: true } } diff --git a/core/frontend/src/views/chart/chart/table/table-info.js b/core/frontend/src/views/chart/chart/table/table-info.js index aa338ae9b7..21486d11eb 100644 --- a/core/frontend/src/views/chart/chart/table/table-info.js +++ b/core/frontend/src/views/chart/chart/table/table-info.js @@ -1,22 +1,81 @@ -import { TableSheet, BaseEvent, S2Event, PivotSheet, DataCell, EXTRA_FIELD, TOTAL_VALUE } from '@antv/s2' +import { + TableSheet, + S2Event, + PivotSheet, + DataCell, + EXTRA_FIELD, + TOTAL_VALUE, + BaseTooltip, + getAutoAdjustPosition, + getTooltipDefaultOptions, + setTooltipContainerStyle, + SERIES_NUMBER_FIELD +} from '@antv/s2' import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table' import { DEFAULT_COLOR_CASE, DEFAULT_TOTAL } from '@/views/chart/chart/chart' import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter' import { handleTableEmptyStrategy, hexColorToRGBA } from '@/views/chart/chart/util' -import { maxBy, minBy } from 'lodash' +import { maxBy, minBy, find } from 'lodash-es' +import TableTooltip from '@/views/chart/components/table/TableTooltip.vue' +class SortTooltip extends BaseTooltip { + vueCom + constructor(spreadsheet, vueCom) { + super(spreadsheet) + this.vueCom = vueCom + } -class RowHoverInteraction extends BaseEvent { - bindEvents() { - this.spreadsheet.on(S2Event.ROW_CELL_HOVER, (event) => { - this.spreadsheet.tooltip.show({ - position: { x: 0, y: 0 }, - content: '...' - }) + show(showOptions) { + const { iconName } = showOptions + if (iconName) { + this.showSortTooltip(showOptions) + return + } + super.show(showOptions) + } + + showSortTooltip(showOptions) { + const { position, options, meta, event } = showOptions + const { enterable } = getTooltipDefaultOptions(options) + const { autoAdjustBoundary, adjustPosition } = + this.spreadsheet.options.tooltip || {} + this.visible = true + this.options = showOptions + const container = this.getContainer() + // 用 vue 手动 patch + const vNode = this.vueCom.$createElement(TableTooltip, { + props: { + table: this.spreadsheet, + meta + } + }) + this.spreadsheet.tooltip.container.innerHTML = '' + const childElement = document.createElement('div') + this.spreadsheet.tooltip.container.appendChild(childElement) + this.vueCom.__patch__(childElement, vNode, false, true) + + const { x, y } = getAutoAdjustPosition({ + spreadsheet: this.spreadsheet, + position, + tooltipContainer: container, + autoAdjustBoundary + }) + + this.position = adjustPosition?.({ position: { x, y }, event }) ?? { + x, + y + } + + setTooltipContainerStyle(container, { + style: { + left: `${this.position?.x}px`, + top: `${this.position?.y}px`, + pointerEvents: enterable ? 'all' : 'none' + }, + visible: true }) } } - -export function baseTableInfo(s2, container, chart, action, tableData, pageInfo) { +export function baseTableInfo(s2, container, chart, action, tableData, pageInfo, vueCom) { const containerDom = document.getElementById(container) // fields @@ -98,12 +157,55 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo) } const customAttr = JSON.parse(chart.customAttr) + const sortIconMap = { + 'asc': 'SortUp', + 'desc': 'SortDown' + } // options const s2Options = { width: containerDom.offsetWidth, height: containerDom.offsetHeight, showSeriesNumber: customAttr.size.showIndex, style: getSize(chart), + tooltip: { + renderTooltip: sheet => new SortTooltip(sheet, vueCom), + getContainer: () => containerDom, + adjustPosition: ({ event }) => { + return getTooltipPosition(event) + }, + style: { + position: 'absolute', + padding: '4px 2px' + } + }, + headerActionIcons: [ + { + iconNames: ['GroupAsc', 'SortUp', 'SortDown'], + belongsCell: 'colCell', + displayCondition: (meta, iconName) => { + if (meta.field === SERIES_NUMBER_FIELD) { + return false + } + const sortMethodMap = meta.spreadsheet.store.get('sortMethodMap') + const sortType = sortMethodMap?.[meta.field] + if (sortType) { + return iconName === sortIconMap[sortType] + } + return iconName === 'GroupAsc' + }, + onClick: (props) => { + const { meta, event } = props + meta.spreadsheet.showTooltip({ + position: { + x: event.clientX, + y: event.clientY + }, + event, + ...props + }) + } + } + ], conditions: getConditions(chart), frozenColCount: customAttr.size.tableColumnFreezeHead ?? 0, frozenRowCount: customAttr.size.tableRowFreezeHead ?? 0 @@ -152,7 +254,7 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo) s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event)) } if (size.tableCellTooltip?.show) { - s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event)) + s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event, meta)) } // theme const customTheme = getCustomTheme(chart) @@ -161,7 +263,7 @@ export function baseTableInfo(s2, container, chart, action, tableData, pageInfo) return s2 } -export function baseTableNormal(s2, container, chart, action, tableData) { +export function baseTableNormal(s2, container, chart, action, tableData, vueCom) { const containerDom = document.getElementById(container) if (!containerDom) return @@ -292,12 +394,55 @@ export function baseTableNormal(s2, container, chart, action, tableData) { } const customAttr = JSON.parse(chart.customAttr) + const sortIconMap = { + 'asc': 'SortUp', + 'desc': 'SortDown' + } // options const s2Options = { width: containerDom.offsetWidth, height: containerDom.offsetHeight, showSeriesNumber: customAttr.size.showIndex, style: getSize(chart), + tooltip: { + renderTooltip: sheet => new SortTooltip(sheet, vueCom), + getContainer: () => containerDom, + adjustPosition: ({ event }) => { + return getTooltipPosition(event) + }, + style: { + position: 'absolute', + padding: '4px 2px' + } + }, + headerActionIcons: [ + { + iconNames: ['GroupAsc', 'SortUp', 'SortDown'], + belongsCell: 'colCell', + displayCondition: (meta, iconName) => { + if (meta.field === SERIES_NUMBER_FIELD) { + return false + } + const sortMethodMap = meta.spreadsheet.store.get('sortMethodMap') + const sortType = sortMethodMap?.[meta.field] + if (sortType) { + return iconName === sortIconMap[sortType] + } + return iconName === 'GroupAsc' + }, + onClick: (props) => { + const { meta, event } = props + meta.spreadsheet.showTooltip({ + position: { + x: event.clientX, + y: event.clientY + }, + event, + ...props + }) + } + } + ], conditions: getConditions(chart), frozenColCount: customAttr.size.tableColumnFreezeHead ?? 0, frozenRowCount: customAttr.size.tableRowFreezeHead ?? 0 @@ -343,7 +488,7 @@ export function baseTableNormal(s2, container, chart, action, tableData) { s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event)) } if (size.tableCellTooltip?.show) { - s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event)) + s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event, meta)) } // theme const customTheme = getCustomTheme(chart) @@ -540,7 +685,17 @@ export function baseTablePivot(s2, container, chart, action, headerAction, table height: containerDom.offsetHeight, style: getSize(chart), totals: totalCfg, - conditions: getConditions(chart) + conditions: getConditions(chart), + tooltip: { + getContainer: () => containerDom, + adjustPosition: ({ event }) => { + return getTooltipPosition(event) + }, + style: { + position: 'absolute', + padding: '4px 2px' + } + }, } // 开始渲染 @@ -562,7 +717,7 @@ export function baseTablePivot(s2, container, chart, action, headerAction, table s2.on(S2Event.COL_CELL_HOVER, event => showTooltip(s2, event, fieldMap)) } if (size.tableCellTooltip?.show) { - s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event)) + s2.on(S2Event.DATA_CELL_HOVER, event => showTooltipValue(s2, event, meta)) } // theme const customTheme = getCustomTheme(chart) @@ -821,15 +976,30 @@ function mappingColor(value, defaultColor, field, type, filedValueMap, rowData) return color } -function showTooltipValue(s2Instance, event) { +function showTooltipValue(s2Instance, event, meta) { const cell = s2Instance.getCell(event.target) - const content = cell.actualText + const valueField = cell.getMeta().valueField + const cellMeta = cell.getMeta() + if (!cellMeta.data) { + return + } + const value = cellMeta.data[valueField] + const metaObj = find(meta, m => + m.field === valueField + ) + event.s2Instance = s2Instance + let content = value?.toString() + if (metaObj) { + content = metaObj.formatter(value) + } s2Instance.showTooltip({ position: { x: event.clientX, y: event.clientY }, - content + content, + meta: cellMeta, + event }) } @@ -840,12 +1010,15 @@ function showTooltip(s2Instance, event, fieldMap) { if (fieldMap?.[content]) { content = fieldMap?.[content] } + event.s2Instance = s2Instance s2Instance.showTooltip({ position: { x: event.clientX, y: event.clientY }, - content + content, + meta, + event }) } @@ -860,38 +1033,65 @@ function getFieldValueMap(view) { } function customCalcFunc(query, data, totalCfgMap) { - if (!data?.length) { + if (!data?.length || !query[EXTRA_FIELD]) { return 0 } const aggregation = totalCfgMap[query[EXTRA_FIELD]].aggregation switch (aggregation) { case 'SUM': { return data.reduce((p, n) => { - return p + n[n[EXTRA_FIELD]] + return p + n[query[EXTRA_FIELD]] }, 0) } case 'AVG': { const sum = data.reduce((p, n) => { - return p + n[n[EXTRA_FIELD]] + return p + n[query[EXTRA_FIELD]] }, 0) return sum / data.length } case 'MIN': { const result = minBy(data, n => { - return n[n[EXTRA_FIELD]] + return n[query[EXTRA_FIELD]] }) - return result[result[EXTRA_FIELD]] + return result?.[query[EXTRA_FIELD]] } case 'MAX': { const result = maxBy(data, n => { - return n[n[EXTRA_FIELD]] + return n[query[EXTRA_FIELD]] }) - return result[result[EXTRA_FIELD]] + return result?.[query[EXTRA_FIELD]] } default: { return data.reduce((p, n) => { - return p + n[n[EXTRA_FIELD]] + return p + n[query[EXTRA_FIELD]] }, 0) } } } + +function getTooltipPosition(event) { + const s2Instance = event.s2Instance + const { x, y } = event + const result = { x: x + 15, y: y + 10 } + if (!s2Instance) { + return result + } + const { height, width} = s2Instance.getCanvasElement().getBoundingClientRect() + const { offsetHeight, offsetWidth } = s2Instance.tooltip.getContainer() + if (offsetWidth > width) { + result.x = 0 + } + if (offsetHeight > height) { + result.y = 0 + } + if (!(result.x || result.y)) { + return result + } + if (result.x && result.x + offsetWidth > width) { + result.x -= (result.x + offsetWidth - width) + } + if (result.y && result.y + offsetHeight > height) { + result.y -= (offsetHeight + 15) + } + return result +} diff --git a/core/frontend/src/views/chart/chart/util.js b/core/frontend/src/views/chart/chart/util.js index bae35d77ae..8fb892c680 100644 --- a/core/frontend/src/views/chart/chart/util.js +++ b/core/frontend/src/views/chart/chart/util.js @@ -3513,9 +3513,16 @@ export function customColor(custom, res, colors) { let flag = false for (let j = 0; j < custom.length; j++) { const c = custom[j] - if (r.name === c.name) { + if (c.id && c.id === r.id) { flag = true result.push(c) + break + } + if (r.name === c.name) { + flag = true + c.id = r.id + result.push(c) + break } } if (!flag) { @@ -3636,6 +3643,7 @@ export function getColors(chart, colors, reset) { const s = series[i] seriesColors.push({ name: s.name, + id: s.id, color: colors[i % colors.length], isCustom: false }) @@ -3662,16 +3670,6 @@ export function getColors(chart, colors, reset) { } else { if (chart.data) { const data = chart.data.data - // data 的维度值,需要根据自定义顺序排序 - // let customSortData - // if (Object.prototype.toString.call(chart.customSort) === '[object Array]') { - // customSortData = JSON.parse(JSON.stringify(chart.customSort)) - // } else { - // customSortData = JSON.parse(chart.customSort) - // } - // if (customSortData && customSortData.length > 0) { - // data = customSort(customSortData, data) - // } for (let i = 0; i < data.length; i++) { const s = data[i] seriesColors.push({ diff --git a/core/frontend/src/views/chart/components/ChartComponentG2.vue b/core/frontend/src/views/chart/components/ChartComponentG2.vue index 0c8ee39698..3cfc23bd60 100644 --- a/core/frontend/src/views/chart/components/ChartComponentG2.vue +++ b/core/frontend/src/views/chart/components/ChartComponentG2.vue @@ -224,6 +224,11 @@ export default { } }) }, + clearLinkage() { + this.linkageActiveHistory = false + this.myChart?.setState('active', () => true, false) + this.myChart?.setState('inactive', () => true, false) + }, checkSelected(param) { return (this.linkageActiveParam.name === param.name || (this.linkageActiveParam.name === 'NO_DATA' && !param.name)) && (this.linkageActiveParam.category === param.category) diff --git a/core/frontend/src/views/chart/components/ChartComponentS2.vue b/core/frontend/src/views/chart/components/ChartComponentS2.vue index ba8599f4ac..7470b841ec 100644 --- a/core/frontend/src/views/chart/components/ChartComponentS2.vue +++ b/core/frontend/src/views/chart/components/ChartComponentS2.vue @@ -39,19 +39,19 @@
    - diff --git a/core/frontend/src/views/chart/components/shapeAttr/TotalCfg.vue b/core/frontend/src/views/chart/components/shapeAttr/TotalCfg.vue index 4a2a0b8ccf..577021dd6a 100644 --- a/core/frontend/src/views/chart/components/shapeAttr/TotalCfg.vue +++ b/core/frontend/src/views/chart/components/shapeAttr/TotalCfg.vue @@ -56,6 +56,7 @@ @@ -74,6 +75,7 @@ @@ -108,6 +110,7 @@ - + diff --git a/core/frontend/src/views/chart/view/ChartStyle.vue b/core/frontend/src/views/chart/view/ChartStyle.vue index ad750844b7..cae44e3d8d 100644 --- a/core/frontend/src/views/chart/view/ChartStyle.vue +++ b/core/frontend/src/views/chart/view/ChartStyle.vue @@ -260,7 +260,7 @@ /> diff --git a/core/frontend/src/views/dataset/add/AddApi.vue b/core/frontend/src/views/dataset/add/AddApi.vue index 7239e0b377..87b438a53f 100644 --- a/core/frontend/src/views/dataset/add/AddApi.vue +++ b/core/frontend/src/views/dataset/add/AddApi.vue @@ -421,20 +421,25 @@ export default { const tables = [] const mode = this.mode const syncType = this.syncType - this.checkTableList.forEach((name) => { - const datasetName = this.tables.find( - (ele) => ele.name === name - ).datasetName + + for (let i = 0; i < this.checkTableList.length; i++) { + const table = this.tables.find( + (ele) => ele.name === this.checkTableList[i] + ) + if(table.setKey && table.keys.length === 0 ){ + this.openMessageSuccess(this.checkTableList[i] + this.$t('dataset.no_set_key') , 'error') + return + } tables.push({ - name: datasetName, + name: table.datasetName, sceneId: sceneId, dataSourceId: dataSourceId, type: 'api', syncType: syncType, mode: parseInt(mode), - info: JSON.stringify({ table: name }) + info: JSON.stringify({ table: this.checkTableList[i], setKey: table.setKey, keys: table.keys}) }) - }) + } post('/dataset/table/batchAdd', tables) .then((response) => { this.openMessageSuccess('deDataset.set_saved_successfully') @@ -610,6 +615,10 @@ export default { width: 420px; margin-left: 12px; } + + .el-checkbox{ + margin-left: 12px; + } } .data { diff --git a/core/frontend/src/views/dataset/add/AddDB.vue b/core/frontend/src/views/dataset/add/AddDB.vue index 120ca46ef8..687e06899f 100644 --- a/core/frontend/src/views/dataset/add/AddDB.vue +++ b/core/frontend/src/views/dataset/add/AddDB.vue @@ -166,6 +166,26 @@ > {{ $t('deDataset.already_exists') }}
    + + {{ $t('dataset.set_key') }} + + + + +
    { this.$set(ele, 'datasetName', dsName + '_' + ele.name) this.$set(ele, 'nameExist', false) + this.$set(ele, 'setKey', false) + this.$set(ele, 'keys', []) }) this.tableData = [...this.tables] this.avilibelTable = !this.tableData.some((ele) => ele.enableCheck) @@ -436,27 +458,33 @@ export default { this.openMessageSuccess('deDataset.cannot_be_duplicate', 'error') return } + if (this.loading) return - this.loading = true const sceneId = this.param.id const dataSourceId = this.dataSource const tables = [] const mode = this.mode const syncType = this.syncType - this.checkTableList.forEach((name) => { - const datasetName = this.tables.find( - (ele) => ele.name === name - ).datasetName + for (let i = 0; i < this.checkTableList.length; i++) { + const table = this.tables.find( + (ele) => ele.name === this.checkTableList[i] + ) + if(table.setKey && table.keys.length === 0 ){ + this.openMessageSuccess(this.checkTableList[i] + this.$t('dataset.no_set_key') , 'error') + return + } tables.push({ - name: datasetName, + name: table.datasetName, sceneId: sceneId, dataSourceId: dataSourceId, type: 'db', syncType: syncType, mode: parseInt(mode), - info: JSON.stringify({ table: name }) + info: JSON.stringify({ table: this.checkTableList[i], setKey: table.setKey, keys: table.keys}) }) - }) + } + + this.loading = true post('/dataset/table/batchAdd', tables) .then((response) => { this.openMessageSuccess('deDataset.set_saved_successfully') @@ -632,6 +660,15 @@ export default { width: 420px; margin-left: 12px; } + + .el-select { + width: 420px; + margin-left: 12px; + } + + .el-checkbox{ + margin-left: 12px; + } } .data { diff --git a/core/frontend/src/views/dataset/add/AddExcel.vue b/core/frontend/src/views/dataset/add/AddExcel.vue index 54112684f7..4bfd7d33b6 100644 --- a/core/frontend/src/views/dataset/add/AddExcel.vue +++ b/core/frontend/src/views/dataset/add/AddExcel.vue @@ -771,6 +771,10 @@ export default { width: 420px; margin-left: 12px; } + + .el-checkbox{ + margin-left: 12px; + } } .data { diff --git a/core/frontend/src/views/dataset/add/AddSQL.vue b/core/frontend/src/views/dataset/add/AddSQL.vue index a9f8f87ae3..22eb2b493c 100644 --- a/core/frontend/src/views/dataset/add/AddSQL.vue +++ b/core/frontend/src/views/dataset/add/AddSQL.vue @@ -61,6 +61,26 @@ value="sync_latter" /> + {{ $t('dataset.set_key') }} + + + + + { this.$emit('setSaveDisabled', false) @@ -1051,7 +1075,9 @@ export default { sqlVariableDetails: JSON.stringify(this.variables), info: JSON.stringify({ sql: Base64.encode(this.sql.trim()), - isBase64Encryption: true + isBase64Encryption: true, + setKey: this.param.setKey, + keys: this.param.keys }) } post('/dataset/table/update', table) diff --git a/core/frontend/src/views/dataset/data/FieldEdit.vue b/core/frontend/src/views/dataset/data/FieldEdit.vue index e7f0500671..177d662385 100644 --- a/core/frontend/src/views/dataset/data/FieldEdit.vue +++ b/core/frontend/src/views/dataset/data/FieldEdit.vue @@ -225,6 +225,22 @@ /> + + + + + + { + this.engineMode = res.data + }) + }, mounted() { window.addEventListener('resize', this.calcHeight) this.calcHeight() @@ -826,6 +865,12 @@ export default { this.dateformats = children }) }, + getKeyFields(item) { + return [ + { label: this.$t('commons.yes'), value: true }, + { label: this.$t('commons.no'), value: false } + ] + }, getFields(item) { if (item.deExtractType === 0) { const children = this.dateformats @@ -850,6 +895,19 @@ export default { ] } }, + + saveKey(item ) { + post('/dataset/field/saveKey', item) + .then((response) => { + this.initField() + localStorage.setItem('reloadDsData', 'true') + }) + .catch((res) => { + this.initField() + localStorage.setItem('reloadDsData', 'true') + }) + }, + saveEdit(item, checkExp = true) { if (item.name && item.name.length > 50) { this.$message.error(this.$t('dataset.field_name_less_50')) diff --git a/core/frontend/src/views/panel/export/PDFPreExport.vue b/core/frontend/src/views/panel/export/PDFPreExport.vue index 76e0a58f1e..4833962431 100644 --- a/core/frontend/src/views/panel/export/PDFPreExport.vue +++ b/core/frontend/src/views/panel/export/PDFPreExport.vue @@ -130,6 +130,10 @@ export default { save() { const _this = this _this.exportLoading = true + // 保存原始的设备像素比值 + const originalDPR = window.devicePixelRatio + // 将设备像素比设置为1 + window.devicePixelRatio = 2 setTimeout(() => { _this.toExport = true setTimeout(() => { @@ -143,6 +147,7 @@ export default { PDF.addImage(pageData, 'JPEG', 0, 0, contentWidth, contentHeight) PDF.save(_this.panelName + '.pdf') _this.$emit('closePreExport') + window.devicePixelRatio = originalDPR }) }, 1500) }, 500) diff --git a/core/frontend/src/views/panel/list/PanelList.vue b/core/frontend/src/views/panel/list/PanelList.vue index 653f38614d..ecf28fcfaa 100644 --- a/core/frontend/src/views/panel/list/PanelList.vue +++ b/core/frontend/src/views/panel/list/PanelList.vue @@ -851,8 +851,9 @@ export default { }, delete(data) { + const title = data.source ? 'commons.cancel_this_dashboard':(data.nodeType === 'folder' ? 'commons.delete_this_folder' : 'commons.delete_this_dashboard') const params = { - title: data.nodeType === 'folder' ? 'commons.delete_this_folder' : 'commons.delete_this_dashboard', + title: title, type: 'danger', cb: () => { delGroup(data.id).then((response) => { diff --git a/core/frontend/src/views/panel/list/PanelViewShow.vue b/core/frontend/src/views/panel/list/PanelViewShow.vue index 8930c79faf..74d504d65d 100644 --- a/core/frontend/src/views/panel/list/PanelViewShow.vue +++ b/core/frontend/src/views/panel/list/PanelViewShow.vue @@ -462,8 +462,8 @@ export default { imageWrapperStyle() { if (this.exporting) { return { - width: '1280px', - height: '720px' + width: '2560px', + height: '1440px' } } else { return { @@ -649,14 +649,29 @@ export default { } }, downLoadToAppPre() { - this.$refs.appExportForm.init({ - appName: this.$store.state.panel.panelInfo.name, - icon: null, - version: '1.0', - creator: this.$store.getters.user.nickName, - required: '1.16.0', - description: null + const result = this.checkTemplate() + if (result && result.length > 0) { + this.$message({ message: this.$t('panel.app_export_tips', [result]), type: 'warning', showClose: true }) + } else { + this.$refs.appExportForm.init({ + appName: this.$store.state.panel.panelInfo.name, + icon: null, + version: '1.0', + creator: this.$store.getters.user.nickName, + required: '1.16.0', + description: null + }) + } + }, + checkTemplate() { + let templateViewNames = ',' + Object.keys(this.panelViewDetailsInfo).forEach(key => { + const viewInfo = JSON.parse(this.panelViewDetailsInfo[key]) + if (viewInfo.dataFrom === 'template') { + templateViewNames = templateViewNames + viewInfo.title + ',' + } }) + return templateViewNames.slice(1) }, downLoadToApp(appAttachInfo) { this.dataLoading = true @@ -705,6 +720,10 @@ export default { downloadAsImage() { this.dataLoading = true + // 保存原始的设备像素比值 + const originalDPR = window.devicePixelRatio + // 将设备像素比设置为1 + window.devicePixelRatio = 2 setTimeout(() => { this.exporting = this.changeExportingState() setTimeout(() => { @@ -723,6 +742,7 @@ export default { a.click() URL.revokeObjectURL(blob) document.body.removeChild(a) + window.devicePixelRatio = originalDPR setTimeout(() => { this.dataLoading = false }, 300) @@ -735,7 +755,10 @@ export default { // this.pdfExportShow = true // this.dataLoading = true - + // 保存原始的设备像素比值 + const originalDPR = window.devicePixelRatio + // 将设备像素比设置为1 + window.devicePixelRatio = 2 setTimeout(() => { this.exporting = this.changeExportingState() setTimeout(() => { @@ -749,6 +772,7 @@ export default { } }) }, 1500) + window.devicePixelRatio = originalDPR }, 500) }, refreshTemplateInfo() { diff --git a/core/frontend/src/views/panel/subjectSetting/panelStyle/MobileBackgroundSelector.vue b/core/frontend/src/views/panel/subjectSetting/panelStyle/MobileBackgroundSelector.vue index 48043da0ba..ab021af0cd 100644 --- a/core/frontend/src/views/panel/subjectSetting/panelStyle/MobileBackgroundSelector.vue +++ b/core/frontend/src/views/panel/subjectSetting/panelStyle/MobileBackgroundSelector.vue @@ -107,6 +107,7 @@ import { deepCopy, imgUrlTrans } from '@/components/canvas/utils/utils' import { COLOR_PANEL } from '@/views/chart/chart/chart' import { uploadFileResult } from '@/api/staticResource/staticResource' import bus from '@/utils/bus' +import { MOBILE_SETTING } from '@/views/panel/panel' export default { name: 'MobileBackgroundSelector', @@ -117,7 +118,7 @@ export default { dialogImageUrl: '', dialogVisible: false, uploadDisabled: false, - mobileSetting: null, + mobileSetting: deepCopy(MOBILE_SETTING), predefineColors: COLOR_PANEL } }, @@ -128,10 +129,14 @@ export default { // deep监听panel 如果改变 提交到 store }, created() { - // 初始化赋值 - this.mobileSetting = this.canvasStyleData.panel.mobileSetting - if (this.mobileSetting.imageUrl && typeof (this.mobileSetting.imageUrl) === 'string') { - this.fileList.push({ url: imgUrlTrans(this.mobileSetting.imageUrl) }) + if (this.canvasStyleData.panel.mobileSetting) { + // 初始化赋值 + this.mobileSetting = this.canvasStyleData.panel.mobileSetting + if (this.mobileSetting.imageUrl && typeof (this.mobileSetting.imageUrl) === 'string') { + this.fileList.push({ url: imgUrlTrans(this.mobileSetting.imageUrl) }) + } + } else { + this.canvasStyleData.panel['mobileSetting'] = this.mobileSetting } }, methods: { diff --git a/core/frontend/src/views/system/sysParam/BasicSetting.vue b/core/frontend/src/views/system/sysParam/BasicSetting.vue index 56e3455145..7f1aa183bd 100644 --- a/core/frontend/src/views/system/sysParam/BasicSetting.vue +++ b/core/frontend/src/views/system/sysParam/BasicSetting.vue @@ -86,7 +86,7 @@