From 37cd2652462c25cd06ee7c5bcad031503b3abc94 Mon Sep 17 00:00:00 2001 From: RB <42044143+getrebuild@users.noreply.github.com> Date: Sun, 20 Nov 2022 22:16:19 +0800 Subject: [PATCH 1/3] Fix 3.1.2 (#546) * nav better * fix: _toggleImage * 3.1.2 * better L * FormElement * better RebuildWebInterceptor * better ChartIndex * fix: show entity * mask SN --- @rbv | 2 +- pom.xml | 2 +- .../java/com/rebuild/core/Application.java | 4 +- .../rebuild/web/RebuildWebInterceptor.java | 81 +++++++++---------- .../web/admin/ConfigurationController.java | 1 + .../web/assets/js/admin/data-imports.js | 6 +- .../web/assets/js/admin/recycle-bin.js | 8 +- .../web/assets/js/admin/revision-history.js | 5 +- .../resources/web/assets/js/admin/syscfg-g.js | 8 +- .../resources/web/assets/js/charts/charts.js | 2 +- src/main/resources/web/assets/js/rb-forms.js | 14 ++-- src/main/resources/web/assets/js/rb-page.js | 5 +- src/main/resources/web/assets/js/rb-view.js | 7 +- .../resources/web/error/server-status.html | 6 +- 14 files changed, 77 insertions(+), 74 deletions(-) diff --git a/@rbv b/@rbv index f256231e8..bd85df492 160000 --- a/@rbv +++ b/@rbv @@ -1 +1 @@ -Subproject commit f256231e8f0d67ee326d47b65ed9408a0ce9320f +Subproject commit bd85df4926ea0f249117ad90f7a0cee621834ce4 diff --git a/pom.xml b/pom.xml index a1c70df9a..b1f0697b6 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.rebuild rebuild - 3.1.1 + 3.1.2 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 ef1a7c97d..98c4c6a68 100644 --- a/src/main/java/com/rebuild/core/Application.java +++ b/src/main/java/com/rebuild/core/Application.java @@ -67,11 +67,11 @@ public class Application implements ApplicationListener /** * Rebuild Version */ - public static final String VER = "3.1.1"; + public static final String VER = "3.1.2"; /** * Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2} */ - public static final int BUILD = 3010109; + public static final int BUILD = 3010209; static { // Driver for DB diff --git a/src/main/java/com/rebuild/web/RebuildWebInterceptor.java b/src/main/java/com/rebuild/web/RebuildWebInterceptor.java index 27f55d6bd..ab3a48311 100644 --- a/src/main/java/com/rebuild/web/RebuildWebInterceptor.java +++ b/src/main/java/com/rebuild/web/RebuildWebInterceptor.java @@ -57,6 +57,7 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt private static final int CODE_STARTING = 600; private static final int CODE_DENIEDMSG = 601; + @SuppressWarnings("unused") private static final int CODE_MAINTAIN = 602; private static final int CODE_UNSAFE_USE = 603; @@ -86,11 +87,11 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt request.setAttribute(WebConstants.LOCALE, requestEntry.getLocale()); request.setAttribute(WebConstants.$BUNDLE, Application.getLanguage().getBundle(requestEntry.getLocale())); - final String requestUrl = requestEntry.getRequestUrl(); + final String requestUri = requestEntry.getRequestUri(); // 服务暂不可用 if (!Application.isReady()) { - final boolean isError = requestUrl.endsWith("/error") || requestUrl.contains("/error/"); + final boolean isError = requestUri.endsWith("/error") || requestUri.contains("/error/"); // 已安装 if (checkInstalled()) { @@ -104,7 +105,7 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt } } // 未安装 - else if (!(requestUrl.contains("/setup/") || requestUrl.contains("/commons/theme/") || isError)) { + else if (!(requestUri.contains("/setup/") || requestUri.contains("/commons/theme/") || isError)) { sendRedirect(response, "/setup/install", null); return false; } else { @@ -120,9 +121,9 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt if (requestUser != null) { // 管理中心二次验证 - if (requestUrl.contains("/admin/") && !AppUtils.isAdminVerified(request)) { - if (isHtmlRequest(request)) { - sendRedirect(response, "/user/admin-verify", requestEntry.getRequestUri()); + if (requestUri.contains("/admin/") && !AppUtils.isAdminVerified(request)) { + if (isHtmlRequest(requestUri, request)) { + sendRedirect(response, "/user/admin-verify", requestEntry.getRequestUriWithQuery()); } else { response.sendError(HttpStatus.FORBIDDEN.value()); } @@ -134,7 +135,7 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt // User request.setAttribute(WebConstants.$USER, Application.getUserStore().getUser(requestUser)); - if (isHtmlRequest(request)) { + if (isHtmlRequest(requestUri, request)) { // Last active Application.getSessionStore().storeLastActive(request); @@ -142,7 +143,7 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt String sidebarCollapsed = ServletUtils.readCookie(request, "rb.sidebarCollapsed"); String sideCollapsedClazz = BooleanUtils.toBoolean(sidebarCollapsed) ? "rb-collapsible-sidebar-collapsed" : ""; // Aside collapsed - if (!(requestUrl.contains("/admin/") || requestUrl.contains("/setup/"))) { + if (!(requestUri.contains("/admin/") || requestUri.contains("/setup/"))) { String asideCollapsed = ServletUtils.readCookie(request, "rb.asideCollapsed"); if (BooleanUtils.toBoolean(asideCollapsed)) sideCollapsedClazz += " rb-aside-collapsed"; } @@ -156,14 +157,14 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt if (RebuildConfiguration.getBool(ConfigurationItem.SecurityEnhanced)) skipCheckSafeUse = false; else skipCheckSafeUse = UserHelper.isSuperAdmin(requestUser); - } else if (!isIgnoreAuth(requestUrl)) { + } else if (!isIgnoreAuth(requestUri)) { // 独立验证逻辑 - if (requestUrl.contains("/filex/")) return true; + if (requestUri.contains("/filex/")) return true; log.warn("Unauthorized access {}", RebuildWebConfigurer.getRequestUrls(request)); - if (isHtmlRequest(request)) { - sendRedirect(response, "/user/login", requestEntry.getRequestUri()); + if (isHtmlRequest(requestUri, request)) { + sendRedirect(response, "/user/login", requestEntry.getRequestUriWithQuery()); } else { response.sendError(HttpStatus.UNAUTHORIZED.value()); } @@ -190,7 +191,7 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt // 打印处理时间 long time = requestEntry == null ? 0 : (System.currentTimeMillis() - requestEntry.getRequestTime()); - if (time > 1000) { + if (time > 1500) { log.warn("Method handle time {} ms. Request URL(s) {}", time, RebuildWebConfigurer.getRequestUrls(request)); } @@ -203,38 +204,38 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt if (rbmobLocale != null) return rbmobLocale; // 0. Session - String havingLocale = (String) ServletUtils.getSessionAttribute(request, AppUtils.SK_LOCALE); + String useLocale = (String) ServletUtils.getSessionAttribute(request, AppUtils.SK_LOCALE); String urlLocale = request.getParameter("locale"); - if (StringUtils.isNotBlank(urlLocale) && !urlLocale.equals(havingLocale)) { + if (StringUtils.isNotBlank(urlLocale) && !urlLocale.equals(useLocale)) { urlLocale = Application.getLanguage().available(urlLocale); if (urlLocale != null) { - havingLocale = urlLocale; + useLocale = urlLocale; - ServletUtils.setSessionAttribute(request, AppUtils.SK_LOCALE, havingLocale); - ServletUtils.addCookie(response, AppUtils.CK_LOCALE, havingLocale, + ServletUtils.setSessionAttribute(request, AppUtils.SK_LOCALE, useLocale); + ServletUtils.addCookie(response, AppUtils.CK_LOCALE, useLocale, CommonsCache.TS_DAY * 90, null, StringUtils.defaultIfBlank(AppUtils.getContextPath(), "/")); if (Application.devMode()) Application.getLanguage().refresh(); } } - if (havingLocale != null) return havingLocale; + if (useLocale != null) return useLocale; // 1. Cookie - havingLocale = ServletUtils.readCookie(request, AppUtils.CK_LOCALE); - if (havingLocale == null) { + useLocale = ServletUtils.readCookie(request, AppUtils.CK_LOCALE); + if (useLocale == null) { // 2. User-Local - havingLocale = request.getLocale().toString(); + useLocale = request.getLocale().toString(); } // 3. Default - if ((havingLocale = Application.getLanguage().available(havingLocale)) == null) { - havingLocale = RebuildConfiguration.get(ConfigurationItem.DefaultLanguage); + if ((useLocale = Application.getLanguage().available(useLocale)) == null) { + useLocale = RebuildConfiguration.get(ConfigurationItem.DefaultLanguage); } - ServletUtils.setSessionAttribute(request, AppUtils.SK_LOCALE, havingLocale); - return havingLocale; + ServletUtils.setSessionAttribute(request, AppUtils.SK_LOCALE, useLocale); + return useLocale; } private boolean isIgnoreAuth(String requestUri) { @@ -242,14 +243,15 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt return true; } - requestUri = requestUri.split("\\?")[0]; requestUri = requestUri.replaceFirst(AppUtils.getContextPath(), ""); return requestUri.length() < 3 || requestUri.endsWith("/error") || requestUri.contains("/error/") - || requestUri.startsWith("/f/") || requestUri.startsWith("/s/") - || requestUri.startsWith("/setup/") + || requestUri.endsWith("/logout") + || requestUri.startsWith("/f/") + || requestUri.startsWith("/s/") || requestUri.startsWith("/gw/") + || requestUri.startsWith("/setup/") || requestUri.startsWith("/language/") || requestUri.startsWith("/filex/access/") || requestUri.startsWith("/filex/download/") @@ -259,12 +261,10 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt || requestUri.startsWith("/commons/barcode/render") || requestUri.startsWith("/commons/theme/") || requestUri.startsWith("/account/user-avatar/") - || requestUri.startsWith("/rbmob/env") - || requestUri.endsWith("/logout"); + || requestUri.startsWith("/rbmob/env"); } - private boolean isHtmlRequest(HttpServletRequest request) { - String requestUri = request.getRequestURI(); + private boolean isHtmlRequest(String requestUri, HttpServletRequest request) { if (ServletUtils.isAjaxRequest(request) || requestUri.contains("/assets/") || requestUri.contains("/commons/frontjs/") @@ -285,9 +285,9 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt } private void sendRedirect(HttpServletResponse response, String url, String nexturl) throws IOException { - String fullUrl = AppUtils.getContextPath(url); - if (nexturl != null) fullUrl += "?nexturl=" + CodecUtils.urlEncode(nexturl); - response.sendRedirect(fullUrl); + String redirectUrl = AppUtils.getContextPath(url); + if (nexturl != null) redirectUrl += "?nexturl=" + CodecUtils.urlEncode(nexturl); + response.sendRedirect(redirectUrl); } private void checkSafeUse(String ipAddr, String requestUri) throws DefinedException { @@ -315,22 +315,21 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt private static class RequestEntry { final long requestTime; final String requestUri; - final String requestUrl; + final String requestUriWithQuery; final ID requestUser; final String locale; RequestEntry(HttpServletRequest request, String locale) { this.requestTime = System.currentTimeMillis(); - this.requestUri = request.getRequestURI() - + (request.getQueryString() != null ? ("?" + request.getQueryString()) : ""); - this.requestUrl = request.getRequestURI(); + this.requestUri = request.getRequestURI(); + this.requestUriWithQuery = this.requestUri + (request.getQueryString() == null ? "" : "?" + request.getQueryString()); this.requestUser = AppUtils.getRequestUser(request, true); this.locale = locale; } @Override public String toString() { - return requestUri; + return requestUriWithQuery; } } } diff --git a/src/main/java/com/rebuild/web/admin/ConfigurationController.java b/src/main/java/com/rebuild/web/admin/ConfigurationController.java index 1663dd64e..93d88ebef 100644 --- a/src/main/java/com/rebuild/web/admin/ConfigurationController.java +++ b/src/main/java/com/rebuild/web/admin/ConfigurationController.java @@ -73,6 +73,7 @@ public class ConfigurationController extends BaseController { mv.getModel().put("LicenseType", auth.getString("authType") + " (" + auth.getString("authObject") + ")"); mv.getModel().put("Version", Application.VER); + mv.getModel().put("SN", "***" + License.SN().substring(12)); return mv; } diff --git a/src/main/resources/web/assets/js/admin/data-imports.js b/src/main/resources/web/assets/js/admin/data-imports.js index 7b7d1ad64..a91f459c1 100644 --- a/src/main/resources/web/assets/js/admin/data-imports.js +++ b/src/main/resources/web/assets/js/admin/data-imports.js @@ -247,8 +247,12 @@ const _fieldsMapping = (columns, fields) => { const $tbody = $('#fieldsMapping tbody').empty() $(columns).each(function (idx, item) { + let L = _LETTERS[idx] + if (idx > 25) L = `A${_LETTERS[idx - 26] || 'X'}` // AA + if (idx > 51) L = `B${_LETTERS[idx - 52] || 'X'}` // BA + const $tr = $(``).appendTo($tbody) - $(`${_LETTERS[idx] || _LETTERS[idx - 26]}1 ${item || $L('空')}`).appendTo($tr) + $(`${L} ${item || $L('空')}`).appendTo($tr) const $td = $('').appendTo($tr) const $clone = $fieldSelect.clone().appendTo($td) $('').appendTo($tr) diff --git a/src/main/resources/web/assets/js/admin/recycle-bin.js b/src/main/resources/web/assets/js/admin/recycle-bin.js index ef58a7215..e040241aa 100644 --- a/src/main/resources/web/assets/js/admin/recycle-bin.js +++ b/src/main/resources/web/assets/js/admin/recycle-bin.js @@ -12,10 +12,10 @@ const _ENTITIES = { $(document).ready(() => { $.get('/commons/metadata/entities?detail=true', (res) => { - $(res.data).each(function () { - $(``).appendTo('#belongEntity') - _ENTITIES[this.name] = this.label - }) + res.data && res.data.forEach((item) => (_ENTITIES[item.name] = item.label)) + for (let name in _ENTITIES) { + $(``).appendTo('#belongEntity') + } renderRbcomp(, 'react-list', function () { RbListPage._RbList = this._List diff --git a/src/main/resources/web/assets/js/admin/revision-history.js b/src/main/resources/web/assets/js/admin/revision-history.js index 83141e8ba..df25b2f93 100644 --- a/src/main/resources/web/assets/js/admin/revision-history.js +++ b/src/main/resources/web/assets/js/admin/revision-history.js @@ -12,10 +12,7 @@ const _ENTITIES = { $(document).ready(() => { $.get('/commons/metadata/entities?detail=true', (res) => { - $(res.data).each(function () { - _ENTITIES[this.name] = this.label - }) - + res.data && res.data.forEach((item) => (_ENTITIES[item.name] = item.label)) for (let name in _ENTITIES) { $(``).appendTo('#belongEntity') } diff --git a/src/main/resources/web/assets/js/admin/syscfg-g.js b/src/main/resources/web/assets/js/admin/syscfg-g.js index 1657f1ddb..943e98ab9 100644 --- a/src/main/resources/web/assets/js/admin/syscfg-g.js +++ b/src/main/resources/web/assets/js/admin/syscfg-g.js @@ -44,6 +44,10 @@ useEditComp = function (name) { ) } else if ('PasswordPolicy' === name) { + // 借用贵宝地 + _toggleImage('.applogo') + _toggleImage('.bgimg') + return ( ) } else if ('DefaultLanguage' === name) { - // 借用贵宝地 - _toggleImage('.applogo') - _toggleImage('.bgimg') - const options = [] for (let k in wpc._LANGS) { options.push( diff --git a/src/main/resources/web/assets/js/charts/charts.js b/src/main/resources/web/assets/js/charts/charts.js index 15d2ae036..8f82d040d 100644 --- a/src/main/resources/web/assets/js/charts/charts.js +++ b/src/main/resources/web/assets/js/charts/charts.js @@ -162,7 +162,7 @@ class ChartIndex extends BaseChart { _resize() { const ch = $(this._$chart).height() - const zoom = ch > 100 ? (ch > 330 ? 2.831 : 1.3) : 1 + const zoom = ch > 100 ? (ch > 330 ? 2 : 1.3) : 1 $(this._$chart).find('strong').css('zoom', zoom) // const $text = $(this._$chart).find('strong') diff --git a/src/main/resources/web/assets/js/rb-forms.js b/src/main/resources/web/assets/js/rb-forms.js index 3a502006d..38f5716b2 100644 --- a/src/main/resources/web/assets/js/rb-forms.js +++ b/src/main/resources/web/assets/js/rb-forms.js @@ -112,7 +112,7 @@ class RbFormModal extends React.Component { const FORM = ( {formModel.elements.map((item) => { - return detectElement(item) + return detectElement(item, entity) })} ) @@ -265,8 +265,7 @@ class RbForm extends React.Component { let _ProTable if (window._CustomizedForms) { _ProTable = window._CustomizedForms.useProTable(this.props.entity, this) - // 不显示 - if (_ProTable === false) return null + if (_ProTable === false) return null // 不显示 } const that = this @@ -2402,8 +2401,13 @@ class RbFormDivider extends React.Component { } // 确定元素类型 -var detectElement = function (item) { - if (!item.key) item.key = 'field-' + (item.field === TYPE_DIVIDER ? $random() : item.field) +var detectElement = function (item, entity) { + if (!item.key) item.key = `field-${item.field === TYPE_DIVIDER ? $random() : item.field}` + + if (entity && window._CustomizedForms) { + const c = window._CustomizedForms.useFormElement(entity, item) + if (c) return c + } if (item.type === 'TEXT' || item.type === 'SERIES') { return diff --git a/src/main/resources/web/assets/js/rb-page.js b/src/main/resources/web/assets/js/rb-page.js index 6f66a876f..e80313202 100644 --- a/src/main/resources/web/assets/js/rb-page.js +++ b/src/main/resources/web/assets/js/rb-page.js @@ -278,14 +278,17 @@ var _initNav = function () { $sub.toggleClass('visible') $currsntSubnav = $this $this.find('a').eq(0).tooltip('hide') - $('.left-sidebar-scroll').perfectScrollbar('update') if ($sub.hasClass('visible')) $this.addClass('open') else $this.removeClass('open') + + $('.left-sidebar-scroll').perfectScrollbar('update') }) + $('.sidebar-elements li.parent .sub-menu').on('click', function (e) { e.stopPropagation() }) + $(document.body).on('click', function () { closeSubnav() if (isOffcanvas) { diff --git a/src/main/resources/web/assets/js/rb-view.js b/src/main/resources/web/assets/js/rb-view.js index 37c193d4d..a70cfce38 100644 --- a/src/main/resources/web/assets/js/rb-view.js +++ b/src/main/resources/web/assets/js/rb-view.js @@ -58,7 +58,7 @@ class RbViewForm extends React.Component { {res.data.elements.map((item) => { if (item.field !== TYPE_DIVIDER) viewData[item.field] = item.value item.$$$parent = this - return detectViewElement(item) + return detectViewElement(item, this.props.entity) })} @@ -163,12 +163,11 @@ class RbViewForm extends React.Component { } } -const detectViewElement = function (item) { +const detectViewElement = function (item, entity) { if (!window.detectElement) throw 'detectElement undef' item.onView = true item.editMode = false - // item.key = `col-${item.field === TYPE_DIVIDER ? $random() : item.field}` - return window.detectElement(item) + return window.detectElement(item, entity) } const _renderError = (message) => { diff --git a/src/main/resources/web/error/server-status.html b/src/main/resources/web/error/server-status.html index 211bccba4..1010d744e 100644 --- a/src/main/resources/web/error/server-status.html +++ b/src/main/resources/web/error/server-status.html @@ -71,11 +71,7 @@ - - - - - + From 2c3e47258ec1c5b17771f528ba6596e3b4233526 Mon Sep 17 00:00:00 2001 From: RB Date: Mon, 21 Nov 2022 23:11:27 +0800 Subject: [PATCH 2/3] enh: Grouping/Category --- @rbv | 2 +- .../general/DataListCategory.java | 74 ++++++++--- .../support/general/ProtocolFilterParser.java | 14 +- .../web/configuration/WidgetController.java | 2 +- src/main/resources/i18n/lang.zh_CN.json | 9 +- .../web/admin/metadata/entity-advanced.html | 6 + .../web/assets/js/metadata/entity-advanced.js | 125 ++++++++++++++---- .../resources/web/general/detail-list.html | 2 +- .../resources/web/general/record-list.html | 2 +- 9 files changed, 170 insertions(+), 66 deletions(-) diff --git a/@rbv b/@rbv index bd85df492..c3184f819 160000 --- a/@rbv +++ b/@rbv @@ -1 +1 @@ -Subproject commit bd85df4926ea0f249117ad90f7a0cee621834ce4 +Subproject commit c3184f8196c0835c70942a2b9723838eebb2ebb6 diff --git a/src/main/java/com/rebuild/core/configuration/general/DataListCategory.java b/src/main/java/com/rebuild/core/configuration/general/DataListCategory.java index 5ca0f2c8e..f91959d01 100644 --- a/src/main/java/com/rebuild/core/configuration/general/DataListCategory.java +++ b/src/main/java/com/rebuild/core/configuration/general/DataListCategory.java @@ -7,6 +7,7 @@ See LICENSE and COMMERCIAL in the project root for license information. package com.rebuild.core.configuration.general; +import cn.devezhao.commons.CalendarUtils; import cn.devezhao.persist4j.Entity; import cn.devezhao.persist4j.Field; import cn.devezhao.persist4j.Query; @@ -16,59 +17,67 @@ import com.alibaba.fastjson.JSONArray; import com.rebuild.core.Application; import com.rebuild.core.configuration.ConfigBean; import com.rebuild.core.metadata.easymeta.DisplayType; +import com.rebuild.core.metadata.easymeta.EasyField; import com.rebuild.core.metadata.easymeta.EasyMetaFactory; import com.rebuild.core.metadata.impl.EasyEntityConfigProps; import com.rebuild.core.support.general.FieldValueHelper; import com.rebuild.utils.JSONUtils; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang.StringUtils; import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; +import java.util.*; /** - * 列表字段分类数据 + * 列表字段分类(分组)数据 * * @author ZHAO * @since 07/23/2022 */ public class DataListCategory { + public static final DataListCategory instance = new DataListCategory(); + + private DataListCategory() { + } + /** * @param entity * @param user * @return */ - public static JSON datas(Entity entity, ID user) { + public JSON datas(Entity entity, ID user) { final Field categoryField = getFieldOfCategory(entity); if (categoryField == null) return null; - DisplayType dt = EasyMetaFactory.getDisplayType(categoryField); + EasyField easyField = EasyMetaFactory.valueOf(categoryField); + DisplayType dt = easyField.getDisplayType(); - List clist = new ArrayList<>(); + List dataList = new ArrayList<>(); if (dt == DisplayType.MULTISELECT || dt == DisplayType.PICKLIST) { ConfigBean[] entries = MultiSelectManager.instance.getPickListRaw(categoryField, true); for (ConfigBean e : entries) { Object id = e.getID("id"); if (dt == DisplayType.MULTISELECT) id = e.getLong("mask"); - - clist.add(new Object[] { e.getString("text"), id }); + dataList.add(new Object[] { e.getString("text"), id }); } } else { - // TODO 考虑支持更多分组字段类型,例如日期(但要考虑日期格式) - String sql; if (dt == DisplayType.N2NREFERENCE) { sql = MessageFormat.format( "select distinct referenceId from NreferenceItem where belongEntity = ''{0}'' and belongField = ''{1}''", entity.getName(), categoryField.getName()); } else { + String wrapField = categoryField.getName(); + if (dt == DisplayType.DATETIME) { + wrapField = String.format("DATE_FORMAT(%s, '%%Y-%%m-%%d')", wrapField); + } + sql = MessageFormat.format( - "select distinct {0} from {1} where {0} is not null", categoryField.getName(), entity.getName()); + "select {0} from {1} where {2} is not null group by {0}", + wrapField, entity.getName(), categoryField.getName()); } Query query = user == null @@ -76,18 +85,38 @@ public class DataListCategory { : Application.getQueryFactory().createQuery(sql, user); Object[][] array = query.array(); + String cf = EasyMetaFactory.valueOf(entity).getExtraAttr(EasyEntityConfigProps.ADV_LIST_SHOWCATEGORY); + String[] ff = cf.split(":"); + String format = ff.length > 1 ? ff[1] : null; + + Set unique = new HashSet<>(); + for (Object[] o : array) { Object id = o[0]; - Object label = FieldValueHelper.getLabelNotry((ID) id); - clist.add(new Object[] { label, id }); - } + Object label; - // TODO 分类数据 code 排序 - clist.sort(Comparator.comparing(o -> o[0].toString())); + if (dt == DisplayType.DATE || dt == DisplayType.DATETIME) { + format = StringUtils.defaultIfBlank(format, CalendarUtils.UTC_DATE_FORMAT); + if (id instanceof Date) { + label = CalendarUtils.format(format, (Date) id); + } else { + label = id.toString().substring(0, format.length()); + } + id = label; + + } else { + label = FieldValueHelper.getLabelNotry((ID) id); + } + + if (unique.contains(id)) continue; + unique.add(id); + + dataList.add(new Object[] { label, id }); + } } JSONArray res = new JSONArray(); - for (Object[] o : clist) { + for (Object[] o : dataList) { res.add(JSONUtils.toJSONObject( new String[] { "label", "id", "count" }, new Object[] { o[0], o[1], 0 } )); @@ -102,9 +131,10 @@ public class DataListCategory { * @param entity * @return */ - public static Field getFieldOfCategory(Entity entity) { + public Field getFieldOfCategory(Entity entity) { String categoryField = EasyMetaFactory.valueOf(entity).getExtraAttr(EasyEntityConfigProps.ADV_LIST_SHOWCATEGORY); - if (StringUtils.isBlank(categoryField) || !entity.containsField(categoryField)) return null; - return entity.getField(categoryField); + if (categoryField != null) categoryField = categoryField.split(":")[0]; + if (categoryField != null && entity.containsField(categoryField)) return entity.getField(categoryField); + return null; } } diff --git a/src/main/java/com/rebuild/core/support/general/ProtocolFilterParser.java b/src/main/java/com/rebuild/core/support/general/ProtocolFilterParser.java index 8f6d553b3..0301ac1f1 100644 --- a/src/main/java/com/rebuild/core/support/general/ProtocolFilterParser.java +++ b/src/main/java/com/rebuild/core/support/general/ProtocolFilterParser.java @@ -189,22 +189,22 @@ public class ProtocolFilterParser { */ protected String parseCategory(String entity, String value) { Entity rootEntity = MetadataHelper.getEntity(entity); - Field classField = DataListCategory.getFieldOfCategory(rootEntity); - if (classField == null) return "(9=9)"; + Field categoryField = DataListCategory.instance.getFieldOfCategory(rootEntity); + if (categoryField == null) return "(9=9)"; - DisplayType dt = EasyMetaFactory.getDisplayType(classField); + DisplayType dt = EasyMetaFactory.getDisplayType(categoryField); if (dt == DisplayType.MULTISELECT) { - return String.format("%s && %d", classField.getName(), ObjectUtils.toInt(value)); + return String.format("%s && %d", categoryField.getName(), ObjectUtils.toInt(value)); } else if (dt == DisplayType.N2NREFERENCE) { return String.format( "exists (select recordId from NreferenceItem where ^%s = recordId and belongField = '%s' and referenceId = '%s')", - rootEntity.getPrimaryField().getName(), classField.getName(), StringEscapeUtils.escapeSql(value)); + rootEntity.getPrimaryField().getName(), categoryField.getName(), StringEscapeUtils.escapeSql(value)); } else { - return String.format("%s = '%s'", classField.getName(), StringEscapeUtils.escapeSql(value)); + return String.format("%s = '%s'", categoryField.getName(), StringEscapeUtils.escapeSql(value)); } } - + /** * @param relatedExpr * @param mainid diff --git a/src/main/java/com/rebuild/web/configuration/WidgetController.java b/src/main/java/com/rebuild/web/configuration/WidgetController.java index 69e87d983..468b5b5a9 100644 --- a/src/main/java/com/rebuild/web/configuration/WidgetController.java +++ b/src/main/java/com/rebuild/web/configuration/WidgetController.java @@ -69,7 +69,7 @@ public class WidgetController extends BaseController implements ShareTo { @GetMapping("widget-category-data") public RespBody getCategoryData(@PathVariable String entity, HttpServletRequest request) { - JSON data = DataListCategory.datas( + JSON data = DataListCategory.instance.datas( MetadataHelper.getEntity(entity), getRequestUser(request)); return RespBody.ok(data); } diff --git a/src/main/resources/i18n/lang.zh_CN.json b/src/main/resources/i18n/lang.zh_CN.json index 821c3438d..26382010d 100644 --- a/src/main/resources/i18n/lang.zh_CN.json +++ b/src/main/resources/i18n/lang.zh_CN.json @@ -2216,7 +2216,6 @@ "请至少添加 1 个查询字段":"请至少添加 1 个查询字段", "请填写固定值":"请填写固定值", "@%s 退回了你的 %s 审批,请重新审核":"@%s 退回了你的 %s 审批,请重新审核", - "显示侧栏分类":"显示侧栏分类", "转换明细记录需选择主记录":"转换明细记录需选择主记录", "@%s 驳回了你的 %s 审批,请重新提交":"@%s 驳回了你的 %s 审批,请重新提交", "如有多个类型请使用逗号或空格分开":"如有多个类型请使用逗号或空格分开", @@ -2265,7 +2264,7 @@ "退回至":"退回至", "提交模式":"提交模式", "启用提交模式必须选择审批流程":"启用提交模式必须选择审批流程", - "显示侧栏“分类”":"显示侧栏“分类”", + "显示侧栏“分组”":"显示侧栏“分组”", "显示侧栏“常用查询”":"显示侧栏“常用查询”", "仅提交不审批。选择的审批流程至少配置一个审批人,否则会提交失败":"仅提交不审批。选择的审批流程至少配置一个审批人,否则会提交失败", "需要先添加 [记录转换](../transforms) 才能在此处选择":"需要先添加 [记录转换](../transforms) 才能在此处选择", @@ -2273,7 +2272,6 @@ "显示侧栏“图表”":"显示侧栏“图表”", "选择的审批流程至少配置一个审批人":"选择的审批流程至少配置一个审批人", "需要先添加 [审批流程](../approvals) 才能在此处选择":"需要先添加 [审批流程](../approvals) 才能在此处选择", - "Category":"分类", "管理员撤销":"管理员撤销", "部分功能可能需要商业版才能正常运行":"部分功能可能需要商业版才能正常运行", "默认大小":"默认大小", @@ -2379,5 +2377,8 @@ "APP SECRET 已重置":"APP SECRET 已重置", "修改 API 秘钥":"修改 API 秘钥", "自动合并单元格":"自动合并单元格", - "重置后第三方应用需更换新的 APP SECRET 使用":"重置后第三方应用需更换新的 APP SECRET 使用" + "重置后第三方应用需更换新的 APP SECRET 使用":"重置后第三方应用需更换新的 APP SECRET 使用", + "分组":"分组", + "字段格式":"字段格式", + "分组字段":"分组字段" } diff --git a/src/main/resources/web/admin/metadata/entity-advanced.html b/src/main/resources/web/admin/metadata/entity-advanced.html index b3a86d563..4b4a2b4f9 100644 --- a/src/main/resources/web/admin/metadata/entity-advanced.html +++ b/src/main/resources/web/admin/metadata/entity-advanced.html @@ -44,6 +44,12 @@ .form-group .switch-button-xs { margin-top: 7px; } + .advListShowCategory-set { + border-radius: 2px; + border: 1px solid #eee; + padding: 15px; + margin-top: 10px; + } diff --git a/src/main/resources/web/assets/js/metadata/entity-advanced.js b/src/main/resources/web/assets/js/metadata/entity-advanced.js index 2d091da5e..1b5cd32a1 100644 --- a/src/main/resources/web/assets/js/metadata/entity-advanced.js +++ b/src/main/resources/web/assets/js/metadata/entity-advanced.js @@ -99,7 +99,8 @@ function modeSave(newOption, next) { }) } -const CLASS_TYPES = ['PICKLIST', 'MULTISELECT', 'CLASSIFICATION', 'REFERENCE', 'N2NREFERENCE'] +// const CATE_TYPES = ['PICKLIST', 'MULTISELECT', 'CLASSIFICATION', 'DATE', 'DATETIME', 'REFERENCE', 'N2NREFERENCE'] +const CATE_TYPES = ['PICKLIST', 'MULTISELECT', 'CLASSIFICATION', 'REFERENCE', 'N2NREFERENCE'] // 模式选项 class DlgMode1Option extends RbFormHandler { @@ -109,7 +110,7 @@ class DlgMode1Option extends RbFormHandler {
-
+
@@ -119,8 +120,8 @@ class DlgMode1Option extends RbFormHandler {
- -
+ +
@@ -128,23 +129,41 @@ class DlgMode1Option extends RbFormHandler {
-
- +
+
+
+ + +
+
+ + +
+
-
+
@@ -155,7 +174,7 @@ class DlgMode1Option extends RbFormHandler {
-
+
@@ -165,7 +184,7 @@ class DlgMode1Option extends RbFormHandler {
-
(this._btns = c)}> +
(this._btns = c)}> @@ -180,8 +199,9 @@ class DlgMode1Option extends RbFormHandler { } componentDidMount() { + let $catFields, $catFormats + const that = this - let $class2 $('#advListShowCategory').on('change', function () { if ($val(this)) { that.setState({ advListShowCategory: true }) @@ -189,19 +209,63 @@ class DlgMode1Option extends RbFormHandler { that.setState({ advListShowCategory: null }) } - if (!$class2) { - $class2 = $('.J_advListShowCategory select') + if (!$catFields) { + $catFields = $('.advListShowCategory-set select:eq(0)') + $catFormats = $('.advListShowCategory-set select:eq(1)') + $.get(`/commons/metadata/fields?entity=${wpc.entityName}&deep=2`, (res) => { const _data = [] - res.data.forEach((item) => { - if (CLASS_TYPES.includes(item.type)) _data.push(item) - }) + res.data && + res.data.forEach((item) => { + if (CATE_TYPES.includes(item.type) && !(item.name.includes('owningDept.') || item.name.includes('owningUser.'))) { + _data.push(item) + } + }) + // FIELD:[FORMAT] + let set = wpc.extConfig && wpc.extConfig.advListShowCategory ? wpc.extConfig.advListShowCategory : null + if (set) set = set.split(':') + + wpc.extConfig.advListShowCategory that.setState({ advListShowCategoryFields: _data }, () => { - $class2 - .select2({ placeholder: $L('选择分类字段') }) - .val((wpc.extConfig && wpc.extConfig.advListShowCategory) || null) - .trigger('change') + $catFields + .select2({ + placeholder: $L('选择分类字段'), + allowClear: false, + }) + .on('change', () => { + const s = $catFields.val() + const found = _data.find((x) => x.name === s) + + let formats + if (found && found.type === 'CLASSIFICATION') { + formats = [ + [0, $L('%d 级分类', 1)], + [1, $L('%d 级分类', 2)], + [2, $L('%d 级分类', 3)], + [3, $L('%d 级分类', 4)], + ] + } else if (found && (found.type === 'DATE' || found.type === 'DATETIME')) { + formats = [ + ['yyyy', 'YYYY'], + ['yyyy-MM', 'YYYY-MM'], + ['yyyy-MM-dd', 'YYYY-MM-DD'], + ] + } + + that.setState({ advListShowCategoryFormats: formats }, () => { + $catFormats.val(null).trigger('change') + }) + }) + + $catFormats.select2({ placeholder: $L('默认') }) + + if (set) { + $catFields.val(set[0]).trigger('change') + setTimeout(() => { + if (set[1]) $catFormats.val(set[1]).trigger('change') + }, 200) + } }) }) } @@ -216,10 +280,13 @@ class DlgMode1Option extends RbFormHandler { const o = { advListHideFilters: !$val('#advListHideFilters'), advListHideCharts: !$val('#advListHideCharts'), - advListShowCategory: this.state.advListShowCategory ? $val('.J_advListShowCategory select') : null, advListFilterPane: $val('#advListFilterPane'), } + if (this.state.advListShowCategory) { + o.advListShowCategory = `${$val('.advListShowCategory-set select:eq(0)')}:${$val('.advListShowCategory-set select:eq(1)') || ''}` + } + this.disabled(true) modeSave(o, () => { this.hide() diff --git a/src/main/resources/web/general/detail-list.html b/src/main/resources/web/general/detail-list.html index d493c1d96..3a924c420 100644 --- a/src/main/resources/web/general/detail-list.html +++ b/src/main/resources/web/general/detail-list.html @@ -16,7 +16,7 @@
diff --git a/src/main/resources/web/general/record-list.html b/src/main/resources/web/general/record-list.html index 45681a34b..bf82d0fe8 100644 --- a/src/main/resources/web/general/record-list.html +++ b/src/main/resources/web/general/record-list.html @@ -16,7 +16,7 @@
From a00d5f1ea82570edc3715d4526e28abe15bd581a Mon Sep 17 00:00:00 2001 From: RB Date: Mon, 21 Nov 2022 23:42:58 +0800 Subject: [PATCH 3/3] close #491 --- .../web/assets/js/trigger/trigger.FIELDWRITEBACK.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/resources/web/assets/js/trigger/trigger.FIELDWRITEBACK.js b/src/main/resources/web/assets/js/trigger/trigger.FIELDWRITEBACK.js index d338eeb66..d1ef4319e 100644 --- a/src/main/resources/web/assets/js/trigger/trigger.FIELDWRITEBACK.js +++ b/src/main/resources/web/assets/js/trigger/trigger.FIELDWRITEBACK.js @@ -250,10 +250,18 @@ class ContentFieldWriteback extends ActionContentSpec { } }) + // fix: GitHub#491 + let sfLast = $(this._$sourceField).val() + sfLast = sourceFields.find((x) => x.name === sfLast) + this.setState({ targetField: null, sourceFields: sourceFields }, () => { - if (sourceFields.length > 0) $(this._$sourceField).val(sourceFields[0].name) + if (!sfLast && sourceFields.length > 0) sfLast = sourceFields[0] + // 强制销毁后再渲染 - this.setState({ targetField: targetField }) + this.setState({ targetField: targetField }, () => { + if (sfLast) $(this._$sourceField).val(sfLast.name) + $(this._$sourceField).trigger('change') + }) }) }
SN[[${T(com.rebuild.core.support.License).SN()}]]
VersionVersion [[${T(com.rebuild.core.Application).VER}]]