mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 07:25:54 +08:00
Form area and break 52 (#554)
* form line collapsed and breaked * better AdvControl * view approval form * view form readonly * tag init
This commit is contained in:
parent
c95de134c6
commit
7e53852ea9
|
@ -112,6 +112,7 @@ public class FormsBuilder extends FormsManager {
|
|||
final Entity hasMainEntity = entityMeta.getMainEntity();
|
||||
// 审批流程(状态)
|
||||
ApprovalState approvalState;
|
||||
String readonlyMessage = null;
|
||||
|
||||
// 判断表单权限
|
||||
|
||||
|
@ -123,11 +124,10 @@ public class FormsBuilder extends FormsManager {
|
|||
|
||||
approvalState = EntityHelper.isUnsavedId(mainid) ? null : getHadApproval(hasMainEntity, mainid);
|
||||
if ((approvalState == ApprovalState.PROCESSING || approvalState == ApprovalState.APPROVED)) {
|
||||
return formatModelError(approvalState == ApprovalState.APPROVED
|
||||
readonlyMessage = approvalState == ApprovalState.APPROVED
|
||||
? Language.L("主记录已完成审批,不能添加明细")
|
||||
: Language.L("主记录正在审批中,不能添加明细"));
|
||||
: Language.L("主记录正在审批中,不能添加明细");
|
||||
}
|
||||
|
||||
// 明细无需审批
|
||||
approvalState = null;
|
||||
|
||||
|
@ -161,9 +161,9 @@ public class FormsBuilder extends FormsManager {
|
|||
if (approvalState != null) {
|
||||
String recordType = hasMainEntity == null ? Language.L("记录") : Language.L("主记录");
|
||||
if (approvalState == ApprovalState.APPROVED) {
|
||||
return formatModelError(Language.L("%s已完成审批,禁止编辑", recordType));
|
||||
readonlyMessage = Language.L("%s已完成审批,禁止编辑", recordType);
|
||||
} else if (approvalState == ApprovalState.PROCESSING) {
|
||||
return formatModelError(Language.L("%s正在审批中,禁止编辑", recordType));
|
||||
readonlyMessage = Language.L("%s正在审批中,禁止编辑", recordType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ public class FormsBuilder extends FormsManager {
|
|||
Set<String> roAutosWithout = record == null ? null : Collections.emptySet();
|
||||
for (Object o : elements) {
|
||||
JSONObject field = (JSONObject) o;
|
||||
if (roAutos.contains(field.getString("field"))) {
|
||||
if (roAutos.contains(field.getString("field")) || readonlyMessage != null) {
|
||||
field.put("readonly", true);
|
||||
|
||||
// 前端可收集值
|
||||
|
@ -213,8 +213,7 @@ public class FormsBuilder extends FormsManager {
|
|||
// v3.1
|
||||
if (!entityMeta.getExtraAttrs().getBooleanValue(EasyEntityConfigProps.NOT_COEDITING)) {
|
||||
model.set("detailMeta", EasyMetaFactory.toJSON(entityMeta.getDetailEntity()));
|
||||
model.set("detailsNotEmpty",
|
||||
entityMeta.getExtraAttrs().getBooleanValue(EasyEntityConfigProps.DETAILS_NOTEMPTY));
|
||||
model.set("detailsNotEmpty", entityMeta.getExtraAttrs().getBooleanValue(EasyEntityConfigProps.DETAILS_NOTEMPTY));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,9 +221,8 @@ public class FormsBuilder extends FormsManager {
|
|||
model.set("lastModified", recordData.getDate(EntityHelper.ModifiedOn).getTime());
|
||||
}
|
||||
|
||||
if (approvalState != null) {
|
||||
model.set("hadApproval", approvalState.getState());
|
||||
}
|
||||
if (approvalState != null) model.set("hadApproval", approvalState.getState());
|
||||
if (readonlyMessage != null) model.set("readonlyMessage", readonlyMessage);
|
||||
|
||||
model.set("id", null); // Clean form's ID of config
|
||||
return model.toJSON();
|
||||
|
|
|
@ -41,6 +41,7 @@ public enum DisplayType {
|
|||
N2NREFERENCE(EasyN2NReference.class, "多引用", FieldType.REFERENCE_LIST, -1, null),
|
||||
LOCATION(EasyLocation.class, "位置", FieldType.STRING, 100, null),
|
||||
SIGN(EasySign.class, "签名", FieldType.TEXT, 32767, null, false, true),
|
||||
TAG(EasyTag.class, "标签", FieldType.REFERENCE_LIST, -1, null),
|
||||
|
||||
// 内部
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*!
|
||||
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.core.metadata.easymeta;
|
||||
|
||||
import cn.devezhao.persist4j.Field;
|
||||
import com.rebuild.core.support.general.N2NReferenceSupport;
|
||||
|
||||
/**
|
||||
* @author Zixin
|
||||
* @since 2022/12/12
|
||||
* @see N2NReferenceSupport
|
||||
*/
|
||||
public class EasyTag extends EasyField {
|
||||
private static final long serialVersionUID = -5827184319679918289L;
|
||||
|
||||
protected EasyTag(Field field, DisplayType displayType) {
|
||||
super(field, displayType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertCompatibleValue(Object value, EasyField targetField) {
|
||||
return super.convertCompatibleValue(value, targetField);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object exprDefaultValue() {
|
||||
return super.exprDefaultValue();
|
||||
}
|
||||
}
|
|
@ -11,6 +11,10 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
|
||||
.rb-right-sidebar.field-aside {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.page-aside,
|
||||
.field-aside {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -923,7 +923,8 @@ select.form-control:not([disabled]) {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.form-layout .form-line {
|
||||
.form-layout .form-line,
|
||||
.form-layout .form-line-breaked {
|
||||
width: 100%;
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
|
@ -946,9 +947,10 @@ select.form-control:not([disabled]) {
|
|||
.rbform-alert {
|
||||
margin: -20px -20px 20px;
|
||||
text-align: center;
|
||||
padding: 0.6rem;
|
||||
padding: 0.4rem;
|
||||
border-radius: 0;
|
||||
color: #fff;
|
||||
color: #836203;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
|
@ -2007,7 +2009,7 @@ th.column-fixed {
|
|||
left: 10px;
|
||||
margin: -11px 0 0;
|
||||
padding: 3px 5px 3px 5px;
|
||||
color: #777;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.form-line.hover fieldset legend {
|
||||
|
@ -2018,6 +2020,12 @@ th.column-fixed {
|
|||
color: #4285f4;
|
||||
}
|
||||
|
||||
.form-line-breaked {
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-primary.btn-outline,
|
||||
.btn-primary.btn-outline[disabled] {
|
||||
background-color: #fff;
|
||||
|
@ -4342,7 +4350,7 @@ html.external-auth .auth-body.must-center .login {
|
|||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn.btn-light:hover {
|
||||
.btn.btn-light:not(:disabled):hover {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
|
|
|
@ -280,7 +280,10 @@ const _handlePicklist = function (dt) {
|
|||
})
|
||||
if (res.data.length > 5) $('#picklist-items').parent().removeClass('autoh')
|
||||
})
|
||||
$('.J_picklist-edit').on('click', () => RbModal.create(`/p/admin/metadata/picklist-editor?entity=${wpc.entityName}&field=${wpc.fieldName}&multi=${dt === 'MULTISELECT'}`, $L('选项配置')))
|
||||
|
||||
$('.J_picklist-edit').on('click', () => {
|
||||
RbModal.create(`/p/admin/metadata/picklist-editor?entity=${wpc.entityName}&field=${wpc.fieldName}&multi=${dt === 'MULTISELECT'}`, $L('配置选项'))
|
||||
})
|
||||
}
|
||||
|
||||
const _handleSeries = function () {
|
||||
|
|
|
@ -22,10 +22,11 @@ const FIELD_TYPES = {
|
|||
'PICKLIST': [$L('下拉列表'), 'mdi-form-select'],
|
||||
'CLASSIFICATION': [$L('分类'), 'mdi-form-dropdown'],
|
||||
'MULTISELECT': [$L('多选'), 'mdi-format-list-checks'],
|
||||
'TAG': [$L('标签'), 'mdi-tag-outline'],
|
||||
'REFERENCE': [$L('引用'), 'mdi-feature-search-outline'],
|
||||
'N2NREFERENCE': [$L('多引用'), 'mdi-text-box-search-outline'],
|
||||
'FILE': [$L('附件'), 'mdi-attachment'],
|
||||
'IMAGE': [$L('图片'), 'mdi-image'],
|
||||
'IMAGE': [$L('图片'), 'mdi-image-outline'],
|
||||
'AVATAR': [$L('头像'), 'mdi-account-box-outline'],
|
||||
'BARCODE': [$L('二维码'), 'mdi-qrcode'],
|
||||
'LOCATION': [$L('位置'), 'mdi-map-marker'],
|
||||
|
|
|
@ -16,7 +16,7 @@ const COLSPANS = {
|
|||
9: 'w-33',
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$(document).ready(() => {
|
||||
$.get(`../list-field?entity=${wpc.entityName}`, function (res) {
|
||||
const validFields = {},
|
||||
configFields = []
|
||||
|
@ -24,26 +24,17 @@ $(document).ready(function () {
|
|||
configFields.push(this.field)
|
||||
})
|
||||
|
||||
const $advControls = $('#adv-control tbody')
|
||||
const template = $advControls.find('tr').html()
|
||||
$advControls.find('tr').remove()
|
||||
|
||||
$(res.data).each(function () {
|
||||
validFields[this.fieldName] = this
|
||||
if (configFields.includes(this.fieldName) === false) render_unset(this)
|
||||
|
||||
// Adv control
|
||||
const $control = $(`<tr data-field="${this.fieldName}">${template}</tr>`).appendTo($advControls)
|
||||
$control.find('td:eq(0)').text(this.fieldLabel)
|
||||
const $req = $control.find('td:eq(2)')
|
||||
if (this.builtin) $req.empty()
|
||||
else if (!this.nullable) $req.find('input').attr({ disabled: true, checked: true })
|
||||
if (!configFields.includes(this.fieldName)) render_unset(this)
|
||||
})
|
||||
|
||||
AdvControl.init()
|
||||
|
||||
$(wpc.formConfig.elements).each(function () {
|
||||
const field = validFields[this.field]
|
||||
if (this.field === DIVIDER_LINE) {
|
||||
render_item({ fieldName: this.field, fieldLabel: this.label || '', colspan: 4 })
|
||||
render_item({ fieldName: this.field, fieldLabel: this.label || '', colspan: 4, collapsed: this.collapsed, breaked: this.breaked })
|
||||
} else if (!field) {
|
||||
const $item = $(`<div class="dd-item"><div class="dd-handle J_field J_missed"><span class="text-danger">[${this.field.toUpperCase()}] ${$L('字段已删除')}</span></div></div>`).appendTo(
|
||||
'.form-preview'
|
||||
|
@ -53,8 +44,7 @@ $(document).ready(function () {
|
|||
$item.remove()
|
||||
})
|
||||
} else {
|
||||
render_item({ ...field, isFull: this.isFull || false, colspan: this.colspan, tip: this.tip || null, height: this.height || null })
|
||||
AdvControl.set(this)
|
||||
render_item({ ...field, ...this })
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -67,7 +57,7 @@ $(document).ready(function () {
|
|||
.disableSelection()
|
||||
})
|
||||
|
||||
$('.J_add-divider').on('click', function () {
|
||||
$('.J_add-divider').on('click', () => {
|
||||
$('.nav-tabs-classic a[href="#form-design"]').tab('show')
|
||||
render_item({ fieldName: DIVIDER_LINE, fieldLabel: '', colspan: 4 })
|
||||
})
|
||||
|
@ -112,6 +102,8 @@ $(document).ready(function () {
|
|||
if (item.field === DIVIDER_LINE) {
|
||||
item.colspan = 4
|
||||
item.label = $this.find('span').text() || ''
|
||||
item.collapsed = $isTrue($this.attr('data-collapsed'))
|
||||
item.breaked = $isTrue($this.attr('data-breaked'))
|
||||
} else {
|
||||
item.colspan = 2 // default
|
||||
if ($this.parent().hasClass('w-100')) item.colspan = 4
|
||||
|
@ -126,7 +118,7 @@ $(document).ready(function () {
|
|||
const height = $this.attr('data-height')
|
||||
if (height) item.height = height
|
||||
|
||||
AdvControl.append(item)
|
||||
AdvControl.cfgAppend(item)
|
||||
}
|
||||
formElements.push(item)
|
||||
})
|
||||
|
@ -184,15 +176,17 @@ const render_item = function (data) {
|
|||
`<div class="dd-handle J_field" data-field="${data.fieldName}" data-label="${data.fieldLabel}"><span _title="${isDivider ? $L('分栏') : 'FIELD'}">${data.fieldLabel}</span></div>`
|
||||
).appendTo($item)
|
||||
|
||||
const $action = $('<div class="dd-action"></div>').appendTo($handle)
|
||||
// 字段
|
||||
if (data.displayType) {
|
||||
if (data.creatable === false) $handle.addClass('readonly')
|
||||
else if (data.nullable === false) $handle.addClass('not-nullable')
|
||||
|
||||
// 填写提示
|
||||
if (data.tip) $('<i class="J_tip zmdi zmdi-info-outline"></i>').appendTo($handle.find('span')).attr('title', data.tip)
|
||||
// 高度
|
||||
// 长文本高度
|
||||
if (data.height) $handle.attr('data-height', data.height)
|
||||
|
||||
const $action = $('<div class="dd-action"></div>').appendTo($handle)
|
||||
if (data.displayType) {
|
||||
$(`<span class="ft">${data.displayType}</span>`).appendTo($item)
|
||||
$(`<a class="mr-1 colspan" title="${$L('宽度')}" data-toggle="dropdown"><i class="zmdi zmdi-view-column"></i></a>`).appendTo($action)
|
||||
|
||||
|
@ -246,26 +240,37 @@ const render_item = function (data) {
|
|||
render_unset(data)
|
||||
$item.remove()
|
||||
})
|
||||
|
||||
AdvControl.set({ ...data })
|
||||
}
|
||||
|
||||
if (isDivider) {
|
||||
$item.addClass('divider')
|
||||
const $handle = $item.find('.dd-handle').attr({
|
||||
'data-collapsed': data.collapsed,
|
||||
'data-breaked': data.breaked,
|
||||
})
|
||||
|
||||
$(`<a title="${$L('修改')}"><i class="zmdi zmdi-edit"></i></a>`)
|
||||
.appendTo($action)
|
||||
.on('click', function () {
|
||||
.on('click', () => {
|
||||
const _onConfirm = function (nv) {
|
||||
$item.find('.dd-handle span').text(nv.dividerName || '')
|
||||
$handle.attr('data-collapsed', $isTrue(nv.collapsed))
|
||||
$handle.attr('data-breaked', $isTrue(nv.breaked))
|
||||
}
|
||||
|
||||
const ov = $item.find('.dd-handle span').text()
|
||||
renderRbcomp(<DlgEditDivider onConfirm={_onConfirm} dividerName={ov || ''} />)
|
||||
const ov = {
|
||||
dividerName: $item.find('.dd-handle span').text() || '',
|
||||
collapsed: $handle.attr('data-collapsed'),
|
||||
breaked: $handle.attr('data-breaked'),
|
||||
}
|
||||
renderRbcomp(<DlgEditDivider onConfirm={_onConfirm} {...ov} />)
|
||||
})
|
||||
|
||||
$(`<a title="${$L('移除')}"><i class="zmdi zmdi-close"></i></a>`)
|
||||
.appendTo($action)
|
||||
.on('click', function () {
|
||||
$item.remove()
|
||||
})
|
||||
.on('click', () => $item.remove())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -344,8 +349,8 @@ class DlgEditField extends RbAlert {
|
|||
}
|
||||
|
||||
handleChange = (e) => {
|
||||
let target = e.target
|
||||
let s = {}
|
||||
const target = e.target
|
||||
const s = {}
|
||||
s[target.name] = target.type === 'checkbox' ? target.checked : target.value
|
||||
this.setState(s)
|
||||
}
|
||||
|
@ -369,6 +374,16 @@ class DlgEditDivider extends DlgEditField {
|
|||
<label>{$L('分栏名称')}</label>
|
||||
<input type="text" className="form-control form-control-sm" name="dividerName" value={this.state.dividerName || ''} onChange={this.handleChange} placeholder={$L('输入分栏名称')} />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mt-0 mb-0">
|
||||
<input className="custom-control-input" type="checkbox" defaultChecked={$isTrue(this.props.collapsed)} name="collapsed" onChange={this.handleChange} />
|
||||
<span className="custom-control-label">{$L('默认收起')}</span>
|
||||
</label>
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mt-0 mb-0 bosskey-show">
|
||||
<input className="custom-control-input" type="checkbox" defaultChecked={$isTrue(this.props.breaked)} name="breaked" onChange={this.handleChange} />
|
||||
<span className="custom-control-label">{$L('仅用于断行')}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="form-group mb-2">
|
||||
<button type="button" className="btn btn-primary" onClick={this._onConfirm}>
|
||||
{$L('确定')}
|
||||
|
@ -396,22 +411,33 @@ const add2Layout = function (fieldName) {
|
|||
|
||||
// 高级控制
|
||||
const AdvControl = {
|
||||
$controls: $('#adv-control tbody'),
|
||||
$tbody: $('#adv-control tbody'),
|
||||
|
||||
append: function (item) {
|
||||
this.$controls.find(`tr[data-field="${item.field}"] input`).each(function () {
|
||||
init() {
|
||||
this._template = this.$tbody.find('tr').html()
|
||||
this.$tbody.find('tr').remove()
|
||||
},
|
||||
|
||||
set: function (field) {
|
||||
const $c = $(`<tr data-field="${field.fieldName}">${this._template}</tr>`).appendTo(this.$tbody)
|
||||
$c.find('td:eq(0)').text(field.fieldLabel)
|
||||
const $req = $c.find('td:eq(2)')
|
||||
if (field.builtin) $req.empty()
|
||||
else if (!field.nullable) $req.find('input').attr({ disabled: true, checked: true })
|
||||
|
||||
this.$tbody.find(`tr[data-field="${field.fieldName}"] input`).each(function () {
|
||||
const $this = $(this)
|
||||
if ($this.prop('disabled')) return
|
||||
const v = field[$this.attr('name')]
|
||||
if (v === true || v === false) $this.attr('checked', v)
|
||||
})
|
||||
},
|
||||
|
||||
cfgAppend: function (item) {
|
||||
this.$tbody.find(`tr[data-field="${item.field}"] input`).each(function () {
|
||||
const $this = $(this)
|
||||
if ($this.prop('disabled')) return
|
||||
item[$this.attr('name')] = $this.prop('checked')
|
||||
})
|
||||
},
|
||||
|
||||
set: function (item) {
|
||||
this.$controls.find(`tr[data-field="${item.field}"] input`).each(function () {
|
||||
const $this = $(this)
|
||||
if ($this.prop('disabled')) return
|
||||
const v = item[$this.attr('name')]
|
||||
if (v === true || v === false) $this.attr('checked', v)
|
||||
})
|
||||
},
|
||||
}
|
||||
|
|
|
@ -115,14 +115,14 @@ class RbFormModal extends React.Component {
|
|||
|
||||
const formModel = res.data
|
||||
const FORM = (
|
||||
<RbForm entity={entity} id={id} rawModel={formModel} $$$parent={this}>
|
||||
<RbForm entity={entity} id={id} rawModel={formModel} $$$parent={this} readonly={!!formModel.readonlyMessage}>
|
||||
{formModel.elements.map((item) => {
|
||||
return detectElement(item, entity)
|
||||
})}
|
||||
</RbForm>
|
||||
)
|
||||
|
||||
this.setState({ formComponent: FORM }, () => {
|
||||
this.setState({ formComponent: FORM, alertMessage: formModel.readonlyMessage || null }, () => {
|
||||
this.setState({ inLoad: false })
|
||||
if (window.FrontJS) {
|
||||
window.FrontJS.Form._trigger('open', [res.data])
|
||||
|
@ -244,8 +244,11 @@ class RbForm extends React.Component {
|
|||
|
||||
this.isNew = !props.id
|
||||
|
||||
this._postBefore = props.postBefore || props.$$$parent.props.postBefore
|
||||
this._postAfter = props.postAfter || props.$$$parent.props.postAfter
|
||||
const $$$props = props.$$$parent && props.$$$parent.props ? props.$$$parent.props : {}
|
||||
this._postBefore = props.postBefore || $$$props.postBefore
|
||||
this._postAfter = props.postAfter || $$$props.postAfter
|
||||
|
||||
this._dividerRefs = []
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -253,9 +256,13 @@ class RbForm extends React.Component {
|
|||
<div className="rbform form-layout">
|
||||
<div className="form row" ref={(c) => (this._form = c)}>
|
||||
{this.props.children.map((fieldComp) => {
|
||||
const refid = fieldComp.props.field === TYPE_DIVIDER ? null : `fieldcomp-${fieldComp.props.field}`
|
||||
return React.cloneElement(fieldComp, { $$$parent: this, ref: refid })
|
||||
const ref = fieldComp.props.field === TYPE_DIVIDER ? $random('divider-') : `fieldcomp-${fieldComp.props.field}`
|
||||
if (fieldComp.props.field === TYPE_DIVIDER && fieldComp.props.collapsed) {
|
||||
this._dividerRefs.push(ref)
|
||||
}
|
||||
return React.cloneElement(fieldComp, { $$$parent: this, ref: ref })
|
||||
})}
|
||||
|
||||
{this.renderCustomizedFormArea()}
|
||||
</div>
|
||||
|
||||
|
@ -265,6 +272,12 @@ class RbForm extends React.Component {
|
|||
)
|
||||
}
|
||||
|
||||
renderCustomizedFormArea() {
|
||||
let _FormArea
|
||||
if (window._CustomizedForms) _FormArea = window._CustomizedForms.useFormArea(this.props.entity, this)
|
||||
return _FormArea || null
|
||||
}
|
||||
|
||||
renderDetailForm() {
|
||||
const detailMeta = this.props.rawModel.detailMeta
|
||||
if (!detailMeta || !window.ProTable) return null
|
||||
|
@ -330,7 +343,10 @@ class RbForm extends React.Component {
|
|||
// 记录转换:预览模式
|
||||
const previewid = this.props.$$$parent ? this.props.$$$parent.state.previewid : null
|
||||
|
||||
const NADD = [5, 10, 20]
|
||||
if (!_ProTable) {
|
||||
_ProTable = <ProTable entity={detailMeta} mainid={this.state.id} previewid={previewid} ref={(c) => (this._ProTable = c)} $$$main={this} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="detail-form-table">
|
||||
<div className="row">
|
||||
|
@ -340,6 +356,7 @@ class RbForm extends React.Component {
|
|||
{detailMeta.entityLabel}
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div className="col text-right">
|
||||
{detailImports && detailImports.length > 0 && (
|
||||
<div className="btn-group mr-2">
|
||||
|
@ -365,15 +382,15 @@ class RbForm extends React.Component {
|
|||
)}
|
||||
|
||||
<div className="btn-group">
|
||||
<button className="btn btn-secondary" type="button" onClick={() => _addNew()}>
|
||||
<button className="btn btn-secondary" type="button" onClick={() => _addNew()} disabled={this.props.readonly}>
|
||||
<i className="icon x14 zmdi zmdi-playlist-plus mr-1" />
|
||||
{$L('添加明细')}
|
||||
</button>
|
||||
<button className="btn btn-secondary dropdown-toggle w-auto" type="button" data-toggle="dropdown">
|
||||
<button className="btn btn-secondary dropdown-toggle w-auto" type="button" data-toggle="dropdown" disabled={this.props.readonly}>
|
||||
<i className="icon zmdi zmdi-chevron-down" />
|
||||
</button>
|
||||
<div className="dropdown-menu dropdown-menu-right">
|
||||
{NADD.map((n) => {
|
||||
{[5, 10, 20].map((n) => {
|
||||
return (
|
||||
<a className="dropdown-item" onClick={() => _addNew(n)} key={`n-${n}`}>
|
||||
{$L('添加 %d 条', n)}
|
||||
|
@ -385,17 +402,11 @@ class RbForm extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-2">{_ProTable ? _ProTable : <ProTable entity={detailMeta} mainid={this.state.id} previewid={previewid} ref={(c) => (this._ProTable = c)} $$$main={this} />}</div>
|
||||
<div className="mt-2">{_ProTable}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
renderCustomizedFormArea() {
|
||||
let _FormArea
|
||||
if (window._CustomizedForms) _FormArea = window._CustomizedForms.useFormArea(this.props.entity, this)
|
||||
return _FormArea || null
|
||||
}
|
||||
|
||||
renderFormAction() {
|
||||
let moreActions = []
|
||||
// 添加明细
|
||||
|
@ -423,10 +434,11 @@ class RbForm extends React.Component {
|
|||
|
||||
return (
|
||||
<div className="dialog-footer" ref={(c) => (this._$formAction = c)}>
|
||||
<button className="btn btn-secondary btn-space mr-2" type="button" onClick={() => this.props.$$$parent.hide()}>
|
||||
<button className="btn btn-secondary btn-space" type="button" onClick={() => this.props.$$$parent.hide()}>
|
||||
{$L('取消')}
|
||||
</button>
|
||||
<div className="btn-group dropup btn-space">
|
||||
{!this.props.readonly && (
|
||||
<div className="btn-group dropup btn-space ml-1">
|
||||
<button className="btn btn-primary" type="button" onClick={() => this.post()}>
|
||||
{$L('保存')}
|
||||
</button>
|
||||
|
@ -439,6 +451,7 @@ class RbForm extends React.Component {
|
|||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -463,6 +476,12 @@ class RbForm extends React.Component {
|
|||
})
|
||||
}
|
||||
|
||||
// v3.2 默认收起
|
||||
this._dividerRefs.forEach((d) => {
|
||||
// eslint-disable-next-line react/no-string-refs
|
||||
this.refs[d].toggle()
|
||||
})
|
||||
|
||||
setTimeout(() => RbForm.renderAfter(this), 0)
|
||||
}
|
||||
|
||||
|
@ -2415,11 +2434,14 @@ class RbFormDivider extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
if (this.props.breaked === true) {
|
||||
return <div className="form-line-breaked"></div>
|
||||
}
|
||||
return (
|
||||
<div className="form-line hover" ref={(c) => (this._$formLine = c)}>
|
||||
<fieldset>
|
||||
{this.props.label && (
|
||||
<legend onClick={() => this.toggle()} className="text-bold">
|
||||
<legend onClick={() => this.toggle()} className="text-bold" title={$L('展开/收起')}>
|
||||
{this.props.label}
|
||||
</legend>
|
||||
)}
|
||||
|
@ -2540,3 +2562,40 @@ const __addRecentlyUse = function (id) {
|
|||
$.post(`/commons/search/recently-add?id=${id}`)
|
||||
}
|
||||
}
|
||||
|
||||
// -- Lite
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
class LiteForm extends RbForm {
|
||||
renderCustomizedFormArea() {
|
||||
return null
|
||||
}
|
||||
|
||||
renderDetailForm() {
|
||||
return null
|
||||
}
|
||||
|
||||
renderFormAction() {
|
||||
return null
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount()
|
||||
// TODO init...
|
||||
}
|
||||
|
||||
buildFormData() {
|
||||
const s = {}
|
||||
const data = this.__FormData || {}
|
||||
for (let k in data) {
|
||||
const error = data[k].error
|
||||
if (error) {
|
||||
RbHighbar.create(error)
|
||||
return false
|
||||
}
|
||||
s[k] = data[k].value
|
||||
}
|
||||
s.metadata = { id: this.props.id || '' }
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ class ProTable extends React.Component {
|
|||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {}
|
||||
|
||||
this._readonly = props.$$$main.props.readonly
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -69,10 +71,10 @@ class ProTable extends React.Component {
|
|||
{FORM}
|
||||
|
||||
<td className={`col-action ${fixed && 'column-fixed'}`}>
|
||||
<button className="btn btn-light hide" title={$L('复制')} onClick={() => this.copyLine(key)}>
|
||||
<button className="btn btn-light hide" title={$L('复制')} onClick={() => this.copyLine(key)} disabled={this._readonly}>
|
||||
<i className="icon zmdi zmdi-copy fs-14" />
|
||||
</button>
|
||||
<button className="btn btn-light" title={$L('移除')} onClick={() => this.removeLine(key)}>
|
||||
<button className="btn btn-light" title={$L('移除')} onClick={() => this.removeLine(key)} disabled={this._readonly}>
|
||||
<i className="icon zmdi zmdi-close fs-16 text-bold" />
|
||||
</button>
|
||||
</td>
|
||||
|
|
Loading…
Reference in a new issue