mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 07:25:54 +08:00
List1 view (#697)
* style: list1-view * Update notifications.js * be: _onFieldValueChangeCall timer * feat: entity-excel * feat: entity from excel * field-new2 * $select2MatcherAll * select2 icon * remove _onFieldValueChangeCall timer
This commit is contained in:
parent
45d7783761
commit
f3b117f864
2
@rbv
2
@rbv
|
@ -1 +1 @@
|
|||
Subproject commit 1055750e8b4add3af4d1ce51a3f1d73f1643d99a
|
||||
Subproject commit 8d66ac27ecebf958e3675fd44c39a9d6670d2ed4
|
|
@ -505,8 +505,8 @@ public class NavBuilder extends NavManager {
|
|||
StringBuilder topNavHtml = new StringBuilder();
|
||||
|
||||
for (Object[] nd : topNav) {
|
||||
String url = AppUtils.getContextPath("/app/home?n=" + nd[0]);
|
||||
if (nd[1] != null) url += "&d=" + nd[1];
|
||||
String url = AppUtils.getContextPath("/app/home?def=" + nd[0]);
|
||||
if (nd[1] != null) url += ":" + nd[1];
|
||||
topNavHtml.append(String.format(
|
||||
"<li class=\"nav-item\" data-id=\"%s\"><a class=\"nav-link text-ellipsis\" href=\"%s\">%s</a></li>", nd[0], url, nd[2]));
|
||||
}
|
||||
|
|
|
@ -56,15 +56,12 @@ public class Entity2Schema extends Field2Schema {
|
|||
* @return Returns 实体名称
|
||||
*/
|
||||
public String createEntity(String entityName, String entityLabel, String comments, String mainEntity, boolean haveNameField, boolean haveSeriesField) {
|
||||
entityName = StringUtils.trim(entityName);
|
||||
entityLabel = StringUtils.trim(entityLabel);
|
||||
|
||||
if (!License.isCommercial() && MetadataHelper.getEntities().length >= 100) {
|
||||
throw new NeedRbvException(Language.L("实体数量超出免费版限制"));
|
||||
}
|
||||
|
||||
entityLabel = CommonsUtils.maxstr(StringUtils.trim(entityLabel), 40);
|
||||
entityName = StringUtils.trim(entityName);
|
||||
entityLabel = StringUtils.trim(entityLabel);
|
||||
|
||||
if (entityName != null) {
|
||||
if (MetadataHelper.containsEntity(entityName)) {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package com.rebuild.core.metadata.impl;
|
||||
|
||||
import cn.devezhao.persist4j.Entity;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.rebuild.core.metadata.MetadataHelper;
|
||||
import com.rebuild.core.metadata.easymeta.DisplayType;
|
||||
import com.rebuild.core.privileges.UserHelper;
|
||||
import com.rebuild.core.support.i18n.Language;
|
||||
import com.rebuild.utils.JSONUtils;
|
||||
import com.rebuild.utils.RbAssert;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* EXCEL 导入实体
|
||||
*
|
||||
* @author RB
|
||||
* @see CopyEntity
|
||||
* @since 2023/12/18
|
||||
*/
|
||||
@Slf4j
|
||||
public class ExcelEntity extends Entity2Schema {
|
||||
|
||||
/**
|
||||
* @param entityName
|
||||
* @param fields
|
||||
* @return
|
||||
*/
|
||||
public String imports(String entityName, JSONArray fields) {
|
||||
final ID user = getUser();
|
||||
RbAssert.isAllow(UserHelper.isSuperAdmin(user), Language.L("仅超级管理员可操作"));
|
||||
|
||||
// 1.实体
|
||||
String uniqueEntityName = createEntity(null, entityName, null, null, false, false);
|
||||
Entity entityNew = MetadataHelper.getEntity(uniqueEntityName);
|
||||
|
||||
// 2.字段
|
||||
try {
|
||||
for (Object o : fields) {
|
||||
JSONArray item = (JSONArray) o;
|
||||
String name = item.getString(0);
|
||||
String type = item.getString(1);
|
||||
|
||||
String refEntityOrClass = item.size() > 2 ? item.getString(2) : null;
|
||||
JSON extConfig = null;
|
||||
if ("CLASSIFICATION".equals(type)) {
|
||||
Assert.notNull(refEntityOrClass, "[refEntityOrClass] cannot be null");
|
||||
ID dataId = ID.valueOf(refEntityOrClass);
|
||||
extConfig = JSONUtils.toJSONObject(EasyFieldConfigProps.CLASSIFICATION_USE, dataId);
|
||||
refEntityOrClass = null;
|
||||
}
|
||||
|
||||
createField(entityNew, name, DisplayType.valueOf(type), null, refEntityOrClass, extConfig);
|
||||
}
|
||||
|
||||
} catch (Throwable ex) {
|
||||
// DROP
|
||||
dropEntity(entityNew, true);
|
||||
|
||||
if (ex instanceof MetadataModificationException) {
|
||||
throw (MetadataModificationException) ex;
|
||||
}
|
||||
throw new MetadataModificationException(Language.L("无法导入实体 : %s", ex.getLocalizedMessage()));
|
||||
}
|
||||
|
||||
return uniqueEntityName;
|
||||
}
|
||||
}
|
|
@ -100,7 +100,7 @@ public class Field2Schema extends SetUser {
|
|||
* @return
|
||||
*/
|
||||
public String createField(Entity entity, String fieldLabel, String fieldName, DisplayType type, String comments, String refEntity, JSON extConfig) {
|
||||
fieldLabel = StringUtils.trim(fieldLabel);
|
||||
fieldLabel = CommonsUtils.maxstr(StringUtils.trim(fieldLabel), 40);
|
||||
fieldName = StringUtils.trim(fieldName);
|
||||
|
||||
if (StringUtils.length(fieldName) < 4) fieldName = toPinyinName(fieldLabel);
|
||||
|
|
|
@ -100,6 +100,7 @@ public abstract class ObservableService extends Observable implements ServiceSpe
|
|||
if (countObservers() > 0) {
|
||||
deleted = EntityHelper.forUpdate(recordId, currentUser, Boolean.FALSE);
|
||||
deleted = recordSnap(deleted, true);
|
||||
if (deleted == null) return 0;
|
||||
|
||||
// 删除前触发,做一些状态保持
|
||||
setChanged();
|
||||
|
|
|
@ -30,6 +30,7 @@ public class OverOperatorType {
|
|||
* 日期加
|
||||
*/
|
||||
static class DateAdd extends AbstractFunction {
|
||||
private static final long serialVersionUID = -7871678038170332371L;
|
||||
@Override
|
||||
public String getName() {
|
||||
return OperatorType.ADD.getToken();
|
||||
|
@ -54,6 +55,7 @@ public class OverOperatorType {
|
|||
* 日期减
|
||||
*/
|
||||
static class DateSub extends AbstractFunction {
|
||||
private static final long serialVersionUID = 8208361199770129766L;
|
||||
@Override
|
||||
public String getName() {
|
||||
return OperatorType.SUB.getToken();
|
||||
|
|
|
@ -82,9 +82,8 @@ public class CommonsUtils {
|
|||
* @return
|
||||
*/
|
||||
public static String maxstr(String text, int maxLength) {
|
||||
if (text.length() > maxLength) {
|
||||
return text.substring(0, maxLength);
|
||||
}
|
||||
if (text == null) return null;
|
||||
if (text.length() > maxLength) return text.substring(0, maxLength);
|
||||
return text;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,11 +93,12 @@ public class DataImportController extends BaseController {
|
|||
}
|
||||
|
||||
DataFileParser parser;
|
||||
int count = -1;
|
||||
int count;
|
||||
List<Cell[]> preview;
|
||||
try {
|
||||
parser = new DataFileParser(tmp);
|
||||
preview = parser.parse(11);
|
||||
preview = parser.parse(101);
|
||||
count = parser.getRowsCount();
|
||||
} catch (Exception ex) {
|
||||
log.error("Parse excel error : " + file, ex);
|
||||
return RespBody.error(Language.L("无法解析数据,请检查数据文件格式"));
|
||||
|
|
|
@ -13,6 +13,7 @@ import cn.devezhao.persist4j.Field;
|
|||
import cn.devezhao.persist4j.Record;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.rebuild.api.RespBody;
|
||||
import com.rebuild.core.Application;
|
||||
|
@ -30,6 +31,7 @@ import com.rebuild.core.metadata.easymeta.EasyMetaFactory;
|
|||
import com.rebuild.core.metadata.impl.CopyEntity;
|
||||
import com.rebuild.core.metadata.impl.EasyEntityConfigProps;
|
||||
import com.rebuild.core.metadata.impl.Entity2Schema;
|
||||
import com.rebuild.core.metadata.impl.ExcelEntity;
|
||||
import com.rebuild.core.metadata.impl.MetaEntityService;
|
||||
import com.rebuild.core.privileges.UserHelper;
|
||||
import com.rebuild.core.rbstore.MetaSchemaGenerator;
|
||||
|
@ -356,4 +358,14 @@ public class MetaEntityController extends EntityController {
|
|||
mv.getModel().put("entities", entities);
|
||||
return mv;
|
||||
}
|
||||
|
||||
@PostMapping("entity/entity-excel")
|
||||
public RespBody entityExcelEvalft(HttpServletRequest request) {
|
||||
final JSON post = ServletUtils.getRequestJson(request);
|
||||
String entityLabel = ((JSONObject) post).getString("entityLabel");
|
||||
JSONArray fields = ((JSONObject) post).getJSONArray("fields");
|
||||
|
||||
String entityName = new ExcelEntity().imports(entityLabel, fields);
|
||||
return RespBody.ok(entityName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ import com.rebuild.core.support.RebuildConfiguration;
|
|||
import com.rebuild.utils.AppUtils;
|
||||
import com.rebuild.utils.CommonsUtils;
|
||||
import com.rebuild.web.BaseController;
|
||||
import com.rebuild.web.IdParam;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
@ -87,11 +87,13 @@ public class CommonPageView extends BaseController {
|
|||
}
|
||||
|
||||
@GetMapping("/app/home")
|
||||
public void appHome(@IdParam(name = "n", required = false) ID useNav,
|
||||
@IdParam(name = "d", required = false) ID useDash,
|
||||
public void appHome(@RequestParam(name = "def", required = false) String def,
|
||||
HttpServletResponse response) throws IOException {
|
||||
addCookie("AppHome.Nav", useNav, response);
|
||||
addCookie("AppHome.Dash", useDash, response);
|
||||
if (def != null && def.length() >= 20) {
|
||||
String[] defs = def.split(":");
|
||||
addCookie("AppHome.Nav", ID.isId(defs[0]) ? ID.valueOf(defs[0]) : null, response);
|
||||
addCookie("AppHome.Dash", defs.length > 1 && ID.isId(defs[1]) ? ID.valueOf(defs[1]) : null, response);
|
||||
}
|
||||
response.sendRedirect("../dashboard/home");
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,33 @@
|
|||
.new-entity .card.entity .card-body .ml-7 .text-muted {
|
||||
display: none;
|
||||
}
|
||||
.entity-new2 .dialog-footer {
|
||||
margin: 15px -35px 10px;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.entity-new2 .init-models {
|
||||
margin-left: -10px;
|
||||
margin-right: -10px;
|
||||
}
|
||||
.table.table-excel th,
|
||||
.table.table-excel td {
|
||||
padding: 3px;
|
||||
border-width: 1px;
|
||||
color: #222;
|
||||
max-width: 200px;
|
||||
}
|
||||
.table.table-excel th {
|
||||
text-align: center;
|
||||
background-color: #dee2e6;
|
||||
color: #444;
|
||||
}
|
||||
.table.table-excel .form-control {
|
||||
width: 100%;
|
||||
min-width: 140px;
|
||||
/* padding: 4px; */
|
||||
/* height: auto !important; */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -113,6 +140,9 @@
|
|||
isSuperAdmin: '[[${isSuperAdmin}]]' === 'true',
|
||||
}
|
||||
</script>
|
||||
<script th:src="@{/assets/js/admin/init-models.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/field-type.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/entity-new2.js}" type="text/babel"></script>
|
||||
<script type="text/babel">
|
||||
$(document).ready(function () {
|
||||
const NO_TAG = '__'
|
||||
|
@ -138,6 +168,7 @@
|
|||
if (!this.builtin) render_entity(this)
|
||||
})
|
||||
|
||||
let _EntityNew2
|
||||
const $new = render_entity({
|
||||
icon: 'plus',
|
||||
entityLabel: $L('添加实体'),
|
||||
|
@ -147,9 +178,20 @@
|
|||
.find('a.card')
|
||||
.attr('href', 'javascript:;')
|
||||
.click(function () {
|
||||
if (window.__PageConfig.isSuperAdmin) RbModal.create('/p/admin/metadata/entity-new', $L('添加实体'))
|
||||
else RbHighbar.error('仅超级管理员可添加实体')
|
||||
if (window.__PageConfig.isSuperAdmin) {
|
||||
if (_EntityNew2) {
|
||||
_EntityNew2.show()
|
||||
} else {
|
||||
renderRbcomp(<EntityNew2 />, null, function () {
|
||||
_EntityNew2 = this
|
||||
})
|
||||
}
|
||||
} else {
|
||||
RbHighbar.error('仅超级管理员可添加实体')
|
||||
}
|
||||
})
|
||||
.find('.more-action')
|
||||
.remove()
|
||||
|
||||
delete groups[NO_TAG]
|
||||
|
||||
|
@ -169,12 +211,13 @@
|
|||
href: `entity/${item.entityName}/base`,
|
||||
title: item.comments || null,
|
||||
})
|
||||
$t.find('.icon').addClass(`zmdi-${item.icon}`)
|
||||
$t.find('.icon:eq(0)').addClass(`zmdi-${item.icon}`)
|
||||
$t.find('span').text(item.entityLabel)
|
||||
$t.find('p').text(item.comments || '-')
|
||||
if (item.comments) $t.find('p').text(item.comments)
|
||||
else $t.find('p').html(' ')
|
||||
|
||||
if (item.builtin) $(`<i class="badge badge-pill badge-secondary font-weight-light">${$L('内置')}</i>`).appendTo($t.find('a.card'))
|
||||
if (!!item.detailEntity) $(`<i class="badge badge-pill badge-secondary font-weight-light">${$L('明细')}</i>`).appendTo($t.find('a.card'))
|
||||
if (item.detailEntity) $(`<i class="badge badge-pill badge-secondary font-weight-light">${$L('明细')}</i>`).appendTo($t.find('a.card'))
|
||||
return $t
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:replace="~{/_include/header}" />
|
||||
<title>[[${bundle.L('添加实体')}]]</title>
|
||||
<style>
|
||||
.text-muted.desc {
|
||||
max-width: 80%;
|
||||
}
|
||||
.init-models {
|
||||
margin: 0 -10px;
|
||||
}
|
||||
.dialog-footer {
|
||||
margin: 15px -40px 0;
|
||||
padding-top: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="dialog">
|
||||
<div class="main-content pt-1">
|
||||
<div class="tab-container">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item"><a class="nav-link active" href="#MANUAL" data-toggle="tab">[[${bundle.L('手动')}]]</a></li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#COPY" data-toggle="tab">[[${bundle.L('复制')}]]</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link J_imports" href="#IMPORTS" data-toggle="tab"> <i class="icon zmdi zmdi-cloud-outline-alt"></i> [[${bundle.L('从 RB 仓库导入')}]] </a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content m-0 pb-0">
|
||||
<div class="tab-pane active" id="MANUAL">
|
||||
<div class="form">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('实体名称')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<input class="form-control form-control-sm" type="text" id="entityLabel" maxlength="40" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('备注')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<textarea class="form-control form-control-sm row2x" id="comments" maxlength="100" th:placeholder="${bundle.L('(选填)')}"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row pt-2">
|
||||
<label class="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div class="col-sm-7">
|
||||
<label class="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input class="custom-control-input" type="checkbox" id="nameField" />
|
||||
<span class="custom-control-label">[[${bundle.L('添加一个名称字段')}]]</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row pt-0">
|
||||
<label class="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div class="col-sm-7">
|
||||
<label class="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input class="custom-control-input" type="checkbox" id="seriesField" />
|
||||
<span class="custom-control-label">[[${bundle.L('添加一个自动编号字段')}]]</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row pt-0">
|
||||
<label class="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div class="col-sm-7">
|
||||
<label class="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input class="custom-control-input" type="checkbox" id="isDetail" />
|
||||
<span class="custom-control-label">
|
||||
[[${bundle.L('这是明细实体')}]]
|
||||
<i class="zmdi zmdi-help zicon" data-toggle="tooltip" th:title="${bundle.L('通过明细实体可以更好的组织业务关系。例如订单明细通常依附于订单,而非独立存在')}"></i>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row J_mainEntity hide">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('选择主实体')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control form-control-sm" id="mainEntity"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row footer">
|
||||
<div class="col-sm-7 offset-sm-3">
|
||||
<button class="btn btn-primary new" type="button">[[${bundle.L('确定')}]]</button>
|
||||
<button class="btn btn-link" type="button" onclick="parent.RbModal.hide()">[[${bundle.L('取消')}]]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="COPY">
|
||||
<div class="form">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('复制哪个实体')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control form-control-sm" id="copySourceEntity"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('实体名称')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<input class="form-control form-control-sm" type="text" id="newEntityLabel" maxlength="40" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row hide J_newDetailLabel">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('明细实体名称')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<input class="form-control form-control-sm" type="text" id="newDetailLabel" maxlength="40" th:placeholder="${bundle.L('(选填)')}" />
|
||||
<p class="form-text">[[${bundle.L('不填写则不复制明细实体')}]]</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row footer">
|
||||
<div class="col-sm-7 offset-sm-3">
|
||||
<button class="btn btn-primary copy" type="button">[[${bundle.L('确定')}]]</button>
|
||||
<button class="btn btn-link" type="button" onclick="parent.RbModal.hide()">[[${bundle.L('取消')}]]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="IMPORTS">
|
||||
<div id="metaschemas"></div>
|
||||
<div class="mt-2 text-right hide">
|
||||
<a href="https://getrebuild.com/market/go/1220-rb-store" class="link" target="_blank">[[${bundle.L('提交数据到 RB 仓库')}]]</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:replace="~{/_include/footer}" />
|
||||
<script th:src="@{/assets/js/admin/init-models.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/entity-new.js}" type="text/babel"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,72 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<th:block th:replace="~{/_include/header}" />
|
||||
<title>[[${bundle.L('添加字段')}]]</title>
|
||||
<style>
|
||||
.select2-container--default .select2-results > .select2-results__options {
|
||||
max-height: 151px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="dialog">
|
||||
<div class="main-content">
|
||||
<form>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('字段名称')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<input class="form-control form-control-sm" type="text" id="fieldLabel" maxlength="40" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('字段类型')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control form-control-sm" id="type"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row hide J_dt-REFERENCE J_dt-N2NREFERENCE">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('选择引用实体')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control form-control-sm" id="refEntity"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row hide J_dt-CLASSIFICATION">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('选择分类数据')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<select class="form-control form-control-sm" id="refClassification"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row hide J_dt-STATE">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('状态类 (StateSpec)')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<input class="form-control form-control-sm" type="text" id="stateClass" placeholder="com.rebuild.core.support.state.HowtoState" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-3 col-form-label text-sm-right">[[${bundle.L('备注')}]]</label>
|
||||
<div class="col-sm-7">
|
||||
<textarea class="form-control form-control-sm row2x" id="comments" maxlength="100" th:placeholder="${bundle.L('(选填)')}"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row pb-1">
|
||||
<label class="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div class="col-sm-7">
|
||||
<label class="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input class="custom-control-input" type="checkbox" id="saveAndNew" />
|
||||
<span class="custom-control-label">[[${bundle.L('继续添加下一个')}]]</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row footer">
|
||||
<div class="col-sm-7 offset-sm-3">
|
||||
<button class="btn btn-primary" type="button">[[${bundle.L('确定')}]]</button>
|
||||
<button class="btn btn-link" type="button" onclick="parent.RbModal.hide()">[[${bundle.L('取消')}]]</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<th:block th:replace="~{/_include/footer}" />
|
||||
<script th:src="@{/assets/js/metadata/field-type.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/field-new.js}" type="text/babel"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -52,7 +52,7 @@
|
|||
<div class="btn-group bosskey-show">
|
||||
<button class="btn btn-light w-auto dropdown-toggle ml-2" type="button" data-toggle="dropdown">[[${bundle.L('更多')}]] <i class="icon zmdi zmdi-more-vert"></i></button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item J_new2-field">[[${bundle.L('批量添加')}]]</a>
|
||||
<a class="dropdown-item J_new9-field">[[${bundle.L('批量添加')}]]</a>
|
||||
<a class="dropdown-item J_export-fields">[[${bundle.L('导出')}]] (CSV)</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -101,5 +101,7 @@
|
|||
</script>
|
||||
<script th:src="@{/assets/js/metadata/entity-switch.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/fields.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/field-type.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/field-new2.js}" type="text/babel"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<div class="rb-right-sidebar field-aside">
|
||||
<div class="rb-content">
|
||||
<div class="tab-container">
|
||||
<ul class="nav nav-tabs bg-transparent">
|
||||
<ul class="nav nav-tabs bg-transparent" style="margin-top: 3px">
|
||||
<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>
|
||||
</ul>
|
||||
|
@ -137,8 +137,9 @@
|
|||
isSuperAdmin: '[[${isSuperAdmin}]]' === 'true',
|
||||
}
|
||||
</script>
|
||||
<script th:src="@{/assets/js/metadata/field-type.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/form-design.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/entity-switch.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/form-design.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/field-type.js}" type="text/babel"></script>
|
||||
<script th:src="@{/assets/js/metadata/field-new2.js}" type="text/babel"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -10,8 +10,8 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
}
|
||||
|
||||
.file-header .file-path {
|
||||
height: 46px;
|
||||
padding: 9px 0;
|
||||
height: 44px;
|
||||
padding: 8px 0;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
|
|
|
@ -336,10 +336,6 @@ form.field-attr label > span {
|
|||
margin-right: 1.385rem;
|
||||
}
|
||||
|
||||
.field-aside .nav.nav-tabs {
|
||||
margin-top: 7px;
|
||||
}
|
||||
|
||||
.type-list .dd-handle {
|
||||
padding-left: 38px !important;
|
||||
}
|
||||
|
|
|
@ -116,22 +116,30 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
|
||||
.quick-filter-tabs {
|
||||
background-color: #fff;
|
||||
padding: 0 18px;
|
||||
margin-bottom: 12px;
|
||||
border-radius: 2px;
|
||||
padding: 0 20px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #e6e6e6;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.quick-filter-tabs > div {
|
||||
font-size: 0;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.quick-filter-tabs > div .dropdown-item {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
line-height: 1;
|
||||
padding: 15px 18px;
|
||||
padding: 9px 20px;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
border-radius: 6px !important;
|
||||
min-width: 60px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.quick-filter-tabs > div .dropdown-item:active {
|
||||
|
@ -147,3 +155,18 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
.quick-filter-tabs > div .dropdown-item.active:active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.page-aside.widgets .nav.nav-tabs {
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.page-aside.widgets .nav.nav-tabs > li.nav-item > .nav-link {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.quick-filter-tabs + .quick-filter-pane,
|
||||
.quick-filter-tabs + .card-table,
|
||||
.quick-filter-tabs + .nav-tabs {
|
||||
margin-top: 44px;
|
||||
}
|
||||
|
|
|
@ -3711,7 +3711,6 @@ form {
|
|||
}
|
||||
|
||||
.page-aside.widgets .tab-container {
|
||||
margin-top: 2px;
|
||||
min-width: 279px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
@ -3806,6 +3805,7 @@ form {
|
|||
#asideFilters .dropdown-item.active,
|
||||
#asideCategory .dropdown-item.active {
|
||||
background-color: #4285f4;
|
||||
background-color: var(--rb-theme-color);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
@ -5414,4 +5414,11 @@ div.dataTables_wrapper.compact div.dataTables_oper .btn-space {
|
|||
|
||||
.code-viewport:hover > a.copy {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
span.icon-append .icon {
|
||||
float: left;
|
||||
width: 22px;
|
||||
font-size: 1.2rem;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
|
|
@ -165,80 +165,82 @@ class AppLogsViewer extends RbModal {
|
|||
|
||||
const dataShow = this.state.dataShow
|
||||
return (
|
||||
<div className="logs">
|
||||
<div className="row">
|
||||
<div className="col-3 logs-list">
|
||||
<div className="search-logs position-relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={$L('搜索')}
|
||||
onKeyDown={(e) => {
|
||||
if (e.keyCode === 13) {
|
||||
this._loadNext(true, e.target.value)
|
||||
}
|
||||
}}
|
||||
maxLength="40"
|
||||
/>
|
||||
</div>
|
||||
<div className="list-group list-group-flush" ref={(c) => (this._$list = c)}>
|
||||
{this.state.dataLogs.map((item) => {
|
||||
const respOk = this._isRespOk(item[5])
|
||||
return (
|
||||
<a
|
||||
key={item[6]}
|
||||
className={`list-group-item list-group-item-action d-flex justify-content-between align-items-center ${dataShow && dataShow[6] === item[6] && 'active'}`}
|
||||
onClick={() => {
|
||||
this.setState({ dataShow: item })
|
||||
}}>
|
||||
<div>
|
||||
{item[3].split('?')[0]}
|
||||
<br />
|
||||
<span className="text-muted fs-12">{item[1].split('UTC')[0]}</span>
|
||||
</div>
|
||||
<span className={`badge badge-${respOk ? 'success' : 'danger'} badge-pill`}>{respOk ? $L('成功') : $L('失败')}</span>
|
||||
<div className="modal-body m-0 p-0">
|
||||
<div className="logs">
|
||||
<div className="row">
|
||||
<div className="col-3 logs-list">
|
||||
<div className="search-logs position-relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={$L('搜索')}
|
||||
onKeyDown={(e) => {
|
||||
if (e.keyCode === 13) {
|
||||
this._loadNext(true, e.target.value)
|
||||
}
|
||||
}}
|
||||
maxLength="40"
|
||||
/>
|
||||
</div>
|
||||
<div className="list-group list-group-flush" ref={(c) => (this._$list = c)}>
|
||||
{this.state.dataLogs.map((item) => {
|
||||
const respOk = this._isRespOk(item[5])
|
||||
return (
|
||||
<a
|
||||
key={item[6]}
|
||||
className={`list-group-item list-group-item-action d-flex justify-content-between align-items-center ${dataShow && dataShow[6] === item[6] && 'active'}`}
|
||||
onClick={() => {
|
||||
this.setState({ dataShow: item })
|
||||
}}>
|
||||
<div>
|
||||
{item[3].split('?')[0]}
|
||||
<br />
|
||||
<span className="text-muted fs-12">{item[1].split('UTC')[0]}</span>
|
||||
</div>
|
||||
<span className={`badge badge-${respOk ? 'success' : 'danger'} badge-pill`}>{respOk ? $L('成功') : $L('失败')}</span>
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{this.state.showMore && (
|
||||
<div className="text-center mt-3">
|
||||
<a className="text-primary" onClick={() => this._loadNext()}>
|
||||
{$L('加载更多')}
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-9">
|
||||
{dataShow ? (
|
||||
<div className="logs-detail">
|
||||
<dl className="row">
|
||||
<dt className="col-sm-3">{$L('编号')} (X-RB-RequestId)</dt>
|
||||
<dd className="col-sm-9">{dataShow[6]}</dd>
|
||||
<dt className="col-sm-3">{$L('来源 IP')}</dt>
|
||||
<dd className="col-sm-9">{dataShow[0]}</dd>
|
||||
<dt className="col-sm-3">{$L('请求时间')}</dt>
|
||||
<dd className="col-sm-9">{dataShow[1].substr(0, 19)}</dd>
|
||||
<dt className="col-sm-3">{$L('响应时间')}</dt>
|
||||
<dd className="col-sm-9">
|
||||
{dataShow[2].substr(0, 19)}
|
||||
<span className="badge badge-light ml-1 up-1">{$moment(dataShow[2]).diff($moment(dataShow[1]), 'seconds')}s</span>
|
||||
</dd>
|
||||
<dt className="col-sm-3">{$L('请求地址')}</dt>
|
||||
<dd className="col-sm-9 text-break">{dataShow[3]}</dd>
|
||||
<dt className="col-sm-12">{$L('请求数据')}</dt>
|
||||
<dd className="col-sm-12">{dataShow[4] && <CodeViewport code={dataShow[4]} />}</dd>
|
||||
<dt className="col-sm-12">{$L('响应数据')}</dt>
|
||||
<dd className="col-sm-12 mb-0">{dataShow[5] && <CodeViewport code={dataShow[5]} />}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-muted pt-8 pb-8 text-center">
|
||||
<p style={{ fontSize: 40 }}>
|
||||
<i className="mdi mdi-script-text-outline text-muted" />
|
||||
</p>
|
||||
{$L('暂无数据')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{this.state.showMore && (
|
||||
<div className="text-center mt-3">
|
||||
<a className="text-primary" onClick={() => this._loadNext()}>
|
||||
{$L('加载更多')}
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-9">
|
||||
{dataShow ? (
|
||||
<div className="logs-detail">
|
||||
<dl className="row">
|
||||
<dt className="col-sm-3">{$L('编号')} (X-RB-RequestId)</dt>
|
||||
<dd className="col-sm-9">{dataShow[6]}</dd>
|
||||
<dt className="col-sm-3">{$L('来源 IP')}</dt>
|
||||
<dd className="col-sm-9">{dataShow[0]}</dd>
|
||||
<dt className="col-sm-3">{$L('请求时间')}</dt>
|
||||
<dd className="col-sm-9">{dataShow[1].substr(0, 19)}</dd>
|
||||
<dt className="col-sm-3">{$L('响应时间')}</dt>
|
||||
<dd className="col-sm-9">
|
||||
{dataShow[2].substr(0, 19)}
|
||||
<span className="badge badge-light ml-1 up-1">{$moment(dataShow[2]).diff($moment(dataShow[1]), 'seconds')}s</span>
|
||||
</dd>
|
||||
<dt className="col-sm-3">{$L('请求地址')}</dt>
|
||||
<dd className="col-sm-9 text-break">{dataShow[3]}</dd>
|
||||
<dt className="col-sm-12">{$L('请求数据')}</dt>
|
||||
<dd className="col-sm-12">{dataShow[4] && <CodeViewport code={dataShow[4]} />}</dd>
|
||||
<dt className="col-sm-12">{$L('响应数据')}</dt>
|
||||
<dd className="col-sm-12 mb-0">{dataShow[5] && <CodeViewport code={dataShow[5]} />}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-muted pt-8 pb-8 text-center">
|
||||
<p style={{ fontSize: 40 }}>
|
||||
<i className="mdi mdi-script-text-outline text-muted" />
|
||||
</p>
|
||||
{$L('暂无数据')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -23,6 +23,12 @@ let import_taskid
|
|||
const entity = $urlp('entity')
|
||||
_Config.entity = entity || null
|
||||
|
||||
_Config.file = $urlp('file') || null
|
||||
if (_Config.file) {
|
||||
_Config.file = $decode(_Config.file)
|
||||
$('.J_upload-input').text($fileCutName(_Config.file))
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
$.get('/commons/metadata/entities?detail=true', (res) => {
|
||||
$(res.data).each(function () {
|
||||
|
@ -288,7 +294,6 @@ const step3_import_cancel = () => {
|
|||
}
|
||||
|
||||
const _LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
|
||||
|
||||
// 渲染字段映射
|
||||
const _fieldsMapping = (columns, fields) => {
|
||||
const canNullText = ` [${$L('必填')}]`
|
||||
|
|
|
@ -339,7 +339,6 @@ class DlgAddChart extends RbFormHandler {
|
|||
this.__select2 = $entity.select2({
|
||||
allowClear: false,
|
||||
placeholder: $L('选择数据来源'),
|
||||
matcher: $select2MatcherAll,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -583,10 +583,7 @@ class FilterItem extends React.Component {
|
|||
|
||||
const that = this
|
||||
const $s2field = $(this._filterField)
|
||||
.select2({
|
||||
allowClear: false,
|
||||
matcher: $select2MatcherAll,
|
||||
})
|
||||
.select2({ allowClear: false })
|
||||
.on('change', function (e) {
|
||||
const fieldAndType = e.target.value.split(NT_SPLIT)
|
||||
that.setState({ field: fieldAndType[0], type: fieldAndType[1] }, () => $s2op.val(that.__op[0]).trigger('change'))
|
||||
|
|
|
@ -1002,10 +1002,11 @@ class RbList extends React.Component {
|
|||
if (supportFixedColumns) $scroller.find('.table').addClass('table-header-fixed')
|
||||
|
||||
$addResizeHandler(() => {
|
||||
let mh = $(window).height() - 210 + 5
|
||||
let mh = $(window).height() - (61 + 20 + 61 + 60 + 2) /* Nav, MarginTop20, TableHeader, TableFooter */
|
||||
if ($('.main-content>.nav-tabs-classic')[0]) mh -= 38 // Has detail-tab
|
||||
if ($('.main-content .quick-filter-pane')[0]) mh -= 75 // Has query-pane
|
||||
if ($('.main-content .quick-filter-tabs')[0]) mh -= 55 // Has query-tabs
|
||||
if ($('.main-content .quick-filter-tabs')[0]) mh -= 44 // Has query-tabs
|
||||
|
||||
$scroller.css({ maxHeight: mh })
|
||||
$scroller.perfectScrollbar('update')
|
||||
})()
|
||||
|
|
|
@ -586,7 +586,8 @@ class RbForm extends React.Component {
|
|||
}
|
||||
|
||||
if (window.FrontJS) {
|
||||
const ret = window.FrontJS.Form._trigger('fieldValueChange', [`${this.props.entity}.${field}`, value, this.props.id || null])
|
||||
const fieldKey = `${this.props.entity}.${field}`
|
||||
const ret = window.FrontJS.Form._trigger('fieldValueChange', [fieldKey, value, this.props.id || null])
|
||||
if (ret === false) return false
|
||||
}
|
||||
}
|
||||
|
@ -2979,7 +2980,7 @@ const __calcFormula = function (_this) {
|
|||
if (res.data) _this.setValue(res.data)
|
||||
else _this.setValue(null)
|
||||
})
|
||||
}, 400)
|
||||
}, 300)
|
||||
return true
|
||||
})
|
||||
|
||||
|
@ -2990,5 +2991,5 @@ const __calcFormula = function (_this) {
|
|||
else _this.setValue(null)
|
||||
})
|
||||
}
|
||||
}, 400) // delay for init
|
||||
}, 600) // delay for init
|
||||
}
|
||||
|
|
|
@ -172,7 +172,6 @@ class DlgRuleEdit extends RbFormHandler {
|
|||
const $s2target = $(this._targetField).select2({
|
||||
placeholder: $L('选择字段'),
|
||||
allowClear: false,
|
||||
matcher: $select2MatcherAll,
|
||||
})
|
||||
this.__select2.push($s2target)
|
||||
|
||||
|
@ -184,7 +183,6 @@ class DlgRuleEdit extends RbFormHandler {
|
|||
.select2({
|
||||
placeholder: $L('选择字段'),
|
||||
allowClear: false,
|
||||
matcher: $select2MatcherAll,
|
||||
})
|
||||
.on('change', (e) => this._renderTargetFields(e.target.value))
|
||||
this.__select2.push($s2source)
|
||||
|
|
|
@ -183,7 +183,7 @@ class DlgMode1Option extends RbFormHandler {
|
|||
<label htmlFor="advListFilterTabs" />
|
||||
</span>
|
||||
</div>
|
||||
<span className="ml-2 down-5 d-inline-block">{$L('常用查询')}</span>
|
||||
<span className="ml-2 down-5 d-inline-block">{$L('列表视图')}</span>
|
||||
</div>
|
||||
<div>
|
||||
<div className="switch-button switch-button-xs">
|
||||
|
|
|
@ -1,165 +0,0 @@
|
|||
/*!
|
||||
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.
|
||||
*/
|
||||
/* global InitModels */
|
||||
|
||||
window.__LAB_SHOWNDETAIL = false
|
||||
window.bosskeyTrigger = function () {
|
||||
window.__LAB_SHOWNDETAIL = true
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
const $bnew = $('.btn-primary.new').on('click', () => {
|
||||
const entityLabel = $val('#entityLabel'),
|
||||
comments = $val('#comments')
|
||||
if (!entityLabel) return RbHighbar.create($L('请输入实体名称'))
|
||||
|
||||
const data = {
|
||||
label: entityLabel,
|
||||
comments: comments,
|
||||
}
|
||||
|
||||
if ($val('#isDetail')) {
|
||||
data.mainEntity = $val('#mainEntity')
|
||||
if (!data.mainEntity) return RbHighbar.create($L('请选择主实体'))
|
||||
}
|
||||
|
||||
$bnew.button('loading')
|
||||
$.post(`/admin/entity/entity-new?nameField=${$val('#nameField')}&seriesField=${$val('#seriesField')}`, JSON.stringify(data), (res) => {
|
||||
if (res.error_code === 0) parent.location.href = `${rb.baseUrl}/admin/entity/${res.data}/base`
|
||||
else RbHighbar.error(res.error_msg)
|
||||
})
|
||||
})
|
||||
|
||||
const $bcopy = $('.btn-primary.copy').on('click', () => {
|
||||
const sourceEntity = $val('#copySourceEntity')
|
||||
if (!sourceEntity) return RbHighbar.create($L('请选择从哪个实体复制'))
|
||||
|
||||
const entityLabel = $val('#newEntityLabel')
|
||||
if (!entityLabel) return RbHighbar.create($L('请输入实体名称'))
|
||||
|
||||
const data = {
|
||||
sourceEntity: sourceEntity,
|
||||
entityName: entityLabel,
|
||||
detailEntityName: $val('#newDetailLabel'),
|
||||
keepConfig: [],
|
||||
}
|
||||
|
||||
$bcopy.button('loading')
|
||||
$.post('/admin/entity/entity-copy', JSON.stringify(data), (res) => {
|
||||
if (res.error_code === 0) parent.location.href = `${rb.baseUrl}/admin/entity/${res.data}/base`
|
||||
else RbHighbar.error(res.error_msg)
|
||||
})
|
||||
})
|
||||
|
||||
let entities
|
||||
function _loadEntities(c) {
|
||||
if (entities) {
|
||||
typeof c === 'function' && c(entities)
|
||||
} else {
|
||||
$.get('/admin/entity/entity-list?detail=true', (res) => {
|
||||
entities = res.data
|
||||
typeof c === 'function' && c(entities)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
_loadEntities((e) => {
|
||||
e.forEach((item) => {
|
||||
$(`<option value="${item.entityName}" data-detail="${item.detailEntity || ''}">${item.entityLabel}</option>`).appendTo('#copySourceEntity')
|
||||
})
|
||||
|
||||
$('#copySourceEntity')
|
||||
.on('change', function () {
|
||||
const $s = $('#copySourceEntity option:selected')
|
||||
if ($s.data('detail')) $('.J_newDetailLabel').removeClass('hide')
|
||||
else $('.J_newDetailLabel').addClass('hide')
|
||||
|
||||
parent.RbModal.resize()
|
||||
})
|
||||
.trigger('change')
|
||||
|
||||
if (e.length === 0) $(`<option value="">${$L('无可用实体')}</option>`).appendTo('#copySourceEntity')
|
||||
})
|
||||
|
||||
$('#isDetail').on('click', () => {
|
||||
$('.J_mainEntity').toggleClass('hide')
|
||||
parent.RbModal.resize()
|
||||
|
||||
if ($('#mainEntity option').length === 0) {
|
||||
_loadEntities((e) => {
|
||||
e.forEach((item) => {
|
||||
if (!item.mainEntity) {
|
||||
if (window.__LAB_SHOWNDETAIL) {
|
||||
$(`<option value="${item.entityName}">${item.entityLabel}${item.detailEntity ? ' (LAB)' : ''}</option>`).appendTo('#mainEntity')
|
||||
} else if (!item.detailEntity) {
|
||||
$(`<option value="${item.entityName}">${item.entityLabel}</option>`).appendTo('#mainEntity')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if ($('#mainEntity option').length === 0) $(`<option value="">${$L('无可用实体')}</option>`).appendTo('#mainEntity')
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
let _MetaschemaList
|
||||
$('.J_imports').on('click', () => {
|
||||
if (_MetaschemaList) return
|
||||
renderRbcomp(<MetaschemaList />, 'metaschemas', function () {
|
||||
_MetaschemaList = this
|
||||
})
|
||||
})
|
||||
|
||||
$('.nav-tabs a').on('click', () => parent.RbModal.resize())
|
||||
})
|
||||
|
||||
class MetaschemaList extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<InitModels ref={(c) => (this._InitModels = c)} onLoad={() => parent.RbModal.resize()} />
|
||||
<div className="dialog-footer">
|
||||
<div className="float-right">
|
||||
<button className="btn btn-primary" onClick={() => this.imports()} ref={(c) => (this._$btn = c)}>
|
||||
{$L('开始导入')}
|
||||
</button>
|
||||
</div>
|
||||
<div className="float-right">
|
||||
<p className="protips mt-2 pr-2">{$L('可在导入后根据自身需求做适当调整/修改')}</p>
|
||||
</div>
|
||||
<div className="clearfix" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
parent.RbModal.resize()
|
||||
}
|
||||
|
||||
imports() {
|
||||
const s = this._InitModels.getSelected()
|
||||
if (s.length < 1) {
|
||||
return RbHighbar.create($L('请选择要导入的实体'))
|
||||
}
|
||||
|
||||
const $btn = $(this._$btn).button('loading')
|
||||
const $mp2 = parent && parent.$mp ? parent.$mp : $mp
|
||||
$mp2.start()
|
||||
$.post(`/admin/metadata/imports?key=${s.join(',')}`, (res) => {
|
||||
$mp2.end()
|
||||
$btn.button('reset')
|
||||
|
||||
if (res.error_code === 0) {
|
||||
RbHighbar.success($L('导入成功'))
|
||||
setTimeout(() => parent.location.reload(), 1500)
|
||||
} else {
|
||||
RbHighbar.error(res.error_msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
572
src/main/resources/web/assets/js/metadata/entity-new2.js
Normal file
572
src/main/resources/web/assets/js/metadata/entity-new2.js
Normal file
|
@ -0,0 +1,572 @@
|
|||
/*!
|
||||
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.
|
||||
*/
|
||||
/* global InitModels, FIELD_TYPES */
|
||||
|
||||
window.__LAB_SHOWNDETAIL = false
|
||||
window.bosskeyTrigger = function () {
|
||||
window.__LAB_SHOWNDETAIL = true
|
||||
}
|
||||
|
||||
// ~~ 新建实体
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
class EntityNew2 extends RbModalHandler {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = { ...props }
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<RbModal ref={(c) => (this._dlg = c)} title={$L('添加实体')} className="entity-new2">
|
||||
<div className="tab-container" ref={(c) => (this._$container = c)}>
|
||||
<ul className="nav nav-tabs">
|
||||
<li className="nav-item">
|
||||
<a className="nav-link active" href="#MANUAL" data-toggle="tab">
|
||||
{$L('手动')}
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="#COPY" data-toggle="tab">
|
||||
{$L('复制')}
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" href="#EXCEL" data-toggle="tab">
|
||||
{$L('从 EXCEL 导入')}
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link J_imports" href="#IMPORTS" data-toggle="tab">
|
||||
{$L('从 RB 仓库导入')}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="tab-content m-0 pb-0">
|
||||
<div className="tab-pane active" id="MANUAL">
|
||||
<div className="form">
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('实体名称')}</label>
|
||||
<div className="col-sm-7">
|
||||
<input className="form-control form-control-sm" type="text" maxLength="40" ref={(c) => (this._$entityLabel = c)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('备注')}</label>
|
||||
<div className="col-sm-7">
|
||||
<textarea className="form-control form-control-sm row2x" maxLength="100" placeholder={$L('(选填)')} ref={(c) => (this._$comments = c)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row pt-2">
|
||||
<label className="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div className="col-sm-7">
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input className="custom-control-input" type="checkbox" ref={(c) => (this._$nameField = c)} />
|
||||
<span className="custom-control-label">{$L('添加一个名称字段')}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row pt-0">
|
||||
<label className="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div className="col-sm-7">
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input className="custom-control-input" type="checkbox" ref={(c) => (this._$seriesField = c)} />
|
||||
<span className="custom-control-label">{$L('添加一个自动编号字段')}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row pt-0">
|
||||
<label className="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div className="col-sm-7">
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input className="custom-control-input" type="checkbox" onClick={(e) => this.setState({ newIsDetail: $val(e.target) })} ref={(c) => (this._$newIsDetail = c)} />
|
||||
<span className="custom-control-label">
|
||||
{$L('这是明细实体')}
|
||||
<i className="zmdi zmdi-help zicon" data-toggle="tooltip" title={$L('通过明细实体可以更好的组织业务关系。例如订单明细通常依附于订单,而非独立存在')}></i>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`form-group row ${this.state.newIsDetail ? '' : 'hide'}`}>
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('选择主实体')}</label>
|
||||
<div className="col-sm-7">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$mainEntity = c)}>
|
||||
{this.state.entities &&
|
||||
this.state.entities.map((item) => {
|
||||
if (item.mainEntity) return null
|
||||
if (item.detailEntity && !window.__LAB_SHOWNDETAIL) return null
|
||||
return (
|
||||
<option key={item.entityName} value={item.entityName}>
|
||||
{item.entityLabel}
|
||||
{item.detailEntity ? ' (LAB)' : ''}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row footer">
|
||||
<div className="col-sm-7 offset-sm-3">
|
||||
<button className="btn btn-primary" type="button" onClick={() => this.postNew()}>
|
||||
{$L('确定')}
|
||||
</button>
|
||||
<button className="btn btn-link" type="button" onClick={() => this.hide()}>
|
||||
{$L('取消')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane" id="COPY">
|
||||
<div className="form">
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('复制哪个实体')}</label>
|
||||
<div className="col-sm-7">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$copySourceEntity = c)}>
|
||||
{this.state.entities &&
|
||||
this.state.entities.map((item) => {
|
||||
return (
|
||||
<option key={item.entityName} value={item.entityName}>
|
||||
{item.entityLabel}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('实体名称')}</label>
|
||||
<div className="col-sm-7">
|
||||
<input className="form-control form-control-sm" type="text" maxLength="40" ref={(c) => (this._$copyEntityLabel = c)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={`form-group row ${this.state.copyHasDetail ? '' : 'hide'}`}>
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('明细实体名称')}</label>
|
||||
<div className="col-sm-7">
|
||||
<input className="form-control form-control-sm" type="text" maxLength="40" placeholder={$L('(选填)')} ref={(c) => (this._$copyDetailLabel = c)} />
|
||||
<p className="form-text">{$L('不填写则不复制明细实体')}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row footer">
|
||||
<div className="col-sm-7 offset-sm-3">
|
||||
<button className="btn btn-primary" type="button" onClick={() => this.postCopy()}>
|
||||
{$L('确定')}
|
||||
</button>
|
||||
<button className="btn btn-link" type="button" onClick={() => this.hide()}>
|
||||
{$L('取消')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane" id="EXCEL">
|
||||
<div className="form">
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('上传数据文件')}</label>
|
||||
<div className="col-sm-7">
|
||||
<div className="file-select">
|
||||
<input type="file" className="inputfile" accept=".xlsx,.xls,.csv" data-local="temp" ref={(c) => (this._$uploadfile = c)} />
|
||||
<label htmlFor="upload-input" className="btn-secondary mb-0" ref={(c) => (this._$uploadbtn = c)}>
|
||||
<i className="zmdi zmdi-upload"></i>
|
||||
<span>{$L('上传文件')}</span>
|
||||
</label>
|
||||
</div>
|
||||
{this.state.excelfile && (
|
||||
<div className="mt-1">
|
||||
<u className="text-bold">{$fileCutName(this.state.excelfile)}</u>
|
||||
</div>
|
||||
)}
|
||||
<p className="form-text">{$L('[点击查看](https://getrebuild.com/docs/admin/entity/#%E4%BB%8E%20EXCEL%20%E5%AF%BC%E5%85%A5) 数据文件格式要求')}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('实体名称')}</label>
|
||||
<div className="col-sm-7">
|
||||
<input className="form-control form-control-sm" type="text" maxLength="40" ref={(c) => (this._$excelEntityLabel = c)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row footer">
|
||||
<div className="col-sm-7 offset-sm-3">
|
||||
<button className="btn btn-primary" type="button" onClick={() => this.postExcel()}>
|
||||
{$L('下一步')}
|
||||
</button>
|
||||
<button className="btn btn-link" type="button" onClick={() => this.hide()}>
|
||||
{$L('取消')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tab-pane" id="IMPORTS">
|
||||
<InitModels ref={(c) => (this._InitModels = c)} />
|
||||
<div className="dialog-footer">
|
||||
<div className="float-right">
|
||||
<button className="btn btn-primary" onClick={() => this.postRbImports()}>
|
||||
{$L('开始导入')}
|
||||
</button>
|
||||
</div>
|
||||
<div className="float-right">
|
||||
<p className="protips mt-2 pr-2">{$L('可在导入后根据自身需求做适当调整/修改')}</p>
|
||||
</div>
|
||||
<div className="clearfix" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 text-right hide">
|
||||
<a href="https://getrebuild.com/market/go/1220-rb-store" className="link" target="_blank">
|
||||
{$L('提交数据到 RB 仓库')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</RbModal>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
$(this._$container).find('[data-toggle="tooltip"]').tooltip()
|
||||
|
||||
$.get('/admin/entity/entity-list?detail=true', (res) => {
|
||||
this.setState({ entities: res.data }, () => {
|
||||
$(this._$mainEntity).select2({ allowClear: false })
|
||||
$(this._$copySourceEntity)
|
||||
.select2({ allowClear: false })
|
||||
.on('change', (e) => {
|
||||
const val = e.currentTarget.value
|
||||
const found = this.state.entities.find((x) => x.entityName === val)
|
||||
this.setState({ copyHasDetail: found && !!found.detailEntity })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
$createUploader(
|
||||
this._$uploadfile,
|
||||
(res) => {
|
||||
$(this._$uploadbtn).text(`${$L('上传中')} ... ${res.percent.toFixed(0)}%`)
|
||||
},
|
||||
(res) => {
|
||||
this.setState({ excelfile: res.key })
|
||||
$(this._$uploadbtn).text($L('上传文件'))
|
||||
$(this._$excelEntityLabel).val($fileCutName(res.key))
|
||||
}
|
||||
)
|
||||
$(this._$uploadbtn).on('click', () => this._$uploadfile.click())
|
||||
|
||||
setTimeout(() => $(this._$entityLabel).focus(), 200)
|
||||
}
|
||||
|
||||
postNew() {
|
||||
const data = {
|
||||
label: $val(this._$entityLabel),
|
||||
comments: $val(this._$comments),
|
||||
}
|
||||
if (!data.label) return RbHighbar.create($L('请输入实体名称'))
|
||||
|
||||
if (this.state.newIsDetail) {
|
||||
data.mainEntity = $val(this._$mainEntity)
|
||||
if (!data.mainEntity) return RbHighbar.create($L('请选择主实体'))
|
||||
}
|
||||
|
||||
const $btn = $(this._$container).find('.btn').button('loading')
|
||||
$.post(`/admin/entity/entity-new?nameField=${$val(this._$nameField)}&seriesField=${$val(this._$seriesField)}`, JSON.stringify(data), (res) => {
|
||||
if (res.error_code === 0) {
|
||||
location.href = `${rb.baseUrl}/admin/entity/${res.data}/base`
|
||||
} else {
|
||||
$btn.button('reset')
|
||||
RbHighbar.error(res.error_msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
postCopy() {
|
||||
const data = {
|
||||
sourceEntity: $val(this._$copySourceEntity),
|
||||
entityName: $val(this._$copyEntityLabel),
|
||||
detailEntityName: $val(this._$copyDetailLabel),
|
||||
keepConfig: [],
|
||||
}
|
||||
if (!data.sourceEntity) return RbHighbar.create($L('请选择从哪个实体复制'))
|
||||
if (!data.entityName) return RbHighbar.create($L('请输入实体名称'))
|
||||
|
||||
const $btn = $(this._$container).find('.btn').button('loading')
|
||||
$.post('/admin/entity/entity-copy', JSON.stringify(data), (res) => {
|
||||
if (res.error_code === 0) {
|
||||
location.href = `${rb.baseUrl}/admin/entity/${res.data}/base`
|
||||
} else {
|
||||
$btn.button('reset')
|
||||
RbHighbar.error(res.error_msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
postExcel() {
|
||||
const excelfile = this.state.excelfile
|
||||
if (!excelfile) return RbHighbar.create($L('请上传数据文件'))
|
||||
|
||||
$.get(`/app/entity/data-imports/check-file?file=${$encode(excelfile)}`, (res) => {
|
||||
if (res.error_code > 0) {
|
||||
this.setState({ excelfile: null })
|
||||
RbHighbar.create(res.error_msg)
|
||||
return
|
||||
}
|
||||
|
||||
const _data = res.data
|
||||
if (_data.preview.length < 1 || _data.preview[0].length === 0) return RbHighbar.create($L('上传的文件无有效数据'))
|
||||
|
||||
const entityLabel = $val(this._$excelEntityLabel)
|
||||
if (!entityLabel) return RbHighbar.create($L('请输入实体名称'))
|
||||
|
||||
renderRbcomp(<ExcelPreview datas={_data.preview} entityLabel={entityLabel} excelfile={excelfile} title={$L('导入字段配置')} maximize _maximize disposeOnHide useWhite />)
|
||||
})
|
||||
}
|
||||
|
||||
postRbImports() {
|
||||
const s = this._InitModels.getSelected()
|
||||
if (s.length < 1) return RbHighbar.create($L('请选择要导入的实体'))
|
||||
|
||||
const $btn = $(this._$container).find('.btn').button('loading')
|
||||
$mp.start()
|
||||
$.post(`/admin/metadata/imports?key=${s.join(',')}`, (res) => {
|
||||
$mp.end()
|
||||
|
||||
if (res.error_code === 0) {
|
||||
RbHighbar.success($L('导入成功'))
|
||||
setTimeout(() => location.reload(), 1500)
|
||||
} else {
|
||||
$btn.button('reset')
|
||||
RbHighbar.error(res.error_msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const _LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
|
||||
class ExcelPreview extends RbModal {
|
||||
renderContent() {
|
||||
let colMax = 0
|
||||
this.props.datas.forEach((d) => {
|
||||
colMax = Math.max(colMax, d.length)
|
||||
})
|
||||
|
||||
const colNames = []
|
||||
for (let i = 0; i < colMax; 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 (
|
||||
<div className="modal-body m-0 p-0">
|
||||
<div style={{ overflow: 'auto' }}>
|
||||
<table className="table table-bordered table-excel m-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
{colNames.map((item) => {
|
||||
return <th key={item}>{item}</th>
|
||||
})}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ref={(c) => (this._$datahead = c)}>
|
||||
<th>1</th>
|
||||
{colNames.map((item, idx) => {
|
||||
return (
|
||||
<td key={item} className="align-text-top">
|
||||
<div>
|
||||
<label className="mb-0">{$L('字段名称')}</label>
|
||||
<input className="form-control form-control-sm" defaultValue={dataHead[idx]} placeholder={$L('不导入')} />
|
||||
</div>
|
||||
<div className="mt-1 J_type">
|
||||
<label className="mb-0">{$L('字段类型')}</label>
|
||||
<select className="form-control form-control-sm" defaultValue={$empty(dataHead[idx]) ? '-' : 'TEXT'}>
|
||||
<option value="-">{$L('不导入')}</option>
|
||||
{ftKeys.map((item) => {
|
||||
if (FIELD_TYPES[item][2]) return null
|
||||
return (
|
||||
<option key={item} value={item}>
|
||||
{FIELD_TYPES[item][0]}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mt-1 J_refEntity hide">
|
||||
<label className="mb-0">{$L('选择引用实体')}</label>
|
||||
<select className="form-control form-control-sm">
|
||||
{this.state.refEntities &&
|
||||
this.state.refEntities.map((item) => {
|
||||
if (item.entityName === 'Team') return null
|
||||
return (
|
||||
<option key={item.entityName} value={item.entityName}>
|
||||
{item.entityLabel}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mt-1 J_refClass hide">
|
||||
<label className="mb-0">{$L('选择分类数据')}</label>
|
||||
<select className="form-control form-control-sm">
|
||||
{this.state.refClasses &&
|
||||
this.state.refClasses.map((item) => {
|
||||
return (
|
||||
<option key={item[0]} value={item[0]}>
|
||||
{item[1]}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
)
|
||||
})}
|
||||
</tr>
|
||||
{this.props.datas.map((d, idx) => {
|
||||
if (idx === 0 || idx > 20) return null
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<th>{idx + 1}</th>
|
||||
{colNames.map((item, idx2) => {
|
||||
const r = this.__colDatas[idx2] || []
|
||||
r.push(d[idx2])
|
||||
this.__colDatas[idx2] = r
|
||||
|
||||
return (
|
||||
<td key={`${idx}-${idx2}`} className="text-break">
|
||||
{d[idx2] || ''}
|
||||
</td>
|
||||
)
|
||||
})}
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div className="float-left">
|
||||
<p className="protips m-0 p-3 pt-4">{$L('最多显示前 %d 行数据', 20)}</p>
|
||||
</div>
|
||||
<div className="text-right p-2 pt-3" ref={(c) => (this._$btns = c)}>
|
||||
<button className="btn btn-link btn-space" type="button" onClick={() => this.hide()}>
|
||||
{$L('返回')}
|
||||
</button>
|
||||
<button className="btn btn-primary btn-space" type="button" onClick={() => this.post2()}>
|
||||
{$L('确定')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
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')
|
||||
.on('change', function () {
|
||||
const $td = $(this).parents('td')
|
||||
$td.find('.J_refEntity, .J_refClass').addClass('hide')
|
||||
|
||||
const t = $(this).val()
|
||||
if (t === 'REFERENCE' || t === 'N2NREFERENCE') {
|
||||
$td.find('.J_refEntity').removeClass('hide')
|
||||
} else if (t === 'CLASSIFICATION') {
|
||||
$td.find('.J_refClass').removeClass('hide')
|
||||
}
|
||||
})
|
||||
|
||||
$(this._$datahead).find('select').select2({ allowClear: false })
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
post2() {
|
||||
const fieldsNew = []
|
||||
$(this._$datahead)
|
||||
.find('td')
|
||||
.each(function () {
|
||||
const name = $(this).find('input').val()
|
||||
const type = $(this).find('.J_type select').val()
|
||||
if (name && type && type !== '-') {
|
||||
let ref2 = null
|
||||
if (type === 'REFERENCE' || type === 'N2NREFERENCE') {
|
||||
ref2 = $(this).find('.J_refEntity select').val()
|
||||
if (!ref2) return RbHighbar.create('请选择引用实体')
|
||||
} else if (type === 'CLASSIFICATION') {
|
||||
ref2 = $(this).find('.J_refClass select').val()
|
||||
if (!ref2) return RbHighbar.create('请选择分类数据')
|
||||
}
|
||||
|
||||
fieldsNew.push([name, type, ref2])
|
||||
}
|
||||
})
|
||||
if (fieldsNew.length === 0) return RbHighbar.create($L('没有配置任何导入字段'))
|
||||
|
||||
const that = this
|
||||
const post = {
|
||||
entityLabel: this.props.entityLabel,
|
||||
fields: fieldsNew,
|
||||
}
|
||||
|
||||
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`
|
||||
},
|
||||
})
|
||||
} else {
|
||||
RbHighbar.error(res.error_msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
|
@ -594,7 +594,7 @@ const _handleCalcFormula = function (formula) {
|
|||
$.get(`/commons/metadata/fields?entity=${wpc.entityName}`, (res) => {
|
||||
const fs = []
|
||||
res.data.forEach((item) => {
|
||||
if (['NUMBER', 'DECIMAL', 'DATE', 'DATETIME'].includes(item.type) && !['approvalLastTime', 'modifiedOn'].includes(item.name) && item.name !== wpc.fieldName) {
|
||||
if (['NUMBER', 'DECIMAL', 'DATE', 'DATETIME'].includes(item.type) && !['approvalLastTime'].includes(item.name) && item.name !== wpc.fieldName) {
|
||||
fs.push(item)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
/*!
|
||||
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.
|
||||
*/
|
||||
/* global FIELD_TYPES */
|
||||
|
||||
$(document).ready(function () {
|
||||
const entity = $urlp('entity')
|
||||
|
||||
const $btn = $('.btn-primary').on('click', function () {
|
||||
const fieldLabel = $val('#fieldLabel'),
|
||||
type = $val('#type'),
|
||||
comments = $val('#comments'),
|
||||
refEntity = $val('#refEntity'),
|
||||
refClassification = $val('#refClassification'),
|
||||
stateClass = $val('#stateClass') || 'com.rebuild.core.support.state.HowtoState'
|
||||
if (!fieldLabel) {
|
||||
return RbHighbar.create($L('请输入字段名称'))
|
||||
}
|
||||
|
||||
if ((type === 'REFERENCE' || type === 'N2NREFERENCE') && !refEntity) {
|
||||
return RbHighbar.create($L('请选择引用实体'))
|
||||
} else if (type === 'CLASSIFICATION' && !refClassification) {
|
||||
return RbHighbar.create($L('请选择分类数据'))
|
||||
} else if (type === 'STATE' && !stateClass) {
|
||||
return RbHighbar.create($L('请输入状态类 (StateSpec)'))
|
||||
}
|
||||
|
||||
const data = {
|
||||
entity: entity,
|
||||
label: fieldLabel,
|
||||
type: type,
|
||||
comments: comments,
|
||||
refEntity: refEntity,
|
||||
refClassification: refClassification,
|
||||
stateClass: stateClass,
|
||||
}
|
||||
|
||||
$btn.button('loading')
|
||||
$.post('/admin/entity/field-new', JSON.stringify(data), function (res) {
|
||||
$btn.button('reset')
|
||||
if (res.error_code === 0) {
|
||||
if ($val('#saveAndNew')) {
|
||||
RbHighbar.success($L('字段已添加'))
|
||||
$('#fieldLabel, #comments').val('')
|
||||
// $('#type').val('TEXT').trigger('change')
|
||||
$('#fieldLabel').focus()
|
||||
|
||||
// @see `field-new.html`
|
||||
parent && parent.loadFields && parent.loadFields()
|
||||
// @see `form-design.js`
|
||||
parent && parent.add2Layout && parent.add2Layout(res.data)
|
||||
} else {
|
||||
parent.location.href = `${rb.baseUrl}/admin/entity/${entity}/field/${res.data}`
|
||||
}
|
||||
} else {
|
||||
RbHighbar.error(res.error_msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
for (let k in FIELD_TYPES) {
|
||||
const t = FIELD_TYPES[k]
|
||||
const $o = $(`<option value="${k}">${t[0]}</option>`).appendTo('#type')
|
||||
if (t[2]) $o.addClass('bosskey-show')
|
||||
}
|
||||
|
||||
// $('#type, #refEntity').select2({})
|
||||
|
||||
let referenceLoaded = false
|
||||
let classificationLoaded = false
|
||||
$('#type').on('change', function () {
|
||||
parent.RbModal.resize()
|
||||
|
||||
$('.J_dt-REFERENCE, .J_dt-N2NREFERENCE, .J_dt-CLASSIFICATION, .J_dt-STATE').addClass('hide')
|
||||
const dt = $(this).val()
|
||||
$(`.J_dt-${dt}`).removeClass('hide')
|
||||
|
||||
if (dt === 'REFERENCE' || dt === 'N2NREFERENCE') {
|
||||
if (referenceLoaded === false) {
|
||||
referenceLoaded = true
|
||||
$.get('/admin/entity/entity-list?detail=true', (res) => {
|
||||
const d = res.data || []
|
||||
d.push({ entityName: 'User', entityLabel: $L('用户') })
|
||||
d.push({ entityName: 'Department', entityLabel: $L('部门') })
|
||||
d.push({ entityName: 'Team', entityLabel: $L('团队') })
|
||||
// _data.push({ entityName: 'Role', entityLabel: $L('角色') })
|
||||
|
||||
$(d).each(function () {
|
||||
$(`<option value="${this.entityName}">${this.entityLabel}</option>`).appendTo('#refEntity')
|
||||
})
|
||||
})
|
||||
}
|
||||
} else if (dt === 'CLASSIFICATION') {
|
||||
if (classificationLoaded === false) {
|
||||
classificationLoaded = true
|
||||
$.get('/admin/metadata/classification/list', (res) => {
|
||||
let hasData = false
|
||||
$(res.data).each(function () {
|
||||
if (!this[2]) {
|
||||
$(`<option value="${this[0]}">${this[1]}</option>`).appendTo('#refClassification')
|
||||
hasData = true
|
||||
}
|
||||
})
|
||||
if (!hasData) $(`<option value="">${$L('无可用分类数据')}</option>`).appendTo('#refClassification')
|
||||
})
|
||||
}
|
||||
} else if (dt === 'STATE') {
|
||||
// NOOP
|
||||
}
|
||||
})
|
||||
|
||||
// via form-design
|
||||
const designType = $urlp('type')
|
||||
if (designType) {
|
||||
$('#type').val(designType).trigger('change').parents('.form-group').addClass('hide')
|
||||
$('#saveAndNew').attr('checked', true).parents('.form-group').addClass('hide')
|
||||
}
|
||||
|
||||
$('#fieldLabel')[0].focus()
|
||||
})
|
197
src/main/resources/web/assets/js/metadata/field-new2.js
Normal file
197
src/main/resources/web/assets/js/metadata/field-new2.js
Normal file
|
@ -0,0 +1,197 @@
|
|||
/*!
|
||||
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.
|
||||
*/
|
||||
/* global FIELD_TYPES */
|
||||
|
||||
// ~~ 新建实体
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
class FieldNew2 extends RbModalHandler {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = { ...props }
|
||||
}
|
||||
|
||||
render() {
|
||||
const ftKeys = Object.keys(FIELD_TYPES)
|
||||
return (
|
||||
<RbModal ref={(c) => (this._dlg = c)} title={$L('添加字段')} disposeOnHide>
|
||||
<div>
|
||||
<form>
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('字段名称')}</label>
|
||||
<div className="col-sm-7">
|
||||
<input className="form-control form-control-sm" type="text" maxLength="40" ref={(c) => (this._$fieldLabel = c)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('字段类型')}</label>
|
||||
<div className="col-sm-7">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$type = c)} defaultValue={this.props.fieldType}>
|
||||
{ftKeys.map((key) => {
|
||||
if (FIELD_TYPES[key][2]) return null
|
||||
return (
|
||||
<option key={key} value={key}>
|
||||
{FIELD_TYPES[key][0]}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`form-group row ${this.state.fieldType === 'REFERENCE' || this.state.fieldType === 'N2NREFERENCE' ? '' : 'hide'}`}>
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('选择引用实体')}</label>
|
||||
<div className="col-sm-7">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$refEntity = c)}>
|
||||
{this.state.refEntities &&
|
||||
this.state.refEntities.map((item) => {
|
||||
if (item.entityName === 'Team') return null
|
||||
return (
|
||||
<option key={item.entityName} value={item.entityName}>
|
||||
{item.entityLabel}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`form-group row ${this.state.fieldType === 'CLASSIFICATION' ? '' : 'hide'}`}>
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('选择分类数据')}</label>
|
||||
<div className="col-sm-7">
|
||||
<select className="form-control form-control-sm" ref={(c) => (this._$refClass = c)}>
|
||||
{this.state.refClasses &&
|
||||
this.state.refClasses.map((item) => {
|
||||
return (
|
||||
<option key={item[0]} value={item[0]}>
|
||||
{item[1]}
|
||||
</option>
|
||||
)
|
||||
})}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`form-group row ${this.state.fieldType === 'STATE' ? '' : 'hide'}`}>
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('状态类 (StateSpec)')}</label>
|
||||
<div className="col-sm-7">
|
||||
<input className="form-control form-control-sm" type="text" placeholder="com.rebuild.core.support.state.HowtoState" ref={(c) => (this._$stateClass = c)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row">
|
||||
<label className="col-sm-3 col-form-label text-sm-right">{$L('备注')}</label>
|
||||
<div className="col-sm-7">
|
||||
<textarea className="form-control form-control-sm row2x" maxLength="100" placeholder={$L('(选填)')} ref={(c) => (this._$comments = c)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row pb-1">
|
||||
<label className="col-sm-3 col-form-label text-sm-right"></label>
|
||||
<div className="col-sm-7">
|
||||
<label className="custom-control custom-control-sm custom-checkbox custom-control-inline mb-0">
|
||||
<input className="custom-control-input" type="checkbox" ref={(c) => (this._$saveAndNew = c)} />
|
||||
<span className="custom-control-label">{$L('继续添加下一个')}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group row footer">
|
||||
<div className="col-sm-7 offset-sm-3" ref={(c) => (this._$btns = c)}>
|
||||
<button className="btn btn-primary" type="button" onClick={() => this.postNew()}>
|
||||
{$L('确定')}
|
||||
</button>
|
||||
<button className="btn btn-link" type="button" onClick={() => this.hide()}>
|
||||
{$L('取消')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</RbModal>
|
||||
)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
$(this._$type)
|
||||
.select2({
|
||||
allowClear: false,
|
||||
templateResult: function (res) {
|
||||
const $span = $('<span class="icon-append"></span>').attr('title', res.text).text(res.text)
|
||||
$(`<i class="icon mdi ${(FIELD_TYPES[res.id] || [])[1]}"></i>`).appendTo($span)
|
||||
return $span
|
||||
},
|
||||
})
|
||||
.on('change', (e) => {
|
||||
this.setState({ fieldType: e.target.value })
|
||||
})
|
||||
|
||||
$.get('/admin/entity/entity-list?detail=true&bizz=true', (res) => {
|
||||
const _entities = res.data || []
|
||||
this.setState({ refEntities: _entities }, () => {
|
||||
$(this._$refEntity).select2({ allowClear: false })
|
||||
})
|
||||
|
||||
$.get('/admin/metadata/classification/list', (res2) => {
|
||||
this.setState({ refClasses: res2.data || [] }, () => {
|
||||
$(this._$refClass).select2({ allowClear: false })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
if (this.props.fieldType) {
|
||||
$(this._$saveAndNew).attr('checked', true)
|
||||
$(this._$saveAndNew).parents('.form-group').hide()
|
||||
$(this._$type).parents('.form-group').hide()
|
||||
}
|
||||
|
||||
setTimeout(() => $(this._$fieldLabel).focus(), 200)
|
||||
}
|
||||
|
||||
postNew() {
|
||||
const fieldLabel = $val(this._$fieldLabel),
|
||||
type = $val(this._$type),
|
||||
comments = $val(this._$comments),
|
||||
refEntity = $val(this._$refEntity),
|
||||
refClassification = $val(this._$refClass),
|
||||
stateClass = $val(this._$stateClass) || 'com.rebuild.core.support.state.HowtoState'
|
||||
if (!fieldLabel) return RbHighbar.create($L('请输入字段名称'))
|
||||
|
||||
if ((type === 'REFERENCE' || type === 'N2NREFERENCE') && !refEntity) {
|
||||
return RbHighbar.create($L('请选择引用实体'))
|
||||
} else if (type === 'CLASSIFICATION' && !refClassification) {
|
||||
return RbHighbar.create($L('请选择分类数据'))
|
||||
} else if (type === 'STATE' && !stateClass) {
|
||||
return RbHighbar.create($L('请输入状态类 (StateSpec)'))
|
||||
}
|
||||
|
||||
const data = {
|
||||
entity: this.props.entity,
|
||||
label: fieldLabel,
|
||||
type: type,
|
||||
comments: comments,
|
||||
refEntity: refEntity,
|
||||
refClassification: refClassification,
|
||||
stateClass: stateClass,
|
||||
}
|
||||
|
||||
const $btn = $(this._$btns).find('.btn').button('loading')
|
||||
$.post('/admin/entity/field-new', JSON.stringify(data), (res) => {
|
||||
$btn.button('reset')
|
||||
|
||||
if (res.error_code === 0) {
|
||||
if ($val(this._$saveAndNew)) {
|
||||
RbHighbar.success($L('字段已添加'))
|
||||
$([this._$fieldLabel, this._$comments]).val('')
|
||||
$(this._$fieldLabel).focus()
|
||||
|
||||
// @see fields.html
|
||||
typeof window.loadFields === 'function' && window.loadFields()
|
||||
// @see `form-design.js`
|
||||
typeof window.add2Layout === 'function' && window.add2Layout(res.data, this)
|
||||
} else {
|
||||
location.href = `${rb.baseUrl}/admin/entity/${data.entity}/field/${res.data}`
|
||||
}
|
||||
} else {
|
||||
RbHighbar.error(res.error_msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -15,12 +15,13 @@ $(document).ready(() => {
|
|||
if (e.which === 13) $('.input-search .btn').trigger('click')
|
||||
})
|
||||
$('.J_new-field').on('click', () => {
|
||||
if (wpc.isSuperAdmin) RbModal.create(`/p/admin/metadata/field-new?entity=${wpc.entityName}`, $L('添加字段'))
|
||||
// eslint-disable-next-line react/jsx-no-undef
|
||||
if (wpc.isSuperAdmin) renderRbcomp(<FieldNew2 entity={wpc.entityName} />)
|
||||
else RbHighbar.error($L('仅超级管理员可添加字段'))
|
||||
})
|
||||
|
||||
$('.J_new2-field').on('click', () => {
|
||||
if (wpc.isSuperAdmin) RbModal.create(`/p/admin/metadata/field-new2?entity=${wpc.entityName}`, $L('批量添加字段'), { width: 1064 })
|
||||
$('.J_new9-field').on('click', () => {
|
||||
if (wpc.isSuperAdmin) RbModal.create(`/p/admin/metadata/field-new9?entity=${wpc.entityName}`, $L('批量添加字段'), { width: 1064 })
|
||||
else RbHighbar.error($L('仅超级管理员可添加字段'))
|
||||
})
|
||||
|
||||
|
|
|
@ -393,7 +393,8 @@ const render_unset = function (data) {
|
|||
const render_type = function (fieldType) {
|
||||
const $item = $(`<li class="dd-item"><div class="dd-handle"><i class="icon mdi ${fieldType.icon || 'mdi-form-textbox'}"></i> ${$L(fieldType.label)}</div></li>`).appendTo('.type-list')
|
||||
$item.on('click', function () {
|
||||
if (wpc.isSuperAdmin) RbModal.create(`/p/admin/metadata/field-new?entity=${wpc.entityName}&type=${fieldType.name}`, $L('添加字段'), { disposeOnHide: true })
|
||||
// eslint-disable-next-line react/jsx-no-undef
|
||||
if (wpc.isSuperAdmin) renderRbcomp(<FieldNew2 entity={wpc.entityName} fieldType={fieldType.name} />)
|
||||
else RbHighbar.error($L('仅超级管理员可添加字段'))
|
||||
})
|
||||
return $item
|
||||
|
@ -514,7 +515,7 @@ class DlgEditRefform extends DlgEditField {
|
|||
<option value="">{$L('无')}</option>
|
||||
{Object.keys(_ValidFields).map((k) => {
|
||||
const field = _ValidFields[k]
|
||||
if (['REFERENCE', 'ANYREFERENCE'].includes(field.displayTypeName) && field.fieldName !== 'approvalId') {
|
||||
if (['REFERENCE', 'ANYREFERENCE'].includes(field.displayTypeName) && field.fieldName !== 'approvalId') {
|
||||
return (
|
||||
<option key={field.fieldName} value={field.fieldName}>
|
||||
{field.fieldLabel}
|
||||
|
@ -537,19 +538,17 @@ class DlgEditRefform extends DlgEditField {
|
|||
|
||||
// 追加到布局
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const add2Layout = function (fieldName) {
|
||||
const add2Layout = function (fieldName, dlg) {
|
||||
$.get(`../list-field?entity=${wpc.entityName}`, function (res) {
|
||||
$(res.data).each(function () {
|
||||
if (this.fieldName === fieldName) {
|
||||
render_item({ ...this, tip: this.tip || null })
|
||||
_ValidFields[fieldName] = this
|
||||
console.log(JSON.stringify(_ValidFields))
|
||||
return false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
RbModal.hide()
|
||||
dlg && dlg.hide()
|
||||
}
|
||||
|
||||
// 高级控制
|
||||
|
|
|
@ -32,7 +32,12 @@ $(document).ready(() => {
|
|||
.select2({
|
||||
placeholder: $L('选择关联项'),
|
||||
allowClear: false,
|
||||
matcher: $select2MatcherAll,
|
||||
templateResult: function (res) {
|
||||
const $span = $('<span class="icon-append"></span>').attr('title', res.text).text(res.text)
|
||||
const found = _entities[res.id]
|
||||
if (found) $(`<i class="icon zmdi zmdi-${found.icon}"></i>`).appendTo($span)
|
||||
return $span
|
||||
},
|
||||
})
|
||||
.on('change', () => {
|
||||
if (item_current_isNew === true) {
|
||||
|
|
|
@ -90,7 +90,7 @@ class MessageList extends React.Component {
|
|||
</div>
|
||||
</div>
|
||||
{append && (
|
||||
<a title={$L('查看记录')} className="badge link" href={`${rb.baseUrl}/app/redirect?id=${item[5]}`}>
|
||||
<a title={$L('查看记录')} className="badge link" href={`${rb.baseUrl}/app/redirect?id=${item[5]}&type=newtab`} target="_blank">
|
||||
{$L('查看')}
|
||||
</a>
|
||||
)}
|
||||
|
|
|
@ -164,6 +164,9 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
$.fn.select2.defaults.set('templateResult', function (res) {
|
||||
return $('<span></span>').attr('title', res.text).text(res.text)
|
||||
})
|
||||
$.fn.select2.defaults.set('matcher', function (params, data) {
|
||||
return $select2MatcherAll(params, data)
|
||||
})
|
||||
})(jQuery)
|
||||
|
||||
// extends Array
|
||||
|
|
|
@ -30,7 +30,7 @@ class RbModal extends React.Component {
|
|||
this._rbmodal = c
|
||||
this._element = c
|
||||
}}>
|
||||
<div className={`modal-dialog ${props.useWhite && 'modal-xl'}`} style={style2}>
|
||||
<div className={`modal-dialog ${props.useWhite && 'modal-xl'} ${props.className || ''}`} style={style2}>
|
||||
<div className="modal-content" style={style2}>
|
||||
<div
|
||||
className={`modal-header ${props.useWhite ? '' : 'modal-header-colored'}`}
|
||||
|
@ -828,7 +828,6 @@ class AnyRecordSelector extends React.Component {
|
|||
.select2({
|
||||
placeholder: $L('无可用实体'),
|
||||
allowClear: false,
|
||||
matcher: $select2MatcherAll,
|
||||
})
|
||||
.on('change', () => {
|
||||
$(this._record).val(null).trigger('change')
|
||||
|
|
|
@ -40,10 +40,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<div class="main-content container-fluid">
|
||||
<div class="main-content container-fluid position-relative">
|
||||
<div class="quick-filter-tabs" th:if="${advListFilterTabs == 'true'}">
|
||||
<div>
|
||||
<div class="dropdown-item"><a>[[${bundle.L('全部数据')}]]</a></div>
|
||||
<div class="dropdown-item"><a>[[${bundle.L('默认视图')}]]</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="quick-filter-pane" th:if="${advListFilterPane == 'true'}">
|
||||
|
|
|
@ -40,10 +40,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<div class="main-content container-fluid">
|
||||
<div class="main-content container-fluid position-relative">
|
||||
<div class="quick-filter-tabs" th:if="${advListFilterTabs == 'true'}">
|
||||
<div>
|
||||
<div class="dropdown-item"><a>[[${bundle.L('全部数据')}]]</a></div>
|
||||
<div class="dropdown-item"><a>[[${bundle.L('默认视图')}]]</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="quick-filter-pane" th:if="${advListFilterPane == 'true'}">
|
||||
|
|
Loading…
Reference in a new issue