diff --git a/pom.xml b/pom.xml index 462fb5d2e..331d6ae02 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.rebuild rebuild - 3.3.3 + 3.3.4 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 d3ec998b5..f4a1ab377 100644 --- a/src/main/java/com/rebuild/core/Application.java +++ b/src/main/java/com/rebuild/core/Application.java @@ -73,11 +73,11 @@ public class Application implements ApplicationListener /** * Rebuild Version */ - public static final String VER = "3.3.3"; + public static final String VER = "3.3.4"; /** * Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2} */ - public static final int BUILD = 3030308; + public static final int BUILD = 3030409; static { // Driver for DB diff --git a/src/main/java/com/rebuild/core/configuration/general/FormsBuilder.java b/src/main/java/com/rebuild/core/configuration/general/FormsBuilder.java index 6be0f6237..cf32cf96a 100644 --- a/src/main/java/com/rebuild/core/configuration/general/FormsBuilder.java +++ b/src/main/java/com/rebuild/core/configuration/general/FormsBuilder.java @@ -39,7 +39,13 @@ import org.apache.commons.lang.StringUtils; import org.springframework.util.Assert; -import java.util.*; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; /** * 表单构造 @@ -310,21 +316,28 @@ protected void buildModelElements(JSONArray elements, Entity entity, Record reco Object requiredOnCreate = el.remove("requiredOnCreate"); Object requiredOnUpdate = el.remove("requiredOnUpdate"); if (useAdvControl) { + // fix v3.3.4 跟随主记录新建/更新 + boolean isNew2 = isNew; + if (entity.getMainEntity() != null) { + ID fromMain = FormsBuilderContextHolder.getMainIdOfDetail(false); + isNew2 = EntityHelper.isUnsavedId(fromMain); + } + // 显示 - if (displayOnCreate != null && !(Boolean) displayOnCreate && isNew) { + if (displayOnCreate != null && !(Boolean) displayOnCreate && isNew2) { iter.remove(); continue; } - if (displayOnUpdate != null && !(Boolean) displayOnUpdate && !isNew) { + if (displayOnUpdate != null && !(Boolean) displayOnUpdate && !isNew2) { iter.remove(); continue; } // 必填 - if (requiredOnCreate != null && (Boolean) requiredOnCreate && isNew) { + if (requiredOnCreate != null && (Boolean) requiredOnCreate && isNew2) { el.put("nullable", false); } - if (requiredOnUpdate != null && (Boolean) requiredOnUpdate && !isNew) { + if (requiredOnUpdate != null && (Boolean) requiredOnUpdate && !isNew2) { el.put("nullable", false); } } diff --git a/src/main/java/com/rebuild/core/privileges/RoleBaseQueryFilter.java b/src/main/java/com/rebuild/core/privileges/RoleBaseQueryFilter.java index 6edb73485..7746d74d7 100644 --- a/src/main/java/com/rebuild/core/privileges/RoleBaseQueryFilter.java +++ b/src/main/java/com/rebuild/core/privileges/RoleBaseQueryFilter.java @@ -225,7 +225,12 @@ private String buildCustomFilter(Privileges ep, Field dtmField) { JSONArray items2 = new JSONArray(); for (Object item : items) { JSONObject c = (JSONObject) JSONUtils.clone((JSON) item); - c.put("field", String.format("%s.%s", dtmField.getName(), c.getString("field"))); + String field = c.getString("field"); + if (field.startsWith("&")) { + c.put("field", String.format("&%s.%s", dtmField.getName(), field.substring(1))); + } else { + c.put("field", String.format("%s.%s", dtmField.getName(), field)); + } items2.add(c); } diff --git a/src/main/java/com/rebuild/core/service/general/recyclebin/RecycleRestore.java b/src/main/java/com/rebuild/core/service/general/recyclebin/RecycleRestore.java index cb9055538..ce319ceef 100644 --- a/src/main/java/com/rebuild/core/service/general/recyclebin/RecycleRestore.java +++ b/src/main/java/com/rebuild/core/service/general/recyclebin/RecycleRestore.java @@ -17,11 +17,17 @@ import com.rebuild.core.Application; import com.rebuild.core.DefinedException; import com.rebuild.core.RebuildException; +import com.rebuild.core.configuration.ConfigurationException; import com.rebuild.core.metadata.EntityHelper; import com.rebuild.core.metadata.MetadataHelper; import com.rebuild.core.privileges.UserService; +import com.rebuild.core.service.DataSpecificationException; import com.rebuild.core.service.TransactionManual; +import com.rebuild.core.service.approval.ApprovalHelper; +import com.rebuild.core.service.approval.ApprovalState; import com.rebuild.core.service.feeds.FeedsService; +import com.rebuild.core.service.project.ProjectManager; +import com.rebuild.core.service.query.QueryHelper; import com.rebuild.core.support.i18n.Language; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.TransactionStatus; @@ -135,7 +141,41 @@ public int restore(boolean cascade) { */ private List conver2Record(JSONObject content, ID recordId) { if (!MetadataHelper.containsEntity(recordId.getEntityCode())) { - throw new DefinedException(Language.L("所属实体已经不存在,无法恢复")); + throw new DefinedException(Language.L("记录所属实体已经不存在,无法恢复")); + } + + final Entity entity = MetadataHelper.getEntity(recordId.getEntityCode()); + + if (entity.getEntityCode() == EntityHelper.ProjectTask) { + String projectId = content.getString("projectId"); + String projectPlanId = content.getString("projectPlanId"); + + try { + ProjectManager.instance.getProject(ID.valueOf(projectId), null); + ProjectManager.instance.getProjectByX(ID.valueOf(projectPlanId), null); + } catch (ConfigurationException know) { + log.warn(null, know); + throw new DefinedException(Language.L("任务所属项目或面板已经不存在,无法恢复")); + } + } + + if (entity.getMainEntity() != null) { + String dtfName = MetadataHelper.getDetailToMainField(entity).getName(); + String dtfValue = content.getString(dtfName); + ID mainid = ID.valueOf(dtfValue); + + if (!QueryHelper.exists(mainid)) { + throw new DefinedException(Language.L("明细所属主记录已经不存在,无法恢复")); + } + + if (MetadataHelper.hasApprovalField(entity.getMainEntity())) { + ApprovalState state = ApprovalHelper.getApprovalState(mainid); + if (state == ApprovalState.APPROVED || state == ApprovalState.PROCESSING) { + throw new DataSpecificationException(state == ApprovalState.APPROVED + ? Language.L("明细所属主记录已完成审批,无法恢复") + : Language.L("明细所属主记录正在审批中,无法恢复")); + } + } } JSONArray detailList = content.getJSONArray(RecycleBean.NAME_DETAILLIST); @@ -144,8 +184,6 @@ private List conver2Record(JSONObject content, ID recordId) { } List records = new ArrayList<>(); - - Entity entity = MetadataHelper.getEntity(recordId.getEntityCode()); Record record = new RestoreRecordCreator(entity, content).create(true); records.add(record); diff --git a/src/main/java/com/rebuild/core/service/project/ProjectTaskService.java b/src/main/java/com/rebuild/core/service/project/ProjectTaskService.java index 590200df5..b96163b25 100644 --- a/src/main/java/com/rebuild/core/service/project/ProjectTaskService.java +++ b/src/main/java/com/rebuild/core/service/project/ProjectTaskService.java @@ -163,7 +163,7 @@ private int getNextSeqViaMidValue(ID projectPlanId) { "select max(seq) from ProjectTask where projectPlanId = ?") .setParameter(1, projectPlanId) .unique(); - return (seqMax == null || seqMax[0] == null) ? 0 : ((Integer) seqMax[0] + MID_VALUE); + return (seqMax == null || seqMax[0] == null) ? MID_VALUE : ((Integer) seqMax[0] + MID_VALUE); } /** diff --git a/src/main/java/com/rebuild/utils/OshiUtils.java b/src/main/java/com/rebuild/utils/OshiUtils.java index c37d8d7be..c32ad4c57 100644 --- a/src/main/java/com/rebuild/utils/OshiUtils.java +++ b/src/main/java/com/rebuild/utils/OshiUtils.java @@ -9,17 +9,23 @@ import cn.devezhao.commons.ObjectUtils; import cn.devezhao.commons.runtime.MemoryInformationBean; +import com.esotericsoftware.minlog.Log; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import oshi.SystemInfo; import oshi.hardware.GlobalMemory; import oshi.hardware.NetworkIF; +import java.net.URL; +import java.net.URLConnection; +import java.util.Date; import java.util.List; /** * @author devezhao * @since 2021/9/22 */ +@Slf4j public class OshiUtils { private static SystemInfo SI; @@ -101,4 +107,30 @@ public static String getLocalIp() { return StringUtils.defaultString(bestipv4, "127.0.0.1"); } + + /** + * 获取网络时间 + * + * @return + */ + public static Date getNetworkDate() { + final String[] FROMURLS = new String[] { + "http://www.baidu.com/", + "http://bjtime.cn/", + "http://www.google.com/", + }; + + for (String u : FROMURLS) { + try { + URLConnection conn = new URL(u).openConnection(); + long l = conn.getDate(); + return new Date(l); + } catch (Exception ex) { + Log.debug("Failed with : {}", u); + } + } + + log.warn("Cannot getdate from network"); + return new Date(); + } } diff --git a/src/main/resources/web/assets/css/rb-page.css b/src/main/resources/web/assets/css/rb-page.css index 21e5bf3ae..e8be936d0 100644 --- a/src/main/resources/web/assets/css/rb-page.css +++ b/src/main/resources/web/assets/css/rb-page.css @@ -813,7 +813,7 @@ body.view-body { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - max-width: 200px; + max-width: 240px; } .select2-container--default .select2-results__group { @@ -921,6 +921,7 @@ select.form-control:not([disabled]) { width: 150px; padding-right: 17px; text-align: right; + flex-shrink: 0; } @media (min-width: 1064px) { @@ -998,6 +999,10 @@ select.form-control:not([disabled]) { top: 8px; } +.type-REFERENCE .col-form-control { + overflow: hidden; +} + .type-N2NREFERENCE .select2-container--default .select2-selection--multiple::after { content: '\f2f9'; font-family: 'Material-Design-Iconic-Font', serif; diff --git a/src/main/resources/web/assets/js/admin/transform-design.js b/src/main/resources/web/assets/js/admin/transform-design.js index d6b3303a0..ab05c5b26 100644 --- a/src/main/resources/web/assets/js/admin/transform-design.js +++ b/src/main/resources/web/assets/js/admin/transform-design.js @@ -174,7 +174,7 @@ class FieldsMapping extends React.Component { constructor(props) { super(props) this.state = { ...props, useVfixed: {} } - this._FieldValueSet = [] + this._FieldValueSet = {} } componentDidMount() { diff --git a/src/main/resources/web/assets/js/project/project-tasks.js b/src/main/resources/web/assets/js/project/project-tasks.js index 2d85c108b..5ff884ca3 100644 --- a/src/main/resources/web/assets/js/project/project-tasks.js +++ b/src/main/resources/web/assets/js/project/project-tasks.js @@ -112,7 +112,7 @@ class PlanBoxes extends React.Component { render() { return ( - + {this.props.plans.map((item) => { return ( ) })} - + ) } @@ -187,6 +187,9 @@ class PlanBoxes extends React.Component { else if (prevSeq === 0) seq = nextSeq / 2 else seq = ~~(prevSeq + (nextSeq - prevSeq) / 2) + // v3.4 bugfix `0` + if (seq <= 0) seq = 1000 + // Use state of react for move let $itemholder if (planidNew) { diff --git a/src/main/resources/web/assets/js/rb-page.js b/src/main/resources/web/assets/js/rb-page.js index 96547d65b..ac43dc890 100644 --- a/src/main/resources/web/assets/js/rb-page.js +++ b/src/main/resources/web/assets/js/rb-page.js @@ -8,7 +8,7 @@ See LICENSE and COMMERCIAL in the project root for license information. /* !!! KEEP IT ES5 COMPATIBLE !!! */ // GA -(function () { +;(function () { const gaScript = document.createElement('script') gaScript.src = 'https://www.googletagmanager.com/gtag/js?id=G-ZCZHJPMEG7' gaScript.async = true @@ -386,13 +386,14 @@ var _loadMessages = function () { $.get('/notification/messages?pageSize=10&preview=true', function (res) { $ul.empty() $(res.data).each(function (idx, item) { - var o = $('
  • ').appendTo($ul) - if (item[3] === true) o.addClass('notification-unread') - o = $('').appendTo(o) - $('
    Avatar
    ').appendTo(o) - o = $('
    ').appendTo(o) - $('
    ' + item[1] + '
    ').appendTo(o) - $('' + $fromNow(item[2]) + '').appendTo(o) + var $o = $('
  • ').appendTo($ul) + if (item[3] === true) $o.addClass('notification-unread') + $o = $('').appendTo($o) + $('
    Avatar
    ').appendTo($o) + $o = $('
    ').appendTo($o) + var $m = $('
    ').appendTo($o) + $m.attr('title', item[1]).text(item[1]) + $('' + $fromNow(item[2]) + '').appendTo($o) }) _loadMessages__state = true diff --git a/src/test/java/com/rebuild/utils/OshiUtilsTest.java b/src/test/java/com/rebuild/utils/OshiUtilsTest.java index c4a954f18..b6d357506 100644 --- a/src/test/java/com/rebuild/utils/OshiUtilsTest.java +++ b/src/test/java/com/rebuild/utils/OshiUtilsTest.java @@ -34,4 +34,9 @@ void getSystemLoad() { void getLocalIp() { System.out.println(OshiUtils.getLocalIp()); } + + @Test + void getNetworkDate() { + System.out.println(OshiUtils.getNetworkDate()); + } } \ No newline at end of file