Merge branch 'dev' into pr@dev_memory_component

This commit is contained in:
dataeaseShu 2023-03-24 11:52:32 +08:00
commit 48cd98a31f
48 changed files with 489 additions and 151 deletions

View File

@ -90,7 +90,7 @@ curl -sSL https://dataease.oss-cn-hangzhou.aliyuncs.com/quick_start.sh | sh
**加入微信交流群**
<img src="https://dataease.oss-cn-hangzhou.aliyuncs.com/img/wechat-group.png" width="156" height="156"/>
<img src="https://dataease.oss-cn-hangzhou.aliyuncs.com/img/wechat-helper.png" width="156" height="156"/>
## DataEase 的技术栈
@ -107,7 +107,7 @@ curl -sSL https://dataease.oss-cn-hangzhou.aliyuncs.com/quick_start.sh | sh
## License
Copyright (c) 2014-2023 飞致云 FIT2CLOUD, All rights reserved.
Copyright (c) 2014-2023 [FIT2CLOUD 飞致云](https://fit2cloud.com/), All rights reserved.
Licensed under The GNU General Public License version 3 (GPLv3) (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

View File

@ -185,7 +185,7 @@
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8</version>
<version>7.7.0</version>
<scope>test</scope>
</dependency>
<!-- ehcache 缓存 -->

View File

@ -0,0 +1,17 @@
package io.dataease.auth.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Target(ElementType.METHOD)
@Retention(RUNTIME)
public @interface SqlInjectValidator {
String[] value() default {};
}

View File

@ -0,0 +1,68 @@
package io.dataease.auth.aop;
import cn.hutool.core.util.ArrayUtil;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.commons.exception.DEException;
import io.dataease.controller.sys.base.BaseGridRequest;
import org.apache.commons.collections4.CollectionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Component
@Aspect
public class SqlInjectAop {
@Around(value = "@annotation(io.dataease.auth.annotation.SqlInjectValidator)")
public Object around(ProceedingJoinPoint point) {
try {
Signature signature = point.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
Object[] args = point.getArgs();
if (args == null || args.length == 0) {
return point.proceed();
}
BaseGridRequest request = null;
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof BaseGridRequest) {
request = (BaseGridRequest) args[i];
break;
}
}
if (request == null) return point.proceed(args);
SqlInjectValidator annotation = AnnotationUtils.findAnnotation(method, SqlInjectValidator.class);
String[] value = annotation.value();
boolean illegal = isIllegal(value, request.getOrders());
if (illegal) {
DEException.throwException("Illegal sort exp");
}
return point.proceed(args);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
private boolean isIllegal(String[] value, List<String> orderList) {
if (CollectionUtils.isEmpty(orderList) || ArrayUtil.isEmpty(value)) return false;
Set<String> wordList = Arrays.stream(value).collect(Collectors.toSet());
wordList.add("asc");
wordList.add("desc");
return orderList.stream().anyMatch(exp ->
Arrays.stream(exp.toLowerCase().split(",")).anyMatch(word ->
Arrays.stream(word.split(" ")).anyMatch(item ->
!wordList.contains(item))));
}
}

View File

@ -225,7 +225,7 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe
if (Arrays.stream(whiteLists.split(",")).anyMatch(item -> url.indexOf(item) != -1)) return false;
}
Pattern pattern= Pattern.compile("(.*\\=.*\\-\\-.*)|(.*(\\+).*)|(.*\\w+(%|\\$|#|&)\\w+.*)|(.*\\|\\|.*)|(.*\\s+(and|or)\\s+.*)" +
"|(.*\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|sleep|extractvalue|updatexml|substring|database|concat|rand)\\b.*)");
"|(.*\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|sleep|extractvalue|updatexml|substring|database|concat|rand|gtid_subset)\\b.*)");
Matcher matcher=pattern.matcher(orders.toLowerCase());
return matcher.find();
}

View File

@ -170,7 +170,7 @@ public class DataSetTableController {
@DePermission(type = DePermissionType.DATASOURCE, value = "dataSourceId", level = ResourceAuthLevel.DATASOURCE_LEVEL_USE)
}, logical = Logical.AND)
public ResultHolder getSQLPreview(@RequestBody DataSetTableRequest dataSetTableRequest) throws Exception {
return dataSetTableService.getSQLPreview(dataSetTableRequest);
return dataSetTableService.getSQLPreview(dataSetTableRequest, true);
}
@ApiOperation("根据sql查询预览数据")

View File

@ -2,6 +2,7 @@ package io.dataease.controller.panel.api;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.plugins.common.base.domain.PanelShare;
import io.dataease.commons.constants.DePermissionType;
import io.dataease.controller.request.panel.PanelShareFineDto;
@ -30,6 +31,7 @@ public interface ShareApi {
@ApiOperation("查询分享给我")
@PostMapping("/treeList")
@SqlInjectValidator(value = {"s.create_time"})
List<PanelShareDto> treeList(BaseGridRequest request);
@ApiOperation("查询我分享的")

View File

@ -2,6 +2,7 @@ package io.dataease.controller.panel.api;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.commons.constants.DePermissionType;
import io.dataease.controller.sys.base.BaseGridRequest;
import io.dataease.dto.panel.PanelStoreDto;
@ -31,6 +32,7 @@ public interface StoreApi {
@ApiOperation("查询收藏")
@PostMapping("/list")
@SqlInjectValidator(value = {"s.create_time"})
List<PanelStoreDto> list(@RequestBody BaseGridRequest request);

View File

@ -33,5 +33,13 @@ public class PanelAppTemplateApplyRequest {
private String datasourceHistoryId;
private String linkJumps;
private String linkJumpInfos;
private String linkages;
private String linkageFields;
private List<DatasourceDTO> datasourceList;
}

View File

@ -16,7 +16,7 @@ import java.util.Map;
* Description:
*/
@RestController
@RequestMapping("/static/resource")
@RequestMapping("/staticResource")
public class StaticResourceController {
@Resource

View File

@ -3,6 +3,7 @@ package io.dataease.controller.sys;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.service.AuthUserService;
import io.dataease.plugins.common.base.domain.SysMsgChannel;
import io.dataease.plugins.common.base.domain.SysMsgSetting;
@ -47,6 +48,7 @@ public class MsgController {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "msgRequest", value = "查询条件", required = true)
})
@SqlInjectValidator(value = {"create_time", "type_id"})
public Pager<List<MsgGridDto>> messages(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody MsgRequest msgRequest) {
Long userId = AuthUtils.getUser().getUserId();
List<Long> typeIds = null;

View File

@ -1,5 +1,6 @@
package io.dataease.controller.sys;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.controller.ResultHolder;
import io.dataease.controller.sys.base.BaseGridRequest;
@ -40,6 +41,7 @@ public class SysDeptController extends ResultHolder {
}
@PostMapping("/search")
@SqlInjectValidator({"name"})
public List<DeptNodeResponse> search(@RequestBody BaseGridRequest request){
List<SysDept> nodes = deptService.nodesTreeByCondition(request);
List<DeptNodeResponse> nodeResponses = nodes.stream().map(node -> {

View File

@ -3,6 +3,7 @@ package io.dataease.controller.sys;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.commons.utils.PageUtils;
import io.dataease.commons.utils.Pager;
import io.dataease.controller.handler.annotation.I18n;
@ -36,6 +37,7 @@ public class SysLogController {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@SqlInjectValidator(value = {"time"})
public Pager<List<SysLogGridDTO>> logGrid(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody KeyGridRequest request) {
request = logService.logRetentionProxy(request);

View File

@ -2,6 +2,7 @@ package io.dataease.controller.sys;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.plugins.common.base.domain.MyPlugin;
import io.dataease.commons.utils.PageUtils;
import io.dataease.commons.utils.Pager;
@ -30,6 +31,7 @@ public class SysPluginController {
@ApiOperation("查询已安装插件")
@PostMapping("/pluginGrid/{goPage}/{pageSize}")
@RequiresPermissions("plugin:read")
@SqlInjectValidator(value = {"install_time"})
public Pager<List<MyPlugin>> pluginGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody BaseGridRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, pluginService.query(request));

View File

@ -5,6 +5,7 @@ import com.github.pagehelper.PageHelper;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.DeLog;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.api.dto.CurrentUserDto;
import io.dataease.auth.entity.AccountLockStatus;
import io.dataease.auth.service.AuthUserService;
@ -78,6 +79,7 @@ public class SysUserController {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@SqlInjectValidator(value = {"create_time", "u.enabled", "nick_name", "u.dept_id"})
public Pager<List<SysUserGridResponse>> userGrid(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody KeyGridRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
@ -102,6 +104,7 @@ public class SysUserController {
@ApiIgnore
@PostMapping("/userLists")
@SqlInjectValidator({"nick_name", "create_time"})
public List<SysUserGridResponse> userLists(@RequestBody BaseGridRequest request) {
KeyGridRequest keyGridRequest = BeanUtils.copyBean(new KeyGridRequest(), request);
return sysUserService.query(keyGridRequest);
@ -224,6 +227,7 @@ public class SysUserController {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@SqlInjectValidator({"create_time", "update_time"})
public Pager<List<SysRole>> roleGrid(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody BaseGridRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);

View File

@ -1,15 +1,15 @@
package io.dataease.controller.sys.request;
import io.dataease.controller.sys.base.BaseGridRequest;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
@ApiModel("消息条件")
public class MsgRequest implements Serializable {
public class MsgRequest extends BaseGridRequest implements Serializable {
private static final long serialVersionUID = 1920091635946508658L;
@ -19,6 +19,4 @@ public class MsgRequest implements Serializable {
@ApiModelProperty("是否订阅")
private Boolean status;
@ApiModelProperty("排序描述")
private List<String> orders;
}

View File

@ -37,6 +37,14 @@ public class PanelExport2App {
private String datasourceInfo;
private String linkJumps;
private String linkJumpInfos;
private String linkages;
private String linkageFields;
public PanelExport2App() {
}
@ -45,7 +53,11 @@ public class PanelExport2App {
this.checkMes = checkMes;
}
public PanelExport2App(List<ChartViewWithBLOBs> chartViewsInfo, List<ChartViewField> chartViewFieldsInfo, List<DatasetTable> datasetTablesInfo, List<DatasetTableField> datasetTableFieldsInfo, List<DataSetTaskDTO> datasetTasksInfo, List<DatasourceDTO> datasourceInfo, List<PanelView> panelViewsInfo) {
public PanelExport2App(List<ChartViewWithBLOBs> chartViewsInfo, List<ChartViewField> chartViewFieldsInfo,
List<DatasetTable> datasetTablesInfo, List<DatasetTableField> datasetTableFieldsInfo,
List<DataSetTaskDTO> datasetTasksInfo, List<DatasourceDTO> datasourceInfo,
List<PanelView> panelViewsInfo,List<PanelLinkJump> linkJumps,List<PanelLinkJumpInfo> linkJumpInfos,
List<PanelViewLinkage> linkages, List<PanelViewLinkageField> linkageFields) {
List empty = new ArrayList();
this.checkStatus = true;
this.checkMes = "success";
@ -56,5 +68,9 @@ public class PanelExport2App {
this.datasetTasksInfo = JSON.toJSONString(datasetTasksInfo!=null?datasetTasksInfo:empty);
this.datasourceInfo = JSON.toJSONString(datasourceInfo!=null?datasourceInfo:empty);
this.panelViewsInfo = JSON.toJSONString(panelViewsInfo!=null?panelViewsInfo:empty);
this.linkJumps = JSON.toJSONString(linkJumps!=null?linkJumps:empty);
this.linkJumpInfos = JSON.toJSONString(linkJumpInfos!=null?linkJumpInfos:empty);
this.linkages = JSON.toJSONString(linkages!=null?linkages:empty);
this.linkageFields = JSON.toJSONString(linkJumpInfos!=null?linkageFields:empty);
}
}

View File

@ -645,7 +645,7 @@
last_sync_time)
SELECT uuid() AS id,
chart_view_field.table_id,
chart_view_field.pv_copy.chart_view_id AS chart_id,
pv_copy.chart_view_id AS chart_id,
chart_view_field.origin_name,
chart_view_field.`name`,
chart_view_field.dataease_name,

View File

@ -2,6 +2,8 @@ package io.dataease.ext;
import io.dataease.dto.panel.linkJump.PanelLinkJumpBaseRequest;
import io.dataease.dto.panel.linkJump.PanelLinkJumpDTO;
import io.dataease.plugins.common.base.domain.PanelLinkJump;
import io.dataease.plugins.common.base.domain.PanelLinkJumpInfo;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -30,4 +32,7 @@ public interface ExtPanelLinkJumpMapper {
void copyLinkJumpInfo(@Param("copyId")String copyId);
void copyLinkJumpTarget(@Param("copyId")String copyId);
List<PanelLinkJump> findLinkJumpWithPanelId(@Param("panelId")String panelId);
List<PanelLinkJumpInfo> findLinkJumpInfoWithPanelId(@Param("panelId")String panelId);
}

View File

@ -269,4 +269,29 @@
WHERE copy_id = #{copyId}) plji_copy
ON panel_link_jump_target_view_info.link_jump_info_id = plji_copy.s_id
</insert>
<select id="findLinkJumpWithPanelId" resultType="io.dataease.plugins.common.base.domain.PanelLinkJump">
SELECT
*
FROM
panel_link_jump
WHERE
source_panel_id = #{panelId}
</select>
<select id="findLinkJumpInfoWithPanelId" resultType="io.dataease.plugins.common.base.domain.PanelLinkJumpInfo">
SELECT
*
FROM
panel_link_jump_info
WHERE
link_type = 'outer'
AND link_jump_id IN (
SELECT
id
FROM
panel_link_jump
WHERE
source_panel_id = #{panelId})
</select>
</mapper>

View File

@ -3,6 +3,8 @@ package io.dataease.ext;
import io.dataease.dto.LinkageInfoDTO;
import io.dataease.dto.PanelViewLinkageDTO;
import io.dataease.plugins.common.base.domain.DatasetTableField;
import io.dataease.plugins.common.base.domain.PanelViewLinkage;
import io.dataease.plugins.common.base.domain.PanelViewLinkageField;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -24,4 +26,8 @@ public interface ExtPanelViewLinkageMapper {
void copyViewLinkage(@Param("copyId") String copyId);
void copyViewLinkageField(@Param("copyId") String copyId);
List<PanelViewLinkage> findLinkageWithPanelId(@Param("panelId") String panelId);
List<PanelViewLinkageField> findLinkageFieldWithPanelId(@Param("panelId") String panelId);
}

View File

@ -195,4 +195,18 @@
) pvlf_copy ON panel_view_linkage_field.linkage_id = pvlf_copy.s_id
</insert>
<select id="findLinkageWithPanelId" resultType="io.dataease.plugins.common.base.domain.PanelViewLinkage">
select * from panel_view_linkage where panel_id =#{panelId};
</select>
<select id="findLinkageFieldWithPanelId" resultType="io.dataease.plugins.common.base.domain.PanelViewLinkageField">
SELECT
*
FROM
panel_view_linkage_field
WHERE
linkage_id IN ( SELECT id FROM panel_view_linkage WHERE panel_id = #{panelId} );
</select>
</mapper>

View File

@ -6,6 +6,7 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.DeLog;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.service.ExtAuthService;
import io.dataease.commons.constants.AuthConstants;
import io.dataease.commons.constants.DePermissionType;
@ -155,6 +156,7 @@ public class XDeptServer {
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@PostMapping("/userGrid/{goPage}/{pageSize}")
@SqlInjectValidator(value = {"dept_name", "nick_name"})
public Pager<List<DeptUserItemDTO>> userGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackDeptUserRequest request) {
DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);

View File

@ -5,6 +5,7 @@ import cn.hutool.core.util.ArrayUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.DeRateLimiter;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.api.dto.CurrentUserDto;
import io.dataease.commons.exception.DEException;
import io.dataease.commons.model.excel.ExcelSheetModel;
@ -59,6 +60,7 @@ public class XEmailTaskServer {
@RequiresPermissions("task-email:read")
@PostMapping("/queryTasks/{goPage}/{pageSize}")
@SqlInjectValidator(value = {"create_time"})
public Pager<List<XpackTaskGridDTO>> queryTask(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody XpackGridRequest request) {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);

View File

@ -5,6 +5,7 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.DeLog;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.service.ExtAuthService;
import io.dataease.commons.constants.AuthConstants;
import io.dataease.commons.constants.DePermissionType;
@ -93,6 +94,7 @@ public class XRoleServer {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@SqlInjectValidator(value = {"create_time", "name"})
public Pager<List<XpackRoleDto>> roleGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackGridRequest request) {
RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);

View File

@ -4,9 +4,12 @@ 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.provider.DDLProviderImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
* @Author gin
@ -25,6 +28,30 @@ public class MysqlDDLProvider extends DDLProviderImpl {
return "CREATE or replace view " + name + " AS (" + viewSQL + ")";
}
@Override
public String insertSql(String name, List<String[]> dataList, int page, int pageNumber) {
String insertSql = "INSERT INTO TABLE_NAME VALUES ".replace("TABLE_NAME", name);
StringBuffer values = new StringBuffer();
Integer realSize = page * pageNumber < dataList.size() ? page * pageNumber : dataList.size();
for (String[] strings : dataList.subList((page - 1) * pageNumber, realSize)) {
String[] strings1 = new String[strings.length];
for (int i = 0; i < strings.length; i++) {
if (StringUtils.isEmpty(strings[i])) {
strings1[i] = null;
} else {
strings1[i] = strings[i].replace("'", "\\'");
}
}
values.append("('").append(UUID.randomUUID())
.append("','").append(String.join("','", Arrays.asList(strings1)))
.append("'),");
}
return (insertSql + values.substring(0, values.length() - 1)).replaceAll(",'null'", ",null");
}
@Override
public String dropTable(String name) {
return "DROP TABLE IF EXISTS " + name;
@ -67,7 +94,7 @@ public class MysqlDDLProvider extends DDLProviderImpl {
}
break;
case 2:
Column_Fields.append("varchar(100)").append(",`");
Column_Fields.append("bigint(20)").append(",`");
break;
case 3:
Column_Fields.append("varchar(100)").append(",`");

View File

@ -879,10 +879,11 @@ public class ChartViewService {
fieldsToFilter.addAll(xAxisBase);
}
ChartDrillRequest head = drillRequestList.get(0);
Map<String, String> dimValMap = head.getDimensionList().stream().collect(Collectors.toMap(ChartDimensionDTO::getId, ChartDimensionDTO::getValue));
Map<String, ChartViewFieldDTO> fieldMap = Stream.of(xAxisBase, xAxisExt, extStack).
flatMap(Collection::stream).
collect(Collectors.toMap(ChartViewFieldDTO::getId, o -> o));
Map<String, String> dimValMap = new HashMap<>();
head.getDimensionList().forEach(item -> dimValMap.put(item.getId(), item.getValue()));
Map<String, ChartViewFieldDTO> fieldMap = Stream.of(xAxisBase, xAxisExt, extStack)
.flatMap(Collection::stream)
.collect(Collectors.toMap(ChartViewFieldDTO::getId, o -> o, ((p, n) -> p)));
for (int i = 0; i < drillRequestList.size(); i++) {
ChartDrillRequest request = drillRequestList.get(i);
ChartViewFieldDTO chartViewFieldDTO = drill.get(i);
@ -893,6 +894,7 @@ public class ChartViewService {
fieldsToFilter.add(chartViewFieldDTO);
dimValMap.put(requestDimension.getId(), requestDimension.getValue());
if (!checkDrillExist(xAxis, extStack, requestDimension.getId(), view)) {
fieldMap.put(chartViewFieldDTO.getId(), chartViewFieldDTO);
xAxis.add(chartViewFieldDTO);
}
if (i == drillRequestList.size() - 1) {

View File

@ -147,6 +147,7 @@ public class DataSetTableService {
public static final String regex = "\\$\\{(.*?)\\}";
private static final String SubstitutedParams = "DATAEASE_PATAMS_BI";
private static final String SubstitutedSql = " 'BI' = 'BI' ";
private static final String SubstitutedSqlVirtualData = " 1 < 2 ";
@Value("${upload.file.path}")
private String path;
@ -323,7 +324,7 @@ public class DataSetTableService {
if (StringUtils.equalsIgnoreCase(datasetTable.getType(), DatasetType.SQL.name()) && !"appApply".equalsIgnoreCase(datasetTable.getOptFrom())) {
DataSetTableRequest dataSetTableRequest = new DataSetTableRequest();
BeanUtils.copyBean(dataSetTableRequest, datasetTable);
getSQLPreview(dataSetTableRequest);
getSQLPreview(dataSetTableRequest, false);
}
if (StringUtils.isEmpty(datasetTable.getId())) {
datasetTable.setId(UUID.randomUUID().toString());
@ -1058,7 +1059,8 @@ public class DataSetTableService {
Matcher matcher = pattern.matcher(sql);
while (matcher.find()) {
SqlVariableDetails defaultsSqlVariableDetail = null;
List<SqlVariableDetails> defaultsSqlVariableDetails = new Gson().fromJson(sqlVariableDetails, new TypeToken<List<SqlVariableDetails>>() {}.getType());
List<SqlVariableDetails> defaultsSqlVariableDetails = new Gson().fromJson(sqlVariableDetails, new TypeToken<List<SqlVariableDetails>>() {
}.getType());
for (SqlVariableDetails sqlVariableDetail : defaultsSqlVariableDetails) {
if (matcher.group().substring(2, matcher.group().length() - 1).equalsIgnoreCase(sqlVariableDetail.getVariableName())) {
defaultsSqlVariableDetail = sqlVariableDetail;
@ -1069,8 +1071,7 @@ public class DataSetTableService {
defaultsSqlVariableDetail.getDefaultValueScope().equals(SqlVariableDetails.DefaultValueScope.ALLSCOPE) && StringUtils.isNotEmpty(defaultsSqlVariableDetail.getDefaultValue())) {
sql = sql.replace(matcher.group(), defaultsSqlVariableDetail.getDefaultValue());
}
if (isEdit && defaultsSqlVariableDetail != null && defaultsSqlVariableDetail.getDefaultValueScope() != null &&
defaultsSqlVariableDetail.getDefaultValueScope().equals(SqlVariableDetails.DefaultValueScope.EDIT) && StringUtils.isNotEmpty(defaultsSqlVariableDetail.getDefaultValue())) {
if (isEdit && defaultsSqlVariableDetail != null && StringUtils.isNotEmpty(defaultsSqlVariableDetail.getDefaultValue())){
sql = sql.replace(matcher.group(), defaultsSqlVariableDetail.getDefaultValue());
}
}
@ -1168,8 +1169,12 @@ public class DataSetTableService {
binaryExpression = (BinaryExpression) expr;
} catch (Exception e) {
}
if (binaryExpression != null && !(binaryExpression.getLeftExpression() instanceof BinaryExpression) && !(binaryExpression.getRightExpression() instanceof BinaryExpression) && hasVariable(binaryExpression.toString())) {
stringBuilder.append(SubstitutedSql);
if (binaryExpression != null) {
if (!(binaryExpression.getLeftExpression() instanceof BinaryExpression) && !(binaryExpression.getLeftExpression() instanceof InExpression) && hasVariable(binaryExpression.getRightExpression().toString())) {
stringBuilder.append(SubstitutedSql);
}else {
expr.accept(getExpressionDeParser(stringBuilder));
}
} else {
expr.accept(getExpressionDeParser(stringBuilder));
}
@ -1243,7 +1248,7 @@ public class DataSetTableService {
return datasetSqlLogMapper.selectByExample(example);
}
public ResultHolder getSQLPreview(DataSetTableRequest dataSetTableRequest) throws Exception {
public ResultHolder getSQLPreview(DataSetTableRequest dataSetTableRequest, boolean realData) throws Exception {
DatasetSqlLog datasetSqlLog = new DatasetSqlLog();
DataTableInfoDTO dataTableInfo = new Gson().fromJson(dataSetTableRequest.getInfo(), DataTableInfoDTO.class);
@ -1254,6 +1259,9 @@ public class DataSetTableService {
throw new Exception(Translator.get("i18n_invalid_ds"));
}
String tmpSql = removeVariables(sql, ds.getType());
if(!realData){
tmpSql.replaceAll(SubstitutedSql, SubstitutedSqlVirtualData);
}
if (dataSetTableRequest.getMode() == 1 && (tmpSql.contains(SubstitutedParams) || tmpSql.contains(SubstitutedSql.trim()))) {
throw new Exception(Translator.get("I18N_SQL_variable_direct_limit"));
}
@ -1264,8 +1272,7 @@ public class DataSetTableService {
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setDatasource(ds);
sql = handleVariableDefaultValue(sql, dataSetTableRequest.getSqlVariableDetails(), ds.getType(), true);
sql = realData ? handleVariableDefaultValue(sql, dataSetTableRequest.getSqlVariableDetails(), ds.getType(), true) : removeVariables(sql, ds.getType()).replaceAll(SubstitutedSql, SubstitutedSqlVirtualData);
if (StringUtils.isEmpty(sql)) {
DataEaseException.throwException(Translator.get("i18n_sql_not_empty"));
}
@ -1641,7 +1648,9 @@ public class DataSetTableService {
// field
StringBuilder field = new StringBuilder();
for (Map.Entry<String, String[]> next : checkedInfo.entrySet()) {
field.append(StringUtils.join(next.getValue(), ",")).append(",");
if (next.getValue().length > 0) {
field.append(StringUtils.join(next.getValue(), ",")).append(",");
}
}
String f = subPrefixSuffixChar(field.toString());
// join
@ -1789,7 +1798,9 @@ public class DataSetTableService {
// field
StringBuilder field = new StringBuilder();
for (Map.Entry<String, String[]> next : checkedInfo.entrySet()) {
field.append(StringUtils.join(next.getValue(), ",")).append(",");
if (next.getValue().length > 0) {
field.append(StringUtils.join(next.getValue(), ",")).append(",");
}
}
String f = subPrefixSuffixChar(field.toString());
// join
@ -1931,7 +1942,7 @@ public class DataSetTableService {
QueryProvider qp = ProviderFactory.getQueryProvider(ds.getType());
DataTableInfoDTO dataTableInfo = new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class);
String sql = dataTableInfo.isBase64Encryption() ? new String(java.util.Base64.getDecoder().decode(dataTableInfo.getSql())) : dataTableInfo.getSql();
sql = handleVariableDefaultValue(sql, null, ds.getType(), false);
sql = removeVariables(sql, ds.getType()).replaceAll(SubstitutedSql, SubstitutedSqlVirtualData);
String sqlAsTable = qp.createSQLPreview(sql, null);
datasourceRequest.setQuery(sqlAsTable);
fields = datasourceProvider.fetchResultField(datasourceRequest);
@ -2268,7 +2279,7 @@ public class DataSetTableService {
}
Set<String> nameSet = new HashSet<>();
for (DataSetTableRequest table : datasetTable) {
if(StringUtils.isEmpty(table.getName())){
if (StringUtils.isEmpty(table.getName())) {
throw new RuntimeException(Translator.get("I18n_name_cant_empty"));
}
nameSet.add(table.getName());

View File

@ -14,7 +14,7 @@ import io.dataease.controller.request.panel.PanelGroupRequest;
import io.dataease.dto.DatasourceDTO;
import io.dataease.ext.ExtPanelAppTemplateMapper;
import io.dataease.plugins.common.base.domain.*;
import io.dataease.plugins.common.base.mapper.PanelAppTemplateMapper;
import io.dataease.plugins.common.base.mapper.*;
import io.dataease.plugins.common.constants.DatasetType;
import io.dataease.service.chart.ChartViewFieldService;
import io.dataease.service.chart.ChartViewService;
@ -72,6 +72,14 @@ public class PanelAppTemplateService {
private StaticResourceService staticResourceService;
@Resource
private ExtractDataService extractDataService;
@Resource
private PanelLinkJumpMapper panelLinkJumpMapper;
@Resource
private PanelLinkJumpInfoMapper panelLinkJumpInfoMapper;
@Resource
private PanelViewLinkageMapper panelViewLinkageMapper;
@Resource
private PanelViewLinkageFieldMapper panelViewLinkageFieldMapper;
public List<PanelAppTemplateWithBLOBs> list(PanelAppTemplateRequest request) {
return extPanelAppTemplateMapper.queryBaseInfo(request.getNodeType(), request.getPid());
@ -411,4 +419,67 @@ public class PanelAppTemplateService {
}
}
@Transactional(rollbackFor = Exception.class)
public Map<String,String> applyLinkJumps(List<PanelLinkJump> linkJumps, Map<String, String> chartViewsRealMap, String newPanelId) {
Map<String,String> linkJumpIdMap = new HashMap<>();
if(!CollectionUtils.isEmpty(linkJumps)){
for(PanelLinkJump linkJump :linkJumps){
String newLinkJumpId = UUIDUtil.getUUIDAsString();
linkJumpIdMap.put(linkJump.getId(),newLinkJumpId);
linkJump.setId(newLinkJumpId);
linkJump.setSourcePanelId(newPanelId);
linkJump.setSourceViewId(chartViewsRealMap.get(linkJump.getSourceViewId()));
panelLinkJumpMapper.insertSelective(linkJump);
}
}
return linkJumpIdMap;
}
@Transactional(rollbackFor = Exception.class)
public void applyLinkJumpInfos(List<PanelLinkJumpInfo> linkJumpInfos, Map<String, String> linkJumpIdMap, Map<String, String> datasetFieldsRealMap) {
if(!CollectionUtils.isEmpty(linkJumpInfos)){
for(PanelLinkJumpInfo linkJumpInfo :linkJumpInfos){
String newLinkJumpInfoId = UUIDUtil.getUUIDAsString();
linkJumpInfo.setId(newLinkJumpInfoId);
linkJumpInfo.setLinkJumpId(linkJumpIdMap.get(linkJumpInfo.getLinkJumpId()));
linkJumpInfo.setSourceFieldId(datasetFieldsRealMap.get(linkJumpInfo.getSourceFieldId()));
datasetFieldsRealMap.forEach((k, v) -> {
linkJumpInfo.setContent(linkJumpInfo.getContent().replaceAll(k, v));
});
panelLinkJumpInfoMapper.insertSelective(linkJumpInfo);
}
}
}
@Transactional(rollbackFor = Exception.class)
public Map<String,String> applyLinkages(List<PanelViewLinkage> linkages, Map<String, String> chartViewsRealMap, String newPanelId) {
Map<String,String> linkageIdMap = new HashMap<>();
if(!CollectionUtils.isEmpty(linkages)){
for(PanelViewLinkage linkage :linkages){
String newId = UUIDUtil.getUUIDAsString();
linkageIdMap.put(linkage.getId(),newId);
linkage.setId(newId);
linkage.setPanelId(newPanelId);
linkage.setSourceViewId(chartViewsRealMap.get(linkage.getSourceViewId()));
linkage.setTargetViewId(chartViewsRealMap.get(linkage.getTargetViewId()));
panelViewLinkageMapper.insertSelective(linkage);
}
}
return linkageIdMap;
}
@Transactional(rollbackFor = Exception.class)
public void applyLinkageFields(List<PanelViewLinkageField> linkageFields, Map<String, String> linkageIdMap, Map<String, String> datasetFieldsRealMap) {
if(!CollectionUtils.isEmpty(linkageFields)){
for(PanelViewLinkageField linkageField :linkageFields){
String newId = UUIDUtil.getUUIDAsString();
linkageField.setId(newId);
linkageField.setLinkageId(linkageIdMap.get(linkageField.getLinkageId()));
linkageField.setSourceField(datasetFieldsRealMap.get(linkageField.getSourceField()));
linkageField.setTargetField(datasetFieldsRealMap.get(linkageField.getTargetField()));
panelViewLinkageFieldMapper.insertSelective(linkageField);
}
}
}
}

View File

@ -964,6 +964,14 @@ public class PanelGroupService {
List<DatasourceDTO> datasourceDTOS = extDataSourceMapper.findByTableIds(allTableIds);
List<PanelView> panelViews = panelViewService.findPanelViewsByPanelId(panelId);
//获取所有跳转信息
List<PanelLinkJump> linkJumps = extPanelLinkJumpMapper.findLinkJumpWithPanelId(panelId);
//获取所有跳转关联信息
List<PanelLinkJumpInfo> linkJumpInfos = extPanelLinkJumpMapper.findLinkJumpInfoWithPanelId(panelId);
//获取所有联动信息
List<PanelViewLinkage> linkages = extPanelViewLinkageMapper.findLinkageWithPanelId(panelId);
//获取所有联动关联信息
List<PanelViewLinkageField> LinkageFields = extPanelViewLinkageMapper.findLinkageFieldWithPanelId(panelId);
//校验标准 1.存在视图且所有视图的数据来源必须是dataset 2.存在数据集且没有excel数据集 3.存在数据源且是单数据源
//1.view check
@ -979,7 +987,8 @@ public class PanelGroupService {
} else if (datasourceDTOS.size() > 1) {
return new PanelExport2App(Translator.get("I18N_APP_ONE_DATASOURCE_TIPS"));
}
return new PanelExport2App(chartViewsInfo, chartViewFieldsInfo, datasetTablesInfo, datasetTableFieldsInfo, dataSetTasksInfo, datasourceDTOS, panelViews);
return new PanelExport2App(chartViewsInfo, chartViewFieldsInfo, datasetTablesInfo, datasetTableFieldsInfo,
dataSetTasksInfo, datasourceDTOS, panelViews, linkJumps, linkJumpInfos, linkages, LinkageFields);
}
@Transactional(rollbackFor = Exception.class)
@ -1016,11 +1025,32 @@ public class PanelGroupService {
//6.获取所有数据源信息
List<Datasource> oldDatasourceInfo = gson.fromJson(appInfo.getDatasourceInfo(), new TypeToken<List<Datasource>>() {
}.getType());
//获取仪表板信息
//7.获取仪表板信息
PanelGroupRequest panelInfo = gson.fromJson(appInfo.getPanelInfo(), PanelGroupRequest.class);
//获取仪表板视图信息
//8.获取仪表板视图信息
List<PanelView> panelViewsInfo = gson.fromJson(appInfo.getPanelViewsInfo(), new TypeToken<List<PanelView>>() {
}.getType());
//9.获取跳转信息
List<PanelLinkJump> linkJumps = null;
if(StringUtils.isNotEmpty(appInfo.getLinkJumps())){
linkJumps = gson.fromJson(appInfo.getLinkJumps(), new TypeToken<List<PanelLinkJump>>() {}.getType());
}
//10.获取跳转关联信息
List<PanelLinkJumpInfo> linkJumpInfos = null;
if(StringUtils.isNotEmpty(appInfo.getLinkJumpInfos())){
linkJumpInfos = gson.fromJson(appInfo.getLinkJumpInfos(), new TypeToken<List<PanelLinkJumpInfo>>() {}.getType());
}
//11.获取联动信息
List<PanelViewLinkage> linkages = null;
if(StringUtils.isNotEmpty(appInfo.getLinkages())){
linkages = gson.fromJson(appInfo.getLinkages(), new TypeToken<List<PanelViewLinkage>>() {}.getType());
}
//12.获取联动关联信息
List<PanelViewLinkageField> linkageFields = null;
if(StringUtils.isNotEmpty(appInfo.getLinkageFields())){
linkageFields = gson.fromJson(appInfo.getLinkageFields(), new TypeToken<List<PanelViewLinkageField>>() {}.getType());
}
Map<String, String> datasourceRealMap = panelAppTemplateService.applyDatasource(oldDatasourceInfo, request);
@ -1044,8 +1074,15 @@ public class PanelGroupService {
panelAppTemplateService.applyPanelView(panelViewsInfo, chartViewsRealMap, newPanelId);
String newDatasourceId = datasourceRealMap.entrySet().stream().findFirst().get().getValue();
Map<String,String> linkageIdMap = panelAppTemplateService.applyLinkages(linkages,chartViewsRealMap,newPanelId);
panelAppTemplateService.applyLinkageFields(linkageFields,linkageIdMap,datasetFieldsRealMap);
Map<String,String> linkJumpIdMap = panelAppTemplateService.applyLinkJumps(linkJumps,chartViewsRealMap,newPanelId);
panelAppTemplateService.applyLinkJumpInfos(linkJumpInfos,linkJumpIdMap,datasetFieldsRealMap);
String newDatasourceId = datasourceRealMap.entrySet().stream().findFirst().get().getValue();
PanelAppTemplateLog templateLog = new PanelAppTemplateLog();
templateLog.setPanelId(newPanelId);

View File

@ -3,6 +3,7 @@ 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.exception.DEException;
import io.dataease.commons.utils.FileUtils;
import io.dataease.commons.utils.LogUtil;
import io.dataease.commons.utils.StaticResourceUtils;
@ -14,7 +15,10 @@ import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -31,61 +35,78 @@ public class StaticResourceService {
private final Path staticDir = Paths.get("/opt/dataease/data/static-resource/");
public void upload(String fileId,MultipartFile file) {
public void upload(String fileId, MultipartFile file) {
// check if the path is valid (not outside staticDir)
Assert.notNull(file, "Multipart file must not be null");
try {
if (!isImage(file)) {
DEException.throwException("Multipart file must be image");
}
String originName = file.getOriginalFilename();
String newFileName = fileId+originName.substring(originName.lastIndexOf("."),originName.length());
String newFileName = fileId + originName.substring(originName.lastIndexOf("."), originName.length());
Path uploadPath = Paths.get(staticDir.toString(), newFileName);
// create dir is absent
FileUtils.createIfAbsent(Paths.get(staticDir.toString()));
Files.createFile(uploadPath);
file.transferTo(uploadPath);
} catch (IOException e) {
LogUtil.error("文件上传失败",e);
LogUtil.error("文件上传失败", e);
DataEaseException.throwException("文件上传失败");
} catch (Exception e){
} catch (Exception e) {
DataEaseException.throwException(e);
}
}
public void saveFilesToServe(String staticResource){
private boolean isImage(MultipartFile file) {
BufferedImage image = null;
try (InputStream input = file.getInputStream()) {
image = ImageIO.read(input);
} catch (IOException e) {
LogUtil.error(e.getMessage(), e);
return false;
}
if (image == null || image.getWidth() <= 0 || image.getHeight() <= 0) {
return false;
}
return true;
}
public void saveFilesToServe(String staticResource) {
Gson gson = new Gson();
if(StringUtils.isNotEmpty(staticResource)){
Map<String,String> resource = gson.fromJson(staticResource,Map.class);
for(Map.Entry<String,String> entry:resource.entrySet()){
if (StringUtils.isNotEmpty(staticResource)) {
Map<String, String> resource = gson.fromJson(staticResource, Map.class);
for (Map.Entry<String, String> entry : resource.entrySet()) {
String path = entry.getKey();
String fileName = path.substring(path.lastIndexOf("/")+1,path.length());
saveSingleFileToServe(fileName,entry.getValue());
String fileName = path.substring(path.lastIndexOf("/") + 1, path.length());
saveSingleFileToServe(fileName, entry.getValue());
}
}
}
public void saveSingleFileToServe(String fileName,String content){
public void saveSingleFileToServe(String fileName, String content) {
Path uploadPath = Paths.get(staticDir.toString(), fileName);
try{
try {
if (uploadPath.toFile().exists()) {
LogUtil.info("file exists");
}else{
if(StringUtils.isNotEmpty(content)){
} else {
if (StringUtils.isNotEmpty(content)) {
Files.createFile(uploadPath);
FileCopyUtils.copy(Base64Decoder.decode(content),Files.newOutputStream(uploadPath));
FileCopyUtils.copy(Base64Decoder.decode(content), Files.newOutputStream(uploadPath));
}
}
}catch (Exception e){
LogUtil.error("template static resource save error"+e.getMessage());
} catch (Exception e) {
LogUtil.error("template static resource save error" + e.getMessage());
}
}
public Map<String,String> findResourceAsBase64(StaticResourceRequest resourceRequest){
Map<String,String> result = new HashMap<>();
if(CollectionUtil.isNotEmpty(resourceRequest.getResourcePathList())){
for(String path :resourceRequest.getResourcePathList()){
String value = StaticResourceUtils.getImgFileToBase64(path.substring(path.lastIndexOf("/")+1,path.length()));
result.put(path,value);
public Map<String, String> findResourceAsBase64(StaticResourceRequest resourceRequest) {
Map<String, String> result = new HashMap<>();
if (CollectionUtil.isNotEmpty(resourceRequest.getResourcePathList())) {
for (String path : resourceRequest.getResourcePathList()) {
String value = StaticResourceUtils.getImgFileToBase64(path.substring(path.lastIndexOf("/") + 1, path.length()));
result.put(path, value);
}
}
return result;
return result;
}
}

View File

@ -54,4 +54,10 @@ END
;;
delimiter ;
INSERT INTO `system_parameter` (`param_key`, `param_value`, `type`, `sort`) VALUES ('loginlimit.multiLogin', '0', 'text', '3');
INSERT INTO `system_parameter` (`param_key`, `param_value`, `type`, `sort`) VALUES ('loginlimit.multiLogin', '0', 'text', '3');
ALTER TABLE `panel_app_template`
ADD COLUMN `link_jumps` longtext NULL AFTER `datasource_info`,
ADD COLUMN `link_jump_infos` longtext NULL AFTER `link_jumps`,
ADD COLUMN `linkages` longtext NULL AFTER `link_jump_infos`,
ADD COLUMN `linkage_fields` longtext NULL AFTER `linkages`;

View File

@ -4,7 +4,7 @@ import store from '@/store'
export function uploadFile(fileId, param) {
return request({
url: '/static/resource/upload/' + fileId,
url: '/staticResource/upload/' + fileId,
method: 'post',
headers: { 'Content-Type': 'multipart/form-data' },
data: param,
@ -26,7 +26,7 @@ export function uploadFileResult(file, callback) {
export function findResourceAsBase64(params) {
return request({
url: '/static/resource/findResourceAsBase64',
url: '/staticResource/findResourceAsBase64',
method: 'post',
data: params,
loading: false

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,7 +1,7 @@
<template>
<div
:style="getOutStyleDefault(config.style)"
class="component"
class="component component-outer"
@click="handleClick"
@mousedown="elementMouseDown"
>
@ -345,8 +345,7 @@ export default {
.component {
position: absolute;
}
.component:hover {
.component-outer:hover {
box-shadow: 0px 0px 3px #0a7be0;
}

View File

@ -291,7 +291,5 @@ export default {
.select-all {
padding: 10px 20px 0 20px;
}
.coustom-de-select {
z-index: 999 !important;
}
</style>

View File

@ -85,7 +85,8 @@ export default {
value: null,
data: [],
onFocus: false,
keyWord: ''
keyWord: '',
separator: ','
}
},
computed: {
@ -150,7 +151,7 @@ export default {
if (!token && linkToken) {
method = linkMultFieldValues
}
const param = { fieldIds: this.element.options.attrs.fieldId.split(','), sort: this.element.options.attrs.sort }
const param = { fieldIds: this.element.options.attrs.fieldId.split(this.separator), sort: this.element.options.attrs.sort }
if (this.panelInfo.proxy) {
param.userId = this.panelInfo.proxy
}
@ -189,7 +190,7 @@ export default {
if (!token && linkToken) {
method = linkMultFieldValues
}
const param = { fieldIds: this.element.options.attrs.fieldId.split(','), sort: this.element.options.attrs.sort }
const param = { fieldIds: this.element.options.attrs.fieldId.split(this.separator), sort: this.element.options.attrs.sort }
if (this.panelInfo.proxy) {
param.userId = this.panelInfo.proxy
}
@ -246,8 +247,8 @@ export default {
this.element.options.value = ''
return
}
const tempValueArray = JSON.parse(JSON.stringify(this.element.options.value.split(',')))
this.element.options.value = tempValueArray.filter(item => optionList.some(option => option === item)).join(',')
const tempValueArray = JSON.parse(JSON.stringify(this.element.options.value.split(this.separator)))
this.element.options.value = tempValueArray.filter(item => optionList.some(option => option === item)).join(this.separator)
}
}
},
@ -298,7 +299,7 @@ export default {
method = linkMultFieldValues
}
method({
fieldIds: this.element.options.attrs.fieldId.split(','),
fieldIds: this.element.options.attrs.fieldId.split(this.separator),
sort: this.element.options.attrs.sort
}).then(res => {
this.data = this.optionData(res.data)
@ -322,7 +323,7 @@ export default {
if (value === null) {
this.element.options.value = ''
} else {
this.element.options.value = Array.isArray(value) ? value.join() : value
this.element.options.value = Array.isArray(value) ? value.join(this.separator) : value
}
this.element.options.manualModify = false
} else {
@ -365,16 +366,19 @@ export default {
formatFilterValue() {
if (this.value === null) return []
if (Array.isArray(this.value)) return this.value
if (!this.element.options.attrs.multiple) {
return [this.value]
}
return this.value.split(',')
},
fillValueDerfault() {
const defaultV = this.element.options.value === null ? '' : this.element.options.value.toString()
if (this.element.options.attrs.multiple) {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV === '[object Object]') return []
return defaultV.split(',')
return defaultV.split(this.separator)
} else {
if (defaultV === null || typeof defaultV === 'undefined' || defaultV === '' || defaultV === '[object Object]') return null
return defaultV.split(',')[0]
return defaultV.split(this.separator)[0]
}
},
optionData(data) {

View File

@ -1521,7 +1521,7 @@ export default {
table_auto_break_line: 'Auto Line Feed',
table_break_line_tip: 'If open this option,the table item height will disabled.',
step: 'Step(px)',
no_function: 'Function not enterplease input.'
no_function: 'Function not enterplease input'
},
dataset: {
scope_edit: 'Effective only when editing',
@ -1533,7 +1533,7 @@ export default {
field_rename: 'Rename Field',
params_work: 'Effective only when editing: parameter values are effective only when editing data sets; Global Effective: It takes effect in dataset view, preview, and view where dataset is used.',
sql_variable_limit_1: '1、SQL variables can only be used in where conditions',
sql_variable_limit_2: '2、Exampleselect * from table_name where column_name1=\'${param_name1}\' and column_name2 in \'${param_name2}\'',
sql_variable_limit_2: '2、Exampleselect * from table_name where column_name1=\'${param_name1}\' and column_name2 in ${param_name2}',
select_year: 'Select Year',
select_month: 'Select Month',
select_date: 'Select Date',

View File

@ -1515,7 +1515,7 @@ export default {
table_auto_break_line: '自動換行',
table_break_line_tip: '開啟自動換行,表格行高設置將失效',
step: '步長(px)',
no_function: '函數尚未支持直接引用,請在字段表達式中手動輸入'
no_function: '函數尚未支持直接引用,請在字段表達式中手動輸入'
},
dataset: {
scope_edit: '僅編輯時生效',
@ -1527,7 +1527,7 @@ export default {
field_rename: '字段重命名',
params_work: '僅編輯時生效:參數值僅在數据集編輯時生效; 全域生效:在數据集查看、預覽、以及用到數据集的視圖中均生效。',
sql_variable_limit_1: '1、SQL變數只能在WHERE條件中使用',
sql_variable_limit_2: '2、示例select * from table_name where column_name1=\'${param_name1}\' and column_name2 in \'${param_name2}\'',
sql_variable_limit_2: '2、示例select * from table_name where column_name1=\'${param_name1}\' and column_name2 in ${param_name2}',
selesql_variable_limit_2ct_year: '選擇年',
select_month: '選擇月',
select_date: '選擇日期',

View File

@ -1516,7 +1516,7 @@ export default {
table_auto_break_line: '自动换行',
table_break_line_tip: '开启自动换行,表格行高设置将失效',
step: '步长(px)',
no_function: '函数尚未支持直接引用,请在字段表达式中手动输入'
no_function: '函数尚未支持直接引用,请在字段表达式中手动输入'
},
dataset: {
scope_edit: '仅编辑时生效',
@ -1529,7 +1529,7 @@ export default {
params_work: '仅编辑时生效:参数值仅在数据集编辑时生效;全局生效:在数据集查看、预览、以及用到数据集的视图中均生效。',
select_year: '选择年',
sql_variable_limit_1: '1、SQL 变量只能在 WHERE 条件中使用',
sql_variable_limit_2: '2、示例select * from table_name where column_name1=\'${param_name1}\' and column_name2 in \'${param_name2}\'',
sql_variable_limit_2: '2、示例select * from table_name where column_name1=\'${param_name1}\' and column_name2 in ${param_name2}',
select_month: '选择月',
select_date: '选择日期',
select_time: '选择时间',

View File

@ -114,7 +114,7 @@ export function baseBarOptionAntV(plot, container, chart, action, isGroup, isSta
if (chart.senior) {
let emptyDataStrategy = JSON.parse(chart.senior)?.functionCfg?.emptyDataStrategy
if (!emptyDataStrategy) {
emptyDataStrategy = 'breakLine'
emptyDataStrategy = 'ignoreData'
}
handleEmptyDataStrategy(emptyDataStrategy, chart, data, options)
}

View File

@ -3554,13 +3554,3 @@ export function resetRgbOpacity(sourceColor, times) {
}
return sourceColor
}
export function getDefaultLabelContent(chart) {
if (chart?.type?.includes('pie')) {
return ['dimension', 'proportion']
}
if (chart?.type?.includes('bar')) {
return ['quota']
}
return []
}

View File

@ -317,6 +317,25 @@ export default {
]
}
},
computed: {
labelContentOptions() {
if (this.chart.type.includes('pie')) {
return [
{ name: this.$t('chart.dimension'), value: 'dimension' },
{ name: this.$t('chart.quota'), value: 'quota' },
{ name: this.$t('chart.proportion'), value: 'proportion' }
]
}
if (this.chart.type.includes('bar')) {
return [
{ name: this.$t('chart.chart_group'), value: 'group' },
{ name: this.$t('chart.stack_item'), value: 'stack' },
{ name: this.$t('chart.quota'), value: 'quota' }
]
}
return []
}
},
watch: {
'chart': {
handler: function() {
@ -398,25 +417,6 @@ export default {
showProperty(property) {
return this.propertyInner.includes(property)
}
},
computed: {
labelContentOptions() {
if (this.chart.type.includes('pie')) {
return [
{ name: this.$t('chart.dimension'), value: 'dimension' },
{ name: this.$t('chart.quota'), value: 'quota' },
{ name: this.$t('chart.proportion'), value: 'proportion' }
]
}
if (this.chart.type.includes('bar')) {
return [
{ name: this.$t('chart.chart_group'), value: 'group' },
{ name: this.$t('chart.stack_item'), value: 'stack' },
{ name: this.$t('chart.quota'), value: 'quota' }
]
}
return []
}
}
}
</script>

View File

@ -513,7 +513,6 @@ import {
} from '../chart/chart'
import { checkViewTitle } from '@/components/canvas/utils/utils'
import { adaptCurTheme } from '@/components/canvas/utils/style'
import { getDefaultLabelContent } from '@/views/chart/chart/util'
export default {
name: 'Group',
@ -1045,6 +1044,11 @@ export default {
setChartDefaultOptions(view) {
const type = view.type
const attr = JSON.parse(view.customAttr)
if (view.render === 'echarts') {
attr.label.position = 'inside'
} else {
attr.label.position = 'middle'
}
if (type.includes('pie')) {
if (view.render === 'echarts') {
attr.label.position = 'inside'
@ -1061,21 +1065,13 @@ export default {
if (type === 'pie-donut-rose') {
attr.size.pieInnerRadius = Math.round(attr.size.pieOuterRadius * 0.5)
}
attr.label.labelContent = getDefaultLabelContent(view)
} else if (type.includes('bar')) {
attr.label.labelContent = ['quota']
const senior = JSON.parse(view.senior)
senior.functionCfg.emptyDataStrategy = 'ignoreData'
view.senior = JSON.stringify(senior)
} else if (type.includes('line')) {
attr.label.position = 'top'
} else if (type.includes('treemap')) {
if (view.render === 'echarts') {
attr.label.position = 'inside'
} else {
attr.label.position = 'middle'
}
} else {
if (view.render === 'echarts') {
attr.label.position = 'inside'
} else {
attr.label.position = 'middle'
}
}
view.customAttr = JSON.stringify(attr)
},

View File

@ -1748,7 +1748,6 @@ import CalcChartFieldEdit from '@/views/chart/view/CalcChartFieldEdit'
import { equalsAny } from '@/utils/StringUtils'
import PositionAdjust from '@/views/chart/view/PositionAdjust'
import MarkMapDataEditor from '@/views/chart/components/map/MarkMapDataEditor'
import { getDefaultLabelContent } from '@/views/chart/chart/util'
export default {
name: 'ChartEdit',
@ -3282,6 +3281,11 @@ export default {
const type = this.view.type
const customAttr = this.view.customAttr
const customStyle = this.view.customStyle
if (this.view.render === 'echarts') {
this.view.customAttr.label.position = 'inside'
} else {
this.view.customAttr.label.position = 'middle'
}
if (type.includes('pie')) {
if (this.view.render === 'echarts') {
customAttr.label.position = 'inside'
@ -3299,22 +3303,12 @@ export default {
if (equalsAny(type, 'pie', 'pie-rose')) {
customAttr.size.pieInnerRadius = 0
}
} else if (type.includes('bar')) {
this.view.customAttr.label.labelContent = ['quota']
this.view.senior.functionCfg.emptyDataStrategy = 'ignoreData'
} else if (type.includes('line')) {
this.view.customAttr.label.position = 'top'
} else if (type.includes('treemap')) {
if (this.view.render === 'echarts') {
this.view.customAttr.label.position = 'inside'
} else {
this.view.customAttr.label.position = 'middle'
}
} else {
if (this.view.render === 'echarts') {
this.view.customAttr.label.position = 'inside'
} else {
this.view.customAttr.label.position = 'middle'
}
}
customAttr.label.labelContent = getDefaultLabelContent(this.view)
// reset custom colors
this.view.customAttr.color.seriesColors = []
},

View File

@ -463,14 +463,6 @@
>
<template #header>
{{ $t('commons.params_value') }}
<el-tooltip
class="item"
effect="dark"
:content="$t('commons.parameter_effect')"
placement="top"
>
<svg-icon icon-class="icon_info_filled" />
</el-tooltip>
</template>
<template slot-scope="scope">
<el-input
@ -927,7 +919,6 @@ export default {
).sql
}
this.variables = JSON.parse(table.sqlVariableDetails)
this.getSQLPreview()
})
}
},

View File

@ -567,6 +567,7 @@ export default {
const data = res.data
this.viewInfos = data
this.updateParentName()
this.childViews.viewInfos = data
})
var type = 'TEXT'
@ -582,6 +583,17 @@ export default {
this.childViews.datasetParams = data
})
},
updateParentName() {
if (this.fieldsParent && this.viewInfos?.length && this.activeName !== 'dataset') {
this.viewInfos.forEach(info => {
if (info.id === this.fieldsParent.id && info.name !== this.fieldsParent.name) {
this.fieldsParent.name = info.name
this.comBackLink(this.fieldsParent)
this.comShowFieldData(this.fieldsParent)
}
})
}
},
handleNodeClick(data) {
if (data.modelInnerType !== 'group') {
this.showFieldData(data)

View File

@ -119,7 +119,7 @@
<div class="contact_title_qr">{{ $t('wizard.technical_group') }}</div>
<img
class="contact_wechat_group_img"
src="@/assets/wizard_wechat-group.png"
src="../../assets/wizard_wechat-group.png"
>
</div>
</div>