forked from github/dataease
Merge pull request #3662 from dataease/pr@dev@feat_dataset_export
feat(数据集): 数据集导出Excel
This commit is contained in:
commit
4f3a17178f
@ -46,7 +46,7 @@ public class ChartViewFieldController {
|
||||
BeanUtils.copyProperties(datasetTable, dataSetTableRequest);
|
||||
DatasetTableField datasetTableField = new DatasetTableField();
|
||||
BeanUtils.copyProperties(chartViewField, datasetTableField);
|
||||
dataSetTableService.getPreviewData(dataSetTableRequest, 1, 1, Collections.singletonList(datasetTableField));
|
||||
dataSetTableService.getPreviewData(dataSetTableRequest, 1, 1, Collections.singletonList(datasetTableField), null);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(Translator.get("i18n_calc_field_error"));
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ import io.dataease.commons.constants.SysLogConstants;
|
||||
import io.dataease.commons.utils.PageUtils;
|
||||
import io.dataease.commons.utils.Pager;
|
||||
import io.dataease.controller.ResultHolder;
|
||||
import io.dataease.controller.handler.annotation.I18n;
|
||||
import io.dataease.controller.request.dataset.DataSetExportRequest;
|
||||
import io.dataease.controller.request.dataset.DataSetTableRequest;
|
||||
import io.dataease.controller.response.DataSetDetail;
|
||||
import io.dataease.dto.dataset.DataSetTableDTO;
|
||||
@ -29,6 +31,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -139,7 +142,7 @@ public class DataSetTableController {
|
||||
@ApiOperation("查询预览数据")
|
||||
@PostMapping("getPreviewData/{page}/{pageSize}")
|
||||
public Map<String, Object> getPreviewData(@RequestBody DataSetTableRequest dataSetTableRequest, @PathVariable Integer page, @PathVariable Integer pageSize) throws Exception {
|
||||
return dataSetTableService.getPreviewData(dataSetTableRequest, page, pageSize, null);
|
||||
return dataSetTableService.getPreviewData(dataSetTableRequest, page, pageSize, null, null);
|
||||
}
|
||||
|
||||
@ApiOperation("db数据库表预览数据")
|
||||
@ -249,4 +252,11 @@ public class DataSetTableController {
|
||||
public List<String> getDatasetNameFromGroup(@PathVariable String sceneId) {
|
||||
return dataSetTableService.getDatasetNameFromGroup(sceneId);
|
||||
}
|
||||
|
||||
@ApiOperation("数据集导出")
|
||||
@PostMapping("/exportDataset")
|
||||
@I18n
|
||||
public void exportDataset(@RequestBody DataSetExportRequest request, HttpServletResponse response) throws Exception {
|
||||
dataSetTableService.exportDataset(request, response);
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public class DataSetTableFieldController {
|
||||
DatasetTable datasetTable = dataSetTableService.get(datasetTableField.getTableId());
|
||||
DataSetTableRequest dataSetTableRequest = new DataSetTableRequest();
|
||||
BeanUtils.copyProperties(datasetTable, dataSetTableRequest);
|
||||
dataSetTableService.getPreviewData(dataSetTableRequest, 1, 1, Collections.singletonList(datasetTableField));
|
||||
dataSetTableService.getPreviewData(dataSetTableRequest, 1, 1, Collections.singletonList(datasetTableField), null);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(Translator.get("i18n_calc_field_error"));
|
||||
}
|
||||
@ -177,7 +177,7 @@ public class DataSetTableFieldController {
|
||||
DecodedJWT jwt = JWT.decode(linkToken);
|
||||
Long userId = jwt.getClaim("userId").asLong();
|
||||
multFieldValuesRequest.setUserId(userId);
|
||||
return dataSetFieldService.fieldValues(multFieldValuesRequest.getFieldIds(), multFieldValuesRequest.getSort(), multFieldValuesRequest.getUserId(), true, true,false);
|
||||
return dataSetFieldService.fieldValues(multFieldValuesRequest.getFieldIds(), multFieldValuesRequest.getSort(), multFieldValuesRequest.getUserId(), true, true, false);
|
||||
}
|
||||
|
||||
@ApiIgnore
|
||||
|
@ -0,0 +1,12 @@
|
||||
package io.dataease.controller.request.dataset;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author Junjun
|
||||
*/
|
||||
@Data
|
||||
public class DataSetExportRequest extends DataSetTableRequest {
|
||||
private String filename;
|
||||
private String expressionTree;
|
||||
}
|
@ -11,6 +11,7 @@ import io.dataease.commons.constants.*;
|
||||
import io.dataease.commons.exception.DEException;
|
||||
import io.dataease.commons.utils.*;
|
||||
import io.dataease.controller.ResultHolder;
|
||||
import io.dataease.controller.request.dataset.DataSetExportRequest;
|
||||
import io.dataease.controller.request.dataset.DataSetGroupRequest;
|
||||
import io.dataease.controller.request.dataset.DataSetTableRequest;
|
||||
import io.dataease.controller.request.dataset.DataSetTaskRequest;
|
||||
@ -32,11 +33,13 @@ import io.dataease.plugins.common.base.domain.*;
|
||||
import io.dataease.plugins.common.base.mapper.*;
|
||||
import io.dataease.plugins.common.constants.DatasetType;
|
||||
import io.dataease.plugins.common.constants.DatasourceTypes;
|
||||
import io.dataease.plugins.common.constants.DeTypeConstants;
|
||||
import io.dataease.plugins.common.dto.dataset.SqlVariableDetails;
|
||||
import io.dataease.plugins.common.dto.datasource.DataSourceType;
|
||||
import io.dataease.plugins.common.dto.datasource.TableField;
|
||||
import io.dataease.plugins.common.request.datasource.DatasourceRequest;
|
||||
import io.dataease.plugins.common.request.permission.DataSetRowPermissionsTreeDTO;
|
||||
import io.dataease.plugins.common.request.permission.DatasetRowPermissionsTreeObj;
|
||||
import io.dataease.plugins.datasource.provider.Provider;
|
||||
import io.dataease.plugins.datasource.query.QueryProvider;
|
||||
import io.dataease.plugins.loader.ClassloaderResponsity;
|
||||
@ -61,8 +64,8 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -72,6 +75,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -558,7 +562,7 @@ public class DataSetTableService {
|
||||
}
|
||||
|
||||
public Map<String, Object> getPreviewData(DataSetTableRequest dataSetTableRequest, Integer page, Integer pageSize,
|
||||
List<DatasetTableField> extFields) throws Exception {
|
||||
List<DatasetTableField> extFields, DatasetRowPermissionsTreeObj extTree) throws Exception {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
String syncStatus = "";
|
||||
DatasetTableField datasetTableField = DatasetTableField.builder().tableId(dataSetTableRequest.getId())
|
||||
@ -576,6 +580,12 @@ public class DataSetTableService {
|
||||
DatasetTable datasetTable = datasetTableMapper.selectByPrimaryKey(dataSetTableRequest.getId());
|
||||
// 行权限
|
||||
List<DataSetRowPermissionsTreeDTO> rowPermissionsTree = permissionsTreeService.getRowPermissionsTree(fields, datasetTable, null);
|
||||
// ext filter
|
||||
if (extTree != null) {
|
||||
DataSetRowPermissionsTreeDTO dto = new DataSetRowPermissionsTreeDTO();
|
||||
dto.setTree(extTree);
|
||||
rowPermissionsTree.add(dto);
|
||||
}
|
||||
// 列权限
|
||||
List<String> desensitizationList = new ArrayList<>();
|
||||
fields = permissionService.filterColumnPermissions(fields, desensitizationList, datasetTable.getId(), null);
|
||||
@ -2869,4 +2879,85 @@ public class DataSetTableService {
|
||||
public void updateDatasetInfo(DatasetTable datasetTable) {
|
||||
datasetTableMapper.updateByPrimaryKeySelective(datasetTable);
|
||||
}
|
||||
|
||||
public void exportDataset(DataSetExportRequest request, HttpServletResponse response) throws Exception {
|
||||
try {
|
||||
DatasetRowPermissionsTreeObj tree = null;
|
||||
if (StringUtils.isNotEmpty(request.getExpressionTree())) {
|
||||
Gson gson = new Gson();
|
||||
tree = gson.fromJson(request.getExpressionTree(), DatasetRowPermissionsTreeObj.class);
|
||||
}
|
||||
Map<String, Object> previewData = getPreviewData(request, 1, 100000, null, tree);
|
||||
List<DatasetTableField> fields = (List<DatasetTableField>) previewData.get("fields");
|
||||
List<Map<String, Object>> data = (List<Map<String, Object>>) previewData.get("data");
|
||||
// 构建Excel数据格式
|
||||
List<List<String>> details = new ArrayList<>();
|
||||
List<String> header = new ArrayList<>();
|
||||
for (DatasetTableField field : fields) {
|
||||
header.add(field.getName());
|
||||
}
|
||||
details.add(header);
|
||||
for (Map<String, Object> obj : data) {
|
||||
List<String> row = new ArrayList<>();
|
||||
for (DatasetTableField field : fields) {
|
||||
String string = (String) obj.get(field.getDataeaseName());
|
||||
row.add(string);
|
||||
}
|
||||
details.add(row);
|
||||
}
|
||||
// 操作Excel
|
||||
Workbook wb = new XSSFWorkbook();
|
||||
// Sheet
|
||||
Sheet detailsSheet = wb.createSheet("数据");
|
||||
//给单元格设置样式
|
||||
CellStyle cellStyle = wb.createCellStyle();
|
||||
Font font = wb.createFont();
|
||||
//设置字体大小
|
||||
font.setFontHeightInPoints((short) 12);
|
||||
//设置字体加粗
|
||||
font.setBold(true);
|
||||
//给字体设置样式
|
||||
cellStyle.setFont(font);
|
||||
//设置单元格背景颜色
|
||||
cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
||||
//设置单元格填充样式(使用纯色背景颜色填充)
|
||||
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
if (CollectionUtils.isNotEmpty(details)) {
|
||||
for (int i = 0; i < details.size(); i++) {
|
||||
Row row = detailsSheet.createRow(i);
|
||||
List<String> rowData = details.get(i);
|
||||
if (rowData != null) {
|
||||
for (int j = 0; j < rowData.size(); j++) {
|
||||
Cell cell = row.createCell(j);
|
||||
if (i == 0) {// 头部
|
||||
cell.setCellValue(rowData.get(j));
|
||||
cell.setCellStyle(cellStyle);
|
||||
//设置列的宽度
|
||||
detailsSheet.setColumnWidth(j, 255 * 20);
|
||||
} else {
|
||||
if ((fields.get(j).getDeType() == DeTypeConstants.DE_INT || fields.get(j).getDeType() == DeTypeConstants.DE_FLOAT) && StringUtils.isNotEmpty(rowData.get(j))) {
|
||||
try {
|
||||
cell.setCellValue(Double.valueOf(rowData.get(j)));
|
||||
} catch (Exception e) {
|
||||
LogUtil.warn("export excel data transform error");
|
||||
}
|
||||
} else {
|
||||
cell.setCellValue(rowData.get(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OutputStream outputStream = response.getOutputStream();
|
||||
response.setContentType("application/vnd.ms-excel");
|
||||
//文件名称
|
||||
response.setHeader("Content-disposition", "attachment;filename=" + request.getFilename() + ".xlsx");
|
||||
wb.write(outputStream);
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
} catch (Exception e) {
|
||||
DataEaseException.throwException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,4 +249,15 @@ export function dsTable(page, size, id) {
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
export default { loadTable, getScene, addGroup, delGroup, addTable, delTable, groupTree, checkCustomDs }
|
||||
|
||||
export function exportDataset(data) {
|
||||
// 初始化仪表板视图缓存
|
||||
return request({
|
||||
url: 'dataset/table/exportDataset',
|
||||
method: 'post',
|
||||
data: data,
|
||||
loading: true,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
export default { loadTable, getScene, addGroup, delGroup, addTable, delTable, groupTree, checkCustomDs, exportDataset }
|
||||
|
@ -1693,7 +1693,11 @@ export default {
|
||||
input_edit_name: 'Input field name',
|
||||
edit_search: 'Search by name',
|
||||
na: 'None',
|
||||
date_format: 'Time format, default: year-month-day hour:minute:second'
|
||||
date_format: 'Time format, default: year-month-day hour:minute:second',
|
||||
export_dataset: 'Export',
|
||||
filename: 'Filename',
|
||||
export_filter: 'Filter',
|
||||
pls_input_filename: 'Please input filename'
|
||||
},
|
||||
driver: {
|
||||
driver: 'Driver',
|
||||
|
@ -1693,7 +1693,11 @@ export default {
|
||||
input_edit_name: '請輸入字段名稱',
|
||||
edit_search: '通過名稱搜索',
|
||||
na: '暫無',
|
||||
date_format: '時間格式,默認:年-月-日 時:分:秒'
|
||||
date_format: '時間格式,默認:年-月-日 時:分:秒',
|
||||
export_dataset: '數據集導出',
|
||||
filename: '文件名稱',
|
||||
export_filter: '篩選條件',
|
||||
pls_input_filename: '請輸入文件名稱'
|
||||
},
|
||||
driver: {
|
||||
driver: '驅動',
|
||||
|
@ -1692,7 +1692,11 @@ export default {
|
||||
input_edit_name: '请输入字段名称',
|
||||
edit_search: '通过名称搜索',
|
||||
na: '暂无',
|
||||
date_format: '时间格式,默认: 年-月-日 时:分:秒'
|
||||
date_format: '时间格式,默认: 年-月-日 时:分:秒',
|
||||
export_dataset: '数据集导出',
|
||||
filename: '文件名称',
|
||||
export_filter: '筛选条件',
|
||||
pls_input_filename: '请输入文件名称'
|
||||
},
|
||||
driver: {
|
||||
driver: '驱动',
|
||||
|
@ -55,12 +55,19 @@
|
||||
</el-popover>
|
||||
</el-col>
|
||||
<el-col
|
||||
v-if="hasDataPermission('manage', param.privileges)"
|
||||
style="text-align: right"
|
||||
:span="8"
|
||||
>
|
||||
<deBtn
|
||||
:disabled="!previewDataSuccess"
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
@click="exportDataset"
|
||||
>
|
||||
{{ $t('dataset.export_dataset') }}
|
||||
</deBtn>
|
||||
<el-dropdown
|
||||
v-if="table.type === 'excel'"
|
||||
v-if="table.type === 'excel' && hasDataPermission('manage', param.privileges)"
|
||||
size="small"
|
||||
trigger="click"
|
||||
placement="bottom-end"
|
||||
@ -81,7 +88,7 @@
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<deBtn
|
||||
v-if="['sql', 'union'].includes(table.type)"
|
||||
v-if="['sql', 'union'].includes(table.type) && hasDataPermission('manage', param.privileges)"
|
||||
type="primary"
|
||||
@click="editDataset(table.type)"
|
||||
>
|
||||
@ -177,11 +184,66 @@
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!--导出数据集弹框-->
|
||||
<el-dialog
|
||||
v-dialogDrag
|
||||
:visible.sync="showExport"
|
||||
width="600px"
|
||||
class="de-dialog-form"
|
||||
:title="$t('dataset.export_dataset')"
|
||||
append-to-body
|
||||
>
|
||||
<el-form
|
||||
ref="exportForm"
|
||||
class="de-form-item"
|
||||
:model="exportForm"
|
||||
:rules="exportFormRules"
|
||||
:before-close="closeExport"
|
||||
@submit.native.prevent
|
||||
@keypress.enter.native="exportDatasetRequest"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$t('dataset.filename')"
|
||||
prop="name"
|
||||
>
|
||||
<el-input
|
||||
v-model.trim="exportForm.name"
|
||||
:placeholder="$t('dataset.pls_input_filename')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('dataset.export_filter')"
|
||||
prop="expressionTree"
|
||||
>
|
||||
<!--TODO 下面的input需用行权限的树形过滤组件替换-->
|
||||
<el-input
|
||||
v-model.trim="exportForm.expressionTree"
|
||||
placeholder="请输入筛选条件"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span class="tip">提示:最多支持导出10万条数据</span>
|
||||
<div
|
||||
slot="footer"
|
||||
class="dialog-footer"
|
||||
>
|
||||
<deBtn
|
||||
secondary
|
||||
@click="closeExport"
|
||||
>{{ $t('dataset.cancel') }}</deBtn>
|
||||
<deBtn
|
||||
type="primary"
|
||||
@click="exportDatasetRequest"
|
||||
>{{ $t('dataset.confirm') }}
|
||||
</deBtn>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { post } from '@/api/dataset/dataset'
|
||||
import { exportDataset, post } from '@/api/dataset/dataset'
|
||||
import TabDataPreview from './TabDataPreview'
|
||||
import UpdateInfo from './UpdateInfo'
|
||||
import DatasetDetail from '../common/DatasetDetail'
|
||||
@ -224,7 +286,27 @@ export default {
|
||||
row: 1000
|
||||
},
|
||||
tabStatus: false,
|
||||
isPluginLoaded: false
|
||||
isPluginLoaded: false,
|
||||
showExport: false,
|
||||
exportForm: {
|
||||
name: '',
|
||||
expressionTree: ''
|
||||
},
|
||||
exportFormRules: {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('commons.input_content'),
|
||||
trigger: 'change'
|
||||
},
|
||||
{
|
||||
max: 50,
|
||||
message: this.$t('commons.char_can_not_more_50'),
|
||||
trigger: 'change'
|
||||
}
|
||||
]
|
||||
},
|
||||
previewDataSuccess: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -294,11 +376,14 @@ export default {
|
||||
this.data = response.data.data
|
||||
this.page = response.data.page
|
||||
this.syncStatus = response.data.syncStatus
|
||||
this.previewDataSuccess = true
|
||||
if (response.data.status === 'warnning') {
|
||||
this.$warning(response.data.msg, 3000)
|
||||
this.previewDataSuccess = false
|
||||
}
|
||||
if (response.data.status === 'error') {
|
||||
this.$error(response.data.msg, 3000)
|
||||
this.previewDataSuccess = false
|
||||
}
|
||||
this.lastRequestComplete = true
|
||||
})
|
||||
@ -311,6 +396,7 @@ export default {
|
||||
pageSize: 1000,
|
||||
show: 0
|
||||
}
|
||||
this.previewDataSuccess = false
|
||||
})
|
||||
}
|
||||
},
|
||||
@ -365,6 +451,32 @@ export default {
|
||||
this.initTable(this.param.id)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
exportDataset() {
|
||||
this.showExport = true
|
||||
this.exportForm.name = this.table.name
|
||||
this.exportForm.expressionTree = ''
|
||||
},
|
||||
closeExport() {
|
||||
this.showExport = false
|
||||
},
|
||||
exportDatasetRequest() {
|
||||
if (this.table.id) {
|
||||
this.table.row = 100000
|
||||
this.table.filename = this.exportForm.name
|
||||
this.table.expressionTree = this.exportForm.expressionTree
|
||||
exportDataset(this.table).then((res) => {
|
||||
const blob = new Blob([res], { type: 'application/vnd.ms-excel' })
|
||||
const link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.download = this.exportForm.name + '.xlsx' // 下载的文件名
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -378,6 +490,11 @@ export default {
|
||||
.blackTheme .icon-class {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.tip {
|
||||
color: #F56C6C;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.view-table {
|
||||
|
Loading…
Reference in New Issue
Block a user