增加用户自定义制式表格设计功能模块

导出:能够按照模板将表格导出为Excel、Word或PDF文件
在各个查询功能模块中增加数据批量下载功能
master
YaoJianze 5 months ago
parent 48596a83fb
commit 43f38b24df
  1. 44
      shandan-bianmu/src/main/java/com/keyware/shandan/bianmu/controller/MetadataController.java
  2. 22
      shandan-bianmu/src/main/resources/static/js/business/metadata/metadata.js
  3. 1
      shandan-bianmu/src/main/resources/view/business/metadata/metadata.html
  4. 12
      shandan-browser/pom.xml
  5. 1
      shandan-browser/src/main/java/com/keyware/shandan/BrowserApplication.java
  6. 91
      shandan-browser/src/main/java/com/keyware/shandan/browser/controller/CustomFormController.java
  7. 20
      shandan-browser/src/main/java/com/keyware/shandan/browser/controller/SearchController.java
  8. 43
      shandan-browser/src/main/java/com/keyware/shandan/browser/entity/CustomForm.java
  9. 15
      shandan-browser/src/main/java/com/keyware/shandan/browser/mapper/CustomFormMapper.java
  10. 14
      shandan-browser/src/main/java/com/keyware/shandan/browser/service/CustomFormService.java
  11. 20
      shandan-browser/src/main/java/com/keyware/shandan/browser/service/impl/CustomFormServiceImpl.java
  12. 48
      shandan-browser/src/main/resources/static/css/customForm.css
  13. 113
      shandan-browser/src/main/resources/static/js/customForm.js
  14. 31
      shandan-browser/src/main/resources/static/js/meta_search.js
  15. 1
      shandan-browser/src/main/resources/static/js/report.js
  16. 127
      shandan-browser/src/main/resources/view/CustomFrom.html
  17. 10
      shandan-browser/src/main/resources/view/meta_search.html
  18. 10
      shandan-browser/src/main/resources/view/report.html
  19. 2
      shandan-common/src/main/resources/static/js/common/common.js
  20. 6
      shandan-system/pom.xml
  21. 2
      shandan-system/src/main/java/com/keyware/shandan/bianmu/controller/MetadataCommonController.java
  22. 9
      shandan-system/src/main/java/com/keyware/shandan/bianmu/entity/DirectoryResource.java
  23. 81
      shandan-system/src/main/java/com/keyware/shandan/bianmu/export/DirectoryExport.java
  24. 1
      shandan-system/src/main/java/com/keyware/shandan/bianmu/export/ExportProgress.java
  25. 5
      shandan-system/src/main/java/com/keyware/shandan/bianmu/export/FileSearchExport.java
  26. 294
      shandan-system/src/main/java/com/keyware/shandan/bianmu/export/MetaTableExport.java
  27. 1
      shandan-system/src/main/java/com/keyware/shandan/system/controller/SysFileController.java
  28. 82
      shandan-system/src/main/java/com/keyware/shandan/system/utils/Word2PdfAsposeUtil.java
  29. 20
      shandan-system/src/main/resources/Aspose.license.lic

@ -9,6 +9,7 @@ import com.keyware.shandan.bianmu.enums.ReviewStatus;
import com.keyware.shandan.bianmu.export.DirectoryExport; import com.keyware.shandan.bianmu.export.DirectoryExport;
import com.keyware.shandan.bianmu.export.ExportCache; import com.keyware.shandan.bianmu.export.ExportCache;
import com.keyware.shandan.bianmu.export.ExportProgress; import com.keyware.shandan.bianmu.export.ExportProgress;
import com.keyware.shandan.bianmu.mapper.DirectoryResourceMapper;
import com.keyware.shandan.bianmu.service.DataLabelsService; import com.keyware.shandan.bianmu.service.DataLabelsService;
import com.keyware.shandan.bianmu.service.DirectoryMetadataService; import com.keyware.shandan.bianmu.service.DirectoryMetadataService;
import com.keyware.shandan.bianmu.service.MetadataService; import com.keyware.shandan.bianmu.service.MetadataService;
@ -55,7 +56,8 @@ public class MetadataController extends BaseController<MetadataService, Metadata
@Autowired @Autowired
private DataLabelsService labelsService; private DataLabelsService labelsService;
@Autowired
private DirectoryResourceMapper directoryResourceMapper;
@Autowired @Autowired
private SysFormConfigService formConfigService; private SysFormConfigService formConfigService;
@ -69,13 +71,46 @@ public class MetadataController extends BaseController<MetadataService, Metadata
} }
@PostMapping("/simple/page") @PostMapping("/simple/page")
public Result<Object> page(HashMap<String, Object> param) { public Result<Object> page(Authentication auth,HashMap<String, Object> param) {
Page<MetadataBasicVo> resultData = getMetadataBasicVoPage(param);
return Result.of(resultData);
}
@PostMapping("/simple/export")
public Result<Object> export(Authentication auth,HashMap<String, Object> param) {
Page<MetadataBasicVo> resultData = getMetadataBasicVoPage(param);
List<DirectoryResource> directoryResourceList = new ArrayList<>();
resultData.getRecords().stream().forEach(metadataBasicVo -> {
DirectoryResource directoryResource = new DirectoryResource();
directoryResource.setId(metadataBasicVo.getId());
directoryResource.setDirectoryPath("/资源注册/"+metadataBasicVo.getMetadataName());
directoryResource.setDataType(metadataBasicVo.getDataType());
directoryResource.setResourceType("metadata");
directoryResourceList.add(directoryResource);
});
Assert.notNull(auth, "用户信息认证失败");
String userId = auth.getPrincipal().toString();
// 这个逻辑只允许同一个用户同时只能有一个导出任务
ExportProgress export = ExportCache.getCache(userId, null);
if (export == null) {
// 查询数据
export = new DirectoryExport(userId, directoryResourceList);
ExportCache.startExport(export);
}
return Result.of(resultData);
}
/**
* 抽取出分页查询方法 共用于数据导出
* @param param
* @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.keyware.shandan.bianmu.entity.MetadataBasicVo>
* @author YaoJz
* @date 2024/04/17 10:14
*/
private Page<MetadataBasicVo> getMetadataBasicVoPage(HashMap<String, Object> param) {
int current = (int) param.getOrDefault("current", "1"); int current = (int) param.getOrDefault("current", "1");
int size = (int) param.getOrDefault("size", "10"); int size = (int) param.getOrDefault("size", "10");
String metadataName = (String) param.getOrDefault("metadataName", ""); String metadataName = (String) param.getOrDefault("metadataName", "");
String reviewStatus = (String) param.getOrDefault("reviewStatus", ""); String reviewStatus = (String) param.getOrDefault("reviewStatus", "");
String useStatus = (String) param.getOrDefault("useStatus", ""); String useStatus = (String) param.getOrDefault("useStatus", "");
MetadataBasicVo metadata = new MetadataBasicVo(); MetadataBasicVo metadata = new MetadataBasicVo();
if (StringUtils.hasText(metadataName)) { if (StringUtils.hasText(metadataName)) {
metadata.setMetadataName(metadataName); metadata.setMetadataName(metadataName);
@ -83,7 +118,6 @@ public class MetadataController extends BaseController<MetadataService, Metadata
if (StringUtils.hasText(reviewStatus)) { if (StringUtils.hasText(reviewStatus)) {
metadata.setReviewStatus(ReviewStatus.valueOf(reviewStatus)); metadata.setReviewStatus(ReviewStatus.valueOf(reviewStatus));
} }
QueryWrapper<MetadataBasicVo> query = new QueryWrapper<>(metadata); QueryWrapper<MetadataBasicVo> query = new QueryWrapper<>(metadata);
if (StringUtils.hasText(useStatus)) { if (StringUtils.hasText(useStatus)) {
Collection<String> ids = new ArrayList<>(); Collection<String> ids = new ArrayList<>();
@ -99,7 +133,7 @@ public class MetadataController extends BaseController<MetadataService, Metadata
StreamUtil.as(resultData.getRecords()).peek(item -> { StreamUtil.as(resultData.getRecords()).peek(item -> {
item.setUsed(ids.contains(item.getId())); item.setUsed(ids.contains(item.getId()));
}).toList(); }).toList();
return Result.of(resultData); return resultData;
} }
@GetMapping("/edit") @GetMapping("/edit")

@ -15,7 +15,7 @@ layui.use(['layer', 'listPage', 'form', 'dict'], function () {
let where = {metadataName: '', reviewStatus: '', useStatus: ''}; let where = {metadataName: '', reviewStatus: '', useStatus: ''};
const fieldMap = new Map() const fieldMap = new Map()
METADATA_FORM_CONFIG.forEach(conf=>fieldMap.set(conf.fieldName, conf)); METADATA_FORM_CONFIG.forEach(conf => fieldMap.set(conf.fieldName, conf));
console.info(fieldMap); console.info(fieldMap);
const listPage = layui.listPage.init({ const listPage = layui.listPage.init({
deleteUrl: `${ctx}/business/metadata/delete`, deleteUrl: `${ctx}/business/metadata/delete`,
@ -34,7 +34,7 @@ layui.use(['layer', 'listPage', 'form', 'dict'], function () {
templet: data => `<lable style="font-weight: ${data.hasMark ? 'bold' : 'italic'};">${data.metadataName}</lable>` templet: data => `<lable style="font-weight: ${data.hasMark ? 'bold' : 'italic'};">${data.metadataName}</lable>`
}, },
{field: 'metadataComment', title: '中文注释',hide: fieldMap.get('metadataName').isShow}, {field: 'metadataComment', title: '中文注释', hide: fieldMap.get('metadataName').isShow},
{ {
field: 'secretLevel', field: 'secretLevel',
title: '密级', title: '密级',
@ -49,7 +49,13 @@ layui.use(['layer', 'listPage', 'form', 'dict'], function () {
width: 100, width: 100,
templet: data => layui.dict.getDictDesc('data_source', data.dataFrom) templet: data => layui.dict.getDictDesc('data_source', data.dataFrom)
}, },
{field: 'collectionTime', title: '任务时间', width: 180, align: 'center',hide: !fieldMap.get('collectionTime').isShow}, {
field: 'collectionTime',
title: '任务时间',
width: 180,
align: 'center',
hide: !fieldMap.get('collectionTime').isShow
},
{ {
field: 'used', title: '关联状态', width: 120, align: 'center', templet: (data) => { field: 'used', title: '关联状态', width: 120, align: 'center', templet: (data) => {
if (data.used) { if (data.used) {
@ -186,7 +192,17 @@ layui.use(['layer', 'listPage', 'form', 'dict'], function () {
}) })
}) })
}); });
//导出文件
listPage.addTableRowEvent('export', (data) => {
let param = {
current: listPage.table.index,
size: listPage.table.limit,
metadataName: where.metadataName
};
console.log("系统异常 文件导出导出导出出",param,listPage)
Util.exportResource('/business/metadata/simple/export', param)
});
listPage.addTableRowEvent('batchCommit', (data) => { listPage.addTableRowEvent('batchCommit', (data) => {
let checkRows = listPage.getCheckStatus(); let checkRows = listPage.getCheckStatus();
let datas = checkRows.data; let datas = checkRows.data;

@ -28,6 +28,7 @@
<div class="layui-btn-container layui-form" lay-filter="metadataSearchForm"> <div class="layui-btn-container layui-form" lay-filter="metadataSearchForm">
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-inline"> <div class="layui-inline">
<button class="layui-btn layui-btn-sm" lay-event="export">导出</button>
<button class="layui-btn layui-btn-sm" lay-event="add">新增</button> <button class="layui-btn layui-btn-sm" lay-event="add">新增</button>
<!--<button class="layui-btn layui-btn-sm" lay-event="add-zhikong">上传指控数据</button>--> <!--<button class="layui-btn layui-btn-sm" lay-event="add-zhikong">上传指控数据</button>-->
<button class="layui-btn layui-btn-sm" lay-event="batchCommit">提交</button> <button class="layui-btn layui-btn-sm" lay-event="batchCommit">提交</button>

@ -56,6 +56,18 @@
<artifactId>shandan-system</artifactId> <artifactId>shandan-system</artifactId>
<version>1.0.0</version> <version>1.0.0</version>
</dependency> </dependency>
<!-- 导出word表格-->
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>5.2.0</version>
</dependency>
<!-- &lt;!&ndash; 引入poi-ooxml依赖,2007+使用 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.apache.poi</groupId>-->
<!-- <artifactId>poi-ooxml</artifactId>-->
<!-- <version>5.0.0</version>-->
<!-- </dependency>-->
</dependencies> </dependencies>
<!--构建工具--> <!--构建工具-->

@ -1,6 +1,7 @@
package com.keyware.shandan; package com.keyware.shandan;
import com.keyware.shandan.browser.SearchLogProcessor; import com.keyware.shandan.browser.SearchLogProcessor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;

@ -0,0 +1,91 @@
package com.keyware.shandan.browser.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.keyware.shandan.bianmu.entity.DirectoryResource;
import com.keyware.shandan.bianmu.export.DirectoryExport;
import com.keyware.shandan.bianmu.export.ExportCache;
import com.keyware.shandan.bianmu.export.ExportProgress;
import com.keyware.shandan.bianmu.mapper.DirectoryResourceMapper;
import com.keyware.shandan.browser.entity.CustomForm;
import com.keyware.shandan.browser.entity.SearchConditionVo;
import com.keyware.shandan.browser.service.CustomFormService;
import com.keyware.shandan.common.entity.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import javax.json.Json;
import javax.json.JsonObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* @author YaoJz
* @description
* 制式表格 控制类
* @date 2024/4/18 17:30
*/
@RestController
@RequestMapping("/CustomForm")
public class CustomFormController {
@Autowired
CustomFormService customFormService;
@Autowired
private DirectoryResourceMapper directoryResourceMapper;
/**
* 创建制式表格
* @param customForm
* @return com.keyware.shandan.common.entity.Result<java.lang.Object>
* @author YaoJz
* @date 2024/04/18 17:43
*/
@PostMapping("/create")
public Result<Object> createCustomForm(CustomForm customForm) {
String fieldConfig = JSON.toJSONString(customForm.getFieldList());
customForm.setFieldConfig(fieldConfig);
return Result.of( customFormService.save(customForm));
}
@GetMapping("/list")
public Result<Object> listCustomForm() {
return Result.of( customFormService.list());
}
@GetMapping("/getOne/{id}")
public Result<Object> getCustomForm(@PathVariable String id) {
return Result.of( customFormService.getById(id));
}
@PostMapping("/updata")
public Result<Object> updataCustomForm(CustomForm customForm) {
return Result.of( customFormService.updateById(customForm));
}
@GetMapping("/delete")
public Result<Object> deleteCustomForm(@PathVariable String id) {
return Result.of( customFormService.removeById(id));
}
@PostMapping("/export/{customFormId}")
public Result<Object> exportCustomForm(@PathVariable String customFormId, Authentication auth) {
CustomForm customForm = customFormService.getById(customFormId);
HashMap<String, String> map = new HashMap<>();
map.put("fieldConfig",customForm.getFieldConfig());
map.put("otherContext",customForm.getOtherContext());
DirectoryResource resource = directoryResourceMapper.selectById(customForm.getMetaId());
resource.setIsCustom(true);
resource.setCustomConfigMap(map);
List<DirectoryResource> directoryResourceList = new ArrayList<>();
directoryResourceList.add(resource);
Assert.notNull(auth, "用户信息认证失败");
String userId = auth.getPrincipal().toString();
// 这个逻辑只允许同一个用户同时只能有一个导出任务
ExportProgress export = ExportCache.getCache(userId, null);
if (export == null) {
// 查询数据
export = new DirectoryExport(userId, directoryResourceList);
ExportCache.startExport(export);
}
return null;
}
}

@ -271,7 +271,6 @@ public class SearchController {
Assert.notNull(auth, "用户信息认证失败"); Assert.notNull(auth, "用户信息认证失败");
MetadataBasicVo metadata = metadataService.getById(metaId); MetadataBasicVo metadata = metadataService.getById(metaId);
Assert.notNull(metadata, "数据资源表不存在"); Assert.notNull(metadata, "数据资源表不存在");
String userId = auth.getPrincipal().toString(); String userId = auth.getPrincipal().toString();
MetaTableExport export = ExportCache.getCache(userId, null); MetaTableExport export = ExportCache.getCache(userId, null);
if (export == null) { if (export == null) {
@ -280,9 +279,23 @@ public class SearchController {
export = newExport; export = newExport;
ExportCache.startExport(export); ExportCache.startExport(export);
} }
return Result.of(export.getProgress()); return Result.of(export.getProgress());
} }
@PostMapping("/export/metadata/{metaId}/{type}")
public Result<Object> exportMetadata(@PathVariable String metaId,@PathVariable String type, SearchConditionVo condition, Authentication auth) {
Assert.notNull(auth, "用户信息认证失败");
MetadataBasicVo metadata = metadataService.getById(metaId);
Assert.notNull(metadata, "数据资源表不存在");
String userId = auth.getPrincipal().toString();
MetaTableExport export = ExportCache.getCache(userId, null);
if (export == null) {
MetaTableExport newExport = new MetaTableExport(userId, metadata,type);
newExport.setQueryHandler((list) -> list.addAll(metadataDataService.list(metadata, condition)));
export = newExport;
ExportCache.startExport(export);
}
return Result.of(export.getProgress());
}
/** /**
* 目录数据导出-查询任务状态 * 目录数据导出-查询任务状态
@ -317,7 +330,8 @@ public class SearchController {
if (export == null) { if (export == null) {
return "错误:导出任务不存在"; return "错误:导出任务不存在";
} }
String path = export.getDownloadPath(); // String path = export.getDownloadPath();
String path = export.tranType();
String downloadName = FileUtil.getName(path); String downloadName = FileUtil.getName(path);
File file = new File(path); File file = new File(path);
return FileDownload.download(response, file, downloadName, true); return FileDownload.download(response, file, downloadName, true);

@ -0,0 +1,43 @@
package com.keyware.shandan.browser.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
import com.baomidou.mybatisplus.annotation.TableName;
import javax.validation.constraints.NotNull;
/**
* @author YaoJz
* @description
* @date 2024/4/18 16:59
*/
@Data
@TableName("CUSTOM_FORM")
public class CustomForm implements Serializable {
private static final long serialVersionUID = 7552053530616826540L;
@TableId("ID")
private Integer id;
@NotNull
private List<CustFormFormat> fieldList;
@TableField("METAID")
@NotNull
private String metaId;
@TableField("OTHERCONTEXT")
private String otherContext;
@TableField("FORMID")
private String formId;
@TableField("FIELD_CONFIG")
private String fieldConfig;
}
@Data
class CustFormFormat{
private String fieldKey;
private String fieldName;
private String fieldIndex;
}

@ -0,0 +1,15 @@
package com.keyware.shandan.browser.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.keyware.shandan.browser.entity.CustomForm;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
/**
* @author YaoJz
* @description
* @date 2024/4/18 17:41
*/
@Mapper
public interface CustomFormMapper extends BaseMapper<CustomForm> {
}

@ -0,0 +1,14 @@
package com.keyware.shandan.browser.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.keyware.shandan.browser.entity.CustomForm;
import com.keyware.shandan.common.service.IBaseService;
/**
* @author YaoJz
* @description
* @date 2024/4/18 17:34
*/
public interface CustomFormService extends IService<CustomForm> {
String checkArg(CustomForm customForm);
}

@ -0,0 +1,20 @@
package com.keyware.shandan.browser.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.keyware.shandan.browser.entity.CustomForm;
import com.keyware.shandan.browser.mapper.CustomFormMapper;
import com.keyware.shandan.browser.service.CustomFormService;
import org.springframework.stereotype.Service;
/**
* @author YaoJz
* @description
* @date 2024/4/18 17:37
*/
@Service
public class CustomFormServiceImpl extends ServiceImpl<CustomFormMapper, CustomForm> implements CustomFormService {
@Override
public String checkArg(CustomForm customForm) {
return null;
}
}

@ -0,0 +1,48 @@
#layer-content-report {
height: 100%
}
.report-main {
display: flex;
flex-direction: column;
width: 100%;
height: 100%
}
.report-main .report-btn-line {
display: flex;
justify-content: flex-end;
padding: 10px 20px;
}
.sorting-item {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 5px 0 !important;
}
.report-main .report-items {
flex-grow: 1;
display: flex;
flex-wrap: wrap;
overflow-y: overlay;
justify-content: space-around;
}
.echarts-item {
width: 500px;
height: 40%;
padding: 0 20px;
}
.layui-elem-field{border-color: #e8e8e8 !important;}
.layui-elem-field legend {
margin-left: 20px;
padding: 0 10px;
font-size: 16px;
font-weight: 400;
color: #7d7d7d;
}
.layui-field-box {
padding: 15px 50px 15px 15px;
}

@ -0,0 +1,113 @@
/**
* 统计报表组件
*
* @author GuoXin
* @since 2021/7/12
*/
const template_configs = `
<div>
<div> asdsssssssasdasd</div>
<!--<table class="layui-hide" id="ID-table-demo-data"></table>-->
<table class="layui-hide" id="ID-table-demo-data" lay-filter="meta-result-table"></table>
<div > <a class="layui-btn layui-btn-xs layui-btn-primary my-btn" name="create"
data-type="single-filed">添加条件</a></div>
</div>
`;
function CustomReportComponent(columns, conditions, metadataId) {
this.metadataId = metadataId || '';
this.columns = columns || [];
this.conditions = conditions || [];
this.echarts = [];
this.size = 0;
this.formData = {};
this.form = {};
this.gtable = {};
layui.use(['form','gtable'], () => {
this.gtable = layui.gtable;
this.form = layui.form;
})
}
function initTable(table) {
var inst = table.render({
elem: '#ID-table-demo-data',
cols: [[ //标题栏
{field: 'id', title: 'ID', width: 80, sort: true},
{field: 'username', title: '名称', width: 120},
{field: 'sign', title: '顺序', minWidth: 160}
]],
data: [{ // 赋值已知数据
"id": "10001",
"username": "张三1",
"sex": "男",
"city": "浙江杭州",
"sign": "人生恰似一场修行",
"experience": "116"
}, {
"id": "10008",
"username": "张三8",
"sex": "男",
"city": "浙江杭州",
"sign": "人生恰似一场修行",
"experience": "106"
}],
page: false, // 是否显示分页
limits: [5, 10, 15],
// limit: 5 // 每页默认显示的数量
});
}
function createNewTable(){
console.log("createNewTable1")
$(`a[name='create']`).on('click', createNewTable);
}
function createTable(){
console.log("createNewTable2")
$(`a[name='create']`).on('click', createNewTable);
}
/**
* 打开统计报表主窗口
*/
CustomReportComponent.prototype.openMainLayer = function () {
const _this = this;
layer.open({
type: 1,
title: '统计报表',
area: ['900px', '100%'],
content: template_configs,
success: function (layero, index) {
initTable(_this.gtable)
createTable()
},
done: function () {
}
})
}
/**
* 打开图表配置窗口
*/
CustomReportComponent.prototype.openEchartsConfigLayer = function () {
const _this = this;
layer.open({
title: '统计报表配置',
type: 1,
resize: false,
closeBtn: false,
btn: ['确定', '取消'],
content: template_config,
success: function (layerObj, index) {
_this.renderSelect();
$('#echartsConfigForm').parent().css('overflow', 'visible')
},
yes: function (index) {
_this.requestData(() => layer.close(index));
}
});
}

@ -38,13 +38,26 @@ layui.use(['dropdown', 'gtable', 'laydate', 'form'], function () {
toolbar: '#table-title', toolbar: '#table-title',
request: {pageName: 'page', limitName: 'size'}, request: {pageName: 'page', limitName: 'size'},
defaultToolbar: ['filter', { defaultToolbar: ['filter', {
title: '导出数据', title: '导出数据(excel)',
layEvent: 'exports', layEvent: 'exports',
icon: 'layui-icon-export' icon: 'layui-icon-export'
}, { }, {
title: '导出数据(word)',
layEvent: 'exportsWord',
icon: 'layui-icon-export'
},
{
title: '导出数据(pdf)',
layEvent: 'exportsPdf',
icon: 'layui-icon-export'
},{
title: '统计报表', title: '统计报表',
layEvent: 'tong-ji', layEvent: 'tong-ji',
icon: 'layui-icon-chart' icon: 'layui-icon-chart'
}, {
title: '自定义制式表格',
layEvent: 'CustomFormExport',
icon: 'layui-icon-chart'
}] }]
}) })
// 排序事件回调 // 排序事件回调
@ -60,7 +73,13 @@ layui.use(['dropdown', 'gtable', 'laydate', 'form'], function () {
if (event === 'tong-ji') { if (event === 'tong-ji') {
openStatisticalReport() openStatisticalReport()
}else if(event === 'exports'){ }else if(event === 'exports'){
Util.exportResource(`/search/export/metadata/${metadata.id}`, where); Util.exportResource(`/search/export/metadata/${metadata.id}/excel`, where);
}else if(event === 'exportsPdf'){
Util.exportResource(`/search/export/metadata/${metadata.id}/pdf`, where);
}else if(event === 'exportsWord'){
Util.exportResource(`/search/export/metadata/${metadata.id}/word`, where);
}else if (event === 'CustomFormExport'){
openStatisticalCustomFormReport()
} }
}); });
}); });
@ -257,4 +276,12 @@ layui.use(['dropdown', 'gtable', 'laydate', 'form'], function () {
const reportComponent = new ReportComponent(columns, getConditionItemValue(), metadata.id); const reportComponent = new ReportComponent(columns, getConditionItemValue(), metadata.id);
reportComponent.openMainLayer(); reportComponent.openMainLayer();
} }
/**
* 打开自定义制式表格
*/
function openStatisticalCustomFormReport() {
const reportComponent = new CustomReportComponent(columns, getConditionItemValue(), metadata.id);
reportComponent.openMainLayer();
}
}); });

@ -11,7 +11,6 @@ function ReportComponent(columns, conditions, metadataId) {
this.echarts = []; this.echarts = [];
this.size = 0; this.size = 0;
this.formData = {}; this.formData = {};
this.form = {}; this.form = {};
layui.use(['form'], () => { layui.use(['form'], () => {
this.form = layui.form; this.form = layui.form;

@ -0,0 +1,127 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="zh-CN">
<script type="text/javascript">
// 达梦日期类型集合
const dm_date_types = ['DATE', 'DATETIME', 'DATETIME WITH TIME ZONE', 'TIME', 'TIMESTAMP', 'TIME WITH TIME ZONE', 'TIMESTAMP WITH TIME ZONE', 'TIMESTAMP WITH LOCAL TIME ZONE'];
// 达梦数值类型集合
const dm_number_types = ['NUMERIC', 'NUMBER', 'DECIMAL', 'DEC', 'INTEGER', 'INT', 'PLS_INTEGER', 'BIGINT', 'TINYINT', 'BYTE', 'SMALLINT', 'FLOAT', 'DOUBLE', 'DOUBLE PRECISION'];
const common_fields = [
{field: 'SOURCE', dataType: 'VARCHAR2', comment: '文件来源'},
{field: 'INPUTDATE', dataType: 'DATETIME', comment: '任务时间'},
{field: 'ENTRYSTAFF', dataType: 'VARCHAR2', comment: '录入人员'},
{field: 'TASKNATURE', dataType: 'VARCHAR2', comment: '任务性质'},
{field: 'TASKCODE', dataType: 'VARCHAR2', comment: '任务代号'},
{field: 'TARGETNUMBER', dataType: 'VARCHAR2', comment: '目标/靶标类型'},
{field: 'TROOPCODE', dataType: 'VARCHAR2', comment: '部队代号'},
{field: 'EQUIPMENTMODEL', dataType: 'VARCHAR2', comment: '装备型号'},
{field: 'MISSILENUMBER', dataType: 'VARCHAR2', comment: '导弹编号'},
];
const template_config = `
<div class="layui-form-item">阿三顶顶顶</div>`;
const template_configs = `
<div class="layui-form" lay-filter="echartsConfigForm" id="echartsConfigForm" style="padding:15px; padding-bottom: 0;">
<fieldset class="layui-elem-field">
<legend>图表配置</legend>
<div class="layui-field-box">
<div class="layui-form-item" style="padding:0 20px;">
<div class="layui-form-label" style="width: 100px">标题</div>
<div class="layui-inline">
<div class="layui-input-inline" style="width: 300px">
<input type="text" name="title" class="layui-input" placeholder="设置图表的标题">
</div>
</div>
</div>
<div class="layui-form-item" style="padding:0 20px;">
<div class="layui-form-label" style="width: 100px">图表类型</div>
<div class="layui-inline">
<div class="layui-input-inline" style="width: 300px">
<select name="reportType" lay-filter="reportType">
<option value="pie" selected>饼图</option>
<option value="bar">柱状图</option>
<option value="line">折线图</option>
</select>
</div>
</div>
</div>
</div>
</fieldset>
<fieldset class="layui-elem-field">
<legend>统计维度</legend>
<div class="layui-field-box">
<div class="layui-form-item" style="padding:0 20px;">
<div class="layui-form-label" style="width: 100px">字段</div>
<div class="layui-inline">
<div class="layui-input-inline" style="width: 300px">
<input type="hidden" name="fieldXType" />
<select name="fieldX" id="selectFieldX" lay-filter="selectFieldX"></select>
</div>
</div>
</div>
<div class="layui-form-item layui-hide" style="padding:0 20px;" id="range-date-item">
<div class="layui-form-label" style="width: 100px">时间间隔</div>
<div class="layui-inline">
<div class="layui-input-inline" style="width: 300px">
<select name="dateInterval" id="dateInterval">
<option value="" selected>选择时间间隔</option>
<option value="minute">每分钟</option>
<option value="hour">每小时</option>
<option value="day">每日</option>
<!--<option value="week">每周</option>-->
<option value="month">每月</option>
<option value="year">每年</option>
</select>
</div>
</div>
</div>
<div class="layui-form-item layui-hide" style="padding:0 20px;" id="range-number-item">
<div class="layui-form-label" style="width: 100px">数值间隔</div>
<div class="layui-inline">
<div class="layui-input-inline" style="width: 300px">
<input class="layui-input" type="text" name="numberInterval" autocomplete="off" />
</div>
</div>
</div>
</div>
</fieldset>
<fieldset class="layui-elem-field">
<legend>统计指标</legend>
<div class="layui-field-box">
<div class="layui-form-item" style="padding:0 20px;">
<div class="layui-form-label" style="width: 100px">描述文本</div>
<div class="layui-inline">
<div class="layui-input-inline" style="width: 300px">
<input type="text" class="layui-input" name="remark" autocomplete="off" placeholder="用于生成文档报表,如:录入总数">
</div>
</div>
</div>
<div class="layui-form-item" style="padding:0 20px;" id="field-select-item-y">
<div class="layui-form-label" style="width: 100px">聚合字段</div>
<div class="layui-inline">
<div class="layui-input-inline" style="width: 300px">
<select name="fieldY" id="selectFieldY" lay-filter="selectFieldY"></select>
</div>
</div>
</div>
<div class="layui-form-item" style="padding:0 20px;">
<div class="layui-form-label" style="width: 100px">聚合方式</div>
<div class="layui-inline">
<div class="layui-input-inline" style="width: 300px">
<select name="aggregationType" id="aggregationType" lay-filter="aggregationType">
<option value="count" selected>计数</option>
<option value="sum">求和</option>
<option value="avg">平均值</option>
</select>
</div>
</div>
</div>
</div>
</fieldset>
</div>`;
</script>
<!-- echarts-5.1.2 -->
<script th:src="@{/js/customForm.js}"></script>
<script th:src="@{/js/common/echarts/echarts.min.js}"></script>
</html>

@ -14,6 +14,15 @@
const metadata = /*[[${metadata}]]*/ {}; const metadata = /*[[${metadata}]]*/ {};
const columns = /*[[${columns}]]*/ []; const columns = /*[[${columns}]]*/ [];
</script> </script>
<style>
.layui-form-label {
width: 90px;
}
.layui-form-item .layui-input-inline {
width: 260px;
}
</style>
</head> </head>
<body> <body>
<div class="layui-row" style="height: 100%"> <div class="layui-row" style="height: 100%">
@ -56,6 +65,7 @@
<!-- js --> <!-- js -->
<script th:replace="common/head::static-foot"></script> <script th:replace="common/head::static-foot"></script>
<script th:replace="report"></script> <script th:replace="report"></script>
<script th:src="@{/js/customForm.js}"></script>
<script th:src="@{/js/meta_search.js}"></script> <script th:src="@{/js/meta_search.js}"></script>
<script type="text/javascript"> <script type="text/javascript">
/** /**

@ -127,6 +127,16 @@
</div> </div>
</fieldset> </fieldset>
</div>`; </div>`;
const template_main = `
<div id="layer-content-report" >
<div class="report-main">
<div class="report-btn-line" style="text-align: right;padding: 10px;">
<a class="layui-btn layui-btn-sm layui-btn-normal" id="btn-add"><i class="layui-icon layui-icon-add-1"></i>定义新报表</a>
<a class="layui-btn layui-btn-sm layui-btn-normal" id="btn-download"><i class="layui-icon layui-icon-download-circle"></i>下载报表</a>
</div>
<div class="report-items" id="report-items"></div>
</div>
</div>`;
</script> </script>
<!-- echarts-5.1.2 --> <!-- echarts-5.1.2 -->
<script th:src="@{/js/common/echarts/echarts.min.js}"></script> <script th:src="@{/js/common/echarts/echarts.min.js}"></script>

@ -600,7 +600,9 @@ commonUtil = {
exportResource: (url, params)=>{ exportResource: (url, params)=>{
let layerIndex; let layerIndex;
showExportMsgLayer('开始准备数据'); showExportMsgLayer('开始准备数据');
console.log("url params",url ,params)
Util.post(url, params, false).then(({flag, data, msg}) => { Util.post(url, params, false).then(({flag, data, msg}) => {
console.log("url params",url ,params)
if (flag) { if (flag) {
showExportMsgLayer(data.msg); showExportMsgLayer(data.msg);
queryProgress(data.exportId); queryProgress(data.exportId);

@ -107,5 +107,11 @@
<version>2.5.1</version> <version>2.5.1</version>
</dependency> </dependency>
<dependency>
<groupId>aspose</groupId>
<artifactId>words</artifactId>
<version>14.8.0</version>
<classifier>jdk16</classifier>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -181,7 +181,7 @@ public class MetadataCommonController {
List<DirectoryResource> records = result.getRecords(); List<DirectoryResource> records = result.getRecords();
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
for (DirectoryResource directoryResource:records){ for (DirectoryResource directoryResource:records){
list.add(directoryResource.getDirectoryId()); list.add(directoryResource.getId());
} }
List<DirectoryResource> directoryResources = directoryResourceMapper.selectListById(list); List<DirectoryResource> directoryResources = directoryResourceMapper.selectListById(list);
Assert.notNull(auth, "用户信息认证失败"); Assert.notNull(auth, "用户信息认证失败");

@ -8,8 +8,10 @@ import com.keyware.shandan.bianmu.enums.ReviewStatus;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import javax.json.JsonObject;
import java.io.Serializable; import java.io.Serializable;
import java.util.Date; import java.util.Date;
import java.util.Map;
@Data @Data
@TableName("V_DIRECTORY_RESOURCE") @TableName("V_DIRECTORY_RESOURCE")
@ -97,4 +99,11 @@ public class DirectoryResource implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private boolean write; private boolean write;
//为自定义表格添加 是否是自定义表格 主要为导出数据时的判断条件
@TableField(exist = false)
private Boolean isCustom ;
@TableField(exist = false)
private Map<String,String> customConfigMap ;
} }

@ -7,6 +7,7 @@ import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
import cn.hutool.poi.excel.BigExcelWriter; import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.keyware.shandan.bianmu.entity.DirectoryResource; import com.keyware.shandan.bianmu.entity.DirectoryResource;
@ -18,12 +19,10 @@ import com.keyware.shandan.frame.config.component.AppContext;
import com.keyware.shandan.system.entity.SysFile; import com.keyware.shandan.system.entity.SysFile;
import com.keyware.shandan.system.service.SysFileService; import com.keyware.shandan.system.service.SysFileService;
import com.keyware.shandan.system.utils.SysSettingUtil; import com.keyware.shandan.system.utils.SysSettingUtil;
import org.elasticsearch.cluster.ClusterState;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class DirectoryExport extends ExportProgress { public class DirectoryExport extends ExportProgress {
@ -48,6 +47,8 @@ public class DirectoryExport extends ExportProgress {
dataList.forEach(resource -> { dataList.forEach(resource -> {
if ("file".equals(resource.getResourceType())) { if ("file".equals(resource.getResourceType())) {
exportFile(resource); exportFile(resource);
} else if (resource.getIsCustom() != null && resource.getIsCustom()) {
exportCustomMetadata(resource);
} else { } else {
exportMetadata(resource); exportMetadata(resource);
} }
@ -90,7 +91,7 @@ public class DirectoryExport extends ExportProgress {
* *
* @param resource 数据资源 * @param resource 数据资源
*/ */
private void exportMetadata(DirectoryResource resource) { private void exportCustomMetadata(DirectoryResource resource) {
File serverFile = new File(createResourceDir(resource.getDirectoryPath())); File serverFile = new File(createResourceDir(resource.getDirectoryPath()));
String path = serverFile.getPath() + ".xlsx"; String path = serverFile.getPath() + ".xlsx";
MetadataBasicVo metadata = null; MetadataBasicVo metadata = null;
@ -113,6 +114,71 @@ public class DirectoryExport extends ExportProgress {
path = dirPath + File.separator + "(数据读取错误)" + temp.getName(); path = dirPath + File.separator + "(数据读取错误)" + temp.getName();
} }
String fieldConfig = resource.getCustomConfigMap().get("fieldConfig");
JSONArray configobj = JSON.parseArray(fieldConfig);
// 所有行的集合
List<List<String>> rowList = new ArrayList<>();
// 字段列名集合
String[] colNameArr = new String[configobj.size()];
// 字段列名注释集合,当做表格的第一行
List<String> columns =StreamUtil.as(configobj).map(field -> {
JSONObject obj = (JSONObject) field;
String fieldKey = obj.getString("fieldKey");
String fieldName = obj.getString("fieldName");
colNameArr[Integer.parseInt(obj.getString("fieldIndex"))] = fieldName;
return fieldName + (StringUtils.hasText(fieldKey) ? "[" + fieldName + "]" : "");
}).toList();
List<String> colNameList = Arrays.asList(colNameArr);
// 添加第一行
rowList.add(columns);
// 遍历数据
datas.forEach(data -> {
// 遍历字段列名,获取对应数据并拼接成列的集合
List<String> cells = colNameList.stream().map(col -> {
Object value = data.get(col);
if (value == null) {
return "";
}
return String.valueOf(value);
}).collect(Collectors.toList());
rowList.add(cells);
});
List<List<String>> rows = CollUtil.newArrayList(rowList);
//通过工具类创建writer
BigExcelWriter writer = ExcelUtil.getBigWriter(path);
//一次性写出内容
writer.write(rows);
//关闭writer,释放内存
writer.close();
}
/**
* 导出数据表
*
* @param resource 数据资源
*/
private void exportMetadata(DirectoryResource resource) {
File serverFile = new File(createResourceDir(resource.getDirectoryPath()));
String path = serverFile.getPath() + ".xlsx";
MetadataBasicVo metadata = null;
JSONArray colsArray = null;
List<Map<String, Object>> datas = null;
try {
metadata = metadataService.getById(resource.getId());
colsArray = metadataService.getColumns(metadata.getId());
datas = metadataService.getDynamicData(metadata);
} catch (Exception e) {
colsArray = new JSONArray();
JSONObject defaultJson = new JSONObject();
defaultJson.put("comment", "数据查询失败,无法连接到指定的数据库");
colsArray.add(defaultJson);
datas = new ArrayList<>();
File temp = new File(path);
String dirPath = temp.getParentFile().getPath();
path = dirPath + File.separator + "(数据读取错误)" + temp.getName();
}
// 所有行的集合 // 所有行的集合
List<List<String>> rowList = new ArrayList<>(); List<List<String>> rowList = new ArrayList<>();
// 字段列名集合 // 字段列名集合
@ -183,4 +249,9 @@ public class DirectoryExport extends ExportProgress {
public String getDownloadPath() { public String getDownloadPath() {
return zipName; return zipName;
} }
@Override
public String tranType() {
return null;
}
} }

@ -37,6 +37,7 @@ public abstract class ExportProgress implements Runnable, Serializable {
public abstract long getStepTotal(); public abstract long getStepTotal();
public abstract String getDownloadPath(); public abstract String getDownloadPath();
public abstract String tranType();
/** /**
* 偏移量自增 * 偏移量自增

@ -188,4 +188,9 @@ public class FileSearchExport extends ExportProgress {
return zipName; return zipName;
} }
@Override
public String tranType() {
return null;
}
} }

@ -13,9 +13,17 @@ import com.keyware.shandan.frame.config.component.AppContext;
import com.keyware.shandan.system.entity.SysOrg; import com.keyware.shandan.system.entity.SysOrg;
import com.keyware.shandan.system.entity.SysUser; import com.keyware.shandan.system.entity.SysUser;
import com.keyware.shandan.system.service.SysUserService; import com.keyware.shandan.system.service.SysUserService;
import com.keyware.shandan.system.utils.Word2PdfAsposeUtil;
import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -36,6 +44,8 @@ public class MetaTableExport extends ExportProgress {
private final List<Map<String, Object>> datas = new ArrayList<>(); private final List<Map<String, Object>> datas = new ArrayList<>();
private Consumer<List<Map<String, Object>>> queryHandler; private Consumer<List<Map<String, Object>>> queryHandler;
private boolean isDone = false; private boolean isDone = false;
//新添加 导出
private String type;
public MetaTableExport(String userId, MetadataBasicVo metadata) { public MetaTableExport(String userId, MetadataBasicVo metadata) {
super(userId); super(userId);
@ -49,6 +59,18 @@ public class MetaTableExport extends ExportProgress {
fileName = tempDir + File.separator + name + ".xlsx"; fileName = tempDir + File.separator + name + ".xlsx";
} }
public MetaTableExport(String userId, MetadataBasicVo metadata,String type) {
super(userId);
this.userService = AppContext.getContext().getBean(SysUserService.class);
this.metadataService = AppContext.getContext().getBean(MetadataService.class);
this.metadata = metadata;
String name = metadata.getMetadataComment();
if (!StringUtils.hasText(name)) {
name = metadata.getMetadataName();
}
fileName = tempDir + File.separator + name + ".xlsx";
this.type=type;
}
@Override @Override
public void run() { public void run() {
this.setTitle("正在读取数据表信息"); this.setTitle("正在读取数据表信息");
@ -65,36 +87,23 @@ public class MetaTableExport extends ExportProgress {
JSONObject field = (JSONObject) json; JSONObject field = (JSONObject) json;
return field.getString("comment"); return field.getString("comment");
}).collect(Collectors.toList())); }).collect(Collectors.toList()));
try { try {
this.setTitle("正在查询数据"); this.setTitle("正在查询数据");
this.autoAddStep(); this.autoAddStep();
this.queryHandler.accept(this.datas); this.queryHandler.accept(this.datas);
handleResult(); handleResult();
File file = new File(fileName); File file = new File(fileName);
if (file.exists()) { if (file.exists()) {
file.delete(); file.delete();
} }
List<List<String>> rows = CollUtil.newArrayList(rowList); List<List<String>> rows = CollUtil.newArrayList(rowList);
//通过工具类创建writer if (type==null||"excel".equals(type)){
BigExcelWriter writer = ExcelUtil.getBigWriter(file); excelExport(fileName, rows);
}else if ("word".equals(type)){
this.setTitle("正在写入缓存"); wordExport(fileName, rows);
this.autoAddStep(); }else if("pdf".equals(type)){
// 添加表头 pdfExport(fileName, rows);
addTableHeader(writer); }
//一次性写出内容
writer.write(rows, true);
this.setTitle("正在写入文件");
this.autoAddStep();
//写入文件后关闭writer,释放内存
writer.close();
this.autoAddStep();
this.setTitle("数据文件准备完毕,开始下载"); this.setTitle("数据文件准备完毕,开始下载");
isDone = true; isDone = true;
} catch (Exception e) { } catch (Exception e) {
@ -105,6 +114,33 @@ public class MetaTableExport extends ExportProgress {
} }
} }
/**
* excel导出
* @param fileName
* @param rows
* @author YaoJz
* @date 2024/04/23 10:44
*/
private void excelExport(String fileName, List<List<String>> rows) {
File file = new File(fileName);
//通过工具类创建writer
BigExcelWriter writer = ExcelUtil.getBigWriter(file);
this.setTitle("正在写入缓存");
this.autoAddStep();
// 添加表头
addTableHeader(writer);
//一次性写出内容
writer.write(rows, true);
this.setTitle("正在写入文件");
this.autoAddStep();
//写入文件后关闭writer,释放内存
writer.close();
this.autoAddStep();
}
private void addTableHeader(BigExcelWriter writer) { private void addTableHeader(BigExcelWriter writer) {
SysUser user = userService.getById(getUserId()); SysUser user = userService.getById(getUserId());
SysOrg org = user.getOrg(); SysOrg org = user.getOrg();
@ -138,6 +174,20 @@ public class MetaTableExport extends ExportProgress {
return this.fileName; return this.fileName;
} }
/**
* 文件类型转换 转换后缀名
* @return java.lang.String
* @author YaoJz
* @date 2024/04/23 12:42
*/
@Override
public String tranType(){
switch (type){
case "word": return this.fileName.replace(".xlsx", ".docx");
case "pdf": return this.fileName.replace(".xlsx", ".pdf");
default: return this.fileName;
}
}
public void handleResult() { public void handleResult() {
for (Map<String, Object> data : this.datas) { for (Map<String, Object> data : this.datas) {
// 遍历字段列名,获取对应数据并拼接成列的集合 // 遍历字段列名,获取对应数据并拼接成列的集合
@ -158,4 +208,208 @@ public class MetaTableExport extends ExportProgress {
public boolean getIsDone() { public boolean getIsDone() {
return isDone; return isDone;
} }
public static void main(String[] args) {
test();
}
public void pdfExport(String fileName, List<List<String>> rows){
wordExport(fileName,rows);
String wordPath = fileName.replace(".xlsx", ".docx");
String pdfPath = fileName.replace(".xlsx", ".pdf");
Word2PdfAsposeUtil.doc2pdf(wordPath,pdfPath);
}
public void wordExport(String fileName, List<List<String>> rows){
// 1.创建一个新的Word文档
XWPFDocument document = new XWPFDocument();
FileOutputStream fos = null;
try {
// 2.创建一个新的表格
int cols=0;
if (rows.get(0)!=null){
cols=rows.get(0).size();
}
XWPFTable table = document.createTable(rows.size(), cols);
// 3.设置表格样式
table.getCTTbl().addNewTblPr().addNewTblStyle().setVal("Table Grid");
table.setWidth(10); // 设置表格宽度为100%
// 4.填充表格内容
XWPFTableCell cell = null;
for (int row = 0; row < rows.size(); row++) { // 循环遍历表格的行
for (int col = 0; col < cols; col++) { // 循环遍历表格的列
// 获取当前单元格
cell = table.getRow(row).getCell(col);
// 设置单元格内容垂直居中
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
// 设置单元格内容水平居中(获取单元格中的第一个段落对象)
cell.getParagraphArray(0).setAlignment(ParagraphAlignment.CENTER);
// 设置单元格内容
cell.setText(rows.get(row).get(col));
}
}
// 保存文档
// 输出流,用于将文档写入磁盘
String wordPath = fileName.replace(".xlsx", ".docx");
fos = new FileOutputStream(wordPath);
// 将文档写入输出流
document.write(fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
// 关闭输出流
fos.close();
if (document != null) {
// 关闭Word文档
document.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void test() {
// 1.创建一个新的Word文档
XWPFDocument document = new XWPFDocument();
FileOutputStream fos = null;
try {
// 2.创建一个新的表格,11行7列
XWPFTable table = document.createTable(11, 7);
// 3.设置表格样式
table.getCTTbl().addNewTblPr().addNewTblStyle().setVal("Table Grid");
table.setWidth(100); // 设置表格宽度为100%
// 4.填充表格内容
XWPFTableCell cell = null;
for (int row = 0; row < 11; row++) { // 循环遍历表格的行
for (int col = 0; col < 7; col++) { // 循环遍历表格的列
// 获取当前单元格
cell = table.getRow(row).getCell(col);
// 设置单元格内容垂直居中
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
// 设置单元格内容水平居中(获取单元格中的第一个段落对象)
cell.getParagraphArray(0).setAlignment(ParagraphAlignment.CENTER);
// 设置单元格内容
cell.setText("行 " + (row + 1) + ", 列 " + (col + 1));
}
}
/**
// 5.合并单元格方式一 // 5.1 合并第1行的第2列到第4列
table.getRow(0).getCell(1).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
table.getRow(0).getCell(2).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
table.getRow(0).getCell(3).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
// 5.2 合并第1列的第3行到第4行
table.getRow(2).getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
table.getRow(3).getCell(0).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
// 5.3 合并第4行第4列、第5列、第5行第4列、第5列为一个单元格 // 5.3.1 合并第4行的第4列到第5列
table.getRow(3).getCell(3).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
table.getRow(3).getCell(4).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
// 5.3.2 合并第5行的第4列到第5列
table.getRow(4).getCell(3).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
table.getRow(4).getCell(4).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
// 5.3.3 合并第4列的第4行到第5行
table.getRow(3).getCell(3).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
table.getRow(4).getCell(3).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
**/
// 6.合并单元格方式二(推荐)
// 6.1 水平合并第1行的第2列到第4列
mergeCellsByHorizontal(table, 0, 1, 3);
// 6.2 垂直合并第1列的第3行到第4行
mergeCellsByVertically(table, 0, 2, 3);
// 6.3 合并第4行第4列、第5列、第5行第4列、第5列为一个单元格
// 6.3.1 合并第4行的第4列到第5列
mergeCellsByHorizontal(table, 3, 3, 4);
// 6.3.2 合并第5行的第4列到第5列
mergeCellsByHorizontal(table, 4, 3, 4);
// 6.3.3 合并第4列的第4行到第5行
mergeCellsByVertically(table, 3, 3, 4);
// 保存文档
// 输出流,用于将文档写入磁盘
fos = new FileOutputStream("D:\\testwordexport\\test.docx");
// 将文档写入输出流
document.write(fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
// 关闭输出流
fos.close();
if (document != null) {
// 关闭Word文档
document.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Word2PdfAsposeUtil.doc2pdf("D:\\testwordexport\\test.docx","D:\\testwordexport\\test.pdf");
System.out.println("Word文档生成成功!");
}
// ==================== private method ====================
/**
* <h5>描述:水平方向合并单元格<h5>
* @param table 表格
* @param rowIndex 合并列所在的行下标(从0开始)
* @param startCellIndex 开始合并的列下标(从0开始)
* @param endCellIndex 结束合并的列下标(从0开始)
*/
private static void mergeCellsByHorizontal(XWPFTable table, int rowIndex, int startCellIndex, int endCellIndex) {
String str = "";
for (int i = startCellIndex; i <= endCellIndex; i++) {
XWPFTableCell cell = table.getRow(rowIndex).getCell(i);
str = "table.getRow("+rowIndex+").getCell("+i+")";
if (i == startCellIndex) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
System.out.println(str + ".getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);");
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
System.out.println(str + ".getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);");
}
}
}
/**
* <h5>描述:垂直方向合并单元格<h5>
* @param table 表格
* @param columnIndex 合并行所在列下标(从0开始)
* @param startCell 开始合并的行下标(从0开始)
* @param endCell 结束合并的行下标(从0开始)
*/
private static void mergeCellsByVertically(XWPFTable table, int columnIndex, int startRowIndex, int endRowIndex) {
String str = "";
for (int i = startRowIndex; i <= endRowIndex; i++) {
XWPFTableCell cell = table.getRow(i).getCell(columnIndex);
str = "table.getRow("+i+").getCell("+columnIndex+")";
if (i == startRowIndex) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
System.out.println(str + ".getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);");
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
System.out.println(str + ".getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);");
}
}
}
} }

@ -20,7 +20,6 @@ import com.keyware.shandan.system.service.SysFormConfigService;
import com.keyware.shandan.system.service.SysSettingService; import com.keyware.shandan.system.service.SysSettingService;
import com.keyware.shandan.system.utils.DictUtil; import com.keyware.shandan.system.utils.DictUtil;
import com.keyware.shandan.system.utils.FileChunkUploadUtil; import com.keyware.shandan.system.utils.FileChunkUploadUtil;
import lombok.val;
import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin4j.PinyinHelper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert; import org.springframework.util.Assert;

@ -0,0 +1,82 @@
package com.keyware.shandan.system.utils;
import com.aspose.words.Document;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @BelongsProject: xscan
* @BelongsPackage: com.keyware.xscan.util
* @Author: yaojz
* @CreateTime: 2022-08-05 13:59
* @Description: TODO
* @Version: ***
*/
public class Word2PdfAsposeUtil {
private static final Logger logger = LoggerFactory.getLogger(Word2PdfAsposeUtil.class);
/**
*
* @return
*/
public static boolean getLicense() {
boolean result = false;
InputStream is = null;
try {
Resource resource = new ClassPathResource("Aspose.license.lic");
is = resource.getInputStream();
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
logger.error("获取许可证异常...",e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
logger.error("关闭流异常...",e);
}
}
}
return result;
}
/**
* @return boolean
* @Param [inPath, outPath]
**/
public static boolean doc2pdf(String inPath, String outPath) {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getLicense()) {
return false;
}
File file = new File(outPath);
// FileOutputStream os = null;
try(FileOutputStream osStream = new FileOutputStream(file) ) {
long old = System.currentTimeMillis();
// 新建一个空白pdf文档
// Address是将要被转化的word文档
Document doc = new Document(inPath);
// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,
doc.save(osStream, SaveFormat.PDF);
osStream.flush();
osStream.close();
// EPUB, XPS, SWF 相互转换
long now = System.currentTimeMillis();
// 转化用时
System.out.println("pdf转换成功,共耗时:" + ((now - old) / 1000.0) + "秒");
} catch (Exception e) {
logger.error("pdf转换失败...",e);
return false;
}
return true;
}
}

@ -0,0 +1,20 @@
<License>
<Data>
<LicensedTo>iMedRIS Data Corporation</LicensedTo>
<EmailTo>whs@imedris.com</EmailTo>
<LicenseType>Developer OEM</LicenseType>
<LicenseNote>Limited to 1 developer, unlimited physical locations</LicenseNote>
<OrderID>190103154649</OrderID>
<UserID>289601</UserID>
<OEM>This is a redistributable license</OEM>
<Products>
<Product>Aspose.Total for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SerialNumber>7f645a78-5687-4fad-ab7f-9b4141651d27</SerialNumber>
<SubscriptionExpiry>20200403</SubscriptionExpiry>
<LicenseVersion>3.0</LicenseVersion>
<LicenseInstructions>https://purchase.aspose.com/policies/use-license</LicenseInstructions>
</Data>
<Signature>cqB2T9ic/d8/1ICIPO2PoYfvwQaljWeY3om8xXMo4zllu3h/xL1CbF8iFc6xk1RXXq2UOd3XKfJL9QnoRtjm3IHod2iINB+DC1lolh5GumiJkR/C8oighnumtCIDJHZyEQvyAK1oqELhTWVlLcpyXOkIwdhXDI6l4/uhptYGz3E=</Signature>
</License>