mirror of
https://github.com/getrebuild/rebuild.git
synced 2025-09-21 14:06:37 +08:00
Feat approve editable (#947)
* Refactor batch update editor and improve NTEXT handling * Enable batch approval and update approval UI * Update table and treemap chart rendering options * Add editable record mode to approval flow nodes * Enable editable approval records for approvers * Allow editing details during approval process * Refactor form modal creation and extra button logic
This commit is contained in:
parent
31730c4464
commit
0c43b36419
24 changed files with 399 additions and 171 deletions
|
@ -159,5 +159,6 @@ module.exports = {
|
|||
marked: true,
|
||||
$focus2End: true,
|
||||
RecordSelectorModal: true,
|
||||
$fetchMetaInfo: true,
|
||||
},
|
||||
}
|
||||
|
|
2
@rbv
2
@rbv
|
@ -1 +1 @@
|
|||
Subproject commit ffe18eeaa8ae3a8acd3de09e1dbed1dbf994e9b4
|
||||
Subproject commit 34e48060b157be1bfbfb69d05506816ccccfbd48
|
|
@ -34,6 +34,7 @@ import com.rebuild.core.privileges.UserService;
|
|||
import com.rebuild.core.privileges.bizz.Department;
|
||||
import com.rebuild.core.privileges.bizz.User;
|
||||
import com.rebuild.core.service.NoRecordFoundException;
|
||||
import com.rebuild.core.service.approval.ApprovalHelper;
|
||||
import com.rebuild.core.service.approval.ApprovalState;
|
||||
import com.rebuild.core.service.approval.RobotApprovalManager;
|
||||
import com.rebuild.core.service.general.GeneralEntityService;
|
||||
|
@ -143,6 +144,7 @@ public class FormsBuilder extends FormsManager {
|
|||
ApprovalState approvalState;
|
||||
// 提示
|
||||
String readonlyMessage = null;
|
||||
String readonlywMessage = null; // 可强制编辑
|
||||
|
||||
// 判断表单权限
|
||||
|
||||
|
@ -153,10 +155,15 @@ public class FormsBuilder extends FormsManager {
|
|||
Assert.notNull(mainid, "CALL `FormBuilderContextHolder#setMainIdOfDetail` FIRST!");
|
||||
|
||||
approvalState = EntityHelper.isUnsavedId(mainid) ? null : getHadApproval(hasMainEntity, mainid);
|
||||
if ((approvalState == ApprovalState.PROCESSING || approvalState == ApprovalState.APPROVED)) {
|
||||
readonlyMessage = approvalState == ApprovalState.APPROVED
|
||||
? Language.L("主记录已审批完成,不能添加明细")
|
||||
: Language.L("主记录正在审批中,不能添加明细");
|
||||
if (approvalState == ApprovalState.APPROVED) {
|
||||
readonlyMessage = Language.L("主记录已审批完成,不能添加明细");
|
||||
} else if (approvalState == ApprovalState.PROCESSING) {
|
||||
boolean allow42 = ApprovalHelper.isAllowEditableRecord(mainid, user);
|
||||
if (allow42) {
|
||||
readonlywMessage = Language.L("主记录正在审批中,审批人允许编辑");
|
||||
} else {
|
||||
readonlyMessage = Language.L("主记录正在审批中,不能添加明细");
|
||||
}
|
||||
}
|
||||
// 明细无需审批
|
||||
approvalState = null;
|
||||
|
@ -193,7 +200,13 @@ public class FormsBuilder extends FormsManager {
|
|||
if (approvalState == ApprovalState.APPROVED) {
|
||||
readonlyMessage = Language.L("%s已审批完成,不能编辑", recordType);
|
||||
} else if (approvalState == ApprovalState.PROCESSING) {
|
||||
readonlyMessage = Language.L("%s正在审批中,不能编辑", recordType);
|
||||
// v4.2
|
||||
boolean allow42 = ApprovalHelper.isAllowEditableRecord(recordId, user);
|
||||
if (allow42) {
|
||||
readonlywMessage = Language.L("%s正在审批中,审批人允许编辑", recordType);
|
||||
} else {
|
||||
readonlyMessage = Language.L("%s正在审批中,不能编辑", recordType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -311,7 +324,8 @@ public class FormsBuilder extends FormsManager {
|
|||
}
|
||||
}
|
||||
|
||||
if (readonlyMessage != null) model.set("readonlyMessage", readonlyMessage);
|
||||
if (readonlywMessage != null) model.set("readonlywMessage", readonlywMessage);
|
||||
else if (readonlyMessage != null) model.set("readonlyMessage", readonlyMessage);
|
||||
|
||||
// v3.4
|
||||
String disabledViewEditable = EasyMetaFactory.valueOf(entityMeta)
|
||||
|
|
|
@ -12,6 +12,7 @@ import cn.devezhao.commons.ObjectUtils;
|
|||
import cn.devezhao.persist4j.Entity;
|
||||
import cn.devezhao.persist4j.Field;
|
||||
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.configuration.ConfigurationException;
|
||||
|
@ -237,6 +238,38 @@ public class ApprovalHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param recordId
|
||||
* @return
|
||||
*/
|
||||
public static FlowNode getCurrentFlowNode(ID recordId) {
|
||||
ApprovalStatus s = getApprovalStatus(recordId);
|
||||
return getFlowNode(s.getApprovalId(), s.getCurrentStepNode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param recordId
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
public static boolean isAllowEditableRecord(ID recordId, ID user) {
|
||||
// 明细需要使用主记录判断
|
||||
if (MetadataHelper.getEntity(recordId.getEntityCode()).getMainEntity() != null) {
|
||||
recordId = QueryHelper.getMainIdByDetail(recordId);
|
||||
}
|
||||
|
||||
ApprovalStatus s = getApprovalStatus(recordId);
|
||||
FlowNode node = getFlowNode(s.getApprovalId(), s.getCurrentStepNode());
|
||||
if (node == null || node.getEditableMode() != FlowNode.EDITABLE_MODE_RECORD) return false;
|
||||
|
||||
JSONArray current = new ApprovalProcessor(recordId, s.getApprovalId()).getCurrentStep(s);
|
||||
for (Object o : current) {
|
||||
JSONObject step = (JSONObject) o;
|
||||
if (StringUtils.equalsIgnoreCase(user.toLiteral(), step.getString("approver"))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取审批超时时间
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.rebuild.core.privileges.UserHelper;
|
|||
import com.rebuild.core.privileges.bizz.Department;
|
||||
import com.rebuild.utils.JSONUtils;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -66,6 +67,12 @@ public class FlowNode {
|
|||
public static final String SIGN_OR = "OR"; // 或签
|
||||
public static final String SIGN_ALL = "ALL"; // 逐个审批(暂未用)
|
||||
|
||||
// 可修改记录
|
||||
|
||||
public static final int EDITABLE_MODE_NONE = 0;
|
||||
public static final int EDITABLE_MODE_RECORD = 1;
|
||||
public static final int EDITABLE_MODE_FIELDS = 10;
|
||||
|
||||
// --
|
||||
|
||||
@Getter
|
||||
|
@ -153,8 +160,9 @@ public class FlowNode {
|
|||
* @return
|
||||
*/
|
||||
public boolean allowBatch() {
|
||||
Boolean b = getDataMap().getBoolean("allowBatch");
|
||||
return b != null && b;
|
||||
// Boolean b = getDataMap().getBoolean("allowBatch");
|
||||
// return b != null && b;
|
||||
return true; // v4.2 全面允许
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -166,7 +174,7 @@ public class FlowNode {
|
|||
*/
|
||||
public Set<ID> getSpecUsers(ID operator, ID record) {
|
||||
JSONArray userDefs = getDataMap().getJSONArray("users");
|
||||
if (userDefs == null || userDefs.isEmpty()) return Collections.emptySet();
|
||||
if (CollectionUtils.isEmpty(userDefs)) return Collections.emptySet();
|
||||
|
||||
String userType = userDefs.getString(0);
|
||||
if (USER_SELF.equalsIgnoreCase(userType)) {
|
||||
|
@ -247,7 +255,7 @@ public class FlowNode {
|
|||
*/
|
||||
public Set<String> getCcAccounts(ID record) {
|
||||
JSONArray accountFields = getDataMap().getJSONArray("accounts");
|
||||
if (accountFields == null || accountFields.isEmpty()) return Collections.emptySet();
|
||||
if (CollectionUtils.isEmpty(accountFields)) return Collections.emptySet();
|
||||
|
||||
Entity useEntity = MetadataHelper.getEntity(record.getEntityCode());
|
||||
List<String> useFields = new ArrayList<>();
|
||||
|
@ -291,20 +299,32 @@ public class FlowNode {
|
|||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj == null) return false;
|
||||
return obj instanceof FlowNode && obj.hashCode() == this.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点可修改记录
|
||||
*
|
||||
* @return 0=不可修改, 1=可修改, 10=可修改字段
|
||||
* @see #getEditableFields()
|
||||
*/
|
||||
public int getEditableMode() {
|
||||
if (getDataMap().containsKey("editableMode")) {
|
||||
return getDataMap().getIntValue("editableMode");
|
||||
}
|
||||
// v4.2 兼容
|
||||
return CollectionUtils.isEmpty(getEditableFields()) ? EDITABLE_MODE_NONE : EDITABLE_MODE_FIELDS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点可编辑字段
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public JSONArray getEditableFields() {
|
||||
JSONArray editableFields = dataMap == null ? null : dataMap.getJSONArray("editableFields");
|
||||
if (editableFields == null) return null;
|
||||
JSONArray editableFields = getDataMap().getJSONArray("editableFields");
|
||||
if (CollectionUtils.isEmpty(editableFields)) return JSONUtils.EMPTY_ARRAY;
|
||||
|
||||
editableFields = (JSONArray) JSONUtils.clone(editableFields);
|
||||
for (Object o : editableFields) {
|
||||
|
@ -321,7 +341,7 @@ public class FlowNode {
|
|||
* @return
|
||||
*/
|
||||
public JSONObject getExpiresAuto() {
|
||||
JSONObject expiresAuto = dataMap == null ? null : dataMap.getJSONObject("expiresAuto");
|
||||
JSONObject expiresAuto = getDataMap().getJSONObject("expiresAuto");
|
||||
if (expiresAuto == null) return null;
|
||||
if (expiresAuto.getIntValue("expiresAuto") <= 0) return null;
|
||||
return expiresAuto;
|
||||
|
|
|
@ -68,16 +68,12 @@ public class RobotApprovalManager implements ConfigManager {
|
|||
|
||||
// 实体的
|
||||
FlowDefinition[] defs = getFlowDefinitions(entity);
|
||||
for (FlowDefinition def : defs) {
|
||||
if (!def.isDisabled()) {
|
||||
return ApprovalState.DRAFT;
|
||||
}
|
||||
for (FlowDefinition d : defs) {
|
||||
if (!d.isDisabled()) return ApprovalState.DRAFT;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取实体是否有流程
|
||||
*
|
||||
|
|
|
@ -19,7 +19,6 @@ import org.apache.commons.lang3.ArrayUtils;
|
|||
import java.math.BigDecimal;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -113,7 +112,13 @@ public class TableChart extends ChartData {
|
|||
}
|
||||
|
||||
String tableHtml = new TableBuilder(this, dataRaw).toHTML();
|
||||
return JSONUtils.toJSONObject("html", tableHtml);
|
||||
|
||||
JSONObject renderOption = config.getJSONObject("option");
|
||||
if (renderOption == null) renderOption = new JSONObject();
|
||||
|
||||
return JSONUtils.toJSONObject(
|
||||
new String[]{"html", "_renderOption"},
|
||||
new Object[]{tableHtml, renderOption});
|
||||
}
|
||||
|
||||
protected boolean isShowLineNumber() {
|
||||
|
|
|
@ -48,7 +48,8 @@ public class TreemapChart extends ChartData {
|
|||
|
||||
JSONObject renderOption = config.getJSONObject("option");
|
||||
if (renderOption == null) renderOption = new JSONObject();
|
||||
renderOption.put("dataFlags", new String[] { getNumericalFlag(num1) });
|
||||
renderOption.put("dataFlags", new String[]{getNumericalFlag(num1)});
|
||||
renderOption.remove("useBgcolor");
|
||||
|
||||
return JSONUtils.toJSONObject(
|
||||
new String[]{"data", "xLabel", "xAmount", "_renderOption"},
|
||||
|
|
|
@ -610,10 +610,13 @@ public class GeneralEntityService extends ObservableService implements EntitySer
|
|||
}
|
||||
|
||||
ApprovalState state = ApprovalHelper.getApprovalState(dtmFieldValue);
|
||||
if (state == ApprovalState.APPROVED || state == ApprovalState.PROCESSING) {
|
||||
throw new DataSpecificationException(state == ApprovalState.APPROVED
|
||||
? Language.L("主记录已审批完成,不能添加明细")
|
||||
: Language.L("主记录正在审批中,不能添加明细"));
|
||||
if (state == ApprovalState.APPROVED) {
|
||||
throw new DataSpecificationException(Language.L("主记录已审批完成,不能添加明细"));
|
||||
} else if (state == ApprovalState.PROCESSING) {
|
||||
boolean allow42 = ApprovalHelper.isAllowEditableRecord(dtmFieldValue, getCurrentUser());
|
||||
if (!allow42) {
|
||||
throw new DataSpecificationException(Language.L("主记录正在审批中,不能添加明细"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,6 +648,13 @@ public class GeneralEntityService extends ObservableService implements EntitySer
|
|||
boolean unallow = false;
|
||||
if (action == BizzPermission.DELETE) {
|
||||
unallow = currentState == ApprovalState.APPROVED || currentState == ApprovalState.PROCESSING;
|
||||
|
||||
// v4.2 允许修改记录
|
||||
if (unallow && currentState == ApprovalState.PROCESSING) {
|
||||
boolean allow42 = ApprovalHelper.isAllowEditableRecord(checkRecordId, getCurrentUser());
|
||||
if (allow42) unallow = false;
|
||||
}
|
||||
|
||||
} else if (action == BizzPermission.UPDATE) {
|
||||
unallow = currentState == ApprovalState.APPROVED || currentState == ApprovalState.PROCESSING;
|
||||
|
||||
|
@ -659,6 +669,15 @@ public class GeneralEntityService extends ObservableService implements EntitySer
|
|||
boolean forceUpdate = GeneralEntityServiceContextHolder.isAllowForceUpdate(false);
|
||||
if (forceUpdate) unallow = false;
|
||||
}
|
||||
|
||||
// v4.2 允许修改记录
|
||||
if (unallow) {
|
||||
boolean is = ApprovalHelper.isAllowEditableRecord(checkRecordId, getCurrentUser());
|
||||
if (is) {
|
||||
unallow = false;
|
||||
GeneralEntityServiceContextHolder.setAllowForceUpdate(checkRecordId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unallow) {
|
||||
|
|
|
@ -38,6 +38,7 @@ import com.rebuild.core.service.trigger.DataValidateException;
|
|||
import com.rebuild.core.support.RbvFunction;
|
||||
import com.rebuild.utils.JSONUtils;
|
||||
import com.rebuild.web.BaseController;
|
||||
import com.rebuild.web.EntityParam;
|
||||
import com.rebuild.web.IdParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
|
@ -85,11 +86,28 @@ public class ApprovalController extends BaseController {
|
|||
return res;
|
||||
}
|
||||
|
||||
@GetMapping("alist")
|
||||
public RespBody getApprovalList(HttpServletRequest request, @EntityParam Entity entity) {
|
||||
boolean valid = getBoolParameter(request, "valid");
|
||||
|
||||
FlowDefinition[] defs = RobotApprovalManager.instance.getFlowDefinitions(entity);
|
||||
List<Object> res = new ArrayList<>();
|
||||
for (FlowDefinition d : defs) {
|
||||
if (d.isDisabled()) continue;
|
||||
// 仅返回可用的
|
||||
if (valid && !d.isWorkable()) continue;
|
||||
|
||||
res.add(JSONUtils.toJSONObject(new String[]{"id", "text"},
|
||||
new Object[]{d.getID("id"), d.getString("name")}));
|
||||
}
|
||||
return RespBody.ok(res);
|
||||
}
|
||||
|
||||
@GetMapping("state")
|
||||
public RespBody getApprovalState(HttpServletRequest request, @IdParam(name = "record") ID recordId) {
|
||||
final Entity approvalEntity = MetadataHelper.getEntity(recordId.getEntityCode());
|
||||
if (!MetadataHelper.hasApprovalField(approvalEntity)) {
|
||||
return RespBody.error("NOT AN APPROVAL ENTITY");
|
||||
return RespBody.error("NONE APPROVAL ENTITY");
|
||||
}
|
||||
|
||||
final ID user = getRequestUser(request);
|
||||
|
@ -189,10 +207,14 @@ public class ApprovalController extends BaseController {
|
|||
if (reqType < 2) data.put("remarkReq", reqType);
|
||||
else data.put("remarkReq", expTime == null || expTime < 0 ? 0 : 1);
|
||||
|
||||
// 可修改字段
|
||||
JSONArray editableFields = currentFlowNode.getEditableFields();
|
||||
if (editableFields != null && !editableFields.isEmpty()) {
|
||||
data.putAll(new EditableFields(editableFields).buildForms(recordId, user));
|
||||
// 可修改记录
|
||||
int editableMode = currentFlowNode.getEditableMode();
|
||||
data.put("editableMode", editableMode);
|
||||
if (editableMode ==FlowNode.EDITABLE_MODE_FIELDS) {
|
||||
JSONArray editableFields = currentFlowNode.getEditableFields();
|
||||
if (!CollectionUtils.isEmpty(editableFields)) {
|
||||
data.putAll(new EditableFields(editableFields).buildForms(recordId, user));
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/*Copyright (c) REBUILD <https://getrebuild.com/> and/or its owners. All rights reserved.
|
||||
|
||||
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
|
||||
See LICENSE and COMMERCIAL in the project root for license information.
|
||||
*/
|
||||
|
||||
package com.rebuild.web.robot.trigger;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.rebuild.core.Application;
|
||||
import com.rebuild.utils.JSONUtils;
|
||||
import com.rebuild.web.BaseController;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author devezhao
|
||||
* @since 2019/05/25
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/admin/robot/trigger/")
|
||||
public class AutoApprovalController extends BaseController {
|
||||
|
||||
@RequestMapping("auto-approval-alist")
|
||||
public JSON approvalList(HttpServletRequest request) {
|
||||
Object[][] array = Application.createQueryNoFilter(
|
||||
"select configId,name from RobotApprovalConfig where belongEntity = ? and isDisabled = ? order by name")
|
||||
.setParameter(1, getParameterNotNull(request, "entity"))
|
||||
.setParameter(2, false)
|
||||
.array();
|
||||
|
||||
return JSONUtils.toJSONObjectArray(new String[] { "id", "text" }, array);
|
||||
}
|
||||
}
|
|
@ -714,7 +714,8 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.expires-notify-set {
|
||||
.expires-notify-set,
|
||||
.editable-mode-set {
|
||||
background-color: #eee;
|
||||
padding: 20px;
|
||||
padding-top: 15px;
|
||||
|
|
|
@ -233,6 +233,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
background-color: #eceff1;
|
||||
border-width: 1px;
|
||||
font-weight: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.chart.ctable .table.line-number thead th:first-child,
|
||||
|
@ -309,6 +310,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
padding-top: 0;
|
||||
padding-bottom: 6px;
|
||||
font-weight: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.chart.ApprovalList .table td,
|
||||
|
@ -744,6 +746,14 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
right: 0;
|
||||
}
|
||||
|
||||
.chart-box.TABLE .chart.ctable .table {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.chart-box.TABLE.gradient-bg .chart.ctable .table th {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
/* gradient-backgrounds.css */
|
||||
|
||||
.gradient-bg-1 {
|
||||
|
|
|
@ -918,6 +918,7 @@ body.view-body {
|
|||
textarea.row1x {
|
||||
height: 37px !important;
|
||||
resize: none;
|
||||
padding-top: 7px;
|
||||
}
|
||||
|
||||
textarea.row2x {
|
||||
|
|
|
@ -221,10 +221,10 @@ class SimpleNode extends NodeSpec {
|
|||
if (this.nodeType === 'approver') {
|
||||
if (data.allowReferral) descs.push($L('允许转审'))
|
||||
if (data.allowCountersign) descs.push($L('允许加签'))
|
||||
if (data.allowBatch) descs.push($L('允许批量'))
|
||||
// if (data.allowBatch) descs.push($L('允许批量'))
|
||||
descs.push(data.signMode === 'AND' ? $L('会签') : data.signMode === 'ALL' ? $L('依次审批') : $L('或签'))
|
||||
if (data.expiresAuto && ~~data.expiresAuto.expiresAuto > 0) descs.push($L('限时审批'))
|
||||
if (data.editableFields && data.editableFields.length > 0) descs.push($L('可修改字段'))
|
||||
if (~~data.editableMode > 0) descs.push($L('可修改记录'))
|
||||
} else if (this.nodeType === 'start') {
|
||||
if (data.unallowCancel) descs.push($L('禁止撤回'))
|
||||
}
|
||||
|
@ -635,6 +635,10 @@ class ApproverNodeConfig extends StartNodeConfig {
|
|||
if (!props.users || props.users.length === 0) this.state.users = 'SPEC'
|
||||
else if (props.users[0] === 'SELF') this.state.users = 'SELF'
|
||||
else this.state.users = 'SPEC'
|
||||
// v4.2 兼容
|
||||
if (props.editableFields && props.editableFields.length > 0 && !props.editableMode) {
|
||||
this.state.editableMode = '10'
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -682,7 +686,7 @@ class ApproverNodeConfig extends StartNodeConfig {
|
|||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group mb-0">
|
||||
<div className="form-group mb-0 hide disabled-on-4.2">
|
||||
<label className="custom-control custom-control-sm custom-checkbox">
|
||||
<input className="custom-control-input" type="checkbox" name="allowBatch" checked={this.state.allowBatch === true} onChange={this.handleChange} />
|
||||
<span className="custom-control-label">
|
||||
|
@ -804,43 +808,57 @@ class ApproverNodeConfig extends StartNodeConfig {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group mt-5">
|
||||
<label className="text-bold">{$L('可修改字段')}</label>
|
||||
<div style={{ position: 'relative' }}>
|
||||
<table className={`table table-sm fields-table ${(this.state.editableFields || []).length === 0 && 'hide'}`}>
|
||||
<tbody ref={(c) => (this._$editableFields = c)}>
|
||||
{(this.state.editableFields || []).map((item) => {
|
||||
return (
|
||||
<tr key={`field-${item.field}`}>
|
||||
<td>{this.__fieldLabel(item.field)}</td>
|
||||
<td width="140" data-field={item.field}>
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline">
|
||||
<input className="custom-control-input" type="checkbox" name="notNull" defaultChecked={item.notNull === true} />
|
||||
<span className="custom-control-label">{$L('必填')}</span>
|
||||
</label>
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline ml-3">
|
||||
<input className="custom-control-input" type="checkbox" name="readOnly" defaultChecked={item.readOnly === true} />
|
||||
<span className="custom-control-label">{$L('只读')}</span>
|
||||
</label>
|
||||
</td>
|
||||
<td width="40">
|
||||
<a className="close" title={$L('移除')} onClick={() => this.removeEditableField(item.field)}>
|
||||
<i className="zmdi icon zmdi-close" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="pb-4">
|
||||
<button className="btn btn-secondary btn-sm" onClick={() => renderRbcomp(<DlgFields selected={this.state.editableFields} call={(fs) => this.setEditableFields(fs)} />)}>
|
||||
+ {$L('选择字段')}
|
||||
</button>
|
||||
<div className="form-group mt-5 pb-5">
|
||||
<label className="text-bold">{$L('修改记录')}</label>
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<select className="form-control form-control-sm" name="editableMode" defaultValue={this.state.editableMode || null} onChange={this.handleChange}>
|
||||
<option value="0">{$L('不可修改')}</option>
|
||||
<option value="1">{$L('可修改')}</option>
|
||||
<option value="10">{$L('可修改指定字段')} </option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="col pl-0" />
|
||||
</div>
|
||||
<div className={`editable-mode-set mt-3 ${~~this.state.editableMode !== 10 && 'hide'}`}>
|
||||
<label className="text-bold">{$L('指定字段')}</label>
|
||||
<div className="position-relative">
|
||||
<table className={`table table-sm fields-table ${(this.state.editableFields || []).length === 0 && 'hide'}`}>
|
||||
<tbody ref={(c) => (this._$editableFields = c)}>
|
||||
{(this.state.editableFields || []).map((item) => {
|
||||
return (
|
||||
<tr key={`field-${item.field}`}>
|
||||
<td width="57%">{this.__fieldLabel(item.field)}</td>
|
||||
<td width="35%" data-field={item.field}>
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline">
|
||||
<input className="custom-control-input" type="checkbox" name="notNull" defaultChecked={item.notNull === true} />
|
||||
<span className="custom-control-label">{$L('必填')}</span>
|
||||
</label>
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline ml-3">
|
||||
<input className="custom-control-input" type="checkbox" name="readOnly" defaultChecked={item.readOnly === true} />
|
||||
<span className="custom-control-label">{$L('只读')}</span>
|
||||
</label>
|
||||
</td>
|
||||
<td width="8%">
|
||||
<a className="close" title={$L('移除')} onClick={() => this.removeEditableField(item.field)}>
|
||||
<i className="zmdi icon zmdi-close" />
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<div>
|
||||
<button className="btn btn-secondary btn-sm" onClick={() => renderRbcomp(<DlgFields selected={this.state.editableFields} call={(fs) => this.setEditableFields(fs)} />)}>
|
||||
+ {$L('选择字段')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{this.renderButton()}
|
||||
</div>
|
||||
)
|
||||
|
@ -907,14 +925,6 @@ class ApproverNodeConfig extends StartNodeConfig {
|
|||
}
|
||||
|
||||
save = () => {
|
||||
const editableFields = []
|
||||
$(this._$editableFields)
|
||||
.find('td[data-field]')
|
||||
.each(function () {
|
||||
const $this = $(this)
|
||||
editableFields.push({ field: $this.data('field'), notNull: $this.find('input:eq(0)').prop('checked'), readOnly: $this.find('input:eq(1)').prop('checked') })
|
||||
})
|
||||
|
||||
const expiresAuto = {}
|
||||
$(this._$expiresAuto)
|
||||
.find('input, select, textarea')
|
||||
|
@ -929,11 +939,27 @@ class ApproverNodeConfig extends StartNodeConfig {
|
|||
return
|
||||
}
|
||||
|
||||
const editableFields = []
|
||||
if (~~this.state.editableMode === 10) {
|
||||
$(this._$editableFields)
|
||||
.find('td[data-field]')
|
||||
.each(function () {
|
||||
const $this = $(this)
|
||||
editableFields.push({ field: $this.data('field'), notNull: $this.find('input:eq(0)').prop('checked'), readOnly: $this.find('input:eq(1)').prop('checked') })
|
||||
})
|
||||
|
||||
if (editableFields.length === 0) {
|
||||
RbHighbar.create($L('请指定可修改字段'))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const d = {
|
||||
nodeName: this.state.nodeName,
|
||||
users: this.state.users === 'SPEC' ? this._UserSelector.getSelected() : [this.state.users],
|
||||
signMode: this.state.signMode,
|
||||
selfSelecting: this.state.selfSelecting,
|
||||
editableMode: this.state.editableMode,
|
||||
editableFields: editableFields,
|
||||
allowReferral: this.state.allowReferral,
|
||||
allowCountersign: this.state.allowCountersign,
|
||||
|
|
|
@ -52,7 +52,9 @@ class BaseChart extends React.Component {
|
|||
)
|
||||
|
||||
return (
|
||||
<div className={`chart-box ${this.props.type} ${this.state.useBgcolor && `gradient-bg-${this.state.useBgcolor}`} ${this.props.type === 'DATALIST2' && 'DataList'}`} ref={(c) => (this._$box = c)}>
|
||||
<div
|
||||
className={`chart-box ${this.props.type} ${this.state.useBgcolor && `gradient-bg gradient-bg-${this.state.useBgcolor}`} ${this.props.type === 'DATALIST2' && 'DataList'}`}
|
||||
ref={(c) => (this._$box = c)}>
|
||||
<div className="chart-head">
|
||||
<div className="chart-title text-truncate">{this.state.title}</div>
|
||||
{opActions}
|
||||
|
|
|
@ -484,6 +484,7 @@ class ApprovalApproveForm extends ApprovalUsersForm {
|
|||
)}
|
||||
|
||||
{(this.state.aform || this.state.aform_details) && this.renderLiteForm()}
|
||||
{this.state.editableMode === 1 && this.renderEditable()}
|
||||
|
||||
<div className="form-group">
|
||||
<label>
|
||||
|
@ -559,6 +560,44 @@ class ApprovalApproveForm extends ApprovalUsersForm {
|
|||
)
|
||||
}
|
||||
|
||||
renderEditable() {
|
||||
return (
|
||||
<div className="form-group">
|
||||
<label>{$L('信息完善')}</label>
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-outline"
|
||||
onClick={() => {
|
||||
$fetchMetaInfo(this.props.entity, (res) => {
|
||||
const editProps = {
|
||||
entity: res.entity,
|
||||
title: $L('编辑%s', res.entityLabel),
|
||||
icon: res.icon,
|
||||
id: this.props.id,
|
||||
postAfter: (recordId, next, formObject) => {
|
||||
// 刷新列表
|
||||
const rlp = window.RbListPage || parent.RbListPage
|
||||
if (rlp) rlp.reload(recordId)
|
||||
RbAlert.create($L('数据可能已更改,是否需要刷新页面?'), {
|
||||
onConfirm: () => {
|
||||
// 刷新视图
|
||||
if (window.RbViewPage) window.RbViewPage.reload()
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
RbFormModal.create(editProps, true)
|
||||
})
|
||||
}}>
|
||||
<i className="icon zmdi zmdi-edit mr-1" />
|
||||
{$L('编辑')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount = () => this.getNextStep()
|
||||
reload = () => this.getNextStep()
|
||||
|
||||
|
@ -632,7 +671,7 @@ class ApprovalApproveForm extends ApprovalUsersForm {
|
|||
}
|
||||
// v4.0
|
||||
if (this.state.remarkReq >= 1 && $empty(data.remark)) {
|
||||
RbHighbar.createl('请填写批注')
|
||||
RbHighbar.createl('请输入批注')
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -419,7 +419,7 @@ class BatchUpdate extends BatchOperator {
|
|||
<span className="badge badge-warning">{field.label}</span>
|
||||
</div>
|
||||
<div className="col-2 pl-0 pr-0">
|
||||
<span className="badge badge-warning">{BUE_OPTYPES[item.op]}</span>
|
||||
<span className="badge badge-warning">{BU_OPS[item.op]}</span>
|
||||
</div>
|
||||
<div className="col-6">
|
||||
{item.op !== 'NULL' && <span className="badge badge-warning text-break text-left">{FieldValueSet.formatFieldText(item.value, field)}</span>}
|
||||
|
@ -433,7 +433,7 @@ class BatchUpdate extends BatchOperator {
|
|||
})}
|
||||
</div>
|
||||
<div className="batch-editor">
|
||||
{this.state.fields && <BatchUpdateEditor ref={(c) => (this._editor = c)} fields={this.state.fields} entity={this.props.entity} />}
|
||||
{this.state.fields && <BatchUpdateEntry ref={(c) => (this._buEntry = c)} fields={this.state.fields} entity={this.props.entity} />}
|
||||
<div className="mt-1">
|
||||
<button className="btn btn-primary btn-sm btn-outline" onClick={() => this.addItem()} type="button">
|
||||
+ {$L('添加')}
|
||||
|
@ -446,7 +446,7 @@ class BatchUpdate extends BatchOperator {
|
|||
}
|
||||
|
||||
addItem() {
|
||||
const item = this._editor.buildItem()
|
||||
const item = this._buEntry.buildItem()
|
||||
if (!item) return
|
||||
|
||||
const contents = this.state.updateContents || []
|
||||
|
@ -537,19 +537,22 @@ class BatchUpdate extends BatchOperator {
|
|||
}
|
||||
}
|
||||
|
||||
// ~ 批量修改编辑器
|
||||
|
||||
const BUE_OPTYPES = {
|
||||
const BU_OPS = {
|
||||
SET: $L('修改为'),
|
||||
NULL: $L('置空'),
|
||||
// TODO 支持更多修改模式
|
||||
// 250813 也可以触发器修改
|
||||
// PREFIX: $L('前添加'),
|
||||
// SUFFIX: $L('后添加'),
|
||||
// REPLACE: $L('替换'),
|
||||
// PLUS: $L('加上'),
|
||||
// MINUS: $L('减去'),
|
||||
// MULTIPLY: $L('乘以'),
|
||||
// DIVIDE: $L('除以'),
|
||||
}
|
||||
|
||||
class BatchUpdateEditor extends React.Component {
|
||||
// 批量修改编辑器
|
||||
class BatchUpdateEntry extends React.Component {
|
||||
state = { ...this.props, selectOp: 'SET' }
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -598,8 +601,8 @@ class BatchUpdateEditor extends React.Component {
|
|||
</div>
|
||||
<div className="col-2 pl-0 pr-0">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$op = c)}>
|
||||
<option value="SET">{BUE_OPTYPES['SET']}</option>
|
||||
<option value="NULL">{BUE_OPTYPES['NULL']}</option>
|
||||
<option value="SET">{BU_OPS['SET']}</option>
|
||||
<option value="NULL">{BU_OPS['NULL']}</option>
|
||||
</select>
|
||||
<span className="text-muted">{$L('修改方式')}</span>
|
||||
</div>
|
||||
|
@ -636,7 +639,10 @@ class BatchUpdateEditor extends React.Component {
|
|||
}
|
||||
|
||||
data.value = this._FieldValue.val()
|
||||
if (!data.value) {
|
||||
if (data.value === false) {
|
||||
// 格式不正确
|
||||
return null
|
||||
} else if (!data.value) {
|
||||
RbHighbar.create($L('请填写新值'))
|
||||
return null
|
||||
} else {
|
||||
|
@ -661,10 +667,11 @@ class BatchApprove extends BatchOperator {
|
|||
}
|
||||
|
||||
renderOperator() {
|
||||
const approveState = ~~this.state.approveState
|
||||
return (
|
||||
<div>
|
||||
<div className="form-group">
|
||||
<label className="text-bold">{$L('审批结果')}</label>
|
||||
<label className="text-bold">{$L('审批方式')}</label>
|
||||
<div>
|
||||
<label className="custom-control custom-control-sm custom-radio custom-control-inline mb-0">
|
||||
<input className="custom-control-input" type="radio" name="approveState" value="10" onClick={this.handleChange} />
|
||||
|
@ -674,36 +681,73 @@ class BatchApprove extends BatchOperator {
|
|||
<input className="custom-control-input" type="radio" name="approveState" value="11" onClick={this.handleChange} />
|
||||
<span className="custom-control-label">{$L('驳回')}</span>
|
||||
</label>
|
||||
<label className="custom-control custom-control-sm custom-radio custom-control-inline mb-0">
|
||||
<input className="custom-control-input" type="radio" name="approveState" value="1" onClick={this.handleChange} />
|
||||
<span className="custom-control-label">{$L('提交')}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
|
||||
<div className={`form-group ${approveState >= 10 ? '' : 'hide'}`}>
|
||||
<label className="text-bold">{$L('批注')}</label>
|
||||
<textarea className="form-control form-control-sm row2x" name="approveRemark" placeholder={$L('输入批注 (可选)')} maxLength="600" onChange={this.handleChange} />
|
||||
<textarea className="form-control form-control-sm row2x" name="approveRemark" placeholder={$L('输入批注')} maxLength="600" onChange={this.handleChange} />
|
||||
</div>
|
||||
<RbAlertBox message={$L('仅处于待你审批,且允许批量审批的记录才能审批成功')} type="info" className="mb-0" />
|
||||
<div className={`form-group ${approveState === 1 ? '' : 'hide'}`}>
|
||||
<label className="text-bold">{$L('审批流程')}</label>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$useApproval = c)} />
|
||||
</div>
|
||||
|
||||
<RbAlertBox message={$L('仅允许你审批或提交的记录,才能审批成功')} type="info" className="mb-0" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
// super.componentDidMount()
|
||||
|
||||
$.get(`/app/entity/approval/alist?entity=${wpc.entity[0]}&valid=true`, (res) => {
|
||||
$(this._$useApproval).select2({
|
||||
placeholder: $L('无'),
|
||||
allowClear: false,
|
||||
language: {
|
||||
noResults: () => $L('无适用流程'),
|
||||
},
|
||||
data: res.data || [],
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
handleConfirm() {
|
||||
if (rb.commercial < 10) {
|
||||
RbHighbar.error(WrapHtml($L('免费版不支持批量审批功能 [(查看详情)](https://getrebuild.com/docs/rbv-features)')))
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.state.approveState) return RbHighbar.create($L('请选择审批结果'))
|
||||
if (!this.state.approveState) return RbHighbar.create($L('请选择审批方式'))
|
||||
|
||||
const _data = {
|
||||
queryData: this.getQueryData(),
|
||||
approveContent: {
|
||||
state: this.state.approveState,
|
||||
remark: this.state.approveRemark,
|
||||
remark: this.state.approveRemark || null,
|
||||
approvalId: $val(this._$useApproval) || null,
|
||||
},
|
||||
}
|
||||
if (~~this.state.approveState === 1) {
|
||||
if (!_data.approveContent.approvalId) {
|
||||
RbHighbar.create($L('请选择审批流程'))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if ($empty(this.state.approveRemark)) {
|
||||
RbHighbar.create($L('请输入批注'))
|
||||
return
|
||||
}
|
||||
}
|
||||
if (rb.env === 'dev') console.log(JSON.stringify(_data))
|
||||
|
||||
const that = this
|
||||
RbAlert.create(<b>{$L('请再次确认审批数据范围和审批结果。开始审批吗?')}</b>, {
|
||||
RbAlert.create(<b>{$L('请再次确认审批数据范围和审批方式。开始审批吗?')}</b>, {
|
||||
onConfirm: function () {
|
||||
this.hide()
|
||||
that.disabled(true, true)
|
||||
|
@ -722,6 +766,7 @@ class BatchApprove extends BatchOperator {
|
|||
}
|
||||
})
|
||||
},
|
||||
countdown: 5,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -838,16 +883,16 @@ const RbListCommon = {
|
|||
RbListPage.init(wpc.listConfig, entity, wpc.privileges)
|
||||
if (wpc.advFilter !== false) AdvFilters.init('.adv-search', entity[0])
|
||||
|
||||
const newProps = { title: $L('新建%s', entity[1]), entity: entity[0], icon: entity[2] }
|
||||
const newProps = { title: $L('新建%s', entity[1]), entity: entity[0], icon: entity[2], showExtraButton: true }
|
||||
const $new = $('.J_new')
|
||||
.attr('disabled', false)
|
||||
.on('click', () => RbFormModal.create(newProps))
|
||||
if (wpc.formsAttr) {
|
||||
$new.next().removeClass('hide')
|
||||
const $nn = $new.next().next()
|
||||
const $next = $new.next().next()
|
||||
wpc.formsAttr.map((n) => {
|
||||
$(`<a class="dropdown-item" data-id="${n.id}">${n.name || $L('默认布局')}</a>`)
|
||||
.appendTo($nn)
|
||||
.appendTo($next)
|
||||
.on('click', () => RbFormModal.create({ ...newProps, specLayout: n.id }, true))
|
||||
})
|
||||
} else {
|
||||
|
|
|
@ -39,10 +39,7 @@ const RbListPage = {
|
|||
$('.J_edit').on('click', () => {
|
||||
const ids = this._RbList.getSelectedIds()
|
||||
if (ids.length >= 1) {
|
||||
const _entity = entity[0]
|
||||
const editProps = { id: ids[0], title: $L('编辑%s', entity[1]), entity: _entity, icon: entity[2] }
|
||||
if ((window.__LAB40_EDIT_PROVIDERS || {})[_entity]) window.__LAB40_EDIT_PROVIDERS[_entity](editProps)
|
||||
else RbFormModal.create(editProps, true)
|
||||
RbFormModal.create({ id: ids[0], title: $L('编辑%s', entity[1]), entity: entity[0], icon: entity[2], showExtraButton: true }, true)
|
||||
}
|
||||
})
|
||||
$('.J_delete').on('click', () => {
|
||||
|
@ -111,7 +108,7 @@ class RbViewModal extends React.Component {
|
|||
super(props)
|
||||
this.state = { ...props, inLoad: true, isHide: true, destroy: false }
|
||||
|
||||
this._mcWidth = this.props.subView === true ? 1344 : 1404
|
||||
this._mcWidth = props.subView === true ? 1344 : 1404
|
||||
if ($(window).width() < 1464) this._mcWidth -= 184
|
||||
}
|
||||
|
||||
|
@ -122,7 +119,14 @@ class RbViewModal extends React.Component {
|
|||
<div className="modal-dialog">
|
||||
<div className="modal-content" style={{ width: this._mcWidth }}>
|
||||
<div className={`modal-body iframe rb-loading ${this.state.inLoad === true && 'rb-loading-active'}`}>
|
||||
<iframe ref={(c) => (this._iframe = c)} className={this.state.isHide ? 'invisible' : ''} src={this.state.showAfterUrl || 'about:blank'} frameBorder="0" scrolling="no" />
|
||||
<iframe
|
||||
data-subview={this.props.subView || false}
|
||||
ref={(c) => (this._iframe = c)}
|
||||
className={this.state.isHide ? 'invisible' : ''}
|
||||
src={this.state.showAfterUrl || 'about:blank'}
|
||||
frameBorder="0"
|
||||
scrolling="no"
|
||||
/>
|
||||
<RbSpinner />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -134,7 +134,7 @@ class RbFormModal extends React.Component {
|
|||
</RbForm>
|
||||
)
|
||||
|
||||
that.setState({ formComponent: FORM, alertMessage: formModel.readonlyMessage || null }, () => {
|
||||
that.setState({ formComponent: FORM, alertMessage: formModel.readonlywMessage || formModel.readonlyMessage || null }, () => {
|
||||
that.setState({ inLoad: false })
|
||||
if (window.FrontJS) {
|
||||
window.FrontJS.Form._trigger('open', [formModel])
|
||||
|
@ -254,6 +254,12 @@ class RbFormModal extends React.Component {
|
|||
* @param {*} forceNew
|
||||
*/
|
||||
static create(props, forceNew) {
|
||||
// 自定义编辑
|
||||
if ((window.__LAB40_EDIT_PROVIDERS || {})[props.entity]) {
|
||||
window.__LAB40_EDIT_PROVIDERS[props.entity](props, forceNew)
|
||||
return
|
||||
}
|
||||
|
||||
// `__CURRENT35`, `__HOLDER` 可能已 unmount
|
||||
const that = this
|
||||
if (forceNew === true) {
|
||||
|
@ -559,7 +565,7 @@ class RbForm extends React.Component {
|
|||
let moreActions = []
|
||||
// 添加明细
|
||||
if (props.rawModel.mainMeta) {
|
||||
if (parentProps._nextAddDetail) {
|
||||
if (parentProps.nextAddDetail) {
|
||||
moreActions.push(
|
||||
<a key="Action101" className="dropdown-item" onClick={() => this.post(RbForm.NEXT_NEWDETAIL)}>
|
||||
{$L('保存并添加')}
|
||||
|
@ -567,10 +573,8 @@ class RbForm extends React.Component {
|
|||
)
|
||||
}
|
||||
} else {
|
||||
if (parentProps._noExtraButton) {
|
||||
// 无扩展按钮
|
||||
} else {
|
||||
// 保存并...
|
||||
// 保存并...
|
||||
if (parentProps.showExtraButton) {
|
||||
if (props.rawModel.hadApproval && window.ApprovalSubmitForm) {
|
||||
moreActions.push(
|
||||
<a key="Action103" className="dropdown-item" onClick={() => this.post(RbForm.NEXT_SUBMIT37)}>
|
||||
|
@ -896,12 +900,12 @@ class RbForm extends React.Component {
|
|||
// 提交前调用
|
||||
_postBeforeExec(data) {
|
||||
if (typeof this._postBefore === 'function') {
|
||||
let ret = this._postBefore(data, this)
|
||||
const ret = this._postBefore(data, this)
|
||||
if (ret === false) return false
|
||||
}
|
||||
|
||||
if (window.FrontJS) {
|
||||
let ret = window.FrontJS.Form._trigger('saveBefore', [data, this])
|
||||
const ret = window.FrontJS.Form._trigger('saveBefore', [data, this])
|
||||
if (ret === false) return false
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class RbViewForm extends React.Component {
|
|||
this.onViewEditable = this.props.onViewEditable
|
||||
if (this.onViewEditable) this.onViewEditable = wpc.onViewEditable !== false
|
||||
if (window.__LAB_VIEWEDITABLE === false) this.onViewEditable = false
|
||||
|
||||
// temp for `saveSingleFieldValue`
|
||||
this.__FormData = {}
|
||||
this._verticalLayout42 = window.__LAB_VERTICALLAYOUT
|
||||
|
@ -46,6 +47,7 @@ class RbViewForm extends React.Component {
|
|||
}
|
||||
|
||||
let hadApproval = res.data.hadApproval
|
||||
if (hadApproval === 2 || hadApproval === 10) this.onViewEditable = false // be:4.2
|
||||
let hadAlert = null
|
||||
let hadSop = res.data.hadSop && rb.commercial > 1
|
||||
if (wpc.type === 'DetailView') {
|
||||
|
@ -503,10 +505,7 @@ class EntityRelatedList extends RelatedList {
|
|||
|
||||
_handleEdit(e, id) {
|
||||
$stopEvent(e, true)
|
||||
const _entity = this.__entity
|
||||
const editProps = { id: id, entity: _entity, title: $L('编辑%s', this.props.entity2[0]), icon: this.props.entity2[1] }
|
||||
if ((window.__LAB40_EDIT_PROVIDERS || {})[_entity]) window.__LAB40_EDIT_PROVIDERS[_entity](editProps)
|
||||
else RbFormModal.create(editProps, true)
|
||||
RbFormModal.create({ id: id, entity: this.__entity, title: $L('编辑%s', this.props.entity2[0]), icon: this.props.entity2[1] }, true)
|
||||
}
|
||||
|
||||
_handleView(e) {
|
||||
|
@ -663,10 +662,7 @@ const RbViewPage = {
|
|||
})
|
||||
|
||||
$('.J_edit').on('click', () => {
|
||||
const _entity = entity[0]
|
||||
const editProps = { id: id, title: $L('编辑%s', entity[1]), entity: _entity, icon: entity[2] }
|
||||
if ((window.__LAB40_EDIT_PROVIDERS || {})[_entity]) window.__LAB40_EDIT_PROVIDERS[_entity](editProps)
|
||||
else RbFormModal.create(editProps, true)
|
||||
RbFormModal.create({ id: id, title: $L('编辑%s', entity[1]), entity: entity[0], icon: entity[2] }, true)
|
||||
})
|
||||
$('.J_assign').on('click', () => DlgAssign.create({ entity: entity[0], ids: [id] }))
|
||||
$('.J_share').on('click', () => DlgShare.create({ entity: entity[0], ids: [id] }))
|
||||
|
@ -674,7 +670,7 @@ const RbViewPage = {
|
|||
$('.J_add-detail-menu>a').on('click', function () {
|
||||
const iv = { $MAINID$: id }
|
||||
const $this = $(this)
|
||||
RbFormModal.create({ title: $L('添加%s', $this.data('label')), entity: $this.data('entity'), icon: $this.data('icon'), initialValue: iv, _nextAddDetail: true })
|
||||
RbFormModal.create({ title: $L('添加%s', $this.data('label')), entity: $this.data('entity'), icon: $this.data('icon'), initialValue: iv, nextAddDetail: true })
|
||||
})
|
||||
|
||||
if (wpc.transformTos && wpc.transformTos.length > 0) {
|
||||
|
@ -928,7 +924,13 @@ const RbViewPage = {
|
|||
if (entity.length > 1) iv[entity[1]] = that.__id
|
||||
else iv[`&${that.__entity[0]}`] = that.__id
|
||||
|
||||
RbFormModal.create({ title: $L('新建%s', item._entityLabel || item.entityLabel), entity: entity[0], icon: item.icon, initialValue: iv, _noExtraButton: true })
|
||||
const newProps = {
|
||||
title: $L('新建%s', item._entityLabel || item.entityLabel),
|
||||
entity: entity[0],
|
||||
icon: item.icon,
|
||||
initialValue: iv,
|
||||
}
|
||||
RbFormModal.create(newProps)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1035,13 +1037,17 @@ $(document).ready(() => {
|
|||
$('.J_home').removeClass('hide')
|
||||
}
|
||||
// v4.2
|
||||
if (parent && parent.RbListPage && parent.RbListPage._RbList && parent.RbListPage._RbList.jumpView) {
|
||||
$('.J_record-next')
|
||||
.removeClass('hide')
|
||||
.on('click', () => parent.RbListPage._RbList.jumpView(1))
|
||||
$('.J_record-prev')
|
||||
.removeClass('hide')
|
||||
.on('click', () => parent.RbListPage._RbList.jumpView(-1))
|
||||
if (window.frameElement && parent && parent.RbListPage && parent.RbListPage._RbList && parent.RbListPage._RbList.jumpView) {
|
||||
if ($(window.frameElement).data('subview')) {
|
||||
// SubView
|
||||
} else {
|
||||
$('.J_record-next')
|
||||
.removeClass('hide')
|
||||
.on('click', () => parent.RbListPage._RbList.jumpView(1))
|
||||
$('.J_record-prev')
|
||||
.removeClass('hide')
|
||||
.on('click', () => parent.RbListPage._RbList.jumpView(-1))
|
||||
}
|
||||
}
|
||||
|
||||
// iframe 点击穿透
|
||||
|
|
|
@ -41,6 +41,10 @@ class FieldValueSet extends React.Component {
|
|||
)
|
||||
}
|
||||
|
||||
if (field.type === 'NTEXT') {
|
||||
return <textarea className="form-control form-control-sm row1x" ref={(c) => (this._$value = c)} key={field.name}></textarea>
|
||||
}
|
||||
|
||||
return <input className="form-control form-control-sm" placeholder={this.props.placeholder} ref={(c) => (this._$value = c)} key={field.name} maxLength="255" />
|
||||
}
|
||||
|
||||
|
|
|
@ -610,7 +610,7 @@ var _initGlobalCreate = function () {
|
|||
var $item = $('<a class="dropdown-item"><i class="icon zmdi zmdi-' + this.icon + '"></i>' + this.entityLabel + '</a>').appendTo($gc)
|
||||
var _this = this
|
||||
$item.on('click', function () {
|
||||
RbFormModal.create({ title: $L('新建%s', _this.entityLabel), entity: _this.entity, icon: _this.icon })
|
||||
RbFormModal.create({ title: $L('新建%s', _this.entityLabel), entity: _this.entity, icon: _this.icon, showExtraButton: true })
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -1479,3 +1479,14 @@ function $focus2End(el, delay) {
|
|||
el.setSelectionRange(len, len)
|
||||
}, delay || 100)
|
||||
}
|
||||
|
||||
// 获取实体元数据
|
||||
function $fetchMetaInfo(name, cb) {
|
||||
$.get('/commons/metadata/meta-info?name=' + $encode(name), function (res) {
|
||||
if (res.error_code === 0) {
|
||||
typeof cb === 'function' && cb(res.data || {})
|
||||
} else {
|
||||
RbHighbar.error(res.error_msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
<option value="macarons">MACARONS</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="hide bosskey-show-- J_opt-INDEX J_opt-LINE J_opt-BAR J_opt-BAR2 J_opt-BAR3 J_opt-PIE J_opt-FUNNEL J_opt-RADAR J_opt-SCATTER">
|
||||
<div class="hide bosskey-show-- J_opt-TABLE J_opt-INDEX J_opt-LINE J_opt-BAR J_opt-BAR2 J_opt-BAR3 J_opt-PIE J_opt-FUNNEL J_opt-RADAR J_opt-SCATTER">
|
||||
<label style="color: #444; margin-bottom: 8px">[[${bundle.L('背景色')}]]</label>
|
||||
<div id="useBgcolor" class="rbcolors">
|
||||
<a class="default" th:title="${bundle.L('默认')}"></a>
|
||||
|
|
Loading…
Add table
Reference in a new issue