feat: 应用导入的时候可以选择已有的数据集进行创建仪表板 (#17154)

This commit is contained in:
王嘉豪
2025-10-11 13:07:57 +08:00
committed by GitHub
parent cd7ed86fc2
commit dfd136c5e5
10 changed files with 413 additions and 255 deletions

View File

@@ -46,6 +46,7 @@ import io.dataease.i18n.Translator;
import io.dataease.license.config.XpackInteract;
import io.dataease.license.manage.CoreLicManage;
import io.dataease.log.DeLog;
import io.dataease.menu.dao.auto.entity.CoreMenu;
import io.dataease.model.BusiNodeRequest;
import io.dataease.model.BusiNodeVO;
import io.dataease.operation.manage.CoreOptRecentManage;
@@ -236,6 +237,65 @@ public class DataVisualizationServer implements DataVisualizationApi {
return null;
}
private void appDatasetMatch(VisualizationExport2AppVO appData, Map<Long, Long> datasourceIdMap, Map<Long, Long> dsGroupIdMap, Map<Long, Long> dsTableIdMap, Map<Long, Long> dsTableFieldsIdMap) {
List<AppCoreDatasetGroupVO> sourceDatasetGroupList = appData.getDatasetGroupsInfo();
List<AppCoreDatasetTableVO> sourceDatasetTableList = appData.getDatasetTablesInfo();
List<AppCoreDatasetTableFieldVO> sourceDatasetTableFieldList = appData.getDatasetTableFieldsInfo();
Map<Long, List<AppCoreDatasetTableVO>> sourceDatasetTableMap =
DeCollectionUtils.groupBy(sourceDatasetTableList, AppCoreDatasetTableVO::getDatasetGroupId);
Map<Long, List<AppCoreDatasetTableFieldVO>> sourceDatasetTableFieldMap =
DeCollectionUtils.groupBy(sourceDatasetTableFieldList, AppCoreDatasetTableFieldVO::getDatasetTableId);
sourceDatasetGroupList.forEach(sourceDatasetGroup -> {
Long systemDatasetGroupId = sourceDatasetGroup.getSystemDatasetId();
Long sourceDatasetGroupId = sourceDatasetGroup.getId();
// 获取 dsGroupIdMap
dsGroupIdMap.put(sourceDatasetGroup.getId(), systemDatasetGroupId);
CoreDatasetGroup systemDatasetGroup = coreDatasetGroupMapper.selectById(systemDatasetGroupId);
if (systemDatasetGroup != null) {
QueryWrapper<CoreDatasetTable> wrapper = new QueryWrapper<>();
wrapper.eq("dataset_group_id", systemDatasetGroupId);
List<CoreDatasetTable> systemDatasetTableList = coreDatasetTableMapper.selectList(wrapper);
List<AppCoreDatasetTableVO> sourceDatasetTableListSub = sourceDatasetTableMap.get(sourceDatasetGroupId);
if (systemDatasetTableList != null && sourceDatasetTableListSub != null) {
for (AppCoreDatasetTableVO sourceTable : sourceDatasetTableListSub) {
for (CoreDatasetTable systemTable : systemDatasetTableList) {
if (sourceTable.getTableName().equals(systemTable.getTableName())) {
// 获取dsTableIdMap datasourceIdMap
dsTableIdMap.put(sourceTable.getId(), systemTable.getId());
datasourceIdMap.put(sourceTable.getDatasourceId(), systemTable.getDatasourceId());
// 获取 dsTableFieldsIdMap
List<AppCoreDatasetTableFieldVO> sourceDatasetTableFieldListSub = sourceDatasetTableFieldMap.get(sourceTable.getId());
QueryWrapper<CoreDatasetTableField> wrapperField = new QueryWrapper<>();
wrapper.eq("dataset_table_id", systemTable.getId());
List<CoreDatasetTableField> systemDatasetTableFieldSub = coreDatasetTableFieldMapper.selectList(wrapperField);
for (AppCoreDatasetTableFieldVO sourceTableField : sourceDatasetTableFieldListSub) {
for (CoreDatasetTableField systemTableField : systemDatasetTableFieldSub) {
if (sourceTable.getTableName().equals(systemTable.getTableName())) {
// 获取dsTableIdMap datasourceIdMap
dsTableFieldsIdMap.put(sourceTableField.getId(), systemTableField.getId());
break;
}
}
}
break;
}
}
}
}
}
});
}
@DeLog(id = "#p0.id", pid = "#p0.pid", ot = LogOT.CREATE, stExp = "#p0.type")
@Override
@Transactional
@@ -264,149 +324,154 @@ public class DataVisualizationServer implements DataVisualizationApi {
Map<String, String> excelTableNamesMap = new HashMap<>();
if (appData != null) {
isAppSave = true;
try {
List<AppCoreDatasourceVO> appCoreDatasourceVO = appData.getDatasourceInfo();
// app 数据源 excel 表名映射
appCoreDatasourceVO.forEach(datasourceOld -> {
newDatasourceId.add(datasourceOld.getSystemDatasourceId());
// Excel 数据表明映射
if (StringUtils.isNotEmpty(datasourceOld.getConfiguration())) {
if (datasourceOld.getType().equals(DatasourceConfiguration.DatasourceType.API.name())) {
DEException.throwException(Translator.get("i18n_app_error_no_api"));
} else if (datasourceOld.getType().equals(DatasourceConfiguration.DatasourceType.Excel.name())) {
dsTableNamesMap.put(datasourceOld.getId(), ExcelUtils.getTableNamesMap(datasourceOld.getType(), datasourceOld.getConfiguration()));
} else if (datasourceOld.getType().contains(DatasourceConfiguration.DatasourceType.API.name())) {
dsTableNamesMap.put(datasourceOld.getId(), (Map<String, String>) datasourceServer.invokeMethod(datasourceOld.getType(), "getTableNamesMap", String.class, datasourceOld.getConfiguration()));
if ("dataset".equals(request.getDataType())) {
appDatasetMatch(appData, datasourceIdMap, dsGroupIdMap, dsTableIdMap, dsTableFieldsIdMap);
} else {
try {
List<AppCoreDatasourceVO> appCoreDatasourceVO = appData.getDatasourceInfo();
// app 数据源 excel 表名映射
appCoreDatasourceVO.forEach(datasourceOld -> {
newDatasourceId.add(datasourceOld.getSystemDatasourceId());
// Excel 数据表明映射
if (StringUtils.isNotEmpty(datasourceOld.getConfiguration())) {
if (datasourceOld.getType().equals(DatasourceConfiguration.DatasourceType.API.name())) {
DEException.throwException(Translator.get("i18n_app_error_no_api"));
} else if (datasourceOld.getType().equals(DatasourceConfiguration.DatasourceType.Excel.name())) {
dsTableNamesMap.put(datasourceOld.getId(), ExcelUtils.getTableNamesMap(datasourceOld.getType(), datasourceOld.getConfiguration()));
} else if (datasourceOld.getType().contains(DatasourceConfiguration.DatasourceType.API.name())) {
dsTableNamesMap.put(datasourceOld.getId(), (Map<String, String>) datasourceServer.invokeMethod(datasourceOld.getType(), "getTableNamesMap", String.class, datasourceOld.getConfiguration()));
}
}
}
});
});
List<CoreDatasource> systemDatasource = coreDatasourceMapper.selectBatchIds(newDatasourceId);
systemDatasource.forEach(datasourceNew -> {
// Excel 数据表明映射
if (StringUtils.isNotEmpty(datasourceNew.getConfiguration())) {
if (datasourceNew.getType().equals(DatasourceConfiguration.DatasourceType.Excel.name())) {
dsTableNamesMap.put(datasourceNew.getId(), ExcelUtils.getTableNamesMap(datasourceNew.getType(), datasourceNew.getConfiguration()));
excelDatasourceId.add(datasourceNew.getId());
} else if (datasourceNew.getType().contains(DatasourceConfiguration.DatasourceType.API.name())) {
dsTableNamesMap.put(datasourceNew.getId(), (Map<String, String>) datasourceServer.invokeMethod(datasourceNew.getType(), "getTableNamesMap", String.class, datasourceNew.getConfiguration()));
List<CoreDatasource> systemDatasource = coreDatasourceMapper.selectBatchIds(newDatasourceId);
systemDatasource.forEach(datasourceNew -> {
// Excel 数据表明映射
if (StringUtils.isNotEmpty(datasourceNew.getConfiguration())) {
if (datasourceNew.getType().equals(DatasourceConfiguration.DatasourceType.Excel.name())) {
dsTableNamesMap.put(datasourceNew.getId(), ExcelUtils.getTableNamesMap(datasourceNew.getType(), datasourceNew.getConfiguration()));
excelDatasourceId.add(datasourceNew.getId());
} else if (datasourceNew.getType().contains(DatasourceConfiguration.DatasourceType.API.name())) {
dsTableNamesMap.put(datasourceNew.getId(), (Map<String, String>) datasourceServer.invokeMethod(datasourceNew.getType(), "getTableNamesMap", String.class, datasourceNew.getConfiguration()));
}
}
}
});
datasourceIdMap.putAll(appData.getDatasourceInfo().stream().collect(Collectors.toMap(AppCoreDatasourceVO::getId, AppCoreDatasourceVO::getSystemDatasourceId)));
Long datasetFolderPid = request.getDatasetFolderPid();
String datasetFolderName = request.getDatasetFolderName();
//新建数据集分组
DatasetGroupInfoDTO datasetFolderNewRequest = new DatasetGroupInfoDTO();
datasetFolderNewRequest.setName(datasetFolderName);
datasetFolderNewRequest.setNodeType("folder");
datasetFolderNewRequest.setPid(datasetFolderPid);
DatasetGroupInfoDTO datasetFolderNew = datasetGroupManage.save(datasetFolderNewRequest, false, false);
Long datasetFolderNewId = datasetFolderNew.getId();
//新建数据集
appData.getDatasetGroupsInfo().forEach(appDatasetGroup -> {
if ("dataset".equals(appDatasetGroup.getNodeType())) {
Long oldId = appDatasetGroup.getId();
});
datasourceIdMap.putAll(appData.getDatasourceInfo().stream().collect(Collectors.toMap(AppCoreDatasourceVO::getId, AppCoreDatasourceVO::getSystemDatasourceId)));
Long datasetFolderPid = request.getDatasetFolderPid();
String datasetFolderName = request.getDatasetFolderName();
//新建数据集分组
DatasetGroupInfoDTO datasetFolderNewRequest = new DatasetGroupInfoDTO();
datasetFolderNewRequest.setName(datasetFolderName);
datasetFolderNewRequest.setNodeType("folder");
datasetFolderNewRequest.setPid(datasetFolderPid);
DatasetGroupInfoDTO datasetFolderNew = datasetGroupManage.save(datasetFolderNewRequest, false, false);
Long datasetFolderNewId = datasetFolderNew.getId();
//新建数据集
appData.getDatasetGroupsInfo().forEach(appDatasetGroup -> {
if ("dataset".equals(appDatasetGroup.getNodeType())) {
Long oldId = appDatasetGroup.getId();
Long newId = IDUtils.snowID();
DatasetGroupInfoDTO datasetNewRequest = new DatasetGroupInfoDTO();
BeanUtils.copyBean(datasetNewRequest, appDatasetGroup);
datasetNewRequest.setId(newId);
datasetNewRequest.setCreateBy(AuthUtils.getUser().getUserId() + "");
datasetNewRequest.setUpdateBy(AuthUtils.getUser().getUserId() + "");
datasetNewRequest.setCreateTime(time);
datasetNewRequest.setLastUpdateTime(time);
datasetNewRequest.setPid(datasetFolderNewId);
try {
newDsGroupInfo.add(datasetNewRequest);
dsGroupIdMap.put(oldId, newId);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
// 新建数据集表
appData.getDatasetTablesInfo().forEach(appCoreDatasetTableVO -> {
Long oldId = appCoreDatasetTableVO.getId();
Long newId = IDUtils.snowID();
DatasetGroupInfoDTO datasetNewRequest = new DatasetGroupInfoDTO();
BeanUtils.copyBean(datasetNewRequest, appDatasetGroup);
datasetNewRequest.setId(newId);
datasetNewRequest.setCreateBy(AuthUtils.getUser().getUserId() + "");
datasetNewRequest.setUpdateBy(AuthUtils.getUser().getUserId() + "");
datasetNewRequest.setCreateTime(time);
datasetNewRequest.setLastUpdateTime(time);
datasetNewRequest.setPid(datasetFolderNewId);
try {
newDsGroupInfo.add(datasetNewRequest);
dsGroupIdMap.put(oldId, newId);
} catch (Exception e) {
throw new RuntimeException(e);
CoreDatasetTable datasetTable = new CoreDatasetTable();
BeanUtils.copyBean(datasetTable, appCoreDatasetTableVO);
datasetTable.setDatasetGroupId(dsGroupIdMap.get(datasetTable.getDatasetGroupId()));
datasetTable.setId(newId);
datasetTable.setDatasourceId(datasourceIdMap.get(datasetTable.getDatasourceId()));
coreDatasetTableMapper.insert(datasetTable);
dsTableIdMap.put(oldId, newId);
});
// 新建数据字段
appData.getDatasetTableFieldsInfo().forEach(appDsTableFields -> {
Long oldId = appDsTableFields.getId();
Long newId = IDUtils.snowID();
CoreDatasetTableField dsDsField = new CoreDatasetTableField();
BeanUtils.copyBean(dsDsField, appDsTableFields);
dsDsField.setDatasetGroupId(dsGroupIdMap.get(dsDsField.getDatasetGroupId()));
dsDsField.setDatasetTableId(dsTableIdMap.get(dsDsField.getDatasetTableId()));
dsDsField.setDatasourceId(datasourceIdMap.get(dsDsField.getDatasourceId()));
dsDsField.setId(newId);
dsTableFieldsList.add(dsDsField);
dsTableFieldsIdMap.put(oldId, newId);
});
// dsTableFields 中存在计算字段在OriginName中 也需要替换
dsTableFieldsList.forEach(dsTableFields -> {
dsTableFieldsIdMap.forEach((key, value) -> {
dsTableFields.setOriginName(dsTableFields.getOriginName().replaceAll(key.toString(), value.toString()));
});
coreDatasetTableFieldMapper.insert(dsTableFields);
});
List<String> dsGroupNameSave = new ArrayList<>();
// 持久化数据集
newDsGroupInfo.forEach(dsGroup -> {
dsTableIdMap.forEach((key, value) -> {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(key.toString(), value.toString()));
});
dsTableFieldsIdMap.forEach((key, value) -> {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(key.toString(), value.toString()));
});
datasourceIdMap.forEach((key, value) -> {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(key.toString(), value.toString()));
//表名映射更新
Map<String, String> appDsTableNamesMap = dsTableNamesMap.get(key);
Map<String, String> systemDsTableNamesMap = dsTableNamesMap.get(value);
if (MapUtils.isNotEmpty(appDsTableNamesMap)) {
appDsTableNamesMap.forEach((keyName, valueName) -> {
if (MapUtils.isNotEmpty(systemDsTableNamesMap) && StringUtils.isNotEmpty(systemDsTableNamesMap.get(keyName))) {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(valueName, systemDsTableNamesMap.get(keyName)));
excelTableNamesMap.put(valueName, systemDsTableNamesMap.get(keyName));
} else {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(valueName, "excel_can_not_find"));
}
});
}
});
if (dsGroupNameSave.contains(dsGroup.getName())) {
dsGroup.setName(dsGroup.getName() + "-" + UUID.randomUUID().toString());
}
}
});
// 新建数据集表
appData.getDatasetTablesInfo().forEach(appCoreDatasetTableVO -> {
Long oldId = appCoreDatasetTableVO.getId();
Long newId = IDUtils.snowID();
CoreDatasetTable datasetTable = new CoreDatasetTable();
BeanUtils.copyBean(datasetTable, appCoreDatasetTableVO);
datasetTable.setDatasetGroupId(dsGroupIdMap.get(datasetTable.getDatasetGroupId()));
datasetTable.setId(newId);
datasetTable.setDatasourceId(datasourceIdMap.get(datasetTable.getDatasourceId()));
coreDatasetTableMapper.insert(datasetTable);
dsTableIdMap.put(oldId, newId);
});
// 新建数据字段
appData.getDatasetTableFieldsInfo().forEach(appDsTableFields -> {
Long oldId = appDsTableFields.getId();
Long newId = IDUtils.snowID();
CoreDatasetTableField dsDsField = new CoreDatasetTableField();
BeanUtils.copyBean(dsDsField, appDsTableFields);
dsDsField.setDatasetGroupId(dsGroupIdMap.get(dsDsField.getDatasetGroupId()));
dsDsField.setDatasetTableId(dsTableIdMap.get(dsDsField.getDatasetTableId()));
dsDsField.setDatasourceId(datasourceIdMap.get(dsDsField.getDatasourceId()));
dsDsField.setId(newId);
dsTableFieldsList.add(dsDsField);
dsTableFieldsIdMap.put(oldId, newId);
});
// dsTableFields 中存在计算字段在OriginName中 也需要替换
dsTableFieldsList.forEach(dsTableFields -> {
dsTableFieldsIdMap.forEach((key, value) -> {
dsTableFields.setOriginName(dsTableFields.getOriginName().replaceAll(key.toString(), value.toString()));
});
coreDatasetTableFieldMapper.insert(dsTableFields);
});
List<String> dsGroupNameSave = new ArrayList<>();
// 持久化数据集
newDsGroupInfo.forEach(dsGroup -> {
dsTableIdMap.forEach((key, value) -> {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(key.toString(), value.toString()));
});
dsTableFieldsIdMap.forEach((key, value) -> {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(key.toString(), value.toString()));
});
datasourceIdMap.forEach((key, value) -> {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(key.toString(), value.toString()));
//表名映射更新
Map<String, String> appDsTableNamesMap = dsTableNamesMap.get(key);
Map<String, String> systemDsTableNamesMap = dsTableNamesMap.get(value);
if (MapUtils.isNotEmpty(appDsTableNamesMap)) {
appDsTableNamesMap.forEach((keyName, valueName) -> {
if (MapUtils.isNotEmpty(systemDsTableNamesMap) && StringUtils.isNotEmpty(systemDsTableNamesMap.get(keyName))) {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(valueName, systemDsTableNamesMap.get(keyName)));
excelTableNamesMap.put(valueName, systemDsTableNamesMap.get(keyName));
} else {
dsGroup.setInfo(dsGroup.getInfo().replaceAll(valueName, "excel_can_not_find"));
}
});
dsGroupNameSave.add(dsGroup.getName());
if (dsGroup.getIsCross() == null) {
if (dsGroup.getUnion() == null) {
dsGroup.setUnion(JsonUtil.parseList(dsGroup.getInfo(), new TypeReference<>() {
}));
}
datasetSQLManage.mergeDatasetCrossDefault(dsGroup);
}
excelAdaptor(dsGroup, excelTableNamesMap, excelDatasourceId);
datasetGroupManage.innerSave(dsGroup);
});
if (dsGroupNameSave.contains(dsGroup.getName())) {
dsGroup.setName(dsGroup.getName() + "-" + UUID.randomUUID().toString());
}
dsGroupNameSave.add(dsGroup.getName());
if (dsGroup.getIsCross() == null) {
if (dsGroup.getUnion() == null) {
dsGroup.setUnion(JsonUtil.parseList(dsGroup.getInfo(), new TypeReference<>() {
}));
}
datasetSQLManage.mergeDatasetCrossDefault(dsGroup);
}
excelAdaptor(dsGroup, excelTableNamesMap, excelDatasourceId);
datasetGroupManage.innerSave(dsGroup);
});
} catch (Exception e) {
LogUtil.error(e);
DEException.throwException(e);
} catch (Exception e) {
LogUtil.error(e);
DEException.throwException(e);
}
}
// 更换主数据内容
AtomicReference<String> componentDataStr = new AtomicReference<>(request.getComponentData());
dsGroupIdMap.forEach((key, value) -> {
@@ -953,22 +1018,22 @@ public class DataVisualizationServer implements DataVisualizationApi {
}
@DeLog(id = "#p0.id", ot = LogOT.APP_TEMPLATE_EXPORT, stExp = "#p0.type")
public void exportLogApp(DataVisualizationBaseRequest request){
public void exportLogApp(DataVisualizationBaseRequest request) {
}
@DeLog(id = "#p0.id", ot = LogOT.TEMPLATE_EXPORT, stExp = "#p0.type")
public void exportLogTemplate(DataVisualizationBaseRequest request){
public void exportLogTemplate(DataVisualizationBaseRequest request) {
}
@DeLog(id = "#p0.id", ot = LogOT.PDF_EXPORT, stExp = "#p0.type")
public void exportLogPDF(DataVisualizationBaseRequest request){
public void exportLogPDF(DataVisualizationBaseRequest request) {
}
@DeLog(id = "#p0.id", ot = LogOT.IMG_EXPORT, stExp = "#p0.type")
public void exportLogImg(DataVisualizationBaseRequest request){
public void exportLogImg(DataVisualizationBaseRequest request) {
}

View File

@@ -234,7 +234,8 @@ const saveCanvasWithCheck = (withPublish = false, status?) => {
pid: '',
name: dvInfo.value.name,
datasetFolderPid: null,
datasetFolderName: dvInfo.value.name
datasetFolderName: dvInfo.value.name,
dataType: dvInfo.value['dataType']
},
appData: appData.value
}

View File

@@ -153,7 +153,8 @@ const saveCanvasWithCheck = (withPublish = false, status?) => {
pid: '',
name: dvInfo.value.name,
datasetFolderPid: null,
datasetFolderName: dvInfo.value.name
datasetFolderName: dvInfo.value.name,
dataType: dvInfo.value['dataType']
},
appData: appData.value
}

View File

@@ -3061,8 +3061,11 @@ export default {
ds_group_name: 'Dataset Group Name',
ds_group_position: 'Dataset Group Position',
datasource_info: 'Datasource Information',
dataset_info: 'Dataset Information',
app_datasource: 'Application Datasource',
app_dataset: 'Application dataset',
sys_datasource: 'System Datasource',
sys_dataset: 'System dataset',
select_folder: 'Please select the associated folder',
belong_folder: 'Belonging Folder',
no_content: 'No relevant content found',
@@ -3070,6 +3073,7 @@ export default {
cancel: 'Cancel',
select_ds_group_folder: 'Please select the folder for the dataset group',
app_no_datasource_tips: 'There are unconfigured datasources',
app_no_dataset_tips: 'There are unconfigured datasets',
dataset: 'Dataset',
delete: 'Delete',
delete_success: 'Delete successful',

View File

@@ -2977,8 +2977,11 @@ export default {
ds_group_name: '數據集分組名稱',
ds_group_position: '數據集分組位置',
datasource_info: '數據源信息',
dataset_info: '數據集信息',
app_datasource: '應用數據源',
app_dataset: '應用數據集',
sys_datasource: '系統數據源',
sys_dataset: '系統數據集',
select_folder: '請選擇所屬文件夾',
belong_folder: '所屬文件夾',
no_content: '沒有找到相關內容',
@@ -2986,6 +2989,7 @@ export default {
cancel: '取消',
select_ds_group_folder: '請選擇數據集分組所屬文件夾',
app_no_datasource_tips: '存在未配置的數據源',
app_no_dataset_tips: '存在未配置的數據集',
dataset: '數據集',
delete: '刪除',
delete_success: '刪除成功',

View File

@@ -2987,8 +2987,11 @@ export default {
ds_group_name: '数据集分组名称',
ds_group_position: '数据集分组位置',
datasource_info: '数据源信息',
dataset_info: '数据集信息',
app_datasource: '应用数据源',
app_dataset: '应用数据集',
sys_datasource: '系统数据源',
sys_dataset: '系统数据集',
select_folder: '请选择所属文件夹',
belong_folder: '所属文件夹',
no_content: '没有找到相关内容',
@@ -2996,6 +2999,7 @@ export default {
cancel: '取消',
select_ds_group_folder: '请选择数据集分组所属文件夹',
app_no_datasource_tips: '存在未配置的数据源',
app_no_dataset_tips: '存在未配置的数据集',
dataset: '数据集',
delete: '删除',
delete_success: '删除成功',

View File

@@ -14,7 +14,7 @@
<el-form
ref="appSaveForm"
:model="state.form"
:rules="state.rule"
:rules="isDatasourceMatch ? state.ruleDatasource : state.ruleDataset"
class="de-form-item app-form"
label-width="180px"
label-position="top"
@@ -51,120 +51,128 @@
</template>
</el-tree-select>
</el-form-item>
<el-form-item :label="t('visualization.ds_group_name')" prop="datasetFolderName">
<el-input
v-model="state.form.datasetFolderName"
autocomplete="off"
:placeholder="t('visualization.input_tips')"
/>
</el-form-item>
<el-form-item :label="t('visualization.ds_group_position')" prop="datasetFolderPid">
<el-tree-select
style="width: 100%"
@keydown.stop
@keyup.stop
v-model="state.form.datasetFolderPid"
:data="state.dsTree"
:props="state.propsTree"
@node-click="dsTreeSelect"
:render-after-expand="false"
filterable
>
<template #default="{ data: { name } }">
<span class="custom-tree-node">
<el-icon>
<Icon name="dv-folder"><dvFolder class="svg-icon" /></Icon>
</el-icon>
<span :title="name">{{ name }}</span>
</span>
</template>
</el-tree-select>
</el-form-item>
<el-form-item :label="t('visualization.data_match_type')" prop="dataType">
<el-radio-group v-model="state.form.dataType">
<el-radio size="small" :label="'datasource'">
{{ t('datasource.datasource') }}</el-radio
>
<el-radio size="small" :label="'dataset'">{{ t('dataset.datalist') }} </el-radio>
</el-radio-group>
<el-select v-model="state.form.dataType" :placeholder="t('chart.pls_select_field')">
<el-option key="datasource" :label="t('datasource.datasource')" value="datasource" />
<el-option key="dataset" :label="t('dataset.datalist')" value="dataset" />
</el-select>
</el-form-item>
<div class="de-row-rules" style="margin: 0 0 16px">
<span>{{ t('visualization.datasource_info') }}</span>
</div>
<el-row class="datasource-link" v-if="state.form.dataType === 'datasource'">
<el-row class="head">
<el-col :span="11">{{ t('visualization.app_datasource') }}</el-col
><el-col :span="2"></el-col
><el-col :span="11">{{ t('visualization.sys_datasource') }}</el-col>
<template v-if="isDatasourceMatch">
<el-form-item :label="t('visualization.ds_group_name')" prop="datasetFolderName">
<el-input
v-model="state.form.datasetFolderName"
autocomplete="off"
:placeholder="t('visualization.input_tips')"
/>
</el-form-item>
<el-form-item :label="t('visualization.ds_group_position')" prop="datasetFolderPid">
<el-tree-select
style="width: 100%"
@keydown.stop
@keyup.stop
v-model="state.form.datasetFolderPid"
:data="state.dsTree"
:props="state.propsTree"
@node-click="dsTreeSelect"
:render-after-expand="false"
filterable
>
<template #default="{ data: { name } }">
<span class="custom-tree-node">
<el-icon>
<Icon name="dv-folder"><dvFolder class="svg-icon" /></Icon>
</el-icon>
<span :title="name">{{ name }}</span>
</span>
</template>
</el-tree-select>
</el-form-item>
<div class="de-row-rules" style="margin: 0 0 16px">
<span>{{ t('visualization.datasource_info') }}</span>
</div>
<el-row class="datasource-link">
<el-row class="head">
<el-col :span="11">{{ t('visualization.app_datasource') }}</el-col
><el-col :span="2"></el-col
><el-col :span="11">{{ t('visualization.sys_datasource') }}</el-col>
</el-row>
<el-row
:key="index"
class="content"
v-for="(appDatasource, index) in state.appData.datasourceInfo"
>
<el-col :span="11">
<el-select style="width: 100%" v-model="appDatasource.name" disabled>
<el-option
:key="appDatasource.name"
:label="appDatasource.name"
:value="appDatasource.name"
>
</el-option>
</el-select> </el-col
><el-col :span="2" class="icon-center">
<Icon name="dv-link-target"
><dvLinkTarget
class="svg-icon"
style="width: 20px; height: 20px" /></Icon></el-col
><el-col :span="11">
<dataset-select
ref="datasetSelector"
v-model="appDatasource.systemDatasourceId"
style="flex: 1"
:state-obj="state"
themes="light"
source-type="datasource"
@add-ds-window="addDatasourceWindow"
view-id="0"
/>
</el-col>
</el-row>
</el-row>
<el-row
:key="index"
class="content"
v-for="(appDatasource, index) in state.appData.datasourceInfo"
>
<el-col :span="11">
<el-select style="width: 100%" v-model="appDatasource.name" disabled>
<el-option
:key="appDatasource.name"
:label="appDatasource.name"
:value="appDatasource.name"
>
</el-option>
</el-select> </el-col
><el-col :span="2" class="icon-center">
<Icon name="dv-link-target"
><dvLinkTarget class="svg-icon" style="width: 20px; height: 20px" /></Icon></el-col
><el-col :span="11">
<dataset-select
ref="datasetSelector"
v-model="appDatasource.systemDatasourceId"
style="flex: 1"
:state-obj="state"
themes="light"
source-type="datasource"
@add-ds-window="addDsWindow"
view-id="0"
/>
</el-col>
</template>
<template v-if="!isDatasourceMatch">
<div class="de-row-rules" style="margin: 0 0 16px">
<span>{{ t('visualization.dataset_info') }}</span>
</div>
<el-row class="datasource-link">
<el-row class="head">
<el-col :span="11">{{ t('visualization.app_dataset') }}</el-col
><el-col :span="2"></el-col
><el-col :span="11">{{ t('visualization.sys_dataset') }}</el-col>
</el-row>
<el-row
:key="index"
class="content"
v-for="(appDataset, index) in state.appData.datasetGroupsInfo"
>
<el-col :span="11">
<el-select style="width: 100%" v-model="appDataset.name" disabled>
<el-option
:key="appDataset.name"
:label="appDataset.name"
:value="appDataset.name"
>
</el-option>
</el-select> </el-col
><el-col :span="2" class="icon-center">
<Icon name="dv-link-target"
><dvLinkTarget
class="svg-icon"
style="width: 20px; height: 20px" /></Icon></el-col
><el-col :span="11">
<dataset-select
ref="datasetSelector"
v-model="appDataset.systemDatasetId"
style="flex: 1"
:state-obj="state"
themes="light"
@add-ds-window="addDatasetWindow"
view-id="0"
/>
</el-col>
</el-row>
</el-row>
</el-row>
<el-row class="datasource-link" v-if="state.form.dataType === 'dataset'">
<el-row class="head">
<el-col :span="11">{{ t('visualization.app_datasource') }}</el-col
><el-col :span="2"></el-col
><el-col :span="11">{{ t('visualization.sys_datasource') }}</el-col>
</el-row>
<el-row
:key="index"
class="content"
v-for="(appDatasource, index) in state.appData.datasourceInfo"
>
<el-col :span="11">
<el-select style="width: 100%" v-model="appDatasource.name" disabled>
<el-option
:key="appDatasource.name"
:label="appDatasource.name"
:value="appDatasource.name"
>
</el-option>
</el-select> </el-col
><el-col :span="2" class="icon-center">
<Icon name="dv-link-target"
><dvLinkTarget class="svg-icon" style="width: 20px; height: 20px" /></Icon></el-col
><el-col :span="11">
<dataset-select
ref="datasetSelector"
v-model="appDatasource.systemDatasourceId"
style="flex: 1"
:state-obj="state"
themes="light"
source-type="datasource"
@add-ds-window="addDsWindow"
view-id="0"
/>
</el-col>
</el-row>
</el-row>
</template>
</el-form>
</div>
<template #footer>
@@ -238,12 +246,19 @@ const dvPreName = computed(() =>
? t('work_branch.dashboard')
: t('work_branch.big_data_screen')
)
const addDsWindow = () => {
const isDatasourceMatch = computed(() => state.form.dataType === 'datasource')
const addDatasourceWindow = () => {
// do addDsWindow
const url = '#/data/datasource?opt=create'
window.open(url, openType)
}
const addDatasetWindow = () => {
// do addDsWindow
const url = '#/data/dataset?opt=create'
window.open(url, openType)
}
const state = reactive({
appApplyDrawer: false,
dvTree: [],
@@ -254,7 +269,8 @@ const state = reactive({
isLeaf: node => !node.children?.length
},
appData: {
datasourceInfo: []
datasourceInfo: [],
datasetGroupsInfo: []
},
form: {
pid: '',
@@ -263,7 +279,30 @@ const state = reactive({
datasetFolderName: null,
dataType: 'datasource'
},
rule: {
ruleDataset: {
name: [
{
required: true,
min: 2,
max: 25,
message: t('datasource.input_limit_2_25', [2, 25]),
trigger: 'blur'
}
],
pid: [
{
required: true,
message: t('visualization.select_folder'),
trigger: 'blur'
}
],
dataType: [
{
required: true
}
]
},
ruleDatasource: {
name: [
{
required: true,
@@ -348,6 +387,7 @@ const init = params => {
state.form = params.base
state.form.dataType = 'datasource'
state.appData.datasourceInfo = deepCopy(appData.value?.datasourceInfo)
state.appData.datasetGroupsInfo = deepCopy(appData.value?.datasetGroupsInfo)
initData()
}
@@ -367,23 +407,37 @@ const close = () => {
const saveApp = () => {
let datasourceMatchReady = true
let datasetMatchReady = true
state.appData.datasourceInfo.forEach(datasource => {
if (!datasource.systemDatasourceId) {
datasourceMatchReady = false
}
})
if (!datasourceMatchReady) {
state.appData.datasetGroupsInfo.forEach(dataset => {
if (!dataset.systemDatasetId) {
datasetMatchReady = false
}
})
if (!datasourceMatchReady && isDatasourceMatch.value) {
ElMessage.error(t('visualization.app_no_datasource_tips'))
return
}
if (!datasetMatchReady && !isDatasourceMatch.value) {
ElMessage.error(t('visualization.app_no_dataset_tips'))
return
}
appSaveForm.value?.validate(valid => {
if (valid) {
// 还原datasource
appData.value['datasourceInfo'] = state.appData.datasourceInfo
appData.value['datasetGroupsInfo'] = state.appData.datasetGroupsInfo
dvInfo.value['pid'] = state.form.pid
dvInfo.value['name'] = state.form.name
dvInfo.value['datasetFolderPid'] = state.form.datasetFolderPid
dvInfo.value['datasetFolderName'] = state.form.datasetFolderName
dvInfo.value['dataType'] = state.form.dataType
dvInfo.value['dataState'] = 'ready'
snapshotStore.recordSnapshotCache('renderChart')
emits('saveAppCanvas')

View File

@@ -67,6 +67,9 @@ public class DataVisualizationBaseRequest extends DataVisualizationVO {
//数据来源 core 主表 snapshot 镜像表
private String resourceTable = "core";
//应用数据来源 datasource 数据源 dataset 数据集
private String dataType = "datasource";
public DataVisualizationBaseRequest(Long id,String busiFlag,String resource,String source) {
this.busiFlag = busiFlag;
this.resourceTable = resource;

View File

@@ -89,4 +89,9 @@ public class AppCoreDatasetGroupVO implements Serializable {
* 是否跨源
*/
private Boolean isCross;
/**
* 映射系统数据集ID
*/
private Long systemDatasetId;
}

View File

@@ -0,0 +1,17 @@
package io.dataease.utils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class DeCollectionUtils {
public static <K, V> Map<K, List<V>> groupBy(List<V> list,
Function<V, K> keyExtractor) {
if (list == null || list.isEmpty()) {
return new HashMap<>();
}
return list.stream().collect(Collectors.groupingBy(keyExtractor));
}
}