mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 15:35:55 +08:00
Fix 2.8.3 (#452)
* Update rb-forms.js * fix: CustomEntityPrivileges for detail-entity * better: file preview * fix: auto-fill field deleted
This commit is contained in:
parent
7f214334c6
commit
3ec4591144
2
pom.xml
2
pom.xml
|
@ -10,7 +10,7 @@
|
|||
</parent>
|
||||
<groupId>com.rebuild</groupId>
|
||||
<artifactId>rebuild</artifactId>
|
||||
<version>2.8.2</version>
|
||||
<version>2.8.3</version>
|
||||
<name>rebuild</name>
|
||||
<description>Building your business-systems freely!</description>
|
||||
<!-- UNCOMMENT USE TOMCAT -->
|
||||
|
|
|
@ -64,11 +64,11 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
|
|||
/**
|
||||
* Rebuild Version
|
||||
*/
|
||||
public static final String VER = "2.8.2";
|
||||
public static final String VER = "2.8.3";
|
||||
/**
|
||||
* Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2}
|
||||
*/
|
||||
public static final int BUILD = 2080205;
|
||||
public static final int BUILD = 2080307;
|
||||
|
||||
static {
|
||||
// Driver for DB
|
||||
|
|
|
@ -57,7 +57,8 @@ public class AutoFillinManager implements ConfigManager {
|
|||
// 内置字段无配置 @see field-edit.html
|
||||
if (easyField.isBuiltin()) return JSONUtils.EMPTY_ARRAY;
|
||||
|
||||
final List<ConfigBean> config = getConfig(field);
|
||||
final List<ConfigBean> config = new ArrayList<>();
|
||||
for (ConfigBean cb : getConfig(field)) config.add(cb.clone());
|
||||
|
||||
// 父级级联
|
||||
// 利用表单回填做父级级联字段回填
|
||||
|
@ -70,7 +71,7 @@ public class AutoFillinManager implements ConfigManager {
|
|||
.set("whenCreate", true)
|
||||
.set("whenUpdate", true)
|
||||
.set("fillinForce", true);
|
||||
|
||||
|
||||
// 移除冲突的表单回填配置
|
||||
for (Iterator<ConfigBean> iter = config.iterator(); iter.hasNext(); ) {
|
||||
ConfigBean cb = iter.next();
|
||||
|
@ -89,28 +90,28 @@ public class AutoFillinManager implements ConfigManager {
|
|||
Entity sourceEntity = MetadataHelper.getEntity(source.getEntityCode());
|
||||
Entity targetEntity = field.getOwnEntity();
|
||||
Set<String> sourceFields = new HashSet<>();
|
||||
for (ConfigBean e : config) {
|
||||
for (Iterator<ConfigBean> iter = config.iterator(); iter.hasNext(); ) {
|
||||
ConfigBean e = iter.next();
|
||||
String sourceField = e.getString("source");
|
||||
String targetField = e.getString("target");
|
||||
if (!MetadataHelper.checkAndWarnField(sourceEntity, sourceField)
|
||||
|| !MetadataHelper.checkAndWarnField(targetEntity, targetField)) {
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
sourceFields.add(sourceField);
|
||||
}
|
||||
if (sourceFields.isEmpty()) {
|
||||
return JSONUtils.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
if (sourceFields.isEmpty()) return JSONUtils.EMPTY_ARRAY;
|
||||
|
||||
String ql = String.format("select %s from %s where %s = ?",
|
||||
StringUtils.join(sourceFields, ","),
|
||||
sourceEntity.getName(),
|
||||
sourceEntity.getPrimaryField().getName());
|
||||
Record sourceRecord = Application.createQueryNoFilter(ql).setParameter(1, source).record();
|
||||
if (sourceRecord == null) {
|
||||
return JSONUtils.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
if (sourceRecord == null) return JSONUtils.EMPTY_ARRAY;
|
||||
|
||||
JSONArray fillin = new JSONArray();
|
||||
for (ConfigBean e : config) {
|
||||
|
|
|
@ -479,7 +479,7 @@ public class FormsBuilder extends FormsManager {
|
|||
}
|
||||
|
||||
// 处理日期格式
|
||||
if (field.getDisplayType() == DisplayType.REFERENCE && value != null && ((ID) value).getLabelRaw() != null) {
|
||||
if (field.getDisplayType() == DisplayType.REFERENCE && value instanceof ID && ((ID) value).getLabelRaw() != null) {
|
||||
Field nameField = field.getRawMeta().getReferenceEntity().getNameField();
|
||||
if (nameField.getType() == FieldType.DATE || nameField.getType() == FieldType.TIMESTAMP) {
|
||||
Object newLabel = EasyMetaFactory.valueOf(nameField).wrapValue(((ID) value).getLabelRaw());
|
||||
|
|
|
@ -405,7 +405,7 @@ public class PrivilegesManager {
|
|||
* @param action
|
||||
* @param ep
|
||||
* @return
|
||||
* @see RoleBaseQueryFilter#buildCustomFilter(Privileges)
|
||||
* @see RoleBaseQueryFilter#buildCustomFilter(Privileges, Field)
|
||||
*/
|
||||
private boolean andPassCustomFilter(ID user, ID target, Permission action, Privileges ep) {
|
||||
if (!(ep instanceof CustomEntityPrivileges)) return true;
|
||||
|
|
|
@ -18,6 +18,8 @@ import cn.devezhao.persist4j.Entity;
|
|||
import cn.devezhao.persist4j.Field;
|
||||
import cn.devezhao.persist4j.Filter;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.rebuild.core.metadata.EntityHelper;
|
||||
import com.rebuild.core.metadata.MetadataHelper;
|
||||
|
@ -26,6 +28,7 @@ import com.rebuild.core.privileges.bizz.CustomEntityPrivileges;
|
|||
import com.rebuild.core.privileges.bizz.Department;
|
||||
import com.rebuild.core.privileges.bizz.User;
|
||||
import com.rebuild.core.service.query.AdvFilterParser;
|
||||
import com.rebuild.utils.JSONUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
|
@ -127,7 +130,7 @@ public class RoleBaseQueryFilter implements Filter, QueryFilter {
|
|||
owningFormat = dtmField.getName() + "." + owningFormat;
|
||||
}
|
||||
|
||||
final String customFilter = buildCustomFilter(ep);
|
||||
final String customFilter = buildCustomFilter(ep, dtmField);
|
||||
final String shareFilter = buildShareFilter(entity, dtmField);
|
||||
|
||||
final DepthEntry depth = ep.superlative(useAction);
|
||||
|
@ -183,19 +186,19 @@ public class RoleBaseQueryFilter implements Filter, QueryFilter {
|
|||
* 共享权限
|
||||
*
|
||||
* @param entity
|
||||
* @param detailToMainField
|
||||
* @param dtmField
|
||||
* @return
|
||||
*/
|
||||
private String buildShareFilter(Entity entity, Field detailToMainField) {
|
||||
private String buildShareFilter(Entity entity, Field dtmField) {
|
||||
if (user == null) return null;
|
||||
|
||||
String shareFilter = "exists (select rights from ShareAccess where belongEntity = '%s' and shareTo = '%s' and recordId = ^%s)";
|
||||
|
||||
// 明细实体,使用主实体的共享
|
||||
if (detailToMainField != null) {
|
||||
// 使用主实体的共享(明细实体)
|
||||
if (dtmField != null) {
|
||||
shareFilter = String.format(shareFilter,
|
||||
detailToMainField.getOwnEntity().getMainEntity().getName(),
|
||||
user.getId(), detailToMainField.getName());
|
||||
dtmField.getOwnEntity().getMainEntity().getName(),
|
||||
user.getId(), dtmField.getName());
|
||||
} else {
|
||||
shareFilter = String.format(shareFilter,
|
||||
entity.getName(), user.getId(), entity.getPrimaryField().getName());
|
||||
|
@ -207,16 +210,33 @@ public class RoleBaseQueryFilter implements Filter, QueryFilter {
|
|||
* 自定义权限
|
||||
*
|
||||
* @param ep
|
||||
* @param dtmField
|
||||
* @return
|
||||
* @see PrivilegesManager#andPassCustomFilter(ID, ID, Permission, Privileges)
|
||||
*/
|
||||
private String buildCustomFilter(Privileges ep) {
|
||||
private String buildCustomFilter(Privileges ep, Field dtmField) {
|
||||
if (user == null || useAction == null
|
||||
|| !(ep instanceof CustomEntityPrivileges)) return null;
|
||||
|
||||
JSONObject hasFilter = ((CustomEntityPrivileges) ep).getCustomFilter(useAction);
|
||||
if (hasFilter == null) return null;
|
||||
|
||||
// 兼容转换(明细实体)
|
||||
if (dtmField != null) {
|
||||
final JSONArray items = hasFilter.getJSONArray("items");
|
||||
|
||||
JSONArray items2 = new JSONArray();
|
||||
for (Object item : items) {
|
||||
JSONObject c = (JSONObject) JSONUtils.clone((JSON) item);
|
||||
c.put("field", String.format("%s.%s", dtmField.getName(), c.getString("field")));
|
||||
items2.add(c);
|
||||
}
|
||||
|
||||
hasFilter = JSONUtils.toJSONObject(
|
||||
new String[] { "entity", "items" },
|
||||
new Object[] { dtmField.getOwnEntity().getName(), items2 });
|
||||
}
|
||||
|
||||
AdvFilterParser advFilterParser = new AdvFilterParser(hasFilter);
|
||||
advFilterParser.setUser(user.getId());
|
||||
return advFilterParser.toSqlWhere();
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||
* @since 2021/11/15
|
||||
*/
|
||||
public class CustomEntityPrivileges extends EntityPrivileges {
|
||||
private static final long serialVersionUID = 2658045031880710476L;
|
||||
|
||||
private Map<String, JSON> customAdvFilters = new HashMap<>();
|
||||
|
||||
|
|
|
@ -110,16 +110,19 @@ public class AutoFillinController extends BaseController {
|
|||
for (Object[] o : array) {
|
||||
String sourceField = (String) o[1];
|
||||
String targetField = (String) o[2];
|
||||
if (!MetadataHelper.checkAndWarnField(sourceEntity, sourceField)
|
||||
|| !MetadataHelper.checkAndWarnField(targetEntity, targetField)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String sourceFieldLabel = sourceEntity.containsField(sourceField)
|
||||
? EasyMetaFactory.getLabel(sourceEntity.getField(sourceField))
|
||||
: String.format("[%s]", sourceField.toUpperCase());
|
||||
String targetFieldLabel = targetEntity.containsField(targetField)
|
||||
? EasyMetaFactory.getLabel(targetEntity.getField(targetField))
|
||||
: String.format("[%s]", targetField.toUpperCase());
|
||||
|
||||
JSON rule = JSONUtils.toJSONObject(
|
||||
new String[]{ "id", "sourceField", "sourceFieldLabel", "targetField", "targetFieldLabel", "extConfig" },
|
||||
new Object[]{ o[0],
|
||||
sourceField, EasyMetaFactory.getLabel(sourceEntity.getField(sourceField)),
|
||||
targetField, EasyMetaFactory.getLabel(targetEntity.getField(targetField)),
|
||||
sourceField, sourceFieldLabel,
|
||||
targetField, targetFieldLabel,
|
||||
JSON.parse((String) o[3])});
|
||||
rules.add(rule);
|
||||
}
|
||||
|
|
|
@ -422,9 +422,8 @@ a.btn {
|
|||
}
|
||||
|
||||
.input-search input + .btn-input-clear::before {
|
||||
font-family: 'Material-Design-Iconic-Font';
|
||||
font-family: 'Material-Design-Iconic-Font', serif;
|
||||
font-size: 1.308rem;
|
||||
content: '\f135';
|
||||
content: '\f136';
|
||||
}
|
||||
|
||||
|
@ -947,7 +946,7 @@ select.form-control:not([disabled]) {
|
|||
|
||||
.type-N2NREFERENCE .select2-container--default .select2-selection--multiple::after {
|
||||
content: '\f2f9';
|
||||
font-family: 'Material-Design-Iconic-Font';
|
||||
font-family: 'Material-Design-Iconic-Font', serif;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 400;
|
||||
line-height: 35px;
|
||||
|
@ -1010,7 +1009,6 @@ select.form-control:not([disabled]) {
|
|||
.img-field .img-upload[disabled] .zmdi {
|
||||
opacity: 1 !important;
|
||||
color: #dbdbdb !important;
|
||||
cursor: default !important;
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
|
||||
|
@ -1095,6 +1093,15 @@ select.form-control:not([disabled]) {
|
|||
cursor: default;
|
||||
}
|
||||
|
||||
.img-field.barcode .img-thumbnail.w-auto {
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.img-field.barcode .img-thumbnail.w-auto > img {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.file-field .file-select label.btn-secondary {
|
||||
line-height: 35px;
|
||||
}
|
||||
|
@ -1594,7 +1601,7 @@ th.column-fixed {
|
|||
transform: translateX(100%);
|
||||
box-shadow: inset 10px 0 8px -8px rgba(0, 0, 0, 0.15);
|
||||
transition: box-shadow 0.3s;
|
||||
width: 20px;
|
||||
/*width: 20px;*/
|
||||
/* fix: Safari */
|
||||
width: 24px;
|
||||
}
|
||||
|
@ -4336,7 +4343,7 @@ html.external-auth .auth-body.must-center .login {
|
|||
|
||||
.user-popup .infos p.phone,
|
||||
.user-popup .infos p.email {
|
||||
font-family: 'Material-Design-Iconic-Font';
|
||||
font-family: 'Material-Design-Iconic-Font', serif;
|
||||
}
|
||||
|
||||
.user-popup .infos p.phone::after,
|
||||
|
@ -4400,7 +4407,7 @@ pre.unstyle {
|
|||
}
|
||||
|
||||
.dropdown-item.check::after {
|
||||
font-family: 'Material-Design-Iconic-Font';
|
||||
font-family: 'Material-Design-Iconic-Font', serif;
|
||||
content: '\f26b';
|
||||
float: right;
|
||||
font-size: 1.2rem;
|
||||
|
@ -4476,7 +4483,7 @@ pre.unstyle {
|
|||
}
|
||||
|
||||
.sign-pad-canvas .pen-colors > a.active::after {
|
||||
font-family: 'Material-Design-Iconic-Font';
|
||||
font-family: 'Material-Design-Iconic-Font', serif;
|
||||
content: '\f26b';
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
|
|
@ -95,7 +95,8 @@ class RbPreview extends React.Component {
|
|||
onLoad={() => this.setState({ imgRendered: true })}
|
||||
onError={() => {
|
||||
RbHighbar.error($L('无法读取图片'))
|
||||
this.hide()
|
||||
// this.hide()
|
||||
// Qiniu: {"error":"xxx is not within the limit, area is out of range [1, 24999999]"}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -181,8 +182,9 @@ class RbPreview extends React.Component {
|
|||
const currentUrl = this.props.urls[this.state.currentIndex]
|
||||
const fileName = $fileCutName(currentUrl)
|
||||
if (this._isDoc(fileName)) {
|
||||
const ispdf = fileName.toLowerCase().endsWith('.pdf')
|
||||
const setPreviewUrl = function (url) {
|
||||
const previewUrl = (rb._officePreviewUrl || 'https://view.officeapps.live.com/op/embed.aspx?src=') + $encode(url)
|
||||
const previewUrl = ispdf ? url : (rb._officePreviewUrl || 'https://view.officeapps.live.com/op/embed.aspx?src=') + $encode(url)
|
||||
that.setState({ previewUrl: previewUrl, errorMsg: null })
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,6 @@ $(document).ready(function () {
|
|||
})
|
||||
|
||||
const $copy = $('.btn-primary.copy').on('click', () => {
|
||||
if (rb.commercial < 1) return
|
||||
|
||||
const sourceEntity = $val('#copySourceEntity')
|
||||
if (!sourceEntity) RbHighbar.create($L('请选择从哪个实体复制'))
|
||||
|
||||
|
|
|
@ -193,6 +193,7 @@ class ReferenceSearcher extends RbModal {
|
|||
|
||||
destroy() {
|
||||
this.setState({ destroy: true })
|
||||
window.referenceSearch__dlg = null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -313,11 +313,12 @@ class RbForm extends React.Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
// 新纪录初始值
|
||||
if (this.isNew) {
|
||||
this.props.children.map((child) => {
|
||||
const val = child.props.value
|
||||
if (val && child.props.readonly !== true) {
|
||||
// 复合型值 {id:xxx, text:xxx}
|
||||
// {id:xxx, text:xxx}
|
||||
this.setFieldValue(child.props.field, typeof val === 'object' ? val.id : val)
|
||||
}
|
||||
})
|
||||
|
@ -340,16 +341,16 @@ class RbForm extends React.Component {
|
|||
// 设置字段值
|
||||
setFieldValue(field, value, error) {
|
||||
this.__FormData[field] = { value: value, error: error }
|
||||
if (!error && this._onFieldValueChange_calls) this._onFieldValueChange_calls.forEach((c) => c({ name: field, value: value }))
|
||||
if (!error) this._onFieldValueChangeCall(field, value)
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
if (rb.env === 'dev') console.log('FV1 ... ' + JSON.stringify(this.__FormData))
|
||||
}
|
||||
|
||||
// 避免无意义更新
|
||||
setFieldUnchanged(field) {
|
||||
setFieldUnchanged(field, originValue) {
|
||||
delete this.__FormData[field]
|
||||
if (this._onFieldValueChange_calls) this._onFieldValueChange_calls.forEach((c) => c({ name: field }))
|
||||
this._onFieldValueChangeCall(field, originValue)
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
if (rb.env === 'dev') console.log('FV2 ... ' + JSON.stringify(this.__FormData))
|
||||
|
@ -361,6 +362,11 @@ class RbForm extends React.Component {
|
|||
c.push(call)
|
||||
this._onFieldValueChange_calls = c
|
||||
}
|
||||
_onFieldValueChangeCall(field, value) {
|
||||
if (this._onFieldValueChange_calls) {
|
||||
this._onFieldValueChange_calls.forEach((c) => c({ name: field, value: value }))
|
||||
}
|
||||
}
|
||||
|
||||
// 保存并添加明细
|
||||
static __NEXT_ADDDETAIL = 102
|
||||
|
@ -471,6 +477,7 @@ class RbFormElement extends React.Component {
|
|||
if (props.colspan === 4 || props.isFull === true) colspan = 12
|
||||
else if (props.colspan === 1) colspan = 3
|
||||
else if (props.colspan === 3) colspan = 9
|
||||
else if (props.colspan === 9) colspan = 4
|
||||
|
||||
const editable = props.$$$parent.onViewEditable && props.onView && !props.readonly
|
||||
|
||||
|
@ -528,8 +535,8 @@ class RbFormElement extends React.Component {
|
|||
title={this.state.hasError}
|
||||
type="text"
|
||||
value={value || ''}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
onBlur={this.props.readonly ? null : () => this.checkValue()}
|
||||
onChange={(e) => this.handleChange(e, this.props.readonly ? false : true)}
|
||||
// onBlur={this.props.readonly ? null : () => this.checkValue()}
|
||||
readOnly={this.props.readonly}
|
||||
maxLength={this.props.maxLength || 200}
|
||||
/>
|
||||
|
@ -573,7 +580,7 @@ class RbFormElement extends React.Component {
|
|||
|
||||
if (this.isValueUnchanged() && !this.props.$$$parent.isNew) {
|
||||
if (err) this.props.$$$parent.setFieldValue(this.props.field, this.state.value, errMsg)
|
||||
else this.props.$$$parent.setFieldUnchanged(this.props.field)
|
||||
else this.props.$$$parent.setFieldUnchanged(this.props.field, this.state.value)
|
||||
} else {
|
||||
this.setState({ hasError: err })
|
||||
this.props.$$$parent.setFieldValue(this.props.field, this.state.value, errMsg)
|
||||
|
@ -760,8 +767,8 @@ class RbFormNumber extends RbFormText {
|
|||
title={this.state.hasError}
|
||||
type="text"
|
||||
value={this._removeComma(value) || ''}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
onBlur={this.props.readonly ? null : () => this.checkValue()}
|
||||
onChange={(e) => this.handleChange(e, this.props.readonly ? false : true)}
|
||||
// onBlur={this.props.readonly ? null : () => this.checkValue()}
|
||||
readOnly={this.props.readonly}
|
||||
maxLength="29"
|
||||
/>
|
||||
|
@ -774,51 +781,56 @@ class RbFormNumber extends RbFormText {
|
|||
// 表单计算(视图下无效)
|
||||
if (this.props.calcFormula && !this.props.onView) {
|
||||
const calcFormula = this.props.calcFormula.replace(new RegExp('×', 'ig'), '*').replace(new RegExp('÷', 'ig'), '/')
|
||||
const watchFields = calcFormula.match(/\{([a-z0-9]+)\}/gi) || []
|
||||
const fixed = this.props.decimalFormat ? (this.props.decimalFormat.split('.')[1] || '').length : 0
|
||||
|
||||
this.calcFormula__values = {}
|
||||
// 初始值
|
||||
// 等待字段初始化完毕
|
||||
setTimeout(() => {
|
||||
const calcFormulaValues = {}
|
||||
const watchFields = calcFormula.match(/\{([a-z0-9]+)\}/gi) || []
|
||||
|
||||
watchFields.forEach((item) => {
|
||||
const name = item.substr(1, item.length - 2)
|
||||
const fieldComp = this.props.$$$parent.refs[`fieldcomp-${name}`]
|
||||
if (fieldComp && fieldComp.state.value) {
|
||||
this.calcFormula__values[name] = this._removeComma(fieldComp.state.value)
|
||||
calcFormulaValues[name] = this._removeComma(fieldComp.state.value)
|
||||
}
|
||||
})
|
||||
}, 400)
|
||||
|
||||
// 小数位
|
||||
const fixed = this.props.decimalFormat ? (this.props.decimalFormat.split('.')[1] || '').length : 0
|
||||
// 表单计算
|
||||
this.props.$$$parent.onFieldValueChange((s) => {
|
||||
if (!watchFields.includes(`{${s.name}}`)) {
|
||||
if (rb.env === 'dev') console.log('onFieldValueChange :', s)
|
||||
return false
|
||||
} else if (rb.env === 'dev') {
|
||||
console.log('onFieldValueChange for calcFormula :', s)
|
||||
}
|
||||
|
||||
// 表单计算
|
||||
this.props.$$$parent.onFieldValueChange((s) => {
|
||||
if (!watchFields.includes(`{${s.name}}`)) return
|
||||
if (s.value) {
|
||||
calcFormulaValues[s.name] = this._removeComma(s.value)
|
||||
} else {
|
||||
delete calcFormulaValues[s.name]
|
||||
}
|
||||
|
||||
if (s.value) {
|
||||
this.calcFormula__values[s.name] = this._removeComma(s.value)
|
||||
} else {
|
||||
delete this.calcFormula__values[s.name]
|
||||
}
|
||||
let formula = calcFormula
|
||||
for (let key in calcFormulaValues) {
|
||||
formula = formula.replace(new RegExp(`{${key}}`, 'ig'), calcFormulaValues[key] || 0)
|
||||
}
|
||||
|
||||
let formula = calcFormula
|
||||
for (let key in this.calcFormula__values) {
|
||||
formula = formula.replace(new RegExp(`{${key}}`, 'ig'), this.calcFormula__values[key] || 0)
|
||||
}
|
||||
if (formula.includes('{')) {
|
||||
this.setValue(null)
|
||||
return false
|
||||
}
|
||||
|
||||
if (formula.includes('{')) {
|
||||
this.setValue(null)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
let calcv = null
|
||||
eval(`calcv = ${formula}`)
|
||||
if (!isNaN(calcv)) this.setValue(calcv.toFixed(fixed))
|
||||
} catch (err) {
|
||||
if (rb.env === 'dev') console.log(err)
|
||||
}
|
||||
})
|
||||
try {
|
||||
let calcv = null
|
||||
eval(`calcv = ${formula}`)
|
||||
if (!isNaN(calcv)) this.setValue(calcv.toFixed(fixed))
|
||||
} catch (err) {
|
||||
if (rb.env === 'dev') console.log(err)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,8 +870,8 @@ class RbFormTextarea extends RbFormElement {
|
|||
className={`form-control form-control-sm row3x ${this.state.hasError ? 'is-invalid' : ''} ${this.props.useMdedit && this.props.readonly ? 'cm-readonly' : ''}`}
|
||||
title={this.state.hasError}
|
||||
value={this.state.value || ''}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
onBlur={this.props.readonly ? null : () => this.checkValue()}
|
||||
onChange={(e) => this.handleChange(e, this.props.readonly ? false : true)}
|
||||
// onBlur={this.props.readonly ? null : () => this.checkValue()}
|
||||
readOnly={this.props.readonly}
|
||||
maxLength="6000"
|
||||
/>
|
||||
|
@ -972,14 +984,14 @@ class RbFormDateTime extends RbFormElement {
|
|||
title={this.state.hasError}
|
||||
type="text"
|
||||
value={this.state.value || ''}
|
||||
onChange={(e) => this.handleChange(e)}
|
||||
onBlur={this.props.readonly ? null : () => this.checkValue()}
|
||||
onChange={(e) => this.handleChange(e, this.props.readonly ? false : true)}
|
||||
// onBlur={this.props.readonly ? null : () => this.checkValue()}
|
||||
maxLength="20"
|
||||
/>
|
||||
<span className={'zmdi zmdi-close clean ' + (this.state.value ? '' : 'hide')} onClick={() => this.handleClear()} />
|
||||
<div className="input-group-append">
|
||||
<button className="btn btn-secondary" type="button" ref={(c) => (this._fieldValue__icon = c)}>
|
||||
<i className="icon zmdi zmdi-calendar" />
|
||||
<i className={`icon zmdi zmdi-${this._icon || 'calendar'}`} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1025,6 +1037,39 @@ class RbFormDateTime extends RbFormElement {
|
|||
}
|
||||
}
|
||||
|
||||
class RbFormTime extends RbFormDateTime {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this._icon = 'time'
|
||||
}
|
||||
|
||||
onEditModeChanged(destroy) {
|
||||
if (destroy) {
|
||||
super.onEditModeChanged(destroy)
|
||||
} else if (!this.props.readonly) {
|
||||
const format = (this.props.timeFormat || 'hh:ii:ss').replace('mm', 'ii').toLowerCase()
|
||||
const minView = format.length === 2 ? 1 : 0
|
||||
|
||||
const that = this
|
||||
this.__datetimepicker = $(this._fieldValue)
|
||||
.datetimepicker({
|
||||
format: format,
|
||||
startView: 1,
|
||||
minView: minView,
|
||||
maxView: 1,
|
||||
pickerPosition: this._getAutoPosition(),
|
||||
title: $L('选择时间'),
|
||||
})
|
||||
.on('changeDate', function () {
|
||||
const val = $(this).val()
|
||||
that.handleChange({ target: { value: val } }, true)
|
||||
})
|
||||
|
||||
$(this._fieldValue__icon).on('click', () => this.__datetimepicker.datetimepicker('show'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RbFormImage extends RbFormElement {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
@ -1371,7 +1416,8 @@ class RbFormReference extends RbFormElement {
|
|||
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount()
|
||||
if (this._ReferenceSearcher) {
|
||||
|
||||
if (this._ReferenceSearcher && !this._hasCascadingField) {
|
||||
this._ReferenceSearcher.destroy()
|
||||
this._ReferenceSearcher = null
|
||||
}
|
||||
|
@ -1715,7 +1761,7 @@ class RbFormBool extends RbFormElement {
|
|||
<label className="custom-control custom-radio custom-control-inline">
|
||||
<input
|
||||
className="custom-control-input"
|
||||
name={'radio-' + this.props.field}
|
||||
name={`radio-${this.props.field}`}
|
||||
type="radio"
|
||||
checked={!$isTrue(this.state.value)}
|
||||
data-value="F"
|
||||
|
@ -1766,8 +1812,8 @@ class RbFormBarcode extends RbFormElement {
|
|||
const codeUrl = `${rb.baseUrl}/commons/barcode/render${isbar ? '' : '-qr'}?t=${$encode(this.state.value)}`
|
||||
return (
|
||||
<div className="img-field barcode">
|
||||
<a className="img-thumbnail" title={this.state.value}>
|
||||
<img src={codeUrl} alt={this.state.value} className={isbar ? 'w-auto' : ''} />
|
||||
<a className={`img-thumbnail ${isbar && 'w-auto'}`} title={this.state.value}>
|
||||
<img src={codeUrl} alt={this.state.value} />
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
|
@ -2071,6 +2117,8 @@ var detectElement = function (item) {
|
|||
return <RbFormFile {...item} />
|
||||
} else if (item.type === 'DATETIME' || item.type === 'DATE') {
|
||||
return <RbFormDateTime {...item} />
|
||||
} else if (item.type === 'TIME') {
|
||||
return <RbFormTime {...item} />
|
||||
} else if (item.type === 'PICKLIST') {
|
||||
return <RbFormPickList {...item} />
|
||||
} else if (item.type === 'REFERENCE') {
|
||||
|
|
Loading…
Reference in a new issue