diff --git a/backend/pom.xml b/backend/pom.xml index e616f0206e..f1e772b196 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -118,7 +118,7 @@ org.apache.commons commons-text - 1.8 + [1.10.0,) commons-codec diff --git a/backend/src/main/java/io/dataease/auth/api/AuthApi.java b/backend/src/main/java/io/dataease/auth/api/AuthApi.java index e4b2df95b5..aeaee10e13 100644 --- a/backend/src/main/java/io/dataease/auth/api/AuthApi.java +++ b/backend/src/main/java/io/dataease/auth/api/AuthApi.java @@ -75,6 +75,10 @@ public interface AuthApi { @PostMapping("/isOpenLark") boolean isOpenLark(); + @ApiOperation("是否开启国际飞书") + @PostMapping("/isOpenLarksuite") + boolean isOpenLarksuite(); + @ApiIgnore @PostMapping("/isPluginLoaded") boolean isPluginLoaded(); diff --git a/backend/src/main/java/io/dataease/auth/config/cas/CasStrategy.java b/backend/src/main/java/io/dataease/auth/config/cas/CasStrategy.java index 7a8693b428..82d5187a82 100644 --- a/backend/src/main/java/io/dataease/auth/config/cas/CasStrategy.java +++ b/backend/src/main/java/io/dataease/auth/config/cas/CasStrategy.java @@ -2,6 +2,7 @@ package io.dataease.auth.config.cas; import io.dataease.auth.service.impl.ShiroServiceImpl; import io.dataease.commons.utils.CommonBeanFactory; +import io.dataease.commons.utils.ServletUtils; import io.dataease.service.system.SystemParameterService; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.util.AntPathMatcher; @@ -17,7 +18,7 @@ import java.util.Set; public class CasStrategy implements UrlPatternMatcherStrategy { - private static Set releaseTypes = new HashSet<>(); + private static Set releaseTypes = new HashSet<>(); @PostConstruct public void init() { @@ -25,6 +26,7 @@ public class CasStrategy implements UrlPatternMatcherStrategy { releaseTypes.add("link"); releaseTypes.add("doc"); } + @Override public boolean matches(String s) { SystemParameterService service = CommonBeanFactory.getBean(SystemParameterService.class); @@ -35,10 +37,14 @@ public class CasStrategy implements UrlPatternMatcherStrategy { if ((beginIndex = s.indexOf(serverName)) != -1) { s = s.substring(beginIndex + serverName.length()); } - if (StringUtils.equals("/", s)) return false; + if (StringUtils.equals("/", s)) { + if (fromLink(serverName)) return true; + return false; + } if (StringUtils.equals("/login", s)) return false; if (StringUtils.startsWith(s, "/cas/callBack")) return false; if (StringUtils.equals("/api/auth/deLogout", s)) return true; + if (s.startsWith("/link.html")) return true; AntPathMatcher antPathMatcher = new AntPathMatcher(); ShiroServiceImpl shiroService = CommonBeanFactory.getBean(ShiroServiceImpl.class); Map stringStringMap = shiroService.loadFilterChainDefinitionMap(); @@ -57,4 +63,15 @@ public class CasStrategy implements UrlPatternMatcherStrategy { public void setPattern(String s) { } + + private Boolean fromLink(String serverName) { + String referrer = ServletUtils.request().getHeader("referer"); + if (StringUtils.isBlank(referrer)) return false; + int beginIndex = -1; + if ((beginIndex = referrer.indexOf(serverName)) != -1) { + referrer = referrer.substring(beginIndex + serverName.length()); + return referrer.startsWith("/link.html"); + } + return false; + } } diff --git a/backend/src/main/java/io/dataease/auth/server/AuthServer.java b/backend/src/main/java/io/dataease/auth/server/AuthServer.java index e4282473a2..e86731d06f 100644 --- a/backend/src/main/java/io/dataease/auth/server/AuthServer.java +++ b/backend/src/main/java/io/dataease/auth/server/AuthServer.java @@ -12,6 +12,7 @@ import io.dataease.auth.service.AuthUserService; import io.dataease.auth.util.JWTUtils; import io.dataease.auth.util.RsaUtil; import io.dataease.commons.constants.SysLogConstants; +import io.dataease.commons.exception.DEException; import io.dataease.commons.utils.*; import io.dataease.controller.sys.request.LdapAddRequest; import io.dataease.exception.DataEaseException; @@ -240,8 +241,13 @@ public class AuthServer implements AuthApi { HttpServletRequest request = ServletUtils.request(); String idToken = request.getHeader("IdToken"); if (StringUtils.isNotBlank(idToken)) { - OidcXpackService oidcXpackService = SpringContextUtil.getBean(OidcXpackService.class); - oidcXpackService.logout(idToken); + try { + OidcXpackService oidcXpackService = SpringContextUtil.getBean(OidcXpackService.class); + oidcXpackService.logout(idToken); + } catch (Exception e) { + LogUtil.error(e.getMessage(), e); + DEException.throwException("oidc_logout_error"); + } } } @@ -253,11 +259,16 @@ public class AuthServer implements AuthApi { String result = null; Integer defaultLoginType = systemParameterService.defaultLoginType(); if (defaultLoginType == 3 && isOpenCas()) { - HttpServletRequest request = ServletUtils.request(); - HttpSession session = request.getSession(); - session.invalidate(); - CasXpackService casXpackService = SpringContextUtil.getBean(CasXpackService.class); - result = casXpackService.logout(); + try { + HttpServletRequest request = ServletUtils.request(); + HttpSession session = request.getSession(); + session.invalidate(); + CasXpackService casXpackService = SpringContextUtil.getBean(CasXpackService.class); + result = casXpackService.logout(); + } catch (Exception e) { + LogUtil.error(e.getMessage(), e); + DEException.throwException("cas_logout_error"); + } } try { Long userId = JWTUtils.tokenInfoByToken(token).getUserId(); @@ -337,6 +348,14 @@ public class AuthServer implements AuthApi { return authUserService.supportLark(); } + @Override + public boolean isOpenLarksuite() { + Boolean licValid = PluginUtils.licValid(); + if (!licValid) + return false; + return authUserService.supportLarksuite(); + } + @Override public boolean isPluginLoaded() { Boolean licValid = PluginUtils.licValid(); diff --git a/backend/src/main/java/io/dataease/auth/service/AuthUserService.java b/backend/src/main/java/io/dataease/auth/service/AuthUserService.java index a9df96a6e8..ba9d201031 100644 --- a/backend/src/main/java/io/dataease/auth/service/AuthUserService.java +++ b/backend/src/main/java/io/dataease/auth/service/AuthUserService.java @@ -23,6 +23,8 @@ public interface AuthUserService { SysUserEntity getUserByDingtalkId(String dingtalkId); SysUserEntity getUserByLarkId(String larkId); + SysUserEntity getUserByLarksuiteId(String larksuiteId); + List roles(Long userId); List permissions(Long userId); @@ -43,6 +45,8 @@ public interface AuthUserService { Boolean supportLark(); + Boolean supportLarksuite(); + Boolean supportLoginLimit(); Boolean pluginLoaded(); diff --git a/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java b/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java index f862f84273..a148882cf5 100644 --- a/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java +++ b/backend/src/main/java/io/dataease/auth/service/impl/AuthUserServiceImpl.java @@ -21,6 +21,7 @@ import io.dataease.plugins.util.PluginUtils; import io.dataease.plugins.xpack.cas.service.CasXpackService; import io.dataease.plugins.xpack.dingtalk.service.DingtalkXpackService; import io.dataease.plugins.xpack.lark.service.LarkXpackService; +import io.dataease.plugins.xpack.larksuite.service.LarksuiteXpackService; import io.dataease.plugins.xpack.ldap.service.LdapXpackService; import io.dataease.plugins.xpack.loginlimit.dto.response.LoginLimitInfo; import io.dataease.plugins.xpack.loginlimit.service.LoginLimitXpackService; @@ -108,6 +109,11 @@ public class AuthUserServiceImpl implements AuthUserService { return authMapper.findLarkUser(larkId); } + @Override + public SysUserEntity getUserByLarksuiteId(String larksuiteId) { + return authMapper.findLarksuiteUser(larksuiteId); + } + @Override public List roles(Long userId) { return authMapper.roleCodes(userId); @@ -221,6 +227,15 @@ public class AuthUserServiceImpl implements AuthUserService { return larkXpackService.isOpen(); } + @Override + public Boolean supportLarksuite() { + Map beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((LarksuiteXpackService.class)); + if (beansOfType.keySet().size() == 0) return false; + LarksuiteXpackService larkXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + if (ObjectUtils.isEmpty(larkXpackService)) return false; + return larkXpackService.isOpen(); + } + @Override public Boolean supportLoginLimit() { Map beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((LoginLimitXpackService.class)); 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 a1a55baffa..0fd46ef9a9 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 @@ -86,6 +86,8 @@ public class ShiroServiceImpl implements ShiroService { filterChainDefinitionMap.put("/api/auth/isOpenWecom", ANON); filterChainDefinitionMap.put("/api/auth/isOpenDingtalk", ANON); filterChainDefinitionMap.put("/api/auth/isOpenLark", ANON); + filterChainDefinitionMap.put("/api/auth/isOpenCas", ANON); + filterChainDefinitionMap.put("/api/auth/isOpenLarksuite", ANON); filterChainDefinitionMap.put("/api/auth/getPublicKey", ANON); filterChainDefinitionMap.put("/api/pluginCommon/component/*", ANON); filterChainDefinitionMap.put("/api/pluginCommon/staticInfo/**", ANON); @@ -101,7 +103,11 @@ public class ShiroServiceImpl implements ShiroService { filterChainDefinitionMap.put("/plugin/lark/callBack*", ANON); filterChainDefinitionMap.put("/plugin/lark/bind*", ANON); filterChainDefinitionMap.put("/plugin/lark/getQrParam", ANON); + filterChainDefinitionMap.put("/plugin/larksuite/callBack*", ANON); + filterChainDefinitionMap.put("/plugin/larksuite/bind*", ANON); + filterChainDefinitionMap.put("/plugin/larksuite/getQrParam", ANON); filterChainDefinitionMap.put("/cas/reset/**", ANON); + filterChainDefinitionMap.put("/cas/loginPage", ANON); filterChainDefinitionMap.put("/unauth", ANON); filterChainDefinitionMap.put("/display/**", ANON); diff --git a/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java b/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java index 5932e7bd14..272304b63c 100644 --- a/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java +++ b/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java @@ -86,7 +86,7 @@ public class DatasourceController { @PostMapping("/get/{id}") public DatasourceDTO getDatasource(@PathVariable String id) throws Exception { DatasourceUnionRequest request = new DatasourceUnionRequest(); - request.setUserId(String.valueOf(AuthUtils.getUser().getUserId())); + request.setUserId("1"); request.setId(id); List datasourceList = datasourceService.getDatasourceList(request); return CollectionUtils.isNotEmpty(datasourceList) ? datasourceList.get(0) : null; diff --git a/backend/src/main/java/io/dataease/controller/panel/AppLogController.java b/backend/src/main/java/io/dataease/controller/panel/AppLogController.java index f388d18a78..45a547acf3 100644 --- a/backend/src/main/java/io/dataease/controller/panel/AppLogController.java +++ b/backend/src/main/java/io/dataease/controller/panel/AppLogController.java @@ -21,24 +21,31 @@ import java.util.List; @RestController @Api(tags = "应用市场:应用日志") @ApiSupport(order = 220) -@RequestMapping("/app/log") +@RequestMapping("app/log") public class AppLogController { @Resource - private AppLogService applogService; + private AppLogService appLogService; @I18n @ApiOperation("查询日志") @PostMapping("/logGrid/{goPage}/{pageSize}") @ApiImplicitParams({ - @ApiImplicitParam(paramType = "path", name = "goPage", value = "页码", required = true, dataType = "Integer"), - @ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"), - @ApiImplicitParam(name = "request", value = "查询条件", required = true) + @ApiImplicitParam(paramType = "path", name = "goPage", value = "页码", required = true, dataType = "Integer"), + @ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"), + @ApiImplicitParam(name = "request", value = "查询条件", required = true) }) public Pager> logGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody KeyGridRequest request) { Page page = PageHelper.startPage(goPage, pageSize, true); - return PageUtils.setPageInfo(page, applogService.query(request)); + return PageUtils.setPageInfo(page, appLogService.query(request)); + } + + + @ApiOperation("删除日志和资源") + @PostMapping("/deleteLog") + public void deleteLogAndResource(@RequestBody AppLogGridDTO request) throws Exception { + appLogService.deleteLogAndResource(request); } } diff --git a/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java b/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java index b9c2cc1dbb..b361b5d725 100644 --- a/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java +++ b/backend/src/main/java/io/dataease/controller/panel/PanelGroupController.java @@ -203,4 +203,18 @@ public class PanelGroupController { result.setResponseSource("appApply"); return result; } + + @PostMapping("/appEdit") + public void appEdit(@RequestBody PanelAppTemplateApplyRequest request) throws Exception{ + panelGroupService.appEdit(request); + } + + @GetMapping("/findOneWithParent/{panelId}") + public PanelGroupDTO findOneWithParent(@PathVariable String panelId) throws Exception{ + PanelGroupDTO result = findOne(panelId); + result.setParents(authService.parentResource(panelId,"panel")); + result.setRequestId(UUIDUtil.getUUIDAsString()); + result.setResponseSource("appApply"); + return result; + } } diff --git a/backend/src/main/java/io/dataease/controller/request/dataset/DataSetGroupRequest.java b/backend/src/main/java/io/dataease/controller/request/dataset/DataSetGroupRequest.java index 5c87b85646..51f8cd76ba 100644 --- a/backend/src/main/java/io/dataease/controller/request/dataset/DataSetGroupRequest.java +++ b/backend/src/main/java/io/dataease/controller/request/dataset/DataSetGroupRequest.java @@ -18,4 +18,6 @@ public class DataSetGroupRequest extends DatasetGroup { private String userId; @ApiModelProperty("ID集合") private Set ids; + @ApiModelProperty("排除的ID") + private String excludedId; } diff --git a/backend/src/main/java/io/dataease/controller/request/panel/PanelAppTemplateApplyRequest.java b/backend/src/main/java/io/dataease/controller/request/panel/PanelAppTemplateApplyRequest.java index 5446e5a84d..77b95aaabe 100644 --- a/backend/src/main/java/io/dataease/controller/request/panel/PanelAppTemplateApplyRequest.java +++ b/backend/src/main/java/io/dataease/controller/request/panel/PanelAppTemplateApplyRequest.java @@ -13,12 +13,18 @@ import java.util.List; @Data public class PanelAppTemplateApplyRequest { + private String logId; + private String panelId; + private String panelGroupPid; + private String panelName; private String datasetGroupId; + private String datasetGroupPid; + private String datasetGroupName; private String appTemplateId; 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 8c8f4d0f87..b528f45bb3 100644 --- a/backend/src/main/java/io/dataease/controller/sys/SysUserController.java +++ b/backend/src/main/java/io/dataease/controller/sys/SysUserController.java @@ -56,6 +56,8 @@ public class SysUserController { private static final String DINGTALK = "dingtalk"; private static final String LARK = "lark"; + private static final String LARKSUITE = "larksuite"; + @Resource private SysUserService sysUserService; @@ -246,13 +248,16 @@ public class SysUserController { AuthBindDTO dto = new AuthBindDTO(); if (ObjectUtils.isEmpty(sysUserAssist)) return dto; if (authUserService.supportWecom() && StringUtils.isNotBlank(sysUserAssist.getWecomId())) { - dto.setWecomBinded(true); + dto.setWecomBound(true); } if (authUserService.supportDingtalk() && StringUtils.isNotBlank(sysUserAssist.getDingtalkId())) { - dto.setDingtalkBinded(true); + dto.setDingtalkBound(true); } if (authUserService.supportLark() && StringUtils.isNotBlank(sysUserAssist.getLarkId())) { - dto.setLarkBinded(true); + dto.setLarkBound(true); + } + if (authUserService.supportLarksuite() && StringUtils.isNotBlank(sysUserAssist.getLarksuiteId())) { + dto.setLarksuiteBound(true); } return dto; } @@ -260,9 +265,9 @@ public class SysUserController { @PostMapping("/unbindAssist/{type}") public void unbindAssist(@PathVariable("type") String type) { - Boolean valid = StringUtils.equals(WECOM, type) || StringUtils.equals(DINGTALK, type) || StringUtils.equals(LARK, type); + Boolean valid = StringUtils.equals(WECOM, type) || StringUtils.equals(DINGTALK, type) || StringUtils.equals(LARK, type) || StringUtils.equals(LARKSUITE, type); if (!valid) { - DEException.throwException("only [wecom, dingtalk, lark] is valid"); + DEException.throwException("only [wecom, dingtalk, lark, larksuite] is valid"); } Long userId = AuthUtils.getUser().getUserId(); SysUserAssist sysUserAssist = sysUserService.assistInfo(userId); @@ -275,10 +280,13 @@ public class SysUserController { if (StringUtils.equals(LARK, type)) { sysUserAssist.setLarkId(null); } - if (StringUtils.isBlank(sysUserAssist.getWecomId()) && StringUtils.isBlank(sysUserAssist.getDingtalkId()) && StringUtils.isBlank(sysUserAssist.getLarkId())) { + if (StringUtils.equals(LARKSUITE, type)) { + sysUserAssist.setLarksuiteId(null); + } + if (StringUtils.isBlank(sysUserAssist.getWecomId()) && StringUtils.isBlank(sysUserAssist.getDingtalkId()) && StringUtils.isBlank(sysUserAssist.getLarkId()) && StringUtils.isBlank(sysUserAssist.getLarksuiteId())) { sysUserService.changeUserFrom(userId, 0); } - sysUserService.saveAssist(userId, sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId()); + sysUserService.saveAssist(userId, sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId(), sysUserAssist.getLarksuiteId()); } diff --git a/backend/src/main/java/io/dataease/controller/sys/response/AuthBindDTO.java b/backend/src/main/java/io/dataease/controller/sys/response/AuthBindDTO.java index 0394961fe3..b01f031a67 100644 --- a/backend/src/main/java/io/dataease/controller/sys/response/AuthBindDTO.java +++ b/backend/src/main/java/io/dataease/controller/sys/response/AuthBindDTO.java @@ -7,9 +7,11 @@ import java.io.Serializable; @Data public class AuthBindDTO implements Serializable { - private Boolean wecomBinded = false; + private Boolean wecomBound = false; - private Boolean dingtalkBinded = false; + private Boolean dingtalkBound = false; - private Boolean larkBinded = false; + private Boolean larkBound = false; + + private Boolean larksuiteBound = false; } diff --git a/backend/src/main/java/io/dataease/dto/appTemplateMarket/AppLogGridDTO.java b/backend/src/main/java/io/dataease/dto/appTemplateMarket/AppLogGridDTO.java index c54b894374..3e1181660c 100644 --- a/backend/src/main/java/io/dataease/dto/appTemplateMarket/AppLogGridDTO.java +++ b/backend/src/main/java/io/dataease/dto/appTemplateMarket/AppLogGridDTO.java @@ -16,4 +16,18 @@ public class AppLogGridDTO extends PanelAppTemplateLog implements Serializable { private String panelName; + private String panelGroupPid; + + private String datasourceType; + + private String datasetGroupPid; + + private Boolean deleteResource; + + private String datasetPrivileges; + + private String panelPrivileges; + + private String datasourcePrivileges; + } diff --git a/backend/src/main/java/io/dataease/ext/AuthMapper.java b/backend/src/main/java/io/dataease/ext/AuthMapper.java index 763d41f414..5ddb83f600 100644 --- a/backend/src/main/java/io/dataease/ext/AuthMapper.java +++ b/backend/src/main/java/io/dataease/ext/AuthMapper.java @@ -37,5 +37,6 @@ public interface AuthMapper { SysUserEntity findWecomUser(@Param("wecomId") String wecomId); SysUserEntity findDingtalkUser(@Param("dingtalkId") String dingtalkId); SysUserEntity findLarkUser(@Param("larkId") String larkId); + SysUserEntity findLarksuiteUser(@Param("larksuiteId") String larksuiteId); } diff --git a/backend/src/main/java/io/dataease/ext/AuthMapper.xml b/backend/src/main/java/io/dataease/ext/AuthMapper.xml index ac07e54e79..9710597aa6 100644 --- a/backend/src/main/java/io/dataease/ext/AuthMapper.xml +++ b/backend/src/main/java/io/dataease/ext/AuthMapper.xml @@ -23,8 +23,7 @@ + + diff --git a/backend/src/main/java/io/dataease/ext/ExtAppLogMapper.xml b/backend/src/main/java/io/dataease/ext/ExtAppLogMapper.xml index ee7b6a93fc..ccd96b59a6 100644 --- a/backend/src/main/java/io/dataease/ext/ExtAppLogMapper.xml +++ b/backend/src/main/java/io/dataease/ext/ExtAppLogMapper.xml @@ -7,12 +7,38 @@ + + + + + + diff --git a/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java b/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java index 4f9d1bced1..d293f49dca 100644 --- a/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java +++ b/backend/src/main/java/io/dataease/job/sechedule/strategy/impl/EmailTaskHandler.java @@ -25,6 +25,8 @@ import io.dataease.plugins.xpack.email.dto.response.XpackEmailTemplateDTO; import io.dataease.plugins.xpack.email.service.EmailXpackService; import io.dataease.plugins.xpack.lark.dto.entity.LarkMsgResult; import io.dataease.plugins.xpack.lark.service.LarkXpackService; +import io.dataease.plugins.xpack.larksuite.dto.response.LarksuiteMsgResult; +import io.dataease.plugins.xpack.larksuite.service.LarksuiteXpackService; import io.dataease.plugins.xpack.wecom.dto.entity.WecomMsgResult; import io.dataease.plugins.xpack.wecom.service.WecomXpackService; import io.dataease.service.chart.ViewExportExcel; @@ -297,6 +299,30 @@ public class EmailTaskHandler extends TaskHandler implements Job { } } + } + break; + case "larksuite": + if (SpringContextUtil.getBean(AuthUserService.class).supportLarksuite()) { + List larksuiteUsers = new ArrayList<>(); + for (int j = 0; j < reciLists.size(); j++) { + String reci = reciLists.get(j); + SysUserEntity userBySub = userService.getUserByName(reci); + if (ObjectUtils.isEmpty(userBySub)) continue; + Long userId = userBySub.getUserId(); + SysUserAssist sysUserAssist = sysUserService.assistInfo(userId); + if (ObjectUtils.isEmpty(sysUserAssist) || StringUtils.isBlank(sysUserAssist.getLarksuiteId())) + continue; + larksuiteUsers.add(sysUserAssist.getLarksuiteId()); + } + + if (CollectionUtils.isNotEmpty(larksuiteUsers)) { + LarksuiteXpackService larksuiteXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + LarksuiteMsgResult larksuiteMsgResult = larksuiteXpackService.pushOaMsg(larksuiteUsers, emailTemplateDTO.getTitle(), contentStr, bytes, files); + if (larksuiteMsgResult.getCode() != 0) { + errorMsgs.add("larksuite: " + larksuiteMsgResult.getMsg()); + } + } + } break; default: diff --git a/backend/src/main/java/io/dataease/plugins/server/CasServer.java b/backend/src/main/java/io/dataease/plugins/server/CasServer.java index c54639c1b3..9a68ebec93 100644 --- a/backend/src/main/java/io/dataease/plugins/server/CasServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/CasServer.java @@ -115,4 +115,13 @@ public class CasServer { return error; } } + + @GetMapping("/loginPage") + @ResponseBody + public String loginPage() { + String casServerUrlPrefix = systemParameterService.getValue("cas.login"); + String callBack = systemParameterService.getValue("cas.callBack"); + String result = casServerUrlPrefix + "?service=" + callBack; + return result; + } } diff --git a/backend/src/main/java/io/dataease/plugins/server/XDingtalkServer.java b/backend/src/main/java/io/dataease/plugins/server/XDingtalkServer.java index 27414e6836..a4c686349b 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XDingtalkServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XDingtalkServer.java @@ -9,6 +9,8 @@ import io.dataease.commons.exception.DEException; import io.dataease.commons.utils.DeLogUtils; import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.ServletUtils; +import io.dataease.exception.DataEaseException; +import io.dataease.i18n.Translator; import io.dataease.plugins.common.base.domain.SysUserAssist; import io.dataease.plugins.config.SpringContextUtil; import io.dataease.plugins.xpack.dingtalk.dto.response.DingQrResult; @@ -101,6 +103,8 @@ public class XDingtalkServer { sysUserService.validateExistUser(username, dingUserEntity.getName(), email); sysUserService.saveDingtalkCUser(dingUserEntity, email); sysUserEntity = authUserService.getUserByDingtalkId(username); + } else if (sysUserEntity.getEnabled() == 0) { + DataEaseException.throwException(Translator.get("i18n_user_is_disable")); } TokenInfo tokenInfo = TokenInfo.builder().userId(sysUserEntity.getUserId()).username(sysUserEntity.getUsername()).build(); String realPwd = sysUserEntity.getPassword(); @@ -185,7 +189,7 @@ public class XDingtalkServer { sysUserAssist.setUserId(Long.parseLong(state)); } sysUserAssist.setDingtalkId(userId); - sysUserService.saveAssist(sysUserAssist.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId()); + sysUserService.saveAssist(sysUserAssist.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId(), sysUserAssist.getLarksuiteId()); response.sendRedirect(url); } catch (Exception e) { diff --git a/backend/src/main/java/io/dataease/plugins/server/XLarkServer.java b/backend/src/main/java/io/dataease/plugins/server/XLarkServer.java index 9f51798be4..a71909fbcb 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XLarkServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XLarkServer.java @@ -9,6 +9,8 @@ import io.dataease.commons.exception.DEException; import io.dataease.commons.utils.DeLogUtils; import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.ServletUtils; +import io.dataease.exception.DataEaseException; +import io.dataease.i18n.Translator; import io.dataease.plugins.common.base.domain.SysUserAssist; import io.dataease.plugins.config.SpringContextUtil; @@ -102,6 +104,8 @@ public class XLarkServer { sysUserService.validateExistUser(username, larkUserInfo.getName(), email); sysUserService.saveLarkCUser(larkUserInfo, email); sysUserEntity = authUserService.getUserByLarkId(username); + } else if (sysUserEntity.getEnabled() == 0) { + DataEaseException.throwException(Translator.get("i18n_user_is_disable")); } TokenInfo tokenInfo = TokenInfo.builder().userId(sysUserEntity.getUserId()).username(sysUserEntity.getUsername()).build(); String realPwd = sysUserEntity.getPassword(); @@ -185,7 +189,7 @@ public class XLarkServer { sysUserAssist.setUserId(Long.parseLong(state)); } sysUserAssist.setLarkId(userId); - sysUserService.saveAssist(sysUserAssist.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId()); + sysUserService.saveAssist(sysUserAssist.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId(), sysUserAssist.getLarksuiteId()); response.sendRedirect(url); } catch (Exception e) { diff --git a/backend/src/main/java/io/dataease/plugins/server/XLarksuiteServer.java b/backend/src/main/java/io/dataease/plugins/server/XLarksuiteServer.java new file mode 100644 index 0000000000..b4af287f4b --- /dev/null +++ b/backend/src/main/java/io/dataease/plugins/server/XLarksuiteServer.java @@ -0,0 +1,210 @@ +package io.dataease.plugins.server; + +import io.dataease.auth.entity.SysUserEntity; +import io.dataease.auth.entity.TokenInfo; +import io.dataease.auth.service.AuthUserService; +import io.dataease.auth.util.JWTUtils; +import io.dataease.commons.constants.SysLogConstants; +import io.dataease.commons.exception.DEException; +import io.dataease.commons.utils.DeLogUtils; +import io.dataease.commons.utils.LogUtil; +import io.dataease.commons.utils.ServletUtils; +import io.dataease.exception.DataEaseException; +import io.dataease.i18n.Translator; +import io.dataease.plugins.common.base.domain.SysUserAssist; +import io.dataease.plugins.config.SpringContextUtil; +import io.dataease.plugins.xpack.display.dto.response.SysSettingDto; +import io.dataease.plugins.xpack.lark.dto.entity.LarkQrResult; +import io.dataease.plugins.xpack.lark.dto.response.LarkInfo; +import io.dataease.plugins.xpack.larksuite.dto.entity.UserData; +import io.dataease.plugins.xpack.larksuite.dto.response.LarksuiteUserResult; +import io.dataease.plugins.xpack.larksuite.service.LarksuiteXpackService; +import io.dataease.service.sys.SysUserService; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import springfox.documentation.annotations.ApiIgnore; + +import javax.annotation.Resource; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.List; +import java.util.Map; + +@ApiIgnore +@RequestMapping("/plugin/larksuite") +@Controller +public class XLarksuiteServer { + + @Resource + private AuthUserService authUserService; + @Resource + private SysUserService sysUserService; + + @ResponseBody + @GetMapping("/info") + public LarkInfo getLarkInfo() { + LarksuiteXpackService larkXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + return larkXpackService.info(); + } + + @ResponseBody + @RequiresPermissions("sysparam:read") + @PostMapping("/save") + public void save(@RequestBody List settings) { + LarksuiteXpackService larkXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + larkXpackService.save(settings); + } + + @ResponseBody + @PostMapping("/testConn") + public void testConn(@RequestBody LarkInfo larkInfo) { + LarksuiteXpackService larkXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + try { + larkXpackService.testConn(larkInfo); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @ResponseBody + @PostMapping("/getQrParam") + public LarkQrResult getQrParam() { + LarksuiteXpackService larkXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + return larkXpackService.getQrParam(); + } + + @GetMapping("/callBack") + public ModelAndView callBack(@RequestParam("code") String code, @RequestParam("state") String state) { + ModelAndView modelAndView = new ModelAndView("redirect:/"); + HttpServletResponse response = ServletUtils.response(); + LarksuiteXpackService larksuiteXpackService = null; + try { + Map beansOfType = SpringContextUtil.getApplicationContext().getBeansOfType((LarksuiteXpackService.class)); + if (beansOfType.keySet().size() == 0) { + DEException.throwException("缺少国际飞书插件"); + } + larksuiteXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + Boolean isOpen = larksuiteXpackService.isOpen(); + if (!isOpen) { + DEException.throwException("未开启国际飞书"); + } + LarksuiteUserResult larksuiteUserResult = larksuiteXpackService.userInfo(code, state, false); + UserData larkUserInfo = larksuiteUserResult.getData(); + String username = larkUserInfo.getUser_id(); + SysUserEntity sysUserEntity = authUserService.getUserByLarksuiteId(username); + if (null == sysUserEntity) { + String email = StringUtils.isNotBlank(larkUserInfo.getEmail()) ? larkUserInfo.getEmail() : (username + "@larksuite.work"); + sysUserService.validateExistUser(username, larkUserInfo.getName(), email); + sysUserService.saveLarksuiteCUser(larkUserInfo, email); + sysUserEntity = authUserService.getUserByLarksuiteId(username); + } else if (sysUserEntity.getEnabled() == 0) { + DataEaseException.throwException(Translator.get("i18n_user_is_disable")); + } + TokenInfo tokenInfo = TokenInfo.builder().userId(sysUserEntity.getUserId()).username(sysUserEntity.getUsername()).build(); + String realPwd = sysUserEntity.getPassword(); + String token = JWTUtils.sign(tokenInfo, realPwd); + ServletUtils.setToken(token); + + DeLogUtils.save(SysLogConstants.OPERATE_TYPE.LOGIN, SysLogConstants.SOURCE_TYPE.USER, sysUserEntity.getUserId(), null, null, null); + + Cookie cookie_token = new Cookie("Authorization", token); + cookie_token.setPath("/"); + + response.addCookie(cookie_token); + } catch (Exception e) { + + String msg = e.getMessage(); + if (null != e.getCause()) { + msg = e.getCause().getMessage(); + } + try { + msg = URLEncoder.encode(msg, "UTF-8"); + LogUtil.error(e); + Cookie cookie_error = new Cookie("LarksuiteError", msg); + cookie_error.setPath("/"); + response.addCookie(cookie_error); + return modelAndView; + } catch (UnsupportedEncodingException e1) { + e.printStackTrace(); + } + } + return modelAndView; + } + + private void bindError(HttpServletResponse response, String url, String errorMsg) { + Cookie cookie_error = new Cookie("LarksuiteError", errorMsg); + cookie_error.setPath("/"); + response.addCookie(cookie_error); + try { + response.sendRedirect(url); + } catch (IOException e) { + LogUtil.error(e.getMessage(), e); + DEException.throwException(e); + } + } + + @GetMapping("/bind") + public void bind(@RequestParam("code") String code, @RequestParam("state") String state) { + + HttpServletResponse response = ServletUtils.response(); + String url = "/#person-info/index"; + + LarksuiteXpackService larksuiteXpackService = null; + try { + SysUserEntity userEntity = authUserService.getUserById(Long.parseLong(state)); + if (ObjectUtils.isEmpty(userEntity)) { + bindError(response, url, "绑定用户不存在"); + return; + } + SysUserAssist sysUserAssist = sysUserService.assistInfo(Long.parseLong(state)); + if (ObjectUtils.isNotEmpty(sysUserAssist) && StringUtils.isNotBlank(sysUserAssist.getLarksuiteId())) { + bindError(response, url, "目标用户已绑定其他国际飞书账号"); + return; + } + + Boolean isOpen = authUserService.supportLarksuite(); + if (!isOpen) { + DEException.throwException("未开启国际飞书"); + } + larksuiteXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + LarksuiteUserResult larksuiteUserResult = larksuiteXpackService.userInfo(code, state, true); + UserData larkUserInfo = larksuiteUserResult.getData(); + String userId = larkUserInfo.getUser_id(); + + + SysUserEntity sysUserEntity = authUserService.getUserByLarksuiteId(userId); + if (null != sysUserEntity) { + bindError(response, url, "当前国际飞书账号已绑定其他DE用户"); + return; + } + + if (ObjectUtils.isEmpty(sysUserAssist)) { + sysUserAssist = new SysUserAssist(); + sysUserAssist.setUserId(Long.parseLong(state)); + } + sysUserAssist.setLarksuiteId(userId); + sysUserService.saveAssist(sysUserAssist.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId(), sysUserAssist.getLarksuiteId()); + response.sendRedirect(url); + } catch (Exception e) { + + String msg = e.getMessage(); + if (null != e.getCause()) { + msg = e.getCause().getMessage(); + } + try { + msg = URLEncoder.encode(msg, "UTF-8"); + LogUtil.error(e); + bindError(response, url, msg); + } catch (UnsupportedEncodingException e1) { + e.printStackTrace(); + } + } + } +} diff --git a/backend/src/main/java/io/dataease/plugins/server/XWecomServer.java b/backend/src/main/java/io/dataease/plugins/server/XWecomServer.java index 7ff7678cdb..2c3df6f20f 100644 --- a/backend/src/main/java/io/dataease/plugins/server/XWecomServer.java +++ b/backend/src/main/java/io/dataease/plugins/server/XWecomServer.java @@ -10,6 +10,8 @@ import io.dataease.commons.exception.DEException; import io.dataease.commons.utils.DeLogUtils; import io.dataease.commons.utils.LogUtil; import io.dataease.commons.utils.ServletUtils; +import io.dataease.exception.DataEaseException; +import io.dataease.i18n.Translator; import io.dataease.plugins.common.base.domain.SysUserAssist; import io.dataease.plugins.config.SpringContextUtil; import io.dataease.plugins.xpack.display.dto.response.SysSettingDto; @@ -106,6 +108,8 @@ public class XWecomServer { sysUserService.validateExistUser(userId, userMap.get("name").toString(), email); sysUserService.saveWecomCUser(userMap, userId, email); sysUserEntity = authUserService.getUserByWecomId(userId); + } else if (sysUserEntity.getEnabled() == 0) { + DataEaseException.throwException(Translator.get("i18n_user_is_disable")); } TokenInfo tokenInfo = TokenInfo.builder().userId(sysUserEntity.getUserId()).username(sysUserEntity.getUsername()).build(); String realPwd = sysUserEntity.getPassword(); @@ -193,7 +197,7 @@ public class XWecomServer { sysUserAssist.setUserId(Long.parseLong(state)); } sysUserAssist.setWecomId(userId); - sysUserService.saveAssist(sysUserAssist.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId()); + sysUserService.saveAssist(sysUserAssist.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId(), sysUserAssist.getLarksuiteId()); response.sendRedirect(url); } catch (Exception e) { diff --git a/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java b/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java index 0a2e7f8800..ea5b3a204e 100644 --- a/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java +++ b/backend/src/main/java/io/dataease/provider/datasource/JdbcProvider.java @@ -90,7 +90,9 @@ public class JdbcProvider extends DefaultJdbcProvider { DatabaseMetaData databaseMetaData = connection.getMetaData(); String tableNamePattern = datasourceRequest.getTable(); if(datasourceRequest.getDatasource().getType().equalsIgnoreCase(DatasourceTypes.mysql.name())){ - tableNamePattern = String.format(MySQLConstants.KEYWORD_TABLE, tableNamePattern); + if(databaseMetaData.getDriverMajorVersion() < 8){ + tableNamePattern = String.format(MySQLConstants.KEYWORD_TABLE, tableNamePattern); + } } ResultSet resultSet = databaseMetaData.getColumns(null, "%", tableNamePattern, "%"); while (resultSet.next()) { @@ -689,7 +691,7 @@ public class JdbcProvider extends DefaultJdbcProvider { if (StringUtils.isEmpty(sqlServerConfiguration.getSchema())) { throw new Exception(Translator.get("i18n_schema_is_empty")); } - return "SELECT TABLE_NAME FROM DATABASE.INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = 'DS_SCHEMA' ;" + return "SELECT TABLE_NAME FROM \"DATABASE\".INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = 'DS_SCHEMA' ;" .replace("DATABASE", sqlServerConfiguration.getDataBase()) .replace("DS_SCHEMA", sqlServerConfiguration.getSchema()); case oracle: diff --git a/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java b/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java index a3daa200d0..c3fe116d71 100644 --- a/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java +++ b/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java @@ -1054,24 +1054,25 @@ public class DataSetTableService { return sql; } - public String removeVariables(String sql, String dsType) throws Exception { + public String removeVariables(final String sql, String dsType) throws Exception { + String tmpSql = sql; Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(sql); + Matcher matcher = pattern.matcher(tmpSql); boolean hasVariables = false; while (matcher.find()) { hasVariables = true; - sql = sql.replace(matcher.group(), SubstitutedParams); + tmpSql = tmpSql.replace(matcher.group(), SubstitutedParams); } - if (!hasVariables && !sql.contains(SubstitutedParams)) { - return sql; + if (!hasVariables && !tmpSql.contains(SubstitutedParams)) { + return tmpSql; } - CCJSqlParserUtil.parse(sql, parser -> parser.withSquareBracketQuotation(true)); - Statement statement = CCJSqlParserUtil.parse(sql); + CCJSqlParserUtil.parse(tmpSql, parser -> parser.withSquareBracketQuotation(true)); + Statement statement = CCJSqlParserUtil.parse(tmpSql); Select select = (Select) statement; if (select.getSelectBody() instanceof PlainSelect) { return handlePlainSelect((PlainSelect) select.getSelectBody(), select, dsType); - }else { + } else { String result = ""; SetOperationList setOperationList = (SetOperationList) select.getSelectBody(); for (int i = 0; i < setOperationList.getSelects().size(); i++) { @@ -1175,15 +1176,24 @@ public class DataSetTableService { } public Map getSQLPreview(DataSetTableRequest dataSetTableRequest) throws Exception { + DataTableInfoDTO dataTableInfo = new Gson().fromJson(dataSetTableRequest.getInfo(), DataTableInfoDTO.class); + String sql = dataTableInfo.isBase64Encryption() ? new String(java.util.Base64.getDecoder().decode(dataTableInfo.getSql())) : dataTableInfo.getSql(); Datasource ds = datasourceMapper.selectByPrimaryKey(dataSetTableRequest.getDataSourceId()); if (ds == null) { throw new Exception(Translator.get("i18n_invalid_ds")); } + String tmpSql = removeVariables(sql, ds.getType()); + if (dataSetTableRequest.getMode() == 1 && (tmpSql.contains(SubstitutedParams) || tmpSql.contains(SubstitutedSql.trim()))) { + throw new Exception(Translator.get("I18N_SQL_variable_direct_limit")); + } + if (tmpSql.contains(SubstitutedParams)) { + throw new Exception(Translator.get("I18N_SQL_variable_limit")); + } Provider datasourceProvider = ProviderFactory.getProvider(ds.getType()); DatasourceRequest datasourceRequest = new DatasourceRequest(); datasourceRequest.setDatasource(ds); - DataTableInfoDTO dataTableInfo = new Gson().fromJson(dataSetTableRequest.getInfo(), DataTableInfoDTO.class); - String sql = dataTableInfo.isBase64Encryption() ? new String(java.util.Base64.getDecoder().decode(dataTableInfo.getSql())) : dataTableInfo.getSql(); + + sql = handleVariableDefaultValue(sql, dataSetTableRequest.getSqlVariableDetails(), ds.getType()); if (StringUtils.isEmpty(sql)) { DataEaseException.throwException(Translator.get("i18n_sql_not_empty")); @@ -2372,7 +2382,7 @@ public class DataSetTableService { if (CollectionUtils.isNotEmpty(data)) { jsonArray = data.stream().map(ele -> { Map map = new HashMap<>(); - for (int i = 0; i < ele.size(); i++) { + for (int i = 0; i < fieldArray.length; i++) { map.put(fieldArray[i], ele.get(i)); } return map; diff --git a/backend/src/main/java/io/dataease/service/message/service/strategy/SendLarksuite.java b/backend/src/main/java/io/dataease/service/message/service/strategy/SendLarksuite.java new file mode 100644 index 0000000000..d5f49cfc77 --- /dev/null +++ b/backend/src/main/java/io/dataease/service/message/service/strategy/SendLarksuite.java @@ -0,0 +1,39 @@ +package io.dataease.service.message.service.strategy; + + +import io.dataease.auth.service.AuthUserService; +import io.dataease.plugins.common.base.domain.SysUserAssist; +import io.dataease.plugins.config.SpringContextUtil; +import io.dataease.plugins.xpack.larksuite.service.LarksuiteXpackService; +import io.dataease.service.message.service.SendService; +import io.dataease.service.sys.SysUserService; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; + +@Service("sendLarksuite") +public class SendLarksuite implements SendService { + + @Autowired + private AuthUserService authUserService; + + @Resource + private SysUserService sysUserService; + + @Override + public void sendMsg(Long userId, Long typeId, String content, String param) { + SysUserAssist sysUserAssist = sysUserService.assistInfo(userId); + if (ObjectUtils.isNotEmpty(sysUserAssist) && StringUtils.isNotBlank(sysUserAssist.getLarksuiteId()) && authUserService.supportLarksuite()) { + String username = sysUserAssist.getLarksuiteId(); + LarksuiteXpackService larksuiteXpackService = SpringContextUtil.getBean(LarksuiteXpackService.class); + List userIds = new ArrayList<>(); + userIds.add(username); + larksuiteXpackService.pushMsg(userIds, content); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/io/dataease/service/panel/PanelAppTemplateService.java b/backend/src/main/java/io/dataease/service/panel/PanelAppTemplateService.java index 75f9c47bb2..db1c7dbb46 100644 --- a/backend/src/main/java/io/dataease/service/panel/PanelAppTemplateService.java +++ b/backend/src/main/java/io/dataease/service/panel/PanelAppTemplateService.java @@ -5,6 +5,7 @@ import io.dataease.commons.constants.CommonConstants; import io.dataease.commons.constants.PanelConstants; import io.dataease.commons.utils.AuthUtils; import io.dataease.commons.utils.BeanUtils; +import io.dataease.controller.datasource.request.UpdataDsRequest; import io.dataease.controller.request.dataset.DataSetTableRequest; import io.dataease.controller.request.panel.PanelAppTemplateApplyRequest; import io.dataease.controller.request.panel.PanelAppTemplateRequest; @@ -270,15 +271,36 @@ public class PanelAppTemplateService { return chartViewFieldsRealMap; } - public void nameCheck(PanelAppTemplateApplyRequest request) { - panelGroupService.checkPanelName(request.getPanelName(), request.getPanelId(), PanelConstants.OPT_TYPE_INSERT, null, "panel"); - DatasetGroup datasetGroup = new DatasetGroup(); - datasetGroup.setPid(request.getDatasetGroupId()); - datasetGroup.setName(request.getDatasetGroupName()); - dataSetGroupService.checkName(datasetGroup); - request.getDatasourceList().stream().forEach(datasource -> { - datasourceService.checkName(datasource.getName(), datasource.getType(), null); - }); + public void nameCheck(PanelAppTemplateApplyRequest request, String optType) { + if ("add".equals(optType)) { + panelGroupService.checkPanelName(request.getPanelName(), request.getPanelGroupPid(), PanelConstants.OPT_TYPE_INSERT, null, "panel"); + DatasetGroup datasetGroup = new DatasetGroup(); + datasetGroup.setPid(request.getDatasetGroupPid()); + datasetGroup.setName(request.getDatasetGroupName()); + dataSetGroupService.checkName(datasetGroup); + request.getDatasourceList().stream().forEach(datasource -> { + datasourceService.checkName(datasource.getName(), datasource.getType(), null); + }); + } else { + DatasetGroup datasetGroup = new DatasetGroup(); + datasetGroup.setPid(request.getDatasetGroupPid()); + datasetGroup.setName(request.getDatasetGroupName()); + datasetGroup.setId(request.getDatasetGroupId()); + dataSetGroupService.checkName(datasetGroup); + request.getDatasourceList().stream().forEach(datasource -> { + datasourceService.checkName(datasource.getName(), datasource.getType(), datasource.getId()); + }); + } } + + @Transactional(rollbackFor = Exception.class) + public void editDatasource(List updateDatasourceList) throws Exception { + for (int i = 0; i < updateDatasourceList.size(); i++) { + UpdataDsRequest updataDsRequest = new UpdataDsRequest(); + BeanUtils.copyBean(updataDsRequest, updateDatasourceList.get(i)); + datasourceService.updateDatasource(updataDsRequest); + + } + } } diff --git a/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java b/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java index 73fb1119ba..cb9af63d96 100644 --- a/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java +++ b/backend/src/main/java/io/dataease/service/panel/PanelGroupService.java @@ -127,9 +127,9 @@ public class PanelGroupService { @Resource private PanelAppTemplateLogService appTemplateLogService; @Resource - private ChartGroupService chartGroupService; - @Resource private DataSetGroupService dataSetGroupService; + @Resource + private DatasetGroupMapper datasetGroupMapper; public List tree(PanelGroupRequest panelGroupRequest) { String userId = String.valueOf(AuthUtils.getUser().getUserId()); @@ -232,6 +232,25 @@ public class PanelGroupService { return panelId; } + public void move(PanelGroupRequest request){ + PanelGroupWithBLOBs panelInfo = panelGroupMapper.selectByPrimaryKey(request.getId()); + if (panelInfo.getPid().equalsIgnoreCase(request.getPid())) { + DataEaseException.throwException(Translator.get("i18n_select_diff_folder")); + } + // 移动校验 + if (StringUtils.isNotEmpty(request.getName())) { + checkPanelName(request.getName(), request.getPid(), PanelConstants.OPT_TYPE_INSERT, request.getId(), panelInfo.getNodeType()); + } + PanelGroupWithBLOBs record = new PanelGroupWithBLOBs(); + record.setName(request.getName()); + record.setId(request.getId()); + record.setPid(request.getPid()); + record.setUpdateTime(request.getUpdateTime()); + record.setUpdateBy(request.getUpdateBy()); + panelGroupMapper.updateByPrimaryKeySelective(record); + DeLogUtils.save(SysLogConstants.OPERATE_TYPE.MODIFY, sourceType, request.getId(), panelInfo.getPid(), request.getPid(), sourceType); + } + public void checkPanelName(String name, String pid, String optType, String id, String nodeType) { PanelGroupExample groupExample = new PanelGroupExample(); @@ -811,12 +830,12 @@ public class PanelGroupService { @Transactional(rollbackFor = Exception.class) public String appApply(PanelAppTemplateApplyRequest request) throws Exception{ //仪表板名称校验,数据集分组名称校验,数据源名称校验 - panelAppTemplateService.nameCheck(request); + panelAppTemplateService.nameCheck(request,"add"); String newPanelId = UUIDUtil.getUUIDAsString(); // 新建数据集分组 DatasetGroup newDatasetGroup = new DatasetGroup(); - newDatasetGroup.setPid(request.getDatasetGroupId()); + newDatasetGroup.setPid(request.getDatasetGroupPid()); newDatasetGroup.setName(request.getDatasetGroupName()); newDatasetGroup.setType("group"); DataSetGroupDTO resultDatasetGroup = dataSetGroupService.save(newDatasetGroup); @@ -853,7 +872,7 @@ public class PanelGroupService { panelAppTemplateService.applyViewsField(chartViewFieldsInfo,chartViewsRealMap,datasetsRealMap,datasetFieldsRealMap); - panelAppTemplateService.applyPanel(panelInfo,chartViewsRealMap,newPanelId, request.getPanelName(), request.getPanelId()); + panelAppTemplateService.applyPanel(panelInfo,chartViewsRealMap,newPanelId, request.getPanelName(), request.getPanelGroupPid()); panelAppTemplateService.applyPanelView(panelViewsInfo,chartViewsRealMap,newPanelId); @@ -873,4 +892,42 @@ public class PanelGroupService { appTemplateLogService.newAppApplyLog(templateLog); return newPanelId; } + + @Transactional(rollbackFor = Exception.class) + public void appEdit(PanelAppTemplateApplyRequest request) throws Exception{ + long currentTime = System.currentTimeMillis(); + String userName = AuthUtils.getUser().getUsername(); + //名称校验,数据集分组名称校验,数据源名称校验 + panelAppTemplateService.nameCheck(request,"update"); + //仪表板移动更新名称 + PanelGroup panelHistoryInfo = panelGroupMapper.selectByPrimaryKey(request.getPanelId()); + String panelHistoryPid = panelHistoryInfo.getPid(); + if(panelHistoryPid.equals(request.getPanelGroupPid())){ + // 未移动 + checkPanelName(request.getPanelName(), request.getPanelGroupPid(), PanelConstants.OPT_TYPE_UPDATE, request.getPanelId(), "panel"); + }else{ + checkPanelName(request.getPanelName(), request.getPanelGroupPid(), PanelConstants.OPT_TYPE_INSERT, null, "panel"); + } + panelHistoryInfo.setName(request.getPanelName()); + panelHistoryInfo.setPid(request.getPanelGroupPid()); + panelHistoryInfo.setUpdateBy(userName); + panelHistoryInfo.setUpdateTime(currentTime); + panelGroupMapper.updateByPrimaryKey(panelHistoryInfo); + + //数据集分组移动,变更 + DatasetGroup datasetGroupHistoryInfo = datasetGroupMapper.selectByPrimaryKey(request.getDatasetGroupId()); + DatasetGroup datasetGroup = new DatasetGroup(); + datasetGroup.setName(request.getDatasetGroupName()); + datasetGroup.setId(request.getDatasetGroupId()); + if(datasetGroupHistoryInfo.getPid().equals(request.getDatasetGroupPid())){ + datasetGroup.setPid(request.getDatasetGroupPid()); + } + dataSetGroupService.checkName(datasetGroup); + datasetGroupHistoryInfo.setName(request.getDatasetGroupName()); + datasetGroupHistoryInfo.setPid(request.getDatasetGroupPid()); + datasetGroupMapper.updateByPrimaryKey(datasetGroupHistoryInfo); + + //数据源变更 + panelAppTemplateService.editDatasource(request.getDatasourceList()); + } } diff --git a/backend/src/main/java/io/dataease/service/panel/applog/AppLogQueryParam.java b/backend/src/main/java/io/dataease/service/panel/applog/AppLogQueryParam.java index 9aee5afaf3..0abc975811 100644 --- a/backend/src/main/java/io/dataease/service/panel/applog/AppLogQueryParam.java +++ b/backend/src/main/java/io/dataease/service/panel/applog/AppLogQueryParam.java @@ -7,5 +7,6 @@ import java.util.List; @Data public class AppLogQueryParam extends GridExample { + private String userId; } diff --git a/backend/src/main/java/io/dataease/service/panel/applog/AppLogService.java b/backend/src/main/java/io/dataease/service/panel/applog/AppLogService.java index 0c174f17a4..7fd1ac2577 100644 --- a/backend/src/main/java/io/dataease/service/panel/applog/AppLogService.java +++ b/backend/src/main/java/io/dataease/service/panel/applog/AppLogService.java @@ -1,13 +1,20 @@ package io.dataease.service.panel.applog; import com.google.gson.Gson; +import io.dataease.commons.utils.AuthUtils; import io.dataease.controller.sys.request.KeyGridRequest; import io.dataease.dto.SysLogDTO; import io.dataease.dto.appTemplateMarket.AppLogGridDTO; import io.dataease.ext.ExtAppLogMapper; import io.dataease.ext.query.GridExample; import io.dataease.plugins.common.base.mapper.PanelAppTemplateLogMapper; +import io.dataease.service.dataset.DataSetGroupService; +import io.dataease.service.datasource.DatasourceService; +import io.dataease.service.panel.PanelGroupService; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import javax.annotation.Resource; import java.util.List; @@ -19,12 +26,19 @@ public class AppLogService { private PanelAppTemplateLogMapper appLogMapper; @Resource private ExtAppLogMapper extAppLogMapper; + @Resource + private PanelGroupService panelGroupService; + @Resource + private DataSetGroupService dataSetGroupService; + @Resource + private DatasourceService datasourceService; public List query(KeyGridRequest request) { GridExample gridExample = request.convertExample(); gridExample.setExtendCondition(request.getKeyWord()); AppLogQueryParam logQueryParam = gson.fromJson(gson.toJson(gridExample), AppLogQueryParam.class); + logQueryParam.setUserId(String.valueOf(AuthUtils.getUser().getUserId())); List voLogs = extAppLogMapper.query(logQueryParam); return voLogs; } @@ -34,4 +48,19 @@ public class AppLogService { } + @Transactional + public void deleteLogAndResource(AppLogGridDTO request) throws Exception { + if (request.getDeleteResource()) { + if (StringUtils.isNotEmpty(request.getPanelId())) { + panelGroupService.deleteCircle(request.getPanelId()); + } + if (StringUtils.isNotEmpty(request.getDatasetGroupId())) { + dataSetGroupService.delete(request.getDatasetGroupId()); + } + if (StringUtils.isNotEmpty(request.getDatasourceId())) { + datasourceService.deleteDatasource(request.getDatasourceId()); + } + } + appLogMapper.deleteByPrimaryKey(request.getId()); + } } diff --git a/backend/src/main/java/io/dataease/service/sys/SysUserService.java b/backend/src/main/java/io/dataease/service/sys/SysUserService.java index bc929fb6d1..466153a885 100644 --- a/backend/src/main/java/io/dataease/service/sys/SysUserService.java +++ b/backend/src/main/java/io/dataease/service/sys/SysUserService.java @@ -21,6 +21,7 @@ import io.dataease.plugins.common.base.mapper.SysUsersRolesMapper; import io.dataease.plugins.common.entity.XpackLdapUserEntity; import io.dataease.plugins.xpack.dingtalk.dto.response.DingUserEntity; import io.dataease.plugins.xpack.lark.dto.entity.LarkUserInfo; +import io.dataease.plugins.xpack.larksuite.dto.entity.UserData; import io.dataease.plugins.xpack.oidc.dto.SSOUserInfo; import org.apache.commons.collections4.CollectionUtils; @@ -107,7 +108,7 @@ public class SysUserService { SysUserAssist sysUserAssist = request.getSysUserAssist(); if (ObjectUtils.isNotEmpty(sysUserAssist) && (StringUtils.isNotBlank(sysUserAssist.getWecomId()) || StringUtils.isNotBlank(sysUserAssist.getDingtalkId()) || StringUtils.isNotBlank(sysUserAssist.getLarkId()))) { - saveAssist(userId, sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId()); + saveAssist(userId, sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId(), sysUserAssist.getLarksuiteId()); } return insert; @@ -157,7 +158,7 @@ public class SysUserService { sysUser.setIsAdmin(false); sysUser.setSub(userId); sysUserMapper.insert(sysUser); - Optional.ofNullable(findOne(sysUser)).ifPresent(u -> saveAssist(u.getUserId(), u.getUsername(), null, null)); + Optional.ofNullable(findOne(sysUser)).ifPresent(u -> saveAssist(u.getUserId(), u.getUsername(), null, null, null)); } @@ -180,7 +181,7 @@ public class SysUserService { sysUser.setSub(dingUserEntity.getUnionid()); sysUser.setPhone(dingUserEntity.getMobile()); sysUserMapper.insert(sysUser); - Optional.ofNullable(findOne(sysUser)).ifPresent(u -> saveAssist(u.getUserId(), null, u.getUsername(), null)); + Optional.ofNullable(findOne(sysUser)).ifPresent(u -> saveAssist(u.getUserId(), null, u.getUsername(), null, null)); } @Transactional @@ -202,7 +203,29 @@ public class SysUserService { sysUser.setSub(larkUserInfo.getSub()); sysUser.setPhone(larkUserInfo.getMobile()); sysUserMapper.insert(sysUser); - Optional.ofNullable(findOne(sysUser)).ifPresent(u -> saveAssist(u.getUserId(), null, null, u.getUsername())); + Optional.ofNullable(findOne(sysUser)).ifPresent(u -> saveAssist(u.getUserId(), null, null, u.getUsername(), null)); + } + + @Transactional + public void saveLarksuiteCUser(UserData larkUserInfo, String email) { + long now = System.currentTimeMillis(); + SysUser sysUser = new SysUser(); + + sysUser.setUsername(larkUserInfo.getUser_id()); + sysUser.setNickName(larkUserInfo.getName()); + sysUser.setEmail(email); + sysUser.setPassword(CodingUtil.md5(DEFAULT_PWD)); + sysUser.setCreateTime(now); + sysUser.setUpdateTime(now); + + sysUser.setEnabled(1L); + sysUser.setLanguage("zh_CN"); + sysUser.setFrom(7); + sysUser.setIsAdmin(false); + sysUser.setSub(larkUserInfo.getUnion_id()); + sysUser.setPhone(larkUserInfo.getMobile()); + sysUserMapper.insert(sysUser); + Optional.ofNullable(findOne(sysUser)).ifPresent(u -> saveAssist(u.getUserId(), null, null, null, u.getUsername())); } @Transactional @@ -299,7 +322,7 @@ public class SysUserService { SysUserAssist sysUserAssist = request.getSysUserAssist(); if (ObjectUtils.isNotEmpty(sysUserAssist) && (StringUtils.isNotBlank(sysUserAssist.getWecomId()) || StringUtils.isNotBlank(sysUserAssist.getDingtalkId()) || StringUtils.isNotBlank(sysUserAssist.getLarkId()))) { - saveAssist(user.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId()); + saveAssist(user.getUserId(), sysUserAssist.getWecomId(), sysUserAssist.getDingtalkId(), sysUserAssist.getLarkId(), sysUserAssist.getLarksuiteId()); } return result; } @@ -550,12 +573,13 @@ public class SysUserService { sysUserAssistMapper.insertSelective(sysUserAssist); } - public void saveAssist(Long userId, String wecomId, String dingtlkId, String larkId) { + public void saveAssist(Long userId, String wecomId, String dingtlkId, String larkId, String larksuiteId) { SysUserAssist existAssist = sysUserAssistMapper.selectByPrimaryKey(userId); if (ObjectUtils.isNotEmpty(existAssist)) { existAssist.setWecomId(wecomId); existAssist.setDingtalkId(dingtlkId); existAssist.setLarkId(larkId); + existAssist.setLarksuiteId(larksuiteId); sysUserAssistMapper.updateByPrimaryKey(existAssist); return; } @@ -564,6 +588,7 @@ public class SysUserService { sysUserAssist.setWecomId(wecomId); sysUserAssist.setDingtalkId(dingtlkId); sysUserAssist.setLarkId(larkId); + sysUserAssist.setLarksuiteId(larksuiteId); sysUserAssistMapper.insert(sysUserAssist); } diff --git a/backend/src/main/resources/db/migration/V29__de1.6.sql b/backend/src/main/resources/db/migration/V29__de1.6.sql index cda07ca6d4..08319e3455 100644 --- a/backend/src/main/resources/db/migration/V29__de1.6.sql +++ b/backend/src/main/resources/db/migration/V29__de1.6.sql @@ -27,7 +27,7 @@ ADD COLUMN `mobile_layout` tinyint(1) NULL DEFAULT 0 COMMENT '启用移动端布 DROP FUNCTION IF EXISTS `GET_PANEL_WITH_PRIVILEGE_AND_MOBILE`; delimiter ;; CREATE FUNCTION `GET_PANEL_WITH_PRIVILEGE_AND_MOBILE`(userId longtext,modelType varchar(255),privilegeType varchar(255)) - RETURNS longtext CHARSET utf8 + RETURNS longtext CHARSET utf8mb4 COLLATE utf8mb4_general_ci READS SQL DATA BEGIN @@ -73,7 +73,7 @@ delimiter ; DROP FUNCTION IF EXISTS `GET_V_AUTH_MODEL_ID_P_USE_MOBILE`; delimiter ;; CREATE FUNCTION `GET_V_AUTH_MODEL_ID_P_USE_MOBILE`(userId longtext,modelType varchar(255)) - RETURNS longtext CHARSET utf8 + RETURNS longtext CHARSET utf8mb4 COLLATE utf8mb4_general_ci READS SQL DATA BEGIN diff --git a/backend/src/main/resources/db/migration/V32__1.8.sql b/backend/src/main/resources/db/migration/V32__1.8.sql index 01201ca456..1f079e7d3b 100644 --- a/backend/src/main/resources/db/migration/V32__1.8.sql +++ b/backend/src/main/resources/db/migration/V32__1.8.sql @@ -344,7 +344,7 @@ CREATE TABLE `sys_background_image` ( `base_url` varchar(255) DEFAULT NULL, `url` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; -- ---------------------------- -- Records of sys_background_image @@ -404,7 +404,7 @@ CREATE TABLE `dataease_code_version` ( `success` tinyint(1) NOT NULL, PRIMARY KEY (`installed_rank`), KEY `dataease_version_s_idx` (`success`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; -- ---------------------------- -- Records of dataease_code_version @@ -429,7 +429,7 @@ CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `v_history_chart_view` AS DROP FUNCTION IF EXISTS `GET_CHART_GROUP_WITH_CHILDREN`; delimiter ;; CREATE FUNCTION `GET_CHART_GROUP_WITH_CHILDREN`(parentId varchar(8000)) - RETURNS LONGTEXT CHARSET utf8 + RETURNS LONGTEXT CHARSET utf8mb4 COLLATE utf8mb4_general_ci READS SQL DATA BEGIN diff --git a/backend/src/main/resources/db/migration/V33__1.9.sql b/backend/src/main/resources/db/migration/V33__1.9.sql index 8cc46a3726..ab7f3fcb7f 100644 --- a/backend/src/main/resources/db/migration/V33__1.9.sql +++ b/backend/src/main/resources/db/migration/V33__1.9.sql @@ -105,7 +105,7 @@ ADD COLUMN `copy_id` varchar(255) NULL COMMENT '复制ID' AFTER `copy_from`; DROP FUNCTION IF EXISTS `copy_auth`; delimiter ;; CREATE FUNCTION `copy_auth`(authSource varchar(255),authSourceType varchar(255),authUser varchar(255)) - RETURNS varchar(255) CHARSET utf8mb4 + RETURNS varchar(255) CHARSET utf8mb4 COLLATE utf8mb4_general_ci READS SQL DATA BEGIN @@ -256,7 +256,7 @@ delimiter ; DROP FUNCTION IF EXISTS `delete_auth_source`; delimiter ;; CREATE FUNCTION `delete_auth_source`(authSource varchar(255),authSourceType varchar(255)) - RETURNS varchar(255) CHARSET utf8mb4 + RETURNS varchar(255) CHARSET utf8mb4 COLLATE utf8mb4_general_ci READS SQL DATA BEGIN @@ -285,7 +285,7 @@ INSERT INTO `sys_menu` VALUES (101, 1, 4, 1, '插件管理', 'system-plugin', 's DROP FUNCTION IF EXISTS `GET_CHART_VIEW_COPY_NAME`; delimiter ;; CREATE FUNCTION `GET_CHART_VIEW_COPY_NAME`(chartId varchar(255),pid varchar(255)) - RETURNS varchar(255) CHARSET utf8mb4 + RETURNS varchar(255) CHARSET utf8mb4 COLLATE utf8mb4_general_ci READS SQL DATA BEGIN diff --git a/backend/src/main/resources/db/migration/V40__1.15.sql b/backend/src/main/resources/db/migration/V40__1.15.sql index ac39813c35..6eca9baaef 100644 --- a/backend/src/main/resources/db/migration/V40__1.15.sql +++ b/backend/src/main/resources/db/migration/V40__1.15.sql @@ -213,7 +213,7 @@ delimiter ; DROP FUNCTION IF EXISTS `GET_CHART_VIEW_COPY_NAME`; delimiter ;; CREATE FUNCTION `GET_CHART_VIEW_COPY_NAME`(chartId varchar(255),pid varchar(255)) - RETURNS varchar(255) CHARSET utf8mb4 + RETURNS varchar(255) CHARSET utf8mb4 COLLATE utf8mb4_general_ci READS SQL DATA BEGIN diff --git a/backend/src/main/resources/db/migration/V42__1.16.sql b/backend/src/main/resources/db/migration/V42__1.16.sql index 2423350791..a44a6a190f 100644 --- a/backend/src/main/resources/db/migration/V42__1.16.sql +++ b/backend/src/main/resources/db/migration/V42__1.16.sql @@ -1,16 +1,272 @@ -UPDATE `sys_menu` set `component` = REPLACE(`component`, 'SysParam', 'sysParam') where (`component` like '%SysParam%'); +UPDATE `sys_menu` +set `component` = REPLACE(`component`, 'SysParam', 'sysParam') +where (`component` like '%SysParam%'); -UPDATE `sys_menu` set `component` = REPLACE(`component`, 'privateForm', 'PrivateForm') where (`component` like '%privateForm%'); +UPDATE `sys_menu` +set `component` = REPLACE(`component`, 'privateForm', 'PrivateForm') +where (`component` like '%privateForm%'); -UPDATE `sys_menu` set `component` = REPLACE(`component`, 'personPwd', 'PersonPwd') where (`component` like '%personPwd%'); +UPDATE `sys_menu` +set `component` = REPLACE(`component`, 'personPwd', 'PersonPwd') +where (`component` like '%personPwd%'); -UPDATE `sys_menu` set `component` = REPLACE(`component`, 'dataset', 'Dataset') where (`component` = 'system/task/dataset'); +UPDATE `sys_menu` +set `component` = REPLACE(`component`, 'dataset', 'Dataset') +where (`component` = 'system/task/dataset'); -UPDATE `sys_menu` set `component` = REPLACE(`component`, 'form', 'Form') where (`component` = 'system/task/form'); +UPDATE `sys_menu` +set `component` = REPLACE(`component`, 'form', 'Form') +where (`component` = 'system/task/form'); -ALTER TABLE `dataset_table_field` ADD COLUMN `date_format` VARCHAR(255) NULL AFTER `accuracy`; +ALTER TABLE `dataset_table_field` + ADD COLUMN `date_format` VARCHAR(255) NULL AFTER `accuracy`; -ALTER TABLE `sys_task_email` ADD COLUMN `view_data_range` VARCHAR(255) NULL DEFAULT 'view' AFTER `reci_users`; +ALTER TABLE `sys_task_email` + ADD COLUMN `view_data_range` VARCHAR(255) NULL DEFAULT 'view' AFTER `reci_users`; -UPDATE `sys_msg_type` set `type_name` = 'i18n_msg_type_dataset_sync_failed' WHERE (`msg_type_id` = 6); +UPDATE `sys_msg_type` +set `type_name` = 'i18n_msg_type_dataset_sync_failed' +WHERE (`msg_type_id` = 6); + +ALTER TABLE `sys_user_assist` + ADD COLUMN `larksuite_id` VARCHAR(255) NULL DEFAULT NULL AFTER `lark_id`; + +INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, + `path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`, + `update_time`) +VALUES (41, 1, 1, 1, '应用管理', 'system-app-template', 'panel/appTemplate/index', 13, 'sys-param', + 'panel/appTemplate/index', 0, 0, 0, NULL, NULL, NULL, NULL, 1620444227389); +INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, + `path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`, + `update_time`) +VALUES (203, 0, 0, 1, '应用', 'app-template-market', 'panel/appTemplateMarket/index', 6, 'dashboard', + '/appTemplateMarket', 0, 0, 0, NULL, NULL, NULL, NULL, 1620444227389); + +ALTER TABLE `dataset_table_field` CHANGE COLUMN `type` `type` VARCHAR(255) NOT NULL COMMENT '原始字段类型' ; + +INSERT INTO `my_plugin` (`name`, `store`, `free`, `cost`, `category`, `descript`, `version`, `creator`, `load_mybatis`, + `install_time`, `module_name`, `ds_type`) +VALUES ('Apache Kylin 数据源插件', 'default', '0', '0', 'datasource', 'Apache Kylin 数据源插件', '1.0-SNAPSHOT', 'DATAEASE', '0', + '1650765903630', 'kylin-backend', 'kylin'); + + + +INSERT INTO `sys_msg_channel` (`msg_channel_id`, `channel_name`, `service_name`) VALUES ('6', 'webmsg.channel_larksuite_msg', 'sendLarksuite'); + +INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, `path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (204, 203, 0, 2, '删除记录', NULL, NULL, 999, NULL, NULL, 0, 0, 0, 'appLog:del', NULL, NULL, 1614930903502, 1614930903502); +INSERT INTO `sys_menu` (`menu_id`, `pid`, `sub_count`, `type`, `title`, `name`, `component`, `menu_sort`, `icon`, `path`, `i_frame`, `cache`, `hidden`, `permission`, `create_by`, `update_by`, `create_time`, `update_time`) VALUES (205, 203, 0, 2, '编辑记录', NULL, NULL, 999, NULL, NULL, 0, 0, 0, 'appLog:edit', NULL, NULL, 1614930935529, 1614930935529); + +INSERT INTO `sys_auth` (`id`, `auth_source`, `auth_source_type`, `auth_target`, `auth_target_type`, `auth_time`, `auth_details`, `auth_user`, `update_time`, `copy_from`, `copy_id`) VALUES ('46e4e2cb-1349-40c3-a72d-7b0b30ab5d14', '203', 'menu', '1', 'role', 1666840141866, NULL, 'admin', NULL, NULL, NULL); +INSERT INTO `sys_auth` (`id`, `auth_source`, `auth_source_type`, `auth_target`, `auth_target_type`, `auth_time`, `auth_details`, `auth_user`, `update_time`, `copy_from`, `copy_id`) VALUES ('6e22ad53-d737-447f-9686-5041e122b4dc', '205', 'menu', '1', 'role', 1666840141468, NULL, 'admin', NULL, NULL, NULL); +INSERT INTO `sys_auth` (`id`, `auth_source`, `auth_source_type`, `auth_target`, `auth_target_type`, `auth_time`, `auth_details`, `auth_user`, `update_time`, `copy_from`, `copy_id`) VALUES ('da17fcfe-7875-4aaf-983b-d750d71f36d2', '204', 'menu', '1', 'role', 1666840141658, NULL, 'admin', NULL, NULL, NULL); + +INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b4fe2e52-55a4-11ed-bf84-0242ac130005', '6e22ad53-d737-447f-9686-5041e122b4dc', 'i18n_auth_grant', 15, 0, 'grant', '基础权限-授权', 'admin', 1666840141000, NULL, NULL, NULL); +INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b4fe3215-55a4-11ed-bf84-0242ac130005', '6e22ad53-d737-447f-9686-5041e122b4dc', 'i18n_auth_use', 1, 1, 'use', '基础权限-使用', 'admin', 1666840141000, NULL, NULL, NULL); +INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b51affbf-55a4-11ed-bf84-0242ac130005', 'da17fcfe-7875-4aaf-983b-d750d71f36d2', 'i18n_auth_grant', 15, 0, 'grant', '基础权限-授权', 'admin', 1666840141000, NULL, NULL, NULL); +INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b51b0473-55a4-11ed-bf84-0242ac130005', 'da17fcfe-7875-4aaf-983b-d750d71f36d2', 'i18n_auth_use', 1, 1, 'use', '基础权限-使用', 'admin', 1666840141000, NULL, NULL, NULL); +INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b53a1ad7-55a4-11ed-bf84-0242ac130005', '46e4e2cb-1349-40c3-a72d-7b0b30ab5d14', 'i18n_auth_grant', 15, 0, 'grant', '基础权限-授权', 'admin', 1666840142000, NULL, NULL, NULL); +INSERT INTO `sys_auth_detail` (`id`, `auth_id`, `privilege_name`, `privilege_type`, `privilege_value`, `privilege_extend`, `remark`, `create_user`, `create_time`, `update_time`, `copy_from`, `copy_id`) VALUES ('b53a1dfd-55a4-11ed-bf84-0242ac130005', '46e4e2cb-1349-40c3-a72d-7b0b30ab5d14', 'i18n_auth_use', 1, 1, 'use', '基础权限-使用', 'admin', 1666840142000, NULL, NULL, NULL); + + +DROP VIEW IF EXISTS `v_auth_model`; +CREATE ALGORITHM = UNDEFINED SQL SECURITY DEFINER VIEW `v_auth_model` AS SELECT + `sys_user`.`user_id` AS `id`, + concat( `sys_user`.`nick_name`, '(', `sys_user`.`username`, ')' ) AS `name`, + `sys_user`.`username` AS `label`, + '0' AS `pid`, + 'leaf' AS `node_type`, + 'user' AS `model_type`, + 'user' AS `model_inner_type`, + 'target' AS `auth_type`, + `sys_user`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `sys_user` + WHERE + ( `sys_user`.`is_admin` <> 1 ) UNION ALL + SELECT + `sys_role`.`role_id` AS `id`, + `sys_role`.`name` AS `name`, + `sys_role`.`name` AS `label`, + '0' AS `pid`, + 'leaf' AS `node_type`, + 'role' AS `model_type`, + 'role' AS `model_inner_type`, + 'target' AS `auth_type`, + `sys_role`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `sys_role` UNION ALL + SELECT + `sys_dept`.`dept_id` AS `id`, + `sys_dept`.`name` AS `name`, + `sys_dept`.`name` AS `label`,( + cast( `sys_dept`.`pid` AS CHAR charset utf8mb4 ) COLLATE utf8mb4_general_ci + ) AS `pid`, + IF + (( `sys_dept`.`sub_count` = 0 ), 'leaf', 'spine' ) AS `node_type`, + 'dept' AS `model_type`, + 'dept' AS `model_inner_type`, + 'target' AS `auth_type`, + `sys_dept`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `sys_dept` UNION ALL + SELECT + `datasource`.`id` AS `id`, + `datasource`.`name` AS `NAME`, + `datasource`.`name` AS `label`, + '0' AS `pid`, + 'leaf' AS `node_type`, + 'link' AS `model_type`, + `datasource`.`type` AS `model_inner_type`, + 'source' AS `auth_type`, + `datasource`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `datasource` UNION ALL + SELECT + `dataset_group`.`id` AS `id`, + `dataset_group`.`name` AS `NAME`, + `dataset_group`.`name` AS `label`, + IF + ( isnull( `dataset_group`.`pid` ), '0', `dataset_group`.`pid` ) AS `pid`, + 'spine' AS `node_type`, + 'dataset' AS `model_type`, + `dataset_group`.`type` AS `model_inner_type`, + 'source' AS `auth_type`, + `dataset_group`.`create_by` AS `create_by`, + `dataset_group`.`level` AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `dataset_group` UNION ALL + SELECT + `dataset_table`.`id` AS `id`, + `dataset_table`.`name` AS `NAME`, + `dataset_table`.`name` AS `label`, + `dataset_table`.`scene_id` AS `pid`, + 'leaf' AS `node_type`, + 'dataset' AS `model_type`, + `dataset_table`.`type` AS `model_inner_type`, + 'source' AS `auth_type`, + `dataset_table`.`create_by` AS `create_by`, + 0 AS `level`, + `dataset_table`.`mode` AS `mode`, + `dataset_table`.`data_source_id` AS `data_source_id` + FROM + `dataset_table` UNION ALL + SELECT + `panel_group`.`id` AS `id`, + `panel_group`.`name` AS `NAME`, + `panel_group`.`name` AS `label`,( + CASE + `panel_group`.`id` + WHEN 'panel_list' THEN + '0' + WHEN 'default_panel' THEN + '0' ELSE `panel_group`.`pid` + END + ) AS `pid`, + IF + (( `panel_group`.`node_type` = 'folder' ), 'spine', 'leaf' ) AS `node_type`, + 'panel' AS `model_type`, + `panel_group`.`panel_type` AS `model_inner_type`, + 'source' AS `auth_type`, + `panel_group`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `panel_group` UNION ALL + SELECT + `sys_menu`.`menu_id` AS `menu_id`, + `sys_menu`.`title` AS `name`, + `sys_menu`.`title` AS `label`, + `sys_menu`.`pid` AS `pid`, + IF + (( `sys_menu`.`sub_count` > 0 ), 'spine', 'leaf' ) AS `node_type`, + 'menu' AS `model_type`,( + CASE + `sys_menu`.`type` + WHEN 0 THEN + 'folder' + WHEN 1 THEN + 'menu' + WHEN 2 THEN + 'button' + END + ) AS `model_inner_type`, + 'source' AS `auth_type`, + `sys_menu`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `sys_menu` + WHERE + (( + `sys_menu`.`i_frame` <> 1 + ) + OR isnull( `sys_menu`.`i_frame` )) UNION ALL + SELECT + `plugin_sys_menu`.`menu_id` AS `menu_id`, + `plugin_sys_menu`.`title` AS `name`, + `plugin_sys_menu`.`title` AS `label`, + `plugin_sys_menu`.`pid` AS `pid`, + IF + (( `plugin_sys_menu`.`sub_count` > 0 ), 'spine', 'leaf' ) AS `node_type`, + 'menu' AS `model_type`,( + CASE + `plugin_sys_menu`.`type` + WHEN 0 THEN + 'folder' + WHEN 1 THEN + 'menu' + WHEN 2 THEN + 'button' + END + ) AS `model_inner_type`, + 'source' AS `auth_type`, + `plugin_sys_menu`.`create_by` AS `create_by`, + 0 AS `level`, + 0 AS `mode`, + '0' AS `data_source_id` + FROM + `plugin_sys_menu` + WHERE + (( + `plugin_sys_menu`.`i_frame` <> 1 + ) + OR isnull( `plugin_sys_menu`.`i_frame` )); + +-- ---------------------------- +-- Function structure for delete_auth_target +-- ---------------------------- +DROP FUNCTION IF EXISTS `delete_auth_target`; +delimiter ;; +CREATE FUNCTION `delete_auth_target`(authTarget varchar(255),authTargetType varchar(255)) + RETURNS varchar(255) CHARSET utf8mb4 + READS SQL DATA +BEGIN + +delete from sys_auth_detail where auth_id in ( + select id from sys_auth where sys_auth.auth_target=authTarget and sys_auth.auth_target_type=authTargetType +); + +delete from sys_auth where sys_auth.auth_target=authTarget and sys_auth.auth_target_type=authTargetType; + +RETURN 'success'; + +END +;; +delimiter ; diff --git a/backend/src/main/resources/i18n/messages_en_US.properties b/backend/src/main/resources/i18n/messages_en_US.properties index d3ba643e92..df1effdcd3 100644 --- a/backend/src/main/resources/i18n/messages_en_US.properties +++ b/backend/src/main/resources/i18n/messages_en_US.properties @@ -194,6 +194,7 @@ I18N_DATASOURCE_LEVEL_GRANT=Grant I18N_NO_PERMISSION=You do not have permission to I18N_PLEASE_CONCAT_ADMIN=Please contact the administrator for authorization I18N_SQL_variable_limit=SQL variables can only be used in where conditions +I18N_SQL_variable_direct_limit=SQL variables can only be used for direct connection I18N_EMAIL_CONFIG_ERROR=Email config error I18N_EMAIL_HOST_ERROR=Email host can not be empty I18N_EMAIL_PORT_ERROR=Email port can not be empty diff --git a/backend/src/main/resources/i18n/messages_zh_CN.properties b/backend/src/main/resources/i18n/messages_zh_CN.properties index bdaa67a794..a0972f0da7 100644 --- a/backend/src/main/resources/i18n/messages_zh_CN.properties +++ b/backend/src/main/resources/i18n/messages_zh_CN.properties @@ -194,6 +194,7 @@ I18N_DATASOURCE_LEVEL_GRANT=\u6388\u6743 I18N_NO_PERMISSION=\u5F53\u524D\u7528\u6237\u6CA1\u6709\u6743\u9650 I18N_PLEASE_CONCAT_ADMIN=\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u5F00\u901A I18N_SQL_variable_limit=SQL \u53D8\u91CF\u53EA\u80FD\u5728 WHERE \u6761\u4EF6\u4E2D\u4F7F\u7528 +I18N_SQL_variable_direct_limit=SQL变量只能用于直连 I18N_EMAIL_CONFIG_ERROR=\u90AE\u4EF6\u914D\u7F6E\u9519\u8BEF I18N_EMAIL_HOST_ERROR=\u90AE\u4EF6\u4E3B\u673A\u4E0D\u80FD\u4E3A\u7A7A I18N_EMAIL_PORT_ERROR=\u90AE\u4EF6\u7AEF\u53E3\u4E0D\u80FD\u4E3A\u7A7A diff --git a/backend/src/main/resources/i18n/messages_zh_TW.properties b/backend/src/main/resources/i18n/messages_zh_TW.properties index 2003f5a638..fb269a8bda 100644 --- a/backend/src/main/resources/i18n/messages_zh_TW.properties +++ b/backend/src/main/resources/i18n/messages_zh_TW.properties @@ -190,6 +190,7 @@ I18N_DATASOURCE_LEVEL_GRANT=\u6388\u6B0A I18N_NO_PERMISSION=\u7576\u524D\u7528\u6236\u6C92\u6709\u6B0A\u9650 I18N_PLEASE_CONCAT_ADMIN=\u8ACB\u806F\u7CFB\u7BA1\u7406\u54E1\u958B\u901A I18N_SQL_variable_limit=SQL\u8B8A\u6578\u53EA\u80FD\u5728WHERE\u689D\u4EF6\u4E2D\u4F7F\u7528 +I18N_SQL_variable_direct_limit=SQL變數只能用於直連 I18N_EMAIL_CONFIG_ERROR=\u90F5\u4EF6\u914D\u7F6E\u932F\u8AA4 I18N_EMAIL_HOST_ERROR=\u90F5\u4EF6\u4E3B\u6A5F\u4E0D\u80FD\u70BA\u7A7A I18N_EMAIL_PORT_ERROR=\u90F5\u4EF6\u7AEF\u53E3\u4E0D\u80FD\u70BA\u7A7A diff --git a/frontend/src/api/appTemplateMarket/log.js b/frontend/src/api/appTemplateMarket/log.js index 3a14b96f80..a652d53b38 100644 --- a/frontend/src/api/appTemplateMarket/log.js +++ b/frontend/src/api/appTemplateMarket/log.js @@ -11,7 +11,7 @@ export function logGrid(page, size, data) { export function opTypes() { return request({ - url: '/api/log/opTypes', + url: '/app/log/opTypes', method: 'post', loading: true }) @@ -19,10 +19,19 @@ export function opTypes() { export function exportExcel(data) { return request({ - url: '/api/log/export', + url: '/app/log/export', method: 'post', loading: true, responseType: 'blob', data }) } + +export function deleteLogAndResource(data) { + return request({ + url: '/app/log/deleteLog', + method: 'post', + data, + loading: true + }) +} diff --git a/frontend/src/api/panel/panel.js b/frontend/src/api/panel/panel.js index 3a74f445a8..f892134606 100644 --- a/frontend/src/api/panel/panel.js +++ b/frontend/src/api/panel/panel.js @@ -313,7 +313,33 @@ export function appApply(data) { return request({ url: 'panel/group/appApply', method: 'post', - loading: true, + loading: false, data }) } + +export function appEdit(data) { + return request({ + url: 'panel/group/appEdit', + method: 'post', + loading: false, + data + }) +} + +export function editApply(data) { + return request({ + url: 'panel/group/appApply', + method: 'post', + loading: false, + data + }) +} + +export function findOneWithParent(panelId) { + return request({ + url: 'panel/group/findOneWithParent/' + panelId, + method: 'get', + loading: false + }) +} diff --git a/frontend/src/api/user.js b/frontend/src/api/user.js index 6899c6726d..ac4b3154b0 100644 --- a/frontend/src/api/user.js +++ b/frontend/src/api/user.js @@ -18,14 +18,16 @@ export function getInfo(token) { export function logout() { return request({ url: '/api/auth/logout', - method: 'post' + method: 'post', + hideMsg: true }) } export function deLogout() { return request({ url: '/api/auth/deLogout', - method: 'post' + method: 'post', + hideMsg: true }) } @@ -100,6 +102,13 @@ export function casStatus() { }) } +export function casLoginPage() { + return request({ + url: '/cas/loginPage', + method: 'get' + }) +} + export function wecomStatus() { return request({ url: '/api/auth/isOpenWecom', @@ -121,6 +130,13 @@ export function larkStatus() { }) } +export function larksuiteStatus() { + return request({ + url: '/api/auth/isOpenLarksuite', + method: 'post' + }) +} + export function pluginLoaded() { return request({ url: '/api/auth/isPluginLoaded', diff --git a/frontend/src/assets/datasource/pg.jpg b/frontend/src/assets/datasource/pg.jpg index ebcb628b89..cc2106b924 100644 Binary files a/frontend/src/assets/datasource/pg.jpg and b/frontend/src/assets/datasource/pg.jpg differ diff --git a/frontend/src/components/AsyncComponent/index.vue b/frontend/src/components/AsyncComponent/index.vue index 485e46a61e..553188bcd8 100644 --- a/frontend/src/components/AsyncComponent/index.vue +++ b/frontend/src/components/AsyncComponent/index.vue @@ -52,7 +52,8 @@ export default { if (res) { const Fn = Function const dynamicCode = res.data || res - this.mode = new Fn(`return ${dynamicCode}`)() + const component = new Fn(`return ${dynamicCode}`)() + this.mode = component.default || component } } } diff --git a/frontend/src/components/DeDrag/MoveInShadow.vue b/frontend/src/components/DeDrag/MoveInShadow.vue deleted file mode 100644 index 68a8317fe9..0000000000 --- a/frontend/src/components/DeDrag/MoveInShadow.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - - diff --git a/frontend/src/components/DeDrag/index.vue b/frontend/src/components/DeDrag/index.vue index ffd15ea2ae..2d38230a34 100644 --- a/frontend/src/components/DeDrag/index.vue +++ b/frontend/src/components/DeDrag/index.vue @@ -22,6 +22,7 @@ @mouseleave="leave" >
{ this.$store.commit('setCurComponent', { component: this.element, index: this.index }) + this.curComponent.optStatus.dragging = true + this.$store.commit('clearTabMoveInfo') }) }, // 元素按下 @@ -905,8 +940,9 @@ export default { } } else { return { - minLeft: this.left % this.grid[0], - maxLeft: Math.floor((this.parentWidth - this.width - this.left) / this.grid[0]) * this.grid[0] + this.left, + // X方向余量向左右偏移this.parentWidthOffset 个余量,可以做到类型像移出canvas的效果,适配Tab的canvas组件 + minLeft: this.left % this.grid[0] - this.parentWidthOffset, + maxLeft: (Math.floor((this.parentWidth - this.width - this.left) / this.grid[0]) * this.grid[0] + this.left) + this.parentWidthOffset, minRight: this.right % this.grid[0], maxRight: Math.floor((this.parentWidth - this.width - this.right) / this.grid[0]) * this.grid[0] + this.right, minTop: this.top % this.grid[1], @@ -1106,7 +1142,8 @@ export default { const bounds = this.bounds const mouseClickPosition = this.mouseClickPosition // 水平移动 - const tmpDeltaX = axis && axis !== 'y' ? mouseClickPosition.mouseX - (e.touches ? e.touches[0].pageX : e.pageX) : 0 + const mX = e.touches ? e.touches[0].pageX : e.pageX + const tmpDeltaX = axis && axis !== 'y' ? mouseClickPosition.mouseX - mX : 0 // 垂直移动 const mY = e.touches ? e.touches[0].pageY : e.pageY const tmpDeltaY = axis && axis !== 'x' ? mouseClickPosition.mouseY - mY : 0 @@ -1132,7 +1169,15 @@ export default { if (this.element.auxiliaryMatrix) { this.$emit('onDragging', e, this.element) } - + if ((-left > (this.parentWidthOffset - 10) || left - bounds.maxRight > (this.parentWidthOffset - 10)) && this.canvasId !== 'canvas-main') { + this.contentDisplay = false + this.$store.commit('setMousePointShadowMap', { mouseX: mX, mouseY: mY, width: this.width, height: this.height }) + this.$store.commit('setTabMoveOutComponentId', this.element.id) + } else { + this.$store.commit('setTabMoveOutComponentId', null) + this.contentDisplay = true + } + await this.tabMoveInCheck() // private 记录当前样式 this.recordCurStyle() }, @@ -1365,9 +1410,6 @@ export default { this.resizing = false this.conflictCheck() this.$emit('refLineParams', refLine) - // this.$emit('resizestop', this.left, this.top, this.width, this.height) - // private - // this.$emit('resizestop') } if (this.dragging) { this.dragging = false @@ -1384,9 +1426,13 @@ export default { // 如果辅助设计 需要最后调整矩阵 if (this.element.auxiliaryMatrix) { - // this.recordMatrixCurStyle() + const historyTabMoveInActiveId = this.tabMoveInActiveId + const historyTabMoveOutComponentId = this.tabMoveOutComponentId setTimeout(() => { - this.recordMatrixCurShadowStyle() + // 移入组件移入Tab时 不需要计算根据阴影面积重置大小 + if (!historyTabMoveInActiveId && !historyTabMoveOutComponentId) { + this.recordMatrixCurShadowStyle(this.curCanvasScaleSelf) + } this.hasMove && this.$store.commit('recordSnapshot', 'handleUp') // 记录snapshot后 移动已记录设置为false this.hasMove = false @@ -1404,14 +1450,77 @@ export default { // 挤占式画布设计 handleUp this.element.auxiliaryMatrix && this.$emit('onHandleUp', e) + this.componentCanvasChange() + // 还原Tab画布状态 + this.$store.commit('clearTabMoveInfo') + // 松开鼠标时 如果当前内容被隐藏,则需要进行显示出来 + if (!this.contentDisplay) { + this.contentDisplay = true + } }, - // 新增方法 ↓↓↓ - // 设置属性 + // 如果Tab移入状态还是Active 状态 则将当前的组件 放置到tab页中 + componentCanvasChange() { + // 主画布移入Tab画布 + if (this.tabMoveInActiveId) { + // 从当前画布移除 + this.$emit('amRemoveItem') + this.element.canvasPid = this.element.canvasId + // Tab内部的画布ID 为 tab组件id + '-' + tabActiveName + const targetCanvasId = this.tabMoveInActiveId + '-' + this.tabActiveTabNameMap[this.tabMoveInActiveId] + const targetCanvasScale = this.curCanvasScaleMap[targetCanvasId] + if (this.element.auxiliaryMatrix) { + this.element.x = 1 + this.element.y = 108 + this.element.sizex = Math.round(this.element.sizex * this.curCanvasScaleSelf.matrixStyleWidth / targetCanvasScale.matrixStyleWidth) + this.element.sizey = Math.round(this.element.sizey * this.curCanvasScaleSelf.matrixStyleHeight / targetCanvasScale.matrixStyleHeight) + this.element.style.width = this.element.sizex * targetCanvasScale.matrixStyleOriginWidth + this.element.style.height = this.element.sizey * targetCanvasScale.matrixStyleOriginHeight + this.element.style.left = 0 + this.element.style.top = (this.element.y - 1) * targetCanvasScale.matrixStyleOriginHeight + } else { + this.element.style.left = 0 + this.element.style.top = 0 + this.element.style.width = this.element.style.width * this.curCanvasScaleSelf.matrixStyleWidth / targetCanvasScale.matrixStyleWidth + this.element.style.height = this.element.style.height * this.curCanvasScaleSelf.matrixStyleHeight / targetCanvasScale.matrixStyleHeight + } + this.element.canvasId = targetCanvasId + } + // Tab 画布 移入主画布 + if (this.tabMoveOutComponentId) { + // 从当前画布移除 + this.$emit('amRemoveItem') + this.element.canvasPid = 0 + this.element.canvasId = 'canvas-main' + // Tab内部的画布ID 为 tab组件id + '-' + tabActiveName + const targetCanvasScale = this.curCanvasScaleMap['canvas-main'] + // 按照阴影位置定位 + this.element.style.left = (this.mousePointShadowMap.mouseX - (this.mousePointShadowMap.width)) / targetCanvasScale.scalePointWidth + this.element.style.top = (this.mousePointShadowMap.mouseY - (this.mousePointShadowMap.height / 2)) / targetCanvasScale.scalePointHeight + this.element.style.width = this.mousePointShadowMap.width / targetCanvasScale.scalePointWidth + this.element.style.height = this.mousePointShadowMap.height / targetCanvasScale.scalePointHeight + + if (this.element.auxiliaryMatrix) { + this.element.x = Math.round(this.element.style.left / targetCanvasScale.matrixStyleOriginWidth) + 1 + this.element.y = Math.round(this.element.style.top / targetCanvasScale.matrixStyleOriginHeight) + 1 + this.element.sizex = Math.round(this.element.style.width / targetCanvasScale.matrixStyleOriginWidth) + this.element.sizey = Math.round(this.element.style.height / targetCanvasScale.matrixStyleOriginHeight) + this.recordMatrixCurShadowStyle(targetCanvasScale) + } + } + }, + + // 设置属性(属性跟随所属canvas component类型 要做出改变) settingAttribute() { // 设置冲突检测 this.$el.setAttribute('data-is-check', `${this.isConflictCheck}`) // 设置对齐元素 this.$el.setAttribute('data-is-snap', `${this.snap}`) + // 设置Tab移入检测 + this.$el.setAttribute('tab-is-check', `${this.isTabMoveCheck}`) + // 设置组件类型 + this.$el.setAttribute('component-type', `${this.element.component}`) + // 设置组件ID + this.$el.setAttribute('component-id', `${this.element.id}`) }, // 冲突检测 conflictCheck() { @@ -1688,10 +1797,10 @@ export default { // 记录当前样式 矩阵处理 recordMatrixCurStyle() { - const left = Math.round(this.left / this.curCanvasScale.matrixStyleWidth) * this.curCanvasScale.matrixStyleWidth - const top = Math.round(this.top / this.curCanvasScale.matrixStyleHeight) * this.curCanvasScale.matrixStyleHeight - const width = Math.round(this.width / this.curCanvasScale.matrixStyleWidth) * this.curCanvasScale.matrixStyleWidth - const height = Math.round(this.height / this.curCanvasScale.matrixStyleHeight) * this.curCanvasScale.matrixStyleHeight + const left = Math.round(this.left / this.curCanvasScaleSelf.matrixStyleWidth) * this.curCanvasScaleSelf.matrixStyleWidth + const top = Math.round(this.top / this.curCanvasScaleSelf.matrixStyleHeight) * this.curCanvasScaleSelf.matrixStyleHeight + const width = Math.round(this.width / this.curCanvasScaleSelf.matrixStyleWidth) * this.curCanvasScaleSelf.matrixStyleWidth + const height = Math.round(this.height / this.curCanvasScaleSelf.matrixStyleHeight) * this.curCanvasScaleSelf.matrixStyleHeight const style = { ...this.defaultStyle } @@ -1705,23 +1814,13 @@ export default { // resize self.$emit('resizeView') - // const self = this - // setTimeout(function() { - // self.$emit('resizeView') - // }, 200) }, // 记录当前样式 跟随阴影位置 矩阵处理 - recordMatrixCurShadowStyle() { - const left = (this.element.x - 1) * this.curCanvasScale.matrixStyleWidth - const top = (this.element.y - 1) * this.curCanvasScale.matrixStyleHeight - const width = this.element.sizex * this.curCanvasScale.matrixStyleWidth - const height = this.element.sizey * this.curCanvasScale.matrixStyleHeight - // const t1 = Math.round(this.width / this.curCanvasScale.matrixStyleWidth) - // const left = Math.round(this.left / this.curCanvasScale.matrixStyleWidth) * this.curCanvasScale.matrixStyleWidth - // const top = Math.round(this.top / this.curCanvasScale.matrixStyleHeight) * this.curCanvasScale.matrixStyleHeight - // const width = t1 * this.curCanvasScale.matrixStyleWidth - // const height = Math.round(this.height / this.curCanvasScale.matrixStyleHeight) * this.curCanvasScale.matrixStyleHeight - + recordMatrixCurShadowStyle(scaleSelf) { + const left = (this.element.x - 1) * scaleSelf.matrixStyleWidth + const top = (this.element.y - 1) * scaleSelf.matrixStyleHeight + const width = this.element.sizex * scaleSelf.matrixStyleWidth + const height = this.element.sizey * scaleSelf.matrixStyleHeight const style = { ...this.defaultStyle } @@ -1730,16 +1829,10 @@ export default { style.width = width style.height = height style.rotate = this.rotate - // this.hasMove = true - this.$store.commit('setShapeStyle', style) - // resize const self = this self.$emit('resizeView') - // setTimeout(function() { - // self.$emit('resizeView') - // }, 200) }, mountedFunction() { // private 冲突检测 和水平设计值保持一致 @@ -1821,6 +1914,71 @@ export default { // 跳转设置 boardSet() { this.$emit('boardSet') + }, + // tab移入检测 + async tabMoveInCheck() { + const top = this.top + const left = this.left + const width = this.width + const height = this.height + // tab 移入检测开启 tab组件不能相互移入另一个tab组件 + if (this.isTabMoveCheck && this.element.type !== 'de-tabs') { + const nodes = this.$el.parentNode.childNodes // 获取当前父节点下所有子节点 + for (const item of nodes) { + if ( + item.className !== undefined && + !item.className.split(' ').includes(this.classNameActive) && + item.getAttribute('tab-is-check') !== null && + item.getAttribute('tab-is-check') !== 'false' && + item.getAttribute('component-type') === 'de-tabs' + ) { + const tw = item.offsetWidth + const th = item.offsetHeight + // 正则获取left与right + const [tl, tt] = this.formatTransformVal(item.style.transform) + // 碰撞有效区域检查 + const collisionT = tt + this.tabMoveInYOffset + const collisionL = tl + (this.curCanvasScaleSelf.matrixStyleWidth / 2) - width + const collisionW = tw + 2 * width - this.curCanvasScaleSelf.matrixStyleWidth + const collisionH = th + height - this.tabMoveInYOffset + + // 左上角靠近左上角区域 + const tfAndTf = collisionT <= top && collisionL <= left + // 左下角靠近左下角区域 + const bfAndBf = (collisionT + collisionH) >= (top + height) && collisionL <= left + // 右上角靠近右上角区域 + const trAndTr = collisionT <= top && (collisionL + collisionW) >= (left + width) + // 右下角靠近右下角区域 + const brAndBr = (collisionT + collisionH) >= (top + height) && (collisionL + collisionW) >= (left + width) + if (tfAndTf && bfAndBf && trAndTr && brAndBr) { + this.$store.commit('setTabCollisionActiveId', item.getAttribute('component-id')) + } else if (this.tabCollisionActiveId === item.getAttribute('component-id')) { + this.$store.commit('setTabCollisionActiveId', null) + } + + // 移入有效区域检查 + // 碰撞有效区域检查 + const activeT = tt + this.tabMoveInYOffset + const activeL = tl + (this.curCanvasScaleSelf.matrixStyleWidth * 10) - width + const activeW = tw + 2 * width - this.curCanvasScaleSelf.matrixStyleWidth * 20 + const activeH = th + height - 2 * this.tabMoveInYOffset + + // 左上角靠近左上角区域 + const activeTfAndTf = activeT <= top && activeL <= left + // 左下角靠近左下角区域 + const activeBfAndBf = (activeT + activeH) >= (top + height) && activeL <= left + // 右上角靠近右上角区域 + const activeTrAndTr = activeT <= top && (activeL + activeW) >= (left + width) + // 右下角靠近右下角区域 + const activeBrAndBr = (activeT + activeH) >= (top + height) && (activeL + activeW) >= (left + width) + if (activeTfAndTf && activeBfAndBf && activeTrAndTr && activeBrAndBr) { + this.$store.commit('setTabMoveInActiveId', item.getAttribute('component-id')) + } else if (this.tabMoveInActiveId === item.getAttribute('component-id')) { + this.$store.commit('setTabMoveInActiveId', null) + } + } + } + } } } diff --git a/frontend/src/components/DeDrag/pointShadow.vue b/frontend/src/components/DeDrag/pointShadow.vue new file mode 100644 index 0000000000..569c968315 --- /dev/null +++ b/frontend/src/components/DeDrag/pointShadow.vue @@ -0,0 +1,116 @@ + + + + diff --git a/frontend/src/components/DeDrag/shadow.vue b/frontend/src/components/DeDrag/shadow.vue index 9550c94f2f..a90e29a698 100644 --- a/frontend/src/components/DeDrag/shadow.vue +++ b/frontend/src/components/DeDrag/shadow.vue @@ -10,8 +10,18 @@ import { mapState } from 'vuex' export default { replace: true, - name: 'ShadowDe', + // eslint-disable-next-line + name: 'Shadow', + props: { + canvasId: { + type: String, + required: true + } + }, computed: { + curCanvasScaleSelf() { + return this.curCanvasScaleMap[this.canvasId] + }, styleInfo() { let left = 0 let top = 0 @@ -21,11 +31,11 @@ export default { if (this.dragComponentInfo) { // 组件移入 if (this.dragComponentInfo.auxiliaryMatrix) { - left = (this.dragComponentInfo.x - 1) * this.curCanvasScale.matrixStyleWidth - top = (this.dragComponentInfo.y - 1) * this.curCanvasScale.matrixStyleHeight + left = (this.dragComponentInfo.x - 1) * this.curCanvasScaleSelf.matrixStyleWidth + top = (this.dragComponentInfo.y - 1) * this.curCanvasScaleSelf.matrixStyleHeight - width = this.dragComponentInfo.sizex * this.curCanvasScale.matrixStyleWidth - height = this.dragComponentInfo.sizey * this.curCanvasScale.matrixStyleHeight + width = this.dragComponentInfo.sizex * this.curCanvasScaleSelf.matrixStyleWidth + height = this.dragComponentInfo.sizey * this.curCanvasScaleSelf.matrixStyleHeight transition = 0.1 } else { left = this.dragComponentInfo.shadowStyle.x @@ -34,14 +44,10 @@ export default { height = this.dragComponentInfo.style.height } } else { - // temp 临时测试 - // left = this.curComponent.style.left * this.curCanvasScale.scaleWidth / 100 - // top = this.curComponent.style.top * this.curCanvasScale.scaleHeight / 100 - left = (this.curComponent.x - 1) * this.curCanvasScale.matrixStyleWidth - top = (this.curComponent.y - 1) * this.curCanvasScale.matrixStyleHeight - - width = this.curComponent.style.width * this.curCanvasScale.scalePointWidth - height = this.curComponent.style.height * this.curCanvasScale.scalePointHeight + left = (this.curComponent.x - 1) * this.curCanvasScaleSelf.matrixStyleWidth + top = (this.curComponent.y - 1) * this.curCanvasScaleSelf.matrixStyleHeight + width = this.curComponent.style.width * this.curCanvasScaleSelf.scalePointWidth + height = this.curComponent.style.height * this.curCanvasScaleSelf.scalePointHeight if (this.curComponent.optStatus.dragging) { transition = 0.1 } @@ -70,13 +76,13 @@ export default { return this.$store.state.dragComponentInfo }, canvasWidth() { - const scaleWidth = this.curCanvasScale.scaleWidth / 100 + const scaleWidth = this.curCanvasScaleSelf.scaleWidth / 100 return this.canvasStyleData.width * scaleWidth }, ...mapState([ 'curComponent', 'editor', - 'curCanvasScale', + 'curCanvasScaleMap', 'canvasStyleData', 'linkageSettingStatus' ]) @@ -89,10 +95,10 @@ export default { this.dragComponentInfo.shadowStyle.y = this.scaleH(y) }, scaleH(h) { - return h / this.curCanvasScale.scalePointHeight + return h / this.curCanvasScaleSelf.scalePointHeight }, scaleW(w) { - return w / this.curCanvasScale.scalePointWidth + return w / this.curCanvasScaleSelf.scalePointWidth } } diff --git a/frontend/src/components/GradientColorSelector/base.js b/frontend/src/components/GradientColorSelector/base.js index 557047a9a5..bf88a65f75 100644 --- a/frontend/src/components/GradientColorSelector/base.js +++ b/frontend/src/components/GradientColorSelector/base.js @@ -86,7 +86,7 @@ export const colorCases = [ export const gradientColorCases = [ { name: '渐变色1', - value: 'gradient1', + value: 'gradient1_continuous_gradient', colors: [ ['rgba(144,202,249,0.5)', 'rgba(1,87,155,0.9)'], ['rgba(127,222,234,1)', 'rgba(0,77,65,1)'], @@ -101,3 +101,72 @@ export const gradientColorCases = [ export const isGradientValue = value => { return value && gradientColorCases.some(item => item.value === value) } + +export const getColorType = value => { + if (value.endsWith('_split_gradient')) { + return 'split_gradient' + } + const cloneColorCases = JSON.parse(JSON.stringify(colorCases)) + if (cloneColorCases.some(item => item.value === value)) { + return 'simple' + } + return 'gradient' +} + +export const getMapColorCases = () => { + const cloneColorCases = JSON.parse(JSON.stringify(colorCases)) + return cloneColorCases.map(colorItem => { + const curColors = colorItem.colors + const len = curColors.length + const start = curColors[0] + const end = curColors[len - 1] + const itemResult = { + name: colorItem.name, + value: colorItem.value + '_split_gradient', + baseColors: [start, end], + colors: stepsColor(start, end, 9, 1) + } + return itemResult + }) +} + +export function stepsColor(start, end, steps, gamma) { + var i; var j; var ms; var me; var output = []; var so = [] + gamma = gamma || 1 + var normalize = function(channel) { + return Math.pow(channel / 255, gamma) + } + start = parseColor(start).map(normalize) + end = parseColor(end).map(normalize) + for (i = 0; i < steps; i++) { + ms = (steps - 1) === 0 ? 0 : (i / (steps - 1)) + me = 1 - ms + for (j = 0; j < 3; j++) { + so[j] = pad( + Math.round( + Math.pow(start[j] * me + end[j] * ms, 1 / gamma) * 255 + ).toString(16) + ) + } + output.push('#' + so.join('')) + } + function parseColor(hexStr) { + return hexStr.length === 4 + ? hexStr + .substr(1) + .split('') + .map(function(s) { + return 0x11 * parseInt(s, 16) + }) + : [hexStr.substr(1, 2), hexStr.substr(3, 2), hexStr.substr(5, 2)].map( + function(s) { + return parseInt(s, 16) + } + ) + } + function pad(s) { + return s.length === 1 ? '0' + s : s + } + return output +} + diff --git a/frontend/src/components/GradientColorSelector/index.vue b/frontend/src/components/GradientColorSelector/index.vue index 48da711b0d..8bffc71dab 100644 --- a/frontend/src/components/GradientColorSelector/index.vue +++ b/frontend/src/components/GradientColorSelector/index.vue @@ -20,7 +20,7 @@ @@ -38,7 +38,7 @@
@@ -47,7 +47,7 @@ @tab-click="handleClick" > - + + @@ -132,7 +139,7 @@ + + diff --git a/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue b/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue index 030ca7e218..50407a9c93 100644 --- a/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue +++ b/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue @@ -41,12 +41,14 @@ :in-screen="inScreen" :edit-mode="'preview'" :h="config.style.height" + :canvas-id="canvasId" /> - - +
+ + + + + + + + + + + + + + + + + + + +
+ + + + + diff --git a/frontend/src/components/canvas/components/Editor/EditBar.vue b/frontend/src/components/canvas/components/Editor/EditBar.vue index e85008ec54..e969bf1bfc 100644 --- a/frontend/src/components/canvas/components/Editor/EditBar.vue +++ b/frontend/src/components/canvas/components/Editor/EditBar.vue @@ -141,6 +141,38 @@
+ + + + + + + + + + @@ -151,18 +183,24 @@ import SettingMenu from '@/components/canvas/components/Editor/SettingMenu' import LinkageField from '@/components/canvas/components/Editor/LinkageField' import toast from '@/components/canvas/utils/toast' import FieldsList from '@/components/canvas/components/Editor/fieldsList' +import LinkJumpSet from '@/views/panel/LinkJumpSet' +import Background from '@/views/background/index' export default { - components: { FieldsList, SettingMenu, LinkageField }, + components: { Background, LinkJumpSet, FieldsList, SettingMenu, LinkageField }, props: { + canvasId: { + type: String, + required: true + }, terminal: { type: String, default: 'pc' }, sourceElement: { type: Object, - required: true + default: () => {} }, element: { type: Object, @@ -191,6 +229,9 @@ export default { }, data() { return { + boardSetVisible: false, + linkJumpSetVisible: false, + linkJumpSetViewId: null, curFields: [], multiplexingCheckModel: false, barWidth: 24, @@ -228,8 +269,8 @@ export default { }, showEditPosition() { if (this.activeModel === 'edit' && !this.linkageAreaShow && !this.batchOptAreaShow) { - const toRight = (this.canvasStyleData.width - this.element.style.left - this.element.style.width) * this.curCanvasScale.scalePointWidth - const toLeft = this.element.style.left * this.curCanvasScale.scalePointWidth + const toRight = (this.canvasStyleData.width - this.element.style.left - this.element.style.width) * this.curCanvasScaleSelf.scalePointWidth + const toLeft = this.element.style.left * this.curCanvasScaleSelf.scalePointWidth if (this.barWidth < toRight) { return 'bar-main-right' } else if (this.barWidth > toRight && this.barWidth > toLeft) { @@ -278,6 +319,9 @@ export default { miniWidth() { return this.mobileLayoutStatus ? 1 : 4 }, + curCanvasScaleSelf() { + return this.curCanvasScaleMap[this.canvasId] + }, ...mapState([ 'menuTop', 'menuLeft', @@ -288,7 +332,7 @@ export default { 'linkageSettingStatus', 'targetLinkageInfo', 'curLinkageView', - 'curCanvasScale', + 'curCanvasScaleMap', 'batchOptStatus', 'mobileLayoutStatus', 'curBatchOptComponents', @@ -302,6 +346,16 @@ export default { } }, methods: { + backgroundSetClose() { + this.boardSetVisible = false + }, + linkJumpSet() { + this.linkJumpSetViewId = this.element.propValue.viewId + this.linkJumpSetVisible = true + }, + closeJumpSetDialog() { + this.linkJumpSetVisible = false + }, fieldsAreaDown(e) { // ignore e.preventDefault() @@ -347,10 +401,10 @@ export default { this.curComponent.auxiliaryMatrix = false this.$emit('amRemoveItem') } else { - this.curComponent.x = Math.round(this.curComponent.style.left / this.curCanvasScale.matrixStyleOriginWidth) + 1 - this.curComponent.y = Math.round(this.curComponent.style.top / this.curCanvasScale.matrixStyleOriginHeight) + 1 - this.curComponent.sizex = Math.round(this.curComponent.style.width / this.curCanvasScale.matrixStyleOriginWidth) - this.curComponent.sizey = Math.round(this.curComponent.style.height / this.curCanvasScale.matrixStyleOriginHeight) + this.curComponent.x = Math.round(this.curComponent.style.left / this.curCanvasScaleSelf.matrixStyleOriginWidth) + 1 + this.curComponent.y = Math.round(this.curComponent.style.top / this.curCanvasScaleSelf.matrixStyleOriginHeight) + 1 + this.curComponent.sizex = Math.round(this.curComponent.style.width / this.curCanvasScaleSelf.matrixStyleOriginWidth) + this.curComponent.sizey = Math.round(this.curComponent.style.height / this.curCanvasScaleSelf.matrixStyleOriginHeight) this.curComponent.sizey = this.curComponent.sizey > this.miniHeight ? this.curComponent.sizey : this.miniHeight this.curComponent.sizex = this.curComponent.sizex > this.miniWidth ? this.curComponent.sizex : this.miniWidth this.curComponent.auxiliaryMatrix = true @@ -364,10 +418,10 @@ export default { }, // 记录当前样式 跟随阴影位置 矩阵处理 recordMatrixCurShadowStyle() { - const left = (this.curComponent.x - 1) * this.curCanvasScale.matrixStyleWidth - const top = (this.curComponent.y - 1) * this.curCanvasScale.matrixStyleHeight - const width = this.curComponent.sizex * this.curCanvasScale.matrixStyleWidth - const height = this.curComponent.sizey * this.curCanvasScale.matrixStyleHeight + const left = (this.curComponent.x - 1) * this.curCanvasScaleSelf.matrixStyleWidth + const top = (this.curComponent.y - 1) * this.curCanvasScaleSelf.matrixStyleHeight + const width = this.curComponent.sizex * this.curCanvasScaleSelf.matrixStyleWidth + const height = this.curComponent.sizey * this.curCanvasScaleSelf.matrixStyleHeight const style = { left: left, top: top, @@ -409,9 +463,6 @@ export default { }) bus.$emit('clear_panel_linkage', { viewId: this.element.propValue.viewId }) }, - linkJumpSet() { - this.$emit('linkJumpSet') - }, goFile() { this.$refs.files.click() }, @@ -435,7 +486,7 @@ export default { reader.readAsDataURL(file) }, boardSet() { - this.$emit('boardSet') + this.boardSetVisible = true }, batchOptChange(val) { if (val) { diff --git a/frontend/src/components/canvas/components/Editor/PGrid.vue b/frontend/src/components/canvas/components/Editor/PGrid.vue index 8a1e8756f0..f1fba8b94c 100644 --- a/frontend/src/components/canvas/components/Editor/PGrid.vue +++ b/frontend/src/components/canvas/components/Editor/PGrid.vue @@ -1,20 +1,17 @@ - diff --git a/frontend/src/views/panel/appTemplateMarket/component/AppMarketPreview.vue b/frontend/src/views/panel/appTemplateMarket/component/AppMarketPreview.vue new file mode 100644 index 0000000000..6b66c30e74 --- /dev/null +++ b/frontend/src/views/panel/appTemplateMarket/component/AppMarketPreview.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/frontend/src/views/panel/appTemplateMarket/index.vue b/frontend/src/views/panel/appTemplateMarket/index.vue index d259e822d7..de50d714fd 100644 --- a/frontend/src/views/panel/appTemplateMarket/index.vue +++ b/frontend/src/views/panel/appTemplateMarket/index.vue @@ -1,12 +1,11 @@ @@ -139,16 +120,18 @@ import { searchAppTemplate } from '@/api/appTemplateMarket' import { groupTree, panelSave } from '@/api/panel/panel' import { DEFAULT_COMMON_CANVAS_STYLE_STRING } from '@/views/panel/panel' -import MarketPreview from '@/views/panel/appTemplateMarket/component/MarketPreview' import elementResizeDetectorMaker from 'element-resize-detector' -import AppTemplateItem from '@/views/panel/appTemplateMarket/component/AppTemplateItem' import AppTemplateLog from '@/views/panel/appTemplateMarket/log' +import AppTemplateContent from '@/views/panel/appTemplate/AppTemplateContent' +import AppMarketPreview from '@/views/panel/appTemplateMarket/component/AppMarketPreview' +import AppTemplateApply from '@/views/panel/appTemplate/component/AppTemplateApply' export default { name: 'AppTemplateMarket', - components: { AppTemplateLog, AppTemplateItem, MarketPreview }, + components: { AppTemplateApply, AppMarketPreview, AppTemplateContent, AppTemplateLog }, data() { return { + previewItem: null, hasResult: true, templateMiniWidth: 330, templateCurWidth: 310, @@ -194,11 +177,8 @@ export default { } } }, - computed: { - - }, - watch: { - }, + computed: {}, + watch: {}, mounted() { this.initMarketTemplate() this.getGroupTree() @@ -215,6 +195,24 @@ export default { }) }, methods: { + applyNew(item) { + const datasourceInfo = JSON.parse(item.datasourceInfo)[0] + const param = { + datasourceType: datasourceInfo.type, + appTemplateId: item.id, + appTemplateName: item.name, + panelName: item.name, + datasetGroupName: item.name + } + this.$refs.templateApply.init(param) + }, + appApply() { + this.applyNew(this.previewItem) + }, + previewApp(item) { + this.previewModel = true + this.previewItem = item + }, initMarketTemplate() { searchAppTemplate({ nodeType: 'folder' }).then(rsp => { this.currentAppShowList = rsp.data @@ -280,109 +278,120 @@ export default { diff --git a/frontend/src/views/panel/appTemplateMarket/log/index.vue b/frontend/src/views/panel/appTemplateMarket/log/index.vue index 5b0dbc0b45..fb000a9004 100644 --- a/frontend/src/views/panel/appTemplateMarket/log/index.vue +++ b/frontend/src/views/panel/appTemplateMarket/log/index.vue @@ -10,7 +10,8 @@ type="primary" icon="el-icon-plus" @click="applyNew()" - >{{ $t('commons.create') }} + >{{ $t('commons.create') }} +   {{ $t("user.filter") - }} + >{{ + $t('user.filter') + }} + @@ -45,7 +48,7 @@ class="filter-texts" > {{ paginationConfig.total }} - {{ $t("user.result_one") }} + {{ $t('user.result_one') }} {{ $t("user.clear_filter") }} + >{{ $t('user.clear_filter') }} +
+ :label="$t('app_template.panel')" + > + + {{ scope.row.applyTime | timestampFormatDate }} + + +
@@ -132,6 +176,39 @@ @search="filterDraw" /> + + + + + + + + + {{ $t('app_template.log_resource_delete_tips') }} + + + {{ $t('commons.cancel') }} + {{ $t('commons.confirm') }} + + @@ -144,10 +221,13 @@ import { addOrder, formatOrders } from '@/utils/index' -import { logGrid } from '@/api/appTemplateMarket/log' +import { deleteLogAndResource, logGrid } from '@/api/appTemplateMarket/log' +import { findOneWithParent } from '@/api/panel/panel' +import AppTemplateApply from '@/views/panel/appTemplate/component/AppTemplateApply' + export default { name: 'AppTemplateLog', - components: { GridTable, filterUser }, + components: { AppTemplateApply, GridTable, filterUser }, mixins: [keyEnter], props: { appTemplateId: { @@ -162,6 +242,12 @@ export default { }, data() { return { + optShow: false, + deleteConfirmDialog: false, + deleteItemInfo: { + deleteResource: false + }, + operateWidth: 168, columns: [], paginationConfig: { currentPage: 1, @@ -194,6 +280,56 @@ export default { this.resizeObserver() }, methods: { + closeDel() { + this.deleteItemInfo = { + deleteResource: false + } + this.deleteConfirmDialog = false + }, + confirmDel() { + deleteLogAndResource(this.deleteItemInfo).then(() => { + this.closeDel() + this.search() + }) + }, + closeDraw() { + this.search() + }, + editApply(item) { + const param = { + datasourceType: item.datasourceType, + logId: item.id, + panelId: item.panelId, + panelGroupPid: item.panelGroupPid, + datasourceId: item.datasourceId, + datasetGroupPid: item.datasetGroupPid, + datasetGroupId: item.datasetGroupId, + datasetGroupName: item.datasetGroupName, + panelName: item.panelName, + datasourcePrivileges: item.datasourcePrivileges, + panelPrivileges: item.panelPrivileges, + datasetPrivileges: item.datasetPrivileges + } + this.$refs.templateEditApply.init(param) + }, + goToDatasource(row) { + + }, + goPanel(row) { + findOneWithParent(row.panelId).then(rsp => { + this.$router.push({ name: 'panel', params: rsp.data }) + }) + }, + edit() { + + }, + del(item) { + this.deleteItemInfo = { + ...item, + deleteResource: false + } + this.deleteConfirmDialog = true + }, applyNew() { this.$emit('applyNew') }, @@ -289,6 +425,11 @@ export default { logGrid(currentPage, pageSize, param).then((response) => { this.data = response.data.listObject this.paginationConfig.total = response.data.itemCount + const _this = this + _this.optShow = false + this.$nextTick(() => { + _this.optShow = true + }) }) } } @@ -302,4 +443,13 @@ export default { .table-container-filter { height: calc(100% - 110px); } + +.link-span { + color: #3370FF; + cursor: pointer; + + &:hover { + text-decoration: underline; + } +} diff --git a/frontend/src/views/panel/edit/ComponentWait.vue b/frontend/src/views/panel/edit/ComponentWait.vue index cc7ace5ece..3434a4b07a 100644 --- a/frontend/src/views/panel/edit/ComponentWait.vue +++ b/frontend/src/views/panel/edit/ComponentWait.vue @@ -6,7 +6,7 @@
- +
-
- - - -
+ + @@ -215,15 +205,17 @@ class="this_mobile_canvas_main" :style="mobileCanvasStyle" > - + + + @@ -382,13 +374,6 @@ @click="e => {e.target.value = '';}" @change="handleFileChange" > - - - {{ $t('panel.no') }} + >{{ $t('panel.no') }} + {{ $t('panel.yes') }} + >{{ $t('panel.yes') }} + + + @@ -491,8 +485,7 @@ import { addClass, removeClass } from '@/utils' import FilterGroup from '../filter' import SubjectSetting from '../SubjectSetting' import bus from '@/utils/bus' -import Editor from '@/components/canvas/components/Editor/index' -import { deepCopy, imgUrlTrans, matrixBaseChange } from '@/components/canvas/utils/utils' +import { deepCopy, getNowCanvasComponentData, imgUrlTrans, matrixBaseChange } from '@/components/canvas/utils/utils' import componentList, { BASE_MOBILE_STYLE, COMMON_BACKGROUND, @@ -524,7 +517,6 @@ import ButtonResetDialog from '../filter/ButtonResetDialog' import toast from '@/components/canvas/utils/toast' import { commonAttr } from '@/components/canvas/custom-component/component-list' import generateID from '@/components/canvas/utils/generateID' -import TextAttr from '@/components/canvas/components/TextAttr' import ComponentWait from '@/views/panel/edit/ComponentWait' import { deleteEnshrine, saveEnshrine, starStatus } from '@/api/panel/enshrine' import ChartEdit from '@/views/chart/view/ChartEdit' @@ -534,9 +526,14 @@ import Multiplexing from '@/views/panel/ViewSelect/multiplexing' import { listenGlobalKeyDown } from '@/components/canvas/utils/shortcutKey' import { adaptCurThemeCommonStyle } from '@/components/canvas/utils/style' import eventBus from '@/components/canvas/utils/eventBus' +import DeCanvas from '@/components/canvas/DeCanvas' +import TextAttr from '@/components/canvas/components/TextAttr' + export default { name: 'PanelEdit', components: { + TextAttr, + DeCanvas, Multiplexing, ChartStyleBatchSet, OuterParamsSet, @@ -545,7 +542,6 @@ export default { DeContainer, DeAsideContainer, FilterGroup, - Editor, Toolbar, FilterDialog, ButtonDialog, @@ -553,13 +549,13 @@ export default { SubjectSetting, Preview, AssistComponent, - TextAttr, ChartGroup, ChartEdit, CanvasOptBar }, data() { return { + canvasId: 'canvas-main', panelCacheExist: false, viewData: [], multiplexingShow: false, @@ -627,6 +623,9 @@ export default { }, computed: { + mainCanvasComponentData() { + return getNowCanvasComponentData(this.canvasId) + }, // 侧边显示控制 chartEditParam() { if (this.curComponent) { @@ -736,9 +735,12 @@ export default { multiplexingDisabled() { return Object.keys(this.curMultiplexingComponents) === 0 }, + curCanvasScaleSelf() { + return this.curCanvasScaleMap[this.canvasId] + }, ...mapState([ 'curComponent', - 'curCanvasScale', + 'curCanvasScaleMap', 'isClickComponent', 'canvasStyleData', 'curComponentIndex', @@ -796,8 +798,8 @@ export default { }, beforeDestroy() { bus.$off('component-on-drag', this.componentOnDrag) - bus.$off('component-dialog-edit', this.editDialog) - bus.$off('button-dialog-edit', this.editButtonDialog) + // bus.$off('component-dialog-edit', this.editDialog) + // bus.$off('button-dialog-edit', this.editButtonDialog) bus.$off('component-dialog-style', this.componentDialogStyle) bus.$off('previewFullScreenClose', this.previewFullScreenClose) bus.$off('change_panel_right_draw', this.changeRightDrawOpen) @@ -844,7 +846,9 @@ export default { const filterIds = com.options.attrs.filterIds let len = filterIds.length while (len--) { - if (param.componentId === filterIds[len]) { filterIds.splice(len, 1) } + if (param.componentId === filterIds[len]) { + filterIds.splice(len, 1) + } } com.options.attrs.filterIds = filterIds } @@ -864,9 +868,7 @@ export default { } this.rightDrawOpen = param if (this.rightDrawOpen) { - setTimeout(() => { - this.outStyle.width = this.outStyle.width + 0.000001 - }, 0) + this.$refs['canvasMainRef'].restore() } }, init(panelId) { @@ -1014,15 +1016,17 @@ export default { } else { this.currentWidget = ApplicationContext.getService(componentInfo.id) this.currentFilterCom = this.currentWidget.getDrawPanel() + this.currentFilterCom['canvasId'] = 'canvas-main' + this.currentFilterCom['canvasPid'] = '0' if (this.canvasStyleData.auxiliaryMatrix) { this.currentFilterCom.x = this.dropComponentInfo.x this.currentFilterCom.y = this.dropComponentInfo.y this.currentFilterCom.sizex = this.dropComponentInfo.sizex this.currentFilterCom.sizey = this.dropComponentInfo.sizey - this.currentFilterCom.style.left = (this.dragComponentInfo.x - 1) * this.curCanvasScale.matrixStyleOriginWidth - this.currentFilterCom.style.top = (this.dragComponentInfo.y - 1) * this.curCanvasScale.matrixStyleOriginHeight - this.currentFilterCom.style.width = this.dragComponentInfo.sizex * this.curCanvasScale.matrixStyleOriginWidth - this.currentFilterCom.style.height = this.dragComponentInfo.sizey * this.curCanvasScale.matrixStyleOriginHeight + this.currentFilterCom.style.left = (this.dragComponentInfo.x - 1) * this.curCanvasScaleSelf.matrixStyleOriginWidth + this.currentFilterCom.style.top = (this.dragComponentInfo.y - 1) * this.curCanvasScaleSelf.matrixStyleOriginHeight + this.currentFilterCom.style.width = this.dragComponentInfo.sizex * this.curCanvasScaleSelf.matrixStyleOriginWidth + this.currentFilterCom.style.height = this.dragComponentInfo.sizey * this.curCanvasScaleSelf.matrixStyleOriginHeight } else { this.currentFilterCom.style.left = this.dragComponentInfo.shadowStyle.x this.currentFilterCom.style.top = this.dragComponentInfo.shadowStyle.y @@ -1053,10 +1057,10 @@ export default { component.sizex = this.dropComponentInfo.sizex component.sizey = this.dropComponentInfo.sizey - component.style.left = (this.dragComponentInfo.x - 1) * this.curCanvasScale.matrixStyleOriginWidth - component.style.top = (this.dragComponentInfo.y - 1) * this.curCanvasScale.matrixStyleOriginHeight - component.style.width = this.dragComponentInfo.sizex * this.curCanvasScale.matrixStyleOriginWidth - component.style.height = this.dragComponentInfo.sizey * this.curCanvasScale.matrixStyleOriginHeight + component.style.left = (this.dragComponentInfo.x - 1) * this.curCanvasScaleSelf.matrixStyleOriginWidth + component.style.top = (this.dragComponentInfo.y - 1) * this.curCanvasScaleSelf.matrixStyleOriginHeight + component.style.width = this.dragComponentInfo.sizex * this.curCanvasScaleSelf.matrixStyleOriginWidth + component.style.height = this.dragComponentInfo.sizey * this.curCanvasScaleSelf.matrixStyleOriginHeight } else { component.style.top = this.dropComponentInfo.shadowStyle.y component.style.left = this.dropComponentInfo.shadowStyle.x @@ -1065,6 +1069,8 @@ export default { } component.id = newComponentId + component['canvasId'] = 'canvas-main' + component['canvasPid'] = '0' // 新拖入的组件矩阵状态 和仪表板当前的矩阵状态 保持一致 component.auxiliaryMatrix = this.canvasStyleData.auxiliaryMatrix // 统一设置背景信息 @@ -1250,14 +1256,14 @@ export default { }, getPositionX(x) { if (this.canvasStyleData.selfAdaption) { - return x * 100 / this.curCanvasScale.scaleWidth + return x * 100 / this.curCanvasScaleSelf.scaleWidth } else { return x } }, getPositionY(y) { if (this.canvasStyleData.selfAdaption) { - return y * 100 / this.curCanvasScale.scaleHeight + return y * 100 / this.curCanvasScaleSelf.scaleHeight } else { return y } @@ -1288,16 +1294,18 @@ export default { component.auxiliaryMatrix = this.canvasStyleData.auxiliaryMatrix // position = absolution 或导致有偏移 这里中和一下偏移量 if (this.canvasStyleData.auxiliaryMatrix) { - component.style.left = (component.x - 1) * this.curCanvasScale.matrixStyleOriginWidth - component.style.top = (component.y - 1) * this.curCanvasScale.matrixStyleOriginHeight - component.style.width = component.sizex * this.curCanvasScale.matrixStyleOriginWidth - component.style.height = component.sizey * this.curCanvasScale.matrixStyleOriginHeight + component.style.left = (component.x - 1) * this.curCanvasScaleSelf.matrixStyleOriginWidth + component.style.top = (component.y - 1) * this.curCanvasScaleSelf.matrixStyleOriginHeight + component.style.width = component.sizex * this.curCanvasScaleSelf.matrixStyleOriginWidth + component.style.height = component.sizey * this.curCanvasScaleSelf.matrixStyleOriginHeight } else { component.style.left = 0 component.style.top = 0 component.x = 1 component.y = 1 } + component['canvasId'] = 'canvas-main' + component['canvasPid'] = '0' component.id = newComponentId // 统一设置背景信息 component.commonBackground = deepCopy(COMMON_BACKGROUND) @@ -1311,9 +1319,9 @@ export default { // 打开属性栏 bus.$emit('change_panel_right_draw', true) }, - canvasScroll(event) { - this.scrollLeft = event.target.scrollLeft - this.scrollTop = event.target.scrollTop + canvasScroll(scrollInfo) { + this.scrollLeft = scrollInfo.scrollLeft + this.scrollTop = scrollInfo.scrollTop bus.$emit('onScroll') }, destroyTimeMachine() { @@ -1359,7 +1367,6 @@ export default { const touchOffset = 100 const canvasInfoMobile = document.getElementById('canvasInfoMobile') // 获取子盒子(高度肯定比父盒子大) - // const editorMobile = document.getElementById('editorMobile') // 画布区顶部到浏览器顶部距离 const canvasTop = canvasInfoMobile.offsetTop + 75 // 画布区有高度 @@ -1394,266 +1401,272 @@ export default { diff --git a/frontend/src/views/panel/filter/filterDialog.vue b/frontend/src/views/panel/filter/filterDialog.vue index c9fe37ef69..bf6c0b64ef 100644 --- a/frontend/src/views/panel/filter/filterDialog.vue +++ b/frontend/src/views/panel/filter/filterDialog.vue @@ -53,7 +53,7 @@ v-if="showDomType === 'tree'" :default-expanded-keys="expandedArray" node-key="id" - :data="tempTreeData || data" + :data="tempTreeData || treeData" :props="defaultProps" @node-click="handleNodeClick" @@ -347,7 +347,7 @@ export default { link: false, type: 'root' }], - data: [], + treeData: [], sceneData: [], fieldData: [], originFieldData: [], @@ -472,7 +472,7 @@ export default { this.tData = JSON.parse(modelInfo) const results = this.buildTree(this.tData) this.defaultData = JSON.parse(JSON.stringify(results)) - this.data = JSON.parse(JSON.stringify(results)) + this.treeData = JSON.parse(JSON.stringify(results)) } queryAuthModel({ modelType: 'dataset' }, !userCache).then(res => { localStorage.setItem('dataset-tree', JSON.stringify(res.data)) @@ -480,7 +480,7 @@ export default { this.tData = res.data const results = this.buildTree(this.tData) this.defaultData = JSON.parse(JSON.stringify(results)) - this.data = JSON.parse(JSON.stringify(results)) + this.treeData = JSON.parse(JSON.stringify(results)) } }) }, @@ -513,7 +513,7 @@ export default { name: val } authModel(queryCondition).then(res => { - this.data = this.buildTree(res.data) + this.treeData = this.buildTree(res.data) }) }, buildTree(arrs) { @@ -602,7 +602,7 @@ export default { groupTree({}).then(res => { const data = res.data - this.data = data + this.treeData = data }) }, @@ -629,7 +629,7 @@ export default { this.dataSetBreads = this.dataSetBreads.slice(0, 1) const root = { id: null, - children: JSON.parse(JSON.stringify(this.data)) + children: JSON.parse(JSON.stringify(this.treeData)) } this.getPathById(node.id, root, res => { if (res.length > 1) { @@ -709,7 +709,7 @@ export default { this.keyWord = '' this.isTreeSearch = false if (bread.id) { - const node = this.getNode(bread.id, this.data) + const node = this.getNode(bread.id, this.treeData) if (node) { this.tempTreeData = node.children } @@ -717,7 +717,7 @@ export default { this.tempTreeData = null } - this.data = JSON.parse(JSON.stringify(this.defaultData)) + this.treeData = JSON.parse(JSON.stringify(this.defaultData)) }) }, comBackLink(bread) { @@ -795,7 +795,7 @@ export default { }) if (xItems && xItems.length > 1) { - this.data.splice(e.newDraggableIndex, 1) + this.treeData.splice(e.newDraggableIndex, 1) } }, removeCheckedKey(e) { diff --git a/frontend/src/views/panel/filter/index.vue b/frontend/src/views/panel/filter/index.vue index cc0a1ec8cf..7e4adde83e 100644 --- a/frontend/src/views/panel/filter/index.vue +++ b/frontend/src/views/panel/filter/index.vue @@ -40,6 +40,12 @@ import eventBus from '@/components/canvas/utils/eventBus' import { mapState } from 'vuex' export default { name: 'FilterGroup', + props: { + canvasId: { + type: String, + require: true + } + }, data() { return { panelInfo: this.$store.state.panel.panelInfo, @@ -73,9 +79,12 @@ export default { computed: { ...mapState([ 'canvasStyleData', - 'curCanvasScale', + 'curCanvasScaleMap', 'componentData' ]), + curCanvasScaleSelf() { + return this.curCanvasScaleMap[this.canvasId] + }, searchButtonExist() { return this.componentData && this.componentData.some(component => component.type === 'custom-button' && component.serviceName === 'buttonSureWidget') }, @@ -119,10 +128,12 @@ export default { // 设置矩阵标记点 dragComponentInfo.x = 1 dragComponentInfo.y = 1 - dragComponentInfo.sizex = Math.round(dragComponentInfo.style.width / this.curCanvasScale.matrixStyleOriginWidth) - dragComponentInfo.sizey = Math.round(dragComponentInfo.style.height / this.curCanvasScale.matrixStyleOriginHeight) + dragComponentInfo.sizex = Math.round(dragComponentInfo.style.width / this.curCanvasScaleSelf.matrixStyleOriginWidth) + dragComponentInfo.sizey = Math.round(dragComponentInfo.style.height / this.curCanvasScaleSelf.matrixStyleOriginHeight) dragComponentInfo.auxiliaryMatrix = this.canvasStyleData.auxiliaryMatrix dragComponentInfo.moveStatus = 'start' + dragComponentInfo['canvasId'] = 'canvas-main' + dragComponentInfo['canvasPid'] = '0' this.$store.commit('setDragComponentInfo', dragComponentInfo) ev.dataTransfer.effectAllowed = 'copy' const dataTrans = { diff --git a/frontend/src/views/panel/list/PanelList.vue b/frontend/src/views/panel/list/PanelList.vue index 0b32bcd0b3..671f996f94 100644 --- a/frontend/src/views/panel/list/PanelList.vue +++ b/frontend/src/views/panel/list/PanelList.vue @@ -33,9 +33,9 @@
- + {{ data.name }} {{ $t('panel.rename') }} {{ $t('panel.delete') }} @@ -98,6 +103,18 @@ +

+ {{ defaultExpansion ? '收起' : '展开' }} + +

@@ -105,7 +122,7 @@ {{ $t('panel.panel_list') }} - + - + {{ data.name }} - - - {{ $t('panel.groupAdd') }} + + + {{ $t('panel.groupAdd') }} - + {{ $t('panel.edit') }} {{ $t('panel.share') }} {{ $t('panel.copy') }} {{ $t('dataset.move_to') }} {{ $t('panel.create_public_links') }} {{ $t('panel.to_default_panel') }} {{ $t('panel.rename') }} {{ $t('panel.delete') }} @@ -305,7 +331,9 @@ {{ $t('panel.cancel') }} + >{{ + $t('panel.cancel') + }} {{ $t('dataset.cancel') }} + >{{ + $t('dataset.cancel') + }} { + this.clearLocalStorage.forEach((item) => { localStorage.removeItem(item) }) this.responseSource = 'panelQuery' @@ -582,9 +632,9 @@ export default { }, initCache() { // 初始化时提前加载视图和数据集的缓存 - this.initLocalStorage.forEach(item => { + this.initLocalStorage.forEach((item) => { if (!localStorage.getItem(item + '-tree')) { - queryAuthModel({ modelType: item }, false).then(res => { + queryAuthModel({ modelType: item }, false).then((res) => { localStorage.setItem(item + '-tree', JSON.stringify(res.data)) }) } @@ -596,7 +646,11 @@ export default { this.defaultTree() this.tree() // 默认展开 同时点击 新增的节点 - if (panelInfo && panelInfo.panelType === 'self' && this.lastActiveNodeData.id) { + if ( + panelInfo && + panelInfo.panelType === 'self' && + this.lastActiveNodeData.id + ) { if (this.editPanel.optType === 'rename') { this.lastActiveNodeData.name = panelInfo.name return @@ -692,10 +746,10 @@ export default { }, beforeClickEdit(type, optType, data, node) { return { - 'type': type, - 'data': data, - 'node': node, - 'optType': optType + type: type, + data: data, + node: node, + optType: optType } }, @@ -726,10 +780,10 @@ export default { beforeClickMore(optType, data, node) { return { - 'type': data.nodeType, - 'data': data, - 'node': node, - 'optType': optType + type: data.nodeType, + data: data, + node: node, + optType: optType } }, @@ -750,7 +804,7 @@ export default { saveGroup(group) { this.$refs['groupForm'].validate((valid) => { if (valid) { - addGroup(group).then(res => { + addGroup(group).then((res) => { this.close() this.$message({ message: this.$t('commons.save_success'), @@ -776,19 +830,20 @@ export default { confirmButtonText: this.$t('panel.confirm'), cancelButtonText: this.$t('panel.cancel'), type: 'warning' - }).then(() => { - delGroup(data.id).then(response => { - this.$message({ - type: 'success', - message: this.$t('panel.delete_success'), - showClose: true - }) - this.clearCanvas() - this.tree() - this.defaultTree() - }) - }).catch(() => { }) + .then(() => { + delGroup(data.id).then((response) => { + this.$message({ + type: 'success', + message: this.$t('panel.delete_success'), + showClose: true + }) + this.clearCanvas() + this.tree() + this.defaultTree() + }) + }) + .catch(() => {}) }, clearCanvas() { @@ -815,11 +870,11 @@ export default { }, tree(cache = false) { const modelInfo = localStorage.getItem('panel-main-tree') - const userCache = (modelInfo && cache) + const userCache = modelInfo && cache if (userCache) { this.tData = JSON.parse(modelInfo) } - groupTree(this.groupForm, !userCache).then(res => { + groupTree(this.groupForm, !userCache).then((res) => { localStorage.setItem('panel-main-tree', JSON.stringify(res.data)) if (!userCache) { this.tData = res.data @@ -839,12 +894,12 @@ export default { panelType: 'system' } const modelInfo = localStorage.getItem('panel-default-tree') - const userCache = (modelInfo && cache) + const userCache = modelInfo && cache if (userCache) { this.defaultData = JSON.parse(modelInfo) } - defaultTree(requestInfo, false).then(res => { + defaultTree(requestInfo, false).then((res) => { localStorage.setItem('panel-default-tree', JSON.stringify(res.data)) if (!userCache) { this.defaultData = res.data @@ -865,7 +920,7 @@ export default { // 清理pc布局缓存 this.$store.commit('setComponentDataCache', null) initPanelData(data.id, false, function(response) { - viewPanelLog({ panelId: data.id }).then(res => { + viewPanelLog({ panelId: data.id }).then((res) => { bus.$emit('set-panel-show-type', 0) data.mobileLayout = response.data.mobileLayout }) @@ -889,7 +944,7 @@ export default { }, beforeClickAddData(type) { return { - 'type': type + type: type } }, @@ -930,15 +985,13 @@ export default { }, resetID(data) { if (data) { - data.forEach(item => { + data.forEach((item) => { item.type !== 'custom' && (item.id = uuid.v1()) }) } return data }, - newPanelSave(id) { - - }, + newPanelSave(id) {}, // 激活并点击当前节点 activeNodeAndClick(panelInfo) { if (panelInfo) { @@ -979,10 +1032,13 @@ export default { moveTo(data) { const _this = this this.moveInfo = data - this.moveDialogTitle = this.$t('dataset.m1') + (data.name.length > 10 ? (data.name.substr(0, 10) + '...') : data.name) + this.$t('dataset.m2') + this.moveDialogTitle = + this.$t('dataset.m1') + + (data.name.length > 10 ? data.name.substr(0, 10) + '...' : data.name) + + this.$t('dataset.m2') const queryInfo = JSON.parse(JSON.stringify(this.groupForm)) queryInfo['nodeType'] = 'folder' - groupTree(queryInfo).then(res => { + groupTree(queryInfo).then((res) => { if (data.nodeType === 'folder') { _this.tGroupData = [ { @@ -1005,7 +1061,7 @@ export default { saveMoveGroup() { this.moveInfo.pid = this.tGroup.id this.moveInfo['optType'] = 'move' - panelUpdate(this.moveInfo).then(response => { + panelUpdate(this.moveInfo).then((response) => { this.tree() this.closeMoveGroup() }) @@ -1050,6 +1106,22 @@ export default { diff --git a/frontend/src/views/panel/list/PanelViewShow.vue b/frontend/src/views/panel/list/PanelViewShow.vue index 4aa8a8d006..f4c4072332 100644 --- a/frontend/src/views/panel/list/PanelViewShow.vue +++ b/frontend/src/views/panel/list/PanelViewShow.vue @@ -118,6 +118,10 @@ icon="el-icon-picture-outline" @click.native="downloadAsImage" >{{ $t('panel.export_to_img') }} + {{ $t('panel.export_to_app') }} @@ -205,7 +209,7 @@ > { - html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => { + html2canvas(document.getElementById(this.canvasInfoTemp)).then(canvas => { this.templateSaveShow = true this.dataLoading = false const snapshot = canvas.toDataURL('image/jpeg', 0.1) // 0.2是图片质量 @@ -426,7 +435,7 @@ export default { _this.dataLoading = true try { _this.findStaticSource(function(staticResource) { - html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => { + html2canvas(document.getElementById(_this.canvasInfoTemp)).then(canvas => { _this.dataLoading = false const snapshot = canvas.toDataURL('image/jpeg', 0.1) // 0.1是图片质量 if (snapshot !== '') { @@ -454,9 +463,9 @@ export default { _this.dataLoading = true try { _this.findStaticSource(function(staticResource) { - html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => { + html2canvas(document.getElementById(_this.canvasInfoTemp)).then(canvas => { _this.dataLoading = false - const snapshot = canvas.toDataURL('image/jpeg', 0.1) // 0.1是图片质量 + const snapshot = canvas.toDataURL('image/jpeg', 1) // 0.1是图片质量 if (snapshot !== '') { const panelInfo = { name: _this.$store.state.panel.panelInfo.name, @@ -524,7 +533,7 @@ export default { setTimeout(() => { this.exporting = true setTimeout(() => { - const canvasID = document.getElementById('canvasInfoTemp') + const canvasID = document.getElementById(this.canvasInfoTemp) const a = document.createElement('a') html2canvas(canvasID).then(canvas => { this.exporting = false @@ -555,7 +564,7 @@ export default { setTimeout(() => { this.exporting = true setTimeout(() => { - html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => { + html2canvas(document.getElementById(this.canvasInfoTemp)).then(canvas => { const snapshot = canvas.toDataURL('image/jpeg', 1) // 是图片质量 this.dataLoading = false this.exporting = false @@ -569,7 +578,7 @@ export default { }, refreshTemplateInfo() { this.templateInfo = {} - html2canvas(document.getElementById('canvasInfoTemp')).then(canvas => { + html2canvas(document.getElementById(this.canvasInfoTemp)).then(canvas => { const snapshot = canvas.toDataURL('image/jpeg', 0.1) // 0.2是图片质量 if (snapshot !== '') { this.templateInfo = { @@ -619,7 +628,9 @@ export default { if (this.showType === 1 && this.shareUserId !== null) { const param = { userId: this.shareUserId } proxyInitPanelData(this.panelInfo.id, param, null) - } else { initPanelData(this.panelInfo.id, false) } + } else { + initPanelData(this.panelInfo.id, false) + } }, changePublishState() { if (this.panelInfo.status === 'publish') { @@ -638,72 +649,76 @@ export default { diff --git a/frontend/src/views/system/datasource/DsForm.vue b/frontend/src/views/system/datasource/DsForm.vue index 96ca0ac5f0..b3aa91b2dc 100644 --- a/frontend/src/views/system/datasource/DsForm.vue +++ b/frontend/src/views/system/datasource/DsForm.vue @@ -1,9 +1,12 @@ @@ -167,6 +303,10 @@ import PluginCom from '@/views/system/plugin/PluginCom' import { listDatasourceType, listDatasource } from '@/api/system/datasource' import deTextarea from '@/components/deCustomCm/deTextarea.vue' import msgCfm from '@/components/msgCfm' +import { dsGroupTree } from '@/api/dataset/dataset' +import { appApply, appEdit, groupTree } from '@/api/panel/panel' +import { deepCopy } from '@/components/canvas/utils/utils' + export default { name: 'DsForm', components: { @@ -175,8 +315,51 @@ export default { deTextarea }, mixins: [msgCfm], + props: { + referencePosition: { + type: String, + default: 'datasource' + }, + outerParams: { + type: Object, + request: false + } + }, data() { return { + appMarketEdit: true, + attachRule: { + panelName: [ + { + required: true, + min: 2, + max: 25, + message: i18n.t('datasource.input_limit_2_25', [2, 25]), + trigger: 'blur' + } + ], + datasetGroupName: [ + { + required: true, + min: 2, + max: 25, + message: i18n.t('datasource.input_limit_2_25', [2, 25]), + trigger: 'blur' + } + ], + datasetGroupPid: [{ required: true, message: i18n.t('chart.select_group'), trigger: 'blur' }], + panelGroupPid: [{ required: true, message: i18n.t('chart.select_group'), trigger: 'blur' }] + }, + panelGroupList: [], + datasetGroupList: [], + attachForm: { + appTemplateId: '', + panelGroupPid: null, + panelName: '', + datasetGroupPid: null, + datasetGroupId: null, + datasetGroupName: '' + }, disabled: false, form: { configuration: { @@ -402,8 +585,30 @@ export default { async created() { await this.datasourceTypes() this.queryTreeData() - const { id, showModel, type, name } = this.$route.query + let { id, showModel, type, name } = this.$route.query this.params = this.$route.query + if (this.positionCheck('appMarket')) { + id = this.outerParams.datasourceId + showModel = this.outerParams.showModel + type = this.outerParams.datasourceType + name = this.outerParams.name + this.attachForm.appTemplateId = this.outerParams.appTemplateId + this.attachForm.panelGroupPid = this.outerParams.panelGroupPid + this.attachForm.panelId = this.outerParams.panelId + this.attachForm.panelName = this.outerParams.panelName + this.attachForm.datasetGroupPid = this.outerParams.datasetGroupPid ? this.outerParams.datasetGroupPid : '0' + this.attachForm.datasetGroupId = this.outerParams.datasetGroupId + this.attachForm.datasetGroupName = this.outerParams.datasetGroupName + this.params = { + id: this.outerParams.datasourceId, + showModel: this.outerParams.showModel, + type: this.outerParams.datasourceType, + name: this.outerParams.name, + privileges: this.outerParams.datasourcePrivileges + } + this.getPanelGroupTree() + this.getDatasetGroupTree() + } if (id) { await this.getDatasourceDetail(id, showModel) this.edit(this.params) @@ -420,6 +625,36 @@ export default { this.disabled = Boolean(id) && showModel === 'show' && !this.canEdit }, methods: { + normalizer(node) { + // 去掉children=null的属性 + if (node.children === null || node.children === 'null') { + delete node.children + } + }, + getDatasetGroupTree() { + dsGroupTree({ nodeType: 'group', excludedId: this.attachForm.datasetGroupId }).then(res => { + this.datasetGroupList = [{ + id: '0', + name: this.$t('dataset.dataset_group'), + label: this.$t('dataset.dataset_group'), + pid: '0', + privileges: 'grant,manage,use', + type: 'group', + children: res.data + }] + }) + }, + getPanelGroupTree() { + groupTree({ nodeType: 'folder' }).then(res => { + this.panelGroupList = res.data + if (!this.attachForm.panelGroupPid && this.panelGroupList && this.panelGroupList.length > 0) { + this.attachForm.panelGroupPid = this.panelGroupList[0].id + } + }) + }, + positionCheck(referencePosition) { + return this.referencePosition === referencePosition + }, datasourceTypes() { return listDatasourceType().then((res) => { this.dsTypes = res.data || [] @@ -569,7 +804,7 @@ export default { if ( configuration.host === this.form.configuration.host && configuration.dataBase === - this.form.configuration.dataBase && + this.form.configuration.dataBase && configuration.port === this.form.configuration.port ) { repeat = true @@ -584,7 +819,7 @@ export default { if ( configuration.host === this.form.configuration.host && configuration.dataBase === - this.form.configuration.dataBase && + this.form.configuration.dataBase && configuration.port === this.form.configuration.port && configuration.schema === this.form.configuration.schema ) { @@ -621,7 +856,7 @@ export default { configuration.schema === this.form.configuration.schema && configuration.host === this.form.configuration.host && configuration.dataBase === - this.form.configuration.dataBase && + this.form.configuration.dataBase && configuration.port === this.form.configuration.port ) { repeat = true @@ -631,7 +866,7 @@ export default { if ( configuration.host === this.form.configuration.host && configuration.dataBase === - this.form.configuration.dataBase && + this.form.configuration.dataBase && configuration.port === this.form.configuration.port ) { repeat = true @@ -656,11 +891,20 @@ export default { if (!status) { return } + if (this.positionCheck('appMarket')) { + this.$refs.attachParamsForm.validate(valid => { + if (!valid) { + return false + } + } + ) + } this.$refs.dsForm.validate((valid) => { if (!valid) { return false } - const method = this.formType === 'add' ? addDs : editDs + let method = this.formType === 'add' ? addDs : editDs + const form = JSON.parse(JSON.stringify(this.form)) if (form.type === 'api') { if (this.form.apiConfiguration.length < 1) { @@ -674,17 +918,29 @@ export default { } else { form.configuration = JSON.stringify(form.configuration) } + const isAppMarket = this.positionCheck('appMarket') + let appApplyForm + if (isAppMarket) { + if (typeof form.desc === 'object') { + form.desc = '' + } + appApplyForm = { + ...this.attachForm, + datasourceList: [deepCopy(form)] + } + method = this.formType === 'add' ? appApply : appEdit + } if ( this.formType === 'modify' && this.originConfiguration !== form.configuration ) { - if (repeat) { + if (repeat && !isAppMarket) { $confirm( i18n.t('datasource.repeat_datasource_msg') + - '[' + - repeatDsName.join(',') + - '], ' + - i18n.t('datasource.confirm_save'), + '[' + + repeatDsName.join(',') + + '], ' + + i18n.t('datasource.confirm_save'), () => { $confirm(i18n.t('datasource.edit_datasource_msg'), () => { this.method(method, form) @@ -693,27 +949,40 @@ export default { ) } else { $confirm(i18n.t('datasource.edit_datasource_msg'), () => { - this.method(method, form) + isAppMarket ? this.appApplyMethod(method, appApplyForm) : this.method(method, form) }) } return } - if (repeat) { + if (repeat && !isAppMarket) { $confirm( i18n.t('datasource.repeat_datasource_msg') + - '[' + - repeatDsName.join(',') + - '], ' + - i18n.t('datasource.confirm_save'), + '[' + + repeatDsName.join(',') + + '], ' + + i18n.t('datasource.confirm_save'), () => { this.method(method, form) } ) } else { - this.method(method, form) + isAppMarket ? this.appApplyMethod(method, appApplyForm) : this.method(method, form) } }) }, + appApplyMethod(method, form) { + this.formLoading = true + method(form).then((res) => { + this.$success(i18n.t('commons.save_success')) + if (this.formType === 'add') { + this.$router.push({ name: 'panel', params: res.data }) + } else { + this.closeDraw() + } + }).finally(() => { + this.formLoading = false + }) + }, method(method, form) { this.formLoading = true method(form).then((res) => { @@ -767,6 +1036,14 @@ export default { if (!status) { return } + if (this.positionCheck('appMarket')) { + this.$refs.attachParamsForm.validate(valid => { + if (!valid) { + return false + } + } + ) + } this.$refs.dsForm.validate((valid) => { if (valid) { const data = JSON.parse(JSON.stringify(this.form)) @@ -844,6 +1121,10 @@ export default { backToList() { this.$router.push('/datasource/index') }, + + closeDraw() { + this.$emit('closeDraw') + }, logOutTips() { const options = { title: 'role.tips', @@ -967,21 +1248,47 @@ export default { } }) }, - handleClick(tab, event) {} + handleClick(tab, event) { + } } }