From 32ef5377585ce325cef37914cd7f41aed785aaff Mon Sep 17 00:00:00 2001 From: RB <42044143+getrebuild@users.noreply.github.com> Date: Tue, 22 Mar 2022 14:46:24 +0800 Subject: [PATCH] Fix 2.8.1 (#444) * fix @rbv * fix #442 * fix: barcode height * enh: Excel support BARCODE * enh: Excel support detail-entity * fix: error show * fix: form layout * best local-ip * style barcode * bestipv4 --- pom.xml | 2 +- .../java/com/rebuild/core/Application.java | 4 +- .../core/metadata/easymeta/DisplayType.java | 2 +- .../core/service/dataimport/DataExporter.java | 2 +- .../datareport/EasyExcelGenerator.java | 72 ++++++++++++++----- .../core/support/general/BarCodeSupport.java | 19 ++--- .../java/com/rebuild/utils/OshiUtils.java | 17 ++++- .../admin/data/ReportTemplateController.java | 2 +- .../commons/BarCodeGeneratorController.java | 5 +- .../web/assets/js/admin/config-comps.js | 2 +- .../web/assets/js/admin/report-templates.js | 1 + .../resources/web/assets/js/print-preview.js | 29 ++++---- src/main/resources/web/assets/js/rb-forms.js | 32 +++++---- .../resources/web/general/detail-view.html | 1 + 14 files changed, 125 insertions(+), 65 deletions(-) diff --git a/pom.xml b/pom.xml index 0f67aad48..35e007ead 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.rebuild rebuild - 2.8.0 + 2.8.1 rebuild Building your business-systems freely! diff --git a/src/main/java/com/rebuild/core/Application.java b/src/main/java/com/rebuild/core/Application.java index 312108d8b..5ee9fb8e5 100644 --- a/src/main/java/com/rebuild/core/Application.java +++ b/src/main/java/com/rebuild/core/Application.java @@ -64,11 +64,11 @@ public class Application implements ApplicationListener /** * Rebuild Version */ - public static final String VER = "2.8.0"; + public static final String VER = "2.8.1"; /** * Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2} */ - public static final int BUILD = 2080003; + public static final int BUILD = 2080104; static { // Driver for DB diff --git a/src/main/java/com/rebuild/core/metadata/easymeta/DisplayType.java b/src/main/java/com/rebuild/core/metadata/easymeta/DisplayType.java index 42b348da7..25e6135d8 100644 --- a/src/main/java/com/rebuild/core/metadata/easymeta/DisplayType.java +++ b/src/main/java/com/rebuild/core/metadata/easymeta/DisplayType.java @@ -39,7 +39,7 @@ public enum DisplayType { BARCODE(EasyBarCode.class, "二维码", FieldType.STRING, 300, null, false, true), N2NREFERENCE(EasyN2NReference.class, "多引用", FieldType.REFERENCE_LIST, -1, null), LOCATION(EasyLocation.class, "位置", FieldType.STRING, 100, null), - SIGN(EasySign.class, "签名", FieldType.TEXT, 32767, null, false, false), + SIGN(EasySign.class, "签名", FieldType.TEXT, 32767, null, false, true), // 内部 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 94a862f2f..9b1188ee5 100644 --- a/src/main/java/com/rebuild/core/service/dataimport/DataExporter.java +++ b/src/main/java/com/rebuild/core/service/dataimport/DataExporter.java @@ -169,7 +169,7 @@ public class DataExporter extends SetUser { if (cellVal.toString().equals(FieldValueHelper.NO_READ_PRIVILEGES)) { cellVal = Language.L("[无权限]"); - } else if (!dt.isExportable()) { + } else if (!dt.isExportable() || (dt == DisplayType.SIGN || dt == DisplayType.BARCODE)) { cellVal = Language.L("[暂不支持]"); } else if (dt == DisplayType.DECIMAL || dt == DisplayType.NUMBER) { cellVal = cellVal.toString().replace(",", ""); // 移除千分位 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 190edbaae..a4a86cd63 100644 --- a/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator.java +++ b/src/main/java/com/rebuild/core/service/datareport/EasyExcelGenerator.java @@ -8,6 +8,7 @@ See LICENSE and COMMERCIAL in the project root for license information. package com.rebuild.core.service.datareport; import cn.devezhao.persist4j.Entity; +import cn.devezhao.persist4j.Field; import cn.devezhao.persist4j.Record; import cn.devezhao.persist4j.engine.ID; import com.alibaba.excel.EasyExcel; @@ -21,14 +22,20 @@ import com.rebuild.core.metadata.easymeta.EasyField; import com.rebuild.core.metadata.easymeta.EasyMetaFactory; import com.rebuild.core.support.RebuildConfiguration; import com.rebuild.core.support.SetUser; +import com.rebuild.core.support.general.BarCodeSupport; import com.rebuild.core.support.general.FieldValueHelper; import com.rebuild.core.support.i18n.Language; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.springframework.util.Assert; import org.springframework.util.Base64Utils; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.IOException; import java.util.*; /** @@ -115,10 +122,19 @@ public class EasyExcelGenerator extends SetUser { TemplateExtractor templateExtractor = new TemplateExtractor(this.template, true); Map varsMap = templateExtractor.transformVars(entity); + Map varsMapOfMain = new HashMap<>(); + Map varsMapOfDetail = new HashMap<>(); + List fieldsOfMain = new ArrayList<>(); List fieldsOfDetail = new ArrayList<>(); for (Map.Entry e : varsMap.entrySet()) { + if (e.getKey().startsWith(TemplateExtractor.NROW_PREFIX)) { + varsMapOfDetail.put(e.getKey(), e.getValue()); + } else { + varsMapOfMain.put(e.getKey(), e.getValue()); + } + String validField = e.getValue(); // 无效字段 if (validField == null) { @@ -138,18 +154,19 @@ public class EasyExcelGenerator extends SetUser { } final List> datas = new ArrayList<>(); - final String baseSql = "select %s from %s where %s = ?"; + final String baseSql = "select %s,%s from %s where %s = ?"; if (!fieldsOfMain.isEmpty()) { String sql = String.format(baseSql, - StringUtils.join(fieldsOfMain, ","), entity.getName(), entity.getPrimaryField().getName()); + StringUtils.join(fieldsOfMain, ","), + entity.getPrimaryField().getName(), entity.getName(), entity.getPrimaryField().getName()); + Record record = Application.createQuery(sql, this.getUser()) .setParameter(1, this.recordId) .record(); Assert.notNull(record, "No record found : " + this.recordId); - Map data = buildData(record, varsMap); - datas.add(data); + datas.add(buildData(record, varsMapOfMain)); this.hasMain = true; } @@ -158,14 +175,16 @@ public class EasyExcelGenerator extends SetUser { String sql = String.format(baseSql + " order by modifiedOn desc", StringUtils.join(fieldsOfDetail, ","), + entity.getDetailEntity().getPrimaryField().getName(), entity.getDetailEntity().getName(), MetadataHelper.getDetailToMainField(entity.getDetailEntity()).getName()); + List list = Application.createQuery(sql, this.getUser()) .setParameter(1, this.recordId) .list(); for (Record c : list) { - datas.add(buildData(c, varsMap)); + datas.add(buildData(c, varsMapOfDetail)); } return datas; } @@ -182,6 +201,7 @@ public class EasyExcelGenerator extends SetUser { final String unsupportFieldTip = Language.L("[暂不支持]"); final Map data = new HashMap<>(); + // 无效字段填充 for (Map.Entry e : varsMap.entrySet()) { if (e.getValue() == null) { @@ -193,17 +213,13 @@ public class EasyExcelGenerator extends SetUser { } } - for (Iterator iter = record.getAvailableFieldIterator(); iter.hasNext(); ) { - final String fieldName = iter.next(); + for (final String fieldName : varsMap.values()) { + if (fieldName == null) continue; + EasyField easyField = EasyMetaFactory.valueOf( Objects.requireNonNull(MetadataHelper.getLastJoinField(entity, fieldName))); DisplayType dt = easyField.getDisplayType(); - if (!dt.isExportable() && dt != DisplayType.SIGN) { - data.put(fieldName, unsupportFieldTip); - continue; - } - // 替换成变量名 String varName = fieldName; for (Map.Entry e : varsMap.entrySet()) { @@ -216,14 +232,22 @@ public class EasyExcelGenerator extends SetUser { varName = varName.substring(1); } + if (!dt.isExportable()) { + data.put(varName, unsupportFieldTip); + continue; + } + Object fieldValue = record.getObjectValue(fieldName); - if (fieldValue == null) { + + if (dt == DisplayType.BARCODE) { + data.put(varName, buildBarcodeData(easyField.getRawMeta(), record.getPrimary())); + } else if (fieldValue == null) { data.put(varName, StringUtils.EMPTY); } else { if (dt == DisplayType.SIGN) { - fieldValue = buildImgData((String) fieldValue); - } else { + fieldValue = buildSignData((String) fieldValue); + } else { fieldValue = FieldValueHelper.wrapFieldValue(fieldValue, easyField, true); if (FieldValueHelper.isUseDesensitized(easyField, this.getUser())) { @@ -236,7 +260,23 @@ public class EasyExcelGenerator extends SetUser { return data; } - private byte[] buildImgData(String base64img) { + private byte[] buildSignData(String base64img) { + // data:image/png;base64,xxx return Base64Utils.decodeFromString(base64img.split("base64,")[1]); } + + private byte[] buildBarcodeData(Field barcodeField, ID recordId) { + BufferedImage bi = BarCodeSupport.getBarCodeImage(barcodeField, recordId); + + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + ImageIO.write(bi, "png", baos); + + String base64 = Base64.encodeBase64String(baos.toByteArray()); + return buildSignData("base64," + base64); + + } catch (IOException e) { + log.error("Cannot encode image of barcode : {}", recordId, e); + } + return null; + } } diff --git a/src/main/java/com/rebuild/core/support/general/BarCodeSupport.java b/src/main/java/com/rebuild/core/support/general/BarCodeSupport.java index 665648ab5..f04e30b9c 100644 --- a/src/main/java/com/rebuild/core/support/general/BarCodeSupport.java +++ b/src/main/java/com/rebuild/core/support/general/BarCodeSupport.java @@ -63,11 +63,10 @@ public class BarCodeSupport { String barcodeType = EasyMetaFactory.valueOf(field).getExtraAttr("barcodeType"); if (TYPE_BARCODE.equalsIgnoreCase(barcodeType)) { - return createBarCode(content); - } - // 默认为二维码 - else { - return createQRCode(content); + return createBarCode(content, 0); + } else { + // 默认为二维码 + return createQRCode(content, 0); } } @@ -75,10 +74,11 @@ public class BarCodeSupport { * QR_CODE * * @param content + * @param w * @return */ - public static BufferedImage createQRCode(String content) { - BitMatrix bitMatrix = createCode(content, BarcodeFormat.QR_CODE, 320); + public static BufferedImage createQRCode(String content, int w) { + BitMatrix bitMatrix = createCode(content, BarcodeFormat.QR_CODE, w <= 0 ? 320 : w); return MatrixToImageWriter.toBufferedImage(bitMatrix); } @@ -86,10 +86,11 @@ public class BarCodeSupport { * CODE_128 * * @param content + * @param h * @return */ - public static BufferedImage createBarCode(String content) { - BitMatrix bitMatrix = createCode(content, BarcodeFormat.CODE_128, 320); + public static BufferedImage createBarCode(String content, int h) { + BitMatrix bitMatrix = createCode(content, BarcodeFormat.CODE_128, h <= 0 ? 80 : h); return MatrixToImageWriter.toBufferedImage(bitMatrix); } diff --git a/src/main/java/com/rebuild/utils/OshiUtils.java b/src/main/java/com/rebuild/utils/OshiUtils.java index 7713c32e3..f48c5db5b 100644 --- a/src/main/java/com/rebuild/utils/OshiUtils.java +++ b/src/main/java/com/rebuild/utils/OshiUtils.java @@ -9,6 +9,7 @@ package com.rebuild.utils; import cn.devezhao.commons.ObjectUtils; import cn.devezhao.commons.runtime.MemoryInformationBean; +import org.apache.commons.lang3.StringUtils; import oshi.SystemInfo; import oshi.hardware.GlobalMemory; import oshi.hardware.NetworkIF; @@ -82,10 +83,22 @@ public class OshiUtils { List nets = getSI().getHardware().getNetworkIFs(); if (nets == null || nets.isEmpty()) return "localhost"; + String bestipv4 = null; for (NetworkIF net : nets) { + for (String ip : net.getIPv4addr()) { + if (bestipv4 == null) bestipv4 = ip; + break; + } + + if (net.isKnownVmMacAddr()) continue; + String[] ipsv4 = net.getIPv4addr(); - if (ipsv4 != null && ipsv4.length > 0) return ipsv4[0]; + if (ipsv4.length > 0) { + bestipv4 = ipsv4[0]; + break; + } } - return "127.0.0.1"; + + return StringUtils.defaultString(bestipv4, "127.0.0.1"); } } 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 c6bb0b019..2344ca998 100644 --- a/src/main/java/com/rebuild/web/admin/data/ReportTemplateController.java +++ b/src/main/java/com/rebuild/web/admin/data/ReportTemplateController.java @@ -110,7 +110,7 @@ public class ReportTemplateController extends BaseController { File template = DataReportManager.instance.getTemplateFile(entity, reportId); file = new EasyExcelGenerator(template, (ID) random[0]).generate(); } catch (ConfigurationException ex) { - response.sendError(400, Language.L("未找到可供预览的记录")); + response.sendError(500, ex.getLocalizedMessage()); return; } diff --git a/src/main/java/com/rebuild/web/commons/BarCodeGeneratorController.java b/src/main/java/com/rebuild/web/commons/BarCodeGeneratorController.java index 8033dbf79..50a5752f5 100644 --- a/src/main/java/com/rebuild/web/commons/BarCodeGeneratorController.java +++ b/src/main/java/com/rebuild/web/commons/BarCodeGeneratorController.java @@ -51,14 +51,15 @@ public class BarCodeGeneratorController extends BaseController { @GetMapping({"/commons/barcode/render-qr", "/commons/barcode/render"}) public void render(HttpServletRequest request, HttpServletResponse response) throws IOException { String content = getParameterNotNull(request, "t"); + int w = getIntParameter(request, "w", 0); // 4小时缓存 ServletUtils.addCacheHead(response, 240); if (request.getRequestURI().endsWith("render-qr")) { - writeTo(BarCodeSupport.createQRCode(content), response); + writeTo(BarCodeSupport.createQRCode(content, w), response); } else { - writeTo(BarCodeSupport.createBarCode(content), response); + writeTo(BarCodeSupport.createBarCode(content, w), response); } } diff --git a/src/main/resources/web/assets/js/admin/config-comps.js b/src/main/resources/web/assets/js/admin/config-comps.js index e0000332e..1930ed84b 100644 --- a/src/main/resources/web/assets/js/admin/config-comps.js +++ b/src/main/resources/web/assets/js/admin/config-comps.js @@ -41,7 +41,7 @@ class ConfigFormDlg extends RbFormHandler { componentDidMount() { if (this._entity) { - $.get('/commons/metadata/entities', (res) => { + $.get(`/commons/metadata/entities?detail=${this.hasDetail === true}`, (res) => { this.setState({ entities: res.data }, () => { this.__select2 = $(this._entity).select2({ placeholder: $L('选择实体'), diff --git a/src/main/resources/web/assets/js/admin/report-templates.js b/src/main/resources/web/assets/js/admin/report-templates.js index 29ef5059a..2e7d089bd 100644 --- a/src/main/resources/web/assets/js/admin/report-templates.js +++ b/src/main/resources/web/assets/js/admin/report-templates.js @@ -68,6 +68,7 @@ class ReporEdit extends ConfigFormDlg { constructor(props) { super(props) this.subtitle = $L('报表模板') + this.hasDetail = true } renderFrom() { diff --git a/src/main/resources/web/assets/js/print-preview.js b/src/main/resources/web/assets/js/print-preview.js index 7e2a43a2c..8ad8f07bf 100644 --- a/src/main/resources/web/assets/js/print-preview.js +++ b/src/main/resources/web/assets/js/print-preview.js @@ -14,8 +14,8 @@ $(document).ready(() => { class PreviewTable extends React.Component { render() { const rows = [] // [[]] - let crtRow = [] - let crtSpan = 0 + let currentRow = [] + let currentSpan = 0 this.props.data.elements.forEach((c) => { let colspan = c.colspan || 2 @@ -23,22 +23,22 @@ class PreviewTable extends React.Component { // set c.colspan = colspan - if (crtSpan + colspan > 4) { - rows.push(crtRow) - crtRow = [c] - crtSpan = colspan - } else if (crtSpan + colspan === 4) { - crtRow.push(c) - rows.push(crtRow) - crtRow = [] - crtSpan = 0 + if (currentSpan + colspan > 4) { + rows.push(currentRow) + currentRow = [c] + currentSpan = colspan + } else if (currentSpan + colspan === 4) { + currentRow.push(c) + rows.push(currentRow) + currentRow = [] + currentSpan = 0 } else { - crtRow.push(c) - crtSpan += colspan + currentRow.push(c) + currentSpan += colspan } }) // last - if (crtRow.length > 0) rows.push(crtRow) + if (currentRow.length > 0) rows.push(currentRow) return ( @@ -103,6 +103,7 @@ class PreviewTable extends React.Component { cells.push({c4.label}) colSpan = 1 cells.push({this.formatValue(c4)}) + return cells } componentDidMount = () => $('.font-italic.hide').removeClass('hide') diff --git a/src/main/resources/web/assets/js/rb-forms.js b/src/main/resources/web/assets/js/rb-forms.js index 23b31cd25..6df28378c 100644 --- a/src/main/resources/web/assets/js/rb-forms.js +++ b/src/main/resources/web/assets/js/rb-forms.js @@ -1016,6 +1016,7 @@ class RbFormDateTime extends RbFormElement { class RbFormImage extends RbFormElement { constructor(props) { super(props) + this._inputid = `${props.field}-input${$random()}` if (props.value) this.state.value = [...props.value] // clone if (this.props.uploadNumber) { @@ -1052,8 +1053,8 @@ class RbFormImage extends RbFormElement { ) })} - (this._fieldValue__input = c)} type="file" className="inputfile" id={`${this.props.field}-input`} accept="image/*" /> - + (this._fieldValue__input = c)} type="file" className="inputfile" id={this._inputid} accept="image/*" /> + @@ -1162,8 +1163,8 @@ class RbFormFile extends RbFormImage { ) })} - (this._fieldValue__input = c)} id={`${this.props.field}-input`} /> - + (this._fieldValue__input = c)} id={this._inputid} /> + {$L('上传文件')} @@ -1737,22 +1738,23 @@ class RbFormBarcode extends RbFormElement { renderElement() { if (this.state.value) return this.renderViewElement() - else - return ( - - {$L('自动值')} ({this.props.barcodeType === 'QRCODE' ? $L('二维码') : $L('条形码')}) - - ) + + return ( + + {$L('自动值')} ({this.props.barcodeType === 'BARCODE' ? $L('条形码') : $L('二维码')}) + + ) } renderViewElement() { if (!this.state.value) return super.renderViewElement() - const codeUrl = `${rb.baseUrl}/commons/barcode/render${this.props.barcodeType === 'BARCODE' ? '' : '-qr'}?t=${$encode(this.state.value)}` + const isbar = this.props.barcodeType === 'BARCODE' + const codeUrl = `${rb.baseUrl}/commons/barcode/render${isbar ? '' : '-qr'}?t=${$encode(this.state.value)}` return ( - + ) @@ -1762,14 +1764,15 @@ class RbFormBarcode extends RbFormElement { class RbFormAvatar extends RbFormElement { constructor(props) { super(props) + this._inputid = `${props.field}-input${$random()}` } renderElement() { return ( - {!this.props.readonly && (this._fieldValue__input = c)} type="file" className="inputfile" id={`${this.props.field}-input`} accept="image/*" />} - + {!this.props.readonly && (this._fieldValue__input = c)} type="file" className="inputfile" id={this._inputid} accept="image/*" />} + @@ -1947,7 +1950,6 @@ class RbFormSign extends RbFormElement { { if (!this.props.readonly) { diff --git a/src/main/resources/web/general/detail-view.html b/src/main/resources/web/general/detail-view.html index 4a74cb6ac..d3a5207f2 100644 --- a/src/main/resources/web/general/detail-view.html +++ b/src/main/resources/web/general/detail-view.html @@ -42,6 +42,7 @@ [[${bundle.L('删除')}]] [[${bundle.L('打印')}]] + [[${bundle.L('报表')}]]