mirror of
https://github.com/getrebuild/rebuild.git
synced 2025-09-30 18:49:49 +08:00
Fix 3.4.4 (#665)
* fix:Gitee#I8326Z * fix: 删除时不生效 * fix: tag fillback * v3.4.4 * frontjs-sdk-demo * bk: getActualMaximum
This commit is contained in:
parent
188cbf73cf
commit
41d33a455f
10 changed files with 320 additions and 22 deletions
2
@rbv
2
@rbv
|
@ -1 +1 @@
|
|||
Subproject commit e83ed9efb79ef2bffacbbe8c2288aecc7bcd2042
|
||||
Subproject commit 0ace77d3b95da6f61691bd2610230c4bd979011d
|
10
pom.xml
10
pom.xml
|
@ -10,7 +10,7 @@
|
|||
</parent>
|
||||
<groupId>com.rebuild</groupId>
|
||||
<artifactId>rebuild</artifactId>
|
||||
<version>3.4.3</version>
|
||||
<version>3.4.4</version>
|
||||
<name>rebuild</name>
|
||||
<description>Building your business-systems freely!</description>
|
||||
<!-- UNCOMMENT USE TOMCAT -->
|
||||
|
@ -38,19 +38,17 @@
|
|||
<!-- <includeSystemScope>true</includeSystemScope> -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<arg>-g:lines</arg>
|
||||
<arg>-Xlint:unchecked</arg>
|
||||
<arg>-Xlint:deprecation</arg>
|
||||
<!-- <arg>-g:none</arg> -->
|
||||
<!-- <arg>-Xlint:unchecked</arg> -->
|
||||
<!-- <arg>-Xlint:deprecation</arg> -->
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
-->
|
||||
<plugin>
|
||||
<groupId>com.github.eirslett</groupId>
|
||||
<artifactId>frontend-maven-plugin</artifactId>
|
||||
|
|
|
@ -73,11 +73,11 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
|
|||
/**
|
||||
* Rebuild Version
|
||||
*/
|
||||
public static final String VER = "3.4.3";
|
||||
public static final String VER = "3.4.4";
|
||||
/**
|
||||
* Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2}
|
||||
*/
|
||||
public static final int BUILD = 3040308;
|
||||
public static final int BUILD = 3040409;
|
||||
|
||||
static {
|
||||
// Driver for DB
|
||||
|
|
|
@ -149,7 +149,8 @@ public class BaseService extends InternalPersistService {
|
|||
for (Field n2nField : n2nFields) {
|
||||
ID[] newRefs;
|
||||
if (isNew) {
|
||||
newRefs = record.getIDArray(n2nField.getName());
|
||||
Object maybeNull = record.getObjectValue(n2nField.getName());
|
||||
newRefs = NullValue.is(maybeNull) ? ID.EMPTY_ID_ARRAY : (ID[]) maybeNull;
|
||||
if (newRefs == null || newRefs.length == 0) continue;
|
||||
} else {
|
||||
if (record.hasValue(n2nField.getName())) {
|
||||
|
|
|
@ -14,7 +14,14 @@ import com.rebuild.core.support.i18n.Language;
|
|||
import com.rebuild.utils.JSONUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 流程解析
|
||||
|
@ -102,11 +109,14 @@ public class FlowParser {
|
|||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 非条件分支,只会有一个节点
|
||||
// 非条件分支只会有一个节点
|
||||
if (!FlowNode.TYPE_BRANCH.equals(next.get(0).getType())) {
|
||||
return next;
|
||||
}
|
||||
|
||||
// fix:Gitee#I8326Z 移除非条件节点
|
||||
next.removeIf(flowNode -> !flowNode.getType().equals(FlowNode.TYPE_BRANCH));
|
||||
|
||||
// 条件节点优先级排序
|
||||
next.sort((o1, o2) -> {
|
||||
int p1 = ((FlowBranch) o1).getPriority();
|
||||
|
|
|
@ -335,26 +335,32 @@ public class AdvFilterParser extends SetUser {
|
|||
int x = NumberUtils.toInt(value);
|
||||
value = formatDate(addDay(x), 0);
|
||||
} else if (ParseHelper.EVW.equalsIgnoreCase(op) || ParseHelper.EVM.equalsIgnoreCase(op)) {
|
||||
Calendar c = CalendarUtils.getInstance();
|
||||
final Calendar today = CalendarUtils.getInstance();
|
||||
|
||||
int x = NumberUtils.toInt(value);
|
||||
if (ParseHelper.EVW.equalsIgnoreCase(op)) {
|
||||
boolean isSunday = c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
|
||||
if (isSunday) c.add(Calendar.DAY_OF_WEEK, -1);
|
||||
boolean isSunday = today.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
|
||||
if (isSunday) today.add(Calendar.DAY_OF_WEEK, -1);
|
||||
if (x < 1) x = 1;
|
||||
if (x > 7) x = 7;
|
||||
x += 1;
|
||||
if (x <= 7) {
|
||||
c.set(Calendar.DAY_OF_WEEK, x);
|
||||
today.set(Calendar.DAY_OF_WEEK, x);
|
||||
} else {
|
||||
c.set(Calendar.DAY_OF_WEEK, 7);
|
||||
c.add(Calendar.DAY_OF_WEEK, 1);
|
||||
today.set(Calendar.DAY_OF_WEEK, 7);
|
||||
today.add(Calendar.DAY_OF_WEEK, 1);
|
||||
}
|
||||
} else {
|
||||
if (x < 1) x = 1;
|
||||
if (x > 31) x = 31;
|
||||
c.set(Calendar.DAY_OF_MONTH, x);
|
||||
|
||||
// v3.4.4 每月最后一天
|
||||
int maxDayOfMonth = today.getActualMaximum(Calendar.DAY_OF_MONTH);
|
||||
if (x > maxDayOfMonth) x = maxDayOfMonth;
|
||||
|
||||
today.set(Calendar.DAY_OF_MONTH, x);
|
||||
}
|
||||
value = formatDate(c.getTime(), 0);
|
||||
value = formatDate(today.getTime(), 0);
|
||||
}
|
||||
else if (ParseHelper.YTA.equalsIgnoreCase(op)) {
|
||||
value = formatDate(addDay(-1), 0);
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
/*!
|
||||
Copyright (c) Ruifang Tech <http://ruifang-tech.com/> and/or its owners. All rights reserved.
|
||||
*/
|
||||
|
||||
package com.rebuild.core.service.trigger.impl;
|
||||
|
||||
import cn.devezhao.persist4j.Entity;
|
||||
import cn.devezhao.persist4j.Field;
|
||||
import cn.devezhao.persist4j.dialect.FieldType;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.rebuild.core.Application;
|
||||
import com.rebuild.core.metadata.EntityHelper;
|
||||
import com.rebuild.core.metadata.MetadataHelper;
|
||||
import com.rebuild.core.privileges.bizz.InternalPermission;
|
||||
import com.rebuild.core.service.approval.ApprovalHelper;
|
||||
import com.rebuild.core.service.approval.ApprovalState;
|
||||
import com.rebuild.core.service.general.OperatingContext;
|
||||
import com.rebuild.core.service.trigger.ActionContext;
|
||||
import com.rebuild.core.service.trigger.TriggerAction;
|
||||
import com.rebuild.core.service.trigger.TriggerException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author devezhao
|
||||
* @since 2023/9/27
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AutoHoldTriggerAction extends TriggerAction {
|
||||
|
||||
private Set<ID> willRecords;
|
||||
|
||||
protected AutoHoldTriggerAction(ActionContext actionContext) {
|
||||
super(actionContext);
|
||||
}
|
||||
|
||||
// 删除前保持
|
||||
@Override
|
||||
protected void prepare(OperatingContext operatingContext) throws TriggerException {
|
||||
if (operatingContext.getAction() == InternalPermission.DELETE_BEFORE) {
|
||||
willRecords = getRelatedRecords(
|
||||
actionContext, operatingContext.getAnyRecord().getPrimary());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取待处理记录
|
||||
*
|
||||
* @param operatingContext
|
||||
* @return
|
||||
*/
|
||||
protected Set<ID> getWillRecords(OperatingContext operatingContext) {
|
||||
if (willRecords == null) {
|
||||
willRecords = getRelatedRecords(
|
||||
actionContext, operatingContext.getAnyRecord().getPrimary());
|
||||
}
|
||||
return willRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取相关记录
|
||||
*
|
||||
* @param actionContext
|
||||
* @param sourceRecordId
|
||||
* @return
|
||||
*/
|
||||
protected static Set<ID> getRelatedRecords(ActionContext actionContext, ID sourceRecordId) {
|
||||
// 共享的需要使用记录 ID
|
||||
if (sourceRecordId.getEntityCode() == EntityHelper.ShareAccess) {
|
||||
Object[] o = Application.getQueryFactory().uniqueNoFilter(sourceRecordId, "recordId");
|
||||
if (o == null) return Collections.emptySet();
|
||||
sourceRecordId = (ID) o[0];
|
||||
}
|
||||
|
||||
final JSONObject actionContent = (JSONObject) actionContext.getActionContent();
|
||||
|
||||
Entity sourceEntity = actionContext.getSourceEntity();
|
||||
JSONArray fs = actionContent.getJSONArray("fields");
|
||||
|
||||
List<String> fieldsSelf = new ArrayList<>();
|
||||
List<Field> fieldsRefto = new ArrayList<>();
|
||||
boolean hasSelf = false;
|
||||
|
||||
for (Object o : fs) {
|
||||
String field = (String) o;
|
||||
if (field.contains(".")) {
|
||||
String[] fieldAndEntity = field.split("\\.");
|
||||
if (MetadataHelper.containsField(fieldAndEntity[1], fieldAndEntity[0])) {
|
||||
fieldsRefto.add(MetadataHelper.getField(fieldAndEntity[1], fieldAndEntity[0]));
|
||||
}
|
||||
|
||||
} else {
|
||||
if (SOURCE_SELF.equals(field)) {
|
||||
fieldsSelf.add(sourceEntity.getPrimaryField().getName());
|
||||
hasSelf = true;
|
||||
} if (sourceEntity.containsField(field)) {
|
||||
fieldsSelf.add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Set<ID> relateds = new HashSet<>();
|
||||
|
||||
if (!fieldsSelf.isEmpty()) {
|
||||
fieldsSelf.add(sourceEntity.getPrimaryField().getName());
|
||||
Object[] o = Application.getQueryFactory().uniqueNoFilter(sourceRecordId, fieldsSelf.toArray(new String[0]));
|
||||
if (o != null) {
|
||||
for (Object id : o) {
|
||||
if (id != null) {
|
||||
if (id instanceof ID[]) Collections.addAll(relateds, (ID[]) id);
|
||||
else relateds.add((ID) id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Field refto : fieldsRefto) {
|
||||
Entity ownEntity = refto.getOwnEntity();
|
||||
String sql = String.format("select %s from %s where ",
|
||||
ownEntity.getPrimaryField().getName(), ownEntity.getName());
|
||||
|
||||
// N2N
|
||||
if (refto.getType() == FieldType.REFERENCE_LIST) {
|
||||
sql += String.format(
|
||||
"exists (select recordId from NreferenceItem where ^%s = recordId and belongField = '%s' and referenceId = '%s')",
|
||||
ownEntity.getPrimaryField().getName(), refto.getName(), sourceRecordId);
|
||||
} else {
|
||||
sql += String.format("%s = '%s'", refto.getName(), sourceRecordId);
|
||||
}
|
||||
|
||||
Object[][] array = Application.createQueryNoFilter(sql).array();
|
||||
for (Object[] o : array) relateds.add((ID) o[0]);
|
||||
}
|
||||
|
||||
// 不含自己
|
||||
if (!hasSelf) relateds.remove(sourceRecordId);
|
||||
|
||||
return relateds;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取审核状态
|
||||
*
|
||||
* @param recordId
|
||||
* @return
|
||||
* @see ApprovalHelper#getApprovalState(ID)
|
||||
*/
|
||||
protected static ApprovalState getApprovalState(ID recordId) {
|
||||
Entity entity = MetadataHelper.getEntity(recordId.getEntityCode());
|
||||
if (MetadataHelper.hasApprovalField(entity)) return ApprovalHelper.getApprovalState(recordId);
|
||||
else return null;
|
||||
}
|
||||
}
|
|
@ -8,10 +8,12 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
package com.rebuild.core.service.trigger.impl;
|
||||
|
||||
import cn.devezhao.bizz.privileges.impl.BizzPermission;
|
||||
import cn.devezhao.persist4j.Entity;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.rebuild.core.Application;
|
||||
import com.rebuild.core.metadata.MetadataHelper;
|
||||
import com.rebuild.core.privileges.PrivilegesGuardContextHolder;
|
||||
import com.rebuild.core.privileges.UserHelper;
|
||||
import com.rebuild.core.service.general.EntityService;
|
||||
|
@ -19,6 +21,7 @@ import com.rebuild.core.service.general.GeneralEntityServiceContextHolder;
|
|||
import com.rebuild.core.service.general.OperatingContext;
|
||||
import com.rebuild.core.service.trigger.ActionContext;
|
||||
import com.rebuild.core.service.trigger.ActionType;
|
||||
import com.rebuild.core.service.trigger.TriggerAction;
|
||||
import com.rebuild.core.service.trigger.TriggerException;
|
||||
import com.rebuild.core.service.trigger.TriggerResult;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -33,7 +36,7 @@ import java.util.Set;
|
|||
* @since 2019/8/23
|
||||
*/
|
||||
@Slf4j
|
||||
public class AutoShare extends AutoAssign {
|
||||
public class AutoShare extends TriggerAction {
|
||||
|
||||
public AutoShare(ActionContext context) {
|
||||
super(context);
|
||||
|
@ -44,6 +47,12 @@ public class AutoShare extends AutoAssign {
|
|||
return ActionType.AUTOSHARE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUsableSourceEntity(int entityCode) {
|
||||
Entity e = MetadataHelper.getEntity(entityCode);
|
||||
return MetadataHelper.hasPrivilegesField(e) || e.getMainEntity() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(OperatingContext operatingContext) throws TriggerException {
|
||||
final JSONObject content = (JSONObject) actionContext.getActionContent();
|
||||
|
|
|
@ -2683,7 +2683,24 @@ class RbFormTag extends RbFormElement {
|
|||
}
|
||||
}
|
||||
|
||||
// isValueUnchanged() {}
|
||||
setValue(val) {
|
||||
if (typeof val === 'object') val = val.join('$$$$')
|
||||
super.setValue(val)
|
||||
|
||||
// fix: v3.4.4
|
||||
if ($empty(val)) {
|
||||
this.__select2.val(null).trigger('change')
|
||||
} else {
|
||||
const names = []
|
||||
val.split('$$$$').forEach((name) => {
|
||||
if (!names.includes(name)) {
|
||||
const o = new Option(name, name, true, true)
|
||||
this.__select2.append(o)
|
||||
names.push(name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 不支持/未开放的字段
|
||||
|
|
97
src/test/resources/frontjs-sdk-demo.js
Normal file
97
src/test/resources/frontjs-sdk-demo.js
Normal file
|
@ -0,0 +1,97 @@
|
|||
// FrontJS 演示
|
||||
// 建议将上方匹配路径设置为 `/` 以便观察效果
|
||||
|
||||
const demoEntityName = 'Account' // TODO 修改为你要测试的实体
|
||||
const demoFieldName = 'AccountName' // TODO 修改为你要测试的实体字段
|
||||
|
||||
let _List, _Form, _View
|
||||
|
||||
FrontJS.ready(() => {
|
||||
_List = FrontJS.DataList
|
||||
_Form = FrontJS.Form
|
||||
_View = FrontJS.View
|
||||
|
||||
demoAddButton()
|
||||
|
||||
demoForList()
|
||||
|
||||
demoForForm()
|
||||
})
|
||||
|
||||
// 添加按钮
|
||||
// 注意在 onOpen 中调用
|
||||
function demoAddButton() {
|
||||
_List.onOpen(() => {
|
||||
_List.addButtonGroup({
|
||||
text: 'FrontJS!',
|
||||
items: [
|
||||
{
|
||||
text: '获取第一选中',
|
||||
onClick: () => {
|
||||
alert(_List.getSelectedId())
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '获取全部选中',
|
||||
onClick: () => {
|
||||
alert(_List.getSelectedIds())
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
_Form.onOpen(() => {
|
||||
_Form.addButton({
|
||||
text: 'FrontJS!',
|
||||
onClick: () => {
|
||||
alert(_Form.getCurrentId())
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
_View.onOpen(() => {
|
||||
_Form.addButton({
|
||||
text: 'FrontJS!',
|
||||
onClick: () => {
|
||||
alert(_Form.getCurrentId())
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 列表操作
|
||||
function demoForList() {
|
||||
// 指定字段加粗加红显示
|
||||
const fieldKey = `${demoEntityName}.${demoFieldName}`
|
||||
_List.regCellRender(fieldKey, function (v) {
|
||||
return <strong className="text-danger">{JSON.stringify(v)}</strong>
|
||||
})
|
||||
|
||||
// 轻量级表单
|
||||
_List.onOpen(() => {
|
||||
_List.addButton({
|
||||
text: 'LiteForm',
|
||||
onClick: () => {
|
||||
const id = _List.getSelectedId()
|
||||
if (!id) {
|
||||
alert('请选择一条记录')
|
||||
return
|
||||
}
|
||||
|
||||
FrontJS.openLiteForm(id, [{ field: demoFieldName, tip: '提示', readonly: true, nullable: true }])
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 表单操作
|
||||
function demoForForm() {
|
||||
// 监听指定字段值变化
|
||||
const lookFieldKey = `${demoEntityName}.${demoFieldName}`
|
||||
_Form.onFieldValueChange(function (fieldKey, fieldValue, recordId) {
|
||||
if (lookFieldKey === fieldKey) {
|
||||
RbHighbar.create(`记录: ${recordId || ''} 的新值 : ${fieldValue}`)
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Add table
Reference in a new issue