diff --git a/backend/src/main/java/io/dataease/auth/api/dto/CurrentUserDto.java b/backend/src/main/java/io/dataease/auth/api/dto/CurrentUserDto.java index ab279d815d..9bc1ac61e3 100644 --- a/backend/src/main/java/io/dataease/auth/api/dto/CurrentUserDto.java +++ b/backend/src/main/java/io/dataease/auth/api/dto/CurrentUserDto.java @@ -1,6 +1,7 @@ package io.dataease.auth.api.dto; import io.dataease.auth.entity.SysUserEntity; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.NoArgsConstructor; @@ -11,7 +12,9 @@ import java.util.List; @NoArgsConstructor public class CurrentUserDto extends SysUserEntity implements Serializable { + @ApiModelProperty("角色集合") private List roles; + @ApiModelProperty("权限集合") private List permissions; } diff --git a/backend/src/main/java/io/dataease/auth/config/F2CRealm.java b/backend/src/main/java/io/dataease/auth/config/F2CRealm.java index 1f0ee7e60d..c7a46650b6 100644 --- a/backend/src/main/java/io/dataease/auth/config/F2CRealm.java +++ b/backend/src/main/java/io/dataease/auth/config/F2CRealm.java @@ -2,18 +2,17 @@ package io.dataease.auth.config; import io.dataease.auth.api.dto.CurrentRoleDto; import io.dataease.auth.api.dto.CurrentUserDto; +import io.dataease.auth.entity.ASKToken; import io.dataease.auth.entity.JWTToken; import io.dataease.auth.entity.SysUserEntity; import io.dataease.auth.entity.TokenInfo; +import io.dataease.auth.handler.ApiKeyHandler; import io.dataease.auth.service.AuthUserService; import io.dataease.auth.util.JWTUtils; import io.dataease.commons.utils.BeanUtils; import io.dataease.commons.utils.LogUtil; import io.dataease.listener.util.CacheUtils; -import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.AuthenticationInfo; -import org.apache.shiro.authc.AuthenticationToken; -import org.apache.shiro.authc.SimpleAuthenticationInfo; +import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; @@ -37,7 +36,7 @@ public class F2CRealm extends AuthorizingRealm { @Override public boolean supports(AuthenticationToken token) { - return token instanceof JWTToken; + return token instanceof JWTToken || token instanceof ASKToken; } //验证资源权限 @@ -56,12 +55,27 @@ public class F2CRealm extends AuthorizingRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException { + + if (auth instanceof ASKToken) { + + Object accessKey = auth.getPrincipal(); + Object signature = auth.getCredentials(); + Long userId = ApiKeyHandler.getUser(accessKey.toString(), signature.toString()); + + SysUserEntity userEntity = userWithId(userId); + CurrentUserDto currentUserDto = queryCacheUserDto(userEntity); + return new SimpleAuthenticationInfo(currentUserDto, signature, "f2cReam"); + } + + + try { CacheUtils.get("lic_info", "lic"); }catch (Exception e) { LogUtil.error(e); throw new AuthenticationException("lic error"); } + TokenInfo tokenInfo = null; String token = null; try { @@ -78,13 +92,14 @@ public class F2CRealm extends AuthorizingRealm { throw new AuthenticationException("token invalid"); } // 使用缓存 - SysUserEntity user = authUserService.getUserById(userId); + /*SysUserEntity user = authUserService.getUserById(userId); if (user == null) { throw new AuthenticationException("User didn't existed!"); } if (user.getEnabled()==0) { throw new AuthenticationException("User is valid!"); - } + }*/ + SysUserEntity user = userWithId(userId); String pass = null; try { pass = user.getPassword(); @@ -94,6 +109,29 @@ public class F2CRealm extends AuthorizingRealm { if (! JWTUtils.verify(token, tokenInfo, pass)) { throw new AuthenticationException("Username or password error"); } + /*// 使用缓存 + List currentRoleDtos = authUserService.roleInfos(user.getUserId()); + // 使用缓存 + List permissions = authUserService.permissions(user.getUserId()); + CurrentUserDto currentUserDto = BeanUtils.copyBean(new CurrentUserDto(), user); + currentUserDto.setRoles(currentRoleDtos); + currentUserDto.setPermissions(permissions);*/ + CurrentUserDto currentUserDto = queryCacheUserDto(user); + return new SimpleAuthenticationInfo(currentUserDto, token, "f2cReam"); + } + + public SysUserEntity userWithId(Long userId) { + SysUserEntity user = authUserService.getUserById(userId); + if (user == null) { + throw new AuthenticationException("User didn't existed!"); + } + if (user.getEnabled()==0) { + throw new AuthenticationException("User is valid!"); + } + return user; + } + + public CurrentUserDto queryCacheUserDto(SysUserEntity user) { // 使用缓存 List currentRoleDtos = authUserService.roleInfos(user.getUserId()); // 使用缓存 @@ -101,6 +139,6 @@ public class F2CRealm extends AuthorizingRealm { CurrentUserDto currentUserDto = BeanUtils.copyBean(new CurrentUserDto(), user); currentUserDto.setRoles(currentRoleDtos); currentUserDto.setPermissions(permissions); - return new SimpleAuthenticationInfo(currentUserDto, token, "f2cReam"); + return currentUserDto; } } diff --git a/backend/src/main/java/io/dataease/auth/config/ShiroConfig.java b/backend/src/main/java/io/dataease/auth/config/ShiroConfig.java index a3d6e190de..764aefb3f3 100644 --- a/backend/src/main/java/io/dataease/auth/config/ShiroConfig.java +++ b/backend/src/main/java/io/dataease/auth/config/ShiroConfig.java @@ -51,6 +51,7 @@ public class ShiroConfig { filterMap.put("jwt", new JWTFilter()); filterMap.put("logout", new F2CLogoutFilter()); filterMap.put("link", new F2CLinkFilter()); + filterMap.put("doc", new F2CDocFilter()); factoryBean.setSecurityManager(securityManager); factoryBean.setLoginUrl("/login"); factoryBean.setUnauthorizedUrl("/login"); diff --git a/backend/src/main/java/io/dataease/auth/entity/ASKToken.java b/backend/src/main/java/io/dataease/auth/entity/ASKToken.java new file mode 100644 index 0000000000..4112fe197e --- /dev/null +++ b/backend/src/main/java/io/dataease/auth/entity/ASKToken.java @@ -0,0 +1,25 @@ +package io.dataease.auth.entity; + +import org.apache.shiro.authc.AuthenticationToken; + +public class ASKToken implements AuthenticationToken { + + private String accessKey; + + private String signature; + + public ASKToken(String accessKey, String signature) { + this.accessKey = accessKey; + this.signature = signature; + } + + @Override + public Object getPrincipal() { + return accessKey; + } + + @Override + public Object getCredentials() { + return signature; + } +} diff --git a/backend/src/main/java/io/dataease/auth/entity/SysUserEntity.java b/backend/src/main/java/io/dataease/auth/entity/SysUserEntity.java index 1bed1ac17b..2eb61eb0b4 100644 --- a/backend/src/main/java/io/dataease/auth/entity/SysUserEntity.java +++ b/backend/src/main/java/io/dataease/auth/entity/SysUserEntity.java @@ -1,6 +1,7 @@ package io.dataease.auth.entity; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -8,23 +9,33 @@ import java.io.Serializable; public class SysUserEntity implements Serializable { + @ApiModelProperty(hidden = true) private Long userId; + @ApiModelProperty("账号") private String username; + @ApiModelProperty("姓名") private String nickName; + @ApiModelProperty("组织ID") private Long deptId; + @ApiModelProperty(hidden = true) private String password; + @ApiModelProperty("状态") private Integer enabled; + @ApiModelProperty("邮箱") private String email; + @ApiModelProperty("电话") private String phone; + @ApiModelProperty(hidden = true) private String language; + @ApiModelProperty(hidden = true) private Boolean isAdmin; } diff --git a/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java b/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java new file mode 100644 index 0000000000..022180c4b3 --- /dev/null +++ b/backend/src/main/java/io/dataease/auth/filter/F2CDocFilter.java @@ -0,0 +1,26 @@ +package io.dataease.auth.filter; + +import org.apache.shiro.web.filter.authc.AnonymousFilter; + +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +public class F2CDocFilter extends AnonymousFilter { + + @Override + protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) { + HttpServletRequest req = (HttpServletRequest) request; + String path = "/deApi"; + try { + req.getRequestDispatcher(path).forward(req, response); + } catch (ServletException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } +} diff --git a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java index ba23292a7a..3077a338a5 100644 --- a/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java +++ b/backend/src/main/java/io/dataease/auth/filter/JWTFilter.java @@ -1,8 +1,10 @@ package io.dataease.auth.filter; +import io.dataease.auth.entity.ASKToken; import io.dataease.auth.entity.JWTToken; import io.dataease.auth.entity.SysUserEntity; import io.dataease.auth.entity.TokenInfo; +import io.dataease.auth.handler.ApiKeyHandler; import io.dataease.auth.service.AuthUserService; import io.dataease.auth.util.JWTUtils; import io.dataease.commons.utils.CommonBeanFactory; @@ -48,6 +50,18 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request; + + + if (ApiKeyHandler.isApiKeyCall(httpServletRequest)) { + // Long userId = ApiKeyHandler.getUser(httpServletRequest); + + ASKToken askToken = ApiKeyHandler.buildToken(httpServletRequest); + + // UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userId.toString(), ApiKeyHandler.random); + getSubject(request, response).login(askToken); + return true; + } + String authorization = httpServletRequest.getHeader("Authorization"); if (StringUtils.startsWith(authorization, "Basic")) { return false; @@ -72,7 +86,10 @@ public class JWTFilter extends BasicHttpAuthenticationFilter { */ @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { - if (isLoginAttempt(request, response)) { + // 先判断是不是api调用 + HttpServletRequest hRequest = (HttpServletRequest) request; + + if (isLoginAttempt(request, response) || ApiKeyHandler.isApiKeyCall(hRequest)) { try { boolean loginSuccess = executeLogin(request, response); return loginSuccess; diff --git a/backend/src/main/java/io/dataease/auth/handler/ApiKeyHandler.java b/backend/src/main/java/io/dataease/auth/handler/ApiKeyHandler.java new file mode 100644 index 0000000000..bd0a0e35a4 --- /dev/null +++ b/backend/src/main/java/io/dataease/auth/handler/ApiKeyHandler.java @@ -0,0 +1,88 @@ +package io.dataease.auth.handler; + +import io.dataease.auth.entity.ASKToken; +import io.dataease.commons.utils.CodingUtil; +import io.dataease.plugins.config.SpringContextUtil; +import io.dataease.plugins.xpack.ukey.dto.request.XpackUkeyDto; +import io.dataease.plugins.xpack.ukey.service.UkeyXpackService; +import org.apache.commons.lang3.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import java.util.UUID; + +public class ApiKeyHandler { + + public static final String API_ACCESS_KEY = "accessKey"; + + public static final String API_SIGNATURE = "signature"; + + + public static String random = UUID.randomUUID().toString() + UUID.randomUUID().toString(); + + public static Long getUser(HttpServletRequest request) { + if (request == null) { + return null; + } + return getUser(request.getHeader(API_ACCESS_KEY), request.getHeader(API_SIGNATURE)); + } + + public static ASKToken buildToken(HttpServletRequest request) { + if (request == null) { + return null; + } + String accessKey = request.getHeader(API_ACCESS_KEY); + String signature = request.getHeader(API_SIGNATURE); + ASKToken askToken = new ASKToken(accessKey, signature); + return askToken; + } + + public static Boolean isApiKeyCall(HttpServletRequest request) { + if (request == null) { + return false; + } + if (StringUtils.isBlank(request.getHeader(API_ACCESS_KEY)) || StringUtils.isBlank(request.getHeader(API_SIGNATURE))) { + return false; + } + return true; + } + + public static XpackUkeyDto ukey(String accessKey) { + UkeyXpackService ukeyXpackService = SpringContextUtil.getBean(UkeyXpackService.class); + XpackUkeyDto userKey = ukeyXpackService.getUserKey(accessKey); + return userKey; + } + + public static Long getUser(String accessKey, String signature) { + if (StringUtils.isBlank(accessKey) || StringUtils.isBlank(signature)) { + return null; + } + XpackUkeyDto userKey = ukey(accessKey); + if (userKey == null) { + throw new RuntimeException("invalid accessKey"); + } + String signatureDecrypt; + try { + signatureDecrypt = CodingUtil.aesDecrypt(signature, userKey.getSecretKey(), accessKey); + } catch (Throwable t) { + throw new RuntimeException("invalid signature"); + } + String[] signatureArray = StringUtils.split(StringUtils.trimToNull(signatureDecrypt), "|"); + if (signatureArray.length < 2) { + throw new RuntimeException("invalid signature"); + } + if (!StringUtils.equals(accessKey, signatureArray[0])) { + throw new RuntimeException("invalid signature"); + } + long signatureTime = 0l; + try { + signatureTime = Long.valueOf(signatureArray[signatureArray.length - 1]).longValue(); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (Math.abs(System.currentTimeMillis() - signatureTime) > 1800000) { + //签名30分钟超时 + throw new RuntimeException("expired signature"); + } + return userKey.getUserId(); + } +} diff --git a/backend/src/main/java/io/dataease/auth/service/impl/ExtAuthServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/ExtAuthServiceImpl.java index 07eccc92c1..e141cc1b62 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/ExtAuthServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/ExtAuthServiceImpl.java @@ -43,9 +43,11 @@ public class ExtAuthServiceImpl implements ExtAuthService { @Override public AuthURD resourceTarget(String resourceId) { AuthURD authURD = new AuthURD(); - SysAuthExample example = new SysAuthExample(); + /*SysAuthExample example = new SysAuthExample(); example.createCriteria().andAuthSourceEqualTo(resourceId); - List sysAuths = sysAuthMapper.selectByExample(example); + List sysAuths = sysAuthMapper.selectByExample(example);*/ + List sysAuths = extAuthMapper.queryByResource(resourceId); + Map> authMap = sysAuths.stream().collect(Collectors.groupingBy(SysAuth::getAuthTargetType)); if (!CollectionUtils.isEmpty(authMap.get("user"))) { authURD.setUserIds(authMap.get("user").stream().map(item -> Long.parseLong(item.getAuthTarget())).collect(Collectors.toList())); diff --git a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java index a6cdf4ec83..c12a511e21 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/ShiroServiceImpl.java @@ -20,7 +20,8 @@ public class ShiroServiceImpl implements ShiroService { // 配置过滤:不会被拦截的链接 -> 放行 start ---------------------------------------------------------- // 放行Swagger2页面,需要放行这些 - filterChainDefinitionMap.put("/doc.html",ANON); + filterChainDefinitionMap.put("/doc.html**","doc"); + filterChainDefinitionMap.put("/deApi**",ANON); filterChainDefinitionMap.put("/swagger-ui.html",ANON); filterChainDefinitionMap.put("/swagger-ui/**",ANON); filterChainDefinitionMap.put("/swagger/**",ANON); diff --git a/backend/src/main/java/io/dataease/base/domain/SysMsgChannel.java b/backend/src/main/java/io/dataease/base/domain/SysMsgChannel.java index 0ca1830b37..2bae1b3142 100644 --- a/backend/src/main/java/io/dataease/base/domain/SysMsgChannel.java +++ b/backend/src/main/java/io/dataease/base/domain/SysMsgChannel.java @@ -1,12 +1,17 @@ package io.dataease.base.domain; import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data public class SysMsgChannel implements Serializable { + + @ApiModelProperty("消息渠道ID") private Long msgChannelId; + @ApiModelProperty("消息渠道名称") private String channelName; private static final long serialVersionUID = 1L; diff --git a/backend/src/main/java/io/dataease/base/domain/SysMsgSetting.java b/backend/src/main/java/io/dataease/base/domain/SysMsgSetting.java index 6d86ed720f..49862f077e 100644 --- a/backend/src/main/java/io/dataease/base/domain/SysMsgSetting.java +++ b/backend/src/main/java/io/dataease/base/domain/SysMsgSetting.java @@ -1,18 +1,25 @@ package io.dataease.base.domain; import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data public class SysMsgSetting implements Serializable { + @ApiModelProperty(hidden = true) private Long msgSettingId; + @ApiModelProperty("订阅用户ID") private Long userId; + @ApiModelProperty("订阅类型ID") private Long typeId; + @ApiModelProperty("订阅渠道ID") private Long channelId; + @ApiModelProperty("订阅状态ID") private Boolean enable; private static final long serialVersionUID = 1L; diff --git a/backend/src/main/java/io/dataease/base/domain/SysMsgType.java b/backend/src/main/java/io/dataease/base/domain/SysMsgType.java index fd27679478..97262451b5 100644 --- a/backend/src/main/java/io/dataease/base/domain/SysMsgType.java +++ b/backend/src/main/java/io/dataease/base/domain/SysMsgType.java @@ -1,18 +1,26 @@ package io.dataease.base.domain; import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data public class SysMsgType implements Serializable { + + @ApiModelProperty("消息类型ID") private Long msgTypeId; + @ApiModelProperty("上级类型ID") private Long pid; + @ApiModelProperty("消息类型名称") private String typeName; + @ApiModelProperty(hidden = true) private String router; + @ApiModelProperty(hidden = true) private String callback; private static final long serialVersionUID = 1L; diff --git a/backend/src/main/java/io/dataease/base/domain/SysUser.java b/backend/src/main/java/io/dataease/base/domain/SysUser.java index 8f62905999..6ebfbcf4d3 100644 --- a/backend/src/main/java/io/dataease/base/domain/SysUser.java +++ b/backend/src/main/java/io/dataease/base/domain/SysUser.java @@ -1,40 +1,58 @@ package io.dataease.base.domain; import java.io.Serializable; + +import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data public class SysUser implements Serializable { + @ApiModelProperty(value = "用户ID" , allowEmptyValue = false, position = 0) private Long userId; + @ApiModelProperty(value = "组织ID" , allowEmptyValue = false, position = 7) private Long deptId; + @ApiModelProperty(value = "账号" , required = true) private String username; + @ApiModelProperty(value = "姓名" , required = true, position = 2) private String nickName; + @ApiModelProperty(value = "性别" ,allowableValues = "男,女", allowEmptyValue = true, position = 5) private String gender; + @ApiModelProperty(value = "电话" , allowEmptyValue = true, position = 1) private String phone; + @ApiModelProperty(value = "邮箱" , required = true, position = 3) private String email; + @ApiModelProperty(value = "密码" , required = true, position = 4) private String password; + @ApiModelProperty(hidden = true) private Boolean isAdmin; + @ApiModelProperty(value = "状态" , allowableValues = "1,0", required = true, position = 6) private Long enabled; + @ApiModelProperty(hidden = true) private String createBy; + @ApiModelProperty(hidden = true) private String updateBy; + @ApiModelProperty(hidden = true) private Long pwdResetTime; + @ApiModelProperty(hidden = true) private Long createTime; + @ApiModelProperty(hidden = true) private Long updateTime; + @ApiModelProperty(hidden = true) private String language; private static final long serialVersionUID = 1L; diff --git a/backend/src/main/java/io/dataease/base/mapper/ext/ExtAuthMapper.java b/backend/src/main/java/io/dataease/base/mapper/ext/ExtAuthMapper.java index fe7d57a75b..9e987aa586 100644 --- a/backend/src/main/java/io/dataease/base/mapper/ext/ExtAuthMapper.java +++ b/backend/src/main/java/io/dataease/base/mapper/ext/ExtAuthMapper.java @@ -1,6 +1,7 @@ package io.dataease.base.mapper.ext; +import io.dataease.base.domain.SysAuth; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -12,6 +13,6 @@ public interface ExtAuthMapper { List queryUserIdWithDeptIds(@Param("deptIds") List deptIds); - + List queryByResource(@Param("resourceId") String resourceId); // Set queryUserIdWithRD(@Param("roleIds") List roleIds, @Param("deptIds") List deptIds); } diff --git a/backend/src/main/java/io/dataease/base/mapper/ext/ExtAuthMapper.xml b/backend/src/main/java/io/dataease/base/mapper/ext/ExtAuthMapper.xml index 991709ff3b..8e961576f2 100644 --- a/backend/src/main/java/io/dataease/base/mapper/ext/ExtAuthMapper.xml +++ b/backend/src/main/java/io/dataease/base/mapper/ext/ExtAuthMapper.xml @@ -23,5 +23,12 @@ + + + diff --git a/backend/src/main/java/io/dataease/base/mapper/ext/ExtPanelViewLinkageMapper.java b/backend/src/main/java/io/dataease/base/mapper/ext/ExtPanelViewLinkageMapper.java index 82cea4163a..96ac3fe6a6 100644 --- a/backend/src/main/java/io/dataease/base/mapper/ext/ExtPanelViewLinkageMapper.java +++ b/backend/src/main/java/io/dataease/base/mapper/ext/ExtPanelViewLinkageMapper.java @@ -1,15 +1,19 @@ package io.dataease.base.mapper.ext; import io.dataease.base.domain.DatasetTableField; +import io.dataease.dto.LinkageInfoDTO; import io.dataease.dto.PanelViewLinkageDTO; import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Map; public interface ExtPanelViewLinkageMapper { List getViewLinkageGather(@Param("panelId") String panelId,@Param("sourceViewId") String sourceViewId,@Param("targetViewIds") List targetViewIds); + List getPanelAllLinkageInfo(@Param("panelId") String panelId); + List queryTableField(@Param("table_id") String tableId); void deleteViewLinkage(@Param("panelId") String panelId,@Param("sourceViewId") String sourceViewId); diff --git a/backend/src/main/java/io/dataease/base/mapper/ext/ExtPanelViewLinkageMapper.xml b/backend/src/main/java/io/dataease/base/mapper/ext/ExtPanelViewLinkageMapper.xml index f81e6c76ea..fb47e5fe23 100644 --- a/backend/src/main/java/io/dataease/base/mapper/ext/ExtPanelViewLinkageMapper.xml +++ b/backend/src/main/java/io/dataease/base/mapper/ext/ExtPanelViewLinkageMapper.xml @@ -24,6 +24,14 @@ + + + + + + + + + SELECT + distinct + CONCAT( panel_view_linkage.source_view_id, '#', panel_view_linkage_field.source_field ) AS 'sourceInfo', + CONCAT( panel_view_linkage.target_view_id, '#', panel_view_linkage_field.target_field ) AS 'targetInfo' + FROM + panel_view_linkage + LEFT JOIN panel_view_linkage_field ON panel_view_linkage.id = panel_view_linkage_field.linkage_id + WHERE + panel_view_linkage.panel_id = #{panelId} + diff --git a/backend/src/main/java/io/dataease/commons/condition/LicStatusCondition.java b/backend/src/main/java/io/dataease/commons/condition/LicStatusCondition.java new file mode 100644 index 0000000000..50e906db95 --- /dev/null +++ b/backend/src/main/java/io/dataease/commons/condition/LicStatusCondition.java @@ -0,0 +1,32 @@ +package io.dataease.commons.condition; + +import io.dataease.commons.license.DefaultLicenseService; +import io.dataease.commons.license.F2CLicenseResponse; +import io.dataease.commons.utils.CommonBeanFactory; +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + + + +public class LicStatusCondition implements Condition { + + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { + // BeanDefinitionRegistry registry = conditionContext.getRegistry(); + + // DefaultLicenseService defaultLicenseService = conditionContext.getBeanFactory().getBean(DefaultLicenseService.class); + + DefaultLicenseService defaultLicenseService = CommonBeanFactory.getBean(DefaultLicenseService.class); + + /*if (null == defaultLicenseService) { + registry.registerBeanDefinition(); + }*/ + if (ObjectUtils.isNotEmpty(defaultLicenseService)) { + F2CLicenseResponse f2CLicenseResponse = defaultLicenseService.validateLicense(); + return F2CLicenseResponse.Status.valid == f2CLicenseResponse.getStatus(); + } + return false; + } +} diff --git a/backend/src/main/java/io/dataease/commons/license/DefaultLicenseService.java b/backend/src/main/java/io/dataease/commons/license/DefaultLicenseService.java index 07a651d3b3..f79f9afc54 100644 --- a/backend/src/main/java/io/dataease/commons/license/DefaultLicenseService.java +++ b/backend/src/main/java/io/dataease/commons/license/DefaultLicenseService.java @@ -3,6 +3,7 @@ package io.dataease.commons.license; import com.google.gson.Gson; import io.dataease.base.domain.License; import io.dataease.commons.exception.DEException; +import io.dataease.commons.utils.LogUtil; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -31,6 +32,7 @@ public class DefaultLicenseService { command.add(licenseKey); try{ execCommand(result, command); + LogUtil.info("read lic content is : " + result.toString()); F2CLicenseResponse f2CLicenseResponse = new Gson().fromJson(result.toString(), F2CLicenseResponse.class); if(f2CLicenseResponse.getStatus() != F2CLicenseResponse.Status.valid){ return f2CLicenseResponse; @@ -43,6 +45,7 @@ public class DefaultLicenseService { } return f2CLicenseResponse; }catch (Exception e){ + e.printStackTrace(); return F2CLicenseResponse.invalid(e.getMessage()); } } diff --git a/backend/src/main/java/io/dataease/commons/utils/CodingUtil.java b/backend/src/main/java/io/dataease/commons/utils/CodingUtil.java index d377fafcfd..4bdea0e469 100644 --- a/backend/src/main/java/io/dataease/commons/utils/CodingUtil.java +++ b/backend/src/main/java/io/dataease/commons/utils/CodingUtil.java @@ -7,6 +7,7 @@ import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.MessageDigest; +import java.util.UUID; /** * 加密解密工具 @@ -153,6 +154,17 @@ public class CodingUtil { } } + /*public static String getSignature(String accessKey, String secretKey) throws Exception { + return aesEncrypt(accessKey + "|" + UUID.randomUUID().toString() + "|" + System.currentTimeMillis(), secretKey, accessKey); + } + + public static void main(String[] args) throws Exception{ + String accessKey = "gnPFmtAsdLhUEWPA"; + String secretKey = "TfK5FGUle0KRfJJJ"; + String signature = getSignature(accessKey, secretKey); + System.out.println(signature); + }*/ + public static String secretKey() { try { KeyGenerator keyGen = KeyGenerator.getInstance("AES"); diff --git a/backend/src/main/java/io/dataease/commons/utils/ExcelXlsxReader.java b/backend/src/main/java/io/dataease/commons/utils/ExcelXlsxReader.java index 4419056510..63448318e1 100644 --- a/backend/src/main/java/io/dataease/commons/utils/ExcelXlsxReader.java +++ b/backend/src/main/java/io/dataease/commons/utils/ExcelXlsxReader.java @@ -19,6 +19,8 @@ import org.xml.sax.helpers.XMLReaderFactory; import java.io.InputStream; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author y @@ -248,6 +250,13 @@ public class ExcelXlsxReader extends DefaultHandler { String value = this.getDataValue(lastIndex.trim(), "");//根据索引值获取对应的单元格值 if (preRef == null) { + String regEx="[^0-9]"; + Pattern p = Pattern.compile(regEx); + Matcher m = p.matcher(ref); + if(curCol < Integer.valueOf(m.replaceAll("").trim()) -1 ){ + cellList.add(curCol, ""); + curCol++; + } preRef = ref; } //补全单元格之间的空单元格 @@ -256,12 +265,16 @@ public class ExcelXlsxReader extends DefaultHandler { }else if (!ref.equals(preRef)) { int len = countNullCell(ref, preRef); for (int i = 0; i < len; i++) { - cellList.add(curCol, ""); - curCol++; + if(curCol < this.fields.size()){ + cellList.add(curCol, ""); + curCol++; + } } } - cellList.add(curCol, value); + if(curCol < this.fields.size()){ + cellList.add(curCol, value); + } curCol++; //如果里面某个单元格含有值,则标识该行不为空行 if (value != null && !"".equals(value)) { @@ -414,6 +427,9 @@ public class ExcelXlsxReader extends DefaultHandler { if(CollectionUtils.isEmpty(this.getFields())){ throw new RuntimeException(Translator.get("i18n_excel_header_empty")); } + if(curCol >= this.fields.size()){ + return thisStr; + } if(curRow==2){ this.getFields().get(curCol).setFieldType(type); }else { diff --git a/backend/src/main/java/io/dataease/config/Knife4jConfiguration.java b/backend/src/main/java/io/dataease/config/Knife4jConfiguration.java index c8174f6e31..e696452ad3 100644 --- a/backend/src/main/java/io/dataease/config/Knife4jConfiguration.java +++ b/backend/src/main/java/io/dataease/config/Knife4jConfiguration.java @@ -1,13 +1,10 @@ package io.dataease.config; -import cn.hutool.core.collection.CollectionUtil; import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver; +import io.dataease.commons.condition.LicStatusCondition; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.http.HttpHeaders; +import org.springframework.context.annotation.*; import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; import springfox.documentation.builders.*; import springfox.documentation.oas.annotations.EnableOpenApi; @@ -15,6 +12,8 @@ import springfox.documentation.service.*; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; + +import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; @@ -29,6 +28,7 @@ public class Knife4jConfiguration { private String version; + @Autowired public Knife4jConfiguration(OpenApiExtensionResolver openApiExtensionResolver) { this.openApiExtensionResolver = openApiExtensionResolver; @@ -64,6 +64,12 @@ public class Knife4jConfiguration { return defaultApi("系统管理", "io.dataease.controller.sys"); } + /*@Bean(value = "pluginsApi") + @Conditional(LicStatusCondition.class) + public Docket pluginsApi() { + return defaultApi("插件管理", "io.dataease.plugins.server"); + }*/ + private ApiInfo apiInfo(){ return new ApiInfoBuilder() @@ -77,7 +83,9 @@ public class Knife4jConfiguration { private Docket defaultApi(String groupName, String packageName) { List securitySchemes=new ArrayList<>(); - securitySchemes.add(apiKey()); + securitySchemes.add(accessKey()); + securitySchemes.add(signature()); + List securityContexts = new ArrayList<>(); securityContexts.add(securityContext()); @@ -100,8 +108,12 @@ public class Knife4jConfiguration { .build(); } - private ApiKey apiKey() { - return new ApiKey("Authorization", "Authorization", "header"); + private ApiKey accessKey() { + return new ApiKey("accessKey", "accessKey", "header"); + } + + private ApiKey signature() { + return new ApiKey("signature", "signature", "header"); } @@ -109,7 +121,12 @@ public class Knife4jConfiguration { AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; authorizationScopes[0] = authorizationScope; - return CollectionUtil.newArrayList(new SecurityReference("Authorization", authorizationScopes)); + + List results = new ArrayList<>(); + results.add(new SecurityReference("accessKey", authorizationScopes)); + results.add(new SecurityReference("signature", authorizationScopes)); + + return results; } } diff --git a/backend/src/main/java/io/dataease/controller/IndexController.java b/backend/src/main/java/io/dataease/controller/IndexController.java index 7a48d8f564..19c83d007f 100644 --- a/backend/src/main/java/io/dataease/controller/IndexController.java +++ b/backend/src/main/java/io/dataease/controller/IndexController.java @@ -1,13 +1,21 @@ package io.dataease.controller; +import io.dataease.commons.license.DefaultLicenseService; +import io.dataease.commons.license.F2CLicenseResponse; +import io.dataease.exception.DataEaseException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import javax.annotation.Resource; + @Controller @RequestMapping public class IndexController { + @Resource + private DefaultLicenseService defaultLicenseService; + @GetMapping(value = "/") public String index() { return "index.html"; @@ -28,5 +36,18 @@ public class IndexController { return "test.html"; } + @GetMapping("/deApi") + public String deApi() { + F2CLicenseResponse f2CLicenseResponse = defaultLicenseService.validateLicense(); + switch (f2CLicenseResponse.getStatus()) { + case valid: + return "doc.html"; + default: + // DataEaseException.throwException("Invalid License."); + return "nolic.html"; + } + // return "index.html"; + } + } diff --git a/backend/src/main/java/io/dataease/controller/panel/PanelViewLinkageController.java b/backend/src/main/java/io/dataease/controller/panel/PanelViewLinkageController.java index b74b33a97f..c994a835f7 100644 --- a/backend/src/main/java/io/dataease/controller/panel/PanelViewLinkageController.java +++ b/backend/src/main/java/io/dataease/controller/panel/PanelViewLinkageController.java @@ -9,6 +9,7 @@ import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.util.List; import java.util.Map; /** @@ -39,5 +40,10 @@ public class PanelViewLinkageController { } + @ApiOperation("获取当前仪表板所有联动信息") + @GetMapping("/getPanelAllLinkageInfo/{panelId}") + public Map> getPanelAllLinkageInfo(@PathVariable String panelId){ + return panelViewLinkageService.getPanelAllLinkageInfo(panelId); + } } diff --git a/backend/src/main/java/io/dataease/controller/request/chart/ChartDrillRequest.java b/backend/src/main/java/io/dataease/controller/request/chart/ChartDrillRequest.java new file mode 100644 index 0000000000..c5537b9d4a --- /dev/null +++ b/backend/src/main/java/io/dataease/controller/request/chart/ChartDrillRequest.java @@ -0,0 +1,15 @@ +package io.dataease.controller.request.chart; + +import io.dataease.dto.chart.ChartDimensionDTO; +import lombok.Data; + +import java.util.List; + +/** + * @Author gin + * @Date 2021/8/10 12:25 下午 + */ +@Data +public class ChartDrillRequest { + private List dimensionList; +} diff --git a/backend/src/main/java/io/dataease/controller/request/chart/ChartExtRequest.java b/backend/src/main/java/io/dataease/controller/request/chart/ChartExtRequest.java index 3806316bd6..edf9a5e9d7 100644 --- a/backend/src/main/java/io/dataease/controller/request/chart/ChartExtRequest.java +++ b/backend/src/main/java/io/dataease/controller/request/chart/ChartExtRequest.java @@ -13,4 +13,8 @@ import java.util.List; @Setter public class ChartExtRequest { private List filter; + + //联动过滤条件 + private List linkageFilters; + private List drill; } diff --git a/backend/src/main/java/io/dataease/controller/sys/SysDeptController.java b/backend/src/main/java/io/dataease/controller/sys/SysDeptController.java index 421aaafa25..38ee1745f5 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SysDeptController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SysDeptController.java @@ -4,14 +4,14 @@ import io.dataease.base.domain.SysDept; import io.dataease.commons.utils.BeanUtils; import io.dataease.controller.ResultHolder; import io.dataease.controller.sys.base.BaseGridRequest; -import io.dataease.controller.sys.request.DeptCreateRequest; +/*import io.dataease.controller.sys.request.DeptCreateRequest; import io.dataease.controller.sys.request.DeptDeleteRequest; -import io.dataease.controller.sys.request.DeptStatusRequest; +import io.dataease.controller.sys.request.DeptStatusRequest;*/ import io.dataease.controller.sys.response.DeptNodeResponse; import io.dataease.controller.sys.response.DeptTreeNode; import io.dataease.service.sys.DeptService; import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +/*import io.swagger.annotations.ApiOperation;*/ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -46,7 +46,6 @@ public class SysDeptController extends ResultHolder { @PostMapping("/search") public List search(@RequestBody BaseGridRequest request){ List nodes = deptService.nodesTreeByCondition(request); - //List nodes = deptService.nodesByPid(pid); List nodeResponses = nodes.stream().map(node -> { DeptNodeResponse deptNodeResponse = BeanUtils.copyBean(new DeptNodeResponse(), node); deptNodeResponse.setHasChildren(node.getSubCount() > 0); @@ -57,14 +56,14 @@ public class SysDeptController extends ResultHolder { return nodeResponses; } - @ApiOperation("查询部门") + /*@ApiOperation("查询部门") @PostMapping("/root") public ResultHolder rootData(){ List root = deptService.nodesByPid(null); return success(root); - } + }*/ - @ApiOperation("新增部门") + /*@ApiOperation("新增部门") @PostMapping("/create") public void create(@RequestBody DeptCreateRequest dept){ deptService.add(dept); @@ -84,7 +83,7 @@ public class SysDeptController extends ResultHolder { @PostMapping("/updateStatus") public void updateStatus(@RequestBody DeptStatusRequest request){ deptService.updateStatus(request); - } + }*/ @PostMapping("/nodesByDeptId/{deptId}") public List nodesByDeptId(@PathVariable("deptId") Long deptId){ diff --git a/backend/src/main/java/io/dataease/controller/sys/SysRoleController.java b/backend/src/main/java/io/dataease/controller/sys/SysRoleController.java index 38ab9ead04..5ba5cca08e 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SysRoleController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SysRoleController.java @@ -1,30 +1,30 @@ package io.dataease.controller.sys; -import com.github.pagehelper.Page; +/*import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import io.dataease.base.domain.SysRole; import io.dataease.commons.utils.PageUtils; import io.dataease.commons.utils.Pager; import io.dataease.controller.sys.base.BaseGridRequest; -import io.dataease.controller.sys.request.RoleMenusRequest; +import io.dataease.controller.sys.request.RoleMenusRequest;*/ import io.dataease.controller.sys.response.RoleUserItem; import io.dataease.service.sys.SysRoleService; import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +/*import io.swagger.annotations.ApiOperation;*/ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import springfox.documentation.annotations.ApiIgnore; import javax.annotation.Resource; import java.util.List; -@ApiIgnore +/*@ApiIgnore @RestController @RequiredArgsConstructor @Api(tags = "系统:角色管理") @RequestMapping("/api/role") -public class SysRoleController { - +public class SysRoleController {*/ + /* @Resource private SysRoleService sysRoleService; @@ -74,4 +74,5 @@ public class SysRoleController { public List all(){ return sysRoleService.allRoles(); } -} + */ +/*}*/ diff --git a/backend/src/main/java/io/dataease/controller/sys/SysUserController.java b/backend/src/main/java/io/dataease/controller/sys/SysUserController.java index 08fa39bd9b..daf98f1796 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SysUserController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SysUserController.java @@ -12,7 +12,9 @@ import io.dataease.controller.sys.base.BaseGridRequest; import io.dataease.controller.sys.request.SysUserCreateRequest; import io.dataease.controller.sys.request.SysUserPwdRequest; import io.dataease.controller.sys.request.SysUserStateRequest; +import io.dataease.controller.sys.response.RoleUserItem; import io.dataease.controller.sys.response.SysUserGridResponse; +import io.dataease.service.sys.SysRoleService; import io.dataease.service.sys.SysUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -32,6 +34,9 @@ public class SysUserController { @Resource private SysUserService sysUserService; + @Resource + private SysRoleService sysRoleService; + @ApiOperation("查询用户") @PostMapping("/userGrid/{goPage}/{pageSize}") public Pager> userGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody BaseGridRequest request) { @@ -68,26 +73,27 @@ public class SysUserController { sysUserService.updateStatus(request); } - @ApiOperation("用户更新密码") + @ApiOperation("更新当前用户密码") @PostMapping("/updatePwd") public void updatePwd(@RequestBody SysUserPwdRequest request){ sysUserService.updatePwd(request); } - @ApiOperation("管理员更新密码") + @ApiOperation("更新指定用户密码") @PostMapping("/adminUpdatePwd") public void adminUpdatePwd(@RequestBody SysUserPwdRequest request){ sysUserService.adminUpdatePwd(request); } - @ApiOperation("个人信息") + @ApiOperation("当前用户信息") @PostMapping("/personInfo") public CurrentUserDto personInfo() { CurrentUserDto user = AuthUtils.getUser(); return user; } + @ApiIgnore @ApiOperation("更新个人信息") @PostMapping("/updatePersonInfo") public void updatePersonInfo(@RequestBody SysUserCreateRequest request){ @@ -104,4 +110,10 @@ public class SysUserController { } }); } + + @ApiOperation("查询所有角色") + @PostMapping("/all") + public List all(){ + return sysRoleService.allRoles(); + } } diff --git a/backend/src/main/java/io/dataease/controller/sys/base/BaseGridRequest.java b/backend/src/main/java/io/dataease/controller/sys/base/BaseGridRequest.java index 7ad000f0a8..0e645dab29 100644 --- a/backend/src/main/java/io/dataease/controller/sys/base/BaseGridRequest.java +++ b/backend/src/main/java/io/dataease/controller/sys/base/BaseGridRequest.java @@ -1,6 +1,7 @@ package io.dataease.controller.sys.base; import io.dataease.base.mapper.ext.query.GridExample; +import io.swagger.annotations.ApiModelProperty; import org.apache.commons.collections.CollectionUtils; import java.io.Serializable; @@ -9,6 +10,7 @@ import java.util.List; public class BaseGridRequest implements Serializable { + @ApiModelProperty("查询条件") private List conditions; public List getConditions() { @@ -27,6 +29,7 @@ public class BaseGridRequest implements Serializable { this.orders = orders; } + @ApiModelProperty("排序描述") private List orders; public GridExample convertExample(){ diff --git a/backend/src/main/java/io/dataease/controller/sys/base/ConditionEntity.java b/backend/src/main/java/io/dataease/controller/sys/base/ConditionEntity.java index 0da0774c41..304cfcf588 100644 --- a/backend/src/main/java/io/dataease/controller/sys/base/ConditionEntity.java +++ b/backend/src/main/java/io/dataease/controller/sys/base/ConditionEntity.java @@ -1,5 +1,6 @@ package io.dataease.controller.sys.base; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -7,10 +8,13 @@ import java.io.Serializable; @Data public class ConditionEntity implements Serializable { + @ApiModelProperty(value = "字段") private String field; + @ApiModelProperty(value = "操作符") private String operator; + @ApiModelProperty(value = "字段值") private Object value; } diff --git a/backend/src/main/java/io/dataease/controller/sys/request/BatchSettingRequest.java b/backend/src/main/java/io/dataease/controller/sys/request/BatchSettingRequest.java index f318e7f1dd..1da1a41e2f 100644 --- a/backend/src/main/java/io/dataease/controller/sys/request/BatchSettingRequest.java +++ b/backend/src/main/java/io/dataease/controller/sys/request/BatchSettingRequest.java @@ -1,5 +1,6 @@ package io.dataease.controller.sys.request; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -7,10 +8,10 @@ import java.util.List; @Data public class BatchSettingRequest implements Serializable { - + @ApiModelProperty("消息类型ID集合") private List typeIds; - + @ApiModelProperty("消息类型ID") private Long channelId; - + @ApiModelProperty("订阅状态") private Boolean enable; } diff --git a/backend/src/main/java/io/dataease/controller/sys/request/MsgRequest.java b/backend/src/main/java/io/dataease/controller/sys/request/MsgRequest.java index 30f55e4093..3645287be2 100644 --- a/backend/src/main/java/io/dataease/controller/sys/request/MsgRequest.java +++ b/backend/src/main/java/io/dataease/controller/sys/request/MsgRequest.java @@ -1,5 +1,6 @@ package io.dataease.controller.sys.request; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -10,9 +11,12 @@ public class MsgRequest implements Serializable { private static final long serialVersionUID = 1920091635946508658L; + @ApiModelProperty("消息类型ID") private Long type; + @ApiModelProperty("是否订阅") private Boolean status; + @ApiModelProperty("排序描述") private List orders; } diff --git a/backend/src/main/java/io/dataease/controller/sys/request/MsgSettingRequest.java b/backend/src/main/java/io/dataease/controller/sys/request/MsgSettingRequest.java index 68ac29e79c..3e59a31efb 100644 --- a/backend/src/main/java/io/dataease/controller/sys/request/MsgSettingRequest.java +++ b/backend/src/main/java/io/dataease/controller/sys/request/MsgSettingRequest.java @@ -1,6 +1,7 @@ package io.dataease.controller.sys.request; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -8,7 +9,9 @@ import java.io.Serializable; @Data public class MsgSettingRequest implements Serializable { + @ApiModelProperty("消息类型ID") private Long typeId; + @ApiModelProperty("消息渠道ID") private Long channelId; } diff --git a/backend/src/main/java/io/dataease/controller/sys/request/SysUserCreateRequest.java b/backend/src/main/java/io/dataease/controller/sys/request/SysUserCreateRequest.java index e5d24f98f4..8f1149ead6 100644 --- a/backend/src/main/java/io/dataease/controller/sys/request/SysUserCreateRequest.java +++ b/backend/src/main/java/io/dataease/controller/sys/request/SysUserCreateRequest.java @@ -1,13 +1,16 @@ package io.dataease.controller.sys.request; import io.dataease.base.domain.SysUser; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import java.util.ArrayList; import java.util.List; @Data public class SysUserCreateRequest extends SysUser { + @ApiModelProperty(value = "角色ID集合", required = true, position = 7) private List roleIds; } diff --git a/backend/src/main/java/io/dataease/controller/sys/request/SysUserPwdRequest.java b/backend/src/main/java/io/dataease/controller/sys/request/SysUserPwdRequest.java index 2627deeede..7f8c2aa3f1 100644 --- a/backend/src/main/java/io/dataease/controller/sys/request/SysUserPwdRequest.java +++ b/backend/src/main/java/io/dataease/controller/sys/request/SysUserPwdRequest.java @@ -1,6 +1,7 @@ package io.dataease.controller.sys.request; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -8,9 +9,13 @@ import java.io.Serializable; @Data public class SysUserPwdRequest implements Serializable { + @ApiModelProperty(value = "用户ID", required = true) private Long userId; + @ApiModelProperty(value = "旧密码(密文)", required = true) private String password; + @ApiModelProperty(hidden = true) private String repeatPassword; + @ApiModelProperty(value = "新密码(明文)", required = true) private String newPassword; diff --git a/backend/src/main/java/io/dataease/controller/sys/request/SysUserStateRequest.java b/backend/src/main/java/io/dataease/controller/sys/request/SysUserStateRequest.java index 4a2fd9ef8c..379eb14d47 100644 --- a/backend/src/main/java/io/dataease/controller/sys/request/SysUserStateRequest.java +++ b/backend/src/main/java/io/dataease/controller/sys/request/SysUserStateRequest.java @@ -1,5 +1,6 @@ package io.dataease.controller.sys.request; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -7,7 +8,9 @@ import java.io.Serializable; @Data public class SysUserStateRequest implements Serializable { + @ApiModelProperty(value = "用户ID", required = true) private Long userId; + @ApiModelProperty(value = "状态", required = true, allowableValues = "1,0") private Long enabled; } diff --git a/backend/src/main/java/io/dataease/controller/sys/response/SettingTreeNode.java b/backend/src/main/java/io/dataease/controller/sys/response/SettingTreeNode.java index bbbd574c00..74d3f6a718 100644 --- a/backend/src/main/java/io/dataease/controller/sys/response/SettingTreeNode.java +++ b/backend/src/main/java/io/dataease/controller/sys/response/SettingTreeNode.java @@ -1,6 +1,7 @@ package io.dataease.controller.sys.response; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -11,9 +12,12 @@ public class SettingTreeNode implements Serializable { private static final long serialVersionUID = -2416283978185545199L; + @ApiModelProperty("消息类型ID") private Long id; + @ApiModelProperty("消息类型名称") private String name; + @ApiModelProperty("子节点") private List children; } diff --git a/backend/src/main/java/io/dataease/datasource/constants/DatasourceTypes.java b/backend/src/main/java/io/dataease/datasource/constants/DatasourceTypes.java index fcaf060a42..3724c7f8ea 100644 --- a/backend/src/main/java/io/dataease/datasource/constants/DatasourceTypes.java +++ b/backend/src/main/java/io/dataease/datasource/constants/DatasourceTypes.java @@ -3,6 +3,7 @@ package io.dataease.datasource.constants; public enum DatasourceTypes { excel("excel", "excel", "", "", "", "", ""), mysql("mysql", "mysql", "com.mysql.jdbc.Driver", "`", "`", "'", "'"), + pg("pg", "pg", "org.postgresql.Driver", "\"", "\"", "\"", "\""), sqlServer("sqlServer", "sqlServer", "com.microsoft.sqlserver.jdbc.SQLServerDriver", "\"", "\"", "\"", "\""), doris("doris", "doris", "com.mysql.jdbc.Driver", "`", "`", "", ""), oracle("oracle", "oracle", "oracle.jdbc.driver.OracleDriver", "\"", "\"", "\"", "\""); diff --git a/backend/src/main/java/io/dataease/datasource/dto/JdbcDTO.java b/backend/src/main/java/io/dataease/datasource/dto/JdbcDTO.java index 4f5c6b822a..e22657cdf0 100644 --- a/backend/src/main/java/io/dataease/datasource/dto/JdbcDTO.java +++ b/backend/src/main/java/io/dataease/datasource/dto/JdbcDTO.java @@ -12,5 +12,6 @@ public class JdbcDTO { private String username; private String password; private String dataBase; + private String schema; private String dataSourceType = "jdbc"; } diff --git a/backend/src/main/java/io/dataease/datasource/dto/OracleConfigration.java b/backend/src/main/java/io/dataease/datasource/dto/OracleConfigration.java index 6cebb06f13..6323791f90 100644 --- a/backend/src/main/java/io/dataease/datasource/dto/OracleConfigration.java +++ b/backend/src/main/java/io/dataease/datasource/dto/OracleConfigration.java @@ -9,7 +9,6 @@ public class OracleConfigration extends JdbcDTO { private String driver = "oracle.jdbc.driver.OracleDriver"; private String connectionType; - private String schema; public String getJdbc() { // 连接参数先写死,后边要把编码、时区等参数放到数据源的设置中 diff --git a/backend/src/main/java/io/dataease/datasource/dto/PgConfigration.java b/backend/src/main/java/io/dataease/datasource/dto/PgConfigration.java new file mode 100644 index 0000000000..3258c575c0 --- /dev/null +++ b/backend/src/main/java/io/dataease/datasource/dto/PgConfigration.java @@ -0,0 +1,19 @@ +package io.dataease.datasource.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PgConfigration extends JdbcDTO { + + private String driver = "org.postgresql.Driver"; + + public String getJdbc() { + // 连接参数先写死,后边要把编码、时区等参数放到数据源的设置中 + return "jdbc:postgresql://HOSTNAME:PORT/DATABASE" + .replace("HOSTNAME", getHost()) + .replace("PORT", getPort().toString()) + .replace("DATABASE", getDataBase()); + } +} \ No newline at end of file diff --git a/backend/src/main/java/io/dataease/datasource/dto/SqlServerConfigration.java b/backend/src/main/java/io/dataease/datasource/dto/SqlServerConfigration.java index 1cbe90c83a..7282704586 100644 --- a/backend/src/main/java/io/dataease/datasource/dto/SqlServerConfigration.java +++ b/backend/src/main/java/io/dataease/datasource/dto/SqlServerConfigration.java @@ -8,7 +8,6 @@ import lombok.Setter; @Setter public class SqlServerConfigration extends JdbcDTO { private String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; - private String schema; public String getJdbc(){ return "jdbc:sqlserver://HOSTNAME:PORT;DatabaseName=DATABASE".replace("HOSTNAME", getHost()).replace("PORT", getPort().toString()).replace("DATABASE", getDataBase()); diff --git a/backend/src/main/java/io/dataease/datasource/provider/JdbcProvider.java b/backend/src/main/java/io/dataease/datasource/provider/JdbcProvider.java index 12e30186df..e53caacbc9 100644 --- a/backend/src/main/java/io/dataease/datasource/provider/JdbcProvider.java +++ b/backend/src/main/java/io/dataease/datasource/provider/JdbcProvider.java @@ -3,10 +3,7 @@ package io.dataease.datasource.provider; import com.google.gson.Gson; import com.mchange.v2.c3p0.ComboPooledDataSource; import io.dataease.datasource.constants.DatasourceTypes; -import io.dataease.datasource.dto.MysqlConfigration; -import io.dataease.datasource.dto.OracleConfigration; -import io.dataease.datasource.dto.SqlServerConfigration; -import io.dataease.datasource.dto.TableFiled; +import io.dataease.datasource.dto.*; import io.dataease.datasource.request.DatasourceRequest; import io.dataease.exception.DataEaseException; import io.dataease.i18n.Translator; @@ -309,7 +306,7 @@ public class JdbcProvider extends DatasourceProvider { resultSet.close(); ps.close(); } catch (Exception e) { - DataEaseException.throwException(Translator.get("i18n_datasource_connect_error") + e.getMessage()); + DataEaseException.throwException(e.getMessage()); } finally { if(con != null){con.close();} } @@ -433,6 +430,12 @@ public class JdbcProvider extends DatasourceProvider { props.put( "oracle.net.CONNECT_TIMEOUT" , "5000") ; // props.put( "oracle.jdbc.ReadTimeout" , "5000" ) ; break; + case pg: + PgConfigration pgConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), PgConfigration.class); + username = pgConfigration.getUsername(); + password = pgConfigration.getPassword(); + driver = pgConfigration.getDriver(); + jdbcurl = pgConfigration.getJdbc(); default: break; } @@ -477,6 +480,13 @@ public class JdbcProvider extends DatasourceProvider { dataSource.setPassword(oracleConfigration.getPassword()); dataSource.setJdbcUrl(oracleConfigration.getJdbc()); break; + case pg: + PgConfigration pgConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), PgConfigration.class); + dataSource.setUser(pgConfigration.getUsername()); + dataSource.setDriverClass(pgConfigration.getDriver()); + dataSource.setPassword(pgConfigration.getPassword()); + dataSource.setJdbcUrl(pgConfigration.getJdbc()); + break; default: break; } @@ -494,6 +504,9 @@ public class JdbcProvider extends DatasourceProvider { case sqlServer: SqlServerConfigration sqlServerConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), SqlServerConfigration.class); return sqlServerConfigration.getDataBase(); + case pg: + PgConfigration pgConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), PgConfigration.class); + return pgConfigration.getDataBase(); default: return null; } @@ -517,6 +530,12 @@ public class JdbcProvider extends DatasourceProvider { throw new Exception(Translator.get("i18n_schema_is_empty")); } return "select table_name, owner from all_tables where owner='" + oracleConfigration.getSchema() + "'"; + case pg: + PgConfigration pgConfigration = new Gson().fromJson(datasourceRequest.getDatasource().getConfiguration(), PgConfigration.class); + if(StringUtils.isEmpty(pgConfigration.getSchema())){ + throw new Exception(Translator.get("i18n_schema_is_empty")); + } + return "SELECT tablename FROM pg_tables WHERE tablename NOT LIKE 'pg%' AND tablename NOT LIKE 'sql_%' AND schemaname='SCHEMA' ;".replace("SCHEMA", pgConfigration.getSchema()); default: return "show tables;"; } @@ -529,6 +548,8 @@ public class JdbcProvider extends DatasourceProvider { return "select * from all_users"; case sqlServer: return "select name from sys.schemas;"; + case pg: + return "SELECT nspname FROM pg_namespace;"; default: return "show tables;"; } diff --git a/backend/src/main/java/io/dataease/datasource/provider/ProviderFactory.java b/backend/src/main/java/io/dataease/datasource/provider/ProviderFactory.java index 88a720571a..d780399648 100644 --- a/backend/src/main/java/io/dataease/datasource/provider/ProviderFactory.java +++ b/backend/src/main/java/io/dataease/datasource/provider/ProviderFactory.java @@ -28,6 +28,8 @@ public class ProviderFactory implements ApplicationContextAware { return context.getBean("jdbc", DatasourceProvider.class); case sqlServer: return context.getBean("jdbc", DatasourceProvider.class); + case pg: + return context.getBean("jdbc", DatasourceProvider.class); default: return context.getBean("jdbc", DatasourceProvider.class); } @@ -42,6 +44,8 @@ public class ProviderFactory implements ApplicationContextAware { return context.getBean("dorisQuery", QueryProvider.class); case sqlServer: return context.getBean("sqlserverQuery", QueryProvider.class); + case pg: + return context.getBean("pgQuery", QueryProvider.class); case oracle: return context.getBean("oracleQuery", QueryProvider.class); default: diff --git a/backend/src/main/java/io/dataease/dto/LinkageInfoDTO.java b/backend/src/main/java/io/dataease/dto/LinkageInfoDTO.java new file mode 100644 index 0000000000..d1f915b042 --- /dev/null +++ b/backend/src/main/java/io/dataease/dto/LinkageInfoDTO.java @@ -0,0 +1,31 @@ +package io.dataease.dto; + +import java.util.List; + +/** + * Author: wangjiahao + * Date: 8/10/21 + * Description: + */ +public class LinkageInfoDTO { + + private String sourceInfo; + + private List targetInfoList; + + public String getSourceInfo() { + return sourceInfo; + } + + public void setSourceInfo(String sourceInfo) { + this.sourceInfo = sourceInfo; + } + + public List getTargetInfoList() { + return targetInfoList; + } + + public void setTargetInfoList(List targetInfoList) { + this.targetInfoList = targetInfoList; + } +} diff --git a/backend/src/main/java/io/dataease/dto/chart/ChartViewDTO.java b/backend/src/main/java/io/dataease/dto/chart/ChartViewDTO.java index 2a48769ef6..a431983eb6 100644 --- a/backend/src/main/java/io/dataease/dto/chart/ChartViewDTO.java +++ b/backend/src/main/java/io/dataease/dto/chart/ChartViewDTO.java @@ -1,9 +1,11 @@ package io.dataease.dto.chart; import io.dataease.base.domain.ChartViewWithBLOBs; +import io.dataease.controller.request.chart.ChartExtFilterRequest; import lombok.Getter; import lombok.Setter; +import java.util.List; import java.util.Map; /** @@ -20,4 +22,8 @@ public class ChartViewDTO extends ChartViewWithBLOBs { private Boolean isLeaf; private String pid; private String sql; + + private boolean drill; + + private List drillFilters; } diff --git a/backend/src/main/java/io/dataease/plugins/server/PluginCommonServer.java b/backend/src/main/java/io/dataease/plugins/server/PluginCommonServer.java index fd75f0d08a..225542842f 100644 --- a/backend/src/main/java/io/dataease/plugins/server/PluginCommonServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/PluginCommonServer.java @@ -8,6 +8,8 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import springfox.documentation.annotations.ApiIgnore; + import javax.servlet.http.HttpServletResponse; import java.io.BufferedInputStream; import java.io.IOException; @@ -17,6 +19,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; +@ApiIgnore @RestController @RequestMapping("/api/pluginCommon") public class PluginCommonServer { diff --git a/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java b/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java index 4a6c0bb6f1..e58fe09995 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XDeptServer.java @@ -11,14 +11,19 @@ import io.dataease.plugins.xpack.dept.dto.request.XpackMoveDept; import io.dataease.plugins.xpack.dept.dto.response.XpackDeptTreeNode; import io.dataease.plugins.xpack.dept.dto.response.XpackSysDept; import io.dataease.plugins.xpack.dept.service.DeptXpackService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; +import springfox.documentation.annotations.ApiIgnore; + import java.util.List; import java.util.stream.Collectors; - +@Api(tags = "xpack:部门管理") @RequestMapping("/plugin/dept") @RestController public class XDeptServer { + @ApiOperation("查询子节点") @PostMapping("/childNodes/{pid}") public List childNodes(@PathVariable("pid") Long pid){ DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); @@ -33,6 +38,7 @@ public class XDeptServer { return nodeResponses; } + @ApiOperation("搜索组织树") @PostMapping("/search") public List search(@RequestBody XpackGridRequest request){ DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); @@ -47,6 +53,7 @@ public class XDeptServer { return nodeResponses; } + @ApiIgnore @PostMapping("/root") public List rootData(){ DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); @@ -54,18 +61,21 @@ public class XDeptServer { return nodes; } + @ApiOperation("创建") @PostMapping("/create") public int create(@RequestBody XpackCreateDept dept){ DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); return deptService.add(dept); } + @ApiOperation("删除") @PostMapping("/delete") public void delete(@RequestBody List requests){ DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); deptService.batchDelete(requests); } + @ApiOperation("更新") @PostMapping("/update") public int update(@RequestBody XpackCreateDept dept){ DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); @@ -73,12 +83,15 @@ public class XDeptServer { } + @ApiIgnore + @ApiOperation("删除") @PostMapping("/nodesByDeptId/{deptId}") public List nodesByDeptId(@PathVariable("deptId") Long deptId){ DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); return deptService.searchTree(deptId); } + @ApiOperation("移动") @PostMapping("/move") public void move(@RequestBody XpackMoveDept xpackMoveDept){ DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class); diff --git a/backend/src/main/java/io/dataease/plugins/server/XRoleServer.java b/backend/src/main/java/io/dataease/plugins/server/XRoleServer.java index 97905e18c5..b9493a0e62 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XRoleServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XRoleServer.java @@ -10,14 +10,19 @@ import io.dataease.plugins.config.SpringContextUtil; import io.dataease.plugins.xpack.role.dto.response.XpackRoleDto; import io.dataease.plugins.xpack.role.dto.response.XpackRoleItemDto; import io.dataease.plugins.xpack.role.service.RoleXpackService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; +import springfox.documentation.annotations.ApiIgnore; import java.util.List; +@Api(tags = "xpack:角色管理") @RequestMapping("/plugin/role") @RestController public class XRoleServer { + @ApiOperation("新增角色") @PostMapping("/create") public void create(@RequestBody XpackRoleDto role){ RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class); @@ -25,6 +30,7 @@ public class XRoleServer { } + @ApiOperation("删除角色") @PostMapping("/delete/{roleId}") public void delete(@PathVariable("roleId") Long roleId){ RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class); @@ -32,12 +38,14 @@ public class XRoleServer { } + @ApiOperation("更新角色") @PostMapping("/update") public void update(@RequestBody XpackRoleDto role){ RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class); roleXpackService.update(role); } + @ApiOperation("分页查询") @PostMapping("/roleGrid/{goPage}/{pageSize}") public Pager> roleGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackGridRequest request) { RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class); @@ -46,6 +54,7 @@ public class XRoleServer { return listPager; } + @ApiIgnore @PostMapping("/all") public List all() { RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class); diff --git a/backend/src/main/java/io/dataease/provider/QueryProvider.java b/backend/src/main/java/io/dataease/provider/QueryProvider.java index 4c56399036..b3f4ad5a8a 100644 --- a/backend/src/main/java/io/dataease/provider/QueryProvider.java +++ b/backend/src/main/java/io/dataease/provider/QueryProvider.java @@ -1,10 +1,15 @@ package io.dataease.provider; +import com.google.gson.Gson; import io.dataease.base.domain.DatasetTableField; import io.dataease.base.domain.Datasource; import io.dataease.controller.request.chart.ChartExtFilterRequest; +import io.dataease.datasource.dto.JdbcDTO; +import io.dataease.datasource.dto.SqlServerConfigration; import io.dataease.dto.chart.ChartCustomFilterDTO; import io.dataease.dto.chart.ChartViewFieldDTO; +import io.dataease.dto.sqlObj.SQLObj; +import io.dataease.provider.pg.PgConstants; import java.util.List; @@ -30,15 +35,15 @@ public abstract class QueryProvider { public abstract String createQuerySQLAsTmpWithPage(String sql, List fields, Integer page, Integer pageSize, Integer realSize, boolean isGroup); - public abstract String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList); + public abstract String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, Datasource ds); public abstract String getSQLAsTmp(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList); - public abstract String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack); + public abstract String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack, Datasource ds); public abstract String getSQLAsTmpStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack); - public abstract String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble); + public abstract String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble, Datasource ds); public abstract String getSQLAsTmpScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble); @@ -59,7 +64,15 @@ public abstract class QueryProvider { public abstract String wrapSql(String sql); - public abstract String createRawQuerySQL(String table, List fields); + public abstract String createRawQuerySQL(String table, List fields, Datasource ds); public abstract String createRawQuerySQLAsTmp(String sql, List fields); + + public void setSchema(SQLObj tableObj, Datasource ds){ + if(ds != null){ + String schema = new Gson().fromJson(ds.getConfiguration(), JdbcDTO.class).getSchema(); + schema = String.format( PgConstants.KEYWORD_TABLE, schema); + tableObj.setTableName(schema + "." + tableObj.getTableName()); + } + } } diff --git a/backend/src/main/java/io/dataease/provider/doris/DorisQueryProvider.java b/backend/src/main/java/io/dataease/provider/doris/DorisQueryProvider.java index 8a411a6de6..f7638fe8c9 100644 --- a/backend/src/main/java/io/dataease/provider/doris/DorisQueryProvider.java +++ b/backend/src/main/java/io/dataease/provider/doris/DorisQueryProvider.java @@ -174,7 +174,7 @@ public class DorisQueryProvider extends QueryProvider { } @Override - public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { + public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(DorisConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) @@ -281,11 +281,11 @@ public class DorisQueryProvider extends QueryProvider { @Override public String getSQLAsTmp(String sql, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { - return getSQL("(" + sql + ")", xAxis, yAxis, customFilter, extFilterRequestList); + return getSQL("(" + sql + ")", xAxis, yAxis, customFilter, extFilterRequestList, null); } @Override - public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { + public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(DorisConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) @@ -395,11 +395,11 @@ public class DorisQueryProvider extends QueryProvider { @Override public String getSQLAsTmpStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { - return getSQLStack("(" + table + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack); + return getSQLStack("(" + table + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack, null); } @Override - public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { + public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(DorisConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) @@ -509,7 +509,7 @@ public class DorisQueryProvider extends QueryProvider { @Override public String getSQLAsTmpScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { - return getSQLScatter("(" + table + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble); + return getSQLScatter("(" + table + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble, null); } @Override @@ -605,7 +605,7 @@ public class DorisQueryProvider extends QueryProvider { } @Override - public String createRawQuerySQL(String table, List fields) { + public String createRawQuerySQL(String table, List fields, Datasource ds) { String[] array = fields.stream().map(f -> { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("`").append(f.getDataeaseName()).append("` AS ").append(f.getDataeaseName()); @@ -616,7 +616,7 @@ public class DorisQueryProvider extends QueryProvider { @Override public String createRawQuerySQLAsTmp(String sql, List fields) { - return createRawQuerySQL(" (" + sqlFix(sql) + ") AS tmp ", fields); + return createRawQuerySQL(" (" + sqlFix(sql) + ") AS tmp ", fields, null); } private String sqlFix(String sql) { diff --git a/backend/src/main/java/io/dataease/provider/mysql/MysqlQueryProvider.java b/backend/src/main/java/io/dataease/provider/mysql/MysqlQueryProvider.java index 5702a9a68d..7d95965a19 100644 --- a/backend/src/main/java/io/dataease/provider/mysql/MysqlQueryProvider.java +++ b/backend/src/main/java/io/dataease/provider/mysql/MysqlQueryProvider.java @@ -165,7 +165,7 @@ public class MysqlQueryProvider extends QueryProvider { } @Override - public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { + public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MySQLConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) @@ -273,11 +273,11 @@ public class MysqlQueryProvider extends QueryProvider { @Override public String getSQLAsTmp(String sql, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { - return getSQL("(" + sqlFix(sql) + ")", xAxis, yAxis, customFilter, extFilterRequestList); + return getSQL("(" + sqlFix(sql) + ")", xAxis, yAxis, customFilter, extFilterRequestList, null); } @Override - public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { + public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MySQLConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) @@ -387,11 +387,11 @@ public class MysqlQueryProvider extends QueryProvider { @Override public String getSQLAsTmpStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { - return getSQLStack("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack); + return getSQLStack("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack, null); } @Override - public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { + public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MySQLConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) @@ -501,7 +501,7 @@ public class MysqlQueryProvider extends QueryProvider { @Override public String getSQLAsTmpScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { - return getSQLScatter("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble); + return getSQLScatter("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble, null); } @Override @@ -597,7 +597,7 @@ public class MysqlQueryProvider extends QueryProvider { } @Override - public String createRawQuerySQL(String table, List fields) { + public String createRawQuerySQL(String table, List fields, Datasource ds) { String[] array = fields.stream().map(f -> { StringBuilder stringBuilder = new StringBuilder(); if (f.getDeExtractType() == 4) { // 处理 tinyint @@ -612,7 +612,7 @@ public class MysqlQueryProvider extends QueryProvider { @Override public String createRawQuerySQLAsTmp(String sql, List fields) { - return createRawQuerySQL(" (" + sqlFix(sql) + ") AS tmp ", fields); + return createRawQuerySQL(" (" + sqlFix(sql) + ") AS tmp ", fields, null); } public String transMysqlFilterTerm(String term) { diff --git a/backend/src/main/java/io/dataease/provider/oracle/OracleQueryProvider.java b/backend/src/main/java/io/dataease/provider/oracle/OracleQueryProvider.java index 02af808450..138a2cac52 100644 --- a/backend/src/main/java/io/dataease/provider/oracle/OracleQueryProvider.java +++ b/backend/src/main/java/io/dataease/provider/oracle/OracleQueryProvider.java @@ -199,7 +199,7 @@ public class OracleQueryProvider extends QueryProvider { } @Override - public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { + public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(OracleConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(OracleConstants.ALIAS_FIX, String.format(TABLE_ALIAS_PREFIX, 0))) @@ -306,11 +306,11 @@ public class OracleQueryProvider extends QueryProvider { @Override public String getSQLAsTmp(String sql, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { - return getSQL("(" + sqlFix(sql) + ")", xAxis, yAxis, customFilter, extFilterRequestList); + return getSQL("(" + sqlFix(sql) + ")", xAxis, yAxis, customFilter, extFilterRequestList, null); } @Override - public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { + public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(OracleConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(OracleConstants.ALIAS_FIX, String.format(TABLE_ALIAS_PREFIX, 0))) @@ -420,11 +420,11 @@ public class OracleQueryProvider extends QueryProvider { @Override public String getSQLAsTmpStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { - return getSQLStack("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack); + return getSQLStack("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack, null); } @Override - public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { + public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(OracleConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(OracleConstants.ALIAS_FIX, String.format(TABLE_ALIAS_PREFIX, 0))) @@ -534,7 +534,7 @@ public class OracleQueryProvider extends QueryProvider { @Override public String getSQLAsTmpScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { - return getSQLScatter("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble); + return getSQLScatter("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble, null); } @Override @@ -629,7 +629,7 @@ public class OracleQueryProvider extends QueryProvider { } @Override - public String createRawQuerySQL(String table, List fields) { + public String createRawQuerySQL(String table, List fields, Datasource ds) { String[] array = fields.stream().map(f -> { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(" \"").append(f.getOriginName()).append("\""); @@ -640,7 +640,7 @@ public class OracleQueryProvider extends QueryProvider { @Override public String createRawQuerySQLAsTmp(String sql, List fields) { - return createRawQuerySQL(" (" + sqlFix(sql) + ") DE_TMP ", fields); + return createRawQuerySQL(" (" + sqlFix(sql) + ") DE_TMP ", fields, null); } public String transMysqlFilterTerm(String term) { diff --git a/backend/src/main/java/io/dataease/provider/pg/PgConstants.java b/backend/src/main/java/io/dataease/provider/pg/PgConstants.java new file mode 100644 index 0000000000..e9f9555ae3 --- /dev/null +++ b/backend/src/main/java/io/dataease/provider/pg/PgConstants.java @@ -0,0 +1,43 @@ +package io.dataease.provider.pg; + +import io.dataease.provider.SQLConstants; + +import static io.dataease.datasource.constants.DatasourceTypes.pg; + +/** + * @Author gin + * @Date 2021/7/8 7:22 下午 + */ +public class PgConstants extends SQLConstants { + public static final String KEYWORD_TABLE = pg.getKeywordPrefix() + "%s" + pg.getKeywordSuffix(); + + public static final String KEYWORD_FIX = "%s." + pg.getKeywordPrefix() + "%s" + pg.getKeywordSuffix(); + + public static final String UNIX_TIMESTAMP = "floor(extract(epoch from(( %s - timestamp '1970-01-01 00:00:00')*1000))) "; + + public static final String DATE_FORMAT = "to_char(%s, %s)"; + + public static final String FROM_UNIXTIME = "to_timestamp(%s)"; + + public static final String CAST = "CAST(%s AS %s)"; + + public static final String DEFAULT_DATE_FORMAT = "'YYYY-MM-DD HH24:MI:SS'"; + + public static final String DEFAULT_INT_FORMAT = "numeric(18,0)"; + + public static final String DEFAULT_FLOAT_FORMAT = "numeric(18,2)"; + + public static final String WHERE_VALUE_NULL = "(NULL,'')"; + + public static final String WHERE_VALUE_VALUE = "'%s'"; + + public static final String AGG_COUNT = "COUNT(*)"; + + public static final String AGG_FIELD = "%s(%s)"; + + public static final String WHERE_BETWEEN = "'%s' AND '%s'"; + + public static final String BRACKETS = "(%s)"; + + +} diff --git a/backend/src/main/java/io/dataease/provider/pg/PgQueryProvider.java b/backend/src/main/java/io/dataease/provider/pg/PgQueryProvider.java new file mode 100644 index 0000000000..eecb57b2d2 --- /dev/null +++ b/backend/src/main/java/io/dataease/provider/pg/PgQueryProvider.java @@ -0,0 +1,922 @@ +package io.dataease.provider.pg; + +import com.google.gson.Gson; +import io.dataease.base.domain.DatasetTableField; +import io.dataease.base.domain.DatasetTableFieldExample; +import io.dataease.base.domain.Datasource; +import io.dataease.base.mapper.DatasetTableFieldMapper; +import io.dataease.commons.constants.DeTypeConstants; +import io.dataease.controller.request.chart.ChartExtFilterRequest; +import io.dataease.datasource.dto.JdbcDTO; +import io.dataease.datasource.dto.PgConfigration; +import io.dataease.datasource.dto.SqlServerConfigration; +import io.dataease.dto.chart.ChartCustomFilterDTO; +import io.dataease.dto.chart.ChartViewFieldDTO; +import io.dataease.dto.sqlObj.SQLObj; +import io.dataease.provider.QueryProvider; +import io.dataease.provider.SQLConstants; +import io.dataease.provider.sqlserver.SqlServerSQLConstants; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.stringtemplate.v4.ST; +import org.stringtemplate.v4.STGroup; +import org.stringtemplate.v4.STGroupFile; + +import javax.annotation.Resource; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static io.dataease.provider.SQLConstants.TABLE_ALIAS_PREFIX; + + + +@Service("pgQuery") +public class PgQueryProvider extends QueryProvider { + @Resource + private DatasetTableFieldMapper datasetTableFieldMapper; + + @Override + public Integer transFieldType(String field) { + field = field.toLowerCase(); + switch (field) { + case "bpchar": + case "varchar": + case "text": + case "tsquery": + case "tsvector": + case "uuid": + case "xml": + case "json": + case "bit": + case "jsonb": + case "cidr": + case "inet": + case "macaddr": + case "txid_snapshot": + case "box": + case "circle": + case "line": + case "lseg": + case "path": + case "point": + case "polygon": + case "bool": + case "interval": + return DeTypeConstants.DE_STRING;// 文本 + case "date": + case "time": + case "timestamp": + case "timestamptz": + return DeTypeConstants.DE_TIME;// 时间 + case "int2": + case "int4": + case "int8": + case "INTEGER": + case "BIGINT": + return DeTypeConstants.DE_INT;// 整型 + case "numeric": + case "float4": + case "float8": + case "money": + return DeTypeConstants.DE_FLOAT;// 浮点 +// case "bool": + case "TINYINT": + return DeTypeConstants.DE_BOOL;// 布尔 + case "bytea": + return DeTypeConstants.DE_Binary;// 二进制 + default: + return DeTypeConstants.DE_STRING; + } + } + + @Override + public String createSQLPreview(String sql, String orderBy) { + return "SELECT * FROM (" + sqlFix(sql) + ") AS tmp " + " LIMIT 1000 offset 0"; + } + + @Override + public String createQuerySQL(String table, List fields, boolean isGroup, Datasource ds) { + SQLObj tableObj = SQLObj.builder() + .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format( PgConstants.KEYWORD_TABLE, table)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) + .build(); + + setSchema(tableObj,ds); + List xFields = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(fields)) { + for (int i = 0; i < fields.size(); i++) { + DatasetTableField f = fields.get(i); + String originField; + if (ObjectUtils.isNotEmpty(f.getExtField()) && f.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originField = calcFieldRegex(f.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(f.getExtField()) && f.getExtField() == 1) { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), f.getOriginName()); + } else { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), f.getOriginName()); + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); + String fieldName = ""; + // 处理横轴字段 + if (f.getDeExtractType() == DeTypeConstants.DE_TIME) { + if (f.getDeType() == DeTypeConstants.DE_INT || f.getDeType() == DeTypeConstants.DE_FLOAT) { + fieldName = String.format( PgConstants.UNIX_TIMESTAMP, originField); + } else { + fieldName = originField; + } + } else if (f.getDeExtractType() == DeTypeConstants.DE_STRING) { + if (f.getDeType() == DeTypeConstants.DE_INT) { + fieldName = String.format( PgConstants.CAST, originField, PgConstants.DEFAULT_INT_FORMAT); + } else if (f.getDeType() == DeTypeConstants.DE_FLOAT) { + fieldName = String.format( PgConstants.CAST, originField, PgConstants.DEFAULT_FLOAT_FORMAT); + } else if (f.getDeType() == DeTypeConstants.DE_TIME) { + fieldName = String.format( PgConstants.CAST, originField, "timestamp"); + } else { + fieldName = originField; + } + } else { + if (f.getDeType() == DeTypeConstants.DE_TIME) { + String cast = String.format( PgConstants.CAST, originField, "bigint"); + fieldName = String.format( PgConstants.FROM_UNIXTIME, cast ); + } else if (f.getDeType() == DeTypeConstants.DE_INT) { + fieldName = String.format( PgConstants.CAST, originField, PgConstants.DEFAULT_INT_FORMAT); + } else { + fieldName = originField; + } + } + xFields.add(SQLObj.builder() + .fieldName(fieldName) + .fieldAlias(fieldAlias) + .build()); + } + } + + STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE); + ST st_sql = stg.getInstanceOf("previewSql"); + st_sql.add("isGroup", isGroup); + if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields); + if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj); + return st_sql.render(); + } + + @Override + public String createQuerySQLAsTmp(String sql, List fields, boolean isGroup) { + return createQuerySQL("(" + sqlFix(sql) + ")", fields, isGroup, null); + } + + @Override + public String createQuerySQLWithPage(String table, List fields, Integer page, Integer pageSize, Integer realSize, boolean isGroup, Datasource ds) { + return createQuerySQL(table, fields, isGroup, null) + " LIMIT " + realSize + " offset " + (page - 1) * pageSize; + } + + @Override + public String createQueryTableWithLimit(String table, List fields, Integer limit, boolean isGroup, Datasource ds) { + return createQuerySQL(table, fields, isGroup, null) + " LIMIT " + limit + " offset 0"; + } + + @Override + public String createQuerySqlWithLimit(String sql, List fields, Integer limit, boolean isGroup) { + return createQuerySQLAsTmp(sql, fields, isGroup) + " LIMIT " + limit + " offset 0"; + } + + @Override + public String createQuerySQLAsTmpWithPage(String sql, List fields, Integer page, Integer pageSize, Integer realSize, boolean isGroup) { + return createQuerySQLAsTmp(sql, fields, isGroup) + " LIMIT " + realSize + " offset " + (page - 1) * pageSize; + } + + @Override + public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, Datasource ds) { + SQLObj tableObj = SQLObj.builder() + .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format( PgConstants.KEYWORD_TABLE, table)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) + .build(); + setSchema(tableObj,ds); + List xFields = new ArrayList<>(); + List xWheres = new ArrayList<>(); + List xOrders = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(xAxis)) { + for (int i = 0; i < xAxis.size(); i++) { + ChartViewFieldDTO x = xAxis.get(i); + String originField; + if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originField = calcFieldRegex(x.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == 1) { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); + } else { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); + // 处理横轴字段 + xFields.add(getXFields(x, originField, fieldAlias)); + // 处理横轴过滤 +// xWheres.addAll(getXWheres(x, originField, fieldAlias)); + // 处理横轴排序 + if (StringUtils.isNotEmpty(x.getSort()) && !StringUtils.equalsIgnoreCase(x.getSort(), "none")) { + xOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(x.getSort()) + .build()); + } + } + } + List yFields = new ArrayList<>(); + List yWheres = new ArrayList<>(); + List yOrders = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(yAxis)) { + for (int i = 0; i < yAxis.size(); i++) { + ChartViewFieldDTO y = yAxis.get(i); + String originField; + if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originField = calcFieldRegex(y.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 1) { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + } else { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i); + // 处理纵轴字段 + yFields.add(getYFields(y, originField, fieldAlias)); + // 处理纵轴过滤 + yWheres.addAll(getYWheres(y, originField, fieldAlias)); + // 处理纵轴排序 + if (StringUtils.isNotEmpty(y.getSort()) && !StringUtils.equalsIgnoreCase(y.getSort(), "none")) { + yOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(y.getSort()) + .build()); + } + } + } + // 处理视图中字段过滤 + List customWheres = transCustomFilterList(tableObj, customFilter); + // 处理仪表板字段过滤 + List extWheres = transExtFilterList(tableObj, extFilterRequestList); + // 构建sql所有参数 + List fields = new ArrayList<>(); + fields.addAll(xFields); + fields.addAll(yFields); + List wheres = new ArrayList<>(); + wheres.addAll(xWheres); + if (customWheres != null) wheres.addAll(customWheres); + if (extWheres != null) wheres.addAll(extWheres); + List groups = new ArrayList<>(); + groups.addAll(xFields); + // 外层再次套sql + List orders = new ArrayList<>(); + orders.addAll(xOrders); + orders.addAll(yOrders); + List aggWheres = new ArrayList<>(); + aggWheres.addAll(yWheres); + + STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE); + ST st_sql = stg.getInstanceOf("querySql"); + if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields); + if (CollectionUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields); + if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres); + if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj); + String sql = st_sql.render(); + + ST st = stg.getInstanceOf("querySql"); + SQLObj tableSQL = SQLObj.builder() + .tableName(String.format( PgConstants.BRACKETS, sql)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 1)) + .build(); + if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres); + if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders); + if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL); + return st.render(); + } + + + @Override + public String getSQLAsTmp(String sql, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { + return getSQL("(" + sqlFix(sql) + ")", xAxis, yAxis, customFilter, extFilterRequestList, null); + } + + @Override + public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack, Datasource ds) { + SQLObj tableObj = SQLObj.builder() + .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format( PgConstants.KEYWORD_TABLE, table)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) + .build(); + setSchema(tableObj,ds); + List xFields = new ArrayList<>(); + List xWheres = new ArrayList<>(); + List xOrders = new ArrayList<>(); + List xList = new ArrayList<>(); + xList.addAll(xAxis); + xList.addAll(extStack); + if (CollectionUtils.isNotEmpty(xList)) { + for (int i = 0; i < xList.size(); i++) { + ChartViewFieldDTO x = xList.get(i); + String originField; + if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originField = calcFieldRegex(x.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == 1) { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); + } else { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); + // 处理横轴字段 + xFields.add(getXFields(x, originField, fieldAlias)); + // 处理横轴过滤 +// xWheres.addAll(getXWheres(x, originField, fieldAlias)); + // 处理横轴排序 + if (StringUtils.isNotEmpty(x.getSort()) && !StringUtils.equalsIgnoreCase(x.getSort(), "none")) { + xOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(x.getSort()) + .build()); + } + } + } + List yFields = new ArrayList<>(); + List yWheres = new ArrayList<>(); + List yOrders = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(yAxis)) { + for (int i = 0; i < yAxis.size(); i++) { + ChartViewFieldDTO y = yAxis.get(i); + String originField; + if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originField = calcFieldRegex(y.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 1) { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + } else { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i); + // 处理纵轴字段 + yFields.add(getYFields(y, originField, fieldAlias)); + // 处理纵轴过滤 + yWheres.addAll(getYWheres(y, originField, fieldAlias)); + // 处理纵轴排序 + if (StringUtils.isNotEmpty(y.getSort()) && !StringUtils.equalsIgnoreCase(y.getSort(), "none")) { + yOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(y.getSort()) + .build()); + } + } + } + // 处理视图中字段过滤 + List customWheres = transCustomFilterList(tableObj, customFilter); + // 处理仪表板字段过滤 + List extWheres = transExtFilterList(tableObj, extFilterRequestList); + // 构建sql所有参数 + List fields = new ArrayList<>(); + fields.addAll(xFields); + fields.addAll(yFields); + List wheres = new ArrayList<>(); + wheres.addAll(xWheres); + if (customWheres != null) wheres.addAll(customWheres); + if (extWheres != null) wheres.addAll(extWheres); + List groups = new ArrayList<>(); + groups.addAll(xFields); + // 外层再次套sql + List orders = new ArrayList<>(); + orders.addAll(xOrders); + orders.addAll(yOrders); + List aggWheres = new ArrayList<>(); + aggWheres.addAll(yWheres); + + STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE); + ST st_sql = stg.getInstanceOf("querySql"); + if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields); + if (CollectionUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields); + if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres); + if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj); + String sql = st_sql.render(); + + ST st = stg.getInstanceOf("querySql"); + SQLObj tableSQL = SQLObj.builder() + .tableName(String.format( PgConstants.BRACKETS, sql)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 1)) + .build(); + if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres); + if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders); + if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL); + return st.render(); + } + + @Override + public String getSQLAsTmpStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { + return getSQLStack("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack, null); + } + + @Override + public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble, Datasource ds) { + SQLObj tableObj = SQLObj.builder() + .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format( PgConstants.KEYWORD_TABLE, table)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) + .build(); + setSchema(tableObj,ds); + List xFields = new ArrayList<>(); + List xWheres = new ArrayList<>(); + List xOrders = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(xAxis)) { + for (int i = 0; i < xAxis.size(); i++) { + ChartViewFieldDTO x = xAxis.get(i); + String originField; + if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originField = calcFieldRegex(x.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == 1) { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); + } else { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); + // 处理横轴字段 + xFields.add(getXFields(x, originField, fieldAlias)); + // 处理横轴过滤 +// xWheres.addAll(getXWheres(x, originField, fieldAlias)); + // 处理横轴排序 + if (StringUtils.isNotEmpty(x.getSort()) && !StringUtils.equalsIgnoreCase(x.getSort(), "none")) { + xOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(x.getSort()) + .build()); + } + } + } + List yFields = new ArrayList<>(); + List yWheres = new ArrayList<>(); + List yOrders = new ArrayList<>(); + List yList = new ArrayList<>(); + yList.addAll(yAxis); + yList.addAll(extBubble); + if (CollectionUtils.isNotEmpty(yList)) { + for (int i = 0; i < yList.size(); i++) { + ChartViewFieldDTO y = yList.get(i); + String originField; + if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originField = calcFieldRegex(y.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 1) { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + } else { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i); + // 处理纵轴字段 + yFields.add(getYFields(y, originField, fieldAlias)); + // 处理纵轴过滤 + yWheres.addAll(getYWheres(y, originField, fieldAlias)); + // 处理纵轴排序 + if (StringUtils.isNotEmpty(y.getSort()) && !StringUtils.equalsIgnoreCase(y.getSort(), "none")) { + yOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(y.getSort()) + .build()); + } + } + } + // 处理视图中字段过滤 + List customWheres = transCustomFilterList(tableObj, customFilter); + // 处理仪表板字段过滤 + List extWheres = transExtFilterList(tableObj, extFilterRequestList); + // 构建sql所有参数 + List fields = new ArrayList<>(); + fields.addAll(xFields); + fields.addAll(yFields); + List wheres = new ArrayList<>(); + wheres.addAll(xWheres); + if (customWheres != null) wheres.addAll(customWheres); + if (extWheres != null) wheres.addAll(extWheres); + List groups = new ArrayList<>(); + groups.addAll(xFields); + // 外层再次套sql + List orders = new ArrayList<>(); + orders.addAll(xOrders); + orders.addAll(yOrders); + List aggWheres = new ArrayList<>(); + aggWheres.addAll(yWheres); + + STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE); + ST st_sql = stg.getInstanceOf("querySql"); + if (CollectionUtils.isNotEmpty(xFields)) st_sql.add("groups", xFields); + if (CollectionUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields); + if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres); + if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj); + String sql = st_sql.render(); + + ST st = stg.getInstanceOf("querySql"); + SQLObj tableSQL = SQLObj.builder() + .tableName(String.format( PgConstants.BRACKETS, sql)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 1)) + .build(); + if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres); + if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders); + if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL); + return st.render(); + } + + @Override + public String getSQLAsTmpScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { + return getSQLScatter("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble, null); + } + + @Override + public String searchTable(String table) { + return "SELECT table_name FROM information_schema.TABLES WHERE table_name ='" + table + "'"; + } + + @Override + public String getSQLSummary(String table, List yAxis, List customFilter, List extFilterRequestList) { + // 字段汇总 排序等 + SQLObj tableObj = SQLObj.builder() + .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format( PgConstants.KEYWORD_TABLE, table)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) + .build(); + List yFields = new ArrayList<>(); + List yWheres = new ArrayList<>(); + List yOrders = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(yAxis)) { + for (int i = 0; i < yAxis.size(); i++) { + ChartViewFieldDTO y = yAxis.get(i); + String originField; + if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originField = calcFieldRegex(y.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 1) { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + } else { + originField = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + } + String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i); + // 处理纵轴字段 + yFields.add(getYFields(y, originField, fieldAlias)); + // 处理纵轴过滤 + yWheres.addAll(getYWheres(y, originField, fieldAlias)); + // 处理纵轴排序 + if (StringUtils.isNotEmpty(y.getSort()) && !StringUtils.equalsIgnoreCase(y.getSort(), "none")) { + yOrders.add(SQLObj.builder() + .orderField(originField) + .orderAlias(fieldAlias) + .orderDirection(y.getSort()) + .build()); + } + } + } + // 处理视图中字段过滤 + List customWheres = transCustomFilterList(tableObj, customFilter); + // 处理仪表板字段过滤 + List extWheres = transExtFilterList(tableObj, extFilterRequestList); + // 构建sql所有参数 + List fields = new ArrayList<>(); + fields.addAll(yFields); + List wheres = new ArrayList<>(); + if (customWheres != null) wheres.addAll(customWheres); + if (extWheres != null) wheres.addAll(extWheres); + List groups = new ArrayList<>(); + // 外层再次套sql + List orders = new ArrayList<>(); + orders.addAll(yOrders); + List aggWheres = new ArrayList<>(); + aggWheres.addAll(yWheres); + + STGroup stg = new STGroupFile(SQLConstants.SQL_TEMPLATE); + ST st_sql = stg.getInstanceOf("querySql"); + if (CollectionUtils.isNotEmpty(yFields)) st_sql.add("aggregators", yFields); + if (CollectionUtils.isNotEmpty(wheres)) st_sql.add("filters", wheres); + if (ObjectUtils.isNotEmpty(tableObj)) st_sql.add("table", tableObj); + String sql = st_sql.render(); + + ST st = stg.getInstanceOf("querySql"); + SQLObj tableSQL = SQLObj.builder() + .tableName(String.format( PgConstants.BRACKETS, sql)) + .tableAlias(String.format(TABLE_ALIAS_PREFIX, 1)) + .build(); + if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres); + if (CollectionUtils.isNotEmpty(orders)) st.add("orders", orders); + if (ObjectUtils.isNotEmpty(tableSQL)) st.add("table", tableSQL); + return st.render(); + } + + @Override + public String getSQLSummaryAsTmp(String sql, List yAxis, List customFilter, List extFilterRequestList) { + return getSQLSummary("(" + sqlFix(sql) + ")", yAxis, customFilter, extFilterRequestList); + } + + @Override + public String wrapSql(String sql) { + sql = sql.trim(); + if (sql.lastIndexOf(";") == (sql.length() - 1)) { + sql = sql.substring(0, sql.length() - 1); + } + String tmpSql = "SELECT * FROM (" + sql + ") AS tmp " + " LIMIT 0 "; + return tmpSql; + } + + @Override + public String createRawQuerySQL(String table, List fields, Datasource ds) { + String[] array = fields.stream().map(f -> { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("\"").append(f.getOriginName()).append("\" AS ").append(f.getDataeaseName()); + return stringBuilder.toString(); + }).toArray(String[]::new); + if(ds != null){ + String schema = new Gson().fromJson(ds.getConfiguration(), JdbcDTO.class).getSchema(); + String tableWithSchema = String.format(SqlServerSQLConstants.KEYWORD_TABLE, schema) + "." + String.format(SqlServerSQLConstants.KEYWORD_TABLE, table); + return MessageFormat.format("SELECT {0} FROM {1} ", StringUtils.join(array, ","), tableWithSchema); + }else { + return MessageFormat.format("SELECT {0} FROM {1} ", StringUtils.join(array, ","), table); + } + } + + @Override + public String createRawQuerySQLAsTmp(String sql, List fields) { + return createRawQuerySQL(" (" + sqlFix(sql) + ") AS tmp ", fields, null); + } + + public String transMysqlFilterTerm(String term) { + switch (term) { + case "eq": + return " = "; + case "not_eq": + return " <> "; + case "lt": + return " < "; + case "le": + return " <= "; + case "gt": + return " > "; + case "ge": + return " >= "; + case "in": + return " IN "; + case "not in": + return " NOT IN "; + case "like": + return " LIKE "; + case "not like": + return " NOT LIKE "; + case "null": + return " IN "; + case "not_null": + return " IS NOT NULL AND %s <> ''"; + case "between": + return " BETWEEN "; + default: + return ""; + } + } + + public List transCustomFilterList(SQLObj tableObj, List requestList) { + if (CollectionUtils.isEmpty(requestList)) { + return null; + } + List list = new ArrayList<>(); + for (ChartCustomFilterDTO request : requestList) { + DatasetTableField field = request.getField(); + if (ObjectUtils.isEmpty(field)) { + continue; + } + String value = request.getValue(); + String whereName = ""; + String whereTerm = transMysqlFilterTerm(request.getTerm()); + String whereValue = ""; + String originName; + if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originName = calcFieldRegex(field.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) { + originName = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), field.getOriginName()); + } else { + originName = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), field.getOriginName()); + } + if (field.getDeType() == 1 && field.getDeExtractType() != 1) { + String cast = String.format( PgConstants.CAST, originName, "bigint"); + whereName = String.format( PgConstants.FROM_UNIXTIME, cast); + } else { + whereName = originName; + } + if (StringUtils.equalsIgnoreCase(request.getTerm(), "null")) { + whereValue = PgConstants.WHERE_VALUE_NULL; + } else if (StringUtils.equalsIgnoreCase(request.getTerm(), "not_null")) { + whereTerm = String.format(whereTerm, originName); + } else if (StringUtils.containsIgnoreCase(request.getTerm(), "in")) { + whereValue = "('" + StringUtils.join(value, "','") + "')"; + } else if (StringUtils.containsIgnoreCase(request.getTerm(), "like")) { + whereValue = "'%" + value + "%'"; + } else { + whereValue = String.format( PgConstants.WHERE_VALUE_VALUE, value); + } + list.add(SQLObj.builder() + .whereField(whereName) + .whereTermAndValue(whereTerm + whereValue) + .build()); + } + return list; + } + + public List transExtFilterList(SQLObj tableObj, List requestList) { + if (CollectionUtils.isEmpty(requestList)) { + return null; + } + List list = new ArrayList<>(); + for (ChartExtFilterRequest request : requestList) { + List value = request.getValue(); + DatasetTableField field = request.getDatasetTableField(); + if (CollectionUtils.isEmpty(value) || ObjectUtils.isEmpty(field)) { + continue; + } + String whereName = ""; + String whereTerm = transMysqlFilterTerm(request.getOperator()); + String whereValue = ""; + + String originName; + if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 2) { + // 解析origin name中有关联的字段生成sql表达式 + originName = calcFieldRegex(field.getOriginName(), tableObj); + } else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) { + originName = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), field.getOriginName()); + } else { + originName = String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), field.getOriginName()); + } + + if (field.getDeType() == 1 && field.getDeExtractType() != 1) { + String cast = String.format( PgConstants.CAST, originName, "bigint"); + whereName = String.format( PgConstants.FROM_UNIXTIME, cast); + } else { + whereName = originName; + } + + if (StringUtils.containsIgnoreCase(request.getOperator(), "in")) { + whereValue = "('" + StringUtils.join(value, "','") + "')"; + } else if (StringUtils.containsIgnoreCase(request.getOperator(), "like")) { + whereValue = "'%" + value.get(0) + "%'"; + } else if (StringUtils.containsIgnoreCase(request.getOperator(), "between")) { + if (request.getDatasetTableField().getDeType() == 1) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String startTime = simpleDateFormat.format(new Date(Long.parseLong(value.get(0)))); + String endTime = simpleDateFormat.format(new Date(Long.parseLong(value.get(1)))); + whereValue = String.format( PgConstants.WHERE_BETWEEN, startTime, endTime); + } else { + whereValue = String.format( PgConstants.WHERE_BETWEEN, value.get(0), value.get(1)); + } + } else { + whereValue = String.format( PgConstants.WHERE_VALUE_VALUE, value.get(0)); + } + list.add(SQLObj.builder() + .whereField(whereName) + .whereTermAndValue(whereTerm + whereValue) + .build()); + } + return list; + } + + private String sqlFix(String sql) { + if (sql.lastIndexOf(";") == (sql.length() - 1)) { + sql = sql.substring(0, sql.length() - 1); + } + return sql; + } + + private String transDateFormat(String dateStyle, String datePattern) { + String split = "-"; + if (StringUtils.equalsIgnoreCase(datePattern, "date_sub")) { + split = "-"; + } else if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { + split = "/"; + } + + switch (dateStyle) { + case "y": + return "'YYYY'"; + case "y_M": + return "'YYYY" + split + "MM'"; + case "y_M_d": + return "'YYYY" + split + "MM" + split + "DD'"; + case "H_m_s": + return "'HH24:MI:SS'"; + case "y_M_d_H_m": + return "'YYYY" + split + "MM" + split + "DD" + " HH24:MI'"; + case "y_M_d_H_m_s": + return "'YYYY" + split + "MM" + split + "DD" + " HH24:MI:SS'"; + default: + return "'YYYY-MM-DD HH24:MI:SS'"; + } + } + + private SQLObj getXFields(ChartViewFieldDTO x, String originField, String fieldAlias) { + String fieldName = ""; + if (x.getDeExtractType() == DeTypeConstants.DE_TIME) { + if (x.getDeType() == 2 || x.getDeType() == 3) { + fieldName = String.format( PgConstants.UNIX_TIMESTAMP, originField); + } else if (x.getDeType() == DeTypeConstants.DE_TIME) { + String format = transDateFormat(x.getDateStyle(), x.getDatePattern()); + fieldName = String.format( PgConstants.DATE_FORMAT, originField, format); + } else { + fieldName = originField; + } + } else { + if (x.getDeType() == DeTypeConstants.DE_TIME) { + String format = transDateFormat(x.getDateStyle(), x.getDatePattern()); + if (x.getDeExtractType() == DeTypeConstants.DE_STRING) { + fieldName = String.format( PgConstants.DATE_FORMAT, originField, format); + } else { + String cast = String.format( PgConstants.CAST, originField, "bigint"); + String from_unixtime = String.format( PgConstants.FROM_UNIXTIME, cast); + fieldName = String.format( PgConstants.DATE_FORMAT, from_unixtime, format); + } + } else { + fieldName = originField; + } + } + return SQLObj.builder() + .fieldName(fieldName) + .fieldAlias(fieldAlias) + .build(); + } + + private SQLObj getYFields(ChartViewFieldDTO y, String originField, String fieldAlias) { + String fieldName = ""; + if (StringUtils.equalsIgnoreCase(y.getOriginName(), "*")) { + fieldName = PgConstants.AGG_COUNT; + } else if (SQLConstants.DIMENSION_TYPE.contains(y.getDeType())) { + fieldName = String.format( PgConstants.AGG_FIELD, y.getSummary(), originField); + } else { + if (StringUtils.equalsIgnoreCase(y.getSummary(), "avg") || StringUtils.containsIgnoreCase(y.getSummary(), "pop")) { + String cast = String.format( PgConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? PgConstants.DEFAULT_INT_FORMAT : PgConstants.DEFAULT_FLOAT_FORMAT); + String agg = String.format( PgConstants.AGG_FIELD, y.getSummary(), cast); + fieldName = String.format( PgConstants.CAST, agg, PgConstants.DEFAULT_FLOAT_FORMAT); + } else { + String cast = String.format( PgConstants.CAST, originField, y.getDeType() == DeTypeConstants.DE_INT ? PgConstants.DEFAULT_INT_FORMAT : PgConstants.DEFAULT_FLOAT_FORMAT); + fieldName = String.format( PgConstants.AGG_FIELD, y.getSummary(), cast); + } + } + return SQLObj.builder() + .fieldName(fieldName) + .fieldAlias(fieldAlias) + .build(); + } + + private List getYWheres(ChartViewFieldDTO y, String originField, String fieldAlias) { + List list = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(y.getFilter()) && y.getFilter().size() > 0) { + y.getFilter().forEach(f -> { + String whereTerm = transMysqlFilterTerm(f.getTerm()); + String whereValue = ""; + // 原始类型不是时间,在de中被转成时间的字段做处理 + if (StringUtils.equalsIgnoreCase(f.getTerm(), "null")) { + whereValue = PgConstants.WHERE_VALUE_NULL; + } else if (StringUtils.equalsIgnoreCase(f.getTerm(), "not_null")) { + whereTerm = String.format(whereTerm, originField); + } else if (StringUtils.containsIgnoreCase(f.getTerm(), "in")) { + whereValue = "('" + StringUtils.join(f.getValue(), "','") + "')"; + } else if (StringUtils.containsIgnoreCase(f.getTerm(), "like")) { + whereValue = "'%" + f.getValue() + "%'"; + } else { + whereValue = String.format( PgConstants.WHERE_VALUE_VALUE, f.getValue()); + } + list.add(SQLObj.builder() + .whereField(fieldAlias) + .whereAlias(fieldAlias) + .whereTermAndValue(whereTerm + whereValue) + .build()); + }); + } + return list; + } + + private String calcFieldRegex(String originField, SQLObj tableObj) { + originField = originField.replaceAll("[\\t\\n\\r]]", ""); + // 正则提取[xxx] + String regex = "\\[(.*?)]"; + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(originField); + Set ids = new HashSet<>(); + while (matcher.find()) { + String id = matcher.group(1); + ids.add(id); + } + if (CollectionUtils.isEmpty(ids)) { + return originField; + } + DatasetTableFieldExample datasetTableFieldExample = new DatasetTableFieldExample(); + datasetTableFieldExample.createCriteria().andIdIn(new ArrayList<>(ids)); + List calcFields = datasetTableFieldMapper.selectByExample(datasetTableFieldExample); + for (DatasetTableField ele : calcFields) { + originField = originField.replaceAll("\\[" + ele.getId() + "]", + String.format( PgConstants.KEYWORD_FIX, tableObj.getTableAlias(), ele.getOriginName())); + } + return originField; + } +} diff --git a/backend/src/main/java/io/dataease/provider/sqlserver/SqlserverQueryProvider.java b/backend/src/main/java/io/dataease/provider/sqlserver/SqlserverQueryProvider.java index 2c8d0254ba..6820889473 100644 --- a/backend/src/main/java/io/dataease/provider/sqlserver/SqlserverQueryProvider.java +++ b/backend/src/main/java/io/dataease/provider/sqlserver/SqlserverQueryProvider.java @@ -7,13 +7,13 @@ import io.dataease.base.domain.Datasource; import io.dataease.base.mapper.DatasetTableFieldMapper; import io.dataease.commons.constants.DeTypeConstants; import io.dataease.controller.request.chart.ChartExtFilterRequest; +import io.dataease.datasource.dto.JdbcDTO; import io.dataease.datasource.dto.SqlServerConfigration; import io.dataease.dto.chart.ChartCustomFilterDTO; import io.dataease.dto.chart.ChartViewFieldDTO; import io.dataease.dto.sqlObj.SQLObj; import io.dataease.provider.QueryProvider; import io.dataease.provider.SQLConstants; -import io.dataease.provider.mysql.MySQLConstants; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; @@ -91,10 +91,7 @@ public class SqlserverQueryProvider extends QueryProvider { .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(SqlServerSQLConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) .build(); - if(ds != null){ - String schema = new Gson().fromJson(ds.getConfiguration(), SqlServerConfigration.class).getSchema(); - tableObj.setTableName(schema + "." + tableObj.getTableName()); - } + setSchema(tableObj,ds); List xFields = new ArrayList<>(); if (CollectionUtils.isNotEmpty(fields)) { @@ -171,11 +168,12 @@ public class SqlserverQueryProvider extends QueryProvider { } @Override - public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { + public String getSQL(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(SqlServerSQLConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) .build(); + setSchema(tableObj,ds); List xFields = new ArrayList<>(); List xWheres = new ArrayList<>(); List xOrders = new ArrayList<>(); @@ -263,15 +261,16 @@ public class SqlserverQueryProvider extends QueryProvider { @Override public String getSQLAsTmp(String sql, List xAxis, List yAxis, List customFilter, List extFilterRequestList) { - return getSQL("(" + sqlFix(sql) + ")", xAxis, yAxis, customFilter, extFilterRequestList); + return getSQL("(" + sqlFix(sql) + ")", xAxis, yAxis, customFilter, extFilterRequestList, null); } @Override - public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { + public String getSQLStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack, Datasource ds) { SQLObj tableObj = SQLObj.builder() .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(SqlServerSQLConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) .build(); + setSchema(tableObj,ds); List xFields = new ArrayList<>(); List xWheres = new ArrayList<>(); List xOrders = new ArrayList<>(); @@ -380,15 +379,16 @@ public class SqlserverQueryProvider extends QueryProvider { @Override public String getSQLAsTmpStack(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extStack) { - return getSQLStack("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack); + return getSQLStack("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extStack, null); } @Override - public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { + public String getSQLScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble, Datasource ds) { SQLObj tableObj = SQLObj.builder() - .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(MySQLConstants.KEYWORD_TABLE, table)) + .tableName((table.startsWith("(") && table.endsWith(")")) ? table : String.format(SqlServerSQLConstants.KEYWORD_TABLE, table)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 0)) .build(); + setSchema(tableObj,ds); List xFields = new ArrayList<>(); List xWheres = new ArrayList<>(); List xOrders = new ArrayList<>(); @@ -400,9 +400,9 @@ public class SqlserverQueryProvider extends QueryProvider { // 解析origin name中有关联的字段生成sql表达式 originField = calcFieldRegex(x.getOriginName(), tableObj); } else if (ObjectUtils.isNotEmpty(x.getExtField()) && x.getExtField() == 1) { - originField = String.format(MySQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); + originField = String.format(SqlServerSQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); } else { - originField = String.format(MySQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); + originField = String.format(SqlServerSQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), x.getOriginName()); } String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i); // 处理横轴字段 @@ -433,9 +433,9 @@ public class SqlserverQueryProvider extends QueryProvider { // 解析origin name中有关联的字段生成sql表达式 originField = calcFieldRegex(y.getOriginName(), tableObj); } else if (ObjectUtils.isNotEmpty(y.getExtField()) && y.getExtField() == 1) { - originField = String.format(MySQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + originField = String.format(SqlServerSQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); } else { - originField = String.format(MySQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); + originField = String.format(SqlServerSQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), y.getOriginName()); } String fieldAlias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i); // 处理纵轴字段 @@ -483,7 +483,7 @@ public class SqlserverQueryProvider extends QueryProvider { ST st = stg.getInstanceOf("querySql"); SQLObj tableSQL = SQLObj.builder() - .tableName(String.format(MySQLConstants.BRACKETS, sql)) + .tableName(String.format(SqlServerSQLConstants.BRACKETS, sql)) .tableAlias(String.format(TABLE_ALIAS_PREFIX, 1)) .build(); if (CollectionUtils.isNotEmpty(aggWheres)) st.add("filters", aggWheres); @@ -494,7 +494,7 @@ public class SqlserverQueryProvider extends QueryProvider { @Override public String getSQLAsTmpScatter(String table, List xAxis, List yAxis, List customFilter, List extFilterRequestList, List extBubble) { - return getSQLScatter("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble); + return getSQLScatter("(" + sqlFix(table) + ")", xAxis, yAxis, customFilter, extFilterRequestList, extBubble, null); } @Override @@ -582,23 +582,24 @@ public class SqlserverQueryProvider extends QueryProvider { } @Override - public String createRawQuerySQL(String table, List fields) { + public String createRawQuerySQL(String table, List fields, Datasource ds) { String[] array = fields.stream().map(f -> { StringBuilder stringBuilder = new StringBuilder(); -// if (f.getDeExtractType() == 4) { // 处理 tinyint -// stringBuilder.append("concat(`").append(f.getOriginName()).append("`,'') AS ").append(f.getDataeaseName()); -// } else { -// stringBuilder.append("`").append(f.getOriginName()).append("` AS ").append(f.getDataeaseName()); -// } stringBuilder.append("\"").append(f.getOriginName()).append("\" AS ").append(f.getDataeaseName()); return stringBuilder.toString(); }).toArray(String[]::new); - return MessageFormat.format("SELECT {0} FROM {1}", StringUtils.join(array, ","), table); + if(ds != null){ + String schema = new Gson().fromJson(ds.getConfiguration(), JdbcDTO.class).getSchema(); + String tableWithSchema = String.format(SqlServerSQLConstants.KEYWORD_TABLE, schema) + "." + String.format(SqlServerSQLConstants.KEYWORD_TABLE, table); + return MessageFormat.format("SELECT {0} FROM {1} ", StringUtils.join(array, ","), tableWithSchema); + }else { + return MessageFormat.format("SELECT {0} FROM {1} ", StringUtils.join(array, ","), table); + } } @Override public String createRawQuerySQLAsTmp(String sql, List fields) { - return createRawQuerySQL(" (" + sqlFix(sql) + ") AS tmp ", fields); + return createRawQuerySQL(" (" + sqlFix(sql) + ") AS tmp ", fields, null); } public String transMysqlFilterTerm(String term) { @@ -773,47 +774,6 @@ public class SqlserverQueryProvider extends QueryProvider { } } - private String transStringToDateFormat(String dateStyle, String datePattern, String originField) { - String split = "-"; - if (StringUtils.equalsIgnoreCase(datePattern, "date_sub")) { - split = "-"; - } else if (StringUtils.equalsIgnoreCase(datePattern, "date_split")) { - split = "/"; - } - switch (dateStyle) { - case "y": - return "CONVERT(varchar(100), datepart(yy, " + "SELECT CONVERT(datetime, " + originField + " ,120)" + "))"; - case "y_M": - if(split.equalsIgnoreCase("-")){ - return "substring( convert(varchar," + "SELECT CONVERT(datetime, " + originField + " ,120)" + ",120),1,7)"; - }else { - return "replace("+ "substring( convert(varchar," + "SELECT CONVERT(datetime, " + originField + " ,120)" + ",120),1,7), '-','/')"; - } - case "y_M_d": - if(split.equalsIgnoreCase("-")){ - return "CONVERT(varchar(100), " + "SELECT CONVERT(datetime, " + originField + " ,120)" + ", 23)"; - }else { - return "CONVERT(varchar(100), " + "SELECT CONVERT(datetime, " + originField + " ,120)" + ", 111)"; - } - case "H_m_s": - return "CONVERT(varchar(100), " + "SELECT CONVERT(datetime, " + originField + " ,120)" + ", 24)"; - case "y_M_d_H_m": - if(split.equalsIgnoreCase("-")){ - return "substring( convert(varchar," + "SELECT CONVERT(datetime, " + originField + " ,120)" + ",120),1,16)"; - }else { - return "replace("+ "substring( convert(varchar," + "SELECT CONVERT(datetime, " + originField + " ,120)" + ",120),1,16), '-','/')"; - } - case "y_M_d_H_m_s": - if(split.equalsIgnoreCase("-")){ - return "convert(varchar," + "SELECT CONVERT(datetime, " + originField + " ,120)" + ",120)"; - }else { - return "replace("+ "convert(varchar," + "SELECT CONVERT(datetime, " + originField + " ,120)" + ",120), '-','/')"; - } - default: - return "convert(varchar," + "SELECT CONVERT(datetime, " + originField + " ,120)" + ",120)"; - } - } - private SQLObj getXFields(ChartViewFieldDTO x, String originField, String fieldAlias) { String fieldName = ""; if (x.getDeExtractType() == DeTypeConstants.DE_TIME) { @@ -912,7 +872,7 @@ public class SqlserverQueryProvider extends QueryProvider { List calcFields = datasetTableFieldMapper.selectByExample(datasetTableFieldExample); for (DatasetTableField ele : calcFields) { originField = originField.replaceAll("\\[" + ele.getId() + "]", - String.format(MySQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), ele.getOriginName())); + String.format(SqlServerSQLConstants.KEYWORD_FIX, tableObj.getTableAlias(), ele.getOriginName())); } return originField; } diff --git a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java index 68fa644ab0..3ab743ceb9 100644 --- a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java +++ b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java @@ -11,19 +11,12 @@ import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.BeanUtils; import io.dataease.commons.utils.CommonBeanFactory; import io.dataease.commons.utils.LogUtil; -import io.dataease.controller.request.chart.ChartExtFilterRequest; -import io.dataease.controller.request.chart.ChartExtRequest; -import io.dataease.controller.request.chart.ChartGroupRequest; -import io.dataease.controller.request.chart.ChartViewRequest; -import io.dataease.controller.request.dataset.DataSetGroupRequest; -import io.dataease.controller.request.dataset.DataSetTableRequest; +import io.dataease.controller.request.chart.*; import io.dataease.datasource.provider.DatasourceProvider; import io.dataease.datasource.provider.ProviderFactory; import io.dataease.datasource.request.DatasourceRequest; import io.dataease.datasource.service.DatasourceService; import io.dataease.dto.chart.*; -import io.dataease.dto.dataset.DataSetGroupDTO; -import io.dataease.dto.dataset.DataSetTableDTO; import io.dataease.dto.dataset.DataSetTableUnionDTO; import io.dataease.dto.dataset.DataTableInfoDTO; import io.dataease.i18n.Translator; @@ -197,6 +190,8 @@ public class ChartViewService { }.getType()); List fieldCustomFilter = new Gson().fromJson(view.getCustomFilter(), new TypeToken>() { }.getType()); + List drill = new Gson().fromJson(view.getDrillFields(), new TypeToken>() { + }.getType()); List customFilter = new ArrayList<>(); for (ChartFieldCustomFilterDTO ele : fieldCustomFilter) { List collect = ele.getFilter().stream().map(f -> { @@ -225,6 +220,8 @@ public class ChartViewService { // 过滤来自仪表板的条件 List extFilterList = new ArrayList<>(); + + //组件过滤条件 if (ObjectUtils.isNotEmpty(requestList.getFilter())) { for (ChartExtFilterRequest request : requestList.getFilter()) { DatasetTableField datasetTableField = dataSetTableFieldsService.get(request.getFieldId()); @@ -241,6 +238,64 @@ public class ChartViewService { } } + //联动过滤条件联动条件全部加上 + if (ObjectUtils.isNotEmpty(requestList.getLinkageFilters())) { + for (ChartExtFilterRequest request : requestList.getLinkageFilters()) { + DatasetTableField datasetTableField = dataSetTableFieldsService.get(request.getFieldId()); + request.setDatasetTableField(datasetTableField); + if (StringUtils.equalsIgnoreCase(datasetTableField.getTableId(), view.getTableId())) { + if (CollectionUtils.isNotEmpty(request.getViewIds())) { + if (request.getViewIds().contains(view.getId())) { + extFilterList.add(request); + } + } else { + extFilterList.add(request); + } + } + } + } + + // 下钻 + List drillFilters = new ArrayList<>(); + boolean isDrill = false; + List drillRequest = requestList.getDrill(); + if (CollectionUtils.isNotEmpty(drillRequest) && (drill.size() > drillRequest.size())) { + for (int i = 0; i < drillRequest.size(); i++) { + ChartDrillRequest request = drillRequest.get(i); + for (ChartDimensionDTO dto : request.getDimensionList()) { + ChartViewFieldDTO chartViewFieldDTO = drill.get(i); + // 将钻取值作为条件传递,将所有钻取字段作为xAxis并加上下一个钻取字段 + if (StringUtils.equalsIgnoreCase(dto.getId(), chartViewFieldDTO.getId())) { + isDrill = true; + DatasetTableField datasetTableField = dataSetTableFieldsService.get(dto.getId()); + ChartViewFieldDTO d = new ChartViewFieldDTO(); + BeanUtils.copyBean(d, datasetTableField); + + ChartExtFilterRequest drillFilter = new ChartExtFilterRequest(); + drillFilter.setFieldId(dto.getId()); + drillFilter.setValue(new ArrayList() {{ + add(dto.getValue()); + }}); + drillFilter.setOperator("in"); + drillFilter.setDatasetTableField(datasetTableField); + extFilterList.add(drillFilter); + + drillFilters.add(drillFilter); + + if (!checkDrillExist(xAxis, extStack, d, view)) { + xAxis.add(d); + } + if (i == drillRequest.size() - 1) { + ChartViewFieldDTO nextDrillField = drill.get(i + 1); + if (!checkDrillExist(xAxis, extStack, nextDrillField, view)) { + xAxis.add(nextDrillField); + } + } + } + } + } + } + // 获取数据集,需校验权限 DatasetTable table = dataSetTableService.get(view.getTableId()); if (ObjectUtils.isEmpty(table)) { @@ -263,11 +318,11 @@ public class ChartViewService { if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType())) { datasourceRequest.setQuery(qp.getSQLSummary(dataTableInfoDTO.getTable(), yAxis, customFilter, extFilterList)); } else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) { - datasourceRequest.setQuery(qp.getSQLStack(dataTableInfoDTO.getTable(), xAxis, yAxis, customFilter, extFilterList, extStack)); + datasourceRequest.setQuery(qp.getSQLStack(dataTableInfoDTO.getTable(), xAxis, yAxis, customFilter, extFilterList, extStack, ds)); } else if (StringUtils.containsIgnoreCase(view.getType(), "scatter")) { - datasourceRequest.setQuery(qp.getSQLScatter(dataTableInfoDTO.getTable(), xAxis, yAxis, customFilter, extFilterList, extBubble)); + datasourceRequest.setQuery(qp.getSQLScatter(dataTableInfoDTO.getTable(), xAxis, yAxis, customFilter, extFilterList, extBubble, ds)); } else { - datasourceRequest.setQuery(qp.getSQL(dataTableInfoDTO.getTable(), xAxis, yAxis, customFilter, extFilterList)); + datasourceRequest.setQuery(qp.getSQL(dataTableInfoDTO.getTable(), xAxis, yAxis, customFilter, extFilterList, ds)); } } else if (StringUtils.equalsIgnoreCase(table.getType(), "sql")) { if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType())) { @@ -316,11 +371,11 @@ public class ChartViewService { if (StringUtils.equalsIgnoreCase("text", view.getType()) || StringUtils.equalsIgnoreCase("gauge", view.getType())) { datasourceRequest.setQuery(qp.getSQLSummary(tableName, yAxis, customFilter, extFilterList)); } else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) { - datasourceRequest.setQuery(qp.getSQLStack(tableName, xAxis, yAxis, customFilter, extFilterList, extStack)); + datasourceRequest.setQuery(qp.getSQLStack(tableName, xAxis, yAxis, customFilter, extFilterList, extStack, ds)); } else if (StringUtils.containsIgnoreCase(view.getType(), "scatter")) { - datasourceRequest.setQuery(qp.getSQLScatter(tableName, xAxis, yAxis, customFilter, extFilterList, extBubble)); + datasourceRequest.setQuery(qp.getSQLScatter(tableName, xAxis, yAxis, customFilter, extFilterList, extBubble, ds)); } else { - datasourceRequest.setQuery(qp.getSQL(tableName, xAxis, yAxis, customFilter, extFilterList)); + datasourceRequest.setQuery(qp.getSQL(tableName, xAxis, yAxis, customFilter, extFilterList, ds)); } /*// 定时抽取使用缓存 Object cache; @@ -339,7 +394,9 @@ public class ChartViewService { data = (List) cache; }*/ // 仪表板有参数不实用缓存 - if (CollectionUtils.isNotEmpty(requestList.getFilter())) { + if (CollectionUtils.isNotEmpty(requestList.getFilter()) + || CollectionUtils.isNotEmpty(requestList.getLinkageFilters()) + || CollectionUtils.isNotEmpty(requestList.getDrill())) { data = datasourceProvider.getData(datasourceRequest); } else { try { @@ -362,16 +419,16 @@ public class ChartViewService { // 图表组件可再扩展 Map mapChart; if (StringUtils.containsIgnoreCase(view.getType(), "stack")) { - mapChart = transStackChartData(xAxis, yAxis, view, data, extStack); + mapChart = transStackChartData(xAxis, yAxis, view, data, extStack, isDrill); } else if (StringUtils.containsIgnoreCase(view.getType(), "scatter")) { - mapChart = transScatterData(xAxis, yAxis, view, data, extBubble); + mapChart = transScatterData(xAxis, yAxis, view, data, extBubble, isDrill); } else if (StringUtils.containsIgnoreCase(view.getType(), "radar")) { - mapChart = transRadarChartData(xAxis, yAxis, view, data); + mapChart = transRadarChartData(xAxis, yAxis, view, data, isDrill); } else if (StringUtils.containsIgnoreCase(view.getType(), "text") || StringUtils.containsIgnoreCase(view.getType(), "gauge")) { - mapChart = transNormalChartData(xAxis, yAxis, view, data); + mapChart = transNormalChartData(xAxis, yAxis, view, data, isDrill); } else { - mapChart = transChartData(xAxis, yAxis, view, data); + mapChart = transChartData(xAxis, yAxis, view, data, isDrill); } // table组件,明细表,也用于导出数据 Map mapTableNormal = transTableNormal(xAxis, yAxis, view, data, extStack); @@ -383,9 +440,30 @@ public class ChartViewService { BeanUtils.copyBean(dto, view); dto.setData(map); dto.setSql(datasourceRequest.getQuery()); + + dto.setDrill(isDrill); + dto.setDrillFilters(drillFilters); return dto; } + private boolean checkDrillExist(List xAxis, List extStack, ChartViewFieldDTO dto, ChartViewWithBLOBs view) { + if (CollectionUtils.isNotEmpty(xAxis)) { + for (ChartViewFieldDTO x : xAxis) { + if (StringUtils.equalsIgnoreCase(x.getId(), dto.getId())) { + return true; + } + } + } + if (StringUtils.containsIgnoreCase(view.getType(), "stack") && CollectionUtils.isNotEmpty(extStack)) { + for (ChartViewFieldDTO x : extStack) { + if (StringUtils.equalsIgnoreCase(x.getId(), dto.getId())) { + return true; + } + } + } + return false; + } + /** * 避免缓存击穿 * 虽然流量不一定能够达到击穿的水平 @@ -423,7 +501,7 @@ public class ChartViewService { } // 基础图形 - private Map transChartData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data) { + private Map transChartData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data, boolean isDrill) { Map map = new HashMap<>(); List x = new ArrayList<>(); @@ -464,11 +542,15 @@ public class ChartViewService { } series.get(j).getData().add(axisChartDataDTO); } - for (int i = 0; i < xAxis.size(); i++) { - if (i == xAxis.size() - 1) { - a.append(d[i]); - } else { - a.append(d[i]).append("\n"); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } } } x.add(a.toString()); @@ -480,7 +562,7 @@ public class ChartViewService { } // 常规图形 - private Map transNormalChartData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data) { + private Map transNormalChartData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data, boolean isDrill) { Map map = new HashMap<>(); List x = new ArrayList<>(); @@ -494,11 +576,15 @@ public class ChartViewService { } for (String[] d : data) { StringBuilder a = new StringBuilder(); - for (int i = 0; i < xAxis.size(); i++) { - if (i == xAxis.size() - 1) { - a.append(d[i]); - } else { - a.append(d[i]).append("\n"); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } } } x.add(a.toString()); @@ -518,7 +604,7 @@ public class ChartViewService { } // radar图 - private Map transRadarChartData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data) { + private Map transRadarChartData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data, boolean isDrill) { Map map = new HashMap<>(); List x = new ArrayList<>(); @@ -532,11 +618,15 @@ public class ChartViewService { } for (String[] d : data) { StringBuilder a = new StringBuilder(); - for (int i = 0; i < xAxis.size(); i++) { - if (i == xAxis.size() - 1) { - a.append(d[i]); - } else { - a.append(d[i]).append("\n"); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } } } x.add(a.toString()); @@ -556,7 +646,7 @@ public class ChartViewService { } // 堆叠图 - private Map transStackChartData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data, List extStack) { + private Map transStackChartData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data, List extStack, boolean isDrill) { Map map = new HashMap<>(); List x = new ArrayList<>(); @@ -570,11 +660,15 @@ public class ChartViewService { // 构建横轴 for (String[] d : data) { StringBuilder a = new StringBuilder(); - for (int i = 0; i < xAxis.size(); i++) { - if (i == xAxis.size() - 1) { - a.append(d[i]); - } else { - a.append(d[i]).append("\n"); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } } } x.add(a.toString()); @@ -681,11 +775,15 @@ public class ChartViewService { } series.get(j).getData().add(axisChartDataDTO); } - for (int i = 0; i < xAxis.size(); i++) { - if (i == xAxis.size() - 1) { - a.append(d[i]); - } else { - a.append(d[i]).append("\n"); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } } } x.add(a.toString()); @@ -698,7 +796,7 @@ public class ChartViewService { } // 散点图 - private Map transScatterData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data, List extBubble) { + private Map transScatterData(List xAxis, List yAxis, ChartViewWithBLOBs view, List data, List extBubble, boolean isDrill) { Map map = new HashMap<>(); List x = new ArrayList<>(); @@ -714,11 +812,15 @@ public class ChartViewService { String[] d = data.get(i1); StringBuilder a = new StringBuilder(); - for (int i = 0; i < xAxis.size(); i++) { - if (i == xAxis.size() - 1) { - a.append(d[i]); - } else { - a.append(d[i]).append("\n"); + if (isDrill) { + a.append(d[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxis.size(); i++) { + if (i == xAxis.size() - 1) { + a.append(d[i]); + } else { + a.append(d[i]).append("\n"); + } } } x.add(a.toString()); diff --git a/backend/src/main/java/io/dataease/service/dataset/ExtractDataService.java b/backend/src/main/java/io/dataease/service/dataset/ExtractDataService.java index 6c90cb0491..c2bb860bb3 100644 --- a/backend/src/main/java/io/dataease/service/dataset/ExtractDataService.java +++ b/backend/src/main/java/io/dataease/service/dataset/ExtractDataService.java @@ -192,7 +192,7 @@ public class ExtractDataService { dropDorisTable(DorisTableUtils.dorisTmpName(DorisTableUtils.dorisName(datasetTableId))); } finally { deleteFile("all_scope", datasetTableId); - deleteFile(new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class).getData()); +// deleteFile(new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class).getData()); } break; @@ -437,28 +437,28 @@ public class ExtractDataService { String Column_Fields = "dataease_uuid varchar(50), `"; for (DatasetTableField datasetTableField : datasetTableFields) { Column_Fields = Column_Fields + datasetTableField.getDataeaseName() + "` "; + Integer size = datasetTableField.getSize() * 3; + if (datasetTableField.getSize() > 65533 || datasetTableField.getSize() * 3 > 65533) { + size = 65533; + } switch (datasetTableField.getDeExtractType()) { case 0: - if (datasetTableField.getSize() > 65533 || datasetTableField.getSize() * 3 > 65533) { - Column_Fields = Column_Fields + "varchar(65533)" + ",`"; - } else { - Column_Fields = Column_Fields + "varchar(lenth)".replace("lenth", String.valueOf(datasetTableField.getSize() * 3)) + ",`"; - } + Column_Fields = Column_Fields + "varchar(lenth)".replace("lenth", String.valueOf(size)) + ",`"; break; case 1: - Column_Fields = Column_Fields + "varchar(lenth)".replace("lenth", String.valueOf(datasetTableField.getSize())) + ",`"; + Column_Fields = Column_Fields + "varchar(lenth)".replace("lenth", String.valueOf(size)) + ",`"; break; case 2: - Column_Fields = Column_Fields + "bigint(lenth)".replace("lenth", String.valueOf(datasetTableField.getSize())) + ",`"; + Column_Fields = Column_Fields + "bigint(lenth)".replace("lenth", String.valueOf(size)) + ",`"; break; case 3: Column_Fields = Column_Fields + "DOUBLE" + ",`"; break; case 4: - Column_Fields = Column_Fields + "TINYINT(lenth)".replace("lenth", String.valueOf(datasetTableField.getSize())) + ",`"; + Column_Fields = Column_Fields + "TINYINT(lenth)".replace("lenth", String.valueOf(size)) + ",`"; break; default: - Column_Fields = Column_Fields + "varchar(lenth)".replace("lenth", String.valueOf(datasetTableField.getSize())) + ",`"; + Column_Fields = Column_Fields + "varchar(lenth)".replace("lenth", String.valueOf(size)) + ",`"; break; } } @@ -735,6 +735,14 @@ public class ExtractDataService { inputStep = inputStep(transMeta, selectSQL); udjcStep = udjc(datasetTableFields, DatasourceTypes.sqlServer); break; + case pg: + PgConfigration pgConfigration = new Gson().fromJson(datasource.getConfiguration(), PgConfigration.class); + dataMeta = new DatabaseMeta("db", "POSTGRESQL", "Native", pgConfigration.getHost(), pgConfigration.getDataBase(), pgConfigration.getPort().toString(), pgConfigration.getUsername(), pgConfigration.getPassword()); + transMeta.addDatabase(dataMeta); + selectSQL = getSelectSQL(extractType, datasetTable, datasource, datasetTableFields, selectSQL); + inputStep = inputStep(transMeta, selectSQL); + udjcStep = udjc(datasetTableFields, DatasourceTypes.pg); + break; case oracle: OracleConfigration oracleConfigration = new Gson().fromJson(datasource.getConfiguration(), OracleConfigration.class); if (oracleConfigration.getConnectionType().equalsIgnoreCase("serviceName")) { @@ -795,7 +803,7 @@ public class ExtractDataService { if (extractType.equalsIgnoreCase("all_scope") && datasetTable.getType().equalsIgnoreCase("db")) { String tableName = new Gson().fromJson(datasetTable.getInfo(), DataTableInfoDTO.class).getTable(); QueryProvider qp = ProviderFactory.getQueryProvider(datasource.getType()); - selectSQL = qp.createRawQuerySQL(tableName, datasetTableFields); + selectSQL = qp.createRawQuerySQL(tableName, datasetTableFields, datasource); } if (extractType.equalsIgnoreCase("all_scope") && datasetTable.getType().equalsIgnoreCase("sql")) { @@ -879,12 +887,18 @@ public class ExtractDataService { outputFields[datasetTableFields.size()] = textFileField; textFileOutputMeta.setOutputFields(outputFields); - }else if (datasource.getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name())){ + }else if (datasource.getType().equalsIgnoreCase(DatasourceTypes.sqlServer.name()) || datasource.getType().equalsIgnoreCase(DatasourceTypes.pg.name())){ TextFileField[] outputFields = new TextFileField[datasetTableFields.size() + 1]; for(int i=0;i< datasetTableFields.size();i++){ TextFileField textFileField = new TextFileField(); textFileField.setName(datasetTableFields.get(i).getDataeaseName()); - textFileField.setType("String"); + if (datasetTableFields.get(i).getDeExtractType() == 1) { + textFileField.setType("String"); + textFileField.setFormat("yyyy-MM-dd HH:mm:ss"); + } else { + textFileField.setType("String"); + } + outputFields[i] = textFileField; } TextFileField textFileField = new TextFileField(); @@ -936,7 +950,6 @@ public class ExtractDataService { } tmp_code = tmp_code.replace("handleBinaryType", handleBinaryTypeCode); - UserDefinedJavaClassDef userDefinedJavaClassDef = new UserDefinedJavaClassDef(UserDefinedJavaClassDef.ClassType.TRANSFORM_CLASS, "Processor", tmp_code); userDefinedJavaClassDef.setActive(true); @@ -1019,13 +1032,13 @@ public class ExtractDataService { } } - private static String handleBinaryType = " \t\tif(\"FEILD\".equalsIgnoreCase(filed)){\n" + + private final static String handleBinaryType = " \t\tif(\"FEILD\".equalsIgnoreCase(filed)){\n" + " get(Fields.Out, filed).setValue(r, \"\");\n" + " get(Fields.Out, filed).getValueMeta().setType(2);\n" + " \t}"; - private static String alterColumnTypeCode = " if(\"FILED\".equalsIgnoreCase(filed)){\n" + + private final static String alterColumnTypeCode = " if(\"FILED\".equalsIgnoreCase(filed)){\n" + "\t if(tmp != null && tmp.equalsIgnoreCase(\"Y\")){\n" + " get(Fields.Out, filed).setValue(r, 1);\n" + " get(Fields.Out, filed).getValueMeta().setType(2);\n" + @@ -1035,7 +1048,7 @@ public class ExtractDataService { " }\n" + " }\n"; - private static String handleExcelIntColumn = " \t\tif(tmp != null && tmp.endsWith(\".0\")){\n" + + private final static String handleExcelIntColumn = " \t\tif(tmp != null && tmp.endsWith(\".0\")){\n" + " try {\n" + " Long.valueOf(tmp.substring(0, tmp.length()-2));\n" + " get(Fields.Out, filed).setValue(r, tmp.substring(0, tmp.length()-2));\n" + @@ -1043,14 +1056,14 @@ public class ExtractDataService { " }catch (Exception e){}\n" + " }"; - private static String handleWraps = " if(tmp != null && ( tmp.contains(\"\\r\") || tmp.contains(\"\\n\"))){\n" + + private final static String handleWraps = " if(tmp != null && ( tmp.contains(\"\\r\") || tmp.contains(\"\\n\"))){\n" + "\t\t\ttmp = tmp.trim();\n" + " tmp = tmp.replaceAll(\"\\r\",\" \");\n" + " tmp = tmp.replaceAll(\"\\n\",\" \");\n" + " get(Fields.Out, filed).setValue(r, tmp);\n" + " } "; - private static String code = "import org.pentaho.di.core.row.ValueMetaInterface;\n" + + private final static String code = "import org.pentaho.di.core.row.ValueMetaInterface;\n" + "import java.util.List;\n" + "import java.io.File;\n" + "import java.security.MessageDigest;\n" + diff --git a/backend/src/main/java/io/dataease/service/panel/PanelViewLinkageService.java b/backend/src/main/java/io/dataease/service/panel/PanelViewLinkageService.java index 792ada85de..20447092a0 100644 --- a/backend/src/main/java/io/dataease/service/panel/PanelViewLinkageService.java +++ b/backend/src/main/java/io/dataease/service/panel/PanelViewLinkageService.java @@ -8,6 +8,7 @@ import io.dataease.base.mapper.PanelViewLinkageMapper; import io.dataease.base.mapper.ext.ExtPanelViewLinkageMapper; import io.dataease.commons.utils.AuthUtils; import io.dataease.controller.request.panel.PanelLinkageRequest; +import io.dataease.dto.LinkageInfoDTO; import io.dataease.dto.PanelViewLinkageDTO; import io.dataease.dto.PanelViewLinkageFieldDTO; import org.apache.commons.collections4.CollectionUtils; @@ -89,19 +90,12 @@ public class PanelViewLinkageService { }); } - - - - } + } - - - - - - - + public Map> getPanelAllLinkageInfo(String panelId) { + List info = extPanelViewLinkageMapper.getPanelAllLinkageInfo(panelId); + return Optional.ofNullable(info).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(LinkageInfoDTO::getSourceInfo,LinkageInfoDTO::getTargetInfoList)); } } diff --git a/backend/src/main/java/io/dataease/service/sys/SysRoleService.java b/backend/src/main/java/io/dataease/service/sys/SysRoleService.java index a27649b558..558c0b7f96 100644 --- a/backend/src/main/java/io/dataease/service/sys/SysRoleService.java +++ b/backend/src/main/java/io/dataease/service/sys/SysRoleService.java @@ -1,38 +1,38 @@ package io.dataease.service.sys; -import io.dataease.base.domain.SysRole; +/*import io.dataease.base.domain.SysRole; import io.dataease.base.domain.SysUsersRolesExample; import io.dataease.base.mapper.SysRoleMapper; -import io.dataease.base.mapper.SysUsersRolesMapper; +import io.dataease.base.mapper.SysUsersRolesMapper;*/ import io.dataease.base.mapper.ext.ExtSysRoleMapper; -import io.dataease.controller.sys.base.BaseGridRequest; -import io.dataease.controller.sys.request.RoleMenusRequest; +/*import io.dataease.controller.sys.base.BaseGridRequest; +import io.dataease.controller.sys.request.RoleMenusRequest;*/ import io.dataease.controller.sys.response.RoleUserItem; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; +/*import org.springframework.transaction.annotation.Transactional;*/ import javax.annotation.Resource; -import java.util.HashMap; +/*import java.util.HashMap;*/ import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; +/*import java.util.Map; +import java.util.stream.Collectors;*/ @Service public class SysRoleService { - @Resource - private SysRoleMapper mapper; + /*@Resource + private SysRoleMapper mapper;*/ @Resource private ExtSysRoleMapper extSysRoleMapper; - @Resource - private SysUsersRolesMapper sysUsersRolesMapper; + /*@Resource + private SysUsersRolesMapper sysUsersRolesMapper;*/ - public int add(SysRole role){ + /*public int add(SysRole role){ Long now = System.currentTimeMillis(); role.setCreateTime(now); role.setUpdateTime(now); @@ -77,7 +77,7 @@ public class SysRoleService { return map; }).collect(Collectors.toList()); return extSysRoleMapper.batchInsertRoleMenu(maps); - } + }*/ public List allRoles(){ return extSysRoleMapper.queryAll(); diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 14368c84d1..d4f4111a23 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -28,7 +28,7 @@ knife4j.enable=true knife4j.setting.enableFooter=false knife4j.setting.enableFooterCustom=false knife4j.setting.footerCustomContent=fit2cloud 1.0-b9 -knife4j.setting.enableSwaggerModels=false +#knife4j.setting.enableSwaggerModels=false knife4j.setting.enableDocumentManage=false knife4j.setting.enableSearch=false knife4j.setting.enableOpenApi=false diff --git a/frontend/public/nolic.html b/frontend/public/nolic.html new file mode 100644 index 0000000000..89f3ecbc52 --- /dev/null +++ b/frontend/public/nolic.html @@ -0,0 +1,13 @@ + + + + + + + + DataEase + + +
+ + diff --git a/frontend/src/api/panel/linkage.js b/frontend/src/api/panel/linkage.js index 4a0f0ecc4a..6b0bd72fa6 100644 --- a/frontend/src/api/panel/linkage.js +++ b/frontend/src/api/panel/linkage.js @@ -18,3 +18,9 @@ export function saveLinkage(requestInfo) { }) } +export function getPanelAllLinkageInfo(panelId) { + return request({ + url: '/linkage/getPanelAllLinkageInfo/' + panelId, + method: 'get' + }) +} diff --git a/frontend/src/api/system/dept.js b/frontend/src/api/system/dept.js index a371ee9998..b35bb78e67 100644 --- a/frontend/src/api/system/dept.js +++ b/frontend/src/api/system/dept.js @@ -17,29 +17,29 @@ export function loadTable(data) { }) } -export function addDept(data) { - return request({ - url: '/api/dept/create', - method: 'post', - data - }) -} +// export function addDept(data) { +// return request({ +// url: '/api/dept/create', +// method: 'post', +// data +// }) +// } -export function delDept(ids) { - return request({ - url: '/api/dept/delete', - method: 'post', - data: ids - }) -} +// export function delDept(ids) { +// return request({ +// url: '/api/dept/delete', +// method: 'post', +// data: ids +// }) +// } -export function editDept(data) { - return request({ - url: '/api/dept/update', - method: 'post', - data - }) -} +// export function editDept(data) { +// return request({ +// url: '/api/dept/update', +// method: 'post', +// data +// }) +// } export function treeByDeptId(deptId) { return request({ @@ -48,4 +48,4 @@ export function treeByDeptId(deptId) { }) } -export default { addDept, delDept, editDept, getDeptTree, loadTable, treeByDeptId } +// export default { addDept, delDept, editDept, getDeptTree, loadTable, treeByDeptId } diff --git a/frontend/src/api/system/role.js b/frontend/src/api/system/role.js index 07be60da4e..dd7326f889 100644 --- a/frontend/src/api/system/role.js +++ b/frontend/src/api/system/role.js @@ -1,57 +1,57 @@ -import request from '@/utils/request' +// import request from '@/utils/request' -export function allRoles() { - return request({ - url: '/api/role/all', - method: 'post', - loading: true - }) -} +// export function allRoles() { +// return request({ +// url: '/api/user/all', +// method: 'post', +// loading: true +// }) +// } -export function roleGrid(pageIndex, pageSize, data) { - return request({ - url: '/api/role/roleGrid/' + pageIndex + '/' + pageSize, - method: 'post', - data, - loading: true - }) -} +// export function roleGrid(pageIndex, pageSize, data) { +// return request({ +// url: '/api/role/roleGrid/' + pageIndex + '/' + pageSize, +// method: 'post', +// data, +// loading: true +// }) +// } -export function delRole(pid) { - return request({ - url: '/api/role/delete/' + pid, - method: 'post' - }) -} +// export function delRole(pid) { +// return request({ +// url: '/api/role/delete/' + pid, +// method: 'post' +// }) +// } -export function addRole(data) { - return request({ - url: '/api/role/create', - method: 'post', - data - }) -} +// export function addRole(data) { +// return request({ +// url: '/api/role/create', +// method: 'post', +// data +// }) +// } -export function editRole(data) { - return request({ - url: '/api/role/update', - method: 'post', - data - }) -} +// export function editRole(data) { +// return request({ +// url: '/api/role/update', +// method: 'post', +// data +// }) +// } -export function addRoleMenus(data) { - return request({ - url: '/api/role/saveRolesMenus', - method: 'post', - data - }) -} +// export function addRoleMenus(data) { +// return request({ +// url: '/api/role/saveRolesMenus', +// method: 'post', +// data +// }) +// } -export function menuIds(roleId) { - return request({ - url: '/api/role/menuIds/' + roleId, - method: 'post' - }) -} -export default { addRole, editRole, delRole, roleGrid, allRoles, addRoleMenus, menuIds } +// export function menuIds(roleId) { +// return request({ +// url: '/api/role/menuIds/' + roleId, +// method: 'post' +// }) +// } +// export default { addRole, editRole, delRole, roleGrid, allRoles, addRoleMenus, menuIds } diff --git a/frontend/src/api/system/user.js b/frontend/src/api/system/user.js index fc23d2b260..f3db990e04 100644 --- a/frontend/src/api/system/user.js +++ b/frontend/src/api/system/user.js @@ -81,4 +81,12 @@ export const updatePersonPwd = (data) => { }) } -export default { editPassword, delUser, editUser, addUser, userLists, editStatus, persionInfo, updatePerson, updatePersonPwd } +export const allRoles = () => { + return request({ + url: '/api/user/all', + method: 'post', + loading: true + }) +} + +export default { editPassword, delUser, editUser, addUser, userLists, editStatus, persionInfo, updatePerson, updatePersonPwd, allRoles } diff --git a/frontend/src/components/canvas/components/Editor/CanvasOptBar.vue b/frontend/src/components/canvas/components/Editor/CanvasOptBar.vue new file mode 100644 index 0000000000..c927bbcf51 --- /dev/null +++ b/frontend/src/components/canvas/components/Editor/CanvasOptBar.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue b/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue index 4b6da3a6ea..88216e9e1a 100644 --- a/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue +++ b/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue @@ -102,7 +102,6 @@ export default { }) }, elementMouseDown(e) { - debugger // private 设置当前组件数据及状态 this.$store.commit('setClickComponentStatus', true) if (this.config.component !== 'v-text' && this.config.component !== 'rect-shape' && this.config.component !== 'de-input-search' && this.config.component !== 'de-number-range') { diff --git a/frontend/src/components/canvas/components/Editor/Preview.vue b/frontend/src/components/canvas/components/Editor/Preview.vue index 1fbc589005..d40a4ae3ed 100644 --- a/frontend/src/components/canvas/components/Editor/Preview.vue +++ b/frontend/src/components/canvas/components/Editor/Preview.vue @@ -3,6 +3,7 @@ {{ $t('panel.panelNull') }} + +
+
+ + TEST + + {{ $t('panel.copy') }} + {{ $t('panel.delete') }} + {{ $t('panel.topComponent') }} + {{ $t('panel.bottomComponent') }} + {{ $t('panel.upComponent') }} + {{ $t('panel.downComponent') }} + 联动设置 + + +
+
+ + + + + diff --git a/frontend/src/components/canvas/components/Editor/ViewTrackBar.vue b/frontend/src/components/canvas/components/Editor/ViewTrackBar.vue new file mode 100644 index 0000000000..998e339b02 --- /dev/null +++ b/frontend/src/components/canvas/components/Editor/ViewTrackBar.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/frontend/src/components/canvas/components/Editor/index.vue b/frontend/src/components/canvas/components/Editor/index.vue index 46412a47ad..f988791ad4 100644 --- a/frontend/src/components/canvas/components/Editor/index.vue +++ b/frontend/src/components/canvas/components/Editor/index.vue @@ -9,6 +9,9 @@ > + + + { + // 刷新联动信息 + getPanelAllLinkageInfo(this.$store.state.panel.panelInfo.id).then(rsp => { + this.$store.commit('setNowPanelTrackInfo', rsp.data) + }) this.cancelLinkageSettingStatus() }) }, diff --git a/frontend/src/components/canvas/custom-component/UserView.vue b/frontend/src/components/canvas/custom-component/UserView.vue index 00cf67d92c..f0ef6e4f13 100644 --- a/frontend/src/components/canvas/custom-component/UserView.vue +++ b/frontend/src/components/canvas/custom-component/UserView.vue @@ -16,9 +16,12 @@ {{ $t('chart.chart_error_tips') }} - + +
+ +
@@ -37,9 +40,11 @@ import { BASE_CHART_STRING } from '@/views/chart/chart/chart' import eventBus from '@/components/canvas/utils/eventBus' import { deepCopy } from '@/components/canvas/utils/utils' import { getToken, getLinkToken } from '@/utils/auth' +import DrillPath from '@/views/chart/view/DrillPath' + export default { name: 'UserView', - components: { ChartComponent, TableNormal, LabelNormal }, + components: { ChartComponent, TableNormal, LabelNormal, DrillPath }, props: { element: { type: Object, @@ -77,13 +82,18 @@ export default { refId: null, chart: BASE_CHART_STRING, requestStatus: 'waiting', - message: null + message: null, + drillClickDimensionList: [], + drillFilters: [], + drillFields: [] } }, computed: { filter() { const filter = {} filter.filter = this.element.filters + filter.linkageFilters = this.element.linkageFilters + filter.drill = this.drillClickDimensionList return filter }, filters() { @@ -91,8 +101,30 @@ export default { if (!this.element.filters) return [] return JSON.parse(JSON.stringify(this.element.filters)) }, + + linkageFilters() { + // 必要 勿删勿该 watch数组,哪怕发生变化 oldValue等于newValue ,深拷贝解决 + if (!this.element.linkageFilters) return [] + console.log('linkageFilters:' + JSON.stringify(this.element.linkageFilters)) + return JSON.parse(JSON.stringify(this.element.linkageFilters)) + }, + trackMenu() { + const trackMenuInfo = [] + let linkageCount = 0 + this.chart.data.fields && this.chart.data.fields.forEach(item => { + const sourceInfo = this.chart.id + '#' + item.id + if (this.nowPanelTrackInfo[sourceInfo]) { + linkageCount++ + } + }) + linkageCount && trackMenuInfo.push('linkage') + this.drillFields.length && trackMenuInfo.push('drill') + console.log('trackMenuInfo' + JSON.stringify(trackMenuInfo)) + return trackMenuInfo + }, ...mapState([ - 'canvasStyleData' + 'canvasStyleData', + 'nowPanelTrackInfo' ]) }, @@ -101,6 +133,13 @@ export default { // this.getData(this.element.propValue.viewId) isChange(val1, val2) && this.getData(this.element.propValue.viewId) }, + linkageFilters: { + handler(newVal, oldVal) { + debugger + isChange(newVal, oldVal) && this.getData(this.element.propValue.viewId) + }, + deep: true + }, // deep监听panel 如果改变 提交到 store canvasStyleData: { handler(newVal, oldVla) { @@ -176,6 +215,13 @@ export default { // 将视图传入echart组件 if (response.success) { this.chart = response.data + this.chart.drillFields = this.chart.drillFields ? JSON.parse(this.chart.drillFields) : [] + debugger + if (!response.data.drill) { + this.drillClickDimensionList.splice(this.drillClickDimensionList.length - 1, 1) + } + this.drillFilters = JSON.parse(JSON.stringify(response.data.drillFilters)) + this.drillFields = JSON.parse(JSON.stringify(response.data.drillFields)) this.requestStatus = 'merging' this.mergeStyle() this.requestStatus = 'success' @@ -210,6 +256,22 @@ export default { tableChart.customAttr = JSON.stringify(tableChart.customAttr) tableChart.customStyle = JSON.stringify(tableChart.customStyle) eventBus.$emit('openChartDetailsDialog', { chart: this.chart, tableChart: tableChart }) + }, + + chartClick(param) { + debugger + if (this.drillClickDimensionList.length < this.chart.drillFields.length - 1) { + this.drillClickDimensionList.push({ dimensionList: param.data.dimensionList }) + this.getData(this.element.propValue.viewId) + } + }, + + resetDrill() { + this.drillClickDimensionList = [] + }, + drillJump(index) { + this.drillClickDimensionList = this.drillClickDimensionList.slice(0, index) + this.getData(this.element.propValue.viewId) } } } diff --git a/frontend/src/components/canvas/store/copy.js b/frontend/src/components/canvas/store/copy.js index ef4eb98351..e7daeb98cd 100644 --- a/frontend/src/components/canvas/store/copy.js +++ b/frontend/src/components/canvas/store/copy.js @@ -41,7 +41,6 @@ export default { data.id = generateID() // 如果是用户视图 测先进行底层复制 - debugger if (data.type === 'view') { chartCopy(data.propValue.viewId).then(res => { const newView = deepCopy(data) diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index 8cf635faf5..9328202b86 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -837,7 +837,10 @@ export default { drill: 'Drill', drag_block_treemap_label: 'Color Label', drag_block_treemap_size: 'Color Size', - bubble_symbol: 'Shape' + bubble_symbol: 'Shape', + gap_width: 'Gap Width', + width: 'Width', + height: 'Height' }, dataset: { sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default', @@ -1176,7 +1179,9 @@ export default { panel_save_tips: 'Do you want to save the changes you made to.', panel_save_warn_tips: "Your changes will be lost if you don't save them!", do_not_save: "Don't Save", - save_and_close: 'Save' + save_and_close: 'Save', + drill: 'drill', + linkage: 'linkage' }, plugin: { local_install: 'Local installation', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index b0a38fd1b0..2d8dcfbea3 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -837,7 +837,10 @@ export default { drill: '鉆取', drag_block_treemap_label: '色塊標簽', drag_block_treemap_size: '色塊大小', - bubble_symbol: '圖形' + bubble_symbol: '圖形', + gap_width: '間隔', + width: '寬度', + height: '高度' }, dataset: { sheet_warn: '有多個sheet頁面,默認抽取第一個', @@ -1176,7 +1179,9 @@ export default { panel_save_tips: '仪表板已变动,是否保存?', panel_save_warn_tips: '如果未保存,你对仪表板做的变更将会丢失!', do_not_save: '不保存', - save: '保存' + save: '保存', + drill: '下钻', + linkage: '联动' }, plugin: { local_install: '本地安裝', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index ba630a4bd8..4e4c656373 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -837,7 +837,10 @@ export default { drill: '钻取', drag_block_treemap_label: '色块标签', drag_block_treemap_size: '色块大小', - bubble_symbol: '图形' + bubble_symbol: '图形', + gap_width: '间隔', + width: '宽度', + height: '高度' }, dataset: { sheet_warn: '有多个 Sheet 页,默认抽取第一个', @@ -1178,7 +1181,9 @@ export default { panel_save_tips: '仪表板已变动,是否保存?', panel_save_warn_tips: '如果未保存,你对仪表板做的变更将会丢失!', do_not_save: '不保存', - save: '保存' + save: '保存', + drill: '下钻', + linkage: '联动' }, plugin: { local_install: '本地安装', diff --git a/frontend/src/nolic/Nolic.vue b/frontend/src/nolic/Nolic.vue new file mode 100644 index 0000000000..3824ab98da --- /dev/null +++ b/frontend/src/nolic/Nolic.vue @@ -0,0 +1,16 @@ + + + diff --git a/frontend/src/nolic/nolic-router.js b/frontend/src/nolic/nolic-router.js new file mode 100644 index 0000000000..4730048019 --- /dev/null +++ b/frontend/src/nolic/nolic-router.js @@ -0,0 +1,17 @@ +import Vue from 'vue' +import Router from 'vue-router' + +Vue.use(Router) + +export default new Router({ + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/nolic/index.vue'), + meta: { + title: '首页' + } + } + ] +}) diff --git a/frontend/src/nolic/nolic.js b/frontend/src/nolic/nolic.js new file mode 100644 index 0000000000..f3110de5ae --- /dev/null +++ b/frontend/src/nolic/nolic.js @@ -0,0 +1,26 @@ +import Vue from 'vue' +import Nolic from './Nolic.vue' +import router from './nolic-router' +import store from '../store' +import '@/styles/index.scss' // global css +import i18n from '../lang' // internationalization +import ElementUI from 'element-ui' +import '@/components/canvas/custom-component' // 注册自定义组件 +import widgets from '@/components/widget' +import * as echarts from 'echarts' +import UmyUi from 'umy-ui' + +Vue.use(UmyUi) +Vue.prototype.$echarts = echarts +Vue.config.productionTip = false +Vue.use(widgets) +Vue.use(ElementUI, { + + i18n: (key, value) => i18n.t(key, value) +}) +new Vue({ + router, + store, + i18n, + render: h => h(Nolic) +}).$mount('#nolic') diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 3f299683e8..43facb6fe1 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -21,7 +21,9 @@ import event from '@/components/canvas/store/event' import layer from '@/components/canvas/store/layer' import snapshot from '@/components/canvas/store/snapshot' import lock from '@/components/canvas/store/lock' -import { valueValid, formatCondition } from '@/utils/conditionUtil' +import { valueValid, formatCondition, formatLinkageCondition } from '@/utils/conditionUtil' +import { Condition } from '@/components/widget/bean/Condition' + import { DEFAULT_COMMON_CANVAS_STYLE_STRING } from '@/views/panel/panel' @@ -54,7 +56,9 @@ const data = { // 当前设置联动的组件 curLinkageView: null, // 和当前组件联动的目标组件 - targetLinkageInfo: [] + targetLinkageInfo: [], + // 当前仪表板联动 下钻 上卷等信息 + nowPanelTrackInfo: {} }, mutations: { ...animation.mutations, @@ -154,6 +158,46 @@ const data = { state.componentData[index] = element } }, + + // 添加联动 下钻 等过滤组件 + addViewTrackFilter(state, data) { + const viewId = data.viewId + const trackInfo = state.nowPanelTrackInfo + for (let index = 0; index < state.componentData.length; index++) { + const element = state.componentData[index] + if (!element.type || element.type !== 'view') continue + const currentFilters = element.linkageFilters || [] // 当前联动filter + + data.dimensionList.forEach(dimension => { + const sourceInfo = viewId + '#' + dimension.id + // 获取所有目标联动信息 + const targetInfoList = trackInfo[sourceInfo] || [] + targetInfoList.forEach(targetInfo => { + const targetInfoArray = targetInfo.split('#') + const targetViewId = targetInfoArray[0] // 目标视图 + if (element.propValue.viewId === targetViewId) { // 如果目标视图 和 当前循环组件id相等 则进行条件增减 + const targetFieldId = targetInfoArray[1] // 目标视图列ID + const condition = new Condition('', targetFieldId, 'eq', [dimension.value], [targetViewId]) + + let j = currentFilters.length + while (j--) { + const filter = currentFilters[j] + // 兼容性准备 viewIds 只会存放一个值 + if (targetFieldId === filter.fieldId && filter.viewIds.includes(targetViewId)) { + currentFilters.splice(j, 1) + } + } + // 不存在该条件 且 条件有效 直接保存该条件 + // !filterExist && vValid && currentFilters.push(condition) + currentFilters.push(condition) + } + }) + }) + + element.linkageFilters = currentFilters + state.componentData[index] = element + } + }, setComponentWithId(state, component) { for (let index = 0; index < state.componentData.length; index++) { const element = state.componentData[index] @@ -189,6 +233,17 @@ const data = { state.linkageSettingStatus = false state.curLinkageView = null state.targetLinkageInfo = [] + }, + setNowPanelTrackInfo(state, trackInfo) { + state.nowPanelTrackInfo = trackInfo + }, + clearPanelLinkageInfo(state) { + state.componentData.forEach(item => { + if (item.linkageFilters && item.linkageFilters.length > 0) { + item.linkageFilters.splice(0, item.linkageFilters.length) + } + }) + state.styleChangeTimes++ } }, modules: { diff --git a/frontend/src/styles/deicon/demo.css b/frontend/src/styles/deicon/demo.css index b7af3aa35d..a67054a0a0 100644 --- a/frontend/src/styles/deicon/demo.css +++ b/frontend/src/styles/deicon/demo.css @@ -3,9 +3,9 @@ font-family: "iconfont logo"; src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), - url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), - url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), - url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); } .logo { @@ -215,35 +215,35 @@ margin: 1em 0; } -.markdown > p, -.markdown > blockquote, -.markdown > .highlight, -.markdown > ol, -.markdown > ul { +.markdown>p, +.markdown>blockquote, +.markdown>.highlight, +.markdown>ol, +.markdown>ul { width: 80%; } -.markdown ul > li { +.markdown ul>li { list-style: circle; } -.markdown > ul li, -.markdown blockquote ul > li { +.markdown>ul li, +.markdown blockquote ul>li { margin-left: 20px; padding-left: 4px; } -.markdown > ul li p, -.markdown > ol li p { +.markdown>ul li p, +.markdown>ol li p { margin: 0.6em 0; } -.markdown ol > li { +.markdown ol>li { list-style: decimal; } -.markdown > ol li, -.markdown blockquote ol > li { +.markdown>ol li, +.markdown blockquote ol>li { margin-left: 20px; padding-left: 4px; } @@ -260,7 +260,7 @@ font-weight: 600; } -.markdown > table { +.markdown>table { border-collapse: collapse; border-spacing: 0px; empty-cells: show; @@ -269,20 +269,20 @@ margin-bottom: 24px; } -.markdown > table th { +.markdown>table th { white-space: nowrap; color: #333; font-weight: 600; } -.markdown > table th, -.markdown > table td { +.markdown>table th, +.markdown>table td { border: 1px solid #e9e9e9; padding: 8px 16px; text-align: left; } -.markdown > table th { +.markdown>table th { background: #F7F7F7; } @@ -318,8 +318,8 @@ display: inline-block; } -.markdown > br, -.markdown > p > br { +.markdown>br, +.markdown>p>br { clear: both; } @@ -453,13 +453,13 @@ pre[class*="language-"] { overflow: auto; } -:not(pre) > code[class*="language-"], +:not(pre)>code[class*="language-"], pre[class*="language-"] { background: #f5f2f0; } /* Inline code */ -:not(pre) > code[class*="language-"] { +:not(pre)>code[class*="language-"] { padding: .1em; border-radius: .3em; white-space: normal; diff --git a/frontend/src/styles/deicon/demo_index.html b/frontend/src/styles/deicon/demo_index.html index e01657bfe5..e997334f0c 100644 --- a/frontend/src/styles/deicon/demo_index.html +++ b/frontend/src/styles/deicon/demo_index.html @@ -54,6 +54,48 @@
    +
  • + +
    线性图标-取消下钻
    +
    &#xe973;
    +
  • + +
  • + +
    线性图标-取消下钻
    +
    &#xe6ed;
    +
  • + +
  • + +
    联动
    +
    &#xe6f7;
    +
  • + +
  • + +
    下钻
    +
    &#xe613;
    +
  • + +
  • + +
    上钻
    +
    &#xe61f;
    +
  • + +
  • + +
    取消联动
    +
    &#xe637;
    +
  • + +
  • + +
    edit-2
    +
    &#xe604;
    +
  • +
  • edit-2
    @@ -318,9 +360,9 @@
    @font-face {
       font-family: 'iconfont';
    -  src: url('iconfont.woff2?t=1627282547459') format('woff2'),
    -       url('iconfont.woff?t=1627282547459') format('woff'),
    -       url('iconfont.ttf?t=1627282547459') format('truetype');
    +  src: url('iconfont.woff2?t=1628652979833') format('woff2'),
    +       url('iconfont.woff?t=1628652979833') format('woff'),
    +       url('iconfont.ttf?t=1628652979833') format('truetype');
     }
     

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

    @@ -346,6 +388,69 @@
      +
    • + +
      + 线性图标-取消下钻 +
      +
      .icon-quxiaoshangzuan +
      +
    • + +
    • + +
      + 线性图标-取消下钻 +
      +
      .icon-quxiaoxiazuan +
      +
    • + +
    • + +
      + 联动 +
      +
      .icon-linkage +
      +
    • + +
    • + +
      + 下钻 +
      +
      .icon-xiazuan +
      +
    • + +
    • + +
      + 上钻 +
      +
      .icon-shangzuan +
      +
    • + +
    • + +
      + 取消联动 +
      +
      .icon-quxiaoliandong +
      +
    • + +
    • + +
      + edit-2 +
      +
      .icon-edit-outline +
      +
    • +
    • @@ -742,6 +847,62 @@
        +
      • + +
        线性图标-取消下钻
        +
        #icon-quxiaoshangzuan
        +
      • + +
      • + +
        线性图标-取消下钻
        +
        #icon-quxiaoxiazuan
        +
      • + +
      • + +
        联动
        +
        #icon-linkage
        +
      • + +
      • + +
        下钻
        +
        #icon-xiazuan
        +
      • + +
      • + +
        上钻
        +
        #icon-shangzuan
        +
      • + +
      • + +
        取消联动
        +
        #icon-quxiaoliandong
        +
      • + +
      • + +
        edit-2
        +
        #icon-edit-outline
        +
      • +
      • +
        @@ -18,9 +19,11 @@ import { baseTreemapOption } from '../chart/treemap/treemap' // import eventBus from '@/components/canvas/utils/eventBus' import { uuid } from 'vue-uuid' import { geoJson } from '@/api/map/map' +import ViewTrackBar from '@/components/canvas/components/Editor/ViewTrackBar' export default { name: 'ChartComponent', + components: { ViewTrackBar }, props: { chart: { type: Object, @@ -32,13 +35,33 @@ export default { default: function() { return {} } + }, + trackMenu: { + type: Array, + required: false, + default: function() { + return ['drill'] + } } }, data() { return { myChart: {}, chartId: uuid.v1(), - currentGeoJson: null + currentGeoJson: null, + showTrackBar: true, + trackBarStyle: { + position: 'absolute', + left: '0px', + top: '0px' + }, + pointParam: null + } + }, + + computed: { + trackBarStyleTime() { + return this.trackBarStyle } }, watch: { @@ -62,6 +85,7 @@ export default { preDraw() { // 基于准备好的dom,初始化echarts实例 // 渲染echart等待dom加载完毕,渲染之前先尝试销毁具有相同id的echart 放置多次切换仪表板有重复id情况 + const that = this new Promise((resolve) => { resolve() }).then(() => { // 此dom为echarts图标展示dom this.myChart = this.$echarts.getInstanceByDom(document.getElementById(this.chartId)) @@ -69,6 +93,18 @@ export default { this.myChart = this.$echarts.init(document.getElementById(this.chartId)) } this.drawEcharts() + + this.myChart.off('click') + this.myChart.on('click', function(param) { + that.pointParam = param + if (that.trackMenu.length < 2) { // 只有一个事件直接调用 + that.trackClick(that.trackMenu[0]) + } else { // 视图关联多个事件 + that.trackBarStyle.left = param.event.offsetX + 'px' + that.trackBarStyle.top = (param.event.offsetY - 15) + 'px' + that.$refs.viewTrack.trackButtonClick() + } + }) }) }, drawEcharts() { @@ -136,7 +172,7 @@ export default { }, initMapChart(geoJson, chart) { // this.$echarts.registerMap('HK', geoJson) - this.$echarts.getMap('HK') || this.$echarts.registerMap('HK', geoJson) + this.$echarts.getMap('MAP') || this.$echarts.registerMap('MAP', geoJson) const base_json = JSON.parse(JSON.stringify(BASE_MAP)) const chart_option = baseMapOption(base_json, chart) this.myEcharts(chart_option) @@ -153,6 +189,23 @@ export default { // 指定图表的配置项和数据 const chart = this.myChart chart.resize() + }, + trackClick(trackAction) { + const linkageParam = { + viewId: this.chart.id, + dimensionList: this.pointParam.data.dimensionList, + quotaList: this.pointParam.data.quotaList + } + switch (trackAction) { + case 'drill': + this.$emit('onChartClick', this.pointParam) + break + case 'linkage': + this.$store.commit('addViewTrackFilter', linkageParam) + break + default: + break + } } } } diff --git a/frontend/src/views/chart/components/shape-attr/SizeSelector.vue b/frontend/src/views/chart/components/shape-attr/SizeSelector.vue index 906a1eb79f..0295369719 100644 --- a/frontend/src/views/chart/components/shape-attr/SizeSelector.vue +++ b/frontend/src/views/chart/components/shape-attr/SizeSelector.vue @@ -151,6 +151,15 @@ + + + + + + + + + @@ -353,6 +362,8 @@ export default { } if (customAttr.size) { this.sizeForm = customAttr.size + this.sizeForm.treemapWidth = this.sizeForm.treemapWidth ? this.sizeForm.treemapWidth : 80 + this.sizeForm.treemapHeight = this.sizeForm.treemapHeight ? this.sizeForm.treemapHeight : 80 } } }, diff --git a/frontend/src/views/chart/view/ChartEdit.vue b/frontend/src/views/chart/view/ChartEdit.vue index 6d48edba2e..df8529901a 100644 --- a/frontend/src/views/chart/view/ChartEdit.vue +++ b/frontend/src/views/chart/view/ChartEdit.vue @@ -247,30 +247,6 @@ /> - - - {{ $t('chart.drill') }} - / - {{ $t('chart.dimension') }} - - - - - - -
        - {{ $t('chart.placeholder_field') }} -
        -
        {{ $t('chart.drag_block_table_data_column') }} @@ -404,6 +380,30 @@ {{ $t('chart.placeholder_field') }}
        + + + {{ $t('chart.drill') }} + / + {{ $t('chart.dimension') }} + + + + + + +
        + {{ $t('chart.placeholder_field') }} +
        +
      @@ -427,7 +427,7 @@ - + @@ -483,7 +483,7 @@
      - +
      @@ -494,6 +494,9 @@
      +
      + +
      @@ -603,6 +606,7 @@ import ChartDragItem from '../components/drag-item/ChartDragItem' import DrillItem from '../components/drag-item/DrillItem' import ResultFilterEditor from '../components/filter/ResultFilterEditor' import ChartComponent from '../components/ChartComponent' +import DrillPath from '@/views/chart/view/DrillPath' import bus from '@/utils/bus' import DatasetChartDetail from '../../dataset/common/DatasetChartDetail' // shape attr,component style @@ -663,7 +667,8 @@ export default { DimensionItem, draggable, ChartDragItem, - DrillItem + DrillItem, + DrillPath }, props: { param: { @@ -738,7 +743,9 @@ export default { filterItem: {}, places: [], attrActiveNames: [], - styleActiveNames: [] + styleActiveNames: [], + drillClickDimensionList: [], + drillFilters: [] } }, computed: { @@ -750,6 +757,7 @@ export default { }, watch: { 'param': function() { + this.resetDrill() if (this.param.optType === 'new') { // } else { @@ -877,6 +885,13 @@ export default { if (view.type === 'treemap' && trigger === 'chart') { view.customAttr.label.show = true } + if (view.type === 'treemap' || + view.type.includes('table') || + view.type.includes('text') || + view.type.includes('gauge') || + view.type.includes('radar')) { + view.drillFields = [] + } view.customFilter.forEach(function(ele) { if (ele && !ele.filter) { ele.filter = [] @@ -894,6 +909,7 @@ export default { // this.get(response.data.id); // this.getData(response.data.id) + this.resetDrill() if (getData) { this.getData(response.data.id) } else { @@ -983,7 +999,8 @@ export default { getData(id) { if (id) { ajaxGetData(id, { - filter: [] + filter: [], + drill: this.drillClickDimensionList }).then(response => { this.initTableData(response.data.tableId) this.view = JSON.parse(JSON.stringify(response.data)) @@ -1003,8 +1020,13 @@ export default { if (this.chart.privileges) { this.param.privileges = this.chart.privileges } + if (!response.data.drill) { + this.drillClickDimensionList.splice(this.drillClickDimensionList.length - 1, 1) + } + this.drillFilters = JSON.parse(JSON.stringify(response.data.drillFilters)) }).catch(err => { this.resetView() + this.resetDrill() this.httpRequest.status = err.response.data.success this.httpRequest.msg = err.response.data.message this.$nextTick(() => { @@ -1487,6 +1509,21 @@ export default { bubbleItemRemove(item) { this.view.extBubble.splice(item.index, 1) this.save(true) + }, + + chartClick(param) { + if (this.drillClickDimensionList.length < this.view.drillFields.length - 1) { + this.drillClickDimensionList.push({ dimensionList: param.data.dimensionList }) + this.getData(this.param.id) + } + }, + + resetDrill() { + this.drillClickDimensionList = [] + }, + drillJump(index) { + this.drillClickDimensionList = this.drillClickDimensionList.slice(0, index) + this.getData(this.param.id) } } } diff --git a/frontend/src/views/chart/view/DrillPath.vue b/frontend/src/views/chart/view/DrillPath.vue new file mode 100644 index 0000000000..b3370eae0d --- /dev/null +++ b/frontend/src/views/chart/view/DrillPath.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/frontend/src/views/nolic/index.vue b/frontend/src/views/nolic/index.vue new file mode 100644 index 0000000000..0ce8caa15f --- /dev/null +++ b/frontend/src/views/nolic/index.vue @@ -0,0 +1,9 @@ + + + diff --git a/frontend/src/views/panel/edit/index.vue b/frontend/src/views/panel/edit/index.vue index 070886ad4d..5149e7ab18 100644 --- a/frontend/src/views/panel/edit/index.vue +++ b/frontend/src/views/panel/edit/index.vue @@ -192,6 +192,7 @@ import { mapState } from 'vuex' import { uuid } from 'vue-uuid' import Toolbar from '@/components/canvas/components/Toolbar' import { findOne } from '@/api/panel/panel' +import { getPanelAllLinkageInfo } from '@/api/panel/linkage' import PreviewFullScreen from '@/components/canvas/components/Editor/PreviewFullScreen' import Preview from '@/components/canvas/components/Editor/Preview' import AttrList from '@/components/canvas/components/AttrList' @@ -363,6 +364,7 @@ export default { const componentDatas = JSON.parse(componentDataTemp) componentDatas.forEach(item => { item.filters = (item.filters || []) + item.linkageFilters = (item.linkageFilters || []) }) this.$store.commit('setComponentData', this.resetID(componentDatas)) // this.$store.commit('setComponentData', this.resetID(JSON.parse(componentDataTemp))) @@ -375,12 +377,17 @@ export default { const componentDatas = JSON.parse(response.data.panelData) componentDatas.forEach(item => { item.filters = (item.filters || []) + item.linkageFilters = (item.linkageFilters || []) }) this.$store.commit('setComponentData', this.resetID(componentDatas)) // this.$store.commit('setComponentData', this.resetID(JSON.parse(response.data.panelData))) const panelStyle = JSON.parse(response.data.panelStyle) this.$store.commit('setCanvasStyle', panelStyle) this.$store.commit('recordSnapshot')// 记录快照 + // 刷新联动信息 + getPanelAllLinkageInfo(panelId).then(rsp => { + this.$store.commit('setNowPanelTrackInfo', rsp.data) + }) }) } }, @@ -463,6 +470,7 @@ export default { } component.propValue = propValue component.filters = [] + component.linkageFilters = [] } }) } else { @@ -660,6 +668,7 @@ export default { } component.propValue = propValue component.filters = [] + component.linkageFilters = [] } }) diff --git a/frontend/src/views/panel/list/EditPanel/index.vue b/frontend/src/views/panel/list/EditPanel/index.vue index 0aca7f717e..368b7c2e3c 100644 --- a/frontend/src/views/panel/list/EditPanel/index.vue +++ b/frontend/src/views/panel/list/EditPanel/index.vue @@ -134,7 +134,6 @@ export default { return false } - debugger if (this.editPanel.panelInfo.name.length > 50) { this.$warning(this.$t('commons.char_can_not_more_50')) return false diff --git a/frontend/src/views/panel/list/PanelList.vue b/frontend/src/views/panel/list/PanelList.vue index d7b5c99bda..6f69d67cde 100644 --- a/frontend/src/views/panel/list/PanelList.vue +++ b/frontend/src/views/panel/list/PanelList.vue @@ -177,6 +177,8 @@ import { uuid } from 'vue-uuid' import bus from '@/utils/bus' import EditPanel from './EditPanel' import { addGroup, delGroup, groupTree, defaultTree, findOne } from '@/api/panel/panel' +import { getPanelAllLinkageInfo } from '@/api/panel/linkage' +import { mapState } from 'vuex' import { DEFAULT_COMMON_CANVAS_STYLE_STRING } from '@/views/panel/panel' @@ -274,7 +276,10 @@ export default { computed: { panelDialogTitle() { return this.editPanel.titlePre + this.editPanel.titleSuf - } + }, + ...mapState([ + 'nowPanelTrackInfo' + ]) }, watch: { // 切换展示页面后 重新点击一下当前节点 @@ -517,12 +522,18 @@ export default { const componentDatas = JSON.parse(response.data.panelData) componentDatas.forEach(item => { item.filters = (item.filters || []) + item.linkageFilters = (item.linkageFilters || []) }) this.$store.commit('setComponentData', this.resetID(componentDatas)) // this.$store.commit('setComponentData', sourceInfo.type === 'custom' ? sourceInfo : this.resetID(sourceInfo)) const temp = JSON.parse(response.data.panelStyle) this.$store.commit('setCanvasStyle', temp) this.$store.dispatch('panel/setPanelInfo', data) + + // 刷新联动信息 + getPanelAllLinkageInfo(data.id).then(rsp => { + this.$store.commit('setNowPanelTrackInfo', rsp.data) + }) }) } if (node.expanded) { diff --git a/frontend/src/views/system/datasource/DsTree.vue b/frontend/src/views/system/datasource/DsTree.vue index 6b4e026daa..ae60457ecb 100644 --- a/frontend/src/views/system/datasource/DsTree.vue +++ b/frontend/src/views/system/datasource/DsTree.vue @@ -156,6 +156,8 @@ export default { return 'SQL Server' } else if (type === 'oracle') { return 'Oracle' + }else if (type === 'pg') { + return 'PostgreSQL' } }, diff --git a/frontend/src/views/system/datasource/form.vue b/frontend/src/views/system/datasource/form.vue index e2ee45c109..1916bbe5a5 100644 --- a/frontend/src/views/system/datasource/form.vue +++ b/frontend/src/views/system/datasource/form.vue @@ -46,30 +46,13 @@ - + {{ $t('datasource.get_schema') }} - - - - - - - - - - {{ $t('datasource.get_schema') }} - - - + - - - - - - - - - - - - {{ $t('commons.yes') }} - {{ $t('commons.no') }} - - - - - - - - {{ $t('commons.save') }} - {{ $t('commons.reset') }} - - - - - - - diff --git a/frontend/src/views/system/dept/index.vue b/frontend/src/views/system/dept/index.vue deleted file mode 100644 index d4ea1402af..0000000000 --- a/frontend/src/views/system/dept/index.vue +++ /dev/null @@ -1,521 +0,0 @@ - - - - - diff --git a/frontend/src/views/system/map/index.vue b/frontend/src/views/system/map/index.vue index b57ec0cf05..4f0377cdd6 100644 --- a/frontend/src/views/system/map/index.vue +++ b/frontend/src/views/system/map/index.vue @@ -37,7 +37,7 @@ export default { series: [ { type: 'map', - map: 'HK', // 自定义扩展图表类型 + map: 'MAP', // 自定义扩展图表类型 roam: true, label: { show: false diff --git a/frontend/src/views/system/role/form.vue b/frontend/src/views/system/role/form.vue deleted file mode 100644 index 7a9930f673..0000000000 --- a/frontend/src/views/system/role/form.vue +++ /dev/null @@ -1,104 +0,0 @@ - - - diff --git a/frontend/src/views/system/role/index.vue b/frontend/src/views/system/role/index.vue deleted file mode 100644 index 27a2399d88..0000000000 --- a/frontend/src/views/system/role/index.vue +++ /dev/null @@ -1,276 +0,0 @@ - - - - diff --git a/frontend/src/views/system/user/form.vue b/frontend/src/views/system/user/form.vue index 25b1887457..72d71aec53 100644 --- a/frontend/src/views/system/user/form.vue +++ b/frontend/src/views/system/user/form.vue @@ -72,16 +72,11 @@