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 ac43dc69ce..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(); 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 b92517f050..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,7 @@ 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); @@ -106,6 +107,7 @@ public class ShiroServiceImpl implements ShiroService { 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/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/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 d293f49dca..965648465f 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 @@ -6,6 +6,7 @@ import io.dataease.auth.service.AuthUserService; import io.dataease.auth.service.impl.AuthUserServiceImpl; import io.dataease.auth.util.JWTUtils; import io.dataease.dto.PermissionProxy; +import io.dataease.dto.chart.ViewOption; import io.dataease.ext.ExtTaskMapper; import io.dataease.commons.utils.CommonBeanFactory; import io.dataease.commons.utils.CronUtils; @@ -29,6 +30,7 @@ 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.ChartViewService; import io.dataease.service.chart.ViewExportExcel; import io.dataease.service.sys.SysUserService; import io.dataease.service.system.EmailService; @@ -199,10 +201,13 @@ public class EmailTaskHandler extends TaskHandler implements Job { List files = null; String viewIds = emailTemplateDTO.getViewIds(); - if (StringUtils.isNotBlank(viewIds)) { + ChartViewService chartViewService = SpringContextUtil.getBean(ChartViewService.class); + List viewOptions = chartViewService.viewOptions(panelId); + if (StringUtils.isNotBlank(viewIds) && CollectionUtils.isNotEmpty(viewOptions)) { + List viewOptionIdList = viewOptions.stream().map(ViewOption::getId).collect(Collectors.toList()); String viewDataRange = emailTemplateDTO.getViewDataRange(); Boolean justExportView = StringUtils.isBlank(viewDataRange) || StringUtils.equals("view", viewDataRange); - List viewIdList = Arrays.asList(viewIds.split(",")).stream().filter(StringUtils::isNotBlank).map(s -> (s.trim())).collect(Collectors.toList()); + List viewIdList = Arrays.asList(viewIds.split(",")).stream().map(s -> s.trim()).filter(viewId -> StringUtils.isNotBlank(viewId) && viewOptionIdList.contains(viewId)).collect(Collectors.toList()); PermissionProxy proxy = new PermissionProxy(); proxy.setUserId(user.getUserId()); files = viewExportExcel.export(panelId, viewIdList, proxy, justExportView); 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/service/chart/ChartViewService.java b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java index 192143ad87..9d628ed9ad 100644 --- a/backend/src/main/java/io/dataease/service/chart/ChartViewService.java +++ b/backend/src/main/java/io/dataease/service/chart/ChartViewService.java @@ -648,6 +648,7 @@ public class ChartViewService { yAxis = yAxis.stream().filter(item -> StringUtils.isNotEmpty(item.getChartId()) || dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList()); break; case "bar-group": + case "bar-group-stack": xAxis = xAxis.stream().filter(item -> StringUtils.isNotEmpty(item.getChartId()) || (!desensitizationList.contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName()))).collect(Collectors.toList()); yAxis = yAxis.stream().filter(item -> StringUtils.isNotEmpty(item.getChartId()) || (!desensitizationList.contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName()))).collect(Collectors.toList()); xAxisBase = xAxisBase.stream().filter(item -> StringUtils.isNotEmpty(item.getChartId()) || (!desensitizationList.contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName()))).collect(Collectors.toList()); @@ -1113,6 +1114,8 @@ public class ChartViewService { } else if (StringUtils.equalsIgnoreCase(view.getRender(), "antv")) { if (StringUtils.equalsIgnoreCase(view.getType(), "bar-group")) { mapChart = ChartDataBuild.transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill); + } else if (StringUtils.equalsIgnoreCase(view.getType(),"bar-group-stack")) { + mapChart = ChartDataBuild.transGroupStackDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, extStack, data, view, isDrill); } else if (StringUtils.containsIgnoreCase(view.getType(), "bar-stack")) { mapChart = ChartDataBuild.transStackChartDataAntV(xAxis, yAxis, view, data, extStack, isDrill); } else if (StringUtils.containsIgnoreCase(view.getType(), "line-stack")) { diff --git a/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java b/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java index 7314367c28..4e28040812 100644 --- a/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java +++ b/backend/src/main/java/io/dataease/service/chart/util/ChartDataBuild.java @@ -994,4 +994,89 @@ public class ChartDataBuild { map.put("tableRow", tableRow); return map; } + + public static Map transGroupStackDataAntV(List xAxisBase, List xAxis, List xAxisExt, List yAxis, List extStack, List data, ChartViewWithBLOBs view, boolean isDrill) { + // 堆叠柱状图 + if (CollectionUtils.isEmpty(xAxisExt)) { + return transStackChartDataAntV(xAxis, yAxis, view, data, extStack, isDrill); + // 分组柱状图 + } else if (CollectionUtils.isNotEmpty(xAxisExt) && CollectionUtils.isEmpty(extStack)) { + return transBaseGroupDataAntV(xAxisBase, xAxis, xAxisExt, yAxis, view, data, isDrill); + // 分组堆叠柱状图 + }else { + Map map = new HashMap<>(); + + List dataList = new ArrayList<>(); + for (int i1 = 0; i1 < data.size(); i1++) { + String[] row = data.get(i1); + + StringBuilder xField = new StringBuilder(); + if (isDrill) { + xField.append(row[xAxis.size() - 1]); + } else { + for (int i = 0; i < xAxisBase.size(); i++) { + if (i == xAxisBase.size() - 1) { + xField.append(row[i]); + } else { + xField.append(row[i]).append("\n"); + } + } + } + + StringBuilder groupField = new StringBuilder(); + for (int i = xAxisBase.size(); i < xAxisBase.size() + xAxisExt.size(); i++) { + if (i == xAxisBase.size() + xAxisExt.size() - 1) { + groupField.append(row[i]); + } else { + groupField.append(row[i]).append("\n"); + } + } + + StringBuilder stackField = new StringBuilder(); + for (int i = xAxis.size(); i < xAxis.size() + extStack.size(); i++) { + if (i == xAxis.size() + extStack.size() - 1) { + stackField.append(row[i]); + } else { + stackField.append(row[i]).append("\n"); + } + } + + AxisChartDataAntVDTO axisChartDataDTO = new AxisChartDataAntVDTO(); + axisChartDataDTO.setField(xField.toString()); + axisChartDataDTO.setName(xField.toString()); + + List dimensionList = new ArrayList<>(); + List quotaList = new ArrayList<>(); + + for (int j = 0; j < xAxis.size(); j++) { + ChartDimensionDTO chartDimensionDTO = new ChartDimensionDTO(); + chartDimensionDTO.setId(xAxis.get(j).getId()); + chartDimensionDTO.setValue(row[j]); + dimensionList.add(chartDimensionDTO); + } + axisChartDataDTO.setDimensionList(dimensionList); + + if (CollectionUtils.isNotEmpty(yAxis)) { + int valueIndex = xAxis.size() + extStack.size(); + ChartQuotaDTO chartQuotaDTO = new ChartQuotaDTO(); + chartQuotaDTO.setId(yAxis.get(0).getId()); + quotaList.add(chartQuotaDTO); + axisChartDataDTO.setQuotaList(quotaList); + try { + axisChartDataDTO.setValue(StringUtils.isEmpty(row[valueIndex]) ? null : new BigDecimal(row[valueIndex])); + } catch (Exception e) { + axisChartDataDTO.setValue(new BigDecimal(0)); + } + } else { + axisChartDataDTO.setQuotaList(quotaList); + axisChartDataDTO.setValue(new BigDecimal(0)); + } + axisChartDataDTO.setGroup(groupField.toString()); + axisChartDataDTO.setCategory(stackField.toString()); + dataList.add(axisChartDataDTO); + } + map.put("data", dataList); + return map; + } + } } 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..8b97b489f6 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; @@ -181,6 +182,7 @@ public class PanelAppTemplateService { for (DatasetTableField datasetTableField : datasetTableFieldsInfo) { String oldId = datasetTableField.getId(); datasetTableField.setTableId(datasetsRealMap.get(datasetTableField.getTableId())); + datasetTableField.setId(null); DatasetTableField newTableField = dataSetTableFieldsService.save(datasetTableField); datasetFieldsRealMap.put(oldId, newTableField.getId()); } @@ -270,15 +272,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/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 b273dda35f..9a78eea9cb 100644 --- a/backend/src/main/resources/db/migration/V42__1.16.sql +++ b/backend/src/main/resources/db/migration/V42__1.16.sql @@ -32,6 +32,17 @@ 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`, @@ -53,3 +64,220 @@ CREATE TABLE `dataset_sql_log` ( `status` varchar(45) DEFAULT NULL COMMENT '状态', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +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/frontend/package.json b/frontend/package.json index f2fc11ddf0..878dfb942d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -45,6 +45,7 @@ "js-cookie": "2.2.0", "jsencrypt": "^3.0.0-rc.1", "jspdf": "^2.3.1", + "jszip": "^3.10.1", "lodash": "^4.17.21", "lodash.isboolean": "^3.0.3", "lodash.isempty": "^4.4.0", 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 32d2067307..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', 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/DeViewSelect/index.vue b/frontend/src/components/DeViewSelect/index.vue index 2995c8bec5..5a30cdcda3 100644 --- a/frontend/src/components/DeViewSelect/index.vue +++ b/frontend/src/components/DeViewSelect/index.vue @@ -157,6 +157,9 @@ export default { loadOptions() { this.panelId && viewOptions(this.panelId).then(res => { this.selectOptions = res.data + this.innerValues?.length && this.selectOptions?.length && this.innerValues.filter(viewId => !this.selectOptions.some(option => option.id === viewId)).forEach(item => { + this._selectRemoveTag(item) + }) this.init() }) }, @@ -185,7 +188,10 @@ export default { }, _selectClearFun() { this.$store.dispatch('task/delPanelViews', this.panelId) - const viewIds = JSON.parse(JSON.stringify(this.$store.getters.panelViews[this.panelId])) + let viewIds = [] + if (this.$store.getters.panelViews?.[this.panelId]) { + viewIds = JSON.parse(JSON.stringify(this.$store.getters.panelViews[this.panelId])) + } this.$emit('input', viewIds) }, diff --git a/frontend/src/components/GradientColorSelector/base.js b/frontend/src/components/GradientColorSelector/base.js index bf88a65f75..e5b98d9fc2 100644 --- a/frontend/src/components/GradientColorSelector/base.js +++ b/frontend/src/components/GradientColorSelector/base.js @@ -39,7 +39,7 @@ export const colorCases = [ { name: i18n.t('chart.color_gentle'), value: 'gentle', - colors: ['#5b9bd5', '#ed7d31', '#70ad47', '#ffc000', '#4472c4', '#91d024', '#b235e6', '#02ae75', '#5b9bd5'] + colors: ['#5b9bd5', '#ed7d31', '#70ad47', '#ffc000', '#4472c4', '#91d024', '#b235e6', '#02ae75', '#003F78'] }, { name: i18n.t('chart.color_technology'), @@ -59,7 +59,7 @@ export const colorCases = [ { name: i18n.t('chart.color_fresh'), value: 'fresh', - colors: ['#5f9b3c', '#75c24b', '#83d65f', '#aacf53', '#c7dc68', '#d8e698', '#e0ebaf', '#bbc8e6', '#e5e5e5'] + colors: ['#e5e5e5', '#bbc8e6', '#e0ebaf', '#d8e698', '#c7dc68', '#aacf53', '#83d65f', '#75c24b', '#5f9b3c'] }, { name: i18n.t('chart.color_energy'), @@ -79,7 +79,7 @@ export const colorCases = [ { name: i18n.t('chart.color_spiritual'), value: 'spiritual', - colors: ['#00a3af', '#4da798', '#57baaa', '#62d0bd', '#6ee4d0', '#86e7d6', '#aeede1', '#bde1e6', '#e5e5e5'] + colors: ['#e5e5e5', '#bde1e6', '#aeede1', '#86e7d6', '#6ee4d0', '#62d0bd', '#57baaa', '#4da798', '#00a3af'] } ] diff --git a/frontend/src/components/GradientColorSelector/index.vue b/frontend/src/components/GradientColorSelector/index.vue index 8bffc71dab..1dcec6bf38 100644 --- a/frontend/src/components/GradientColorSelector/index.vue +++ b/frontend/src/components/GradientColorSelector/index.vue @@ -106,6 +106,7 @@ @@ -423,4 +424,7 @@ export default { width: 20px; height: 20px; } +.gradient-picker-dropdown .el-color-dropdown__link-btn { + display: none; +} diff --git a/frontend/src/components/business/DeLayoutContent.vue b/frontend/src/components/business/DeLayoutContent.vue index 372b5c4c94..039be3d450 100644 --- a/frontend/src/components/business/DeLayoutContent.vue +++ b/frontend/src/components/business/DeLayoutContent.vue @@ -42,7 +42,7 @@ export default { return backPath || backName || backTo }, needInnerPadding() { - return ['sys-identification', 'sys-abutment', 'sys-task-email', 'system-dept', 'system-dept-form', 'system-auth', 'sys-appearance', 'system-param', 'system-template', 'sys-task-dataset', 'sys-msg-web-all', 'system-plugin'].includes(this.$route.name) + return ['system-app-template', 'sys-identification', 'sys-abutment', 'sys-task-email', 'system-dept', 'system-dept-form', 'system-auth', 'sys-appearance', 'system-param', 'system-template', 'sys-task-dataset', 'sys-msg-web-all', 'system-plugin'].includes(this.$route.name) } } } diff --git a/frontend/src/components/canvas/DeCanvas.vue b/frontend/src/components/canvas/DeCanvas.vue index 921f978d4d..5ecd17d185 100644 --- a/frontend/src/components/canvas/DeCanvas.vue +++ b/frontend/src/components/canvas/DeCanvas.vue @@ -61,8 +61,8 @@ v-if="filterVisible && panelInfo.id" :title="(currentWidget && currentWidget.getLeftPanel && currentWidget.getLeftPanel().label ? $t(currentWidget.getLeftPanel().label) : '') + $t('panel.module')" :visible.sync="filterVisible" - custom-class="de-filter-dialog" - :append-to-body="true" + custom-class="de-filter-dialog min-width-730" + append-to-body @close="cancelFilter" > - - @@ -239,13 +232,6 @@ export default { mobileLayoutStatus() { this.restore() } - // //监控当前组件移动 检查是否靠近tab - // curComponent: { - // handler(newVal, oldVla) { - // // this.restore() - // }, - // deep: true - // }, }, created() { }, @@ -301,8 +287,7 @@ export default { } }, canvasScroll(e) { - this.scrollLeft = e.target.scrollLeft - this.scrollTop = e.target.scrollTop + this.$emit('canvasScroll', { scrollLeft: e.target.scrollLeft, scrollTop: e.target.scrollTop }) bus.$emit('onScroll') }, // handleDrop(e) { @@ -597,4 +582,7 @@ export default { overflow-y: auto; background-size: 100% 100% !important; } +.min-width-730 { + min-width: 730px !important; +} diff --git a/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue b/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue index cf18c101c3..827e3d692b 100644 --- a/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue +++ b/frontend/src/components/canvas/components/Editor/ComponentWrapper.vue @@ -10,6 +10,7 @@ :source-element="sourceConfig" :terminal="terminal" :element="config" + :canvas-id="canvasId" :show-position="showPosition" @showViewDetails="showViewDetails" /> @@ -195,7 +196,7 @@ export default { return style }, componentActiveFlag() { - return (this.curComponent && this.config === this.curComponent && !this.previewVisible && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing') + return !this.mobileLayoutStatus && ((this.curComponent && this.config === this.curComponent && !this.previewVisible && !this.showPosition.includes('email-task')) || this.showPosition.includes('multiplexing')) }, curGap() { return (this.canvasStyleData.panel.gap === 'yes' && this.config.auxiliaryMatrix) ? this.componentGap : 0 diff --git a/frontend/src/components/canvas/components/Editor/DeEditor.vue b/frontend/src/components/canvas/components/Editor/DeEditor.vue index eccbc53c7c..bd7bc2c023 100644 --- a/frontend/src/components/canvas/components/Editor/DeEditor.vue +++ b/frontend/src/components/canvas/components/Editor/DeEditor.vue @@ -942,12 +942,6 @@ export default { height: this.outStyle.height + this.scrollTop + 'px !important' } }, - // 挤占式画布设计 - // eslint-disable-next-line - coordinates() { - // eslint-disable-next-line - return this.coordinates - }, customStyle() { let style = { width: '100%', diff --git a/frontend/src/components/canvas/components/Editor/Preview.vue b/frontend/src/components/canvas/components/Editor/Preview.vue index 3f36a04261..ef6cba429d 100644 --- a/frontend/src/components/canvas/components/Editor/Preview.vue +++ b/frontend/src/components/canvas/components/Editor/Preview.vue @@ -27,7 +27,7 @@ v-else-if="componentDataShow && componentDataShow.length===0" class="custom-position" > - {{ $t('panel.panelNull') }} + {{ $t('panel.panelNull') }}
diff --git a/frontend/src/components/canvas/custom-component/DeRichTextView.vue b/frontend/src/components/canvas/custom-component/DeRichTextView.vue index c91825be1e..8dfecebff4 100644 --- a/frontend/src/components/canvas/custom-component/DeRichTextView.vue +++ b/frontend/src/components/canvas/custom-component/DeRichTextView.vue @@ -1,6 +1,7 @@ @@ -211,11 +221,16 @@ import { findPanelElementInfo } from '@/api/panel/panel' import { getNowCanvasComponentData } from '@/components/canvas/utils/utils' import DeCanvasTab from '@/components/canvas/DeCanvas' import Preview from '@/components/canvas/components/Editor/Preview' +import TextAttr from '@/components/canvas/components/TextAttr' export default { name: 'DeTabs', - components: { Preview, DeCanvasTab, TabUseList, ViewSelect, DataeaseTabs }, + components: { TextAttr, Preview, DeCanvasTab, TabUseList, ViewSelect, DataeaseTabs }, props: { + canvasId: { + type: String, + default: 'canvas-main' + }, element: { type: Object, default: null @@ -252,6 +267,20 @@ export default { }, data() { return { + scrollLeft: 50, + scrollTop: 10, + // 需要展示属性设置的组件类型 + showAttrComponent: [ + 'custom', + 'v-text', + 'picture-add', + 'de-tabs', + 'rect-shape', + 'de-show-date', + 'de-video', + 'de-stream-media', + 'de-frame' + ], activeTabName: null, tabIndex: 1, dialogVisible: false, @@ -264,6 +293,23 @@ export default { } }, computed: { + curCanvasScaleSelf() { + return this.curCanvasScaleMap[this.canvasId] + }, + showAttr() { + if (this.mobileLayoutStatus) { + return false + } else if (this.curComponent && this.showAttrComponent.includes(this.curComponent.type)) { + // 过滤组件有标题才显示 + if (this.curComponent.type === 'custom' && (!this.curComponent.options.attrs.showTitle || !this.curComponent.options.attrs.title)) { + return false + } else { + return true + } + } else { + return false + } + }, moveActive() { return this.tabMoveInActiveId && this.tabMoveInActiveId === this.element.id }, @@ -285,7 +331,9 @@ export default { 'curComponent', 'mobileLayoutStatus', 'canvasStyleData', - 'tabMoveInActiveId' + 'tabMoveInActiveId', + 'curCanvasScaleMap', + 'pcComponentData' ]), fontColor() { return this.element && this.element.style && this.element.style.headFontColor || 'none' @@ -360,9 +408,23 @@ export default { bus.$off('add-new-tab', this.addNewTab) }, methods: { + initScroll() { + this.scrollLeft = 50 + this.scrollTop = 10 + }, + canvasScroll(scrollInfo) { + this.scrollLeft = scrollInfo.scrollLeft + 50 + this.scrollTop = scrollInfo.scrollTop + 10 + console.log('scrollInfo=' + JSON.stringify(scrollInfo)) + bus.$emit('onScroll') + }, tabCanvasComponentData(tabName) { - const result = getNowCanvasComponentData(this.element.id + '-' + tabName) - return result + const tabCanvasId = this.element.id + '-' + tabName + if (this.mobileLayoutStatus) { + return this.pcComponentData.filter(item => item.canvasId === tabCanvasId) + } else { + return getNowCanvasComponentData(tabCanvasId) + } }, setContentThemeStyle() { this.element.options.tabList.forEach(tab => { diff --git a/frontend/src/icons/svg/bar-group-stack.svg b/frontend/src/icons/svg/bar-group-stack.svg new file mode 100644 index 0000000000..3ecd3eeef0 --- /dev/null +++ b/frontend/src/icons/svg/bar-group-stack.svg @@ -0,0 +1 @@ + diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index 32df53dbb0..80679abdad 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -1423,6 +1423,7 @@ export default { gauge_size_field_delete: 'Dynamic field changed,please edit again', chart_group: 'Sub Type', chart_bar_group: 'Bar Group', + chart_bar_group_stack: 'Group Stack Bar', field_dynamic: 'Dynamic', aggregation: 'Aggregation', filter_between: 'Between', @@ -2631,6 +2632,28 @@ export default { search_by_keyword: 'Search by keyword', apply_logs: 'Apply logs', app_group_delete_tips: 'Are you sure to delete this application category?', - app_group_delete_content: 'After deletion, all application templates in this category will also be deleted.' + + app_group_delete_content: 'After deletion, all application templates in this category will also be deleted.', + panel_position: 'Panel position', + panel_name: 'Panel name', + dataset_group_position: 'Dataset group position', + dataset_group_name: 'Dataset name', + datasource_info: 'Datasource info', + datasource: 'Datasource', + dataset_group: 'Dataset group', + panel: 'Panel', + log_delete_tips: 'Are you sure to delete this application record?', + log_resource_delete_tips: 'Delete related resources (irrecoverable after deletion)', + file_error_tips: 'The relevant data file is not found. The current file may not be a DataEase application file, or the file may be damaged ', + app_export: 'Application export', + app_version: 'Application version', + program_version: 'DataEase minimum version', + creator: 'Author', + export: 'Export' + }, + + logout: { + oidc_logout_error: 'OIDC failed to exit, do you continue to exit DataEase?', + cas_logout_error: 'The CAS service is abnormal, please contact the administrator!' } } diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index 784ada7e2a..ce10038f30 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -1423,6 +1423,7 @@ export default { gauge_size_field_delete: '動態值中字段發生變更,請重新編輯', chart_group: '子類別', chart_bar_group: '分組柱狀圖', + chart_bar_group_stack: '分組堆疊柱狀圖', field_dynamic: '動態值', aggregation: '聚合方式', filter_between: '介於', @@ -2632,6 +2633,27 @@ export default { search_by_keyword: '通過關鍵字搜索', apply_logs: '應用記錄', app_group_delete_tips: '確定刪除該應用分類嗎?', - app_group_delete_content: '刪除後,該分類中所有的應用模闆也將被刪除。' + app_group_delete_content: '刪除後,該分類中所有的應用模板也將被刪除。', + panel_position: '儀表板位置', + panel_name: '儀表板名稱', + dataset_group_position: '數據集分組位置', + dataset_group_name: '數據集分組名稱', + datasource_info: '數據源信息', + datasource: '數據源', + dataset_group: '數據集分組', + panel: '儀表板', + log_delete_tips: '確定刪除該條應用記錄嗎?', + log_resource_delete_tips: '刪除相關資源(刪除後不可恢復)', + file_error_tips: '未找到相關數據文件,當前文件可能不是DataEase應用文件,或者文件已經損壞', + app_export: '应用导出', + app_version: '应用版本', + program_version: 'DataEase最低版本', + creator: '作者', + export: '导出' + }, + + logout: { + oidc_logout_error: 'OIDC退出失敗,是否繼續退出DataEase?', + cas_logout_error: 'CAS服務異常,請聯系管理員!' } } diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index 76b1f86e61..f8f169c915 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -1422,6 +1422,7 @@ export default { gauge_size_field_delete: '动态值中字段发生变更,请重新编辑', chart_group: '子类别', chart_bar_group: '分组柱状图', + chart_bar_group_stack: '分组堆叠柱状图', field_dynamic: '动态值', aggregation: '聚合方式', filter_between: '介于', @@ -2632,6 +2633,27 @@ export default { search_by_keyword: '通过关键字搜索', apply_logs: '应用记录', app_group_delete_tips: '确定删除该应用分类吗?', - app_group_delete_content: '删除后,该分类中所有的应用模板也将被删除。' + app_group_delete_content: '删除后,该分类中所有的应用模板也将被删除。', + panel_position: '仪表板位置', + panel_name: '仪表板名称', + dataset_group_position: '数据集分组位置', + dataset_group_name: '数据集分组名称', + datasource_info: '数据源信息', + datasource: '数据源', + dataset_group: '数据集分组', + panel: '仪表板', + log_delete_tips: '确定删除该条应用记录吗?', + log_resource_delete_tips: '删除相关资源(删除后不可恢复)', + file_error_tips: '未找到相关数据文件,当前文件可能不是DataEase应用文件,或者文件已经损坏', + app_export: '應用導出', + app_version: '應用版本', + program_version: 'DataEase最低版本', + creator: '作者', + export: '導出' + }, + + logout: { + oidc_logout_error: 'OIDC退出失败,是否继续退出DataEase?', + cas_logout_error: 'CAS服务异常,请联系管理员!' } } diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index f75bc770f1..c7fded233e 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -151,8 +151,8 @@ const data = { mouseY: 0, width: 0, height: 0 - } - + }, + previewVisible: false }, mutations: { ...animation.mutations, @@ -172,6 +172,10 @@ const data = { state.isClickComponent = status }, + setPreviewVisible(state, previewVisible) { + state.previewVisible = previewVisible + }, + setEditMode(state, mode) { state.editMode = mode }, @@ -259,6 +263,7 @@ const data = { } else { state.componentData.push(component) } + this.commit('setCurComponent', { component: component, index: index || state.componentData.length - 1 }) }, removeViewFilter(state, componentId) { state.componentData = state.componentData.map(item => { diff --git a/frontend/src/store/modules/user.js b/frontend/src/store/modules/user.js index a14a2db029..5d8795d358 100644 --- a/frontend/src/store/modules/user.js +++ b/frontend/src/store/modules/user.js @@ -6,6 +6,7 @@ import { getLanguage } from '@/lang/index' import Cookies from 'js-cookie' import router from '@/router' import i18n from '@/lang' +import { $alert, $confirm } from '@/utils/message' const getDefaultState = () => { return { token: getToken(), @@ -146,6 +147,28 @@ const actions = { resolve(res.data) }).catch(error => { reject(error) + if (error?.response?.data?.message) { + if (error.response.data.message === ('oidc_logout_error')) { + const message = i18n.t('logout.' + error.response.data.message) + $confirm(message, () => { + removeToken() // must remove token first + resetRouter() + commit('RESET_STATE') + window.location.href = '/' + }, { + confirmButtonText: i18n.t('commons.confirm') + }) + } + if (error.response.data.message === ('cas_logout_error')) { + const message = i18n.t('logout.' + error.response.data.message) + $alert(message, () => { + + }, { + confirmButtonText: i18n.t('commons.confirm'), + showClose: false + }) + } + } }) }) }, diff --git a/frontend/src/styles/index.scss b/frontend/src/styles/index.scss index 0c6f4b2b69..3b1b8cfb1d 100644 --- a/frontend/src/styles/index.scss +++ b/frontend/src/styles/index.scss @@ -1632,4 +1632,29 @@ div:focus { white-space: nowrap; height: 24px; } +} + +.db-multiple-select-pop { + .selected::after { + content: ''; + width: 6px; + height: 12px; + position: absolute; + right: 12px; + top: 9px; + border: 2px solid #3370ff; + border-top-color: rgba(0, 0, 0, 0); + border-left-color: rgba(0, 0, 0, 0); + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + } +} + +.role-add-name { + .el-select-dropdown__item.selected::after { + content: ''; + position: absolute; + right: 12px; + top: 9px; + } } \ No newline at end of file diff --git a/frontend/src/views/chart/chart/bar/bar_antv.js b/frontend/src/views/chart/chart/bar/bar_antv.js index 5c3cbb30a6..8a95f15dd8 100644 --- a/frontend/src/views/chart/chart/bar/bar_antv.js +++ b/frontend/src/views/chart/chart/bar/bar_antv.js @@ -93,6 +93,12 @@ export function baseBarOptionAntV(plot, container, chart, action, isGroup, isSta } else { delete options.isStack } + + if (chart.type === 'bar-group-stack') { + options.groupField = 'group' + } else { + delete options.groupField + } // 目前只有百分比堆叠柱状图需要这个属性,先直接在这边判断而不作为参数传过来 options.isPercent = chart.type === 'percentage-bar-stack' // custom color diff --git a/frontend/src/views/chart/chart/chart.js b/frontend/src/views/chart/chart/chart.js index c79e0ae12d..1a9a2cd68a 100644 --- a/frontend/src/views/chart/chart/chart.js +++ b/frontend/src/views/chart/chart/chart.js @@ -889,7 +889,9 @@ export const BASE_MAP = { }, emphasis: { - + label: { + show: false + } } } } diff --git a/frontend/src/views/chart/chart/common/common_antv.js b/frontend/src/views/chart/chart/common/common_antv.js index 3f6093278c..7244f2467f 100644 --- a/frontend/src/views/chart/chart/common/common_antv.js +++ b/frontend/src/views/chart/chart/common/common_antv.js @@ -195,7 +195,7 @@ export function getLabel(chart) { f.formatterCfg.thousandSeparator = false } res = valueFormatter(param.value, f.formatterCfg) - } else if (chart.type === 'bar-group') { + } else if (equalsAny(chart.type, 'bar-group', 'bar-group-stack')) { const f = yAxis[0] if (f.formatterCfg) { res = valueFormatter(param.value, f.formatterCfg) @@ -350,7 +350,11 @@ export function getTooltip(chart) { } } } else if (chart.type.includes('group')) { - obj = { name: param.category, value: param.value } + if (chart.type === 'bar-group') { + obj = { name: param.category, value: param.value } + } else { + obj = { name: param.group, value: param.value } + } for (let i = 0; i < yAxis.length; i++) { const f = yAxis[i] if (f.formatterCfg) { diff --git a/frontend/src/views/chart/chart/map/map.js b/frontend/src/views/chart/chart/map/map.js index ead8013c8f..65ae8ff0d9 100644 --- a/frontend/src/views/chart/chart/map/map.js +++ b/frontend/src/views/chart/chart/map/map.js @@ -95,6 +95,7 @@ export function baseMapOption(chart_option, chart, themeStyle, curAreaCode) { chart_option.series[0].label.shadowBlur = 2 chart_option.series[0].label.showdowColor = customAttr.label.shadowColor } + chart_option.series[0].itemStyle.emphasis.label.show = customAttr.label.show } const valueArr = chart.data.series[0].data // visualMap diff --git a/frontend/src/views/chart/chart/table/table-info.js b/frontend/src/views/chart/chart/table/table-info.js index 2324b6b0fd..1225886c54 100644 --- a/frontend/src/views/chart/chart/table/table-info.js +++ b/frontend/src/views/chart/chart/table/table-info.js @@ -3,7 +3,6 @@ import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table import { DEFAULT_COLOR_CASE, DEFAULT_TOTAL } from '@/views/chart/chart/chart' import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter' import { hexColorToRGBA } from '@/views/chart/chart/util' -import Vue from 'vue' export function baseTableInfo(s2, container, chart, action, tableData) { const containerDom = document.getElementById(container) @@ -12,7 +11,6 @@ export function baseTableInfo(s2, container, chart, action, tableData) { if (!fields || fields.length === 0) { if (s2) { s2.destroy() - destroyS2() } return } @@ -140,7 +138,6 @@ export function baseTableInfo(s2, container, chart, action, tableData) { // 开始渲染 if (s2) { s2.destroy() - destroyS2 } s2 = new TableSheet(containerDom, s2DataConfig, s2Options) @@ -163,7 +160,6 @@ export function baseTableNormal(s2, container, chart, action, tableData) { if (!fields || fields.length === 0) { if (s2) { s2.destroy() - destroyS2 } return } @@ -278,7 +274,6 @@ export function baseTableNormal(s2, container, chart, action, tableData) { // 开始渲染 if (s2) { s2.destroy() - destroyS2() } s2 = new TableSheet(containerDom, s2DataConfig, s2Options) @@ -315,7 +310,6 @@ export function baseTablePivot(s2, container, chart, action, tableData) { if (!fields || fields.length === 0) { if (s2) { s2.destroy() - destroyS2() } return } @@ -437,7 +431,6 @@ export function baseTablePivot(s2, container, chart, action, tableData) { // 开始渲染 if (s2) { s2.destroy() - destroyS2() } s2 = new PivotSheet(containerDom, s2DataConfig, s2Options) @@ -451,13 +444,6 @@ export function baseTablePivot(s2, container, chart, action, tableData) { return s2 } -function destroyS2(s2) { - for (const i in s2) { - Vue.$delete(s2, i) - } - s2 = null -} - function getCurrentField(valueFieldList, field) { let list = [] let res = null diff --git a/frontend/src/views/chart/chart/util.js b/frontend/src/views/chart/chart/util.js index a7bab92044..77295df0e6 100644 --- a/frontend/src/views/chart/chart/util.js +++ b/frontend/src/views/chart/chart/util.js @@ -833,6 +833,85 @@ export const TYPE_CONFIGS = [ ] } }, + { + render: 'antv', + category: 'chart.chart_type_compare', + value: 'bar-group-stack', + title: 'chart.chart_bar_group_stack', + icon: 'bar-group-stack', + properties: [ + 'color-selector', + 'size-selector-ant-v', + 'label-selector-ant-v', + 'tooltip-selector-ant-v', + 'x-axis-selector-ant-v', + 'y-axis-selector-ant-v', + 'title-selector-ant-v', + 'legend-selector-ant-v' + ], + propertyInner: { + 'color-selector': [ + 'value', + 'colorPanel', + 'customColor', + 'alpha' + ], + 'size-selector-ant-v': [ + 'barDefault', + 'barGap' + ], + 'label-selector-ant-v': [ + 'show', + 'fontSize', + 'color', + 'position-v' + ], + 'tooltip-selector-ant-v': [ + 'show', + 'textStyle' + ], + 'x-axis-selector-ant-v': [ + 'show', + 'position', + 'name', + 'nameTextStyle', + 'splitLine', + 'axisForm', + 'axisLabel' + ], + 'y-axis-selector-ant-v': [ + 'show', + 'position', + 'name', + 'nameTextStyle', + 'axisValue', + 'splitLine', + 'axisForm', + 'axisLabel' + ], + 'title-selector-ant-v': [ + 'show', + 'title', + 'fontSize', + 'color', + 'hPosition', + 'isItalic', + 'isBolder', + 'remarkShow', + 'fontFamily', + 'letterSpace', + 'fontShadow' + ], + 'legend-selector-ant-v': [ + 'show', + 'icon', + 'orient', + 'textStyle', + 'hPosition', + 'vPosition' + ] + } + }, { render: 'antv', category: 'chart.chart_type_compare', diff --git a/frontend/src/views/chart/components/ChartComponent.vue b/frontend/src/views/chart/components/ChartComponent.vue index ef6702181f..b6d2577ca1 100644 --- a/frontend/src/views/chart/components/ChartComponent.vue +++ b/frontend/src/views/chart/components/ChartComponent.vue @@ -47,6 +47,9 @@
+
@@ -167,7 +170,8 @@ export default { borderRadius: '0px', mapCenter: null, linkageActiveParam: null, - buttonTextColor: null + buttonTextColor: null, + loading: true } }, @@ -222,6 +226,7 @@ export default { } }, preDraw() { + this.loading = true // 基于准备好的dom,初始化echarts实例 // 渲染echart等待dom加载完毕,渲染之前先尝试销毁具有相同id的echart 放置多次切换仪表板有重复id情况 const that = this @@ -253,6 +258,10 @@ export default { that.$refs.viewTrack.trackButtonClick() } }) + this.myChart.off('finished') + this.myChart.on('finished', () => { + this.loading = false + }) }) }, loadThemeStyle() { diff --git a/frontend/src/views/chart/components/ChartComponentG2.vue b/frontend/src/views/chart/components/ChartComponentG2.vue index cd7b2b1334..c55b9c80fe 100644 --- a/frontend/src/views/chart/components/ChartComponentG2.vue +++ b/frontend/src/views/chart/components/ChartComponentG2.vue @@ -67,6 +67,7 @@ import TitleRemark from '@/views/chart/view/TitleRemark' import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart' import { baseMixOptionAntV } from '@/views/chart/chart/mix/mix_antv' import { compareItem } from '@/views/chart/chart/compare' +import { mapState } from 'vuex' import clickoutside from 'element-ui/src/utils/clickoutside.js' import bus from '@/utils/bus' @@ -163,7 +164,11 @@ export default { }, mainActiveName() { return this.$store.state.panel.mainActiveName - } + }, + ...mapState([ + 'mobileLayoutStatus', + 'previewVisible' + ]) }, watch: { chart: { @@ -253,6 +258,8 @@ export default { this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false) } else if (chart.type === 'bar-stack' || chart.type === 'percentage-bar-stack') { this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true) + } else if (chart.type === 'bar-group-stack') { + this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, true) } else if (chart.type === 'bar-horizontal') { this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false) } else if (chart.type === 'bar-stack-horizontal') { @@ -442,7 +449,7 @@ export default { }) }, handleTitleEditer() { - if (this.mainActiveName !== 'PanelEdit') return + if (this.mainActiveName !== 'PanelEdit' || this.mobileLayoutStatus || this.previewVisible) return this.chartTitleEditer = true this.chartTitleUpdate = this.chart.title this.$nextTick(() => { diff --git a/frontend/src/views/chart/components/ChartComponentS2.vue b/frontend/src/views/chart/components/ChartComponentS2.vue index 8ed97e0ff3..9a37f67555 100644 --- a/frontend/src/views/chart/components/ChartComponentS2.vue +++ b/frontend/src/views/chart/components/ChartComponentS2.vue @@ -98,6 +98,7 @@ import TitleRemark from '@/views/chart/view/TitleRemark' import { DEFAULT_TITLE_STYLE } from '@/views/chart/chart/chart' import clickoutside from 'element-ui/src/utils/clickoutside.js' import bus from '@/utils/bus' +import { mapState } from 'vuex' import { compareItem } from '@/views/chart/chart/compare' import { getChartDetails @@ -197,7 +198,11 @@ export default { }, mainActiveName() { return this.$store.state.panel.mainActiveName - } + }, + ...mapState([ + 'mobileLayoutStatus', + 'previewVisible' + ]) }, watch: { chart: { @@ -220,7 +225,6 @@ export default { }, beforeDestroy() { clearInterval(this.scrollTimer) - this.destroyS2() }, methods: { initData() { @@ -263,13 +267,6 @@ export default { }) } }, - destroyS2() { - if (!this.myChart) return - for (const i in this.myChart) { - this.$delete(this.myChart, i) - } - this.myChart = null - }, drawView() { const chart = this.chart // type @@ -295,7 +292,6 @@ export default { if (this.myChart) { this.antVRenderStatus = false this.myChart.destroy() - this.destroyS2() } } @@ -479,7 +475,7 @@ export default { }) }, handleTitleEditer() { - if (this.mainActiveName !== 'PanelEdit') return + if (this.mainActiveName !== 'PanelEdit' || this.mobileLayoutStatus || this.previewVisible) return this.chartTitleEditer = true this.chartTitleUpdate = this.chart.title this.$nextTick(() => { diff --git a/frontend/src/views/chart/components/component-style/TitleSelector.vue b/frontend/src/views/chart/components/component-style/TitleSelector.vue index d5691cc72e..b674de0668 100644 --- a/frontend/src/views/chart/components/component-style/TitleSelector.vue +++ b/frontend/src/views/chart/components/component-style/TitleSelector.vue @@ -12,10 +12,10 @@ :label="$t('chart.show')" class="form-item" > - {{ $t('chart.show') }} + />
@@ -274,7 +274,7 @@ :title="$t('chart.threshold')" :visible="editTableThresholdDialog" :show-close="false" - width="50%" + width="800px" class="dialog-css" append-to-body > diff --git a/frontend/src/views/chart/components/senior/dialog/AssistLineEdit.vue b/frontend/src/views/chart/components/senior/dialog/AssistLineEdit.vue index 21e133f793..655a2a4a7c 100644 --- a/frontend/src/views/chart/components/senior/dialog/AssistLineEdit.vue +++ b/frontend/src/views/chart/components/senior/dialog/AssistLineEdit.vue @@ -17,6 +17,7 @@ diff --git a/frontend/src/views/chart/components/senior/dialog/TableThresholdEdit.vue b/frontend/src/views/chart/components/senior/dialog/TableThresholdEdit.vue index 073dfdee8b..9e0a3b62cd 100644 --- a/frontend/src/views/chart/components/senior/dialog/TableThresholdEdit.vue +++ b/frontend/src/views/chart/components/senior/dialog/TableThresholdEdit.vue @@ -100,6 +100,7 @@ v-show="!item.term.includes('null') && !item.term.includes('empty') && item.term !== 'between'" v-model="item.value" class="value-item" + style="margin-left: 10px;" :placeholder="$t('chart.drag_block_label_value')" size="mini" clearable @@ -426,7 +427,7 @@ span { .between-item { position: relative; display: inline-block; - width: 80px !important; + width: 90px !important; } .select-item { diff --git a/frontend/src/views/chart/view/ChartEdit.vue b/frontend/src/views/chart/view/ChartEdit.vue index 0ee0dc0012..140954889d 100644 --- a/frontend/src/views/chart/view/ChartEdit.vue +++ b/frontend/src/views/chart/view/ChartEdit.vue @@ -549,7 +549,7 @@ diff --git a/frontend/src/views/chart/view/ChartStyle.vue b/frontend/src/views/chart/view/ChartStyle.vue index 3a752184a0..6ee80ef828 100644 --- a/frontend/src/views/chart/view/ChartStyle.vue +++ b/frontend/src/views/chart/view/ChartStyle.vue @@ -123,7 +123,7 @@ - + {{ $t('chart.module_style') }} .de-collapse-style { - .el-collapse-item__header { + ::v-deep.el-collapse-item__header { height: 34px !important; line-height: 34px !important; padding: 0 0 0 6px !important; diff --git a/frontend/src/views/dataset/add/AddApi.vue b/frontend/src/views/dataset/add/AddApi.vue index a142f9a921..2e009ccca8 100644 --- a/frontend/src/views/dataset/add/AddApi.vue +++ b/frontend/src/views/dataset/add/AddApi.vue @@ -32,6 +32,7 @@ - diff --git a/frontend/src/views/dataset/add/AddDB.vue b/frontend/src/views/dataset/add/AddDB.vue index ba39fb8381..791f839d8c 100644 --- a/frontend/src/views/dataset/add/AddDB.vue +++ b/frontend/src/views/dataset/add/AddDB.vue @@ -33,7 +33,7 @@ v-model="dataSource" class="ds-list" filterable - popper-class="db-select-pop" + popper-class="db-multiple-select-pop" :placeholder="$t('dataset.pls_slc_data_source')" size="small" > @@ -640,20 +640,3 @@ export default { } } - diff --git a/frontend/src/views/dataset/form.vue b/frontend/src/views/dataset/form.vue index fa397647c1..6612092422 100644 --- a/frontend/src/views/dataset/form.vue +++ b/frontend/src/views/dataset/form.vue @@ -21,7 +21,7 @@ style="left: 55px" class="el-form-item__error" > - {{ $t('deDataset.already_Exists') }} + {{ $t('deDataset.already_exists') }}
@@ -64,6 +66,7 @@ import { save, update, nameCheck } from '@/api/system/appTemplate' import msgCfm from '@/components/msgCfm/index' import { find } from '@/api/system/template' import { imgUrlTrans } from '@/components/canvas/utils/utils' +import JSZip from 'jszip' export default { mixins: [msgCfm], @@ -186,22 +189,31 @@ export default { }) }, handleFileChange(e) { + const jsZip = new JSZip() const file = e.target.files[0] - const reader = new FileReader() const _this = this - reader.onload = (res) => { - _this.appResultInfo = JSON.parse(res.target.result) - _this.importTemplateInfo = JSON.parse(this.appResultInfo.panelInfo) - _this.templateInfo.name = this.importTemplateInfo.name - _this.templateInfo.templateStyle = this.importTemplateInfo.panelStyle - _this.templateInfo.templateData = this.importTemplateInfo.panelData - _this.templateInfo.snapshot = this.importTemplateInfo.snapshot - _this.templateInfo.dynamicData = this.importTemplateInfo.dynamicData - _this.templateInfo.staticResource = - _this.importTemplateInfo.staticResource - _this.templateInfo.nodeType = 'template' - } - reader.readAsText(file) + jsZip.loadAsync(file).then(function(file) { + jsZip.file('DATA_RELATION.DE').async('string').then(function(content) { + _this.appResultInfo = { ...JSON.parse(content), ..._this.appResultInfo } + }) + jsZip.file('APP.json').async('string').then(function(content) { + _this.appResultInfo['applicationInfo'] = content + const appInfo = JSON.parse(content) + _this.templateInfo.name = appInfo.appName + }) + jsZip.file('TEMPLATE.DET').async('string').then(function(content) { + _this.appResultInfo['panelInfo'] = content + _this.importTemplateInfo = JSON.parse(content) + _this.templateInfo.templateStyle = _this.importTemplateInfo.panelStyle + _this.templateInfo.templateData = _this.importTemplateInfo.panelData + _this.templateInfo.snapshot = _this.importTemplateInfo.snapshot + _this.templateInfo.dynamicData = _this.importTemplateInfo.dynamicData + _this.templateInfo.staticResource = _this.importTemplateInfo.staticResource + _this.templateInfo.nodeType = 'template' + }) + }).catch(() => { + _this.$warning(this.$t('app_template.file_error_tips')) + }) }, goFile() { this.$refs.files.click() @@ -216,10 +228,12 @@ export default { border: none; padding: 0 0; } + .my_table ::v-deep .el-table th.is-leaf { /* 去除上边框 */ border: none; } + .my_table ::v-deep .el-table::before { /* 去除下边框 */ height: 0; @@ -229,6 +243,7 @@ export default { margin-top: 24px; text-align: right; } + .preview { margin-top: -12px; border: 1px solid #e6e6e6; @@ -237,6 +252,7 @@ export default { background-size: 100% 100% !important; border-radius: 4px; } + .preview-show { border-left: 1px solid #e6e6e6; height: 300px; @@ -250,6 +266,7 @@ export default { display: flex; align-items: center; justify-content: space-between; + .el-input { margin-right: 2px; flex: 1; diff --git a/frontend/src/views/panel/appTemplate/component/TemplateItem.vue b/frontend/src/views/panel/appTemplate/component/TemplateItem.vue index b86fbee65c..d6674d4172 100644 --- a/frontend/src/views/panel/appTemplate/component/TemplateItem.vue +++ b/frontend/src/views/panel/appTemplate/component/TemplateItem.vue @@ -12,7 +12,10 @@ alt="" > -
+
- {{ $t("commons.update") }} + {{ $t('commons.update') }} - {{ $t("commons.uninstall") }} + {{ $t('commons.uninstall') }}
+ +
+ + + + {{ model.name }} + + + + {{ $t('panel.preview') }} + + {{ $t('panel.apply') }} + + + +
- 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 @@ @@ -466,6 +468,13 @@ + + @@ -519,10 +528,12 @@ 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, @@ -767,6 +778,9 @@ export default { }, mobileLayoutStatus() { this.restore() + }, + previewVisible(val) { + this.$store.commit('setPreviewVisible', val) } }, created() { @@ -1309,9 +1323,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() { @@ -1501,6 +1515,7 @@ export default { color: gray; height: 30px; width: 100%; + text-align: center; } .this_mobile_canvas_bottom { diff --git a/frontend/src/views/panel/list/AppExportForm.vue b/frontend/src/views/panel/list/AppExportForm.vue new file mode 100644 index 0000000000..565b21f96b --- /dev/null +++ b/frontend/src/views/panel/list/AppExportForm.vue @@ -0,0 +1,195 @@ + + + + diff --git a/frontend/src/views/panel/list/EditPanel/index.vue b/frontend/src/views/panel/list/EditPanel/index.vue index a6daca3789..03a5e89aee 100644 --- a/frontend/src/views/panel/list/EditPanel/index.vue +++ b/frontend/src/views/panel/list/EditPanel/index.vue @@ -8,16 +8,19 @@ {{ $t('panel.custom') }} + > {{ $t('panel.custom') }} + {{ $t('panel.import_template') }} + >{{ $t('panel.import_template') }} + {{ $t('panel.copy_template') }} + >{{ $t('panel.copy_template') }} + {{ $t('panel.upload_template') }} + >{{ $t('panel.upload_template') }} + {{ $t('commons.cancel') }} + >{{ $t('commons.cancel') }} + {{ $t('commons.confirm') }} + >{{ $t('commons.confirm') }} + @@ -234,7 +240,7 @@ export default { showClose: true }) this.loading = false - this.$emit('closeEditPanelDialog', response.data) + this.$emit('closeEditPanelDialog', { id: response.data, name: this.editPanel.panelInfo.name }) }).catch(() => { this.loading = false }) @@ -265,34 +271,38 @@ export default { diff --git a/frontend/src/views/panel/list/PanelList.vue b/frontend/src/views/panel/list/PanelList.vue index 671f996f94..1ff274d29f 100644 --- a/frontend/src/views/panel/list/PanelList.vue +++ b/frontend/src/views/panel/list/PanelList.vue @@ -645,6 +645,9 @@ export default { if (panelInfo) { this.defaultTree() this.tree() + if (this.editPanel.optType === 'rename' && panelInfo.id === this.$store.state.panel.panelInfo.id) { + this.$store.state.panel.panelInfo.name = panelInfo.name + } // 默认展开 同时点击 新增的节点 if ( panelInfo && diff --git a/frontend/src/views/panel/list/PanelViewShow.vue b/frontend/src/views/panel/list/PanelViewShow.vue index 106a7dbb4a..fe6ff3bac8 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') }} @@ -274,6 +278,48 @@ @closePreExport="closePreExport" /> + + + + + + + + + + + + + + diff --git a/frontend/src/views/panel/list/common/PanelDetailInfo.vue b/frontend/src/views/panel/list/common/PanelDetailInfo.vue index 97b73fc60e..c9c9ccab8e 100644 --- a/frontend/src/views/panel/list/common/PanelDetailInfo.vue +++ b/frontend/src/views/panel/list/common/PanelDetailInfo.vue @@ -29,20 +29,6 @@