forked from github/dataease
Merge pull request #10873 from dataease/pr@dev-v2@feat_app-export
feat(数据大屏、仪表板): 支持应用导出
This commit is contained in:
commit
ce97990761
@ -2,7 +2,13 @@ package io.dataease.visualization.server;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import io.dataease.api.visualization.vo.VisualizationReportFilterVO;
|
||||
import io.dataease.api.visualization.vo.*;
|
||||
import io.dataease.dataset.manage.DatasetDataManage;
|
||||
import io.dataease.dataset.manage.DatasetGroupManage;
|
||||
import io.dataease.dataset.manage.DatasetTableManage;
|
||||
import io.dataease.extensions.datasource.dto.DatasetTableDTO;
|
||||
import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO;
|
||||
import io.dataease.extensions.datasource.dto.DatasourceDTO;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import io.dataease.api.template.dto.TemplateManageFileDTO;
|
||||
import io.dataease.api.template.dto.VisualizationTemplateExtendDataDTO;
|
||||
@ -10,9 +16,6 @@ import io.dataease.api.visualization.DataVisualizationApi;
|
||||
import io.dataease.api.visualization.dto.VisualizationViewTableDTO;
|
||||
import io.dataease.api.visualization.request.DataVisualizationBaseRequest;
|
||||
import io.dataease.api.visualization.request.VisualizationWorkbranchQueryRequest;
|
||||
import io.dataease.api.visualization.vo.DataVisualizationVO;
|
||||
import io.dataease.api.visualization.vo.VisualizationResourceVO;
|
||||
import io.dataease.api.visualization.vo.VisualizationWatermarkVO;
|
||||
import io.dataease.chart.dao.auto.entity.CoreChartView;
|
||||
import io.dataease.chart.dao.auto.mapper.CoreChartViewMapper;
|
||||
import io.dataease.chart.manage.ChartDataManage;
|
||||
@ -22,6 +25,7 @@ import io.dataease.commons.constants.OptConstants;
|
||||
import io.dataease.constant.CommonConstants;
|
||||
import io.dataease.constant.LogOT;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.i18n.Translator;
|
||||
import io.dataease.license.config.XpackInteract;
|
||||
import io.dataease.log.DeLog;
|
||||
import io.dataease.model.BusiNodeRequest;
|
||||
@ -41,6 +45,7 @@ import io.dataease.visualization.dao.ext.mapper.ExtDataVisualizationMapper;
|
||||
import io.dataease.visualization.manage.CoreVisualizationManage;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@ -91,6 +96,12 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
@Resource
|
||||
private VisualizationWatermarkMapper watermarkMapper;
|
||||
|
||||
@Resource
|
||||
private DatasetGroupManage datasetGroupManage;
|
||||
|
||||
@Resource
|
||||
private DatasetDataManage datasetDataManage;
|
||||
|
||||
@Override
|
||||
public DataVisualizationVO findCopyResource(Long dvId, String busiFlag) {
|
||||
DataVisualizationVO result = findById(new DataVisualizationBaseRequest(dvId, busiFlag));
|
||||
@ -390,6 +401,41 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VisualizationExport2AppVO export2AppCheck(Long dvId) {
|
||||
//1.获取所有视图信息
|
||||
List<ChartViewDTO> chartViewsInfo = chartViewManege.listBySceneId(dvId);
|
||||
//2.获取视图扩展字段信息 获取所有数据集信息
|
||||
List<Long> allTableIds = chartViewsInfo.stream().map(ChartViewDTO::getTableId).collect(Collectors.toList());
|
||||
List<DatasetTableDTO> datasetTablesInfo = datasetGroupManage.getDetail(allTableIds);
|
||||
// dataset check
|
||||
if (CollectionUtils.isEmpty(datasetTablesInfo)) {
|
||||
return new VisualizationExport2AppVO(Translator.get("I18N_APP_NO_DATASET_ERROR"));
|
||||
}
|
||||
//4.获取所有数据集字段信息
|
||||
List<DatasetTableFieldDTO> datasetTableFieldsInfo = new ArrayList<>();
|
||||
datasetTablesInfo.stream().forEach(datasetTable ->{
|
||||
try {
|
||||
List<DatasetTableFieldDTO> result = datasetDataManage.getTableFields(datasetTable);
|
||||
if(!CollectionUtils.isEmpty(result)){
|
||||
datasetTableFieldsInfo.addAll(result);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
//校验标准 1.存在视图且所有视图的数据来源必须是dataset 2.存在数据集且没有excel数据集 3.存在数据源且是单数据源
|
||||
//1.view check
|
||||
if (CollectionUtils.isEmpty(chartViewsInfo)) {
|
||||
return new VisualizationExport2AppVO(Translator.get("I18N_APP_NO_VIEW_ERROR"));
|
||||
} else if (chartViewsInfo.stream().filter(chartView -> chartView.getDataFrom().equals("template")).collect(Collectors.toList()).size() > 0) {
|
||||
return new VisualizationExport2AppVO(Translator.get("I18N_APP_TEMPLATE_VIEW_ERROR"));
|
||||
}
|
||||
return new VisualizationExport2AppVO(chartViewsInfo, null, datasetTablesInfo, datasetTableFieldsInfo,
|
||||
null, null, null, null, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void nameCheck(DataVisualizationBaseRequest request) {
|
||||
|
@ -94,3 +94,11 @@ export const getComponentInfo = dvId => {
|
||||
loading: false
|
||||
})
|
||||
}
|
||||
|
||||
export const export2AppCheck = dvId => {
|
||||
return request.get({
|
||||
url: '/dataVisualization/export2AppCheck/' + dvId,
|
||||
method: 'get',
|
||||
loading: true
|
||||
})
|
||||
}
|
||||
|
147
core/core-frontend/src/components/de-app/AppExportForm.vue
Normal file
147
core/core-frontend/src/components/de-app/AppExportForm.vue
Normal file
@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:title="'应用导出'"
|
||||
v-model:visible="state.applyDownloadDrawer"
|
||||
custom-class="de-user-drawer"
|
||||
size="600px"
|
||||
direction="rtl"
|
||||
>
|
||||
<div class="app-export">
|
||||
<el-form
|
||||
ref="applyDownloadForm"
|
||||
:model="state.form"
|
||||
:rules="state.rule"
|
||||
size="small"
|
||||
class="de-form-item"
|
||||
label-width="180px"
|
||||
label-position="right"
|
||||
>
|
||||
<el-form-item :label="'应用名称'" prop="appName">
|
||||
<el-input v-model="form.appName" autocomplete="off" :placeholder="'请输入名称'" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="'应用版本号'" prop="version">
|
||||
<el-input v-model="state.form.version" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="'DataEase最低版本号'" prop="required">
|
||||
<el-input v-model="state.form.required" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="'作者'" prop="creator">
|
||||
<el-input v-model="state.form.creator" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="'描述'" prop="description">
|
||||
<el-input
|
||||
:placeholder="'请输入内容'"
|
||||
show-word-limit
|
||||
:value="state.form.description"
|
||||
type="textarea"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="app-export-bottom">
|
||||
<div class="apply" style="width: 100%">
|
||||
<el-button secondary @click="close">{{ $t('commons.cancel') }} </el-button>
|
||||
<el-button type="primary" @click="downloadApp">{{ $t('app_template.export') }} </el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElButton, ElDrawer, ElForm, ElFormItem, ElInput } from 'element-plus-secondary'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
const emits = defineEmits(['closeDraw', 'downLoadApp'])
|
||||
const applyDownloadForm = ref(null)
|
||||
const state = reactive({
|
||||
applyDownloadDrawer: false,
|
||||
form: {
|
||||
appName: null,
|
||||
icon: null,
|
||||
version: null,
|
||||
creator: null,
|
||||
required: '1.16.0',
|
||||
description: null
|
||||
},
|
||||
rule: {
|
||||
appName: [
|
||||
{
|
||||
required: true,
|
||||
min: 2,
|
||||
max: 25,
|
||||
message: t('datasource.input_limit_2_25', [2, 25]),
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
creator: [
|
||||
{
|
||||
required: true,
|
||||
min: 2,
|
||||
max: 25,
|
||||
message: t('datasource.input_limit_2_25', [2, 25]),
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
required: [
|
||||
{
|
||||
required: true,
|
||||
min: 2,
|
||||
max: 25,
|
||||
message: t('datasource.input_limit_2_25', [2, 25]),
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
version: [
|
||||
{
|
||||
required: true,
|
||||
min: 2,
|
||||
max: 25,
|
||||
message: t('datasource.input_limit_2_25', [2, 25]),
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const init = params => {
|
||||
state.applyDownloadDrawer = true
|
||||
state.form = params
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
emits('closeDraw')
|
||||
state.applyDownloadDrawer = false
|
||||
}
|
||||
|
||||
const downloadApp = () => {
|
||||
applyDownloadForm.value?.validate(valid => {
|
||||
if (valid) {
|
||||
emits('downLoadApp', state.form)
|
||||
state.applyDownloadDrawer = false
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
init
|
||||
})
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.app-export {
|
||||
width: 100%;
|
||||
height: calc(100% - 56px);
|
||||
}
|
||||
|
||||
.app-export-bottom {
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
:deep(.ed-drawer__body) {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
</style>
|
@ -15,9 +15,12 @@ import { Icon } from '@/components/icon-custom'
|
||||
import { download2AppTemplate, downloadCanvas2 } from '@/utils/imgUtils'
|
||||
import MultiplexPreviewShow from '@/views/data-visualization/MultiplexPreviewShow.vue'
|
||||
import DvPreview from '@/views/data-visualization/DvPreview.vue'
|
||||
import AppExportForm from "@/components/de-app/AppExportForm.vue";
|
||||
import {personInfoApi} from "@/api/user";
|
||||
import {ElMessage} from "element-plus-secondary";
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { dvInfo } = storeToRefs(dvMainStore)
|
||||
const { dvInfo, canvasViewDataInfo } = storeToRefs(dvMainStore)
|
||||
const previewCanvasContainer = ref(null)
|
||||
const dvPreviewRef = ref(null)
|
||||
const slideShow = ref(true)
|
||||
@ -26,6 +29,7 @@ const permissionStore = usePermissionStoreWithOut()
|
||||
const dataInitState = ref(true)
|
||||
const downloadStatus = ref(false)
|
||||
const { width, node } = useMoveLine('DASHBOARD')
|
||||
const appExportFormRef = ref(null)
|
||||
const props = defineProps({
|
||||
showPosition: {
|
||||
required: false,
|
||||
@ -110,6 +114,46 @@ const downloadAsAppTemplate = downloadType => {
|
||||
})
|
||||
}
|
||||
|
||||
const downLoadToAppPre =()=>{
|
||||
const result = checkTemplate()
|
||||
if (result && result.length > 0) {
|
||||
ElMessage.warning(`当前仪表板中[${result}]属于模版视图,无法导出,请先设置数据集!`,)
|
||||
} else {
|
||||
appExportFormRef.value.init({
|
||||
appName: dvInfo.value.name,
|
||||
icon: null,
|
||||
version: '2.0',
|
||||
creator: state.userLoginInfo?.nickName,
|
||||
required: '2.9.0',
|
||||
description: null
|
||||
})
|
||||
}
|
||||
}
|
||||
const checkTemplate =()=> {
|
||||
let templateViewNames = ','
|
||||
Object.keys(canvasViewDataInfo.value).forEach(key => {
|
||||
const viewInfo = canvasViewDataInfo.value[key]
|
||||
if (viewInfo.dataFrom === 'template') {
|
||||
templateViewNames = templateViewNames + viewInfo.title + ','
|
||||
}
|
||||
})
|
||||
return templateViewNames.slice(1)
|
||||
}
|
||||
const downLoadToApp = (appAttachInfo) =>{
|
||||
this.dataLoading = true
|
||||
export2AppCheck(this.$store.state.panel.panelInfo.id).then(rsp => {
|
||||
if (rsp.data.checkStatus) {
|
||||
this.saveAppFile(rsp.data, appAttachInfo)
|
||||
} else {
|
||||
this.dataLoading = false
|
||||
this.$message({
|
||||
message: rsp.data.checkMes,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
const slideOpenChange = () => {
|
||||
slideShow.value = !slideShow.value
|
||||
}
|
||||
@ -127,7 +171,8 @@ const state = reactive({
|
||||
canvasStylePreview: null,
|
||||
canvasViewInfoPreview: null,
|
||||
dvInfo: null,
|
||||
curPreviewGap: 0
|
||||
curPreviewGap: 0,
|
||||
userLoginInfo: {}
|
||||
})
|
||||
|
||||
const sideTreeStatus = ref(true)
|
||||
@ -147,6 +192,16 @@ const getPreviewStateInfo = () => {
|
||||
return state
|
||||
}
|
||||
|
||||
const downLoadApp = (appAttachInfo) =>{
|
||||
downLoadToApp(appAttachInfo)
|
||||
}
|
||||
|
||||
const findUserData = callback => {
|
||||
personInfoApi().then(rsp => {
|
||||
callback(rsp)
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
getPreviewStateInfo
|
||||
})
|
||||
@ -155,6 +210,9 @@ onBeforeMount(() => {
|
||||
if (props.showPosition === 'preview') {
|
||||
dvMainStore.canvasDataInit()
|
||||
}
|
||||
findUserData(res => {
|
||||
state.userLoginInfo = res.data
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -244,6 +302,8 @@ onBeforeMount(() => {
|
||||
</template>
|
||||
</el-container>
|
||||
</div>
|
||||
<app-export-form ref="appExportFormRef"
|
||||
@downLoadApp="downLoadApp"></app-export-form>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
|
@ -7,6 +7,7 @@ import io.dataease.api.visualization.dto.VisualizationViewTableDTO;
|
||||
import io.dataease.api.visualization.request.DataVisualizationBaseRequest;
|
||||
import io.dataease.api.visualization.request.VisualizationWorkbranchQueryRequest;
|
||||
import io.dataease.api.visualization.vo.DataVisualizationVO;
|
||||
import io.dataease.api.visualization.vo.VisualizationExport2AppVO;
|
||||
import io.dataease.api.visualization.vo.VisualizationResourceVO;
|
||||
import io.dataease.auth.DeApiPath;
|
||||
import io.dataease.auth.DePermit;
|
||||
@ -110,4 +111,8 @@ public interface DataVisualizationApi {
|
||||
@GetMapping("/viewDetailList/{dvId}")
|
||||
@Operation(summary = "仪表板视图明细数据")
|
||||
List<VisualizationViewTableDTO> detailList(@PathVariable("dvId") Long dvId);
|
||||
|
||||
@GetMapping("/export2AppCheck/{dvId}")
|
||||
@Operation(summary = "仪表板视图明细数据")
|
||||
VisualizationExport2AppVO export2AppCheck(@PathVariable("dvId") Long dvId);
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
package io.dataease.api.visualization.vo;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import io.dataease.extensions.datasource.dto.DatasetTableDTO;
|
||||
import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO;
|
||||
import io.dataease.extensions.datasource.dto.DatasourceDTO;
|
||||
import io.dataease.extensions.view.dto.ChartViewDTO;
|
||||
import io.dataease.extensions.view.dto.ChartViewFieldDTO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class VisualizationExport2AppVO {
|
||||
|
||||
private Boolean checkStatus = false;
|
||||
|
||||
private String checkMes;
|
||||
|
||||
private String visualizationInfo;
|
||||
|
||||
private String visualizationViewsInfo;
|
||||
|
||||
private String chartViewsInfo;
|
||||
|
||||
private String chartViewFieldsInfo;
|
||||
|
||||
private String datasetTablesInfo;
|
||||
|
||||
private String datasetTableFieldsInfo;
|
||||
|
||||
private String datasetTasksInfo;
|
||||
|
||||
private String datasourceInfo;
|
||||
|
||||
private String linkJumps;
|
||||
|
||||
private String linkJumpInfos;
|
||||
|
||||
private String linkages;
|
||||
|
||||
private String linkageFields;
|
||||
|
||||
public VisualizationExport2AppVO() {
|
||||
|
||||
}
|
||||
|
||||
public VisualizationExport2AppVO(String checkMes) {
|
||||
this.checkMes = checkMes;
|
||||
}
|
||||
|
||||
public VisualizationExport2AppVO(List<ChartViewDTO> chartViewsInfo, List<ChartViewFieldDTO> chartViewFieldsInfo,
|
||||
List<DatasetTableDTO> datasetTablesInfo, List<DatasetTableFieldDTO> datasetTableFieldsInfo, List<DatasourceDTO> datasourceInfo, List<VisualizationLinkJumpVO> linkJumps, List<VisualizationLinkJumpInfoVO> linkJumpInfos,
|
||||
List<VisualizationLinkageVO> linkages, List<VisualizationLinkageFieldVO> linkageFields) {
|
||||
List empty = new ArrayList();
|
||||
Gson gson = new Gson();
|
||||
this.checkStatus = true;
|
||||
this.checkMes = "success";
|
||||
this.chartViewsInfo = gson.toJson(chartViewsInfo != null ? chartViewsInfo : empty);
|
||||
this.chartViewFieldsInfo = gson.toJson(chartViewFieldsInfo != null ? chartViewFieldsInfo : empty);
|
||||
this.datasetTablesInfo = gson.toJson(datasetTablesInfo != null ? datasetTablesInfo : empty);
|
||||
this.datasetTableFieldsInfo = gson.toJson(datasetTableFieldsInfo != null ? datasetTableFieldsInfo : empty);
|
||||
this.datasetTasksInfo = gson.toJson(datasetTasksInfo != null ? datasetTasksInfo : empty);
|
||||
this.datasourceInfo = gson.toJson(datasourceInfo != null ? datasourceInfo : empty);
|
||||
this.visualizationViewsInfo = gson.toJson(visualizationViewsInfo != null ? visualizationViewsInfo : empty);
|
||||
this.linkJumps = gson.toJson(linkJumps != null ? linkJumps : empty);
|
||||
this.linkJumpInfos = gson.toJson(linkJumpInfos != null ? linkJumpInfos : empty);
|
||||
this.linkages = gson.toJson(linkages != null ? linkages : empty);
|
||||
this.linkageFields = gson.toJson(linkJumpInfos != null ? linkageFields : empty);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user