From 30ddd5528aa689d972a1688a5ec4262b5d10e1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?REBUILD=20=E4=BC=81=E4=B8=9A=E7=AE=A1=E7=90=86=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F?= <42044143+getrebuild@users.noreply.github.com> Date: Tue, 26 Dec 2023 14:50:25 +0800 Subject: [PATCH] form readonly attr (#700) * be * session-timeout:2h; form readonly * feat: field attr readonly * style: entity excel --------- Co-authored-by: devezhao --- .../configuration/general/FormsBuilder.java | 20 +- .../com/rebuild/core/support/CommonsLog.java | 3 +- .../admin/metadata/MetaFieldController.java | 1 + src/main/resources/application.yml | 2 +- .../web/admin/metadata/entities.html | 18 +- .../web/admin/metadata/form-design.html | 13 + .../web/assets/js/charts/dashboard.js | 19 +- .../web/assets/js/metadata/entity-new2.js | 261 ++++++++---------- .../web/assets/js/metadata/form-design.js | 13 +- 9 files changed, 179 insertions(+), 171 deletions(-) diff --git a/src/main/java/com/rebuild/core/configuration/general/FormsBuilder.java b/src/main/java/com/rebuild/core/configuration/general/FormsBuilder.java index 10d5ad189..851595f95 100644 --- a/src/main/java/com/rebuild/core/configuration/general/FormsBuilder.java +++ b/src/main/java/com/rebuild/core/configuration/general/FormsBuilder.java @@ -347,11 +347,13 @@ public class FormsBuilder extends FormsManager { // v2.2 高级控制 if (viewModel) useAdvControl = false; if (useAdvControl) { - Object displayOnCreate = el.remove("displayOnCreate"); - Object displayOnUpdate = el.remove("displayOnUpdate"); - Object requiredOnCreate = el.remove("requiredOnCreate"); - Object requiredOnUpdate = el.remove("requiredOnUpdate"); - + final Object displayOnCreate = el.remove("displayOnCreate"); + final Object displayOnUpdate = el.remove("displayOnUpdate"); + final Object requiredOnCreate = el.remove("requiredOnCreate"); + final Object requiredOnUpdate = el.remove("requiredOnUpdate"); + final Object readonlyOnCreate = el.remove("readonlyOnCreate"); + final Object readonlyOnUpdate = el.remove("readonlyOnUpdate"); + // fix v3.3.4 跟随主记录新建/更新 boolean isNew2 = isNew; if (entity.getMainEntity() != null) { @@ -376,6 +378,14 @@ public class FormsBuilder extends FormsManager { if (requiredOnUpdate != null && (Boolean) requiredOnUpdate && !isNew2) { el.put("nullable", false); } + + // 只读 v3.6 + if (readonlyOnCreate != null && (Boolean) readonlyOnCreate && isNew2) { + el.put("readonly", true); + } + if (readonlyOnUpdate != null && (Boolean) readonlyOnUpdate && !isNew2) { + el.put("readonly", true); + } } // 自动只读的 diff --git a/src/main/java/com/rebuild/core/support/CommonsLog.java b/src/main/java/com/rebuild/core/support/CommonsLog.java index c007e9859..a7ce8be7c 100644 --- a/src/main/java/com/rebuild/core/support/CommonsLog.java +++ b/src/main/java/com/rebuild/core/support/CommonsLog.java @@ -13,6 +13,7 @@ import cn.devezhao.persist4j.engine.ID; import com.rebuild.core.Application; import com.rebuild.core.metadata.EntityHelper; import com.rebuild.core.support.task.TaskExecutors; +import com.rebuild.utils.CommonsUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -65,7 +66,7 @@ public class CommonsLog { clog.setID("source", ObjectUtils.defaultIfNull(source, user)); clog.setInt("status", status); clog.setDate("logTime", CalendarUtils.now()); - if (content != null) clog.setString("logContent", content); + if (content != null) clog.setString("logContent", CommonsUtils.maxstr(content, 32767)); TaskExecutors.queue(() -> Application.getCommonsService().create(clog, false)); } diff --git a/src/main/java/com/rebuild/web/admin/metadata/MetaFieldController.java b/src/main/java/com/rebuild/web/admin/metadata/MetaFieldController.java index 284dc17e0..0c5b553bb 100644 --- a/src/main/java/com/rebuild/web/admin/metadata/MetaFieldController.java +++ b/src/main/java/com/rebuild/web/admin/metadata/MetaFieldController.java @@ -80,6 +80,7 @@ public class MetaFieldController extends BaseController { map.put("nullable", field.isNullable()); map.put("builtin", easyMeta.isBuiltin()); map.put("creatable", field.isCreatable()); + map.put("updatable", field.isUpdatable()); DisplayType dt = easyMeta.getDisplayType(); map.put("displayType", Language.L(dt)); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c782ed3a1..282911f58 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -14,7 +14,7 @@ server: cookie: same-site: lax name: RBSESSION - timeout: 14400 + timeout: 7200 error: whitelabel.enabled: false tomcat: diff --git a/src/main/resources/web/admin/metadata/entities.html b/src/main/resources/web/admin/metadata/entities.html index 48782afdf..3450a1942 100644 --- a/src/main/resources/web/admin/metadata/entities.html +++ b/src/main/resources/web/admin/metadata/entities.html @@ -81,21 +81,13 @@ } .table.table-excel th, .table.table-excel td { - padding: 3px; - border-width: 1px; - color: #222; - max-width: 200px; + vertical-align: text-top; } - .table.table-excel th { - text-align: center; - background-color: #dee2e6; - color: #444; + .table.table-excel thead th { + border: 0 none; } - .table.table-excel .form-control { - width: 100%; - min-width: 140px; - /* padding: 4px; */ - /* height: auto !important; */ + .table.table-excel { + border-bottom: 1px solid #dee2e6; } diff --git a/src/main/resources/web/admin/metadata/form-design.html b/src/main/resources/web/admin/metadata/form-design.html index 7c38a9ecb..ba56ba83e 100644 --- a/src/main/resources/web/admin/metadata/form-design.html +++ b/src/main/resources/web/admin/metadata/form-design.html @@ -93,6 +93,9 @@ [[${bundle.L('必填')}]] + + [[${bundle.L('只读')}]] + @@ -118,6 +121,16 @@ [[${bundle.L('编辑时')}]] + + + + diff --git a/src/main/resources/web/assets/js/charts/dashboard.js b/src/main/resources/web/assets/js/charts/dashboard.js index 60cf65971..aa7089434 100644 --- a/src/main/resources/web/assets/js/charts/dashboard.js +++ b/src/main/resources/web/assets/js/charts/dashboard.js @@ -313,7 +313,7 @@ class DlgAddChart extends RbFormHandler {
- (this._$entity = c)} />
@@ -329,16 +329,23 @@ class DlgAddChart extends RbFormHandler { } componentDidMount() { - const $entity = $(this.refs['entity']) $.get('/commons/metadata/entities?detail=true', (res) => { - $(res.data).each(function () { - if (!$isSysMask(this.label)) { - $(``).appendTo($entity) + const _data = res.data || [] + _data.forEach((item) => { + if (!$isSysMask(item.label)) { + $(``).appendTo(this._$entity) } }) - this.__select2 = $entity.select2({ + + this.__select2 = $(this._$entity).select2({ allowClear: false, placeholder: $L('选择数据来源'), + // templateResult: function (res) { + // const $span = $('').attr('title', res.text).text(res.text) + // const found = _data.find((x) => x.entity === res.id) + // if (found) $(``).appendTo($span) + // return $span + // }, }) }) } diff --git a/src/main/resources/web/assets/js/metadata/entity-new2.js b/src/main/resources/web/assets/js/metadata/entity-new2.js index 558328a56..0e1117207 100644 --- a/src/main/resources/web/assets/js/metadata/entity-new2.js +++ b/src/main/resources/web/assets/js/metadata/entity-new2.js @@ -17,6 +17,7 @@ class EntityNew2 extends RbModalHandler { constructor(props) { super(props) this.state = { ...props } + // this.state.excelfile = '134807507__副本IUI000008390352CNY23100100N-111.xls' } render() { @@ -305,7 +306,9 @@ class EntityNew2 extends RbModalHandler { const excelfile = this.state.excelfile if (!excelfile) return RbHighbar.create($L('请上传数据文件')) + const $btn = $(this._$container).find('.btn').button('loading') $.get(`/app/entity/data-imports/check-file?file=${$encode(excelfile)}`, (res) => { + $btn.button('reset') if (res.error_code > 0) { this.setState({ excelfile: null }) RbHighbar.create(res.error_msg) @@ -318,7 +321,7 @@ class EntityNew2 extends RbModalHandler { const entityLabel = $val(this._$excelEntityLabel) if (!entityLabel) return RbHighbar.create($L('请输入实体名称')) - renderRbcomp() + renderRbcomp() }) } @@ -343,126 +346,88 @@ class EntityNew2 extends RbModalHandler { } const _LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('') -class ExcelPreview extends RbModal { +class ExcelFieldsPreview extends RbModal { renderContent() { - let colMax = 0 - this.props.datas.forEach((d) => { - colMax = Math.max(colMax, d.length) - }) - + const ftKeys = Object.keys(FIELD_TYPES) + const fieldsHead = this.props.datas[0] const colNames = [] - for (let i = 0; i < colMax; i++) { + for (let i = 0; i < fieldsHead.length; i++) { let L = _LETTERS[i] if (i > 25) L = `A${_LETTERS[i - 26] || 'X'}` // AA if (i > 51) L = `B${_LETTERS[i - 52] || 'X'}` // BA colNames.push(L) } - const ftKeys = Object.keys(FIELD_TYPES) - const dataHead = this.props.datas[0] - - this.__colNames = colNames - this.__colDatas = {} - return (
-
- - - - - {colNames.map((item) => { - return - })} - - - - (this._$datahead = c)}> - - {colNames.map((item, idx) => { - return ( - - ) - })} - - ) - })} - -
{item}
1 -
- - -
-
- - + + + + + + + + (this._$tbody = c)}> + {fieldsHead.map((item, idx) => { + return ( + + + + - ) - })} - - {this.props.datas.map((d, idx) => { - if (idx === 0 || idx > 20) return null - return ( - - - {colNames.map((item, idx2) => { - const r = this.__colDatas[idx2] || [] - r.push(d[idx2]) - this.__colDatas[idx2] = r + + +
+ + +
+ + + ) + })} + +
{$L('字段名称')}{$L('字段类型')}
{colNames[idx]} + + + +
+ + -
-
- - -
-
- - -
-
{idx + 1}
- return ( -
- {d[idx2] || ''} -
-
-
-

{$L('最多显示前 %d 行数据', 20)}

-
-
(this._$btns = c)}> - - +
) @@ -471,38 +436,24 @@ class ExcelPreview extends RbModal { componentDidMount() { super.componentDidMount() - // 评估字段类型 - function _evalFieldType(cols) { - let isNumber = undefined - let isDecimal = undefined - cols.forEach((item) => { - if ($empty(item)) return - - if (isNumber || isNumber === undefined) isNumber = !isNaN(item) - if (isDecimal || isDecimal === undefined) { - isDecimal = isNumber && /\./g.test(item) - } - }) - if (isDecimal) return 'DECIMAL' - if (isNumber) return 'NUMBER' - return null - } - $.get('/admin/entity/entity-list?detail=true', (res) => { this.setState({ refEntities: res.data || [] }) $.get('/admin/metadata/classification/list', (res2) => { this.setState({ refClasses: res2.data || [] }, () => { // init - this.__colNames.forEach((item, idx) => { - const type = _evalFieldType(this.__colDatas[idx] || []) - type && $(this._$datahead).find('td').eq(idx).find('.J_type select').val(type) - }) - - $(this._$datahead) - .find('.J_type select') + $(this._$tbody) + .find('.J_type') + .select2({ + allowClear: false, + templateResult: function (res) { + const $span = $('').attr('title', res.text).text(res.text) + $(``).appendTo($span) + return $span + }, + }) .on('change', function () { - const $td = $(this).parents('td') + const $td = $(this).parent() $td.find('.J_refEntity, .J_refClass').addClass('hide') const t = $(this).val() @@ -513,20 +464,39 @@ class ExcelPreview extends RbModal { } }) - $(this._$datahead).find('select').select2({ allowClear: false }) + $(this._$tbody).find('.J_refEntity select, .J_refClass select').select2({ allowClear: false }) }) }) }) } + _evalFieldType(name, colidx) { + if ($empty(name)) return null + + let isNumber = undefined + let isDecimal = undefined + this.props.datas.forEach((row, idx) => { + if (idx < 1) return + const v = row[colidx] + if (isNumber || isNumber === undefined) isNumber = !isNaN(v) + if (isDecimal || isDecimal === undefined) { + isDecimal = isNumber && /\./g.test(v) + } + }) + + if (isDecimal) return 'DECIMAL' + if (isNumber) return 'NUMBER' + return null + } + post2() { const fieldsNew = [] - $(this._$datahead) - .find('td') + $(this._$tbody) + .find('tr') .each(function () { const name = $(this).find('input').val() - const type = $(this).find('.J_type select').val() - if (name && type && type !== '-') { + const type = $(this).find('.J_type').val() + if (name) { let ref2 = null if (type === 'REFERENCE' || type === 'N2NREFERENCE') { ref2 = $(this).find('.J_refEntity select').val() @@ -539,7 +509,7 @@ class ExcelPreview extends RbModal { fieldsNew.push([name, type, ref2]) } }) - if (fieldsNew.length === 0) return RbHighbar.create($L('没有配置任何导入字段')) + if (fieldsNew.length === 0) return RbHighbar.create($L('没有任何导入字段')) const that = this const post = { @@ -547,21 +517,24 @@ class ExcelPreview extends RbModal { fields: fieldsNew, } - RbAlert.create($L('请确认导入字段配置。开始导入吗?'), { + RbAlert.create($L('请再次确认导入字段。开始导入吗?'), { onConfirm: function () { this.disabled(true, true) $.post('/admin/entity/entity-excel', JSON.stringify(post), (res) => { this.hide(true) if (res.error_code === 0) { - RbAlert.create($L('实体导入成功。是否需要进行数据导入?'), { - onConfirm: function () { - location.href = `${rb.baseUrl}/admin/data/data-imports?entity=${res.data}&file=${$encode(that.props.excelfile)}` - }, - onCancel: function () { - location.href = `${rb.baseUrl}/admin/entity/${res.data}/fields` - }, - }) + setTimeout(() => { + RbAlert.create($L('实体导入成功。是否需要进行数据导入?'), { + onConfirm: function () { + location.href = `${rb.baseUrl}/admin/data/data-imports?entity=${res.data}&file=${$encode(that.props.excelfile)}` + }, + onCancel: function () { + location.href = `${rb.baseUrl}/admin/entity/${res.data}/fields` + }, + cancelText: $L('不需要'), + }) + }, 200) } else { RbHighbar.error(res.error_msg) } diff --git a/src/main/resources/web/assets/js/metadata/form-design.js b/src/main/resources/web/assets/js/metadata/form-design.js index 24f39109f..c42b8b610 100644 --- a/src/main/resources/web/assets/js/metadata/form-design.js +++ b/src/main/resources/web/assets/js/metadata/form-design.js @@ -563,9 +563,20 @@ const AdvControl = { set: function (field) { const $c = $(`${this._template}`).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 }) + else if (!field.nullable) { + $req.find('input').attr({ disabled: true, checked: true }) + } + // 只读 + const $ro = $c.find('td:eq(3)') + if (field.builtin) $ro.empty() + else { + if (!field.creatable) $ro.find('input:eq(0)').attr({ disabled: true, checked: true }) + if (!field.updatable) $ro.find('input:eq(1)').attr({ disabled: true, checked: true }) + } this.$tbody.find(`tr[data-field="${field.fieldName}"] input`).each(function () { const $this = $(this)