mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 15:35:55 +08:00
Merge pull request #174 from getrebuild/dept-tree-collapse-563
RB-563 Dept tree collapse
This commit is contained in:
commit
25d6cd35a3
|
@ -232,15 +232,6 @@ public final class Application {
|
|||
return serversReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加服务停止钩子
|
||||
* @param hook
|
||||
*/
|
||||
public static void addShutdownHook(Thread hook) {
|
||||
LOG.info("Add shutdown hook : " + hook.getName());
|
||||
Runtime.getRuntime().addShutdownHook(hook);
|
||||
}
|
||||
|
||||
/**
|
||||
* SPRING Context
|
||||
* @return
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.rebuild.server.helper.ConfigurableItem;
|
|||
import com.rebuild.server.helper.License;
|
||||
import com.rebuild.server.helper.SysConfiguration;
|
||||
import com.rebuild.server.helper.setup.InstallState;
|
||||
import com.rebuild.server.helper.task.TaskExecutors;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
@ -82,8 +83,9 @@ public class ServerListener extends ContextCleanupListener implements InstallSta
|
|||
@Override
|
||||
public void contextDestroyed(ServletContextEvent event) {
|
||||
LOG.info("Rebuild shutdown ...");
|
||||
super.contextDestroyed(event);
|
||||
Application.getBean(TaskExecutors.class).shutdown();
|
||||
((ClassPathXmlApplicationContext) Application.getApplicationContext()).close();
|
||||
super.contextDestroyed(event);
|
||||
}
|
||||
|
||||
// --
|
||||
|
|
|
@ -91,7 +91,7 @@ public class RobotTriggerObserver extends OperatingObserver {
|
|||
}
|
||||
}
|
||||
|
||||
// 异步执行。注意这会开启新事物
|
||||
// 异步执行
|
||||
for (TriggerAction action : actions) {
|
||||
if (!action.useAsync()) continue;
|
||||
LOG.info("Trigger [ " + action.getType() + " ] by record : " + context.getAnyRecord().getPrimary());
|
||||
|
|
|
@ -52,7 +52,7 @@ public interface TriggerAction {
|
|||
void prepare(OperatingContext operatingContext) throws TriggerException;
|
||||
|
||||
/**
|
||||
* 异步执行。注意:异步执行会开启新事物,所以如果依赖主事物的数据,可能存在幻读
|
||||
* 异步执行。注意:由于异步执行可能会开启新事物,所以如果依赖主事物的数据,可能存在脏读
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
|
|
@ -47,7 +47,6 @@ public class SendNotification implements TriggerAction {
|
|||
private static final Log LOG = LogFactory.getLog(SendNotification.class);
|
||||
|
||||
// 通知
|
||||
@SuppressWarnings("unused")
|
||||
private static final int TYPE_NOTIFICATION = 1;
|
||||
// 邮件
|
||||
private static final int TYPE_MAIL = 2;
|
||||
|
@ -104,7 +103,7 @@ public class SendNotification implements TriggerAction {
|
|||
SMSender.sendSMS(mobile, message);
|
||||
}
|
||||
|
||||
} else {
|
||||
} else if (type == TYPE_NOTIFICATION) {
|
||||
Message m = MessageBuilder.createMessage(user, message, context.getSourceRecord());
|
||||
Application.getNotifications().send(m);
|
||||
|
||||
|
@ -124,44 +123,39 @@ public class SendNotification implements TriggerAction {
|
|||
* @return
|
||||
*/
|
||||
protected String formatMessage(String message, ID recordId) {
|
||||
ThreadPool.waitFor(200);
|
||||
|
||||
Map<String, String> vars = null;
|
||||
Map<String, String> fieldVars = new HashMap<>();
|
||||
if (recordId != null) {
|
||||
Entity entity = MetadataHelper.getEntity(recordId.getEntityCode());
|
||||
vars = new HashMap<>();
|
||||
|
||||
Matcher m = PATT_FIELD.matcher(message);
|
||||
while (m.find()) {
|
||||
String field = m.group(1);
|
||||
if (MetadataHelper.getLastJoinField(entity, field) == null) {
|
||||
continue;
|
||||
String fieldName = m.group(1);
|
||||
if (MetadataHelper.checkAndWarnField(entity, fieldName)) {
|
||||
fieldVars.put(fieldName, null);
|
||||
}
|
||||
vars.put(field, null);
|
||||
}
|
||||
|
||||
if (!vars.isEmpty()) {
|
||||
if (!fieldVars.isEmpty()) {
|
||||
String sql = String.format("select %s from %s where %s = ?",
|
||||
StringUtils.join(vars.keySet(), ","), entity.getName(), entity.getPrimaryField().getName());
|
||||
StringUtils.join(fieldVars.keySet(), ","), entity.getName(), entity.getPrimaryField().getName());
|
||||
|
||||
Record o = Application.createQueryNoFilter(sql)
|
||||
.setParameter(1, recordId)
|
||||
.record();
|
||||
ThreadPool.waitFor(500);
|
||||
Record o = Application.createQueryNoFilter(sql).setParameter(1, recordId).record();
|
||||
if (o != null) {
|
||||
for (String field : vars.keySet()) {
|
||||
for (String field : fieldVars.keySet()) {
|
||||
Object value = o.getObjectValue(field);
|
||||
value = FieldValueWrapper.instance.wrapFieldValue(
|
||||
value, MetadataHelper.getLastJoinField(entity, field), true);
|
||||
if (value != null) {
|
||||
vars.put(field, value.toString());
|
||||
fieldVars.put(field, value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vars != null) {
|
||||
for (Map.Entry<String, String> e : vars.entrySet()) {
|
||||
|
||||
if (!fieldVars.isEmpty()) {
|
||||
for (Map.Entry<String, String> e : fieldVars.entrySet()) {
|
||||
message = message.replaceAll(
|
||||
"\\{" + e.getKey() + "}", StringUtils.defaultIfBlank(e.getValue(), StringUtils.EMPTY));
|
||||
}
|
||||
|
@ -169,6 +163,8 @@ public class SendNotification implements TriggerAction {
|
|||
return message;
|
||||
}
|
||||
|
||||
// 这里使用异步可能存在脏读问题
|
||||
// 但考虑到具体的业务消息(短信、邮件)发送后也不能撤销、提升速度
|
||||
@Override
|
||||
public boolean useAsync() {
|
||||
return true;
|
||||
|
|
|
@ -18,13 +18,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
package com.rebuild.server.helper.cache;
|
||||
|
||||
import com.rebuild.server.Application;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.Cache.ValueWrapper;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.ehcache.EhCacheCacheManager;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
@ -94,12 +92,4 @@ public class EhcacheDriver<V extends Serializable> implements CacheTemplate<V> {
|
|||
public Cache cache() {
|
||||
return ehcacheManager.getCache("rebuild");
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭 Ehcache 以便将缓存持久化到硬盘
|
||||
*/
|
||||
public void shutdown() {
|
||||
Application.LOG.info("Ehcache shutdown ...");
|
||||
((EhCacheCacheManager) ehcacheManager).getCacheManager().shutdown();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
/*
|
||||
rebuild - Building your business-systems freely.
|
||||
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
|
||||
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
|
||||
See LICENSE and COMMERCIAL in the project root for license information.
|
||||
*/
|
||||
|
||||
package com.rebuild.server.helper.task;
|
||||
|
@ -21,12 +10,14 @@ package com.rebuild.server.helper.task;
|
|||
import cn.devezhao.commons.CodecUtils;
|
||||
import cn.devezhao.commons.ThreadPool;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
import com.rebuild.server.Application;
|
||||
import com.rebuild.server.RebuildException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -39,9 +30,13 @@ import java.util.concurrent.TimeUnit;
|
|||
*
|
||||
* @author devezhao
|
||||
* @since 09/29/2018
|
||||
* @see org.springframework.core.task.SyncTaskExecutor
|
||||
* @see org.springframework.core.task.AsyncTaskExecutor
|
||||
*/
|
||||
public class TaskExecutors extends QuartzJobBean {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(TaskExecutors.class);
|
||||
|
||||
private static final int MAX_TASK = Runtime.getRuntime().availableProcessors() / 2;
|
||||
|
||||
private static final int MAX_QUEUE = MAX_TASK * 10;
|
||||
|
@ -122,8 +117,17 @@ public class TaskExecutors extends QuartzJobBean {
|
|||
long leftTime = (System.currentTimeMillis() - task.getCompletedTime().getTime()) / 1000;
|
||||
if (leftTime > 60 * 120) {
|
||||
TASKS.remove(e.getKey());
|
||||
Application.LOG.info("HeavyTask self-destroying : " + e.getKey());
|
||||
LOG.info("HeavyTask self-destroying : " + e.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public void shutdown() {
|
||||
List<Runnable> runs = EXECS.shutdownNow();
|
||||
if (!runs.isEmpty()) {
|
||||
LOG.warn(runs.size() + " tasks interrupted");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
/*
|
||||
rebuild - Building your business-systems freely.
|
||||
Copyright (C) 2019 devezhao <zhaofang123@gmail.com>
|
||||
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
|
||||
See LICENSE and COMMERCIAL in the project root for license information.
|
||||
*/
|
||||
|
||||
package com.rebuild.server.service;
|
||||
|
@ -30,6 +19,7 @@ import org.springframework.transaction.support.DefaultTransactionDefinition;
|
|||
*
|
||||
* @author devezhao
|
||||
* @since 2019/8/21
|
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
*/
|
||||
public class TransactionManual {
|
||||
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
/*
|
||||
rebuild - Building your business-systems freely.
|
||||
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
|
||||
Copyright (c) REBUILD <https://getrebuild.com/> and its owners. All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
rebuild is dual-licensed under commercial and open source licenses (GPLv3).
|
||||
See LICENSE and COMMERCIAL in the project root for license information.
|
||||
*/
|
||||
|
||||
package com.rebuild.web;
|
||||
|
@ -33,6 +22,7 @@ import com.rebuild.web.user.signin.LoginControll;
|
|||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -58,7 +48,13 @@ public class OnlineSessionStore extends CurrentCaller implements HttpSessionList
|
|||
private static final Set<HttpSession> ONLINE_SESSIONS = new CopyOnWriteArraySet<>();
|
||||
private static final Map<ID, HttpSession> ONLINE_USERS = new ConcurrentHashMap<>();
|
||||
|
||||
private static final ThreadLocal<String> LOCALE = new ThreadLocal<>();
|
||||
private static final ThreadLocal<String> LOCALE = new NamedThreadLocal<>("Current session user");
|
||||
|
||||
/**
|
||||
* 最近访问 [时间, 路径]
|
||||
* @see #storeLastActive(HttpServletRequest)
|
||||
*/
|
||||
public static final String SK_LASTACTIVE = WebUtils.KEY_PREFIX + "Session-LastActive";
|
||||
|
||||
@Override
|
||||
public void sessionCreated(HttpSessionEvent event) {
|
||||
|
@ -94,16 +90,7 @@ public class OnlineSessionStore extends CurrentCaller implements HttpSessionList
|
|||
Application.getCommonService().update(logout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 最近访问时间
|
||||
*/
|
||||
public static final String SK_LASTACTIVE = WebUtils.KEY_PREFIX + "Session-LastActive";
|
||||
/**
|
||||
* 最近访问路径
|
||||
*/
|
||||
public static final String SK_LASTACCESS = WebUtils.KEY_PREFIX + "Session-LastAccess";
|
||||
|
||||
|
||||
/**
|
||||
* 所有会话
|
||||
*
|
||||
|
@ -130,10 +117,10 @@ public class OnlineSessionStore extends CurrentCaller implements HttpSessionList
|
|||
* @param request
|
||||
*/
|
||||
public void storeLastActive(HttpServletRequest request) {
|
||||
HttpSession s = request.getSession(true);
|
||||
s.setAttribute(SK_LASTACTIVE, CalendarUtils.now());
|
||||
HttpSession s = request.getSession();
|
||||
s.setAttribute(SK_LASTACTIVE, new Object[] { System.currentTimeMillis(), request.getRequestURI() } );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param request
|
||||
*/
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>EMAIL TEMPLATE</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="background-color:#f5f5f5;margin:0;font-size:0.9rem;padding:20px 30px;color:#333;font-family:Roboto,Helvetica,'Microsoft YaHei','宋体',sans-serif;line-height:1.5">
|
||||
<div style="border:1px solid #eee;padding:30px 20px;background-color:#fff;border-radius:3px;border-top:3px solid #4285f4;max-width:720px;margin:10px 0">
|
||||
<h2 class="rb-title" style="font-size:1.4rem;margin:0;font-weight:400">%TITLE%</h2>
|
||||
<div class="rb-content" style="margin-top:10px">%CONTETN%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="rb-footer" style="margin:0;color:#888;font-size:12px;max-width:760px">
|
||||
<div style="float:left">
|
||||
本消息由 REBUILD 系统自动发送,请不要直接回复。<br>
|
||||
<div style="background-color:#f5f5f5;margin:0;font-size:0.9rem;padding:20px;color:#333;font-family:Roboto,Helvetica,'Microsoft YaHei','宋体',sans-serif;line-height:1.5">
|
||||
<div>
|
||||
<a href="https://getrebuild.com/" target="_blank"><img src="https://getrebuild.com/img/logo.png" alt="REBUILD" style="width:134px;display:inline-block;font-size:0" /></a>
|
||||
</div>
|
||||
<div style="border:1px solid #eee;padding:30px 20px;background-color:#fff;border-radius:3px;border-top:3px solid #4285f4;max-width:720px;margin:10px 0">
|
||||
<h2 class="rb-title" style="font-size:1.3rem;margin:0;font-weight:400">%TITLE%</h2>
|
||||
<div class="rb-content" style="margin-top:10px">%CONTETN%</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="rb-footer" style="margin:0;color:#888;font-size:12px;max-width:760px">
|
||||
本消息由 REBUILD 系统自动发送,请不要直接回复。
|
||||
<br>
|
||||
<em>This email was sent to %TO% at %TIME%</em>
|
||||
</div>
|
||||
<div style="float:right">
|
||||
<a href="https://getrebuild.com/" target="_blank"><img src="https://getrebuild.com/img/logo.png" alt="REBUILD" style="width:134px;display:inline-block;margin-top:3px"/></a>
|
||||
</div>
|
||||
<div style="clear:both;font-size:0"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -17,7 +17,7 @@
|
|||
<div class="rb-content">
|
||||
<aside class="page-aside">
|
||||
<div class="rb-scroller">
|
||||
<div class="dept-tree">
|
||||
<div class="aside-tree">
|
||||
<div class="ph-item rb">
|
||||
<div class="ph-col-12 p-0">
|
||||
<div class="ph-row">
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
<div class="rb-content">
|
||||
<aside class="page-aside">
|
||||
<div class="rb-scroller">
|
||||
<div class="dept-tree">
|
||||
<div class="aside-tree">
|
||||
<div class="ph-item rb">
|
||||
<div class="ph-col-12 p-0">
|
||||
<div class="ph-row">
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<div class="rb-content">
|
||||
<aside class="page-aside">
|
||||
<div class="rb-scroller">
|
||||
<div class="dept-tree">
|
||||
<div class="aside-tree">
|
||||
<div class="ph-item rb">
|
||||
<div class="ph-col-12 p-0">
|
||||
<div class="ph-row">
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<div class="rb-content">
|
||||
<aside class="page-aside">
|
||||
<div class="rb-scroller">
|
||||
<div class="dept-tree">
|
||||
<div class="aside-tree">
|
||||
<h5 class="config-title">应用实体</h5>
|
||||
<ul class="list-unstyled">
|
||||
<li class="active"><a>所有实体</a></li>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<div class="rb-content">
|
||||
<aside class="page-aside">
|
||||
<div class="rb-scroller">
|
||||
<div class="dept-tree">
|
||||
<div class="aside-tree">
|
||||
<h5 class="config-title">应用实体</h5>
|
||||
<ul class="list-unstyled">
|
||||
<li class="active"><a>所有实体</a></li>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<div class="rb-content">
|
||||
<aside class="page-aside">
|
||||
<div class="rb-scroller">
|
||||
<div class="dept-tree">
|
||||
<div class="aside-tree">
|
||||
<h5 class="config-title">源实体</h5>
|
||||
<ul class="list-unstyled">
|
||||
<li class="active"><a>所有实体</a></li>
|
||||
|
|
|
@ -419,7 +419,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.side-wrapper .dept-tree {
|
||||
.side-wrapper .aside-tree {
|
||||
padding: 0;
|
||||
max-height: 240px;
|
||||
}
|
||||
|
|
|
@ -156,13 +156,13 @@
|
|||
margin-right: 0;
|
||||
}
|
||||
|
||||
.dept-tree li>a>.icon {
|
||||
.aside-tree li>a>.icon {
|
||||
font-size: 12px;
|
||||
color: #aaa;
|
||||
margin-left: 6px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.dept-tree li.active>a>.icon {
|
||||
.aside-tree li.active>a>.icon {
|
||||
color: #fff;
|
||||
}
|
|
@ -13,13 +13,13 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
}
|
||||
|
||||
html.dev .dev-show,
|
||||
html.admin .admin-show
|
||||
html.admin .admin-show,
|
||||
html.rbv .rbv-show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html.dev .dev-show.row,
|
||||
html.admin .admin-show.row
|
||||
html.admin .admin-show.row,
|
||||
html.rbv .rbv-show.row {
|
||||
display: flex;
|
||||
}
|
||||
|
@ -1686,11 +1686,11 @@ th.column-fixed {
|
|||
box-shadow: 0 1px 0 rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
.dept-tree {
|
||||
.aside-tree {
|
||||
padding: 25px 18px;
|
||||
}
|
||||
|
||||
.dept-tree .config-title {
|
||||
.aside-tree .config-title {
|
||||
margin-bottom: 16px;
|
||||
margin-top: 17px;
|
||||
border-bottom: 1px solid #eee;
|
||||
|
@ -1698,49 +1698,49 @@ th.column-fixed {
|
|||
color: #777;
|
||||
}
|
||||
|
||||
.dept-tree .list-unstyled {
|
||||
.aside-tree .list-unstyled {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.dept-tree .list-unstyled ul {
|
||||
.aside-tree .list-unstyled ul {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.dept-tree li {
|
||||
.aside-tree li {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.dept-tree li>a {
|
||||
.aside-tree li>a {
|
||||
display: block;
|
||||
padding: 7px 10px;
|
||||
cursor: pointer;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.dept-tree li>a.text-disabled {
|
||||
.aside-tree li>a.text-disabled {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.dept-tree li>a.text-disabled>small::after {
|
||||
.aside-tree li>a.text-disabled>small::after {
|
||||
content: '[已停用]';
|
||||
}
|
||||
|
||||
.dept-tree>ul>li>a {
|
||||
.aside-tree>ul>li>a {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.dept-tree li>a:hover {
|
||||
.aside-tree li>a:hover {
|
||||
background-color: #eee;
|
||||
border-radius: 2px
|
||||
}
|
||||
|
||||
.dept-tree li.active>a {
|
||||
.aside-tree li.active>a {
|
||||
color: #fff !important;
|
||||
background-color: #4285f4 !important;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.dept-tree li>div.action,
|
||||
.aside-tree li>div.action,
|
||||
.adv-search .dropdown-item div.action {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
|
@ -1750,7 +1750,7 @@ th.column-fixed {
|
|||
|
||||
}
|
||||
|
||||
.dept-tree li>div.action a,
|
||||
.aside-tree li>div.action a,
|
||||
.adv-search .dropdown-item div.action a {
|
||||
display: inline-block;
|
||||
height: 34px;
|
||||
|
@ -1762,20 +1762,36 @@ th.column-fixed {
|
|||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.dept-tree li>div.action a:hover {
|
||||
.aside-tree li>div.action a:hover {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.dept-tree ul>li.active:hover>div.action,
|
||||
.aside-tree ul>li.active:hover>div.action,
|
||||
.adv-search .dropdown-item:hover div.action {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dept-tree li.nodata {
|
||||
.aside-tree li.nodata {
|
||||
padding-left: 10px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.aside-tree li>span.toggle {
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
width: 12px;
|
||||
font-size: 1.45rem;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.aside-tree li>span.toggle:hover {
|
||||
color: #4285f4;
|
||||
}
|
||||
|
||||
.adv-search .dropdown-item div.action a {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
|
@ -3441,7 +3457,7 @@ a.icon-link>.zmdi {
|
|||
/* text overflow */
|
||||
|
||||
.aside-header .title,
|
||||
.dept-tree ul li a,
|
||||
.aside-tree ul li a,
|
||||
.dropdown-item,
|
||||
.modal-header .modal-title,
|
||||
.view-header .title {
|
||||
|
|
|
@ -90,7 +90,7 @@ class ConfigList extends React.Component {
|
|||
$(this.state.data).each(function () {
|
||||
ues[this[1]] = this[2]
|
||||
})
|
||||
const dest = $('.dept-tree ul')
|
||||
const dest = $('.aside-tree ul')
|
||||
for (let k in ues) {
|
||||
$(`<li data-entity="${k}"><a class="text-truncate">${ues[k]}</a></li>`).appendTo(dest)
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ See LICENSE and COMMERCIAL in the project root for license information.
|
|||
|
||||
var loadDeptTree = function () {
|
||||
$.get('/admin/bizuser/dept-tree', function (res) {
|
||||
$('.dept-tree').empty()
|
||||
let root = $('<ul class="list-unstyled"></ul>').appendTo('.dept-tree')
|
||||
$('.aside-tree').empty()
|
||||
let root = $('<ul class="list-unstyled"></ul>').appendTo('.aside-tree')
|
||||
renderDeptTree({ id: '$ALL$', name: '所有部门' }, root).addClass('active')
|
||||
$(res.data).each(function () {
|
||||
renderDeptTree(this, root)
|
||||
|
@ -20,7 +20,7 @@ var loadDeptTree = function () {
|
|||
const renderDeptTree = function (dept, target) {
|
||||
let child = $(`<li data-id="${dept.id}"><a href="#dept=${dept.id}" class="text-truncate ${dept.disabled && ' text-disabled'}">${dept.name} ${dept.disabled ? '<small></small>' : ''}</a></li>`).appendTo(target)
|
||||
child.find('a').click(function () {
|
||||
$('.dept-tree li').removeClass('active')
|
||||
$('.aside-tree li').removeClass('active')
|
||||
child.addClass('active')
|
||||
|
||||
let ids = [child.data('id')]
|
||||
|
|
|
@ -73,11 +73,11 @@ const clickPriv = function (elements, action) {
|
|||
}
|
||||
const loadRoles = function () {
|
||||
$.get('/admin/bizuser/role-list', function (res) {
|
||||
$('.dept-tree .ph-item').remove()
|
||||
$('.dept-tree ul').empty()
|
||||
$('.aside-tree .ph-item').remove()
|
||||
$('.aside-tree ul').empty()
|
||||
$(res.data).each(function () {
|
||||
let _id = this.id
|
||||
let item = $('<li><a class="text-truncate' + (this.disabled ? ' text-disabled' : '') + '" href="' + rb.baseUrl + '/admin/bizuser/role/' + _id + '">' + this.name + (this.disabled ? '<small></small>' : '') + '</a></li>').appendTo('.dept-tree ul')
|
||||
let item = $('<li><a class="text-truncate' + (this.disabled ? ' text-disabled' : '') + '" href="' + rb.baseUrl + '/admin/bizuser/role/' + _id + '">' + this.name + (this.disabled ? '<small></small>' : '') + '</a></li>').appendTo('.aside-tree ul')
|
||||
let action = $('<div class="action"><a class="J_edit"><i class="zmdi zmdi-edit"></i></a><a class="J_del"><i class="zmdi zmdi-delete"></i></a></div>').appendTo(item)
|
||||
if (role_id === this.id) item.addClass('active')
|
||||
if (this.id === '003-0000000000000001') action.remove()
|
||||
|
|
|
@ -86,8 +86,8 @@ $(document).ready(function () {
|
|||
if (gs) $('.search-input-gs, .J_search-key').val($decode(gs))
|
||||
|
||||
renderRbcomp(<RbFeeds />, 'rb-feeds', function () { rbFeeds = this })
|
||||
renderRbcomp(<GroupList hasAction={true} />, $('#collapseGroup .dept-tree'), function () { rbGroupList = this })
|
||||
renderRbcomp(<UserList />, $('#collapseUser .dept-tree'), function () { rbUserList = this })
|
||||
renderRbcomp(<GroupList hasAction={true} />, $('#collapseGroup .aside-tree'), function () { rbGroupList = this })
|
||||
renderRbcomp(<UserList />, $('#collapseUser .aside-tree'), function () { rbUserList = this })
|
||||
|
||||
let rbGroupListLoaded = false,
|
||||
rbUserListLoaded = false
|
||||
|
|
|
@ -15,7 +15,7 @@ class EntityTree extends React.Component {
|
|||
state = { activeItem: 1, ...this.props }
|
||||
|
||||
render() {
|
||||
return <div className="dept-tree p-0">
|
||||
return <div className="aside-tree p-0">
|
||||
<ul className="list-unstyled">
|
||||
{(this.state.list || []).map((item) => {
|
||||
return <li key={`entity-${item.id}`} className={this.state.activeItem === item.id ? 'active' : ''}>
|
||||
|
|
|
@ -224,7 +224,7 @@ class FolderTree extends React.Component {
|
|||
state = { activeItem: __DEFAULT_ALL, ...this.props }
|
||||
|
||||
render() {
|
||||
return <div className="dept-tree p-0">
|
||||
return <div className="aside-tree p-0">
|
||||
<ul className="list-unstyled">
|
||||
{(this.state.list || []).map((item) => { return this._renderItem(item) })}
|
||||
</ul>
|
||||
|
|
|
@ -28,7 +28,7 @@ window.__PageConfig = {
|
|||
}
|
||||
</script>
|
||||
<script type="text/babel">
|
||||
__RESIZE_CALLS = null // No need
|
||||
window.__ONRESIZE_CALLS = []
|
||||
$(document).ready(function() {
|
||||
const ph = (parent && parent.RbViewModal) ? parent.RbViewModal.holder(window.__PageConfig.id) : null
|
||||
if (ph) $('.J_close').click(() => ph.hide())
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
</div>
|
||||
<div class="collapse" id="collapseFeedsType">
|
||||
<div class="card-body">
|
||||
<div class="dept-tree rb-scroller">
|
||||
<div class="aside-tree rb-scroller">
|
||||
<ul class="list-unstyled">
|
||||
<li data-type="1"><a>动态</a></li>
|
||||
<li data-type="2"><a>跟进</a></li>
|
||||
|
@ -81,7 +81,7 @@
|
|||
<div class="collapse" id="collapseGroup">
|
||||
<div class="card-body">
|
||||
<div class="search-member"><input type="text" placeholder="搜索团队" /></div>
|
||||
<div class="dept-tree rb-scroller">
|
||||
<div class="aside-tree rb-scroller">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -93,7 +93,7 @@
|
|||
<div class="collapse" id="collapseUser">
|
||||
<div class="card-body pb-3">
|
||||
<div class="search-member"><input type="text" placeholder="搜索用户" /></div>
|
||||
<div class="dept-tree rb-scroller">
|
||||
<div class="aside-tree rb-scroller">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<%@ page import="com.rebuild.server.Application"%>
|
||||
<%@ page import="com.rebuild.server.ServerStatus"%>
|
||||
<%@ page import="com.rebuild.server.ServerStatus.Status"%>
|
||||
<%@ page import="java.util.Map" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
@ -90,6 +91,14 @@
|
|||
<th>Temp Directory</th>
|
||||
<td><%=SysConfiguration.getFileOfTemp("/")%></td>
|
||||
</tr>
|
||||
<tr class="<%=request.getParameter("jvm") == null ? "hide" : ""%>">
|
||||
<th>JVM Arguments</th>
|
||||
<td>
|
||||
<div style="word-break:break-all;word-wrap:break-word;">
|
||||
<% for (Map.Entry<String, String> e : System.getenv().entrySet()) out.print(e.getKey() + "=" + e.getValue() + "<br>"); %>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue