From e6b2ea8e2d0b4b6f8b4bbe11224fa9cfae6d6360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?REBUILD=20=E4=BC=81=E4=B8=9A=E7=AE=A1=E7=90=86=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F?= <42044143+getrebuild@users.noreply.github.com> Date: Wed, 18 Oct 2023 13:56:46 +0800 Subject: [PATCH] tmpl better (#668) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * be: isSame * socketTimeout=0 * feat: front * WordReportGenerator * style: print * be: common-save * be: 本地加载PDF * fops * inTriggerTime2 * report 100w * word tmpl * word table * style * Update @rbv * AppHome._InTab * IsNullFunction * modal onDoubleClick --- @rbv | 2 +- pom.xml | 14 +- .../core/service/dataimport/DataExporter.java | 6 +- .../service/datareport/DataReportManager.java | 59 +- .../datareport/EasyExcelGenerator.java | 35 +- .../datareport/EasyExcelGenerator33.java | 31 +- .../datareport/EasyExcelListGenerator.java | 4 +- .../service/datareport/TemplateExtractor.java | 18 +- .../datareport/TemplateExtractor33.java | 8 +- .../core/service/datareport/TemplateFile.java | 17 +- .../service/general/RecordDifference.java | 22 +- .../core/service/query/QueryFactory.java | 4 +- .../service/trigger/aviator/AviatorUtils.java | 1 + .../trigger/aviator/IsNullFunction.java | 58 + .../support/general/BatchOperatorQuery.java | 4 +- .../core/support/integration/QiniuCloud.java | 42 +- .../java/com/rebuild/utils/CommonsUtils.java | 19 + .../java/com/rebuild/utils/PdfConverter.java | 18 +- .../rebuild/web/KnownExceptionConverter.java | 6 +- .../web/admin/ConfigurationController.java | 4 +- .../admin/data/ReportTemplateController.java | 55 +- .../rebuild/web/commons/CommonPageView.java | 8 +- .../rebuild/web/commons/FileDownloader.java | 2 +- .../general/CommonOperatingController.java | 8 +- .../web/general/GeneralListController.java | 25 +- .../web/general/GeneralModelController.java | 2 +- .../web/general/ModelExtrasController.java | 4 +- .../web/general/ReportsController.java | 21 +- src/main/resources/application-bean.xml | 3 + src/main/resources/logback.xml | 7 +- src/main/resources/web/_include/header.html | 2 + .../web/admin/integration/apis-manager.html | 2 +- .../web/admin/metadata/entities.html | 2 +- src/main/resources/web/assets/css/rb-page.css | 17 +- .../resources/web/assets/css/view-page.css | 8 +- .../web/assets/js/admin/report-templates.js | 114 +- .../web/assets/js/charts/chart-design.js | 2 +- .../resources/web/assets/js/charts/charts.js | 2 +- .../resources/web/assets/js/file-preview.js | 21 +- .../resources/web/assets/js/print-preview.js | 42 +- .../web/assets/js/project/project-tasks.js | 2 +- .../resources/web/assets/js/rb-components.js | 13 +- .../web/assets/js/rb-datalist.common.js | 9 +- src/main/resources/web/assets/js/rb-forms.js | 23 +- src/main/resources/web/assets/js/rb-page.js | 20 + .../resources/web/assets/js/rb-view.append.js | 2 +- src/main/resources/web/assets/js/rb-view.js | 18 +- .../web/assets/js/trigger/trigger-design.js | 6 +- .../web/assets/lib/wangeditor/index.js | 24129 ++++++++++++++++ .../assets/lib/wangeditor/normalize.min.css | 2 + .../web/assets/lib/wangeditor/style.css | 27 + .../resources/web/general/print-preview.html | 68 +- src/test/resources/frontjs-sdk-demo.js | 13 + 53 files changed, 24798 insertions(+), 253 deletions(-) create mode 100644 src/main/java/com/rebuild/core/service/trigger/aviator/IsNullFunction.java create mode 100644 src/main/resources/web/assets/lib/wangeditor/index.js create mode 100644 src/main/resources/web/assets/lib/wangeditor/normalize.min.css create mode 100644 src/main/resources/web/assets/lib/wangeditor/style.css diff --git a/@rbv b/@rbv index 551b01618..8dbf3078a 160000 --- a/@rbv +++ b/@rbv @@ -1 +1 @@ -Subproject commit 551b01618f09293e287ef53fba4f4d6a68821eb2 +Subproject commit 8dbf3078ac9aa1a3741ba85bc071aadfcb44c67c diff --git a/pom.xml b/pom.xml index 8e91d3a5c..75cc953a7 100644 --- a/pom.xml +++ b/pom.xml @@ -320,12 +320,12 @@ com.alibaba druid - 1.2.18 + 1.2.20 com.mysql mysql-connector-j - 8.0.33 + 8.1.0 net.sf.ehcache @@ -398,15 +398,20 @@ + + com.deepoove + poi-tl + 1.12.1 + org.apache.poi poi - 4.1.2 + 5.2.4 org.apache.poi poi-ooxml - 4.1.2 + 5.2.4 org.apache.poi @@ -488,6 +493,7 @@ 2.4.0 + commons-io diff --git a/src/main/java/com/rebuild/core/service/dataimport/DataExporter.java b/src/main/java/com/rebuild/core/service/dataimport/DataExporter.java index 96f597b85..0370768e0 100644 --- a/src/main/java/com/rebuild/core/service/dataimport/DataExporter.java +++ b/src/main/java/com/rebuild/core/service/dataimport/DataExporter.java @@ -62,10 +62,10 @@ public class DataExporter extends SetUser { /** - * 最大行数 + * 最大导出行数 */ - public static final int MAX_ROWS = 65535 - 1; - + public static final int MAX_ROWS = 1000000; + final private JSONObject queryData; // 字段 private List headFields = new ArrayList<>(); diff --git a/src/main/java/com/rebuild/core/service/datareport/DataReportManager.java b/src/main/java/com/rebuild/core/service/datareport/DataReportManager.java index 7b6e12892..819f0b283 100644 --- a/src/main/java/com/rebuild/core/service/datareport/DataReportManager.java +++ b/src/main/java/com/rebuild/core/service/datareport/DataReportManager.java @@ -45,19 +45,31 @@ private DataReportManager() {} public static final int TYPE_RECORD = 1; public static final int TYPE_LIST = 2; + public static final int TYPE_HTML5 = 3; + public static final int TYPE_WORD = 4; /** - * 获取报表列表 + * 获取可用报表 * * @param entity - * @param type + * @param type 指定类型 * @param user * @return */ public JSONArray getReports(Entity entity, int type, ID user) { JSONArray alist = new JSONArray(); for (ConfigBean e : getReportsRaw(entity)) { - if (!e.getBoolean("disabled") && e.getInteger("type") == type) { + if (e.getBoolean("disabled")) continue; + + boolean can; + int aType = e.getInteger("type"); + if (type == DataReportManager.TYPE_LIST) { + can = aType == type; + } else { + can = aType == DataReportManager.TYPE_RECORD || aType == DataReportManager.TYPE_WORD; + } + + if (can) { // v3.5 String vuDef = e.getString("visibleUsers"); if (StringUtils.isNotBlank(vuDef)) { @@ -85,7 +97,7 @@ public ConfigBean[] getReportsRaw(Entity entity) { } Object[][] array = Application.createQueryNoFilter( - "select configId,name,isDisabled,templateFile,templateType,extraDefinition from DataReportConfig where belongEntity = ?") + "select configId,name,isDisabled,templateFile,templateType,extraDefinition,templateContent from DataReportConfig where belongEntity = ?") .setParameter(1, entity.getName()) .array(); @@ -104,7 +116,8 @@ public ConfigBean[] getReportsRaw(Entity entity) { .set("type", ObjectUtils.toInt(o[4], TYPE_RECORD)) .set("outputType", outputType) .set("templateVersion", templateVersion) - .set("visibleUsers", visibleUsersDef); + .set("visibleUsers", visibleUsersDef) + .set("templateContent", o[6]); alist.add(cb); } @@ -119,29 +132,36 @@ public ConfigBean[] getReportsRaw(Entity entity) { * @return */ public TemplateFile getTemplateFile(Entity entity, ID reportId) { - String template = null; - boolean isList = false; + String templateFile = null; + String templateContent = null; + int type = DataReportManager.TYPE_RECORD; boolean isV33 = false; for (ConfigBean e : getReportsRaw(entity)) { if (e.getID("id").equals(reportId)) { - template = e.getString("template"); - isList = e.getInteger("type") == TYPE_LIST; + templateFile = e.getString("template"); + templateContent = e.getString("templateContent"); + type = e.getInteger("type"); isV33 = e.getInteger("templateVersion") == 3; break; } } - if (template == null) { + // v35 HTML5 + if (templateContent != null) { + return new TemplateFile(templateContent, entity); + } + + if (templateFile == null) { throw new ConfigurationException("No template of report found : " + reportId); } - File file = RebuildConfiguration.getFileOfData(template); + File file = RebuildConfiguration.getFileOfData(templateFile); if (!file.exists()) { throw new ConfigurationException("File of template not extsts : " + file); } - return new TemplateFile(file, entity, isList, isV33); + return new TemplateFile(file, entity, type, isV33); } /** @@ -150,15 +170,12 @@ public TemplateFile getTemplateFile(Entity entity, ID reportId) { * @see #getTemplateFile(Entity, ID) 性能好 */ public TemplateFile getTemplateFile(ID reportId) { - Object[] report = Application.createQueryNoFilter( - "select belongEntity from DataReportConfig where configId = ?") - .setParameter(1, reportId) - .unique(); - if (report == null || !MetadataHelper.containsEntity((String) report[0])) { + Object[] o = Application.getQueryFactory().uniqueNoFilter(reportId, "belongEntity"); + if (o == null || !MetadataHelper.containsEntity((String) o[0])) { throw new ConfigurationException("No config of report found : " + reportId); } - return getTemplateFile(MetadataHelper.getEntity((String) report[0]), reportId); + return getTemplateFile(MetadataHelper.getEntity((String) o[0]), reportId); } @Override @@ -167,6 +184,8 @@ public void clean(Object entity) { Application.getCommonsCache().evict(cKey); } + // -- + /** * 获取报表名称 * @@ -176,7 +195,8 @@ public void clean(Object entity) { * @return */ public static String getReportName(ID reportId, Object idOrEntity, String fileName) { - Entity be = idOrEntity instanceof ID ? MetadataHelper.getEntity(((ID) idOrEntity).getEntityCode()) + final Entity be = idOrEntity instanceof ID + ? MetadataHelper.getEntity(((ID) idOrEntity).getEntityCode()) : MetadataHelper.getEntity((String) idOrEntity); String name = null; @@ -191,6 +211,7 @@ public static String getReportName(ID reportId, Object idOrEntity, String fileNa // suffix if (fileName.endsWith(".pdf")) name += ".pdf"; + else if (fileName.endsWith(".docx")) name += ".docx"; else name += fileName.endsWith(".xlsx") ? ".xlsx" : ".xls"; break; } diff --git a/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator.java b/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator.java index 818dfd3ab..5ff303e66 100644 --- a/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator.java +++ b/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator.java @@ -79,7 +79,7 @@ @Slf4j public class EasyExcelGenerator extends SetUser { - protected File template; + protected File templateFile; protected Integer writeSheetAt = null; protected ID recordId; @@ -92,7 +92,7 @@ public class EasyExcelGenerator extends SetUser { * @param recordId */ protected EasyExcelGenerator(File template, ID recordId) { - this.template = getFixTemplate(template); + this.templateFile = getFixTemplate(template); this.recordId = recordId; } @@ -116,7 +116,7 @@ public File generate() { FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); - try (ExcelWriter excelWriter = EasyExcel.write(target).withTemplate(template).build()) { + try (ExcelWriter excelWriter = EasyExcel.write(target).withTemplate(templateFile).build()) { WriteSheet writeSheet = EasyExcel.writerSheet(writeSheetAt) .registerWriteHandler(new FixsMergeStrategy()) .registerWriteHandler(new FormulaCellWriteHandler()) @@ -150,8 +150,13 @@ public File generate() { * @return */ protected File getTargetFile() { - return RebuildConfiguration.getFileOfTemp(String.format("RBREPORT-%d.%s", - System.currentTimeMillis(), template.getName().endsWith(".xlsx") ? "xlsx" : "xls")); + String suffix = "xls"; + if (templateFile.getName().endsWith(".xlsx")) suffix = "xlsx"; + if (templateFile.getName().endsWith(".html")) suffix = "html"; + if (templateFile.getName().endsWith(".docx")) suffix = "docx"; + if (templateFile.getName().endsWith(".doc")) suffix = "doc"; + + return RebuildConfiguration.getFileOfTemp(String.format("RBREPORT-%d.%s", System.currentTimeMillis(), suffix)); } /** @@ -160,9 +165,9 @@ protected File getTargetFile() { * @return 第一个为主记录(若有) */ protected List> buildData() { - Entity entity = MetadataHelper.getEntity(this.recordId.getEntityCode()); + Entity entity = MetadataHelper.getEntity(recordId.getEntityCode()); - TemplateExtractor templateExtractor = new TemplateExtractor(this.template); + TemplateExtractor templateExtractor = new TemplateExtractor(templateFile); Map varsMap = templateExtractor.transformVars(entity); Map varsMapOfMain = new HashMap<>(); @@ -193,7 +198,7 @@ protected List> buildData() { } // 无效字段 else if (validField == null) { - log.warn("Invalid field `{}` in template : {}", e.getKey(), this.template); + log.warn("Invalid field `{}` in template : {}", e.getKey(), templateFile); continue; } @@ -219,9 +224,9 @@ else if (validField == null) { entity.getPrimaryField().getName(), entity.getName(), entity.getPrimaryField().getName()); Record record = Application.createQuery(sql, this.getUser()) - .setParameter(1, this.recordId) + .setParameter(1, recordId) .record(); - Assert.notNull(record, "No record found : " + this.recordId); + Assert.notNull(record, "No record found : " + recordId); datas.add(buildData(record, varsMapOfMain)); this.hasMain = true; @@ -236,7 +241,7 @@ else if (validField == null) { MetadataHelper.getDetailToMainField(entity.getDetailEntity()).getName()); List list = Application.createQuery(sql, this.getUser()) - .setParameter(1, this.recordId) + .setParameter(1, recordId) .list(); phNumber = 1; @@ -253,7 +258,7 @@ else if (validField == null) { StringUtils.join(fieldsOfApproval, ",")); List list = Application.createQueryNoFilter(sql) - .setParameter(1, this.recordId) + .setParameter(1, recordId) .list(); phNumber = 1; @@ -519,7 +524,8 @@ public static EasyExcelGenerator create(ID reportId, List recordIds) { if (recordIds.size() == 1) { return create(reportId, recordId); } else { - TemplateFile tt = DataReportManager.instance.getTemplateFile(MetadataHelper.getEntity(recordId.getEntityCode()), reportId); + TemplateFile tt = DataReportManager.instance + .getTemplateFile(MetadataHelper.getEntity(recordId.getEntityCode()), reportId); return new EasyExcelGenerator33(tt.templateFile, recordIds); } } @@ -530,7 +536,8 @@ public static EasyExcelGenerator create(ID reportId, List recordIds) { * @return */ public static EasyExcelGenerator create(ID reportId, ID recordId) { - TemplateFile tt = DataReportManager.instance.getTemplateFile(MetadataHelper.getEntity(recordId.getEntityCode()), reportId); + TemplateFile tt = DataReportManager.instance + .getTemplateFile(MetadataHelper.getEntity(recordId.getEntityCode()), reportId); return create(tt.templateFile, recordId, tt.isV33); } diff --git a/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator33.java b/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator33.java index 3248fac4a..05ba5d794 100644 --- a/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator33.java +++ b/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator33.java @@ -45,23 +45,23 @@ @Slf4j public class EasyExcelGenerator33 extends EasyExcelGenerator { - final private List recordIds; + final private List recordIdMultiple; - protected EasyExcelGenerator33(File template, ID recordId) { - super(template, recordId); - this.recordIds = null; + protected EasyExcelGenerator33(File templateFile, ID recordId) { + super(templateFile, recordId); + this.recordIdMultiple = null; } protected EasyExcelGenerator33(File template, List recordIds) { super(template, recordIds.get(0)); - this.recordIds = recordIds; + this.recordIdMultiple = recordIds; } @Override protected List> buildData() { final Entity entity = MetadataHelper.getEntity(recordId.getEntityCode()); - final TemplateExtractor33 templateExtractor33 = new TemplateExtractor33(template); + final TemplateExtractor33 templateExtractor33 = this.buildTemplateExtractor33(); final Map varsMap = templateExtractor33.transformVars(entity); // 变量 @@ -102,7 +102,7 @@ protected List> buildData() { if (TemplateExtractor33.isPlaceholder(varName)) continue; // 无效字段 if (fieldName == null) { - log.warn("Invalid field `{}` in template : {}", e.getKey(), template); + log.warn("Invalid field `{}` in template : {}", e.getKey(), templateFile); continue; } @@ -182,21 +182,28 @@ protected List> buildData() { return datas; } - // -- V34 多个 + /** + * @return + */ + protected TemplateExtractor33 buildTemplateExtractor33() { + return new TemplateExtractor33(templateFile); + } + + // -- V34 支持多记录导出 @Override public File generate() { - if (recordIds == null) return super.generate(); + if (recordIdMultiple == null) return super.generate(); // init File targetFile = super.getTargetFile(); try { - FileUtils.copyFile(this.template, targetFile); + FileUtils.copyFile(templateFile, targetFile); } catch (IOException e) { throw new ReportsException(e); } - for (ID recordId : this.recordIds) { + for (ID recordId : recordIdMultiple) { int newSheetAt; try (Workbook wb = WorkbookFactory.create(Files.newInputStream(targetFile.toPath()))) { // 1.复制模板 @@ -220,7 +227,7 @@ public File generate() { } // 生成报表 - this.template = targetFile; + this.templateFile = targetFile; this.writeSheetAt = newSheetAt; this.recordId = recordId; this.hasMain = false; diff --git a/src/main/java/com/rebuild/core/service/datareport/EasyExcelListGenerator.java b/src/main/java/com/rebuild/core/service/datareport/EasyExcelListGenerator.java index b4252d2a1..88cc85e5a 100644 --- a/src/main/java/com/rebuild/core/service/datareport/EasyExcelListGenerator.java +++ b/src/main/java/com/rebuild/core/service/datareport/EasyExcelListGenerator.java @@ -53,7 +53,7 @@ protected EasyExcelListGenerator(File template, JSONObject queryData) { @Override protected List> buildData() { Entity entity = MetadataHelper.getEntity(queryData.getString("entity")); - TemplateExtractor varsExtractor = new TemplateExtractor(this.template, Boolean.TRUE); + TemplateExtractor varsExtractor = new TemplateExtractor(templateFile, Boolean.TRUE); Map varsMap = varsExtractor.transformVars(entity); List validFields = new ArrayList<>(); @@ -68,7 +68,7 @@ protected List> buildData() { if (validField != null && e.getKey().startsWith(NROW_PREFIX)) { validFields.add(validField); } else { - log.warn("Invalid field `{}` in template : {}", e.getKey(), this.template); + log.warn("Invalid field `{}` in template : {}", e.getKey(), templateFile); } } diff --git a/src/main/java/com/rebuild/core/service/datareport/TemplateExtractor.java b/src/main/java/com/rebuild/core/service/datareport/TemplateExtractor.java index 83b65bb6a..6ceb7db02 100644 --- a/src/main/java/com/rebuild/core/service/datareport/TemplateExtractor.java +++ b/src/main/java/com/rebuild/core/service/datareport/TemplateExtractor.java @@ -55,11 +55,11 @@ public class TemplateExtractor { // 当前日期时间 protected static final String PH__CURRENTDATETIME = PLACEHOLDER + "CURRENTDATETIME"; - // v2:{xxx} v1:${xxx} + // 变量匹配 v2:{xxx} v1:${xxx} protected static final Pattern PATT_V2 = Pattern.compile("\\{(.*?)}"); - final protected File template; - final private boolean isList; + final protected File templateFile; + final private boolean isListType; /** * @param template @@ -69,12 +69,12 @@ public TemplateExtractor(File template) { } /** - * @param template + * @param templateFile * @param isList 列表模板 */ - public TemplateExtractor(File template, boolean isList) { - this.template = template; - this.isList = isList; + public TemplateExtractor(File templateFile, boolean isList) { + this.templateFile = templateFile; + this.isListType = isList; } /** @@ -86,7 +86,7 @@ public TemplateExtractor(File template, boolean isList) { public Map transformVars(Entity entity) { final Set vars = extractVars(); - Entity detailEntity = this.isList ? null : entity.getDetailEntity(); + Entity detailEntity = this.isListType ? null : entity.getDetailEntity(); Entity approvalEntity = MetadataHelper.hasApprovalField(entity) ? MetadataHelper.getEntity(EntityHelper.RobotApprovalStep) : null; @@ -135,7 +135,7 @@ else if (MetadataHelper.getLastJoinField(entity, listField) != null) { * @return */ protected Set extractVars() { - List rows = ExcelUtils.readExcel(this.template); + List rows = ExcelUtils.readExcel(templateFile); Set vars = new HashSet<>(); for (Cell[] row : rows) { diff --git a/src/main/java/com/rebuild/core/service/datareport/TemplateExtractor33.java b/src/main/java/com/rebuild/core/service/datareport/TemplateExtractor33.java index 60977223a..359bbb674 100644 --- a/src/main/java/com/rebuild/core/service/datareport/TemplateExtractor33.java +++ b/src/main/java/com/rebuild/core/service/datareport/TemplateExtractor33.java @@ -34,10 +34,10 @@ public class TemplateExtractor33 extends TemplateExtractor { private Map sortFields = new HashMap<>(); /** - * @param template + * @param templateFile */ - public TemplateExtractor33(File template) { - super(template, Boolean.FALSE); + public TemplateExtractor33(File templateFile) { + super(templateFile, Boolean.FALSE); } /** @@ -57,7 +57,7 @@ public Map transformVars(Entity entity) { for (final String varName : vars) { // 列表型字段 if (varName.startsWith(NROW_PREFIX)) { - final String listField = varName.substring(1); + final String listField = varName.substring(1).replace("$", "."); if (isPlaceholder(listField)) { map.put(varName, null); diff --git a/src/main/java/com/rebuild/core/service/datareport/TemplateFile.java b/src/main/java/com/rebuild/core/service/datareport/TemplateFile.java index 8a832d1a2..7d2a3cab6 100644 --- a/src/main/java/com/rebuild/core/service/datareport/TemplateFile.java +++ b/src/main/java/com/rebuild/core/service/datareport/TemplateFile.java @@ -18,14 +18,25 @@ public class TemplateFile { final public File templateFile; + final public String templateContent; final public Entity entity; - final public boolean isList; + final public int type; final public boolean isV33; - public TemplateFile(File templateFile, Entity entity, boolean isList, boolean isV33) { + public TemplateFile(File templateFile, Entity entity, int type, boolean isV33) { this.templateFile = templateFile; this.entity = entity; - this.isList = isList; + this.type = type; this.isV33 = isV33; + this.templateContent = null; + } + + // HTML5 + public TemplateFile(String templateContent, Entity entity) { + this.templateContent = templateContent; + this.entity = entity; + this.type = DataReportManager.TYPE_HTML5; + this.isV33 = true; + this.templateFile = null; } } diff --git a/src/main/java/com/rebuild/core/service/general/RecordDifference.java b/src/main/java/com/rebuild/core/service/general/RecordDifference.java index 33ef6af99..dece820f3 100644 --- a/src/main/java/com/rebuild/core/service/general/RecordDifference.java +++ b/src/main/java/com/rebuild/core/service/general/RecordDifference.java @@ -7,7 +7,6 @@ package com.rebuild.core.service.general; -import cn.devezhao.commons.ObjectUtils; import cn.devezhao.persist4j.Entity; import cn.devezhao.persist4j.Field; import cn.devezhao.persist4j.Record; @@ -19,11 +18,11 @@ import com.rebuild.core.RebuildException; import com.rebuild.core.metadata.EntityHelper; import com.rebuild.core.metadata.MetadataHelper; +import com.rebuild.utils.CommonsUtils; import com.rebuild.utils.JSONUtils; import org.apache.commons.collections4.map.CaseInsensitiveMap; import java.util.Map; -import java.util.Objects; /** * 两个 Record 的不同 @@ -103,7 +102,7 @@ protected JSON diffMerge(Record after, boolean diffCommons) { for (Map.Entry e : merged.entrySet()) { Object[] vals = e.getValue(); if (vals[0] == null && vals[1] == null) continue; - if (isEquals(vals[0], vals[1])) continue; + if (CommonsUtils.isSame(vals[0], vals[1])) continue; JSON item = JSONUtils.toJSONObject( new String[]{"field", "before", "after"}, @@ -142,21 +141,4 @@ private boolean isIgnoreField(Field field) { || field.getType() == FieldType.PRIMARY || MetadataHelper.isApprovalField(fieldName); } - - /** - * 相等 - * - * @param v1 - * @param v2 - * @return - */ - private boolean isEquals(Object v1, Object v2) { - boolean e = Objects.equals(v1, v2); - if (!e) { - if (v1 instanceof Number && v2 instanceof Number) { - e = ObjectUtils.toDouble(v1) == ObjectUtils.toDouble(v2); - } - } - return e; - } } diff --git a/src/main/java/com/rebuild/core/service/query/QueryFactory.java b/src/main/java/com/rebuild/core/service/query/QueryFactory.java index 9ebd7a9ea..02cf3653e 100644 --- a/src/main/java/com/rebuild/core/service/query/QueryFactory.java +++ b/src/main/java/com/rebuild/core/service/query/QueryFactory.java @@ -37,8 +37,8 @@ @Service public class QueryFactory { - private static final int QUERY_TIMEOUT = 15 * 1000; - private static final int SLOW_LOGGER_TIME = 3 * 1000; + private static final int QUERY_TIMEOUT = 15; // s + private static final int SLOW_LOGGER_TIME = 3 * 1000; // ms private final PersistManagerFactory aPMFactory; diff --git a/src/main/java/com/rebuild/core/service/trigger/aviator/AviatorUtils.java b/src/main/java/com/rebuild/core/service/trigger/aviator/AviatorUtils.java index 028472d7a..43e8d4a9a 100644 --- a/src/main/java/com/rebuild/core/service/trigger/aviator/AviatorUtils.java +++ b/src/main/java/com/rebuild/core/service/trigger/aviator/AviatorUtils.java @@ -51,6 +51,7 @@ public class AviatorUtils { addCustomFunction(new CurrentDateFunction()); addCustomFunction(new ChineseYuanFunction()); addCustomFunction(new TextFunction()); + addCustomFunction(new IsNullFunction()); } /** diff --git a/src/main/java/com/rebuild/core/service/trigger/aviator/IsNullFunction.java b/src/main/java/com/rebuild/core/service/trigger/aviator/IsNullFunction.java new file mode 100644 index 000000000..2a81accf5 --- /dev/null +++ b/src/main/java/com/rebuild/core/service/trigger/aviator/IsNullFunction.java @@ -0,0 +1,58 @@ +/*! +Copyright (c) REBUILD and/or its owners. All rights reserved. + +rebuild is dual-licensed under commercial and open source licenses (GPLv3). +See LICENSE and COMMERCIAL in the project root for license information. +*/ + +package com.rebuild.core.service.trigger.aviator; + +import cn.devezhao.commons.ObjectUtils; +import cn.devezhao.persist4j.engine.NullValue; +import com.googlecode.aviator.runtime.function.AbstractFunction; +import com.googlecode.aviator.runtime.type.AviatorBoolean; +import com.googlecode.aviator.runtime.type.AviatorObject; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collection; +import java.util.Map; + +/** + * Usage: ISNULL($any) + * Return: Boolean + * + * @author RB + * @since 2023/10/18 + */ +@Slf4j +public class IsNullFunction extends AbstractFunction { + private static final long serialVersionUID = -7849948179882904490L; + + @Override + public AviatorObject call(Map env, AviatorObject arg1) { + final Object $any = arg1.getValue(env); + + if (NullValue.isNull($any)) return AviatorBoolean.TRUE; + + if ($any instanceof Number) { + if (ObjectUtils.toDouble($any) == 0d) return AviatorBoolean.TRUE; + if (ObjectUtils.toLong($any) == 0L) return AviatorBoolean.TRUE; + } + + if ($any instanceof Object[]) { + return ((Object[]) $any).length == 0 ? AviatorBoolean.TRUE : AviatorBoolean.FALSE; + } + + if ($any instanceof Collection) { + return ((Collection) $any).isEmpty() ? AviatorBoolean.TRUE : AviatorBoolean.FALSE; + } + + return StringUtils.isEmpty($any.toString()) ? AviatorBoolean.TRUE : AviatorBoolean.FALSE; + } + + @Override + public String getName() { + return "ISNULL"; + } +} diff --git a/src/main/java/com/rebuild/core/support/general/BatchOperatorQuery.java b/src/main/java/com/rebuild/core/support/general/BatchOperatorQuery.java index f2e8d3bf5..5da358dae 100644 --- a/src/main/java/com/rebuild/core/support/general/BatchOperatorQuery.java +++ b/src/main/java/com/rebuild/core/support/general/BatchOperatorQuery.java @@ -69,7 +69,7 @@ public BatchOperatorQuery(int dataRange, JSONObject queryData) { public JSONObject wrapQueryData(int maxRows, boolean clearFields) { if (this.dataRange != DR_PAGED) { queryData.put("pageNo", 1); - queryData.put("pageSize", maxRows); // Max + queryData.put("pageSize", maxRows); } if (this.dataRange == DR_SELECTED || this.dataRange == DR_ALL) { @@ -134,7 +134,7 @@ public ID[] getQueryedRecordIds() { Object[][] array = Application.createQuery(sql, getUser()) .setLimit(pageSize, pageNo * pageSize - pageSize) - .setTimeout(60) + .setTimeout(180) .array(); Set ids = new HashSet<>(); diff --git a/src/main/java/com/rebuild/core/support/integration/QiniuCloud.java b/src/main/java/com/rebuild/core/support/integration/QiniuCloud.java index e1a580f07..a453885cb 100644 --- a/src/main/java/com/rebuild/core/support/integration/QiniuCloud.java +++ b/src/main/java/com/rebuild/core/support/integration/QiniuCloud.java @@ -103,20 +103,32 @@ public Auth getAuth() { * 文件上传 * * @param file + * @param fops * @return * @throws IOException */ - public String upload(File file) throws IOException { - String key = formatFileKey(file.getName()); - Response resp = UPLOAD_MANAGER.put(file, key, getAuth().uploadToken(bucketName)); + public String upload(File file, String fops) throws IOException { + String fileKey = formatFileKey(file.getName()); + Response resp = UPLOAD_MANAGER.put(file, fileKey, getUploadToken(fileKey, fops)); if (resp.isOK()) { - return key; + return fileKey; } else { log.error("Cannot upload file : {}. Resp: {}", file.getName(), resp); return null; } } + /** + * 文件上传 + * + * @param file + * @return + * @throws IOException + */ + public String upload(File file) throws IOException { + return upload(file, null); + } + /** * 从 URL 上传 * @@ -218,7 +230,8 @@ public boolean delete(String key) { @SuppressWarnings("deprecation") public long stats() { String time = CalendarUtils.getPlainDateFormat().format(CalendarUtils.now()); - String url = String.format("%s/v6/space?bucket=%s&begin=%s000000&end=%s235959&g=day", + String url = String.format( + "%s/v6/space?bucket=%s&begin=%s000000&end=%s235959&g=day", CONFIGURATION.apiHost(), bucketName, time, time); StringMap headers = getAuth().authorization(url); @@ -237,15 +250,30 @@ public long stats() { } /** + * 获取上传 Token + * * @param fileKey + * @param fops 异步预处理 * @return * @see #formatFileKey(String) */ - public String getUploadToken(String fileKey) { + public String getUploadToken(String fileKey, String fops) { // 上传策略参见 https://developer.qiniu.com/kodo/manual/1206/put-policy int maxSize = RebuildConfiguration.getInt(ConfigurationItem.PortalUploadMaxSize); StringMap policy = new StringMap().put("fsizeLimit", FileUtils.ONE_MB * maxSize); - return getAuth().uploadToken(bucketName, fileKey, 60 * 10, policy); + if (fops != null) policy.put("persistentOps", fops).put("persistentNotifyUrl", "https://webhook.site/e2784dd3-cf2c-49ce-8d53-05666e7f5bd0"); + + return getAuth().uploadToken(bucketName, fileKey, 3600L, policy, true); + } + + /** + * 获取上传 Token + * + * @param fileKey + * @return + */ + public String getUploadToken(String fileKey) { + return getUploadToken(fileKey, null); } /** diff --git a/src/main/java/com/rebuild/utils/CommonsUtils.java b/src/main/java/com/rebuild/utils/CommonsUtils.java index fa75d8220..796ee8822 100644 --- a/src/main/java/com/rebuild/utils/CommonsUtils.java +++ b/src/main/java/com/rebuild/utils/CommonsUtils.java @@ -26,6 +26,7 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.Collection; +import java.util.Objects; import java.util.UUID; import java.util.regex.Pattern; @@ -248,4 +249,22 @@ public static boolean hasLength(Object any) { if (NullValue.is(any)) return false; return !any.toString().isEmpty(); } + + /** + * 值相等 + * + * @param a + * @param b + * @return + */ + public static boolean isSame(Object a, Object b) { + boolean e = Objects.equals(a, b); + if (!e) { + if (a instanceof Number && b instanceof Number) { + // FIXME 有精度问题 + e = ObjectUtils.toDouble(a) == ObjectUtils.toDouble(b); + } + } + return e; + } } diff --git a/src/main/java/com/rebuild/utils/PdfConverter.java b/src/main/java/com/rebuild/utils/PdfConverter.java index b19933b51..1188dc669 100644 --- a/src/main/java/com/rebuild/utils/PdfConverter.java +++ b/src/main/java/com/rebuild/utils/PdfConverter.java @@ -85,15 +85,17 @@ protected static Path convert(Path path, String type, boolean forceRegen) throws type = StringUtils.defaultIfBlank(type, TYPE_PDF); // 打开并保存以便公式生效 - try (Workbook wb = WorkbookFactory.create(Files.newInputStream(path))) { - wb.setForceFormulaRecalculation(true); - wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); - - try (FileOutputStream fos = new FileOutputStream(path.toFile())) { - wb.write(fos); + if (path.toString().endsWith(".xls") || path.toString().endsWith(".xlsx")) { + try (Workbook wb = WorkbookFactory.create(Files.newInputStream(path))) { + wb.setForceFormulaRecalculation(true); + wb.getCreationHelper().createFormulaEvaluator().evaluateAll(); + + try (FileOutputStream fos = new FileOutputStream(path.toFile())) { + wb.write(fos); + } + } catch (IOException e) { + throw new PdfConverterException(e); } - } catch (IOException e) { - throw new PdfConverterException(e); } final File outdir = RebuildConfiguration.getFileOfTemp(null); diff --git a/src/main/java/com/rebuild/web/KnownExceptionConverter.java b/src/main/java/com/rebuild/web/KnownExceptionConverter.java index 0b336d1c1..827954406 100644 --- a/src/main/java/com/rebuild/web/KnownExceptionConverter.java +++ b/src/main/java/com/rebuild/web/KnownExceptionConverter.java @@ -15,6 +15,7 @@ import java.sql.DataTruncation; import java.sql.SQLException; +import java.sql.SQLTimeoutException; /** * @author devezhao @@ -47,11 +48,14 @@ public static String convert2ErrorMsg(Throwable ex) { } else if (cause instanceof SQLException && StringUtils.countMatches(exMsg, "\\x") >= 4) { // mb4 log.error("DBERR: {}", exMsg); return Language.L("数据库编码不支持 4 字节编码"); + } else if (cause instanceof SQLTimeoutException) { + log.error("DBERR: {}", exMsg); + return Language.L("数据库语句执行超时"); } else if (ex instanceof ConstraintViolationException) { log.error("DBERR: {}", exMsg); return Language.L("数据库字段违反唯一性约束"); } - + return null; } } diff --git a/src/main/java/com/rebuild/web/admin/ConfigurationController.java b/src/main/java/com/rebuild/web/admin/ConfigurationController.java index cf80f3ada..c9301cc3b 100644 --- a/src/main/java/com/rebuild/web/admin/ConfigurationController.java +++ b/src/main/java/com/rebuild/web/admin/ConfigurationController.java @@ -45,6 +45,8 @@ import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.Arrays; import java.util.Comparator; import java.util.Date; @@ -60,7 +62,7 @@ */ @Slf4j @RestController -@RequestMapping("/admin/") +@RequestMapping("/admin") public class ConfigurationController extends BaseController { public static final String ETAG_DIMGLOGOTIME = "dimgLogoTime"; diff --git a/src/main/java/com/rebuild/web/admin/data/ReportTemplateController.java b/src/main/java/com/rebuild/web/admin/data/ReportTemplateController.java index 7ee31f3fb..ffcef55f3 100644 --- a/src/main/java/com/rebuild/web/admin/data/ReportTemplateController.java +++ b/src/main/java/com/rebuild/web/admin/data/ReportTemplateController.java @@ -12,6 +12,7 @@ import cn.hutool.core.io.file.FileNameUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import com.esotericsoftware.minlog.Log; import com.rebuild.api.RespBody; import com.rebuild.core.Application; import com.rebuild.core.configuration.ConfigurationException; @@ -19,6 +20,7 @@ import com.rebuild.core.privileges.UserHelper; import com.rebuild.core.service.datareport.DataReportManager; import com.rebuild.core.service.datareport.EasyExcelGenerator; +import com.rebuild.core.service.datareport.EasyExcelGenerator33; import com.rebuild.core.service.datareport.EasyExcelListGenerator; import com.rebuild.core.service.datareport.TemplateExtractor; import com.rebuild.core.service.datareport.TemplateExtractor33; @@ -26,6 +28,7 @@ import com.rebuild.core.support.RebuildConfiguration; import com.rebuild.core.support.i18n.Language; import com.rebuild.core.support.integration.QiniuCloud; +import com.rebuild.utils.CommonsUtils; import com.rebuild.utils.JSONUtils; import com.rebuild.utils.PdfConverter; import com.rebuild.utils.RbAssert; @@ -57,12 +60,13 @@ * * @author devezhao * @since 2019/8/13 + * @see com.rebuild.web.general.ReportsController */ @RestController @RequestMapping("/admin/data/") public class ReportTemplateController extends BaseController { - @RequestMapping("/report-templates") + @GetMapping("/report-templates") public ModelAndView page() { return createModelAndView("/admin/data/report-templates"); } @@ -99,19 +103,33 @@ public RespBody reportList(HttpServletRequest request) { @RequestMapping("/report-templates/check-template") public RespBody checkTemplate(@EntityParam Entity entity, HttpServletRequest request) { - String file = getParameterNotNull(request, "file"); - boolean isList = getBoolParameter(request, "list"); // 列表模板 + final String file = getParameterNotNull(request, "file"); + final int type = getIntParameter(request, "type", DataReportManager.TYPE_RECORD); File template = RebuildConfiguration.getFileOfData(file); - Map vars = isList - ? new TemplateExtractor(template, Boolean.TRUE).transformVars(entity) - : new TemplateExtractor33(template).transformVars(entity); - if (vars.isEmpty()) { + Map vars = null; + try { + if (type == DataReportManager.TYPE_RECORD) { + vars = new TemplateExtractor33(template).transformVars(entity); + } else if (type == DataReportManager.TYPE_LIST) { + vars = new TemplateExtractor(template, Boolean.TRUE).transformVars(entity); + } else if (type == DataReportManager.TYPE_WORD) { + //noinspection unchecked + vars = (Map) CommonsUtils.invokeMethod( + "com.rebuild.rbv.data.WordTemplateExtractor#transformVars", template, entity.getName()); + } + + } catch (Exception ex) { + Log.error(null, ex); + return RespBody.error(Language.L("无效模板文件 (无法读取模板文件)")); + } + + if (vars == null || vars.isEmpty()) { return RespBody.error(Language.L("无效模板文件 (未找到有效字段)")); } String invalidMsg = null; - if (isList) { + if (type == DataReportManager.TYPE_LIST) { invalidMsg = Language.L("这可能不是一个有效的列表模板"); for (String varName : vars.keySet()) { if (varName.startsWith(NROW_PREFIX)) { @@ -146,8 +164,8 @@ public void preview(@IdParam(required = false) ID reportId, if (reportId == null) { String entity = getParameter(request, "entity"); String template = getParameter(request, "file"); - boolean isList = getBoolParameter(request, "list"); - tt = new TemplateFile(RebuildConfiguration.getFileOfData(template), MetadataHelper.getEntity(entity), isList, true); + int type = getIntParameter(request, "type", DataReportManager.TYPE_RECORD); + tt = new TemplateFile(RebuildConfiguration.getFileOfData(template), MetadataHelper.getEntity(entity), type, true); } else { // 使用配置 tt = DataReportManager.instance.getTemplateFile(reportId); @@ -163,13 +181,21 @@ public void preview(@IdParam(required = false) ID reportId, File output; try { - // 列表报表 - if (tt.isList) { + // EXCEL 列表 + if (tt.type == DataReportManager.TYPE_LIST) { JSONObject queryData = JSONUtils.toJSONObject( new String[] { "pageSize", "entity" }, new Object[] { 2, tt.entity.getName() }); output = EasyExcelListGenerator.create(tt.templateFile, queryData).generate(); - } else { + } + // WORD + else if (tt.type == DataReportManager.TYPE_WORD) { + EasyExcelGenerator33 word = (EasyExcelGenerator33) CommonsUtils.invokeMethod( + "com.rebuild.rbv.data.WordReportGenerator#create", tt.templateFile, random[0]); + output = word.generate(); + } + // EXCEL + else { output = EasyExcelGenerator.create(tt.templateFile, (ID) random[0], tt.isV33).generate(); } @@ -180,7 +206,8 @@ public void preview(@IdParam(required = false) ID reportId, RbAssert.is(output != null, Language.L("无法输出报表,请检查报表模板是否有误")); - String attname = "RBREPORT-PREVIEW." + FileNameUtil.getSuffix(output);; + String attname = "RBREPORT-PREVIEW." + FileNameUtil.getSuffix(output); + String typeOutput = getParameter(request, "output"); if (PdfConverter.TYPE_PDF.equalsIgnoreCase(typeOutput) || PdfConverter.TYPE_HTML.equalsIgnoreCase(typeOutput)) { output = PdfConverter.convert(output.toPath(), typeOutput).toFile(); diff --git a/src/main/java/com/rebuild/web/commons/CommonPageView.java b/src/main/java/com/rebuild/web/commons/CommonPageView.java index d2fbe549d..7cc88d9c5 100644 --- a/src/main/java/com/rebuild/web/commons/CommonPageView.java +++ b/src/main/java/com/rebuild/web/commons/CommonPageView.java @@ -21,7 +21,6 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.Cookie; @@ -38,7 +37,7 @@ @Controller public class CommonPageView extends BaseController { - @RequestMapping("/") + @GetMapping("/") public void index(HttpServletRequest request, HttpServletResponse response) throws IOException { if (AppUtils.isMobile(request) && License.isRbvAttached()) { response.sendRedirect(RebuildConfiguration.getMobileUrl("/")); @@ -88,8 +87,9 @@ public ModelAndView page(HttpServletRequest request) { } @GetMapping("/app/home") - public void home(@IdParam(name = "n", required = false) ID useNav, @IdParam(name = "d", required = false) ID useDash, - HttpServletResponse response) throws IOException { + public void appHome(@IdParam(name = "n", required = false) ID useNav, + @IdParam(name = "d", required = false) ID useDash, + HttpServletResponse response) throws IOException { addCookie("AppHome.Nav", useNav, response); addCookie("AppHome.Dash", useDash, response); response.sendRedirect("../dashboard/home"); diff --git a/src/main/java/com/rebuild/web/commons/FileDownloader.java b/src/main/java/com/rebuild/web/commons/FileDownloader.java index 09861a684..6b4c6f2e2 100644 --- a/src/main/java/com/rebuild/web/commons/FileDownloader.java +++ b/src/main/java/com/rebuild/web/commons/FileDownloader.java @@ -160,7 +160,7 @@ public void download(HttpServletRequest request, HttpServletResponse response) t if (QiniuCloud.instance().available() && !temp) { String privateUrl = QiniuCloud.instance().makeUrl(filePath); - privateUrl += "&attname=" + CodecUtils.urlEncode(attname); + if (!INLINE_FORCE.equals(attname)) privateUrl += "&attname=" + CodecUtils.urlEncode(attname); response.sendRedirect(privateUrl); } else { diff --git a/src/main/java/com/rebuild/web/general/CommonOperatingController.java b/src/main/java/com/rebuild/web/general/CommonOperatingController.java index 0af39a4d8..8c8a7ced0 100644 --- a/src/main/java/com/rebuild/web/general/CommonOperatingController.java +++ b/src/main/java/com/rebuild/web/general/CommonOperatingController.java @@ -22,6 +22,7 @@ import com.rebuild.web.BaseController; import com.rebuild.web.IdParam; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -63,10 +64,9 @@ public JSON delete(@IdParam ID recordId) { @RequestMapping("common-get") public RespBody get(@IdParam ID recordId, HttpServletRequest request) { - // 为空则返回全部 - String fields = getParameter(request, "fields", ""); - - Record record = Application.getQueryFactory().recordNoFilter(recordId, fields.split(",")); + final String fields = getParameter(request, "fields"); + Record record = Application.getQueryFactory() + .record(recordId, StringUtils.isBlank(fields) ? new String[0] : fields.split(",")); return RespBody.ok(record); } diff --git a/src/main/java/com/rebuild/web/general/GeneralListController.java b/src/main/java/com/rebuild/web/general/GeneralListController.java index 4e234928b..dab5b3392 100644 --- a/src/main/java/com/rebuild/web/general/GeneralListController.java +++ b/src/main/java/com/rebuild/web/general/GeneralListController.java @@ -14,6 +14,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.rebuild.api.RespBody; import com.rebuild.core.Application; import com.rebuild.core.configuration.general.DataListManager; import com.rebuild.core.metadata.EntityHelper; @@ -29,6 +30,8 @@ import com.rebuild.core.support.general.DataListBuilderImpl; import com.rebuild.core.support.i18n.Language; import com.rebuild.web.EntityController; +import com.rebuild.web.KnownExceptionConverter; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.GetMapping; @@ -51,6 +54,7 @@ * @author Zixin (RB) * @since 08/22/2018 */ +@Slf4j @RestController @RequestMapping("/app/{entity}/") public class GeneralListController extends EntityController { @@ -150,13 +154,28 @@ public ModelAndView pageList(@PathVariable String entity, HttpServletRequest req } @PostMapping("data-list") - public JSON dataList(@PathVariable String entity, HttpServletRequest request) { + public RespBody dataList(@PathVariable String entity, HttpServletRequest request) { JSONObject query = (JSONObject) ServletUtils.getRequestJson(request); DataListBuilder builder = new DataListBuilderImpl(query, getRequestUser(request)); - return builder.getJSONResult(); + + try { + return RespBody.ok(builder.getJSONResult()); + + } catch (Exception ex) { + String known = KnownExceptionConverter.convert2ErrorMsg(ex); + if (known != null) return RespBody.error(known); + + log.error(null, ex); + return RespBody.error(ex.getLocalizedMessage()); + } } - // 快速查询 + /** + * 快速查询字段 + * + * @param entity + * @return + */ static String getQuickFieldsLabel(Entity entity) { Set quickFields = ParseHelper.buildQuickFields(entity, null); diff --git a/src/main/java/com/rebuild/web/general/GeneralModelController.java b/src/main/java/com/rebuild/web/general/GeneralModelController.java index 33b49f6ba..6840fa7b7 100644 --- a/src/main/java/com/rebuild/web/general/GeneralModelController.java +++ b/src/main/java/com/rebuild/web/general/GeneralModelController.java @@ -156,7 +156,7 @@ else if (FormsBuilder.DV_MAINID.equals(mainid)) { for (ConfigBean cb : imports) { JSONObject trans = (JSONObject) EasyMetaFactory.valueOf(cb.getString("source")).toJSON(); trans.put("transid", cb.getID("id")); -// trans.put("transName", cb.getID("name")); + trans.put("transName", cb.getID("name")); detailImports.add(trans); } diff --git a/src/main/java/com/rebuild/web/general/ModelExtrasController.java b/src/main/java/com/rebuild/web/general/ModelExtrasController.java index 0fe4ac157..6b893fa2f 100644 --- a/src/main/java/com/rebuild/web/general/ModelExtrasController.java +++ b/src/main/java/com/rebuild/web/general/ModelExtrasController.java @@ -31,7 +31,6 @@ import com.rebuild.web.EntityParam; import com.rebuild.web.IdParam; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -40,6 +39,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Objects; /** * 表单/视图 功能扩展 @@ -86,7 +86,7 @@ public RespBody transform(HttpServletRequest request) { } return RespBody.errorl("记录转换失败 (%s)", - StringUtils.defaultString(error, ex.getClass().getSimpleName())); + Objects.toString(error, ex.getClass().getSimpleName())); } } diff --git a/src/main/java/com/rebuild/web/general/ReportsController.java b/src/main/java/com/rebuild/web/general/ReportsController.java index 3408ff2e7..7fb0162a9 100644 --- a/src/main/java/com/rebuild/web/general/ReportsController.java +++ b/src/main/java/com/rebuild/web/general/ReportsController.java @@ -26,11 +26,14 @@ import com.rebuild.core.service.dataimport.DataExporter; import com.rebuild.core.service.datareport.DataReportManager; import com.rebuild.core.service.datareport.EasyExcelGenerator; +import com.rebuild.core.service.datareport.EasyExcelGenerator33; +import com.rebuild.core.service.datareport.TemplateFile; import com.rebuild.core.support.CommonsLog; import com.rebuild.core.support.ConfigurationItem; import com.rebuild.core.support.RebuildConfiguration; import com.rebuild.core.support.general.BatchOperatorQuery; import com.rebuild.core.support.i18n.Language; +import com.rebuild.utils.CommonsUtils; import com.rebuild.utils.JSONUtils; import com.rebuild.utils.PdfConverter; import com.rebuild.utils.RbAssert; @@ -88,15 +91,21 @@ public void reportGenerate(@PathVariable String entity, for (String id : record.split(",")) { if (ID.isId(id)) recordIds.add(ID.valueOf(id)); } + final ID recordId = recordIds.get(0); + final TemplateFile tt = DataReportManager.instance.getTemplateFile(reportId); File output = null; try { - if (recordIds.size() > 1) { - output = EasyExcelGenerator.create(reportId, recordIds).generate(); + if (tt.type == DataReportManager.TYPE_WORD) { + EasyExcelGenerator33 word = (EasyExcelGenerator33) CommonsUtils.invokeMethod( + "com.rebuild.rbv.data.WordReportGenerator#create", reportId, recordId); + output = word.generate(); } else { - output = EasyExcelGenerator.create(reportId, recordId).generate(); + // 支持多个 + output = EasyExcelGenerator.create(reportId, recordIds).generate(); } + } catch (ExcelRuntimeException ex) { log.error(null, ex); } @@ -105,8 +114,8 @@ public void reportGenerate(@PathVariable String entity, final String typeOutput = getParameter(request, "output"); final boolean isHtml = "HTML".equalsIgnoreCase(typeOutput); - // PDF - if ("PDF".equalsIgnoreCase(typeOutput) || isOnlyPdf(entity, reportId)) { + final boolean isPdf = "PDF".equalsIgnoreCase(typeOutput); + if (isPdf || isOnlyPdf(entity, reportId)) { output = PdfConverter.convertPdf(output.toPath()).toFile(); } else if (isHtml) { output = PdfConverter.convertHtml(output.toPath()).toFile(); @@ -134,7 +143,7 @@ public void reportGenerate(@PathVariable String entity, } else { // 直接预览 - boolean forcePreview = isHtml || getBoolParameter(request, "preview"); + boolean forcePreview = isHtml || isPdf || getBoolParameter(request, "preview"); FileDownloader.downloadTempFile(response, output, forcePreview ? FileDownloader.INLINE_FORCE : fileName); } } diff --git a/src/main/resources/application-bean.xml b/src/main/resources/application-bean.xml index c80e45e2e..c71b27893 100644 --- a/src/main/resources/application-bean.xml +++ b/src/main/resources/application-bean.xml @@ -29,6 +29,9 @@ + + + diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index c2e7e96e1..def9dfeed 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -30,8 +30,9 @@ - - - + + + + diff --git a/src/main/resources/web/_include/header.html b/src/main/resources/web/_include/header.html index 47d847dee..d602e873f 100644 --- a/src/main/resources/web/_include/header.html +++ b/src/main/resources/web/_include/header.html @@ -6,6 +6,7 @@ + @@ -18,6 +19,7 @@ + diff --git a/src/main/resources/web/admin/integration/apis-manager.html b/src/main/resources/web/admin/integration/apis-manager.html index cc6fef9da..7b1606ef5 100644 --- a/src/main/resources/web/admin/integration/apis-manager.html +++ b/src/main/resources/web/admin/integration/apis-manager.html @@ -43,7 +43,7 @@ display: block; } .search-logs > input:focus { - background-color: #ccc; + background-color: #ddd; } .search-logs::after { font-family: 'Material Design Icons', serif; diff --git a/src/main/resources/web/admin/metadata/entities.html b/src/main/resources/web/admin/metadata/entities.html index f9fb25716..a123792d6 100644 --- a/src/main/resources/web/admin/metadata/entities.html +++ b/src/main/resources/web/admin/metadata/entities.html @@ -96,7 +96,7 @@ -