feat(图表): 支持在视图侧导出视图原始明细数据 #5894
This commit is contained in:
parent
1e8729918b
commit
73c5a8c371
@ -12,6 +12,7 @@ import io.dataease.commons.constants.DePermissionType;
|
||||
import io.dataease.commons.constants.PanelConstants;
|
||||
import io.dataease.commons.constants.ResourceAuthLevel;
|
||||
import io.dataease.controller.handler.annotation.I18n;
|
||||
import io.dataease.controller.request.dataset.DataSetExportRequest;
|
||||
import io.dataease.controller.request.panel.*;
|
||||
import io.dataease.dto.PermissionProxy;
|
||||
import io.dataease.dto.authModel.VAuthModelDTO;
|
||||
@ -155,6 +156,13 @@ public class PanelGroupController {
|
||||
return panelGroupService.queryPanelComponents(id);
|
||||
}
|
||||
|
||||
@ApiOperation("视图导出数据集明细")
|
||||
@PostMapping("/exportDatasetDetails")
|
||||
@I18n
|
||||
public void exportDatasetDetails(@RequestBody PanelViewDetailsRequest request, HttpServletResponse response) throws Exception {
|
||||
panelGroupService.exportDatasetDetails(request, response);
|
||||
}
|
||||
|
||||
@ApiOperation("公共连接导出仪表板视图明细")
|
||||
@PostMapping("/exportDetails")
|
||||
@I18n
|
||||
@ -172,9 +180,14 @@ public class PanelGroupController {
|
||||
@PostMapping("/innerExportDetails")
|
||||
@DePermissionProxy(value = "proxy")
|
||||
@I18n
|
||||
public void innerExportDetails(@RequestBody PanelViewDetailsRequest request) throws IOException {
|
||||
public void innerExportDetails(@RequestBody PanelViewDetailsRequest request) throws Exception {
|
||||
if("dataset".equals(request.getDownloadType())){
|
||||
DataSetExportRequest exportRequest = panelGroupService.composeDatasetExportRequest(request);
|
||||
exportCenterService.addTask(exportRequest.getId(), "dataset", exportRequest);
|
||||
}else{
|
||||
exportCenterService.addTask(request.getViewId(), "chart", request);
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation("更新仪表板状态")
|
||||
@PostMapping("/updatePanelStatus/{panelId}")
|
||||
|
||||
@ -10,6 +10,7 @@ import io.dataease.commons.constants.*;
|
||||
import io.dataease.commons.utils.*;
|
||||
import io.dataease.controller.request.authModel.VAuthModelRequest;
|
||||
import io.dataease.controller.request.chart.ChartExtRequest;
|
||||
import io.dataease.controller.request.dataset.DataSetExportRequest;
|
||||
import io.dataease.controller.request.dataset.DataSetTableRequest;
|
||||
import io.dataease.controller.request.panel.*;
|
||||
import io.dataease.dto.DatasourceDTO;
|
||||
@ -32,6 +33,9 @@ import io.dataease.plugins.common.base.domain.*;
|
||||
import io.dataease.plugins.common.base.mapper.*;
|
||||
import io.dataease.plugins.common.constants.DeTypeConstants;
|
||||
import io.dataease.plugins.common.exception.DataEaseException;
|
||||
import io.dataease.plugins.common.request.chart.ChartExtFilterRequest;
|
||||
import io.dataease.plugins.common.request.permission.DatasetRowPermissionsTreeItem;
|
||||
import io.dataease.plugins.common.request.permission.DatasetRowPermissionsTreeObj;
|
||||
import io.dataease.plugins.common.util.HttpClientUtil;
|
||||
import io.dataease.service.chart.ChartViewService;
|
||||
import io.dataease.service.dataset.DataSetGroupService;
|
||||
@ -144,6 +148,9 @@ public class PanelGroupService {
|
||||
@Resource
|
||||
private DatasourceMapper datasourceMapper;
|
||||
|
||||
@Resource
|
||||
private DatasetTableMapper datasetTableMapper;
|
||||
|
||||
@Value("${export.views.limit:100000}")
|
||||
private Long limit;
|
||||
|
||||
@ -657,6 +664,72 @@ public class PanelGroupService {
|
||||
CacheUtils.removeAll(AuthConstants.DEPT_PANEL_NAME);
|
||||
}
|
||||
|
||||
public DataSetExportRequest composeDatasetExportRequest(PanelViewDetailsRequest request){
|
||||
ChartExtRequest extRequest = request.getComponentFilterInfo();
|
||||
List<ChartExtFilterRequest> filter = new ArrayList();
|
||||
if(extRequest != null){
|
||||
if(CollectionUtils.isNotEmpty(extRequest.getFilter())){
|
||||
filter.addAll(extRequest.getFilter());
|
||||
}if(CollectionUtils.isNotEmpty(extRequest.getLinkageFilters())){
|
||||
filter.addAll(extRequest.getLinkageFilters());
|
||||
}if(CollectionUtils.isNotEmpty(extRequest.getOuterParamsFilters())){
|
||||
filter.addAll(extRequest.getOuterParamsFilters());
|
||||
}
|
||||
}
|
||||
Gson gson = new Gson();
|
||||
DatasetRowPermissionsTreeObj permissionsTreeObjFilter = new DatasetRowPermissionsTreeObj();
|
||||
permissionsTreeObjFilter.setLogic("and");
|
||||
List<DatasetRowPermissionsTreeItem> composePermission = new ArrayList<>();
|
||||
permissionsTreeObjFilter.setItems(composePermission);
|
||||
if(CollectionUtils.isNotEmpty(filter)){
|
||||
filter.forEach(filterInfo ->{
|
||||
DatasetRowPermissionsTreeItem filterPermission = new DatasetRowPermissionsTreeItem();
|
||||
List<String> values = filterInfo.getValue();
|
||||
String operator = filterInfo.getOperator();
|
||||
String dataSetFilterType = "logic";
|
||||
String term = operator;
|
||||
if("eq".equals(operator) && values.size()>1){
|
||||
dataSetFilterType = "enum";
|
||||
}
|
||||
String fieldId = filterInfo.getFieldId();
|
||||
filterPermission.setFieldId(fieldId);
|
||||
filterPermission.setFilterType(dataSetFilterType);
|
||||
filterPermission.setType("item");
|
||||
if(dataSetFilterType.equals("enum")){
|
||||
filterPermission.setEnumValue(values);
|
||||
}else{
|
||||
filterPermission.setTerm(term);
|
||||
filterPermission.setValue(values.get(0));
|
||||
}
|
||||
composePermission.add(filterPermission);
|
||||
});
|
||||
}
|
||||
|
||||
ChartViewWithBLOBs chartInfo = chartViewMapper.selectByPrimaryKey(request.getViewId());
|
||||
String customFilter = chartInfo.getCustomFilter();
|
||||
|
||||
DatasetTable datasetTable = datasetTableMapper.selectByPrimaryKey(chartInfo.getTableId());
|
||||
DataSetExportRequest dataSetExportRequest = new DataSetExportRequest();
|
||||
BeanUtils.copyBean(dataSetExportRequest,datasetTable);
|
||||
if(CollectionUtils.isNotEmpty(composePermission)){
|
||||
DatasetRowPermissionsTreeObj permissionsTreeObjCustomsFilter = gson.fromJson(customFilter,DatasetRowPermissionsTreeObj.class);
|
||||
DatasetRowPermissionsTreeItem customFilterPermission = new DatasetRowPermissionsTreeItem();
|
||||
customFilterPermission.setType("tree");
|
||||
customFilterPermission.setSubTree(permissionsTreeObjCustomsFilter);
|
||||
composePermission.add(customFilterPermission);
|
||||
dataSetExportRequest.setExpressionTree(gson.toJson(permissionsTreeObjFilter));
|
||||
}else{
|
||||
dataSetExportRequest.setExpressionTree(customFilter);
|
||||
}
|
||||
dataSetExportRequest.setFilename(dataSetExportRequest.getName());
|
||||
|
||||
return dataSetExportRequest;
|
||||
}
|
||||
|
||||
public void exportDatasetDetails(PanelViewDetailsRequest request, HttpServletResponse response) throws Exception {
|
||||
dataSetTableService.exportDataset(composeDatasetExportRequest(request),response);
|
||||
}
|
||||
|
||||
|
||||
public void exportPanelViewDetails(PanelViewDetailsRequest request, HttpServletResponse response) throws IOException {
|
||||
OutputStream outputStream = response.getOutputStream();
|
||||
|
||||
@ -269,6 +269,15 @@ export function innerExportDetails(data) {
|
||||
})
|
||||
}
|
||||
|
||||
export function exportDatasetDetails(data) {
|
||||
return request({
|
||||
url: 'panel/group/exportDatasetDetails',
|
||||
method: 'post',
|
||||
data: data,
|
||||
loading: true
|
||||
})
|
||||
}
|
||||
|
||||
export function updatePanelStatus(panelId, param) {
|
||||
return request({
|
||||
url: '/panel/group/updatePanelStatus/' + panelId,
|
||||
|
||||
@ -206,7 +206,7 @@ import { uploadFileResult } from '@/api/staticResource/staticResource'
|
||||
import eventBus from '@/components/canvas/utils/eventBus'
|
||||
import { hasDataPermission } from '@/utils/permission'
|
||||
import { exportExcelDownload } from '@/components/canvas/utils/utils'
|
||||
import { Button } from "element-ui";
|
||||
import { Button } from 'element-ui'
|
||||
|
||||
export default {
|
||||
components: { Background, LinkJumpSet, FieldsList, SettingMenu, LinkageField, MapLayerController },
|
||||
@ -476,73 +476,73 @@ export default {
|
||||
}
|
||||
|
||||
if (val && val.success === false) {
|
||||
this.openMessageSuccess( `${this.chart.title ? this.chart.title : this.chart.name} 导出失败,前往`, 'error',this.exportData);
|
||||
this.openMessageSuccess(`${this.chart.title ? this.chart.title : this.chart.name} 导出失败,前往`, 'error', this.exportData)
|
||||
}
|
||||
},
|
||||
exportData() {
|
||||
bus.$emit('data-export-center')
|
||||
},
|
||||
openMessageLoading(cb) {
|
||||
const h = this.$createElement;
|
||||
const iconClass = `el-icon-loading`;
|
||||
const customClass = `de-message-loading de-message-export`;
|
||||
const h = this.$createElement
|
||||
const iconClass = `el-icon-loading`
|
||||
const customClass = `de-message-loading de-message-export`
|
||||
this.$message({
|
||||
message: h("p", null, [
|
||||
message: h('p', null, [
|
||||
this.$t('data_export.exporting'),
|
||||
h(
|
||||
Button,
|
||||
{
|
||||
props: {
|
||||
type: "text",
|
||||
size: "mini",
|
||||
type: 'text',
|
||||
size: 'mini'
|
||||
},
|
||||
class: "btn-text",
|
||||
class: 'btn-text',
|
||||
on: {
|
||||
click: () => {
|
||||
cb();
|
||||
cb()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
this.$t('data_export.export_center'),
|
||||
this.$t('data_export.export_center')
|
||||
),
|
||||
this.$t('data_export.export_info'),
|
||||
this.$t('data_export.export_info')
|
||||
]),
|
||||
iconClass,
|
||||
showClose: true,
|
||||
customClass,
|
||||
});
|
||||
customClass
|
||||
})
|
||||
},
|
||||
openMessageSuccess(text, type, cb) {
|
||||
const h = this.$createElement;
|
||||
const iconClass = `el-icon-${type || "success"}`;
|
||||
const customClass = `de-message-${type || "success"} de-message-export`;
|
||||
const h = this.$createElement
|
||||
const iconClass = `el-icon-${type || 'success'}`
|
||||
const customClass = `de-message-${type || 'success'} de-message-export`
|
||||
this.$message({
|
||||
message: h("p", null, [
|
||||
h("span", null, text),
|
||||
message: h('p', null, [
|
||||
h('span', null, text),
|
||||
h(
|
||||
Button,
|
||||
{
|
||||
props: {
|
||||
type: "text",
|
||||
size: "mini",
|
||||
type: 'text',
|
||||
size: 'mini'
|
||||
},
|
||||
class: "btn-text",
|
||||
class: 'btn-text',
|
||||
on: {
|
||||
click: () => {
|
||||
cb();
|
||||
cb()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
this.$t('data_export.export_center'),
|
||||
),
|
||||
this.$t('data_export.export_center')
|
||||
)
|
||||
]),
|
||||
iconClass,
|
||||
showClose: true,
|
||||
customClass,
|
||||
});
|
||||
customClass
|
||||
})
|
||||
},
|
||||
exportExcelDownload() {
|
||||
exportExcelDownload(this.chart, null, null, null, null, this.exportDataCb)
|
||||
exportExcelDownload(this.chart, null, null, null, null, null, this.exportDataCb)
|
||||
},
|
||||
auxiliaryMatrixChange() {
|
||||
if (this.curComponent.auxiliaryMatrix) {
|
||||
|
||||
@ -202,6 +202,18 @@
|
||||
class="ds-icon-excel"
|
||||
/>{{ $t('chart.export') }}Excel
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
v-if="showChartInfoType==='details' && hasDataPermission('export',panelInfo.privileges)"
|
||||
size="mini"
|
||||
:disabled="$store.getters.loadingMap[$store.getters.currentPath] || dialogLoading"
|
||||
@click="exportSourceDetails"
|
||||
>
|
||||
<svg-icon
|
||||
icon-class="ds-excel"
|
||||
class="ds-icon-excel"
|
||||
/>{{ $t('chart.導出原始明細') }}
|
||||
</el-button>
|
||||
</span>
|
||||
<user-view-dialog
|
||||
v-if="chartDetailsVisible"
|
||||
@ -239,7 +251,7 @@ import ChartComponent from '@/views/chart/components/ChartComponent.vue'
|
||||
import TableNormal from '@/views/chart/components/table/TableNormal'
|
||||
import LabelNormal from '../../../views/chart/components/normal/LabelNormal'
|
||||
import { uuid } from 'vue-uuid'
|
||||
import { Button } from "element-ui";
|
||||
import { Button } from 'element-ui'
|
||||
import bus from '@/utils/bus'
|
||||
import { mapState } from 'vuex'
|
||||
import { isChange } from '@/utils/conditionUtil'
|
||||
@ -760,63 +772,63 @@ export default {
|
||||
bus.$emit('data-export-center')
|
||||
},
|
||||
openMessageLoading(cb) {
|
||||
const h = this.$createElement;
|
||||
const iconClass = `el-icon-loading`;
|
||||
const customClass = `de-message-loading de-message-export`;
|
||||
const h = this.$createElement
|
||||
const iconClass = `el-icon-loading`
|
||||
const customClass = `de-message-loading de-message-export`
|
||||
this.$message({
|
||||
message: h("p", null, [
|
||||
message: h('p', null, [
|
||||
this.$t('data_export.exporting'),
|
||||
h(
|
||||
Button,
|
||||
{
|
||||
props: {
|
||||
type: "text",
|
||||
size: "mini",
|
||||
type: 'text',
|
||||
size: 'mini'
|
||||
},
|
||||
class: "btn-text",
|
||||
class: 'btn-text',
|
||||
on: {
|
||||
click: () => {
|
||||
cb();
|
||||
cb()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
this.$t('data_export.export_center'),
|
||||
this.$t('data_export.export_center')
|
||||
),
|
||||
this.$t('data_export.export_info'),
|
||||
this.$t('data_export.export_info')
|
||||
]),
|
||||
iconClass,
|
||||
showClose: true,
|
||||
customClass,
|
||||
});
|
||||
customClass
|
||||
})
|
||||
},
|
||||
openMessageSuccess(text, type, cb) {
|
||||
const h = this.$createElement;
|
||||
const iconClass = `el-icon-${type || "success"}`;
|
||||
const customClass = `de-message-${type || "success"} de-message-export`;
|
||||
const h = this.$createElement
|
||||
const iconClass = `el-icon-${type || 'success'}`
|
||||
const customClass = `de-message-${type || 'success'} de-message-export`
|
||||
this.$message({
|
||||
message: h("p", null, [
|
||||
h("span", null, text),
|
||||
message: h('p', null, [
|
||||
h('span', null, text),
|
||||
h(
|
||||
Button,
|
||||
{
|
||||
props: {
|
||||
type: "text",
|
||||
size: "mini",
|
||||
type: 'text',
|
||||
size: 'mini'
|
||||
},
|
||||
class: "btn-text",
|
||||
class: 'btn-text',
|
||||
on: {
|
||||
click: () => {
|
||||
cb();
|
||||
cb()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
this.$t('data_export.export_center'),
|
||||
),
|
||||
this.$t('data_export.export_center')
|
||||
)
|
||||
]),
|
||||
iconClass,
|
||||
showClose: true,
|
||||
customClass,
|
||||
});
|
||||
customClass
|
||||
})
|
||||
},
|
||||
exportExcel() {
|
||||
this.dialogLoading = true
|
||||
@ -826,11 +838,25 @@ export default {
|
||||
}
|
||||
|
||||
if (val && val.success === false) {
|
||||
this.openMessageSuccess( `${this.chart.title ? this.chart.title : this.chart.name} 导出失败,前往`, 'error',this.exportData);
|
||||
this.openMessageSuccess(`${this.chart.title ? this.chart.title : this.chart.name} 导出失败,前往`, 'error', this.exportData)
|
||||
}
|
||||
this.dialogLoading = false
|
||||
})
|
||||
},
|
||||
exportSourceDetails() {
|
||||
this.dialogLoading = true
|
||||
this.$refs['userViewDialog'].exportSourceDetails((val) => {
|
||||
if (val && val.success) {
|
||||
this.openMessageLoading(this.exportData)
|
||||
}
|
||||
|
||||
if (val && val.success === false) {
|
||||
this.openMessageSuccess(`${this.chart.title ? this.chart.title : this.chart.name} 导出失败,前往`, 'error', this.exportData)
|
||||
}
|
||||
this.dialogLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
exportViewImg() {
|
||||
this.imageDownloading = true
|
||||
this.$refs['userViewDialog'].exportViewImg(this.pixel, () => {
|
||||
|
||||
@ -96,7 +96,7 @@ import ChartComponentS2 from '@/views/chart/components/ChartComponentS2'
|
||||
import LabelNormalText from '@/views/chart/components/normal/LabelNormalText'
|
||||
import html2canvas from 'html2canvasde'
|
||||
import { hexColorToRGBA } from '@/views/chart/chart/util'
|
||||
import {deepCopy, exportExcelDownload, exportImg, exportImgNew, imgUrlTrans} from '@/components/canvas/utils/utils'
|
||||
import { deepCopy, exportExcelDownload, exportImg, exportImgNew, imgUrlTrans } from '@/components/canvas/utils/utils'
|
||||
import { activeWatermark } from '@/components/canvas/tools/watermark'
|
||||
import { proxyUserLoginInfo, userLoginInfo } from '@/api/systemInfo/userLogin'
|
||||
|
||||
@ -296,6 +296,10 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
exportSourceDetails(callBack) {
|
||||
const loadingWrapper = { val: this.linkLoading }
|
||||
exportExcelDownload(this.chart, null, null, null, loadingWrapper, { downloadType: 'dataset' }, callBack)
|
||||
},
|
||||
exportViewImg(pixel, callback) {
|
||||
this.pixel = pixel
|
||||
this.exportLoading = true
|
||||
@ -320,7 +324,7 @@ export default {
|
||||
},
|
||||
exportExcelDownload(snapshot, width, height, callBack) {
|
||||
const loadingWrapper = { val: this.linkLoading }
|
||||
exportExcelDownload(this.chart, snapshot, width, height, loadingWrapper, callBack)
|
||||
exportExcelDownload(this.chart, snapshot, width, height, loadingWrapper, null, callBack)
|
||||
},
|
||||
|
||||
renderComponent() {
|
||||
|
||||
@ -468,7 +468,7 @@ export function getCacheTree(treeName) {
|
||||
return JSON.parse(localStorage.getItem(treeName))
|
||||
}
|
||||
|
||||
export function exportExcelDownload(chart, snapshot, width, height, loadingWrapper, callBack) {
|
||||
export function exportExcelDownload(chart, snapshot, width, height, loadingWrapper, downloadParams, callBack) {
|
||||
if (chart.render === 'antv' && !chart.data?.data?.length) {
|
||||
return
|
||||
}
|
||||
@ -507,6 +507,7 @@ export function exportExcelDownload(chart, snapshot, width, height, loadingWrapp
|
||||
const request = {
|
||||
proxy: null,
|
||||
viewId: chart.id,
|
||||
downloadType: downloadParams?.downloadType ? downloadParams.downloadType : 'view',
|
||||
viewName: excelName,
|
||||
header: excelHeader,
|
||||
details: excelData,
|
||||
|
||||
@ -1128,6 +1128,7 @@ export default {
|
||||
password_input_error: 'Original password input error'
|
||||
},
|
||||
chart: {
|
||||
export_source: 'Export Source',
|
||||
empty_hide: 'hide empty',
|
||||
hide: 'hide',
|
||||
chart_refresh_tips: 'View refresh setting takes precedence over panel refresh setting',
|
||||
|
||||
@ -1128,6 +1128,7 @@ export default {
|
||||
password_input_error: '原始密碼輸入錯誤'
|
||||
},
|
||||
chart: {
|
||||
export_source: '導出原始明細',
|
||||
empty_hide: '隱藏空值',
|
||||
hide: '隱藏',
|
||||
chart_refresh_tips: '視圖刷新設置優先於儀表板刷新設置',
|
||||
|
||||
@ -1124,6 +1124,7 @@ export default {
|
||||
log_live_time_error: '请填写1-4000整数'
|
||||
},
|
||||
chart: {
|
||||
export_source: '导出原始明细',
|
||||
empty_hide: '隐藏空值',
|
||||
hide: '隐藏',
|
||||
chart_refresh_tips: '视图刷新设置优先于仪表板刷新设置',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user