diff --git a/doc/docs/.vuepress/config.js b/doc/docs/.vuepress/config.js index dbc5da55..e4198973 100644 --- a/doc/docs/.vuepress/config.js +++ b/doc/docs/.vuepress/config.js @@ -34,6 +34,7 @@ module.exports = { collapsable: false, children: [ {title: 'V1.0.0', path: '/guide/releases/1.0.0'}, + {title: 'V1.1.0', path: '/guide/releases/1.1.0'}, ] }, { diff --git a/doc/docs/guide/charts.md b/doc/docs/guide/charts.md index fec268d8..d0cd2113 100644 --- a/doc/docs/guide/charts.md +++ b/doc/docs/guide/charts.md @@ -54,6 +54,20 @@ 当超链接和视频链接无效的时候,请尝试使用内联框架。
+## 样式组件 + +### 边框 + +![img42](../picture/charts/img_42.png)
+ +### 装饰 + +![img43](../picture/charts/img_43.png)
+ +### 装饰饼图 + +![img12](../picture/charts/img_12.png)
+ ## 柱状图 ### 柱状图 @@ -265,13 +279,6 @@ **如有问题,请提交 [Issue](https://gitee.com/anji-plus/report/issues)
** -## 装饰图 - -### 装饰饼图 - -装饰用,可单独使用或者配合文本框等图表组件来使整个大屏立体、丰满。
-![img12](../picture/charts/img_12.png)
- ## 词云图 ### 词云图 diff --git a/doc/docs/guide/chartsLinkage.md b/doc/docs/guide/chartsLinkage.md index 2ce62d2c..02b7ffee 100644 --- a/doc/docs/guide/chartsLinkage.md +++ b/doc/docs/guide/chartsLinkage.md @@ -1,12 +1,38 @@ ## 简要说明 现有系统联动的本质是数据集查询参数“示例值”的替换, 现在联动有两种。
+除下文介绍的示例外,还可去数据集、体验地址去查看示例。
- 表单联动
目前支持的有下拉框、时间筛选器。
+ V1.0.0 支持被联动的组件有:
+ - 文本栏 - V1.1.0 + - 文本 + - 滚动文本 + - 表格 + - 柱状图(包含全部) + - 折线图(包含全部) + - 柱线图(包含全部) + - 饼图(包含全部) + - 漏斗图(包含全部) + - 百分比(包含全部)-V1.1.0 + - 中国地图(包含全部) + - 词云图(包含全部)-V1.1.0 + - 热力图(包含全部) + - 雷达图(包含全部) + - 刻度尺(包含全部)-V1.1.0 - 图表联动:
目前联动主要集中在柱状图、折线图、饼图等这种二维图表,二维图表是指图表只支持2个字段的数据集,当然并不是说需要3个字段的堆叠图(柱状/折线)不支持联动,而是这种三维图表去联动二维图表会带来一些问题,反之二维的去联动三维的同样存在问题,因此目前源代码中只添加了部分二维图表的联动。
+ V1.0.0 支持联动的组件有:
+ - 柱状图 + - 柱状图 + - 柱状图-渐变色 + - 折线图 + - 折线图 + - 饼图 + - 饼图 + - 南丁格尔玫瑰图 **注:** 没有多级联动,联动都是一对一的。例如,时间筛选器绑定了A柱图,A柱图绑定了B饼图,当使用时间筛选器更改时间后,只会更新绑定的A柱图,A绑定的B饼图并不会更新数据。
diff --git a/doc/docs/guide/dataset.md b/doc/docs/guide/dataset.md index 902b9345..d93ff4dc 100644 --- a/doc/docs/guide/dataset.md +++ b/doc/docs/guide/dataset.md @@ -51,26 +51,54 @@ 自定义JS,这里的JS是java的scriptengine执行的,支持ES5的写法。 +- 示例一
+ 返回yyyyy-MM-dd类型的当前时间 + ```js -//返回yyyyy-MM-dd类型的当前时间 -function verification(data){ - //自定义脚本内容 - //获取当前时间 - var date = new Date(); - var year = date.getFullYear(); - var month = date.getMonth() + 1; - var day = date.getDate(); - if (month < 10) { - month = "0" + month; - } - if (day < 10) { - day = "0" + day; - } - var nowDate = year + "-" + month + "-" + day; - return nowDate; +// 返回yyyyy-MM-dd类型的当前时间 +function verification(data) { + //自定义脚本内容 + //获取当前时间 + var date = new Date(); + var year = date.getFullYear(); + var month = date.getMonth() + 1; + var day = date.getDate(); + if (month < 10) { + month = "0" + month; + } + if (day < 10) { + day = "0" + day; + } + var nowDate = year + "-" + month + "-" + day; + return nowDate; } ``` +- 示例二
+ 不传参则查询全部 + +```sql +// sql可以这么写 +SELECT DATE_FORMAT(create_time, '%Y-%m-%d') create_time, sum(nums) sum_nums +FROM aj_report_city ${city_name} +group by create_time; +``` + +```js +// 不传参则查询全部 +function verification(data) { + // 获取示例值 + data = data.sampleItem; + if (data == null || data == '') { + return '' + } + data = 'where city_name = "' + data + '" ' + return data; +} +``` + +**注:** 当前V1.0.0版本示例值是不可为空的,所以实际使用可能会麻烦点 + ### 数据转换 数据转换是在执行完 sql 之后进行的数据清洗操作。 @@ -82,26 +110,26 @@ function verification(data){ ```js // 根据sql查询出的结果进行数据清洗 -function dataTransform(data){ - //自定义脚本内容 - - //1.遍历测试预览中的java.util.ArrayList - for(j = 0, len = data.length; j < len; j++){ - //获取一行数据 - var row = data[j] - //比如对brand字段进行拆分,例如A-100,B-50 - var brand = row['brand'] - var split = brand.split('-') - //新增两个字段 - var model = split[0] - var series = split[1] - - //对原始对象赋值 - data[j]['model'] = model - data[j]['series'] = series - - } - return data; +function dataTransform(data) { + //自定义脚本内容 + + //1.遍历测试预览中的java.util.ArrayList + for (j = 0, len = data.length; j < len; j++) { + //获取一行数据 + var row = data[j] + //比如对brand字段进行拆分,例如A-100,B-50 + var brand = row['brand'] + var split = brand.split('-') + //新增两个字段 + var model = split[0] + var series = split[1] + + //对原始对象赋值 + data[j]['model'] = model + data[j]['series'] = series + + } + return data; } ``` diff --git a/doc/docs/guide/releases/1.1.0.md b/doc/docs/guide/releases/1.1.0.md new file mode 100644 index 00000000..63c72522 --- /dev/null +++ b/doc/docs/guide/releases/1.1.0.md @@ -0,0 +1,24 @@ +## 注意事项 + +- 之前版本更新至本版本时,可能会遇到图表不显示静态、动态数据,需对该图表重新配置;如果已对旧版本进行二次开发,请谨慎更新。
+ 跨版本更新可查对应版本的[releases](https://gitee.com/anji-plus/report/releases)。
+ +## 新增/优化 + +- 1、引入datav依赖,新增样式组件,装饰边框+装饰图 贡献人:wenqindong@wenqindong +- 2、大屏图表-文本组件增加对多行的支持 贡献人:StefanZhu@stefanZhu +- 3、Excel报表支持pdf导出 贡献人:陈旭光@chen-xuguang +- 4、大屏文本栏组件-文本、滚动文本、表格支持被联动 +- 5、大屏刻度尺组件-被联动,词云组件-被联动,仪表盘被联动 + +## 修复 + +- 1、部分图表的副标题和数值设定颜色冲突 +- 2、当数据集第一条数据中存在null值时被自动过滤导致未能解析 +- 3、大屏图表-仪表盘的配置项冲突重复 +- 4、大屏图片-饼图图例位置不正确问题 +- 5、装饰饼图不显示问题 + +## 其他 + +- 1、文档更新 diff --git a/doc/docs/picture/charts/img_42.png b/doc/docs/picture/charts/img_42.png new file mode 100644 index 00000000..a255ced6 Binary files /dev/null and b/doc/docs/picture/charts/img_42.png differ diff --git a/doc/docs/picture/charts/img_43.png b/doc/docs/picture/charts/img_43.png new file mode 100644 index 00000000..02b643d1 Binary files /dev/null and b/doc/docs/picture/charts/img_43.png differ diff --git a/report-core/pom.xml b/report-core/pom.xml index 4fc498d3..ad74fd59 100644 --- a/report-core/pom.xml +++ b/report-core/pom.xml @@ -166,6 +166,18 @@ 3.0.9 + + org.xhtmlrenderer + core-renderer + R8 + + + + com.itextpdf.tool + xmlworker + 5.5.13 + + diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataset/service/impl/DataSetServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataset/service/impl/DataSetServiceImpl.java index a39faf70..d669254b 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataset/service/impl/DataSetServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/dataset/service/impl/DataSetServiceImpl.java @@ -1,8 +1,11 @@ package com.anjiplus.template.gaea.business.modules.dataset.service.impl; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.Feature; +import com.alibaba.fastjson.serializer.SerializerFeature; import com.anji.plus.gaea.constant.Enabled; import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper; import com.anji.plus.gaea.exception.BusinessExceptionBuilder; @@ -27,6 +30,7 @@ import com.anjiplus.template.gaea.business.util.JdbcConstants; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; @@ -39,10 +43,10 @@ import java.util.*; import java.util.stream.Collectors; /** -* @desc DataSet 数据集服务实现 -* @author Raod -* @date 2021-03-18 12:11:31.150755900 -**/ + * @author Raod + * @desc DataSet 数据集服务实现 + * @date 2021-03-18 12:11:31.150755900 + **/ @Service //@RequiredArgsConstructor @Slf4j @@ -62,7 +66,7 @@ public class DataSetServiceImpl implements DataSetService { @Override public GaeaBaseMapper getMapper() { - return dataSetMapper; + return dataSetMapper; } /** @@ -113,9 +117,9 @@ public class DataSetServiceImpl implements DataSetService { List dataSetTransformList = dataSetTransformService.list( new QueryWrapper() - .lambda() - .eq(DataSetTransform::getSetCode, setCode) - .orderByAsc(DataSetTransform::getOrderNum) + .lambda() + .eq(DataSetTransform::getSetCode, setCode) + .orderByAsc(DataSetTransform::getOrderNum) ); List dataSetTransformDtoList = new ArrayList<>(); dataSetTransformList.forEach(dataSetTransform -> { @@ -131,7 +135,7 @@ public class DataSetServiceImpl implements DataSetService { JSONObject jsonObject = jsonArray.getJSONObject(0); dto.setSetParamList(jsonObject.keySet()); } catch (Exception e) { - log.error("error",e); + log.error("error", e); } } return dto; @@ -159,7 +163,7 @@ public class DataSetServiceImpl implements DataSetService { Object o = objects.get(0); objects = new JSONArray(); objects.add(o); - dataSet.setCaseResult(objects.toJSONString()); + dataSet.setCaseResult(JSON.toJSONString(objects, SerializerFeature.WriteMapNullValue)); } } catch (Exception e) { log.info("结果集只保留一行数据失败...{}", e.getMessage()); @@ -180,7 +184,7 @@ public class DataSetServiceImpl implements DataSetService { * @param dto */ @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public void updateSet(DataSetDto dto) { List dataSetParamDtoList = dto.getDataSetParamDtoList(); List dataSetTransformDtoList = dto.getDataSetTransformDtoList(); @@ -194,7 +198,7 @@ public class DataSetServiceImpl implements DataSetService { Object o = objects.get(0); objects = new JSONArray(); objects.add(o); - dataSet.setCaseResult(objects.toJSONString()); + dataSet.setCaseResult(JSON.toJSONString(objects, SerializerFeature.WriteMapNullValue)); } } catch (Exception e) { log.info("结果集只保留一行数据失败...{}", e.getMessage()); @@ -266,12 +270,12 @@ public class DataSetServiceImpl implements DataSetService { String body = JSONObject.parseObject(dynSentence).getString("body"); if (StringUtils.isNotBlank(body)) { dynSentence = body; - }else { + } else { dynSentence = "{}"; } - }else { - dataSource = dataSourceService.selectOne("source_code", dataSetDto.getSourceCode()); + } else { + dataSource = dataSourceService.selectOne("source_code", dataSetDto.getSourceCode()); } //3.参数替换 @@ -322,12 +326,12 @@ public class DataSetServiceImpl implements DataSetService { String body = JSONObject.parseObject(dynSentence).getString("body"); if (StringUtils.isNotBlank(body)) { dynSentence = body; - }else { + } else { dynSentence = "{}"; } - }else { - dataSource = dataSourceService.selectOne("source_code", sourceCode); + } else { + dataSource = dataSourceService.selectOne("source_code", sourceCode); } //3.参数替换 @@ -374,7 +378,7 @@ public class DataSetServiceImpl implements DataSetService { return dataSetMapper.selectList(wrapper); } - public void dataSetParamBatch(List dataSetParamDtoList,String setCode){ + public void dataSetParamBatch(List dataSetParamDtoList, String setCode) { dataSetParamService.delete( new QueryWrapper() .lambda() @@ -396,7 +400,7 @@ public class DataSetServiceImpl implements DataSetService { } - public void dataSetTransformBatch(List dataSetTransformDtoList,String setCode){ + public void dataSetTransformBatch(List dataSetTransformDtoList, String setCode) { dataSetTransformService.delete( new QueryWrapper() .lambda() @@ -420,10 +424,11 @@ public class DataSetServiceImpl implements DataSetService { /** * dataSetParamDtoList转map + * * @param dataSetParamDtoList * @return */ - public Map setContextData(List dataSetParamDtoList){ + public Map setContextData(List dataSetParamDtoList) { Map map = new HashMap<>(); if (null != dataSetParamDtoList && dataSetParamDtoList.size() > 0) { dataSetParamDtoList.forEach(dataSetParamDto -> map.put(dataSetParamDto.getParamName(), dataSetParamDto.getSampleItem())); diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CellStyleDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CellStyleDto.java new file mode 100644 index 00000000..07cf70b2 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CellStyleDto.java @@ -0,0 +1,20 @@ +package com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto; + +import lombok.Data; + +/** + * @author chenxg + * @date 2023/8/1 10:37 + */ +@Data +public class CellStyleDto { + /** + * 格式名称 + */ + private String fa; + + /** + * 格式类型 + */ + private String t; +} \ No newline at end of file diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CommentDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CommentDto.java new file mode 100644 index 00000000..acc26525 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/CommentDto.java @@ -0,0 +1,42 @@ +package com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto; + + +import lombok.Data; + +/** + * @author chenxg + * @date 2023/8/1 10:37 + */ +@Data +public class CommentDto { + /** + * 批注框左边距 + */ + private int left; + + /** + * 批注框上边距 + */ + private int top; + + /** + * 批注框宽度 + */ + private int width; + + /** + * 批注框高度 + */ + private int height; + + /** + * 批注内容 + */ + private String value; + + /** + * 批注框是否显示 + */ + private boolean isshow; +} + diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelDto.java index df92b09f..739563f0 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelDto.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelDto.java @@ -5,6 +5,7 @@ import com.anji.plus.gaea.curd.dto.GaeaBaseDTO; import lombok.Data; import java.io.Serializable; +import java.util.List; /** @@ -58,4 +59,9 @@ public class ReportExcelDto extends GaeaBaseDTO implements Serializable { */ private String exportType; + /** + * 报表总体数据 + */ + private String rowDatas; + } diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelStyleDto.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelStyleDto.java new file mode 100644 index 00000000..dc8d41f9 --- /dev/null +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/controller/dto/ReportExcelStyleDto.java @@ -0,0 +1,97 @@ + +package com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto; + +import com.anji.plus.gaea.curd.dto.GaeaBaseDTO; +import lombok.Data; + +import java.io.Serializable; + + +/** + * @author chenxg + * @date 2023/8/1 10:37 + */ +@Data +public class ReportExcelStyleDto extends GaeaBaseDTO implements Serializable { + /** + * 单元格值格式 + */ + private CellStyleDto ct; + + /** + * 内容的原始值 + */ + private String v; + + /** + * 内容的显示值 + */ + private String m; + + /** + * 背景颜色 + */ + private String bg; + + /** + * 字体编号 + */ + private String ff; + + /** + * 字体颜色 + */ + private String fc; + + /** + * 是否加粗 + */ + private boolean bl; + + /** + * 是否斜体 + */ + private boolean it; + + /** + * 字体大小 + */ + private int fs; + + /** + * 是否删除线 + */ + private boolean cl; + + /** + * 水平对齐方式 + */ + private int ht; + + /** + * 垂直对齐方式 + */ + private int vt; + + /** + * 文字旋转角度 + */ + private int tr; + + /** + * 是否自动换行 + */ + private int tb; + + /** + * 批注信息 + */ + private CommentDto ps; + + /** + * 单元格公式 + */ + private String f; + + +} \ No newline at end of file diff --git a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java index fd17950a..911d1ada 100644 --- a/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java +++ b/report-core/src/main/java/com/anjiplus/template/gaea/business/modules/reportexcel/service/impl/ReportExcelServiceImpl.java @@ -19,29 +19,40 @@ import com.anjiplus.template.gaea.business.modules.file.service.GaeaFileService; import com.anjiplus.template.gaea.business.modules.report.dao.ReportMapper; import com.anjiplus.template.gaea.business.modules.report.dao.entity.Report; import com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto.ReportExcelDto; +import com.anjiplus.template.gaea.business.modules.reportexcel.controller.dto.ReportExcelStyleDto; import com.anjiplus.template.gaea.business.modules.reportexcel.dao.ReportExcelMapper; import com.anjiplus.template.gaea.business.modules.reportexcel.dao.entity.ReportExcel; import com.anjiplus.template.gaea.business.modules.reportexcel.service.ReportExcelService; import com.anjiplus.template.gaea.business.modules.reportexcel.util.CellType; import com.anjiplus.template.gaea.business.modules.reportexcel.util.XlsUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.itextpdf.text.*; +import com.itextpdf.text.Font; +import com.itextpdf.text.pdf.BaseFont; +import com.itextpdf.text.pdf.PdfPCell; +import com.itextpdf.text.pdf.PdfPTable; +import com.itextpdf.text.pdf.PdfWriter; +import com.itextpdf.tool.xml.XMLWorkerHelper; +import com.lowagie.text.DocumentException; +import io.swagger.models.auth.In; import org.apache.commons.lang3.StringUtils; +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.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.xhtmlrenderer.pdf.ITextRenderer; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.*; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * TODO @@ -136,43 +147,286 @@ public class ReportExcelServiceImpl implements ReportExcelService { @Override public Boolean exportExcel(ReportExcelDto reportExcelDto) { + logger.error("导出..."); + exportExcelCore(reportExcelDto); + return true; + } + /** + * 抽取导出Excel核心逻辑 + */ + public void exportExcelCore(ReportExcelDto reportExcelDto) + { String reportCode = reportExcelDto.getReportCode(); String exportType = reportExcelDto.getExportType(); - logger.error("导出..."); - if (exportType.equals(ExportTypeEnum.GAEA_TEMPLATE_EXCEL.getCodeValue())) { - ReportExcelDto report = detailByReportCode(reportCode); - reportExcelDto.setJsonStr(report.getJsonStr()); - String jsonStr = analysisReportData(reportExcelDto); - List lists=(List ) JSON.parse(jsonStr); - OutputStream out = null; - File file = null; - try { - String fileName = report.getReportCode(); - File dir = new File(dictPath + ZIP_PATH); - if (!dir.exists()){ - dir.mkdirs(); - } - String filePath = dir.getAbsolutePath() + File.separator + fileName + ".xlsx"; - file = new File(filePath); - out = Files.newOutputStream(Paths.get(filePath)); - XlsUtil.exportXlsFile(out, true, lists); + List> reportExcelStyleList = new ArrayList<>(); + JSONObject rowData= JSON.parseObject(reportExcelDto.getRowDatas()); + // 将JSONObject对象转换为列表 + List dataNumList = rowData.keySet().stream().map(Integer::parseInt).sorted().collect(Collectors.toList()); + for (Integer i : dataNumList) { + JSONArray jsonArray = rowData.getJSONArray(i.toString()); + List reportExcelStyleDtos = jsonArray.toJavaList(ReportExcelStyleDto.class); + reportExcelStyleList.add(reportExcelStyleDtos); + } + ReportExcelDto report = detailByReportCode(reportCode); + reportExcelDto.setJsonStr(report.getJsonStr()); + String jsonStr = analysisReportData(reportExcelDto); + List lists=(List ) JSON.parse(jsonStr); + OutputStream out = null; + File file = null; + File pdfFile = null; + try { + String fileName = report.getReportCode(); + File dir = new File(dictPath + ZIP_PATH); + if (!dir.exists()){ + dir.mkdirs(); + } + String filePath = dir.getAbsolutePath() + File.separator + fileName + ".xlsx"; + file = new File(filePath); + out = Files.newOutputStream(Paths.get(filePath)); + XlsUtil.exportXlsFile(out, true, lists); + if (exportType.equals(ExportTypeEnum.GAEA_TEMPLATE_EXCEL.getCodeValue())) { gaeaFileService.upload(file); + } + else if(exportType.equals(ExportTypeEnum.GAEA_TEMPLATE_PDF.getCodeValue())) + { + // 将Excel文件转换为PDF + String pdfFileName = fileName + ".pdf"; + String pdfFilePath = dir.getAbsolutePath() + File.separator + pdfFileName; + pdfFile = convertExcelToPdf(filePath, pdfFilePath,reportExcelStyleList); + gaeaFileService.upload(pdfFile); + } + } catch (IOException e) { + logger.error("导出失败", e); + }finally { + try { + out.close(); + file.delete(); + if(!Objects.isNull(pdfFile)) + { + pdfFile.delete(); + } } catch (IOException e) { - logger.error("导出失败", e); - }finally { - try { - out.close(); - file.delete(); - } catch (IOException e) { - throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + throw BusinessExceptionBuilder.build(ResponseCode.FILE_OPERATION_FAILED, e.getMessage()); + } + + } + } + // 将Excel文件转换为PDF + public File convertExcelToPdf(String excelFilePath, String pdfFilePath, List> reportExcelStyleList) { + try { + // 读取Excel文件 + Workbook workbook = new XSSFWorkbook(excelFilePath); + Sheet sheet = workbook.getSheetAt(0); + + // 创建PDF文档 + Document document = new Document(PageSize.A4); + PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(pdfFilePath)); + document.open(); + + // 创建PDF表格 + PdfPTable table = new PdfPTable(sheet.getRow(0).getLastCellNum()); + table.setWidthPercentage(100); + + // 设置中文字体 + BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); + Font font = new Font(baseFont, 10, Font.NORMAL); + + // 设置表头 + Row headerRow = sheet.getRow(0); + for (int i = 0; i < headerRow.getLastCellNum(); i++) { + Cell headerCell = headerRow.getCell(i); + + // 获取单元格样式 + PdfPCell tableCell = new PdfPCell(); + tableCell.setPhrase(new Phrase(getStringValue(headerCell), font)); + ReportExcelStyleDto reportExcelStyleDto = reportExcelStyleList.get(0).get(i); + if(!Objects.isNull(reportExcelStyleDto)) + { + processCellStyle(reportExcelStyleDto,tableCell,font); } + table.addCell(tableCell); + } + // 遍历Excel表格的行和列 + for (int i = 1; i <= sheet.getLastRowNum(); i++) { + Row row = sheet.getRow(i); + if (row == null) { + // 如果行为空,创建一个空的行并添加到PDF表格中 + row = sheet.createRow(i); + } + for (int j = 0; j < headerRow.getLastCellNum(); j++) { + Cell cell = row.getCell(j, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); + if (cell.getCellType() == org.apache.poi.ss.usermodel.CellType.BLANK) { + cell.setCellValue(" "); + } + PdfPCell tableCell = new PdfPCell(); + tableCell.setPhrase(new Phrase(getStringValue(cell), font)); + ReportExcelStyleDto reportExcelStyleDto = reportExcelStyleList.get(i).get(j); + if(!Objects.isNull(reportExcelStyleDto)) + { + processCellStyle(reportExcelStyleDto,tableCell,font); + } + table.addCell(tableCell); + } } + + // 将表格添加到PDF文档中 + document.add(table); + + document.close(); + workbook.close(); + + System.out.println("Excel转换为PDF成功!"); + + return new File(pdfFilePath); + } catch (IOException e) { + e.printStackTrace(); + } catch (com.itextpdf.text.DocumentException e) { + e.printStackTrace(); } - return true; + + return null; } + /** + * 处理导出pdf文件样式 + * @param tableCell + */ + public void processCellStyle(ReportExcelStyleDto reportExcelStyleDto,PdfPCell tableCell,Font font) + { + // 处理单元格背景颜色 + String bg = reportExcelStyleDto.getBg(); + java.awt.Color color = null; + if(!Objects.isNull(bg)) + { + color = parseRGB(bg); + tableCell.setBackgroundColor(new BaseColor(color.getRed(), color.getGreen(), color.getBlue())); + } + // 处理字体 + String fc = reportExcelStyleDto.getFc(); + Integer fs = reportExcelStyleDto.getFs(); + String ff = reportExcelStyleDto.getFf(); + Boolean bl = reportExcelStyleDto.isBl(); + Boolean it = reportExcelStyleDto.isIt(); + Boolean cl = reportExcelStyleDto.isCl(); + Integer ht = reportExcelStyleDto.getHt(); + Integer vt = reportExcelStyleDto.getVt(); + + + // 设置字体颜色 + if(!Objects.isNull(fc)) + { + color = parseRGB(fc); + font.setColor(new BaseColor(color.getRed(), color.getGreen(), color.getBlue())); + } + // 设置字体 + if(!Objects.isNull(ff) && !Objects.equals("0",ff)) + { + font.setFamily(ff.toString()); + } + // 设置字体大小 + if(!Objects.isNull(fs) && !Objects.equals(0,fs)) + { + font.setSize(fs); + } + // 设置字体加粗 + if(Objects.equals(Boolean.TRUE,bl)) + { + font.setStyle(Font.BOLD); + } + // 设置字体斜体 + if(Objects.equals(Boolean.TRUE,it)) + { + font.setStyle(Font.ITALIC); + } + // 设置字体加粗且斜体 + if(Objects.equals(Boolean.TRUE,bl) && Objects.equals(Boolean.TRUE,it)) + { + font.setStyle(Font.BOLDITALIC); + } + // 是否删除线 + if(Objects.equals(Boolean.TRUE,cl)) + { + // 如果是粗体且斜体 + if (font.getStyle() == Font.BOLDITALIC) + { + font.setStyle(Font.BOLDITALIC | Font.STRIKETHRU); + } + // 如果是粗体 + else if(font.getStyle() == Font.BOLD) + { + font.setStyle(Font.BOLD | Font.STRIKETHRU); + } + // 如果是斜体 + else if(font.getStyle() == Font.ITALIC) + { + font.setStyle(Font.ITALIC | Font.STRIKETHRU); + } + else + { + font.setStyle(Font.STRIKETHRU); + } + } + // 水平对齐 + if(!Objects.isNull(ht)) + { + if(Objects.equals(ht,0)) + { + tableCell.setHorizontalAlignment(Element.ALIGN_CENTER); + } + else if(Objects.equals(ht,1)) + { + tableCell.setHorizontalAlignment(Element.ALIGN_LEFT); + } + else if(Objects.equals(ht,2)) + { + tableCell.setHorizontalAlignment(Element.ALIGN_RIGHT); + } + } + // 垂直对齐 + if(!Objects.isNull(vt)) + { + if(Objects.equals(ht,0)) + { + tableCell.setVerticalAlignment(com.itextpdf.text.Element.ALIGN_MIDDLE); + } + else if(Objects.equals(ht,1)) + { + tableCell.setVerticalAlignment(Element.ALIGN_TOP); + } + else if(Objects.equals(ht,2)) + { + tableCell.setVerticalAlignment(Element.ALIGN_BOTTOM); + } + } + Phrase phrase = tableCell.getPhrase(); + tableCell.setPhrase(new Paragraph(phrase.getContent(), font)); + //处理字体 + tableCell.setBorderColor(BaseColor.BLACK); + + } + + public static java.awt.Color parseRGB(String rgb) { + try { + String[] components = rgb.substring(rgb.indexOf("(") + 1, rgb.indexOf(")")).split(","); + int red = Integer.parseInt(components[0].trim()); + int green = Integer.parseInt(components[1].trim()); + int blue = Integer.parseInt(components[2].trim()); + + return new java.awt.Color(red, green, blue); + } catch (Exception e) { + e.printStackTrace(); + return null; // 解析失败,返回null + } + } + + private String getStringValue(Cell cell) { + if (cell == null) + return ""; + else + return cell.toString(); + } /** * 解析报表数据,动态插入列表数据和对象数据 */ diff --git a/report-core/src/main/resources/db/migration/V1.1.0__update.sql b/report-core/src/main/resources/db/migration/V1.1.0__update.sql new file mode 100644 index 00000000..e69de29b diff --git a/report-ui/package.json b/report-ui/package.json index efd67958..1858c0ad 100644 --- a/report-ui/package.json +++ b/report-ui/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "@ckeditor/ckeditor5-build-decoupled-document": "^23.1.0", + "@jiaminghi/data-view": "^2.10.0", "@smallwei/avue": "^2.8.23", "axios": "0.18.0", "chokidar": "^3.5.2", diff --git a/report-ui/src/main.js b/report-ui/src/main.js index abc86422..2fc0e97d 100644 --- a/report-ui/src/main.js +++ b/report-ui/src/main.js @@ -22,7 +22,9 @@ import 'echarts/lib/component/tooltip' //import 'echarts-liquidfill' // import 'echarts-gl' Vue.component('v-chart', ECharts) - +// 全局引入datav +import dataV from '@jiaminghi/data-view' +Vue.use(dataV) // anji component import anjiCrud from '@/components/AnjiPlus/anji-crud/anji-crud' import anjiSelect from '@/components/AnjiPlus/anji-select' diff --git a/report-ui/src/views/bigscreenDesigner/designer/index.vue b/report-ui/src/views/bigscreenDesigner/designer/index.vue index 4aa964b0..77bc8eb4 100644 --- a/report-ui/src/views/bigscreenDesigner/designer/index.vue +++ b/report-ui/src/views/bigscreenDesigner/designer/index.vue @@ -65,7 +65,7 @@ :style="{ width: widthLeftForToolsHideButton + 'px' }" @click="toolIsShow = !toolIsShow" > - +
- + - + @@ -349,7 +349,7 @@ + diff --git a/report-ui/src/views/bigscreenDesigner/designer/widget/decorate/widgetDecoratePieChart.vue b/report-ui/src/views/bigscreenDesigner/designer/widget/styleWidget/widgetDecoratePieChart.vue similarity index 99% rename from report-ui/src/views/bigscreenDesigner/designer/widget/decorate/widgetDecoratePieChart.vue rename to report-ui/src/views/bigscreenDesigner/designer/widget/styleWidget/widgetDecoratePieChart.vue index e25b5654..cea85ba4 100644 --- a/report-ui/src/views/bigscreenDesigner/designer/widget/decorate/widgetDecoratePieChart.vue +++ b/report-ui/src/views/bigscreenDesigner/designer/widget/styleWidget/widgetDecoratePieChart.vue @@ -1,6 +1,6 @@ diff --git a/report-ui/src/views/bigscreenDesigner/designer/widget/styleWidget/widgetDecoration.vue b/report-ui/src/views/bigscreenDesigner/designer/widget/styleWidget/widgetDecoration.vue new file mode 100644 index 00000000..680877eb --- /dev/null +++ b/report-ui/src/views/bigscreenDesigner/designer/widget/styleWidget/widgetDecoration.vue @@ -0,0 +1,47 @@ + + + diff --git a/report-ui/src/views/bigscreenDesigner/designer/widget/temp.vue b/report-ui/src/views/bigscreenDesigner/designer/widget/temp.vue index 5c2037ad..df892766 100644 --- a/report-ui/src/views/bigscreenDesigner/designer/widget/temp.vue +++ b/report-ui/src/views/bigscreenDesigner/designer/widget/temp.vue @@ -34,7 +34,7 @@ import widgetBarStackChart from "./bar/widgetBarStackChart"; import widgetLineStackChart from "./line/widgetLineStackChart"; import widgetBarCompareChart from "./bar/widgetBarCompareChart"; import widgetLineCompareChart from "./line/widgetLineCompareChart"; -import widgetDecoratePieChart from "./decorate/widgetDecoratePieChart"; +import widgetDecoratePieChart from "./styleWidget/widgetDecoratePieChart.vue"; import widgetMoreBarLineChart from "./barline/widgetMoreBarLineChart"; import widgetWordCloud from "./wordcloud/widgetWordCloud"; import widgetHeatmap from "./heatmap/widgetHeatmap"; @@ -46,12 +46,16 @@ import widgetFormTime from "./form/widgetFormTime.vue"; import widgetScaleVertical from "./scale/widgetScaleVertical.vue"; import widgetScaleHorizontal from "./scale/widgetScaleHorizontal.vue"; import widgetBarDoubleYaxisChart from "./bar/widgetBarDoubleYaxisChart.vue"; +import widgetBorder from "./styleWidget/widgetBorder.vue"; +import widgetDecoration from "./styleWidget/widgetDecoration.vue"; export default { name: "WidgetTemp", components: { widgetHref, widgetText, + widgetBorder, + widgetDecoration, WidgetMarquee, widgetTime, widgetImage, diff --git a/report-ui/src/views/bigscreenDesigner/designer/widget/texts/widgetMarquee.vue b/report-ui/src/views/bigscreenDesigner/designer/widget/texts/widgetMarquee.vue index 4c9ea4c0..89fedfdd 100644 --- a/report-ui/src/views/bigscreenDesigner/designer/widget/texts/widgetMarquee.vue +++ b/report-ui/src/views/bigscreenDesigner/designer/widget/texts/widgetMarquee.vue @@ -7,6 +7,8 @@ diff --git a/report-ui/src/views/layout/components/Sidebar/index.vue b/report-ui/src/views/layout/components/Sidebar/index.vue index f0a062c5..a36d1e40 100644 --- a/report-ui/src/views/layout/components/Sidebar/index.vue +++ b/report-ui/src/views/layout/components/Sidebar/index.vue @@ -3,7 +3,7 @@
- V1.0.0 + V1.1.0