From 3c5c98dd89ccf26daf1aa9ff60efc80a089fa3e0 Mon Sep 17 00:00:00 2001 From: taojinlong Date: Thu, 24 Feb 2022 14:29:20 +0800 Subject: [PATCH 1/6] =?UTF-8?q?fix:=20=E5=85=AC=E5=85=B1=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/dataease/service/dataset/DataSetTableService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e2fc21d256..d92fc35991 100644 --- a/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java +++ b/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java @@ -405,7 +405,7 @@ public class DataSetTableService { public DataSetTableDTO getWithPermission(String id, Long user) { CurrentUserDto currentUserDto = AuthUtils.getUser(); - Long userId = user != null ? currentUserDto.getUserId() : user; + Long userId = currentUserDto != null ? currentUserDto.getUserId() : user; DataSetTableRequest dataSetTableRequest = new DataSetTableRequest(); dataSetTableRequest.setId(id); From d5c0a625fa3c9d73c6583e9f8424ac6f7ac2da55 Mon Sep 17 00:00:00 2001 From: junjun Date: Thu, 24 Feb 2022 14:33:11 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=E4=B8=AD=E6=95=B0=E6=8D=AE=E9=9B=86=E5=AD=97=E6=AE=B5=E3=80=81?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8C=E6=9C=AA=E5=8F=97=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=9B=86=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/dataset/DataSetTableService.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 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 e2fc21d256..c621e531b4 100644 --- a/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java +++ b/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java @@ -405,7 +405,7 @@ public class DataSetTableService { public DataSetTableDTO getWithPermission(String id, Long user) { CurrentUserDto currentUserDto = AuthUtils.getUser(); - Long userId = user != null ? currentUserDto.getUserId() : user; + Long userId = user != null ? user : currentUserDto.getUserId(); DataSetTableRequest dataSetTableRequest = new DataSetTableRequest(); dataSetTableRequest.setId(id); @@ -464,7 +464,7 @@ public class DataSetTableService { } public Map getPreviewData(DataSetTableRequest dataSetTableRequest, Integer page, Integer pageSize, - List extFields) throws Exception { + List extFields) throws Exception { Map map = new HashMap<>(); DatasetTableField datasetTableField = DatasetTableField.builder().tableId(dataSetTableRequest.getId()) .checked(Boolean.TRUE).build(); @@ -926,8 +926,8 @@ public class DataSetTableService { DorisTableUtils.dorisFieldName( datasetTableField.getTableId() + "_" + datasetTableField.getDataeaseName())) || StringUtils.equalsIgnoreCase(tableField.getFieldName(), - DorisTableUtils.dorisFieldNameShort(datasetTableField.getTableId() + "_" - + datasetTableField.getOriginName()))) { + DorisTableUtils.dorisFieldNameShort(datasetTableField.getTableId() + "_" + + datasetTableField.getOriginName()))) { tableField.setRemarks(datasetTableField.getName()); break; } @@ -990,7 +990,7 @@ public class DataSetTableService { DorisTableUtils.dorisFieldName( datasetTableField.getTableId() + "_" + datasetTableField.getDataeaseName())) || StringUtils.equalsIgnoreCase(tableField.getFieldName(), DorisTableUtils.dorisFieldName( - datasetTableField.getTableId() + "_" + datasetTableField.getOriginName()))) { + datasetTableField.getTableId() + "_" + datasetTableField.getOriginName()))) { tableField.setRemarks(datasetTableField.getName()); break; } @@ -1073,7 +1073,7 @@ public class DataSetTableService { } public String getCustomSQLDatasource(DataTableInfoDTO dataTableInfoDTO, List list, - Datasource ds) { + Datasource ds) { DatasourceTypes datasourceTypes = DatasourceTypes.valueOf(ds.getType()); String keyword = datasourceTypes.getKeywordPrefix() + "%s" + datasourceTypes.getKeywordSuffix(); Map customInfo = new TreeMap<>(); @@ -1260,7 +1260,7 @@ public class DataSetTableService { // 递归计算出所有子级的checkedFields和unionParam private void getUnionSQLDorisJoin(List childrenDs, Map checkedInfo, - List unionList, List checkedFields) { + List unionList, List checkedFields) { for (int i = 0; i < childrenDs.size(); i++) { UnionDTO unionDTO = childrenDs.get(i); String tableId = unionDTO.getCurrentDs().getId(); @@ -1398,7 +1398,7 @@ public class DataSetTableService { // 递归计算出所有子级的checkedFields和unionParam private void getUnionSQLDatasourceJoin(List childrenDs, Map checkedInfo, - List unionList, String keyword, List checkedFields) { + List unionList, String keyword, List checkedFields) { for (int i = 0; i < childrenDs.size(); i++) { UnionDTO unionDTO = childrenDs.get(i); @@ -1703,10 +1703,10 @@ public class DataSetTableService { if (datasetTableIncrementalConfig == null || StringUtils.isEmpty(datasetTableIncrementalConfig.getTableId())) { return; } - if(StringUtils.isNotEmpty(datasetTableIncrementalConfig.getIncrementalAdd())){ + if (StringUtils.isNotEmpty(datasetTableIncrementalConfig.getIncrementalAdd())) { datasetTableIncrementalConfig.setIncrementalAdd(datasetTableIncrementalConfig.getIncrementalAdd().trim()); } - if(StringUtils.isNotEmpty(datasetTableIncrementalConfig.getIncrementalDelete())){ + if (StringUtils.isNotEmpty(datasetTableIncrementalConfig.getIncrementalDelete())) { datasetTableIncrementalConfig.setIncrementalDelete(datasetTableIncrementalConfig.getIncrementalDelete().trim()); } if (StringUtils.isEmpty(datasetTableIncrementalConfig.getId())) { From c1e9d3570d43616d4d50da940216e52c5f91184a Mon Sep 17 00:00:00 2001 From: junjun Date: Thu, 24 Feb 2022 14:36:29 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=E4=B8=AD=E6=95=B0=E6=8D=AE=E9=9B=86=E5=AD=97=E6=AE=B5=E3=80=81?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8C=E6=9C=AA=E5=8F=97=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=9B=86=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/dataease/service/dataset/DataSetTableService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c621e531b4..e63fe1f17a 100644 --- a/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java +++ b/backend/src/main/java/io/dataease/service/dataset/DataSetTableService.java @@ -405,7 +405,7 @@ public class DataSetTableService { public DataSetTableDTO getWithPermission(String id, Long user) { CurrentUserDto currentUserDto = AuthUtils.getUser(); - Long userId = user != null ? user : currentUserDto.getUserId(); + Long userId = currentUserDto != null ? currentUserDto.getUserId() : user; DataSetTableRequest dataSetTableRequest = new DataSetTableRequest(); dataSetTableRequest.setId(id); From 5e695b3b819dd98f8b2797036b4c4b4d0aa6a763 Mon Sep 17 00:00:00 2001 From: junjun Date: Thu, 24 Feb 2022 16:42:31 +0800 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20=E6=BC=8F=E6=96=97=E5=9B=BE?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/chart/view/ChartEdit.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/views/chart/view/ChartEdit.vue b/frontend/src/views/chart/view/ChartEdit.vue index 8e35536a73..be24d248c7 100644 --- a/frontend/src/views/chart/view/ChartEdit.vue +++ b/frontend/src/views/chart/view/ChartEdit.vue @@ -622,7 +622,7 @@ /> From 52fcd983aeb9f94ec7cd0f188f5e4c6f87671b06 Mon Sep 17 00:00:00 2001 From: taojinlong Date: Thu, 24 Feb 2022 16:43:54 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=E6=98=BE=E7=A4=BAapi=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E8=A1=A8=E7=9A=84=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datasource/DatasourceController.java | 2 +- .../request/datasource/ApiDefinition.java | 1 + .../provider/datasource/ApiProvider.java | 28 ++--- .../service/datasource/DatasourceService.java | 110 +++++++++++++----- .../main/resources/db/migration/V32__1.8.sql | 3 + frontend/src/lang/en.js | 6 +- frontend/src/lang/tw.js | 6 +- frontend/src/lang/zh.js | 6 +- frontend/src/views/system/datasource/form.vue | 63 +++++++--- 9 files changed, 159 insertions(+), 66 deletions(-) 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 b6b1218c01..a47f6b28cc 100644 --- a/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java +++ b/backend/src/main/java/io/dataease/controller/datasource/DatasourceController.java @@ -50,7 +50,7 @@ public class DatasourceController { @DePermission(type = DePermissionType.DATASOURCE, value = "id") @ApiOperation("验证数据源") @PostMapping("/validate") - public ResultHolder validate(@RequestBody Datasource datasource) throws Exception { + public ResultHolder validate(@RequestBody DatasourceDTO datasource) throws Exception { return datasourceService.validate(datasource); } diff --git a/backend/src/main/java/io/dataease/controller/request/datasource/ApiDefinition.java b/backend/src/main/java/io/dataease/controller/request/datasource/ApiDefinition.java index 36e4d8e41a..59fda7863b 100644 --- a/backend/src/main/java/io/dataease/controller/request/datasource/ApiDefinition.java +++ b/backend/src/main/java/io/dataease/controller/request/datasource/ApiDefinition.java @@ -16,5 +16,6 @@ public class ApiDefinition { private List fields; private String request; private String dataPath; + private String status; private List datas = new ArrayList<>(); } diff --git a/backend/src/main/java/io/dataease/provider/datasource/ApiProvider.java b/backend/src/main/java/io/dataease/provider/datasource/ApiProvider.java index 948b9710d1..42a800f1c5 100644 --- a/backend/src/main/java/io/dataease/provider/datasource/ApiProvider.java +++ b/backend/src/main/java/io/dataease/provider/datasource/ApiProvider.java @@ -12,15 +12,13 @@ import io.dataease.controller.request.datasource.ApiDefinitionRequest; import io.dataease.controller.request.datasource.DatasourceRequest; import io.dataease.dto.datasource.TableDesc; import io.dataease.dto.datasource.TableField; -import io.dataease.exception.DataEaseException; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpHeaders; + import org.springframework.stereotype.Service; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.Statement; + import java.util.*; import java.util.stream.Collectors; @@ -102,22 +100,18 @@ public class ApiProvider extends DatasourceProvider{ @Override public String checkStatus(DatasourceRequest datasourceRequest) throws Exception { - List apiDefinitionList = JSONObject.parseArray(datasourceRequest.getDatasource().getConfiguration(), ApiDefinition.class).stream().filter(item -> item.getName().equalsIgnoreCase(datasourceRequest.getTable())).collect(Collectors.toList()); - int success = 0; + List apiDefinitionList = JSONObject.parseArray(datasourceRequest.getDatasource().getConfiguration(), ApiDefinition.class); + JSONObject apiItemStatuses = new JSONObject(); for (ApiDefinition apiDefinition : apiDefinitionList) { datasourceRequest.setTable(apiDefinition.getName()); try { - getData(datasourceRequest); - success++; - }catch (Exception ignore){} + getData(datasourceRequest); + apiItemStatuses.put(apiDefinition.getName(), "Success"); + }catch (Exception ignore){ + apiItemStatuses.put(apiDefinition.getName(), "Error"); + } } - if(success == apiDefinitionList.size()){ - return "Success"; - } - if(success > 0 && success < apiDefinitionList.size() ){ - return "Warning"; - } - return "Error"; + return JSONObject.toJSONString(apiItemStatuses); } static public String execHttpRequest(ApiDefinition apiDefinition) throws Exception{ diff --git a/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java b/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java index e1a360d7f0..4ac401ce31 100644 --- a/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java +++ b/backend/src/main/java/io/dataease/service/datasource/DatasourceService.java @@ -1,5 +1,6 @@ package io.dataease.service.datasource; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; import com.jayway.jsonpath.JsonPath; @@ -110,12 +111,38 @@ public class DatasourceService { datasourceDTO.setConfiguration(JSONObject.toJSONString(new Gson().fromJson(datasourceDTO.getConfiguration(), CHConfiguration.class)) ); break; case api: - datasourceDTO.setApiConfiguration(JSONObject.parseArray(datasourceDTO.getConfiguration())); + JSONArray apiDefinitionList = JSONObject.parseArray(datasourceDTO.getConfiguration()); + JSONArray apiDefinitionListWithStatus = new JSONArray(); + int success = 0; + if(StringUtils.isNotEmpty(datasourceDTO.getStatus())){ + JSONObject apiItemStatuses = JSONObject.parseObject(datasourceDTO.getStatus()); + for (Object apiDefinition : apiDefinitionList) { + String status = apiItemStatuses.getString(JSONObject.parseObject(apiDefinition.toString()).getString("name") ); + JSONObject object = JSONObject.parseObject(apiDefinition.toString()); + object.put("status", status); + apiDefinitionListWithStatus.add(object); + if(StringUtils.isNotEmpty(status) && status.equalsIgnoreCase("Success")){ + success ++; + } + } + } + datasourceDTO.setApiConfiguration(apiDefinitionListWithStatus); + if(success == apiDefinitionList.size()){ + datasourceDTO.setStatus("Success"); + break; + } + if(success > 0 && success < apiDefinitionList.size() ){ + datasourceDTO.setStatus("Warning"); + break; + } + datasourceDTO.setStatus("Error"); break; default: break; } - }catch (Exception ignore){} + }catch (Exception ignore){ + ignore.printStackTrace(); + } }); return datasourceDTOS; @@ -156,22 +183,39 @@ public class DatasourceService { handleConnectionPool(datasource, "edit"); } - public ResultHolder validate(Datasource datasource) throws Exception { + public ResultHolder validate(DatasourceDTO datasource) throws Exception { try { DatasourceProvider datasourceProvider = ProviderFactory.getProvider(datasource.getType()); DatasourceRequest datasourceRequest = new DatasourceRequest(); datasourceRequest.setDatasource(datasource); - String status = datasourceProvider.checkStatus(datasourceRequest); - if (status.equalsIgnoreCase("Success")) { - return ResultHolder.success("Success"); + String datasourceStatus = datasourceProvider.checkStatus(datasourceRequest); + if(datasource.getType().equalsIgnoreCase("api")){ + int success = 0; + JSONArray apiDefinitionList = JSONObject.parseArray(datasource.getConfiguration()); + JSONArray apiDefinitionListWithStatus = new JSONArray(); + if(StringUtils.isNotEmpty(datasourceStatus)){ + JSONObject apiItemStatuses = JSONObject.parseObject(datasourceStatus); + for (Object apiDefinition : apiDefinitionList) { + String status = apiItemStatuses.getString(JSONObject.parseObject(apiDefinition.toString()).getString("name") ); + JSONObject object = JSONObject.parseObject(apiDefinition.toString()); + object.put("status", status); + apiDefinitionListWithStatus.add(object); + if(StringUtils.isNotEmpty(status) && status.equalsIgnoreCase("Success")){ + success ++; + } + } + } + + datasource.setApiConfiguration(apiDefinitionListWithStatus); + if(success == apiDefinitionList.size()){ + return ResultHolder.success(datasource); + } + if(success > 0 && success < apiDefinitionList.size() ){ + return ResultHolder.error("Datasource has invalid tables", datasource); + } + return ResultHolder.error("Datasource is invalid.", datasource); } - if (status.equalsIgnoreCase("Warning")) { - return ResultHolder.error("Datasource has invalid items"); - } - if (status.equalsIgnoreCase("Error")) { - return ResultHolder.error("Datasource is invalid"); - } - return ResultHolder.success("Success"); + return ResultHolder.success(datasource); }catch (Exception e){ return ResultHolder.error("Datasource is invalid: " + e.getMessage()); } @@ -187,17 +231,29 @@ public class DatasourceService { DatasourceProvider datasourceProvider = ProviderFactory.getProvider(datasource.getType()); DatasourceRequest datasourceRequest = new DatasourceRequest(); datasourceRequest.setDatasource(datasource); - String status = datasourceProvider.checkStatus(datasourceRequest); - datasource.setStatus(status); - if (status.equalsIgnoreCase("Success")) { - return ResultHolder.success("Success"); - } - if (status.equalsIgnoreCase("Warning")) { - return ResultHolder.error("Datasource has invalid items"); - } - if (status.equalsIgnoreCase("Error")) { - return ResultHolder.error("Datasource is invalid"); + String datasourceStatus = datasourceProvider.checkStatus(datasourceRequest); + datasource.setStatus(datasourceStatus); + + if(datasource.getType().equalsIgnoreCase("api")){ + List apiDefinitionList = JSONObject.parseArray(datasource.getConfiguration(), ApiDefinition.class); + JSONObject apiItemStatuses = JSONObject.parseObject(datasourceStatus); + int success = 0; + for (ApiDefinition apiDefinition : apiDefinitionList) { + String status = apiItemStatuses.getString(apiDefinition.getName()); + apiDefinition.setStatus(status); + if(status.equalsIgnoreCase("Success")){ + success ++; + } + } + if(success == apiDefinitionList.size()){ + return ResultHolder.success(datasource); + } + if(success > 0 && success < apiDefinitionList.size() ){ + return ResultHolder.error("Datasource has invalid tables", datasource); + } + return ResultHolder.error("Datasource is invalid.", datasource); } + return ResultHolder.success("Success"); }catch (Exception e){ datasource.setStatus("Error"); @@ -219,12 +275,14 @@ public class DatasourceService { DatasourceProvider datasourceProvider = ProviderFactory.getProvider(ds.getType()); DatasourceRequest datasourceRequest = new DatasourceRequest(); datasourceRequest.setDatasource(ds); - datasourceProvider.checkStatus(datasourceRequest); + if(!datasource.getType().equalsIgnoreCase("api")){ + datasourceProvider.checkStatus(datasourceRequest); + } + List tables = datasourceProvider.getTables(datasourceRequest); - // 获取当前数据源下的db类型数据集 + // 获取当前数据源下的db、api类型数据集 DatasetTableExample datasetTableExample = new DatasetTableExample(); - datasetTableExample.createCriteria().andTypeIn(Arrays.asList("db","api")).andDataSourceIdEqualTo(datasource.getId()); List datasetTables = datasetTableMapper.selectByExampleWithBLOBs(datasetTableExample); List list = new ArrayList<>(); 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 13335f6742..d1ee94fafc 100644 --- a/backend/src/main/resources/db/migration/V32__1.8.sql +++ b/backend/src/main/resources/db/migration/V32__1.8.sql @@ -353,3 +353,6 @@ SET FOREIGN_KEY_CHECKS = 1; ALTER TABLE `panel_view` ADD COLUMN `position` varchar(255) NULL DEFAULT 'panel' COMMENT '视图位置 panel 仪表板中,tab Tab页中' AFTER `update_time`; + +ALTER TABLE `datasource` + CHANGE COLUMN `status` `status` LONGTEXT NULL DEFAULT NULL COMMENT '状态' ; diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index 48c2fc2982..0b8b52bd60 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -1337,7 +1337,11 @@ export default { auth_config_info: 'Permission verification is required for the request', verified: 'Verified', verification_method: 'Verification Method', - username: 'Username' + username: 'Username', + api_table_not_empty: 'API data table cannot be empty', + has_repeat_name: 'Duplicate API data table name', + valid: 'Valid', + invalid: 'Invalid' }, pblink: { key_pwd: 'Please enter the password to open the link', diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index 7c7e66103d..16b9565570 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -1338,7 +1338,11 @@ export default { auth_config_info: '請求需要進行權限校驗', verified: '認證', verification_method: '認證方式', - username: '用戶名' + username: '用戶名', + api_table_not_empty: 'API 數據表不能為空', + has_repeat_name: 'API 數據表名稱重複', + valid: '有效', + invalid: '無效' }, pblink: { key_pwd: '請輸入密碼打開鏈接', diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index c318df97e6..e8f9ffebca 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -1346,7 +1346,11 @@ export default { auth_config_info: '请求需要进行权限校验', verified: '认证', verification_method: '认证方式', - username: '用户名' + username: '用户名', + api_table_not_empty: 'API 数据表不能为空', + has_repeat_name: 'API 数据表名称重复', + valid: '有效', + invalid: '无效' }, pblink: { key_pwd: '请输入密码打开链接', diff --git a/frontend/src/views/system/datasource/form.vue b/frontend/src/views/system/datasource/form.vue index ec700d09e9..05ad8a15f5 100644 --- a/frontend/src/views/system/datasource/form.vue +++ b/frontend/src/views/system/datasource/form.vue @@ -48,6 +48,18 @@ + + + + +