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)
- $('').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)
+ $('').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