Fix 4.0.3 (#890)

* be: DockerInstaller

* be: docker

* 4.0.3

* be

* Update RebuildException.java

* ND tips

* Update DepartmentService.java

* fix: 审批统计数量

* fix: style

* fix:使用 RecordTransfomer39 修复表单回填/计算后端问题

* fix: 表单折叠隐藏字段

* Update trigger.FIELDWRITEBACK.js

---------

Co-authored-by: devezhao <zhaofang123@gmail.com>
This commit is contained in:
REBUILD 企业管理系统 2025-04-24 12:45:48 +08:00 committed by GitHub
parent 49c315cf65
commit f49dc27c89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 183 additions and 4417 deletions

View file

@ -4,7 +4,7 @@ RUN apk add ttf-dejavu
RUN apk add wget
RUN mkdir -p /app/rebuild/.rebuild/
ADD ./rebuild-boot-4.0.0.jar /app/rebuild/rebuild-boot.jar
ADD ./rebuild.jar /app/rebuild/rebuild-boot.jar
ADD https://www.qn-cdn.getrebuild.com/pub/deploy/SourceHanSansK-Regular.ttf /app/rebuild/.rebuild/
EXPOSE 18080

View file

@ -3,11 +3,11 @@ services:
image: mysql:5.7
environment:
MYSQL_ROOT_HOST: "%"
MYSQL_ROOT_PASSWORD: "rebuildP4wd"
MYSQL_ROOT_PASSWORD: "rebuild!P4wd"
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD" ]
test: [ "CMD", "mysqladmin", "ping", "-h", "mysql", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD" ]
interval: 5s
timeout: 3s
retries: 10
@ -15,7 +15,7 @@ services:
- app_network
rebuild:
image: getrebuild/rebuild:4.0.2
image: getrebuild/rebuild:latest
depends_on:
mysql:
condition: service_healthy
@ -23,8 +23,7 @@ services:
command:
- >
mkdir -p /app/rebuild/.rebuild &&
wget -O /app/rebuild/.rebuild/.rebuild https://www.qn-cdn.getrebuild.com/pub/deploy/.rebuild &&
java -Dinitialize=yes -Duser.timezone=Asia/Shanghai -DDataDirectory=/app/rebuild/.rebuild -jar /app/rebuild/rebuild-boot.jar
java -Dinitialize=docker -Duser.timezone=Asia/Shanghai -DSN= -DDataDirectory=/app/rebuild/.rebuild -jar /app/rebuild/rebuild-boot.jar
ports:
- "18080:18080"
volumes:

4249
.deploy/package-lock.json generated

File diff suppressed because it is too large Load diff

2
@rbv

@ -1 +1 @@
Subproject commit b93ade10867b9c370870d8feffa2e429f503ea6b
Subproject commit 07ba14147145a9fb9646563605427f680ac82d13

View file

@ -10,7 +10,7 @@
</parent>
<groupId>com.rebuild</groupId>
<artifactId>rebuild</artifactId>
<version>4.0.2</version>
<version>4.0.3</version>
<name>rebuild</name>
<description>Building your business-systems freely!</description>
<url>https://getrebuild.com/</url>

View file

@ -75,11 +75,11 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
/**
* Rebuild Version
*/
public static final String VER = "4.0.2";
public static final String VER = "4.0.3";
/**
* Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2}
*/
public static final int BUILD = 4000208;
public static final int BUILD = 4000309;
static {
// Driver for DB
@ -134,46 +134,9 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
final Timer timer = new Timer("Boot-Timer");
try {
// v4.0.2 for Docker
DockerInstaller di = new DockerInstaller();
final boolean isNeedInitialize = di.isNeedInitialize();
if (isNeedInitialize) {
log.info("Initializing REBUILD for Docker container ...");
di.install();
}
if (Installer.isInstalled()) {
started = init();
if (started) {
final long timeCost = System.currentTimeMillis() - time;
timer.schedule(new TimerTask() {
@Override
public void run() {
String localUrl = BootApplication.getLocalUrl(null);
String banner = RebuildBanner.formatSimple(
"REBUILD (" + VER + ") started successfully in " + timeCost + " ms.",
" License : " + License.queryAuthority().values(),
"Access URLs : ",
" Local : " + localUrl,
" External : " + localUrl.replace("localhost", OshiUtils.getLocalIp()),
" Public : " + RebuildConfiguration.getHomeUrl());
log.info(banner);
if (!License.isCommercial()) {
String thanks = RebuildBanner.formatSimple(
"**********",
"感谢使用 REBUILD",
"您当前使用的是免费版本,如果 REBUILD 对贵公司业务有帮助,请考虑购买商业授权版本,帮助我们可持续发展!",
"查看详情 https://getrebuild.com/#pricing-plans",
"**********");
System.out.println(thanks);
}
}
}, 999);
if (isNeedInitialize) di.installAfter();
}
if (started) printStartup(timer, System.currentTimeMillis() - time);
} else {
timer.schedule(new TimerTask() {
@ -184,6 +147,14 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
"Install : " + BootApplication.getLocalUrl("/setup/install")));
}
}, 999);
// v4.0.3 for Docker
DockerInstaller di = new DockerInstaller();
if (di.isNeedInitialize()) {
log.info("Initializing REBUILD for Docker container ...");
di.install();
printStartup(timer, System.currentTimeMillis() - time);
}
}
} catch (Exception ex) {
@ -205,6 +176,34 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
}
}
// 打印启动信息
private void printStartup(Timer timer, long timeCost) {
timer.schedule(new TimerTask() {
@Override
public void run() {
String localUrl = BootApplication.getLocalUrl(null);
String banner = RebuildBanner.formatSimple(
"REBUILD (" + VER + ") started successfully in " + timeCost + " ms.",
" License : " + License.queryAuthority().values(),
"Access URLs : ",
" Local : " + localUrl,
" External : " + localUrl.replace("localhost", OshiUtils.getLocalIp()),
" Public : " + RebuildConfiguration.getHomeUrl());
log.info(banner);
if (!License.isCommercial()) {
String thanks = RebuildBanner.formatSimple(
"\n **********",
"感谢使用 REBUILD",
"您当前使用的是免费版本,如果 REBUILD 对贵公司业务有帮助,请考虑购买商业授权版本,帮助我们可持续发展!",
"查看详情 https://getrebuild.com/#pricing-plans",
"**********");
log.info(thanks);
}
}
}, 999);
}
/**
* 系统初始化
*

View file

@ -17,6 +17,7 @@ public class RebuildException extends RuntimeException {
private static final long serialVersionUID = -889444005870894361L;
public RebuildException() {
super();
}
public RebuildException(String message) {

View file

@ -56,6 +56,11 @@ public class DepartmentService extends BaseService {
@Override
public Record update(Record record) {
if (ROOT_DEPT.equals(record.getPrimary())) {
Boolean b = record.getBoolean("isDisabled");
if (b != null && b) throw new OperationDeniedException("内置部门不能禁用");
}
checkAdminGuard(BizzPermission.UPDATE, record.getPrimary());
// 检查父子循环依赖

View file

@ -7,10 +7,10 @@ See LICENSE and COMMERCIAL in the project root for license information.
package com.rebuild.core.service.dashboard.charts.builtin;
import cn.devezhao.commons.ObjectUtils;
import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.engine.ID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.core.Application;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.metadata.easymeta.EasyMetaFactory;
@ -28,9 +28,7 @@ import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 审批列表/统计
@ -61,38 +59,43 @@ public class ApprovalList extends ChartData implements BuiltinChart {
@Override
public JSON build() {
final int viewState = ObjectUtils.toInt(getExtraParams().get("state"), ApprovalState.DRAFT.getState());
final String baseWhere = "where isCanceled = 'F' and isWaiting = 'F' and approver = ?" +
" and approvalId <> '' and recordId <> '' and ";
// FIXME 存在一定性能问题
JSONObject data = new JSONObject();
data.put("state1", queryByState(ApprovalState.DRAFT.getState()));
data.put("state10", queryByState(ApprovalState.APPROVED.getState()));
data.put("state11", queryByState(ApprovalState.REJECTED.getState()));
return data;
}
Object[][] array = Application.createQueryNoFilter(
"select createdBy,modifiedOn,recordId,approvalId from RobotApprovalStep " +
baseWhere + " state = ? order by modifiedOn desc")
protected List<Object[]> queryByState(int viewState) {
String sql = "select createdBy,modifiedOn,recordId,approvalId from RobotApprovalStep" +
" where isCanceled = 'F' and isWaiting = 'F' and approver = ? and approvalId <> '' and recordId <> '' and state = ?" +
" order by modifiedOn desc";
Object[][] array = Application.createQueryNoFilter(sql)
.setParameter(1, getUser())
.setParameter(2, viewState)
.setLimit(500) // 最多显示
.array();
List<Object> rearray = new ArrayList<>();
int removed = 0;
List<Object[]> stateList = new ArrayList<>();
for (Object[] o : array) {
final ID recordId = (ID) o[2];
String label;
try {
label = FieldValueHelper.getLabel(recordId);
} catch (NoRecordFoundException ignored) {
removed++;
// 已删除
continue;
}
final ApprovalState currentState = ApprovalHelper.getApprovalState(recordId);
// 已取消
ApprovalState currentState = ApprovalHelper.getApprovalState(recordId);
if (currentState == ApprovalState.CANCELED) {
removed++;
continue;
}
FlowNode currentNode = null;
if (currentState == ApprovalState.PROCESSING) {
if (viewState == ApprovalState.PROCESSING.getState()) {
try {
ApprovalProcessor approvalProcessor = new ApprovalProcessor(recordId, (ID) o[3]);
currentNode = approvalProcessor.getCurrentNode();
@ -103,7 +106,7 @@ public class ApprovalList extends ChartData implements BuiltinChart {
Entity e = MetadataHelper.getEntity(recordId.getEntityCode());
ID s = ApprovalHelper.getSubmitter(recordId, (ID) o[3]);
rearray.add(new Object[]{
stateList.add(new Object[]{
s,
UserHelper.getName(s),
I18nUtils.formatDate((Date) o[1]),
@ -116,27 +119,6 @@ public class ApprovalList extends ChartData implements BuiltinChart {
});
}
Object[][] stats = Application.createQueryNoFilter(
"select state,count(state) from RobotApprovalStep " + baseWhere + " state < ? group by state")
.setParameter(1, this.getUser())
.setParameter(2, ApprovalState.CANCELED.getState())
.array();
// 排除删除和无效的可能导致不同状态下数据不一致
if (removed > 0) {
for (Object[] o : stats) {
if ((Integer) o[0] == viewState) {
o[1] = ObjectUtils.toInt(o[1]) - removed;
if ((Integer) o[1] < 0) {
o[1] = 0;
}
}
}
}
Map<String, Object> ret = new HashMap<>();
ret.put("data", rearray);
ret.put("stats", stats);
ret.put("overLimit", array.length >= 500);
return (JSON) JSON.toJSON(ret);
return stateList;
}
}

View file

@ -40,6 +40,11 @@ public class RecordTransfomer37 extends RecordTransfomer {
super(targetEntity, transConfig, skipGuard);
}
@Override
public ID transform(ID sourceRecordId) {
return this.transform(sourceRecordId, null);
}
@Override
public ID transform(ID sourceRecordId, ID specMainId) {
//

View file

@ -35,6 +35,8 @@ import java.util.Map;
import java.util.Set;
/**
* v3.9 新增转换为新记录或已存在记录
*
* @author Zixin
* @since 2024/4/8
*/
@ -52,6 +54,16 @@ public class RecordTransfomer39 extends RecordTransfomer37 {
this.transid = transid;
}
@Override
public ID transform(ID sourceRecordId) {
return this.transform(sourceRecordId, null, null);
}
@Override
public ID transform(ID sourceRecordId, ID specMainId) {
return this.transform(sourceRecordId, specMainId, null);
}
/**
* 转换
*

View file

@ -9,10 +9,17 @@ package com.rebuild.core.support.setup;
import com.alibaba.fastjson.JSONObject;
import com.rebuild.core.Application;
import com.rebuild.core.support.RebuildConfiguration;
import com.rebuild.utils.JSONUtils;
import com.rebuild.utils.OshiUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import java.io.File;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.Properties;
import static com.rebuild.core.support.ConfigurationItem.CacheHost;
/**
* Docker 安装
@ -32,7 +39,7 @@ public class DockerInstaller extends Installer {
JSONObject installProps = new JSONObject();
JSONObject databaseProps = JSONUtils.toJSONObject(
new String[]{"dbName", "dbHost", "dbPort", "dbUser", "dbPassword"},
new String[]{"rebuild40", "mysql", "3306", "root", "rebuildP4wd"});
new String[]{"rebuild40", "mysql", "3306", "root", "rebuild!P4wd"});
if (Application.devMode()) {
databaseProps.put("dbHost", "localhost");
databaseProps.put("dbUser", "rebuild");
@ -45,28 +52,27 @@ public class DockerInstaller extends Installer {
@Override
public void install() throws Exception {
this.installDatabase();
}
/**
*/
public void installAfter() {
try {
this.installClassificationAsync();
} catch (Exception ex) {
log.error("Error installing classification data", ex);
Properties installProps = buildConnectionProps(null);
installProps.put(CONF_PREFIX + CacheHost.name(), "0");
File dest = RebuildConfiguration.getFileOfData(INSTALL_FILE);
try (OutputStream os = Files.newOutputStream(dest.toPath())) {
installProps.store(os, "REBUILD INSTALLER MAGIC FOR DOCKER !!! DO NOT EDIT !!!");
log.info("Saved installation file : {}", dest);
}
this.refresh();
this.installClassificationAsync();
}
/**
* 是否需要安装
*
* @return
*/
public boolean isNeedInitialize() {
if (!OshiUtils.isDockerEnv()) return false;
if (!BooleanUtils.toBoolean(System.getProperty("initialize"))) return false;
if (Installer.isInstalled()) {
return !isRbDatabase();
}
return false;
if (Installer.isInstalled()) return false;
return OshiUtils.isDockerEnv() && "docker".equals(System.getProperty("initialize"));
}
}

View file

@ -132,11 +132,10 @@ public class Installer implements InstallState {
installProps.put(CONF_PREFIX + CachePassword.name(), String.format("AES(%s)", AES.encrypt(cachePasswd)));
}
} else {
// Use ehcache
// Ehcache
installProps.put(CONF_PREFIX + CacheHost.name(), "0");
}
// Save install state (file)
File dest = RebuildConfiguration.getFileOfData(INSTALL_FILE);
try {
FileUtils.deleteQuietly(dest);
@ -149,7 +148,6 @@ public class Installer implements InstallState {
throw new SetupException(e);
}
// Refresh
try {
refresh();
} catch (Exception ex) {
@ -157,7 +155,6 @@ public class Installer implements InstallState {
throw ex;
}
// Clean cached
clearAllCache();
if (!dbNew) return;
@ -174,17 +171,13 @@ public class Installer implements InstallState {
log.error("Error installing business module", ex);
}
try {
this.installClassificationAsync();
} catch (Exception ex) {
log.error("Error installing classification data", ex);
}
this.installClassificationAsync();
}
/**
* 刷新配置
*/
private void refresh() throws Exception {
protected void refresh() throws Exception {
// 重配置
Application.getBean(BootEnvironmentPostProcessor.class).postProcessEnvironment(null, null);
@ -248,7 +241,7 @@ public class Installer implements InstallState {
* @param dbName
* @return
*/
private Properties buildConnectionProps(String dbName) {
protected Properties buildConnectionProps(String dbName) {
final JSONObject dbProps = installProps.getJSONObject("databaseProps");
if (dbName == null) {
dbName = dbProps == null ? null : dbProps.getString("dbName");

View file

@ -17,7 +17,7 @@ import org.apache.commons.lang.SystemUtils;
*/
public class RebuildBanner {
static final String COMMON_BANNER = "" +
static final String COMMON_BANNER =
"\n Version : " + Application.VER +
"\n OS : " + SystemUtils.OS_NAME + " (" + SystemUtils.OS_ARCH + ")" +
"\n JVM : " + SystemUtils.JAVA_VM_NAME + " (" + SystemUtils.JAVA_VERSION + ")" +

View file

@ -38,6 +38,7 @@ import com.rebuild.core.privileges.UserHelper;
import com.rebuild.core.rbstore.MetaschemaExporter;
import com.rebuild.core.service.general.QuickCodeReindexTask;
import com.rebuild.core.service.general.series.SeriesGeneratorFactory;
import com.rebuild.core.support.License;
import com.rebuild.core.support.RebuildConfiguration;
import com.rebuild.core.support.general.FieldValueHelper;
import com.rebuild.core.support.task.TaskExecutors;
@ -209,6 +210,11 @@ public class MetaEntityController extends EntityController {
if (useMain.getMainEntity() != null) {
return RespBody.errorl("明细实体不能作为主实体");
}
if (useMain.getDetailEntity() != null && !License.isCommercial()) {
return RespBody.errorl(
"免费版不支持%s功能 [(查看详情)](https://getrebuild.com/docs/rbv-features)", "多明细");
}
}
try {

View file

@ -127,7 +127,7 @@ public class LoginController extends LoginAction {
} else {
mv.getModel().put("ssoDingtalk", "#");
mv.getModel().put("ssoWxwork", "#");
// mv.getModel().put("ssoFeishu", "#");
mv.getModel().put("ssoFeishu", "#");
}
mv.getModelMap().put("UsersMsg", SysbaseHeartbeat.getUsersDanger());

View file

@ -147,6 +147,7 @@ div.dataTables_wrapper div.dataTables_oper.compact .btn-space {
.page-aside.widgets .tab-container {
min-width: 229px;
}
.rb-aside .page-head,
.rb-aside .main-content {
margin-left: 230px;
}

View file

@ -1004,6 +1004,10 @@ a.link.link-icon::after {
margin-right: 15px;
}
.form-layout .collapsed-hide {
display: none !important;
}
.rbform > .row.form {
padding-top: 5px;
padding-bottom: 5px;

View file

@ -866,18 +866,28 @@ class ApprovalList extends BaseChart {
constructor(props) {
super(props)
this.__approvalForms = {}
this.state.viewState = 1
}
renderChart(data) {
let statsTotal = 0
this._lastStats = this._lastStats || data.stats
this._lastStats.forEach((item) => (statsTotal += item[1]))
renderChart(data, viewState) {
viewState = viewState || 1
const stats = (
let stats = []
let statsTotal = 0
Object.keys(APPROVAL_STATES).forEach((state) => {
let len = (data['state' + state] || []).length
stats.push([~~state, len])
statsTotal += len
})
if (statsTotal === 0) {
this.renderError($L('暂无数据'))
return
}
const statsComp = (
<div className="progress-wrap sticky">
<div className="progress">
{this._lastStats.map((item) => {
{stats.map((item) => {
const s = APPROVAL_STATES[item[0]]
if (!s || s[1] <= 0) return null
@ -885,26 +895,22 @@ class ApprovalList extends BaseChart {
return (
<div
key={s[0]}
className={`progress-bar bg-${s[0]} ${this.state.viewState === item[0] && 'active'}`}
// title={`${s[1]} : ${item[1]} (${p})`}
className={`progress-bar bg-${s[0]} ${viewState === item[0] && 'active'}`}
style={{ width: p }}
onClick={() => this._changeState(item[0])}>
onClick={() => {
this.renderChart(data, item[0])
}}>
{s[1]} ({item[1]})
</div>
)
})}
</div>
<p className="m-0 mt-1 fs-11 text-muted text-right hide">{$L('审批统计')}</p>
</div>
)
if (statsTotal === 0) {
this.renderError($L('暂无数据'))
return
}
const table =
(data.data || []).length === 0 ? (
const viewData = data['state' + viewState] || []
const tableComp =
viewData.length === 0 ? (
<div className="chart-undata must-center">
<i className="zmdi zmdi-check icon text-success" /> {$L('你已完成所有审批')}
</div>
@ -919,7 +925,7 @@ class ApprovalList extends BaseChart {
</tr>
</thead>
<tbody>
{data.data.map((item, idx) => {
{viewData.map((item, idx) => {
let expType = isNaN(item[8]) ? null : item[8]
if (expType !== null) expType = item[8] > 0 ? 2 : 1
return (
@ -942,20 +948,20 @@ class ApprovalList extends BaseChart {
<span className="cell-detail-description">{item[6]}</span>
</td>
<td className="actions text-right text-nowrap">
{this.state.viewState === 1 && (
{viewState === 1 && (
<button className="btn btn-secondary btn-sm" onClick={() => this.approve(item[3], item[5], item[7])}>
{$L('审批')}
</button>
)}
{this.state.viewState === 10 && <span className="text-success">{$L('通过')}</span>}
{this.state.viewState === 11 && <span className="text-danger">{$L('驳回')}</span>}
{viewState === 10 && <span className="text-success">{$L('通过')}</span>}
{viewState === 11 && <span className="text-danger">{$L('驳回')}</span>}
</td>
</tr>
)
})}
</tbody>
</table>
{data.overLimit && (
{viewData.length >= 500 && (
<div className="m-2 text-center text-warning">
<i className="mdi mdi-information-outline" /> {$L('最多显示最近 500 条记录')}
</div>
@ -965,8 +971,8 @@ class ApprovalList extends BaseChart {
const chartdata = (
<div className="chart ApprovalList">
{stats}
{table}
{statsComp}
{tableComp}
</div>
)
this.setState({ chartdata: chartdata }, () => {
@ -975,14 +981,14 @@ class ApprovalList extends BaseChart {
.find('.ApprovalList')
.css('height', $tb.height() - 5)
.perfectScrollbar()
this._$tb = $tb
})
}
resize() {
$setTimeout(
() => {
if (this._$tb) this._$tb.find('.ApprovalList').css('height', this._$tb.height() - 5)
const $tb = $(this._$body)
if ($tb) $tb.find('.ApprovalList').css('height', $tb.height() - 5)
},
400,
`resize-chart-${this.state.id}`
@ -990,31 +996,27 @@ class ApprovalList extends BaseChart {
}
approve(record, approval, entity) {
event.preventDefault()
window.event && window.event.preventDefault()
if (this.__approvalForms[record]) {
this.__approvalForms[record].show()
} else {
const that = this
const close = function () {
if (that.__approvalForms[record]) that.__approvalForms[record].hide(true)
that.loadChartData()
}
// eslint-disable-next-line react/jsx-no-undef
renderRbcomp(<ApprovalApproveForm id={record} approval={approval} entity={entity} call={close} />, function () {
that.__approvalForms[record] = this
that._lastStats = null
})
renderRbcomp(
<ApprovalApproveForm
id={record}
approval={approval}
entity={entity}
call={() => {
if (that.__approvalForms[record]) that.__approvalForms[record].hide(true)
that.loadChartData()
}}
/>,
function () {
that.__approvalForms[record] = this
}
)
}
}
_changeState(state) {
if (state === this.state.viewState) state = 1
this.setState({ viewState: state }, () => this.loadChartData())
}
buildDataUrl() {
return `${super.buildDataUrl()}&state=${this.state.viewState}`
}
}
// ~ 我的日程

View file

@ -3127,8 +3127,8 @@ class RbFormDivider extends React.Component {
let $next = $(this._$formLine)
while (($next = $next.next()).length > 0) {
if ($next.hasClass('form-line') || $next.hasClass('footer')) break
$next.toggleClass('hide')
if (collapsed === null) collapsed = $next.hasClass('hide')
$next.toggleClass('collapsed-hide')
if (collapsed === null) collapsed = $next.hasClass('collapsed-hide')
}
this.setState({ collapsed })
}

View file

@ -93,7 +93,6 @@ class EntityNew2 extends RbModalHandler {
{this.state.entities &&
this.state.entities.map((item) => {
if (item.mainEntity) return null
if (item.detailEntity && rb.commercial < 10) return null
return (
<option key={item.entityName} value={item.entityName}>
{item.entityLabel}
@ -270,7 +269,7 @@ class EntityNew2 extends RbModalHandler {
location.href = `${rb.baseUrl}/admin/entity/${res.data}/base`
} else {
$btn.button('reset')
RbHighbar.error(res.error_msg)
RbHighbar.error(WrapHtml(res.error_msg))
}
})
}

View file

@ -252,8 +252,9 @@ class ContentFieldWriteback extends ActionContentSpec {
templateResult: function (res) {
const text = res.text.split(' (N)')
const $span = $('<span></span>').text(text[0])
if (text.length > 1) $('<span class="badge badge-default badge-pill">N</span>').appendTo($span)
else if (res.children && res.children.length > 0) $('<sup class="rbv ml-1"></sup>').appendTo($span)
if (text.length > 1 || (res.children && res.children.length > 0)) {
$('<span class="badge badge-default badge-pill">N</span>').appendTo($span)
}
return $span
},
})