Merge pull request #10988 from dataease/pr@dev-v2@feat_app-download
feat(仪表板、大屏): 支持应用导出
This commit is contained in:
commit
9d3c055ca0
@ -21,11 +21,11 @@ public class MybatisPlusGenerator {
|
||||
/**
|
||||
* 业务模块例如datasource,dataset,panel等
|
||||
*/
|
||||
private static final String busi = "visualization";
|
||||
private static final String busi = "template";
|
||||
/**
|
||||
* 这是要生成代码的表名称
|
||||
*/
|
||||
private static final String TABLE_NAME = "visualization_report_filter";
|
||||
private static final String TABLE_NAME = "visualization_template";
|
||||
|
||||
/**
|
||||
* 下面两个配置基本上不用动
|
||||
|
||||
@ -5,11 +5,11 @@ import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
*
|
||||
* 模板表
|
||||
* </p>
|
||||
*
|
||||
* @author fit2cloud
|
||||
* @since 2024-04-11
|
||||
* @since 2024-07-16
|
||||
*/
|
||||
@TableName("visualization_template")
|
||||
public class VisualizationTemplate implements Serializable {
|
||||
@ -37,12 +37,12 @@ public class VisualizationTemplate implements Serializable {
|
||||
private Integer level;
|
||||
|
||||
/**
|
||||
* 模版种类 dataV or dashboard 目录或者文件夹
|
||||
* 模板种类 dataV or dashboard 目录或者文件夹
|
||||
*/
|
||||
private String dvType;
|
||||
|
||||
/**
|
||||
* 节点类型 folder or panel 目录或者文件夹
|
||||
* 节点类型 app or template 应用 或者 模板
|
||||
*/
|
||||
private String nodeType;
|
||||
|
||||
@ -62,7 +62,7 @@ public class VisualizationTemplate implements Serializable {
|
||||
private String snapshot;
|
||||
|
||||
/**
|
||||
* 模版类型 system 系统内置 self 用户自建
|
||||
* 模板类型 system 系统内置 self 用户自建
|
||||
*/
|
||||
private String templateType;
|
||||
|
||||
@ -81,14 +81,16 @@ public class VisualizationTemplate implements Serializable {
|
||||
*/
|
||||
private String dynamicData;
|
||||
|
||||
/**
|
||||
* app数据
|
||||
*/
|
||||
private String appData;
|
||||
|
||||
/**
|
||||
* 使用次数
|
||||
*/
|
||||
private Integer useCount;
|
||||
|
||||
/**
|
||||
* 使用仪表板的版本
|
||||
*/
|
||||
private Integer version;
|
||||
|
||||
public String getId() {
|
||||
@ -195,6 +197,14 @@ public class VisualizationTemplate implements Serializable {
|
||||
this.dynamicData = dynamicData;
|
||||
}
|
||||
|
||||
public String getAppData() {
|
||||
return appData;
|
||||
}
|
||||
|
||||
public void setAppData(String appData) {
|
||||
this.appData = appData;
|
||||
}
|
||||
|
||||
public Integer getUseCount() {
|
||||
return useCount;
|
||||
}
|
||||
@ -227,6 +237,7 @@ public class VisualizationTemplate implements Serializable {
|
||||
", templateStyle = " + templateStyle +
|
||||
", templateData = " + templateData +
|
||||
", dynamicData = " + dynamicData +
|
||||
", appData = " + appData +
|
||||
", useCount = " + useCount +
|
||||
", version = " + version +
|
||||
"}";
|
||||
|
||||
@ -6,11 +6,11 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* 模板表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author fit2cloud
|
||||
* @since 2024-04-11
|
||||
* @since 2024-07-16
|
||||
*/
|
||||
@Mapper
|
||||
public interface VisualizationTemplateMapper extends BaseMapper<VisualizationTemplate> {
|
||||
|
||||
@ -52,6 +52,6 @@ public interface ExtVisualizationTemplateMapper{
|
||||
|
||||
List<VisualizationLinkJumpInfoVO> findAppLinkJumpInfoInfo(@Param("dvId") Long dvId);
|
||||
|
||||
List<VisualizationLinkJumpTargetViewInfoVO> findAppJumpTargetViewInfo(@Param("dvId") Long dvId);
|
||||
List<VisualizationLinkJumpTargetViewInfoVO> findAppLinkJumpTargetViewInfoInfo(@Param("dvId") Long dvId);
|
||||
|
||||
}
|
||||
|
||||
@ -80,10 +80,10 @@ public class TemplateManageService implements TemplateManageApi {
|
||||
request.setId(UUID.randomUUID().toString());
|
||||
request.setCreateTime(System.currentTimeMillis());
|
||||
request.setCreateBy(AuthUtils.getUser().getUserId().toString());
|
||||
if ("template".equals(request.getNodeType())) {
|
||||
if ("template".equals(request.getNodeType()) || "app".equals(request.getNodeType())) {
|
||||
//Store static resource into the server
|
||||
staticResourceServer.saveFilesToServe(request.getStaticResource());
|
||||
String snapshotName = "template-" + request.getId() + ".jpeg";
|
||||
String snapshotName = request.getNodeType() + "-" + request.getId() + ".jpeg";
|
||||
staticResourceServer.saveSingleFileToServe(snapshotName, request.getSnapshot().replace("data:image/jpeg;base64,", ""));
|
||||
request.setSnapshot("/" + UPLOAD_URL_PREFIX + '/' + snapshotName);
|
||||
}
|
||||
@ -107,7 +107,7 @@ public class TemplateManageService implements TemplateManageApi {
|
||||
|
||||
VisualizationTemplate template = new VisualizationTemplate();
|
||||
BeanUtils.copyBean(template, request);
|
||||
if(template.getVersion() == null){
|
||||
if (template.getVersion() == null) {
|
||||
template.setVersion(2);
|
||||
}
|
||||
templateMapper.insert(template);
|
||||
@ -137,7 +137,7 @@ public class TemplateManageService implements TemplateManageApi {
|
||||
}
|
||||
VisualizationTemplate template = new VisualizationTemplate();
|
||||
BeanUtils.copyBean(template, request);
|
||||
if(template.getVersion() == null){
|
||||
if (template.getVersion() == null) {
|
||||
template.setVersion(2);
|
||||
}
|
||||
templateMapper.updateById(template);
|
||||
@ -191,7 +191,7 @@ public class TemplateManageService implements TemplateManageApi {
|
||||
|
||||
@Override
|
||||
public String checkCategoryTemplateBatchNames(TemplateManageRequest request) {
|
||||
Long result = extTemplateMapper.checkCategoryTemplateBatchNames(request.getTemplateNames(),request.getCategories(),request.getTemplateArray());
|
||||
Long result = extTemplateMapper.checkCategoryTemplateBatchNames(request.getTemplateNames(), request.getCategories(), request.getTemplateArray());
|
||||
if (result == 0) {
|
||||
return CommonConstants.CHECK_RESULT.NONE;
|
||||
} else {
|
||||
@ -272,7 +272,7 @@ public class TemplateManageService implements TemplateManageApi {
|
||||
public List<String> findCategoriesByTemplateIds(TemplateManageRequest request) throws Exception {
|
||||
if (!CollectionUtils.isEmpty(request.getTemplateArray())) {
|
||||
List<String> result = extTemplateMapper.findTemplateArrayCategories(request.getTemplateArray());
|
||||
if(!CollectionUtils.isEmpty(result) &&result.size() == 1 ){
|
||||
if (!CollectionUtils.isEmpty(result) && result.size() == 1) {
|
||||
return Arrays.stream(result.get(0).split(",")).toList();
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,6 +304,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
String templateData = null;
|
||||
String dynamicData = null;
|
||||
String staticResource = null;
|
||||
String appData = null;
|
||||
String name = null;
|
||||
String dvType = null;
|
||||
Integer version = null;
|
||||
@ -316,6 +317,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
name = visualizationTemplate.getName();
|
||||
dvType = visualizationTemplate.getDvType();
|
||||
version = visualizationTemplate.getVersion();
|
||||
appData = visualizationTemplate.getAppData();
|
||||
// 模板市场记录
|
||||
coreOptRecentManage.saveOpt(request.getTemplateId(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE, OptConstants.OPT_TYPE.NEW);
|
||||
VisualizationTemplate visualizationTemplateUpdate = new VisualizationTemplate();
|
||||
@ -327,6 +329,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
templateData = request.getComponentData();
|
||||
dynamicData = request.getDynamicData();
|
||||
staticResource = request.getStaticResource();
|
||||
appData = request.getAppData();
|
||||
name = request.getName();
|
||||
dvType = request.getType();
|
||||
} else if (DataVisualizationConstants.NEW_PANEL_FROM.NEW_MARKET_TEMPLATE.equals(newFrom)) {
|
||||
@ -341,6 +344,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
name = templateFileInfo.getName();
|
||||
dvType = templateFileInfo.getDvType();
|
||||
version = templateFileInfo.getVersion();
|
||||
appData = templateFileInfo.getAppData();
|
||||
// 模板市场记录
|
||||
coreOptRecentManage.saveOpt(request.getResourceName(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE, OptConstants.OPT_TYPE.NEW);
|
||||
}
|
||||
@ -383,7 +387,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
request.setCanvasStyleData(templateStyle);
|
||||
//Store static resource into the server
|
||||
staticResourceServer.saveFilesToServe(staticResource);
|
||||
return new DataVisualizationVO(newDvId, name, dvType, version, templateStyle, templateData, canvasViewInfo, null);
|
||||
return new DataVisualizationVO(newDvId, name, dvType, version, templateStyle, templateData,appData, canvasViewInfo, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -415,10 +419,10 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
List<AppCoreDatasourceVO> datasourceVOInfo = null;
|
||||
List<AppCoreDatasourceTaskVO> datasourceTaskVOInfo = null;
|
||||
//TODO 获取所有视图信息
|
||||
if (CollectionUtils.isEmpty(viewIds)) {
|
||||
if (!CollectionUtils.isEmpty(viewIds)) {
|
||||
chartViewVOInfo = appTemplateMapper.findAppViewInfo(viewIds);
|
||||
}
|
||||
if (CollectionUtils.isEmpty(dsIds)) {
|
||||
if (!CollectionUtils.isEmpty(dsIds)) {
|
||||
datasetGroupVOInfo = appTemplateMapper.findAppDatasetGroupInfo(dsIds);
|
||||
datasetTableVOInfo = appTemplateMapper.findAppDatasetTableInfo(dsIds);
|
||||
datasetTableFieldVOInfo = appTemplateMapper.findAppDatasetTableFieldInfo(dsIds);
|
||||
@ -430,7 +434,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
|
||||
List<VisualizationLinkageFieldVO> linkageFieldVOInfo = appTemplateMapper.findAppLinkageFieldInfo(dvId);
|
||||
List<VisualizationLinkJumpVO> linkJumpVOInfo = appTemplateMapper.findAppLinkJumpInfo(dvId);
|
||||
List<VisualizationLinkJumpInfoVO> linkJumpInfoVOInfo = appTemplateMapper.findAppLinkJumpInfoInfo(dvId);
|
||||
List<VisualizationLinkJumpTargetViewInfoVO> listJumpTargetViewInfoVO = appTemplateMapper.findAppJumpTargetViewInfo(dvId);
|
||||
List<VisualizationLinkJumpTargetViewInfoVO> listJumpTargetViewInfoVO = appTemplateMapper.findAppLinkJumpTargetViewInfoInfo(dvId);
|
||||
|
||||
return new VisualizationExport2AppVO(chartViewVOInfo, datasetGroupVOInfo, datasetTableVOInfo,
|
||||
datasetTableFieldVOInfo, datasourceVOInfo, datasourceTaskVOInfo,
|
||||
|
||||
@ -48,3 +48,7 @@ INSERT INTO `core_copilot_config` VALUES (1, 'https://copilot-demo.test.fit2clou
|
||||
|
||||
UPDATE `core_sys_setting` SET `pkey` = 'ai.baseUrl', `pval` = 'https://maxkb.fit2cloud.com/ui/chat/2ddd8b594ce09dbb?mode=embed', `type` = 'text', `sort` = 0 WHERE `id` = 3;
|
||||
|
||||
ALTER TABLE `visualization_template`
|
||||
MODIFY COLUMN `node_type` varchar(255) NULL DEFAULT NULL COMMENT '节点类型 app or template 应用 或者 模板' AFTER `dv_type`,
|
||||
ADD COLUMN `app_data` longtext NULL COMMENT 'app数据' AFTER `dynamic_data`;
|
||||
|
||||
|
||||
@ -69,3 +69,7 @@ CREATE TABLE `core_api_traffic`
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
ALTER TABLE `visualization_template`
|
||||
MODIFY COLUMN `node_type` varchar(255) NULL DEFAULT NULL COMMENT '节点类型 app or template 应用 或者 模板' AFTER `dv_type`,
|
||||
ADD COLUMN `app_data` longtext NULL COMMENT 'app数据' AFTER `dynamic_data`;
|
||||
|
||||
|
||||
@ -95,10 +95,10 @@ export const getComponentInfo = dvId => {
|
||||
})
|
||||
}
|
||||
|
||||
export const export2AppCheck = dvId => {
|
||||
return request.get({
|
||||
url: '/dataVisualization/export2AppCheck/' + dvId,
|
||||
method: 'get',
|
||||
export const export2AppCheck = params => {
|
||||
return request.post({
|
||||
url: '/dataVisualization/export2AppCheck',
|
||||
data: params,
|
||||
loading: true
|
||||
})
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ import OuterParamsSet from '@/components/visualization/OuterParamsSet.vue'
|
||||
import MultiplexingCanvas from '@/views/common/MultiplexingCanvas.vue'
|
||||
import ComponentButtonLabel from '@/components/visualization/ComponentButtonLabel.vue'
|
||||
import DeFullscreen from '@/components/visualization/common/DeFullscreen.vue'
|
||||
import DeAppApply from '@/views/common/DeAppApply.vue'
|
||||
let nameEdit = ref(false)
|
||||
let inputName = ref('')
|
||||
let nameInput = ref(null)
|
||||
@ -32,7 +33,8 @@ const snapshotStore = snapshotStoreWithOut()
|
||||
const { styleChangeTimes, snapshotIndex } = storeToRefs(snapshotStore)
|
||||
const resourceGroupOpt = ref(null)
|
||||
const dvToolbarMain = ref(null)
|
||||
const { componentData, canvasStyleData, dvInfo, editMode } = storeToRefs(dvMainStore)
|
||||
const { componentData, canvasStyleData, canvasViewInfo, dvInfo, editMode } =
|
||||
storeToRefs(dvMainStore)
|
||||
let scaleEdit = 100
|
||||
const { wsCache } = useCache('localStorage')
|
||||
const dvModel = 'dataV'
|
||||
@ -342,6 +344,12 @@ const fullScreenPreview = () => {
|
||||
cur-canvas-type="dataV"
|
||||
ref="resourceGroupOpt"
|
||||
/>
|
||||
<de-app-apply
|
||||
ref="resourceGroupOpt"
|
||||
:component-data="componentData"
|
||||
:dv-info="dvInfo"
|
||||
:canvas-view-info="canvasViewInfo"
|
||||
></de-app-apply>
|
||||
</div>
|
||||
<de-fullscreen ref="fullScreeRef" show-position="dvEdit"></de-fullscreen>
|
||||
<multiplexing-canvas ref="multiplexingRef"></multiplexing-canvas>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:title="'应用导出'"
|
||||
v-model:visible="state.applyDownloadDrawer"
|
||||
v-model="state.applyDownloadDrawer"
|
||||
custom-class="de-user-drawer"
|
||||
size="600px"
|
||||
direction="rtl"
|
||||
@ -11,13 +11,12 @@
|
||||
ref="applyDownloadForm"
|
||||
:model="state.form"
|
||||
:rules="state.rule"
|
||||
size="small"
|
||||
class="de-form-item"
|
||||
label-width="180px"
|
||||
label-position="right"
|
||||
label-position="top"
|
||||
>
|
||||
<el-form-item :label="'应用名称'" prop="appName">
|
||||
<el-input v-model="form.appName" autocomplete="off" :placeholder="'请输入名称'" />
|
||||
<el-input v-model="state.form.appName" autocomplete="off" :placeholder="'请输入名称'" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="'应用版本号'" prop="version">
|
||||
<el-input v-model="state.form.version" autocomplete="off" />
|
||||
@ -38,22 +37,43 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="app-export-bottom">
|
||||
<template #footer>
|
||||
<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>
|
||||
<el-button type="primary" @click="downloadApp">导出</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ElButton, ElDrawer, ElForm, ElFormItem, ElInput } from 'element-plus-secondary'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { reactive, ref, toRefs } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { export2AppCheck } from '@/api/visualization/dataVisualization'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
const { t } = useI18n()
|
||||
const emits = defineEmits(['closeDraw', 'downLoadApp'])
|
||||
const applyDownloadForm = ref(null)
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
|
||||
const props = defineProps({
|
||||
componentData: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
canvasViewInfo: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
dvInfo: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
const { componentData, canvasViewInfo, dvInfo } = toRefs(props)
|
||||
|
||||
const state = reactive({
|
||||
applyDownloadDrawer: false,
|
||||
form: {
|
||||
@ -61,7 +81,7 @@ const state = reactive({
|
||||
icon: null,
|
||||
version: null,
|
||||
creator: null,
|
||||
required: '1.16.0',
|
||||
required: '2.8.0',
|
||||
description: null
|
||||
},
|
||||
rule: {
|
||||
@ -105,6 +125,7 @@ const state = reactive({
|
||||
})
|
||||
|
||||
const init = params => {
|
||||
console.log('init==')
|
||||
state.applyDownloadDrawer = true
|
||||
state.form = params
|
||||
}
|
||||
@ -114,11 +135,44 @@ const close = () => {
|
||||
state.applyDownloadDrawer = false
|
||||
}
|
||||
|
||||
const gatherAppInfo = (viewIds, dsIds) => {
|
||||
componentData.value.forEach(item => {
|
||||
if (item.component === 'UserView' && canvasViewInfo.value[item.id]) {
|
||||
const viewDetails = canvasViewInfo.value[item.id]
|
||||
const { id, tableId } = viewDetails
|
||||
viewIds.push(id)
|
||||
dsIds.push(tableId)
|
||||
} else if (item.component === 'Group') {
|
||||
item.propValue.forEach(groupItem => {
|
||||
const viewDetails = canvasViewInfo.value[groupItem.id]
|
||||
const { id, tableId } = viewDetails
|
||||
viewIds.push(id)
|
||||
dsIds.push(tableId)
|
||||
})
|
||||
} else if (item.component === 'DeTabs') {
|
||||
item.propValue.forEach(tabItem => {
|
||||
tabItem.componentData.forEach(tabComponent => {
|
||||
const viewDetails = canvasViewInfo.value[tabComponent.id]
|
||||
const { id, tableId } = viewDetails
|
||||
viewIds.push(id)
|
||||
dsIds.push(tableId)
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const downloadApp = () => {
|
||||
applyDownloadForm.value?.validate(valid => {
|
||||
if (valid) {
|
||||
emits('downLoadApp', state.form)
|
||||
state.applyDownloadDrawer = false
|
||||
const viewIds = []
|
||||
const dsIds = []
|
||||
gatherAppInfo(viewIds, dsIds)
|
||||
export2AppCheck({ dvId: dvInfo.value.id, viewIds, dsIds }).then(rsp => {
|
||||
const params = { ...rsp.data, ...state.form }
|
||||
emits('downLoadApp', params)
|
||||
state.applyDownloadDrawer = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -537,7 +537,8 @@ export async function decompressionPre(params, callBack) {
|
||||
deTemplateData = {
|
||||
canvasStyleData: sourceCanvasStyle,
|
||||
componentData: sourceComponentData,
|
||||
canvasViewInfo: deTemplateDataTemp['canvasViewInfo']
|
||||
canvasViewInfo: deTemplateDataTemp['canvasViewInfo'],
|
||||
appData: deTemplateDataTemp['appData']
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
|
||||
@ -35,7 +35,7 @@ export function imgUrlTrans(url) {
|
||||
}
|
||||
}
|
||||
|
||||
export function download2AppTemplate(downloadType, canvasDom, name, callBack?) {
|
||||
export function download2AppTemplate(downloadType, canvasDom, name, attachParams, callBack?) {
|
||||
try {
|
||||
findStaticSource(function (staticResource) {
|
||||
html2canvas(canvasDom).then(canvas => {
|
||||
@ -50,11 +50,13 @@ export function download2AppTemplate(downloadType, canvasDom, name, callBack?) {
|
||||
templateType: 'self',
|
||||
snapshot: snapshot,
|
||||
dvType: dvInfo.value.type,
|
||||
nodeType: downloadType,
|
||||
version: 3,
|
||||
canvasStyleData: JSON.stringify(canvasStyleData.value),
|
||||
componentData: JSON.stringify(componentData.value),
|
||||
dynamicData: JSON.stringify(canvasViewDataTemplate),
|
||||
staticResource: JSON.stringify(staticResource || {})
|
||||
staticResource: JSON.stringify(staticResource || {}),
|
||||
appData: JSON.stringify(attachParams || {})
|
||||
}
|
||||
const blob = new Blob([JSON.stringify(templateInfo)], { type: '' })
|
||||
if (downloadType === 'template') {
|
||||
|
||||
256
core/core-frontend/src/views/common/DeAppApply.vue
Normal file
256
core/core-frontend/src/views/common/DeAppApply.vue
Normal file
@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
:title="'保存应用'"
|
||||
v-model="state.appApplyDrawer"
|
||||
custom-class="de-user-drawer"
|
||||
size="600px"
|
||||
direction="rtl"
|
||||
>
|
||||
<div class="app-export">
|
||||
<el-form
|
||||
ref="appSaveForm"
|
||||
:model="state.form"
|
||||
:rules="state.rule"
|
||||
class="de-form-item"
|
||||
label-width="180px"
|
||||
label-position="top"
|
||||
>
|
||||
<div class="de-row-rules" style="margin: 0 0 16px">
|
||||
<span>基本信息</span>
|
||||
</div>
|
||||
<el-form-item :label="dvPreName + '名称'" prop="appName">
|
||||
<el-input v-model="state.form.name" autocomplete="off" :placeholder="'请输入名称'" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="dvPreName + '所在位置'" prop="version">
|
||||
<el-tree-select
|
||||
style="width: 100%"
|
||||
@keydown.stop
|
||||
@keyup.stop
|
||||
v-model="state.form.pid"
|
||||
:data="state.dvTree"
|
||||
:props="state.propsTree"
|
||||
@node-click="dvTreeSelect"
|
||||
:filter-method="dvTreeFilterMethod"
|
||||
:render-after-expand="false"
|
||||
filterable
|
||||
>
|
||||
<template #default="{ data: { name } }">
|
||||
<span class="custom-tree-node">
|
||||
<el-icon>
|
||||
<Icon name="dv-folder"></Icon>
|
||||
</el-icon>
|
||||
<span :title="name">{{ name }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="'数据集分组名称'" prop="appName">
|
||||
<el-input
|
||||
v-model="state.form.datasetFolderName"
|
||||
autocomplete="off"
|
||||
:placeholder="'请输入名称'"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="数据集分组位置" prop="version">
|
||||
<el-tree-select
|
||||
style="width: 100%"
|
||||
@keydown.stop
|
||||
@keyup.stop
|
||||
v-model="state.form.datasetFolderPid"
|
||||
:data="state.dvTree"
|
||||
:props="state.propsTree"
|
||||
@node-click="dvTreeSelect"
|
||||
:filter-method="dvTreeFilterMethod"
|
||||
:render-after-expand="false"
|
||||
filterable
|
||||
>
|
||||
<template #default="{ data: { name } }">
|
||||
<span class="custom-tree-node">
|
||||
<el-icon>
|
||||
<Icon name="dv-folder"></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>数据源信息</span>
|
||||
</div>
|
||||
<div>数据源信息配置</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="apply" style="width: 100%">
|
||||
<el-button secondary @click="close">{{ $t('commons.cancel') }} </el-button>
|
||||
<el-button type="primary" @click="downloadApp">保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
ElButton,
|
||||
ElDrawer,
|
||||
ElForm,
|
||||
ElFormItem,
|
||||
ElInput,
|
||||
ElTreeSelect
|
||||
} from 'element-plus-secondary'
|
||||
import { computed, reactive, ref, toRefs } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
const emits = defineEmits(['closeDraw', 'downLoadApp'])
|
||||
const appSaveForm = ref(null)
|
||||
|
||||
const props = defineProps({
|
||||
componentData: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
canvasViewInfo: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
dvInfo: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
dvType: {
|
||||
type: String,
|
||||
default: 'dashboard'
|
||||
}
|
||||
})
|
||||
|
||||
const { componentData, canvasViewInfo, dvInfo, dvType } = toRefs(props)
|
||||
|
||||
const dvPreName = computed(() => (dvType.value === 'dashboard' ? '仪表板' : '数据大屏'))
|
||||
|
||||
const state = reactive({
|
||||
appApplyDrawer: false,
|
||||
dvTree: [],
|
||||
propsTree: {
|
||||
label: 'name',
|
||||
children: 'children',
|
||||
isLeaf: node => !node.children?.length
|
||||
},
|
||||
form: {
|
||||
pid: '',
|
||||
name: '新建',
|
||||
datasetFolderPid: null,
|
||||
datasetFolderName: null,
|
||||
datasourceMap: {} // 数据源ID映射
|
||||
},
|
||||
rule: {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
min: 2,
|
||||
max: 25,
|
||||
message: t('datasource.input_limit_2_25', [2, 25]),
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
pid: [
|
||||
{
|
||||
required: true,
|
||||
min: 2,
|
||||
max: 25,
|
||||
message: '请选择所属文件夹',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
datasetFolderName: [
|
||||
{
|
||||
required: true,
|
||||
min: 2,
|
||||
max: 25,
|
||||
message: t('datasource.input_limit_2_25', [2, 25]),
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
datasetFolderPid: [
|
||||
{
|
||||
required: true,
|
||||
min: 2,
|
||||
max: 25,
|
||||
message: '请选择数据集分组所属文件夹',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
const init = params => {
|
||||
console.log('init==')
|
||||
state.appApplyDrawer = true
|
||||
state.form = params
|
||||
}
|
||||
|
||||
const dvTreeFilterMethod = value => {
|
||||
state.dvTree = [...state.dvTree].filter(item => item.name.includes(value))
|
||||
}
|
||||
|
||||
const dvTreeSelect = element => {
|
||||
state.form.pid = element.id
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
emits('closeDraw')
|
||||
state.appApplyDrawer = false
|
||||
}
|
||||
|
||||
const saveApp = () => {
|
||||
appSaveForm.value?.validate(valid => {
|
||||
if (valid) {
|
||||
const viewIds = []
|
||||
const dsIds = []
|
||||
} 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;
|
||||
}
|
||||
|
||||
.de-row-rules {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
padding-left: 10px;
|
||||
margin: 24px 0 16px 0;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
height: 14px;
|
||||
width: 2px;
|
||||
background: #3370ff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -172,6 +172,9 @@ const initOpenHandler = newWindow => {
|
||||
<el-dropdown-item style="width: 118px" @click="downloadAsAppTemplate('template')"
|
||||
>模板</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item style="width: 118px" @click="downloadAsAppTemplate('app')"
|
||||
>应用</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item @click="download('img')">{{
|
||||
t('chart.image')
|
||||
}}</el-dropdown-item>
|
||||
|
||||
@ -104,16 +104,25 @@ const download = type => {
|
||||
}, 200)
|
||||
}
|
||||
|
||||
const downloadAsAppTemplate = downloadType => {
|
||||
const fileDownload = (downloadType, attachParams) => {
|
||||
downloadStatus.value = true
|
||||
nextTick(() => {
|
||||
const vueDom = previewCanvasContainer.value.querySelector('.canvas-container')
|
||||
download2AppTemplate(downloadType, vueDom, state.dvInfo.name, () => {
|
||||
download2AppTemplate(downloadType, vueDom, state.dvInfo.name, attachParams, () => {
|
||||
downloadStatus.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const downloadAsAppTemplate = downloadType => {
|
||||
console.log('===test===' + downloadType)
|
||||
if (downloadType === 'template') {
|
||||
fileDownload(downloadType, null)
|
||||
} else if (downloadType === 'app') {
|
||||
downLoadToAppPre()
|
||||
}
|
||||
}
|
||||
|
||||
const downLoadToAppPre = () => {
|
||||
const result = checkTemplate()
|
||||
if (result && result.length > 0) {
|
||||
@ -123,7 +132,7 @@ const downLoadToAppPre = () => {
|
||||
appName: dvInfo.value.name,
|
||||
icon: null,
|
||||
version: '2.0',
|
||||
creator: state.userLoginInfo?.nickName,
|
||||
creator: state.userLoginInfo?.name,
|
||||
required: '2.9.0',
|
||||
description: null
|
||||
})
|
||||
@ -139,9 +148,6 @@ const checkTemplate = () => {
|
||||
})
|
||||
return templateViewNames.slice(1)
|
||||
}
|
||||
const downLoadToApp = appAttachInfo => {
|
||||
// do attach
|
||||
}
|
||||
|
||||
const slideOpenChange = () => {
|
||||
slideShow.value = !slideShow.value
|
||||
@ -182,7 +188,7 @@ const getPreviewStateInfo = () => {
|
||||
}
|
||||
|
||||
const downLoadApp = appAttachInfo => {
|
||||
downLoadToApp(appAttachInfo)
|
||||
fileDownload('app', appAttachInfo)
|
||||
}
|
||||
|
||||
const findUserData = callback => {
|
||||
@ -291,7 +297,13 @@ onBeforeMount(() => {
|
||||
</template>
|
||||
</el-container>
|
||||
</div>
|
||||
<app-export-form ref="appExportFormRef" @downLoadApp="downLoadApp"></app-export-form>
|
||||
<app-export-form
|
||||
ref="appExportFormRef"
|
||||
:dv-info="state.dvInfo"
|
||||
:component-data="state.canvasDataPreview"
|
||||
:canvas-view-info="state.canvasViewInfoPreview"
|
||||
@downLoadApp="downLoadApp"
|
||||
></app-export-form>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
@ -88,6 +88,7 @@ const leftSidebarRef = ref(null)
|
||||
const dvLayout = ref(null)
|
||||
const canvasCenterRef = ref(null)
|
||||
const mainHeight = ref(300)
|
||||
let createType = null
|
||||
const state = reactive({
|
||||
datasetTree: [],
|
||||
scaleHistory: null,
|
||||
@ -295,7 +296,7 @@ onMounted(async () => {
|
||||
const pid = embeddedStore.pid || router.currentRoute.value.query.pid
|
||||
const templateParams =
|
||||
embeddedStore.templateParams || router.currentRoute.value.query.templateParams
|
||||
const createType = embeddedStore.createType || router.currentRoute.value.query.createType
|
||||
createType = embeddedStore.createType || router.currentRoute.value.query.createType
|
||||
const opt = embeddedStore.opt || router.currentRoute.value.query.opt
|
||||
const checkResult = await checkPer(dvId)
|
||||
if (!checkResult) {
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
id="input"
|
||||
ref="filesRef"
|
||||
type="file"
|
||||
accept=".DET2"
|
||||
accept=".DET2,.DET2APP"
|
||||
hidden
|
||||
@change="handleFileChange"
|
||||
/>
|
||||
@ -127,10 +127,12 @@ const state = reactive({
|
||||
pid: props.pid,
|
||||
categories: [],
|
||||
dvType: 'dashboard',
|
||||
nodeType: 'template',
|
||||
name: '',
|
||||
templateStyle: null,
|
||||
templateData: null,
|
||||
dynamicData: null,
|
||||
appData: null,
|
||||
staticResource: null,
|
||||
snapshot: '',
|
||||
version: null
|
||||
@ -265,8 +267,9 @@ const handleFileChange = e => {
|
||||
state.templateInfo.templateData = state.importTemplateInfo['componentData']
|
||||
state.templateInfo.snapshot = state.importTemplateInfo.snapshot
|
||||
state.templateInfo.dynamicData = state.importTemplateInfo['dynamicData']
|
||||
state.templateInfo.appData = state.importTemplateInfo['appData']
|
||||
state.templateInfo.staticResource = state.importTemplateInfo['staticResource']
|
||||
state.templateInfo['nodeType'] = 'template'
|
||||
state.templateInfo['nodeType'] = state.importTemplateInfo['nodeType'] || 'template'
|
||||
state.templateInfo['version'] = state.importTemplateInfo['version']
|
||||
}
|
||||
reader.readAsText(file)
|
||||
|
||||
@ -76,6 +76,11 @@ public class VisualizationTemplateVO {
|
||||
*/
|
||||
private String dynamicData;
|
||||
|
||||
/**
|
||||
* app数据
|
||||
*/
|
||||
private String appData;
|
||||
|
||||
/**
|
||||
* 使用次数
|
||||
*/
|
||||
|
||||
@ -113,7 +113,7 @@ public interface DataVisualizationApi {
|
||||
@Operation(summary = "仪表板视图明细数据")
|
||||
List<VisualizationViewTableDTO> detailList(@PathVariable("dvId") Long dvId);
|
||||
|
||||
@GetMapping("/export2AppCheck")
|
||||
@PostMapping("/export2AppCheck")
|
||||
@Operation(summary = "仪表板视图明细数据")
|
||||
VisualizationExport2AppVO export2AppCheck(@RequestBody VisualizationAppExportRequest appExportRequest);
|
||||
}
|
||||
|
||||
@ -168,8 +168,13 @@ public class DataVisualizationVO implements Serializable {
|
||||
*/
|
||||
private Integer weight;
|
||||
|
||||
/**
|
||||
* 应用信息
|
||||
*/
|
||||
private String appData;
|
||||
|
||||
public DataVisualizationVO(Long id, String name, String type, Integer version, String canvasStyleData, String componentData, Map<Long, ChartViewDTO> canvasViewInfo, Map<Long, VisualizationTemplateExtendDataDTO> extendDataInfo) {
|
||||
|
||||
public DataVisualizationVO(Long id, String name, String type, Integer version, String canvasStyleData, String componentData,String appData, Map<Long, ChartViewDTO> canvasViewInfo, Map<Long, VisualizationTemplateExtendDataDTO> extendDataInfo) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
@ -177,6 +182,7 @@ public class DataVisualizationVO implements Serializable {
|
||||
this.componentData = componentData;
|
||||
this.canvasViewInfo = canvasViewInfo;
|
||||
this.extendDataInfo = extendDataInfo;
|
||||
this.appData = appData;
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user