mirror of
https://github.com/getrebuild/rebuild.git
synced 2025-09-08 07:36:52 +08:00
Add editable record mode to approval flow nodes
This commit is contained in:
parent
76431d61c5
commit
efd2a5fd67
6 changed files with 114 additions and 56 deletions
|
@ -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
|
||||
|
@ -167,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)) {
|
||||
|
@ -248,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<>();
|
||||
|
@ -292,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) {
|
||||
|
@ -322,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;
|
||||
|
|
|
@ -207,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;
|
||||
|
|
|
@ -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,
|
||||
|
@ -748,6 +750,10 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
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 {
|
||||
|
|
|
@ -224,7 +224,7 @@ class SimpleNode extends NodeSpec {
|
|||
// 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() {
|
||||
|
@ -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}
|
||||
|
|
Loading…
Add table
Reference in a new issue