mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 15:35:55 +08:00
Merge pull request #348 from getrebuild/text-expr-686
trigger : All fields support formula
This commit is contained in:
commit
6394ec7184
2
@rbv
2
@rbv
|
@ -1 +1 @@
|
|||
Subproject commit d6df9e9bc54aedb4d1627a6cdb0b1c28b857a96c
|
||||
Subproject commit fff7b6eb61ad97fd79d876a229de681d4c64af62
|
|
@ -30,7 +30,7 @@ public enum DisplayType {
|
|||
SERIES(EasySeries.class, "自动编号", FieldType.STRING, 40, "{YYYYMMDD}-{0000}"),
|
||||
IMAGE(EasyImage.class, "图片", FieldType.STRING, 700, null),
|
||||
FILE(EasyFile.class, "附件", FieldType.STRING, 700, null),
|
||||
PICKLIST(EasyPickList.class, "选项", FieldType.REFERENCE, -1, null),
|
||||
PICKLIST(EasyPickList.class, "下拉列表", FieldType.REFERENCE, -1, null),
|
||||
CLASSIFICATION(EasyClassification.class, "分类", FieldType.REFERENCE, -1, null),
|
||||
REFERENCE(EasyReference.class, "引用", FieldType.REFERENCE, -1, null),
|
||||
AVATAR(EasyAvatar.class, "头像", FieldType.STRING, 300, null),
|
||||
|
|
|
@ -13,6 +13,7 @@ import cn.devezhao.commons.ObjectUtils;
|
|||
import cn.devezhao.persist4j.Field;
|
||||
import cn.devezhao.persist4j.Record;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
import cn.devezhao.persist4j.engine.StandardRecord;
|
||||
import cn.devezhao.persist4j.metadata.MissingMetaExcetion;
|
||||
import cn.devezhao.persist4j.record.RecordVisitor;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
|
@ -35,8 +36,8 @@ import com.rebuild.core.service.trigger.TriggerException;
|
|||
import com.rebuild.core.support.general.ContentWithFieldVars;
|
||||
import com.rebuild.utils.CommonsUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.BooleanUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -51,6 +52,7 @@ import java.util.*;
|
|||
public class FieldWriteback extends FieldAggregation {
|
||||
|
||||
private static final String DATE_EXPR = "#";
|
||||
private static final String CODE_PREFIX = "{{{{"; // ends with }}}}
|
||||
|
||||
private Set<ID> targetRecordIds;
|
||||
private Record targetRecordData;
|
||||
|
@ -133,7 +135,7 @@ public class FieldWriteback extends FieldAggregation {
|
|||
final Record record = EntityHelper.forNew(targetEntity.getEntityCode(), UserService.SYSTEM_USER, false);
|
||||
final JSONArray items = ((JSONObject) context.getActionContent()).getJSONArray("items");
|
||||
|
||||
Set<String> fieldVars = new HashSet<>();
|
||||
final Set<String> fieldVars = new HashSet<>();
|
||||
for (Object o : items) {
|
||||
JSONObject item = (JSONObject) o;
|
||||
String sourceField = item.getString("sourceField");
|
||||
|
@ -146,7 +148,7 @@ public class FieldWriteback extends FieldAggregation {
|
|||
if ("FIELD".equalsIgnoreCase(updateMode)) {
|
||||
fieldVars.add(sourceField);
|
||||
} else if ("FORMULA".equalsIgnoreCase(updateMode)) {
|
||||
if (sourceField.contains(DATE_EXPR)) {
|
||||
if (sourceField.contains(DATE_EXPR) && !sourceField.startsWith(CODE_PREFIX)) {
|
||||
fieldVars.add(sourceField.split(DATE_EXPR)[0]);
|
||||
} else {
|
||||
Set<String> matchsVars = ContentWithFieldVars.matchsVars(sourceField);
|
||||
|
@ -179,7 +181,7 @@ public class FieldWriteback extends FieldAggregation {
|
|||
EasyField targetFieldEasy = EasyMetaFactory.valueOf(targetEntity.getField(targetField));
|
||||
|
||||
String updateMode = item.getString("updateMode");
|
||||
String sourceField = item.getString("sourceField");
|
||||
String sourceAny = item.getString("sourceField");
|
||||
|
||||
// 置空
|
||||
if ("VNULL".equalsIgnoreCase(updateMode)) {
|
||||
|
@ -188,15 +190,15 @@ public class FieldWriteback extends FieldAggregation {
|
|||
|
||||
// 固定值
|
||||
else if ("VFIXED".equalsIgnoreCase(updateMode)) {
|
||||
RecordVisitor.setValueByLiteral(targetField, sourceField, record);
|
||||
RecordVisitor.setValueByLiteral(targetField, sourceAny, record);
|
||||
}
|
||||
|
||||
// 字段
|
||||
else if ("FIELD".equalsIgnoreCase(updateMode)) {
|
||||
Field sourceField2 = MetadataHelper.getLastJoinField(sourceEntity, sourceField);
|
||||
Field sourceField2 = MetadataHelper.getLastJoinField(sourceEntity, sourceAny);
|
||||
if (sourceField2 == null) continue;
|
||||
|
||||
Object value = Objects.requireNonNull(useSourceData).getObjectValue(sourceField);
|
||||
Object value = Objects.requireNonNull(useSourceData).getObjectValue(sourceAny);
|
||||
Object newValue = value == null ? null : EasyMetaFactory.valueOf(sourceField2)
|
||||
.convertCompatibleValue(value, targetFieldEasy);
|
||||
if (newValue != null) {
|
||||
|
@ -206,17 +208,23 @@ public class FieldWriteback extends FieldAggregation {
|
|||
|
||||
// 公式
|
||||
else if ("FORMULA".equalsIgnoreCase(updateMode)) {
|
||||
Assert.notNull(useSourceData, "[useSourceData] not be null");
|
||||
if (useSourceData == null) {
|
||||
log.warn("[useSourceData] is null, Set to empty");
|
||||
useSourceData = new StandardRecord(sourceEntity, null);
|
||||
}
|
||||
|
||||
// 高级公式代码
|
||||
final boolean useCode = sourceAny.startsWith(CODE_PREFIX);
|
||||
|
||||
// 日期兼容 fix: v2.2
|
||||
if (sourceField.contains(DATE_EXPR)) {
|
||||
String fieldName = sourceField.split(DATE_EXPR)[0];
|
||||
if (sourceAny.contains(DATE_EXPR) && !useCode) {
|
||||
String fieldName = sourceAny.split(DATE_EXPR)[0];
|
||||
Field sourceField2 = MetadataHelper.getLastJoinField(sourceEntity, fieldName);
|
||||
if (sourceField2 == null) continue;
|
||||
|
||||
Object value = useSourceData.getObjectValue(fieldName);
|
||||
Object newValue = value == null ? null : ((EasyDateTime) EasyMetaFactory.valueOf(sourceField2))
|
||||
.convertCompatibleValue(value, targetFieldEasy, sourceField);
|
||||
.convertCompatibleValue(value, targetFieldEasy, sourceAny);
|
||||
if (newValue != null) {
|
||||
record.setObjectValue(targetField, newValue);
|
||||
}
|
||||
|
@ -224,21 +232,25 @@ public class FieldWriteback extends FieldAggregation {
|
|||
|
||||
// 公式
|
||||
else {
|
||||
String clearFormual = sourceField.toUpperCase()
|
||||
String clearFormual = useCode
|
||||
? sourceAny.substring(4, sourceAny.length() - 4)
|
||||
: sourceAny
|
||||
.replace("×", "*")
|
||||
.replace("÷", "/")
|
||||
.replace("`", "'");
|
||||
.replace("`", "\""); // fix: 2.4 改为 "
|
||||
|
||||
for (String fieldName : useSourceData.getAvailableFields()) {
|
||||
String replace = "{" + fieldName.toUpperCase() + "}";
|
||||
for (String fieldName : fieldVars) {
|
||||
String replace = "{" + fieldName + "}";
|
||||
if (clearFormual.contains(replace)) {
|
||||
Object value = useSourceData.getObjectValue(fieldName);
|
||||
if (value instanceof Date) {
|
||||
value = CalendarUtils.getUTCDateTimeFormat().format(value);
|
||||
} else {
|
||||
value = value == null ? "0" : value.toString();
|
||||
value = value == null ? StringUtils.EMPTY : value.toString();
|
||||
}
|
||||
clearFormual = clearFormual.replace(replace, (String) value);
|
||||
} else {
|
||||
log.warn("No replace of field found : {}", replace);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -251,6 +263,11 @@ public class FieldWriteback extends FieldAggregation {
|
|||
record.setDouble(targetField, ObjectUtils.toDouble(newValue));
|
||||
} else if (dt == DisplayType.DATE || dt == DisplayType.DATETIME) {
|
||||
record.setDate(targetField, (Date) newValue);
|
||||
} else {
|
||||
newValue = checkoutFieldValue(newValue, targetFieldEasy);
|
||||
if (newValue != null) {
|
||||
record.setObjectValue(targetField, newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,4 +275,64 @@ public class FieldWriteback extends FieldAggregation {
|
|||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DisplayType
|
||||
* @see com.rebuild.core.metadata.EntityRecordCreator
|
||||
*/
|
||||
private Object checkoutFieldValue(Object value, EasyField field) {
|
||||
|
||||
DisplayType dt = field.getDisplayType();
|
||||
Object newValue = null;
|
||||
|
||||
if (dt == DisplayType.PICKLIST || dt == DisplayType.CLASSIFICATION
|
||||
|| dt == DisplayType.REFERENCE || dt == DisplayType.ANYREFERENCE) {
|
||||
|
||||
ID id = ID.isId(value) ? ID.valueOf(value.toString()) : null;
|
||||
if (id != null) {
|
||||
int idCode = id.getEntityCode();
|
||||
if (dt == DisplayType.PICKLIST) {
|
||||
if (idCode == EntityHelper.PickList) newValue = id;
|
||||
} else if (dt == DisplayType.CLASSIFICATION) {
|
||||
if (idCode == EntityHelper.ClassificationData) newValue = id;
|
||||
} else if (dt == DisplayType.REFERENCE) {
|
||||
if (field.getRawMeta().getReferenceEntity().getEntityCode() == idCode) newValue = id;
|
||||
} else {
|
||||
newValue = id;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (dt == DisplayType.N2NREFERENCE) {
|
||||
|
||||
String[] ids = value.toString().split(",");
|
||||
List<String> idsList = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
if (ID.isId(id)) idsList.add(id);
|
||||
}
|
||||
if (ids.length == idsList.size()) newValue = value.toString();
|
||||
|
||||
} else if (dt == DisplayType.BOOL) {
|
||||
|
||||
if (value instanceof Boolean) {
|
||||
newValue = value;
|
||||
} else {
|
||||
newValue = BooleanUtils.toBooleanObject(value.toString());
|
||||
}
|
||||
|
||||
} else if (dt == DisplayType.MULTISELECT || dt == DisplayType.STATE) {
|
||||
|
||||
if (value instanceof Integer || value instanceof Long) {
|
||||
newValue = value;
|
||||
}
|
||||
|
||||
} else {
|
||||
// TODO 验证字段格式
|
||||
newValue = value.toString();
|
||||
}
|
||||
|
||||
if (newValue == null) {
|
||||
log.warn("Value `{}` cannot be convert to field (value) : {}", value, field.getRawMeta());
|
||||
}
|
||||
return newValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ package com.rebuild.web.robot.trigger;
|
|||
|
||||
import cn.devezhao.persist4j.Entity;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.rebuild.core.Application;
|
||||
import com.rebuild.core.metadata.MetadataHelper;
|
||||
import com.rebuild.core.metadata.MetadataSorter;
|
||||
|
@ -71,12 +72,19 @@ public class TriggerAdminController extends BaseController {
|
|||
mv.getModel().put("when", config[2]);
|
||||
mv.getModel().put("whenTimer", config[7] == null ? StringUtils.EMPTY : config[7]);
|
||||
mv.getModel().put("whenFilter", StringUtils.defaultIfBlank((String) config[3], JSONUtils.EMPTY_OBJECT_STR));
|
||||
mv.getModel().put("actionContent", StringUtils.defaultIfBlank((String) config[4], JSONUtils.EMPTY_OBJECT_STR));
|
||||
mv.getModel().put("actionContent", JSONUtils.EMPTY_OBJECT_STR);
|
||||
mv.getModel().put("priority", config[5]);
|
||||
mv.getModel().put("name", config[6]);
|
||||
return mv;
|
||||
}
|
||||
|
||||
// 单独加载,否则会有转义问题
|
||||
@GetMapping("trigger/{id}/actionContent")
|
||||
public JSON pageEditor(@PathVariable String id) throws IOException {
|
||||
Object[] x = Application.getQueryFactory().unique(ID.valueOf(id), "actionContent");
|
||||
return (JSON) JSON.parse(x[0] == null ? "{}" : (String) x[0]);
|
||||
}
|
||||
|
||||
@GetMapping("trigger/available-actions")
|
||||
public List<String[]> getAvailableActions() {
|
||||
List<String[]> alist = new ArrayList<>();
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"自动编号":"自动编号",
|
||||
"图片":"图片",
|
||||
"附件":"附件",
|
||||
"选项":"选项",
|
||||
"下拉列表":"下拉列表",
|
||||
"分类":"分类",
|
||||
"引用":"引用",
|
||||
"头像":"头像",
|
||||
|
@ -68,7 +68,6 @@
|
|||
"所属主实体":"所属主实体",
|
||||
"字段":"字段",
|
||||
"显示类型":"显示类型",
|
||||
"下拉列表":"下拉列表",
|
||||
"排序":"排序",
|
||||
"布局":"布局",
|
||||
"共享给谁":"共享给谁",
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<a th:href="@{/admin/projects}"><i class="icon zmdi zmdi-shape"></i><span>[[${bundle.L('项目')}]]</span></a>
|
||||
</li>
|
||||
<li th:class="${active == 'frontjs-code'} ? 'active'">
|
||||
<a th:href="@{/admin/frontjs-code}"><i class="icon zmdi zmdi-code-setting"></i><span>FrontJS</span> <sup class="rbv"></sup></a>
|
||||
<a th:href="@{/admin/frontjs-code}"><i class="icon zmdi zmdi-code"></i><span>FrontJS</span> <sup class="rbv"></sup></a>
|
||||
</li>
|
||||
<li class="divider">[[${bundle.L('用户')}]]</li>
|
||||
<li th:class="${active == 'users'} ? 'active'">
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<option value="DECIMAL">[[${bundle.L('货币')}]]</option>
|
||||
<option value="DATE">[[${bundle.L('日期')}]]</option>
|
||||
<option value="DATETIME">[[${bundle.L('日期时间')}]]</option>
|
||||
<option value="PICKLIST">[[${bundle.L('选项')}]]</option>
|
||||
<option value="PICKLIST">[[${bundle.L('下拉列表')}]]</option>
|
||||
<option value="CLASSIFICATION">[[${bundle.L('分类')}]]</option>
|
||||
<option value="MULTISELECT">[[${bundle.L('多选')}]]</option>
|
||||
<option value="REFERENCE">[[${bundle.L('引用')}]]</option>
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<div class="tab-container">
|
||||
<ul class="nav nav-tabs bg-transparent">
|
||||
<li class="nav-item"><a class="nav-link active" href="#FIELDLIST" data-toggle="tab">[[${bundle.L('字段列表')}]]</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#FIELDNEW" data-toggle="tab">[[${bundle.L('添加字段')}]]</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#FIELDNEW" data-toggle="tab">+ [[${bundle.L('添加字段')}]]</a></li>
|
||||
</ul>
|
||||
<div class="tab-content bg-transparent p-0">
|
||||
<div class="tab-pane active" id="FIELDLIST">
|
||||
|
|
|
@ -130,6 +130,10 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.formula-calc {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.formula-calc .fields ul:empty::after {
|
||||
content: attr(_title);
|
||||
color: #999;
|
||||
|
@ -264,6 +268,45 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.form-control-plaintext.formula.switch-code {
|
||||
padding-right: 40px;
|
||||
}
|
||||
|
||||
.form-control-plaintext.formula.switch-code + .switch-code-btn {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
display: inline-block;
|
||||
width: 33px;
|
||||
height: 33px;
|
||||
line-height: 33px;
|
||||
text-align: center;
|
||||
font-size: 1.35rem;
|
||||
color: #777;
|
||||
border-radius: 2px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.form-control-plaintext.formula.switch-code + .switch-code-btn:hover {
|
||||
background-color: #212121;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
textarea.formula-code {
|
||||
font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, serif;
|
||||
font-size: 13px;
|
||||
background-color: #212121;
|
||||
color: #f07178;
|
||||
border: 0 none;
|
||||
height: 223px;
|
||||
width: 100%;
|
||||
resize: none;
|
||||
outline: none;
|
||||
border-radius: 0;
|
||||
line-height: 1.6;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
.auto-assign .select2-selection__rendered,
|
||||
.auto-share .select2-selection__rendered {
|
||||
display: block !important;
|
||||
|
|
|
@ -18,12 +18,6 @@ class FormulaCalc extends RbAlert {
|
|||
return (
|
||||
<div className="formula-calc">
|
||||
<div className="form-control-plaintext formula mb-2" _title={$L('计算公式')} ref={(c) => (this._$formula = c)}></div>
|
||||
<div className="bosskey-show mb-2">
|
||||
<textarea className="form-control form-control-sm row3x mb-1" ref={(c) => (this._$formulaInput = c)} />
|
||||
<a href="https://www.yuque.com/boyan-avfmj/aviatorscript" target="_blank" className="link">
|
||||
EXPRESSION ENGINE : AVIATORSCRIPT
|
||||
</a>
|
||||
</div>
|
||||
<div className="row unselect">
|
||||
<div className="col-6">
|
||||
<div className="fields rb-scroller" ref={(c) => (this._$fields = c)}>
|
||||
|
@ -84,17 +78,14 @@ class FormulaCalc extends RbAlert {
|
|||
}
|
||||
|
||||
confirm() {
|
||||
let expr = []
|
||||
const expr = []
|
||||
$(this._$formula)
|
||||
.find('i')
|
||||
.each(function () {
|
||||
expr.push($(this).data('v'))
|
||||
})
|
||||
|
||||
expr = expr.join('')
|
||||
if ($(this._$formulaInput).val()) expr = $(this._$formulaInput).val()
|
||||
|
||||
typeof this.props.onConfirm === 'function' && this.props.onConfirm(expr)
|
||||
typeof this.props.onConfirm === 'function' && this.props.onConfirm(expr.join(''))
|
||||
this.hide()
|
||||
}
|
||||
|
||||
|
@ -124,7 +115,7 @@ class FormulaDate extends RbAlert {
|
|||
<div className="form-group">
|
||||
<label className="text-bold">{$L('设置日期公式')}</label>
|
||||
<div className="input-group">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._base = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$base = c)}>
|
||||
{base.map((item) => {
|
||||
return (
|
||||
<option key={item[0]} value={item[0]}>
|
||||
|
@ -161,7 +152,7 @@ class FormulaDate extends RbAlert {
|
|||
</div>
|
||||
</div>
|
||||
<div className="form-group mb-1">
|
||||
<button type="button" className="btn btn-space btn-primary" onClick={() => this.confirm()}>
|
||||
<button type="button" className="btn btn-primary" onClick={() => this.confirm()}>
|
||||
{$L('确定')}
|
||||
</button>
|
||||
</div>
|
||||
|
@ -170,7 +161,7 @@ class FormulaDate extends RbAlert {
|
|||
}
|
||||
|
||||
confirm() {
|
||||
let expr = $(this._base).val()
|
||||
let expr = $(this._$base).val()
|
||||
if (!expr) return
|
||||
|
||||
if (this.state.calcOp) {
|
||||
|
|
|
@ -75,7 +75,7 @@ $(document).ready(function () {
|
|||
'DECIMAL': $L('货币'),
|
||||
'DATE': $L('日期'),
|
||||
'DATETIME': $L('日期时间'),
|
||||
'PICKLIST': $L('选项'),
|
||||
'PICKLIST': $L('下拉列表'),
|
||||
'CLASSIFICATION': $L('分类'),
|
||||
'MULTISELECT': $L('多选'),
|
||||
'REFERENCE': $L('引用'),
|
||||
|
|
|
@ -735,11 +735,17 @@ var $expired = function (date, offset) {
|
|||
*/
|
||||
var _$unthy = function (text) {
|
||||
if (!text) return null
|
||||
if (rb.env === 'dev') console.log(text)
|
||||
text = text.replace(/"/g, '"')
|
||||
text = text.replace(/\n/g, '\\n')
|
||||
try {
|
||||
var s = $.parseJSON(text)
|
||||
if (rb.env === 'dev') console.log(s)
|
||||
if (rb.env === 'dev') console.log(text, s)
|
||||
return s
|
||||
} catch (err) {
|
||||
console.log(text, err)
|
||||
return null
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取语言(PH_KEY)
|
||||
|
|
|
@ -38,7 +38,9 @@ $(document).ready(() => {
|
|||
})
|
||||
saveFilter(wpc.whenFilter)
|
||||
|
||||
renderContentComp({ sourceEntity: wpc.sourceEntity, content: wpc.actionContent })
|
||||
$.get(`/admin/robot/trigger/${wpc.configId}/actionContent`, (res) => {
|
||||
renderContentComp({ sourceEntity: wpc.sourceEntity, content: res.data })
|
||||
})
|
||||
|
||||
const $btn = $('.J_save').click(() => {
|
||||
if (!contentComp) return
|
||||
|
|
|
@ -31,7 +31,7 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
<div className="col-md-12 col-lg-9">
|
||||
<div className="row">
|
||||
<div className="col-5">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._targetEntity = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$targetEntity = c)}>
|
||||
{(this.state.targetEntities || []).map((item) => {
|
||||
const val = `${item[2]}.${item[0]}`
|
||||
return (
|
||||
|
@ -82,7 +82,7 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
</div>
|
||||
<div className="row">
|
||||
<div className="col-5">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._targetField = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$targetField = c)}>
|
||||
{(this.state.targetFields || []).map((item) => {
|
||||
return (
|
||||
<option key={item[0]} value={item[0]}>
|
||||
|
@ -95,7 +95,7 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
</div>
|
||||
<div className="col-2 pr-0">
|
||||
<span className="zmdi zmdi-forward zmdi-hc-rotate-180"></span>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._calcMode = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$calcMode = c)}>
|
||||
{Object.keys(CALC_MODES).map((item) => {
|
||||
return (
|
||||
<option key={item} value={item}>
|
||||
|
@ -112,7 +112,7 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
<p>{$L('计算公式')}</p>
|
||||
</div>
|
||||
<div className={this.state.calcMode === 'FORMULA' ? 'hide' : ''}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._sourceField = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$sourceField = c)}>
|
||||
{(this.state.sourceFields || []).map((item) => {
|
||||
return (
|
||||
<option key={item[0]} value={item[0]}>
|
||||
|
@ -136,7 +136,7 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
<label className="col-md-12 col-lg-3 col-form-label text-lg-right"></label>
|
||||
<div className="col-md-12 col-lg-9">
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input className="custom-control-input" type="checkbox" ref={(c) => (this._readonlyFields = c)} />
|
||||
<input className="custom-control-input" type="checkbox" ref={(c) => (this._$readonlyFields = c)} />
|
||||
<span className="custom-control-label">
|
||||
{$L('自动设置目标字段为只读')}
|
||||
<i className="zmdi zmdi-help zicon down-1" data-toggle="tooltip" title={$L('本选项仅针对表单有效')} />
|
||||
|
@ -163,7 +163,7 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
this.__select2 = []
|
||||
$.get(`/admin/robot/trigger/field-aggregation-entities?source=${this.props.sourceEntity}`, (res) => {
|
||||
this.setState({ targetEntities: res.data }, () => {
|
||||
const $s2te = $(this._targetEntity)
|
||||
const $s2te = $(this._$targetEntity)
|
||||
.select2({ placeholder: $L('选择目标实体') })
|
||||
.on('change', () => this._changeTargetEntity())
|
||||
|
||||
|
@ -178,13 +178,13 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
})
|
||||
|
||||
if (content) {
|
||||
$(this._readonlyFields).attr('checked', content.readonlyFields === true)
|
||||
$(this._$readonlyFields).attr('checked', content.readonlyFields === true)
|
||||
this._saveAdvFilter(content.dataFilter)
|
||||
}
|
||||
}
|
||||
|
||||
_changeTargetEntity() {
|
||||
const te = ($(this._targetEntity).val() || '').split('.')[1]
|
||||
const te = ($(this._$targetEntity).val() || '').split('.')[1]
|
||||
if (!te) return
|
||||
// 清空现有规则
|
||||
this.setState({ items: [] })
|
||||
|
@ -195,12 +195,12 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
|
||||
if (this.state.targetFields) {
|
||||
this.setState({ targetFields: res.data.target }, () => {
|
||||
$(this._calcMode).trigger('change')
|
||||
$(this._$calcMode).trigger('change')
|
||||
})
|
||||
} else {
|
||||
this.setState({ sourceFields: res.data.source, targetFields: res.data.target }, () => {
|
||||
const $s2sf = $(this._sourceField).select2({ placeholder: $L('选择源字段') })
|
||||
const $s2cm = $(this._calcMode)
|
||||
const $s2sf = $(this._$sourceField).select2({ placeholder: $L('选择源字段') })
|
||||
const $s2cm = $(this._$calcMode)
|
||||
.select2({ placeholder: $L('选择聚合方式') })
|
||||
.on('change', (e) => {
|
||||
this.setState({ calcMode: e.target.value })
|
||||
|
@ -213,7 +213,7 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
this.setState({ sourceFields: fs })
|
||||
}
|
||||
})
|
||||
const $s2tf = $(this._targetField).select2({ placeholder: $L('选择目标字段') })
|
||||
const $s2tf = $(this._$targetField).select2({ placeholder: $L('选择目标字段') })
|
||||
|
||||
$s2cm.trigger('change')
|
||||
|
||||
|
@ -257,9 +257,9 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
}
|
||||
|
||||
addItem() {
|
||||
const tf = $(this._targetField).val()
|
||||
const calc = $(this._calcMode).val()
|
||||
const sf = calc === 'FORMULA' ? null : $(this._sourceField).val()
|
||||
const tf = $(this._$targetField).val()
|
||||
const calc = $(this._$calcMode).val()
|
||||
const sf = calc === 'FORMULA' ? null : $(this._$sourceField).val()
|
||||
const formula = calc === 'FORMULA' ? $(this._$formula).attr('data-v') : null
|
||||
|
||||
if (!tf) return RbHighbar.create($L('请选择目标字段'))
|
||||
|
@ -270,7 +270,7 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
}
|
||||
|
||||
// 目标字段=源字段
|
||||
const tfFull = `${$(this._targetEntity).val().split('.')[0]}.${tf}`.replace('$PRIMARY$.', '')
|
||||
const tfFull = `${$(this._$targetEntity).val().split('.')[0]}.${tf}`.replace('$PRIMARY$.', '')
|
||||
if (sf === tfFull) return RbHighbar.create($L('目标字段与源字段不能为同一字段'))
|
||||
|
||||
const items = this.state.items || []
|
||||
|
@ -290,9 +290,9 @@ class ContentFieldAggregation extends ActionContentSpec {
|
|||
|
||||
buildContent() {
|
||||
const content = {
|
||||
targetEntity: $(this._targetEntity).val(),
|
||||
targetEntity: $(this._$targetEntity).val(),
|
||||
items: this.state.items,
|
||||
readonlyFields: $(this._readonlyFields).prop('checked'),
|
||||
readonlyFields: $(this._$readonlyFields).prop('checked'),
|
||||
dataFilter: this._advFilter__data,
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
<div className="col-md-12 col-lg-9">
|
||||
<div className="row">
|
||||
<div className="col-5">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._targetEntity = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$targetEntity = c)}>
|
||||
{(this.state.targetEntities || []).map((item) => {
|
||||
const val = `${item[2]}.${item[0]}`
|
||||
return (
|
||||
|
@ -85,7 +85,7 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
</div>
|
||||
<div className="row">
|
||||
<div className="col-5">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._targetField = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$targetField = c)}>
|
||||
{(this.state.targetFields || []).map((item) => {
|
||||
return (
|
||||
<option key={item.name} value={item.name}>
|
||||
|
@ -98,7 +98,7 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
</div>
|
||||
<div className="col-2 pr-0">
|
||||
<span className="zmdi zmdi-forward zmdi-hc-rotate-180"></span>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._updateMode = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$updateMode = c)}>
|
||||
{Object.keys(UPDATE_MODES).map((item) => {
|
||||
return (
|
||||
<option key={item} value={item}>
|
||||
|
@ -111,7 +111,7 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
</div>
|
||||
<div className={`col-5 ${this.state.targetField ? '' : 'hide'}`}>
|
||||
<div className={this.state.updateMode === 'FIELD' ? '' : 'hide'}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._sourceField = c)}>
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$sourceField = c)}>
|
||||
{(this.state.sourceFields || []).map((item) => {
|
||||
return (
|
||||
<option key={item.name} value={item.name}>
|
||||
|
@ -124,13 +124,13 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
</div>
|
||||
<div className={this.state.updateMode === 'VFIXED' ? '' : 'hide'}>
|
||||
{this.state.updateMode === 'VFIXED' && this.state.targetField && (
|
||||
<FieldValueSet entity={this.state.targetEntity} field={this.state.targetField} placeholder={$L('固定值')} ref={(c) => (this._sourceValue = c)} />
|
||||
<FieldValueSet entity={this.state.targetEntity} field={this.state.targetField} placeholder={$L('固定值')} ref={(c) => (this._$sourceValue = c)} />
|
||||
)}
|
||||
<p>{$L('固定值')}</p>
|
||||
</div>
|
||||
<div className={this.state.updateMode === 'FORMULA' ? '' : 'hide'}>
|
||||
{this.state.updateMode === 'FORMULA' && this.state.targetField && (
|
||||
<FieldFormula fields={this.__sourceFieldsCache} field={this.state.targetField} ref={(c) => (this._sourceFormula = c)} />
|
||||
<FieldFormula fields={this.__sourceFieldsCache} field={this.state.targetField} ref={(c) => (this._$sourceFormula = c)} />
|
||||
)}
|
||||
<p>{$L('计算公式')}</p>
|
||||
</div>
|
||||
|
@ -147,7 +147,7 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
<label className="col-md-12 col-lg-3 col-form-label text-lg-right"></label>
|
||||
<div className="col-md-12 col-lg-9">
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input className="custom-control-input" type="checkbox" ref={(c) => (this._readonlyFields = c)} />
|
||||
<input className="custom-control-input" type="checkbox" ref={(c) => (this._$readonlyFields = c)} />
|
||||
<span className="custom-control-label">
|
||||
{$L('自动设置目标字段为只读')}
|
||||
<i className="zmdi zmdi-help zicon down-1" data-toggle="tooltip" title={$L('本选项仅针对表单有效')} />
|
||||
|
@ -165,7 +165,7 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
this.__select2 = []
|
||||
$.get(`/admin/robot/trigger/field-writeback-entities?source=${this.props.sourceEntity}`, (res) => {
|
||||
this.setState({ targetEntities: res.data }, () => {
|
||||
const $s2te = $(this._targetEntity)
|
||||
const $s2te = $(this._$targetEntity)
|
||||
.select2({ placeholder: $L('选择目标实体') })
|
||||
.on('change', () => this._changeTargetEntity())
|
||||
|
||||
|
@ -180,12 +180,12 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
})
|
||||
|
||||
if (content) {
|
||||
$(this._readonlyFields).attr('checked', content.readonlyFields === true)
|
||||
$(this._$readonlyFields).attr('checked', content.readonlyFields === true)
|
||||
}
|
||||
}
|
||||
|
||||
_changeTargetEntity() {
|
||||
const te = ($(this._targetEntity).val() || '').split('.')[1]
|
||||
const te = ($(this._$targetEntity).val() || '').split('.')[1]
|
||||
if (!te) return
|
||||
// 清空现有规则
|
||||
this.setState({ targetEntity: te, items: [] })
|
||||
|
@ -196,19 +196,19 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
|
||||
if (this.state.targetFields) {
|
||||
this.setState({ targetFields: res.data.target }, () => {
|
||||
$(this._targetField).trigger('change')
|
||||
$(this._$targetField).trigger('change')
|
||||
})
|
||||
} else {
|
||||
this.setState({ sourceFields: res.data.source, targetFields: res.data.target }, () => {
|
||||
const $s2tf = $(this._targetField)
|
||||
const $s2tf = $(this._$targetField)
|
||||
.select2({ placeholder: $L('选择目标字段') })
|
||||
.on('change', () => this._changeTargetField())
|
||||
const $s2um = $(this._updateMode)
|
||||
const $s2um = $(this._$updateMode)
|
||||
.select2({ placeholder: $L('选择更新方式') })
|
||||
.on('change', (e) => {
|
||||
this.setState({ updateMode: e.target.value })
|
||||
})
|
||||
const $s2sf = $(this._sourceField).select2({ placeholder: $L('选择源字段') })
|
||||
const $s2sf = $(this._$sourceField).select2({ placeholder: $L('选择源字段') })
|
||||
|
||||
$s2tf.trigger('change')
|
||||
this.__select2.push($s2tf)
|
||||
|
@ -224,7 +224,7 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
}
|
||||
|
||||
_changeTargetField() {
|
||||
const tf = $(this._targetField).val()
|
||||
const tf = $(this._$targetField).val()
|
||||
if (!tf) return
|
||||
const targetField = this.state.targetFields.find((x) => x.name === tf)
|
||||
|
||||
|
@ -237,29 +237,29 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
})
|
||||
|
||||
this.setState({ targetField: null, sourceFields: sourceFields }, () => {
|
||||
if (sourceFields.length > 0) $(this._sourceField).val(sourceFields[0].name)
|
||||
if (sourceFields.length > 0) $(this._$sourceField).val(sourceFields[0].name)
|
||||
// 强制销毁后再渲染
|
||||
this.setState({ targetField: targetField })
|
||||
})
|
||||
}
|
||||
|
||||
addItem() {
|
||||
const tf = $(this._targetField).val()
|
||||
const mode = $(this._updateMode).val()
|
||||
const tf = $(this._$targetField).val()
|
||||
const mode = $(this._$updateMode).val()
|
||||
if (!tf) return RbHighbar.create($L('请选择目标字段'))
|
||||
|
||||
let sourceField = null
|
||||
if (mode === 'FIELD') {
|
||||
sourceField = $(this._sourceField).val()
|
||||
sourceField = $(this._$sourceField).val()
|
||||
|
||||
// 目标字段=源字段
|
||||
const tfFull = `${$(this._targetEntity).val().split('.')[0]}.${tf}`.replace('$PRIMARY$.', '')
|
||||
const tfFull = `${$(this._$targetEntity).val().split('.')[0]}.${tf}`.replace('$PRIMARY$.', '')
|
||||
if (tfFull === sourceField) return RbHighbar.create($L('目标字段与源字段不能为同一字段'))
|
||||
} else if (mode === 'FORMULA') {
|
||||
sourceField = this._sourceFormula.val()
|
||||
sourceField = this._$sourceFormula.val()
|
||||
if (!sourceField) return RbHighbar.create($L('请输入计算公式'))
|
||||
} else if (mode === 'VFIXED') {
|
||||
sourceField = this._sourceValue.val()
|
||||
sourceField = this._$sourceValue.val()
|
||||
if (!sourceField) return
|
||||
} else if (mode === 'VNULL') {
|
||||
const tf2 = this.state.targetFields.find((x) => x.name === tf)
|
||||
|
@ -271,7 +271,7 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
if (exists) return RbHighbar.create($L('目标字段重复'))
|
||||
|
||||
items.push({ targetField: tf, updateMode: mode, sourceField: sourceField })
|
||||
this.setState({ items: items })
|
||||
this.setState({ items: items }, () => this._$sourceFormula.clear())
|
||||
}
|
||||
|
||||
delItem(targetField) {
|
||||
|
@ -283,9 +283,9 @@ class ContentFieldWriteback extends ActionContentSpec {
|
|||
|
||||
buildContent() {
|
||||
const content = {
|
||||
targetEntity: $(this._targetEntity).val(),
|
||||
targetEntity: $(this._$targetEntity).val(),
|
||||
items: this.state.items,
|
||||
readonlyFields: $(this._readonlyFields).prop('checked'),
|
||||
readonlyFields: $(this._$readonlyFields).prop('checked'),
|
||||
}
|
||||
if (!content.targetEntity) {
|
||||
RbHighbar.create($L('请选择目标实体'))
|
||||
|
@ -314,37 +314,53 @@ class FieldFormula extends React.Component {
|
|||
|
||||
render() {
|
||||
const fieldType = this.state.field.type
|
||||
if (fieldType === 'DATE' || fieldType === 'DATETIME' || fieldType === 'NUMBER' || fieldType === 'DECIMAL') {
|
||||
return <div className="form-control-plaintext formula" _title={$L('计算公式')} ref={(c) => (this._formula = c)} onClick={() => this.showFormula()}></div>
|
||||
} else {
|
||||
// @see DisplayType.java
|
||||
if (fieldType === 'AVATAR' || fieldType === 'IMAGE' || fieldType === 'FILE') {
|
||||
return <div className="form-control-plaintext text-danger">{$L('暂不支持')}</div>
|
||||
} else {
|
||||
return (
|
||||
<div className="form-control-plaintext formula" _title={$L('计算公式')} onClick={() => this.show(this.state.field.type)}>
|
||||
{this.state.valueText}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
showFormula() {
|
||||
const fieldVars = []
|
||||
show(ft) {
|
||||
const ndVars = []
|
||||
this.props.fields.forEach((item) => {
|
||||
if (item.name !== this.state.field.name && ['NUMBER', 'DECIMAL', 'DATE', 'DATETIME'].includes(item.type)) {
|
||||
fieldVars.push([item.name, item.label, item.type])
|
||||
if (['NUMBER', 'DECIMAL', 'DATE', 'DATETIME'].includes(item.type)) {
|
||||
ndVars.push([item.name, item.label, item.type])
|
||||
}
|
||||
})
|
||||
|
||||
renderRbcomp(<FormulaCalc2 fields={fieldVars} onConfirm={(expr) => this._confirm(expr)} />)
|
||||
// 数字、日期支持计算器模式
|
||||
const ndType = ['NUMBER', 'DECIMAL', 'DATE', 'DATETIME'].includes(ft)
|
||||
renderRbcomp(<FormulaCalcWithCode fields={ndVars} forceCode={!ndType} onConfirm={(expr) => this.onConfirm(expr)} />)
|
||||
}
|
||||
|
||||
_confirm(expr) {
|
||||
onConfirm(expr) {
|
||||
this._value = expr
|
||||
$(this._formula).text(FieldFormula.formatText(expr, this.props.fields))
|
||||
this.setState({ valueText: FieldFormula.formatText(expr, this.props.fields) })
|
||||
}
|
||||
|
||||
val() {
|
||||
return this._value
|
||||
}
|
||||
|
||||
clear() {
|
||||
this._value = null
|
||||
this.setState({ valueText: null })
|
||||
}
|
||||
}
|
||||
|
||||
FieldFormula.formatText = function (formula, fields) {
|
||||
if (!formula) return
|
||||
|
||||
// CODE
|
||||
if (formula.startsWith('{{{{')) {
|
||||
return FormulaCode.textCode(formula)
|
||||
}
|
||||
// DATE
|
||||
if (formula.includes('#')) {
|
||||
const fs = formula.split('#')
|
||||
|
@ -355,15 +371,27 @@ FieldFormula.formatText = function (formula, fields) {
|
|||
else {
|
||||
const fs = []
|
||||
fields.forEach((item) => fs.push([item.name, item.label]))
|
||||
return FormulaCalc2.textFormula(formula, fs)
|
||||
return FormulaCalcWithCode.textFormula(formula, fs)
|
||||
}
|
||||
}
|
||||
|
||||
// ~ 公式编辑器
|
||||
// eslint-disable-next-line no-undef
|
||||
class FormulaCalc2 extends FormulaCalc {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
class FormulaCalcWithCode extends FormulaCalc {
|
||||
renderContent() {
|
||||
if (this.props.forceCode || this.state.useCode) {
|
||||
return (
|
||||
<FormulaCode
|
||||
initCode={this.props.initCode}
|
||||
onConfirm={(code) => {
|
||||
this.props.onConfirm(`{{{{${code}}}}}`)
|
||||
this.hide()
|
||||
}}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return super.renderContent()
|
||||
}
|
||||
}
|
||||
|
||||
renderExtraKeys() {
|
||||
|
@ -382,7 +410,8 @@ class FormulaCalc2 extends FormulaCalc {
|
|||
DATESUB
|
||||
</a>
|
||||
<div className="dropdown-divider"></div>
|
||||
<a className="dropdown-item" target="_blank" href="https://getrebuild.com/docs/admin/triggers#%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0%20(%E6%95%B0%E6%8D%AE%E8%BD%AC%E5%86%99)%20~~v2.3">
|
||||
<a className="dropdown-item" target="_blank" href="https://getrebuild.com/docs/admin/triggers#%E5%85%AC%E5%BC%8F%E7%BC%96%E8%BE%91%E5%99%A8">
|
||||
<i className="zmdi zmdi-help icon"></i>
|
||||
{$L('如何使用函数')}
|
||||
</a>
|
||||
</div>
|
||||
|
@ -405,7 +434,7 @@ class FormulaCalc2 extends FormulaCalc {
|
|||
</div>
|
||||
</li>
|
||||
<li className="list-inline-item">
|
||||
<a onClick={() => this.handleInput('`')}>`</a>
|
||||
<a onClick={() => this.handleInput('"')}>"</a>
|
||||
</li>
|
||||
<li className="list-inline-item">
|
||||
<a onClick={() => this.handleInput(',')}>,</a>
|
||||
|
@ -415,17 +444,24 @@ class FormulaCalc2 extends FormulaCalc {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this._$fields) {
|
||||
$(this._$fields).css('max-height', 221)
|
||||
|
||||
const $btn = $(`<a class="switch-code-btn" title="${$L('使用高级计算公式')}"><i class="icon zmdi zmdi-edit"></i></a>`)
|
||||
$(this._$formula).addClass('switch-code').after($btn)
|
||||
$btn.click(() => this.setState({ useCode: true }))
|
||||
}
|
||||
|
||||
super.componentDidMount()
|
||||
}
|
||||
|
||||
handleInput(v) {
|
||||
if (['DATEDIFF', 'DATEADD', 'DATESUB', ',', '`'].includes(v)) {
|
||||
$(`<i class="v oper" data-v="${v}">${v}</em>`).appendTo(this._$formula)
|
||||
if (['DATEDIFF', 'DATEADD', 'DATESUB', ',', '"'].includes(v)) {
|
||||
$(`<i class="v oper">${v}</em>`).appendTo(this._$formula).attr('data-v', v)
|
||||
|
||||
if (['DATEDIFF', 'DATEADD', 'DATESUB'].includes(v)) {
|
||||
setTimeout(() => this.handleInput('('), 400)
|
||||
setTimeout(() => this.handleInput('`'), 600)
|
||||
setTimeout(() => this.handleInput('('), 300)
|
||||
setTimeout(() => this.handleInput('"'), 400)
|
||||
}
|
||||
} else {
|
||||
super.handleInput(v)
|
||||
|
@ -433,13 +469,44 @@ class FormulaCalc2 extends FormulaCalc {
|
|||
}
|
||||
}
|
||||
|
||||
class FormulaCode extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<textarea className="formula-code" ref={(c) => (this._$formulaInput = c)} defaultValue={this.props.initCode || ''} maxLength="2000" placeholder="// Support AviatorScript" autoFocus />
|
||||
<div className="row mt-1">
|
||||
<div className="col pt-2">
|
||||
<span className="d-inline-block">
|
||||
<a href="https://getrebuild.com/docs/admin/triggers#%E9%AB%98%E7%BA%A7%E8%AE%A1%E7%AE%97%E5%85%AC%E5%BC%8F" target="_blank" className="link">
|
||||
{$L('如何使用高级计算公式')}
|
||||
</a>
|
||||
<i className="zmdi zmdi-help zicon"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div className="col text-right">
|
||||
<button type="button" className="btn btn-primary" onClick={() => this.confirm()}>
|
||||
{$L('确定')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
confirm() {
|
||||
typeof this.props.onConfirm === 'function' && this.props.onConfirm($val(this._$formulaInput))
|
||||
}
|
||||
|
||||
// 格式化显示
|
||||
static textCode(code) {
|
||||
code = code.substr(4, code.length - 8) // Remove {{{{ xxx }}}}
|
||||
code = code.replace(/\n/gi, '<br/>').replace(/( )/gi, ' ')
|
||||
return <code style={{ lineHeight: 1.2 }} dangerouslySetInnerHTML={{ __html: code }} />
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
renderContentComp = function (props) {
|
||||
// // 禁用`删除`
|
||||
// $('.J_when .custom-control-input').each(function () {
|
||||
// if (~~$(this).val() === 2) $(this).attr('disabled', true)
|
||||
// })
|
||||
|
||||
renderRbcomp(<ContentFieldWriteback {...props} />, 'react-content', function () {
|
||||
// eslint-disable-next-line no-undef
|
||||
contentComp = this
|
||||
|
|
Loading…
Reference in a new issue