Merge branch 'develop' into field-sign

This commit is contained in:
devezhao 2021-12-30 19:41:17 +08:00
commit d06e3a6cec
28 changed files with 526 additions and 155 deletions

View file

@ -17,8 +17,6 @@ const revHash = require('rev-hash')
const replace = require('gulp-replace')
const filter = require('gulp-filter')
// const jsObfuscator = require('gulp-javascript-obfuscator')
const BABEL_OPTIONS = {
presets: ['@babel/preset-env', '@babel/preset-react'],
plugins: ['@babel/plugin-proposal-class-properties'],
@ -33,7 +31,6 @@ function compileJs(m) {
return (
src(`${m || WEB_ROOT}/assets/js/**/*.js`)
.pipe(babel(BABEL_OPTIONS))
// .pipe(jsObfuscator({ compact: true }))
.pipe(
debug({
title: 'Compiled .js : ',

View file

@ -18,7 +18,6 @@
"gulp-clean-css": "^4.3.0",
"gulp-debug": "^4.0.0",
"gulp-filter": "^7.0.0",
"gulp-javascript-obfuscator": "^1.1.6",
"gulp-replace": "^1.1.3",
"rev-hash": "^3.0.0"
}

2
@rbv

@ -1 +1 @@
Subproject commit 124928a57816827e75c01f81e6d3cda6d59475d7
Subproject commit 85c5ae2c04a9014fbce35bf89084c30f6fe4f7c1

View file

@ -7,7 +7,7 @@
## 项目特色
REBUILD 更侧重于业务需求实现,而非基础的技术框架或项目启动模板通过 REBUILD 可以真正实现零代码快速搭建业务系统,无需编程、无需编译代码,甚至无需了解技术。
REBUILD 通过领先的业务流程引擎为你快速搭建企业管理系统。REBUILD 更侧重于业务需求实现,而非基础的技术框架或项目启动模板通过 REBUILD 可以真正实现零代码快速搭建,无需编程、无需编译代码,甚至无需了解技术。
更多详情介绍 [https://getrebuild.com/](https://getrebuild.com/)
@ -35,13 +35,13 @@ REBUILD 更侧重于业务需求实现,而非基础的技术框架或项目启
## 使用
开始使用 REBUILD 非常简单,不需要搭建复杂的运行环境,零依赖快速部署,就是那么简单!
开始使用 REBUILD 非常简单,不需要搭建复杂的运行环境,零依赖快速部署,简单!
#### 1. 使用已发布版本
_生产环境强烈推荐使用此方式 !!!_
首先 [下载](https://getrebuild.com/download) 安装包,我们同时提供 `standalone``boot` 两种安装包。`standalone` 为集成安装包,`boot` 为 SpringBoot 的 `jar` 包,两种安装包在功能上没有区别。
首先 [下载](https://getrebuild.com/download) 安装包,我们同时提供 `standalone``boot` 两种安装包。`standalone` 为集成安装包(推荐)`boot` 为 SpringBoot 的 `jar` 包,两种安装包在功能上没有区别。
下载后解压(集成安装包),双击/运行 `start-rebuild.bat``start-rebuild.sh` 启动, 打开浏览器输入 [http://127.0.0.1:18080/](http://127.0.0.1:18080/) 开始体验!
@ -89,4 +89,4 @@ REBUILD uses both open source ([GPL-3.0](LICENSE)) and [commercial](COMMERCIAL)
## 购买商业版
从 2.0 版本开始RB 将推出商业版增值功能计划。如果 REBUILD 对贵公司业务有帮助,可以考虑 [购买商业授权](https://getrebuild.com/#pricing-plans) 以支持 RB 的日常运营及发展。除了增值功能,还可以得到更好的技术支持服务。非常感谢!
从 2.0 版本开始RB 将推出商业版增值功能计划。如果 REBUILD 对贵公司业务有帮助,请考虑 [购买商业授权](https://getrebuild.com/#pricing-plans) 支持 RB 可持续发展。除了增值功能,还可以得到更好的技术支持服务。非常感谢!

14
pom.xml
View file

@ -10,7 +10,7 @@
</parent>
<groupId>com.rebuild</groupId>
<artifactId>rebuild</artifactId>
<version>2.7.0-beta1</version>
<version>2.8.0-dev</version>
<name>rebuild</name>
<description>RB V2 use SpringBoot</description>
<!-- UNCOMMENT USE TOMCAT -->
@ -317,7 +317,7 @@
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>7.9.0</version>
<version>7.9.1</version>
</dependency>
<dependency>
<groupId>com.github.whvcse</groupId>
@ -359,6 +359,11 @@
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
@ -370,11 +375,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>

View file

@ -64,11 +64,11 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
/**
* Rebuild Version
*/
public static final String VER = "2.7.0-beta1";
public static final String VER = "2.8.0-dev";
/**
* Rebuild Build [MAJOR]{1}[MINOR]{2}[PATCH]{2}[BUILD]{2}
*/
public static final int BUILD = 2070001;
public static final int BUILD = 2080001;
static {
// Driver for DB
@ -135,7 +135,20 @@ public class Application implements ApplicationListener<ApplicationStartedEvent>
" Local : " + localUrl,
" External : " + localUrl.replace("localhost", OshiUtils.getLocalIp()),
" Public : " + RebuildConfiguration.getHomeUrl());
log.info(banner);
if (License.isCommercial()) {
System.out.println(banner);
} else {
System.out.print(banner);
String thanks = RebuildBanner.formatSimple(
"**********",
"感谢使用 REBUILD",
"您当前使用的是免费版本,如果 REBUILD 对贵公司业务有帮助,请考虑购买商业授权版本,帮助我们可持续发展!",
"查看详情 https://getrebuild.com/#pricing-plans",
"**********");
System.out.println(thanks);
}
}
}, 1500);
}

View file

@ -20,10 +20,12 @@ import com.rebuild.core.Application;
import com.rebuild.core.UserContextHolder;
import com.rebuild.core.metadata.EntityHelper;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.metadata.MetadataSorter;
import com.rebuild.core.metadata.easymeta.DisplayType;
import com.rebuild.core.metadata.easymeta.EasyEntity;
import com.rebuild.core.metadata.easymeta.EasyMetaFactory;
import com.rebuild.core.support.License;
import com.rebuild.core.support.NeedRbvException;
import com.rebuild.core.support.i18n.Language;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
@ -66,6 +68,10 @@ public class Entity2Schema extends Field2Schema {
* @return returns 实体名称
*/
public String createEntity(String entityName, String entityLabel, String comments, String mainEntity, boolean haveNameField) {
if (License.isCommercial() && MetadataHelper.getEntities().length > 100) {
throw new NeedRbvException("实体数量超出免费版限制");
}
if (entityName != null) {
if (MetadataHelper.containsEntity(entityName)) {
throw new MetadataModificationException(Language.L("实体已存在 : %s", entityName));
@ -92,9 +98,6 @@ public class Entity2Schema extends Field2Schema {
"select min(typeCode) from MetaEntity").unique();
int typeCode = maxTypeCode == null || ObjectUtils.toInt(maxTypeCode[0]) == 0
? 999 : (ObjectUtils.toInt(maxTypeCode[0]) - 1);
if (typeCode <= (License.isCommercial() ? 399 : 949)) {
throw new MetadataModificationException("ENTITY CODE EXCEEDS SYSTEM LIMIT : " + typeCode);
}
// 名称字段
String nameFiled = EntityHelper.CreatedOn;

View file

@ -27,6 +27,8 @@ import com.rebuild.core.metadata.easymeta.DisplayType;
import com.rebuild.core.metadata.easymeta.EasyField;
import com.rebuild.core.metadata.easymeta.EasyMetaFactory;
import com.rebuild.core.privileges.UserHelper;
import com.rebuild.core.support.License;
import com.rebuild.core.support.NeedRbvException;
import com.rebuild.core.support.SetUser;
import com.rebuild.core.support.i18n.Language;
import com.rebuild.core.support.setup.Installer;
@ -79,9 +81,20 @@ public class Field2Schema extends SetUser {
* @return
*/
public String createField(Entity entity, String fieldLabel, DisplayType type, String comments, String refEntity, JSON extConfig) {
long count;
if ((count = checkRecordCount(entity)) > 100000) {
throw new MetadataModificationException(Language.L("实体记录过多 (%d),增加/删除字段可能导致表损坏", count));
if (!License.isCommercial()) {
if (entity.getFields().length >= 50) {
throw new NeedRbvException("字段数量超出免费版限制");
}
if (type == DisplayType.LOCATION) {
Object[] limit = Application.createQueryNoFilter(
"select count(fieldId) from MetaField where displayType = ?")
.setParameter(1, type.name())
.unique();
if (ObjectUtils.toInt(limit[0]) >= 1) {
throw new NeedRbvException("位置字段超出免费版限制");
}
}
}
String fieldName = toPinyinName(fieldLabel);

View file

@ -43,8 +43,10 @@ public enum ConfigurationItem {
// 开放注册
OpenSignUp(true),
// 登录背景图
// 动态登录背景图
LiveWallpaper(true),
// 自定登录背景图
CustomWallpaper,
// 启用文件分享
FileSharable(true),
@ -82,6 +84,11 @@ public enum ConfigurationItem {
// 登录密码过期时间0为不过期
PasswordExpiredDays(0),
// 允许使用时间
AllowUsesTime,
// 允许使用 IP
AllowUsesIp,
// DingTalk
DingtalkAgentid, DingtalkAppkey, DingtalkAppsecret, DingtalkCorpid,
DingtalkPushAeskey, DingtalkPushToken,

View file

@ -0,0 +1,22 @@
/*
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.
*/
package com.rebuild.core.support;
import com.rebuild.core.DefinedException;
/**
* @author devezhao
* @since 2021/12/30
*/
public class NeedRbvException extends DefinedException {
private static final long serialVersionUID = -5539922471794653867L;
public NeedRbvException(String msg) {
super(msg);
}
}

View file

@ -9,6 +9,7 @@ package com.rebuild.utils;
import cn.devezhao.commons.ObjectUtils;
import com.rebuild.core.Application;
import com.rebuild.core.RebuildException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
@ -16,6 +17,7 @@ import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
@ -166,4 +168,28 @@ public class CommonsUtils {
}
return false;
}
/**
* @param desc
* @param args
* @return
*/
public static Object invokeMethod(String desc, Object... args) {
String[] classAndMethod = desc.split("#");
try {
Class<?> clazz = Class.forName(classAndMethod[0]);
Class<?>[] paramTypes = new Class<?>[args.length];
for (int i = 0; i < args.length; i++) {
paramTypes[i] = args[i].getClass();
}
Method method = clazz.getMethod(classAndMethod[1], paramTypes);
return method.invoke(null, args);
} catch (ReflectiveOperationException ex) {
log.error("Invalid method invoke : {}", desc);
throw new RebuildException(ex);
}
}
}

View file

@ -49,7 +49,7 @@ public class RebuildBanner {
* @return
*/
public static String formatSimple(String... texts) {
StringBuilder banner = new StringBuilder("\n\n");
StringBuilder banner = new StringBuilder("\n");
for (String t : texts) {
banner.append(" ").append(t).append("\n");
}

View file

@ -9,7 +9,7 @@ package com.rebuild.web;
import cn.devezhao.commons.ThrowableUtils;
import cn.devezhao.commons.web.ServletUtils;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter4;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.alibaba.fastjson.support.spring.FastJsonJsonView;
import com.rebuild.core.Application;
import com.rebuild.core.DefinedException;
@ -92,7 +92,8 @@ public class RebuildWebConfigurer implements WebMvcConfigurer, ErrorViewResolver
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new FastJsonHttpMessageConverter4());
// converters.add(0, new FastJsonHttpMessageConverter4());
converters.add(0, new FastJsonHttpMessageConverter());
}
@Override

View file

@ -7,6 +7,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
package com.rebuild.web;
import cn.devezhao.commons.CalendarUtils;
import cn.devezhao.commons.CodecUtils;
import cn.devezhao.commons.web.ServletUtils;
import cn.devezhao.persist4j.engine.ID;
@ -16,15 +17,20 @@ import com.rebuild.core.DefinedException;
import com.rebuild.core.ServerStatus;
import com.rebuild.core.UserContextHolder;
import com.rebuild.core.cache.CommonsCache;
import com.rebuild.core.privileges.UserHelper;
import com.rebuild.core.privileges.bizz.ZeroEntry;
import com.rebuild.core.support.ConfigurationItem;
import com.rebuild.core.support.CsrfToken;
import com.rebuild.core.support.License;
import com.rebuild.core.support.RebuildConfiguration;
import com.rebuild.core.support.i18n.Language;
import com.rebuild.core.support.setup.InstallState;
import com.rebuild.utils.AppUtils;
import com.rebuild.utils.CommonsUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.core.NamedThreadLocal;
import org.springframework.http.HttpStatus;
import org.springframework.util.MimeType;
@ -50,16 +56,20 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt
private static final ThreadLocal<RequestEntry> REQUEST_ENTRY = new NamedThreadLocal<>("RequestEntry");
private static final int CODE_STARTING = 600;
private static final int CODE_NOT_ALLOW_USE = 610;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
response.addHeader("X-RB-Server", ServerStatus.STARTUP_ONCE + "/" + Application.BUILD);
if (Application.isWaitLoad()) {
throw new DefinedException(600, "Please wait while REBUILD starting up ...");
throw new DefinedException(CODE_STARTING, "Please wait while REBUILD starting up ...");
}
UserContextHolder.setReqip(ServletUtils.getRemoteAddr(request));
final String ipAddr = ServletUtils.getRemoteAddr(request);
UserContextHolder.setReqip(ipAddr);
// Locale
final String locale = detectLocale(request, response);
@ -100,11 +110,14 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt
final ID requestUser = requestEntry.getRequestUser();
boolean skipCheckSafeUse;
// 用户验证
if (requestUser != null) {
boolean adminVerified = AppUtils.isAdminVerified(request);
// 管理中心
if (requestUri.contains("/admin/") && !AppUtils.isAdminVerified(request)) {
if (requestUri.contains("/admin/") && !adminVerified) {
if (isHtmlRequest(request)) {
sendRedirect(response, "/user/admin-verify", requestUri);
} else {
@ -124,17 +137,20 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt
// Last active
Application.getSessionStore().storeLastActive(request);
// Side collapsed
// Nav collapsed
String sidebarCollapsed = ServletUtils.readCookie(request, "rb.sidebarCollapsed");
String sideCollapsedClazz = "false".equals(sidebarCollapsed) ? "" : "rb-collapsible-sidebar-collapsed";
// Aside
String sideCollapsedClazz = BooleanUtils.toBoolean(sidebarCollapsed) ? "rb-collapsible-sidebar-collapsed" : "";
// Aside collapsed
if (!(requestEntry.getRequestUri().contains("/admin/") || requestEntry.getRequestUri().contains("/setup/"))) {
String asideCollapsed = ServletUtils.readCookie(request, "rb.asideCollapsed");
if (!"false".equals(asideCollapsed)) sideCollapsedClazz += " rb-aside-collapsed";
if (BooleanUtils.toBoolean(asideCollapsed)) sideCollapsedClazz += " rb-aside-collapsed";
}
request.setAttribute("sideCollapsedClazz", sideCollapsedClazz);
}
// 超管设置仍可访问
skipCheckSafeUse = adminVerified || UserHelper.isSuperAdmin(requestUser);
} else if (!isIgnoreAuth(requestUri)) {
// 外部表单特殊处理媒体字段上传/预览
if (requestUri.contains("/filex/") && CsrfToken.verify(request, false)) {
@ -150,8 +166,12 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt
}
return false;
} else {
skipCheckSafeUse = true;
}
if (!skipCheckSafeUse) checkSafeUse(ipAddr);
return true;
}
@ -175,14 +195,6 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt
UserContextHolder.clear();
}
/**
* 语言探测
*
* @param request
* @param response
* @return
* @see AppUtils#getReuqestLocale(HttpServletRequest)
*/
private String detectLocale(HttpServletRequest request, HttpServletResponse response) {
String rbmobLocale = request.getHeader(AppUtils.HF_LOCALE);
if (rbmobLocale != null) return rbmobLocale;
@ -222,12 +234,6 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt
return havingLocale;
}
/**
* 忽略认证的资源
*
* @param requestUri
* @return
*/
private boolean isIgnoreAuth(String requestUri) {
if (requestUri.contains("/user/") && !requestUri.contains("/user/admin")) {
return true;
@ -253,12 +259,6 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt
|| requestUri.startsWith("/rbmob/env");
}
/**
* 是否 HTML 请求
*
* @param request
* @return
*/
private boolean isHtmlRequest(HttpServletRequest request) {
String requestUri = request.getRequestURI();
if (ServletUtils.isAjaxRequest(request)
@ -280,21 +280,33 @@ public class RebuildWebInterceptor implements AsyncHandlerInterceptor, InstallSt
}
}
/**
* @param response
* @param url
* @param nexturl
* @throws IOException
*/
private void sendRedirect(HttpServletResponse response, String url, String nexturl) throws IOException {
String fullUrl = AppUtils.getContextPath(url);
if (nexturl != null) fullUrl += "?nexturl=" + CodecUtils.urlEncode(nexturl);
response.sendRedirect(fullUrl);
}
/**
* 请求参数封装
*/
private void checkSafeUse(String ipAddr) throws DefinedException {
if (!License.isRbvAttached()) return;
if (ipAddr.equals("localhost") || ipAddr.equals("127.0.0.1")) {
log.warn("Allow localhost uses ");
return;
}
Object allowIp = CommonsUtils.invokeMethod(
"com.rebuild.rbv.commons.SafeUses#checkIp", ipAddr);
if (!(Boolean) allowIp) {
throw new DefinedException(CODE_NOT_ALLOW_USE, Language.L("你的 IP 地址不在允许范围内"));
}
Object allowTime = CommonsUtils.invokeMethod(
"com.rebuild.rbv.commons.SafeUses#checkTime", CalendarUtils.now());
if (!(Boolean) allowTime) {
throw new DefinedException(CODE_NOT_ALLOW_USE, Language.L("当前时间不允许使用"));
}
}
@Data
private static class RequestEntry {
final long requestTime;

View file

@ -54,6 +54,9 @@ import java.util.Map;
@RequestMapping("/admin/")
public class ConfigurationController extends BaseController {
public static final String ETAG_DIMGLOGOTIME = "dimgLogoTime";
public static final String ETAG_DIMGBGIMGTIME = "dimgBgimgTime";
@GetMapping("systems")
public ModelAndView pageSystems() {
ModelAndView mv = createModelAndView("/admin/system-cfg");
@ -93,11 +96,14 @@ public class ConfigurationController extends BaseController {
}
}
String dLOGO = data.getString("LOGO");
String dLOGOWhite = data.getString("LOGOWhite");
String dLOGO = data.getString(ConfigurationItem.LOGO.name());
String dLOGOWhite = data.getString(ConfigurationItem.LOGOWhite.name());
if (dLOGO != null || dLOGOWhite != null) {
// @see UseThemeController#useLogo
Application.getCommonsCache().evict("dimgLogoTime");
Application.getCommonsCache().evict(ETAG_DIMGLOGOTIME);
}
String dCustomWallpaper = data.getString(ConfigurationItem.CustomWallpaper.name());
if (dCustomWallpaper != null) {
Application.getCommonsCache().evict(ETAG_DIMGBGIMGTIME);
}
setValues(data);

View file

@ -24,7 +24,6 @@ import com.rebuild.web.BaseController;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@ -63,7 +62,9 @@ public class FileDownloader extends BaseController {
return;
}
final boolean temp = BooleanUtils.toBoolean(request.getParameter("temp"));
final boolean temp = getBoolParameter(request, "temp");
final boolean local = temp || getBoolParameter(request, "local"); // 强制本地
String imageView2 = request.getQueryString();
if (imageView2 != null && imageView2.contains("imageView2/")) {
imageView2 = "imageView2/" + imageView2.split("imageView2/")[1].split("&")[0];
@ -73,8 +74,8 @@ public class FileDownloader extends BaseController {
ServletUtils.addCacheHead(response, 60);
// Local storage || temp
if (!QiniuCloud.instance().available() || temp) {
// Local storage || temp || local
if (!QiniuCloud.instance().available() || local) {
String fileName = QiniuCloud.parseFileName(filePath);
String mimeType = request.getServletContext().getMimeType(fileName);
if (mimeType != null) {
@ -163,7 +164,8 @@ public class FileDownloader extends BaseController {
filePath = filePath.split("/filex/download/")[1];
}
boolean temp = getBoolParameter(request, "temp");
final boolean temp = getBoolParameter(request, "temp");
String attname = getParameter(request, "attname");
if (StringUtils.isBlank(attname)) attname = QiniuCloud.parseFileName(filePath);

View file

@ -35,7 +35,6 @@ import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@ -229,7 +228,7 @@ public class LoginController extends BaseController {
// Tour 显示规则
Object[] initLoginTimes = Application.createQueryNoFilter(
"select count(loginTime) from LoginLog where user = ? and loginTime > '2021-12-01'")
"select count(loginTime) from LoginLog where user = ? and loginTime > '2022-01-01'")
.setParameter(1, user)
.unique();
if (ObjectUtils.toLong(initLoginTimes[0]) <= 10

View file

@ -10,6 +10,7 @@
CREATE DATABASE rebuild20 COLLATE utf8mb4_general_ci;
CREATE USER 'rebuild'@'127.0.0.1' IDENTIFIED BY 'rebuild';
GRANT ALL PRIVILEGES ON rebuild20.* TO 'rebuild'@'127.0.0.1';
GRANT RELOAD ON *.* TO 'rebuild'@'127.0.0.1';
FLUSH PRIVILEGES;
USE rebuild20;
*/

View file

@ -3,17 +3,48 @@
<head>
<th:block th:replace="~{/_include/header}" />
<title>[[${bundle.L('通用配置')}]]</title>
<style type="text/css">
<style>
.syscfg a.img-thumbnail {
display: inline-block;
padding: 0.4rem 0.5rem;
background-color: #fff;
cursor: default;
position: relative;
}
.applogo.edit a.img-thumbnail,
.applogo.edit a.img-thumbnail .logo-img {
.syscfg.edit a.img-thumbnail {
cursor: pointer;
}
.syscfg a.img-thumbnail b {
position: absolute;
background: rgba(0, 0, 0, 0.4);
width: 24px;
height: 24px;
top: 2px;
right: 2px;
border-radius: 2px;
cursor: pointer;
display: none;
font-size: 1.4rem;
color: #fff;
text-align: center;
overflow: hidden;
}
.syscfg.edit a.img-thumbnail:hover b {
display: inline-block;
}
.bgimg-img {
display: inline-block;
width: 192px;
height: 108px;
background: #eee url(../assets/img/bg.jpg) repeat 0 0;
background-size: cover;
}
</style>
<style th:if="${commercial > 1}">
.bgimg-img {
background-image: url(../commons/theme/use-bgimg);
}
</style>
</head>
<body>
@ -40,10 +71,16 @@
<tr>
<td>LOGO <sup class="rbv"></sup></td>
<td class="fs-0 applogo">
<a class="img-thumbnail"><i class="logo-img"></i></a>
<a class="img-thumbnail bg-primary ml-1"><i class="logo-img white"></i></a>
<a class="img-thumbnail" data-id="LOGO">
<i class="logo-img"></i>
<b th:title="${bundle.L('还原')}"><span class="zmdi zmdi-replay"></span></b>
</a>
<a class="img-thumbnail bg-primary ml-1" data-id="LOGOWhite">
<i class="logo-img white"></i>
<b th:title="${bundle.L('还原')}"><span class="zmdi zmdi-replay"></span></b>
</a>
<input type="file" class="hide" accept="image/*" data-maxsize="5000000" data-local="true" />
<p class="mt-2 text-dark hide">[[${bundle.L('请分别上传深色与白色 LOGO透明背景宽高为 268 × 54')}]]</p>
<p class="mt-2 text-dark hide">[[${bundle.L('请分别上传深色与白色 LOGO透明背景建议尺寸 268 × 54')}]]</p>
</td>
</tr>
<tr>
@ -53,6 +90,10 @@
</td>
<td data-id="HomeURL" th:data-value="${HomeURL}">[[${HomeURL}]]</td>
</tr>
<tr>
<td>[[${bundle.L('默认语言')}]]</td>
<td data-id="DefaultLanguage" th:data-value="${DefaultLanguage}" id="_DefaultLanguage">[[${DefaultLanguage}]]</td>
</tr>
<tr>
<td>
[[${bundle.L('页脚')}]]
@ -61,14 +102,33 @@
<td data-id="PageFooter" th:data-value="${PageFooter}" data-optional="true"><pre class="unstyle">[[${PageFooter ?:bundle.L('无')}]]</pre></td>
</tr>
<tr>
<td>[[${bundle.L('默认语言')}]]</td>
<td data-id="DefaultLanguage" th:data-value="${DefaultLanguage}" id="_DefaultLanguage">[[${DefaultLanguage}]]</td>
<td>[[${bundle.L('登录页每日一图')}]]</td>
<td data-id="LiveWallpaper" th:data-value="${LiveWallpaper}">[[${LiveWallpaper ? bundle.L('是') : bundle.L('否')}]]</td>
</tr>
<tr>
<td>[[${bundle.L('自定义登录页图')}]] <sup class="rbv"></sup></td>
<td class="fs-0 bgimg">
<a class="img-thumbnail p-0 border-0" data-id="CustomWallpaper">
<i class="bgimg-img"></i>
<b th:title="${bundle.L('还原')}"><span class="zmdi zmdi-replay"></span></b>
</a>
<input type="file" class="hide" accept="image/*" data-maxsize="5000000" data-local="true" />
<p class="mt-2 text-dark hide">[[${bundle.L('建议尺寸 1920 × 1080')}]]</p>
</td>
</tr>
</tbody>
</table>
<h5>[[${bundle.L('系统选项')}]]</h5>
<h5>[[${bundle.L('安全使用')}]]</h5>
<table class="table">
<tbody>
<tr>
<td>[[${bundle.L('显示页面水印')}]]</td>
<td data-id="MarkWatermark" th:data-value="${MarkWatermark}">[[${MarkWatermark ? bundle.L('是') : bundle.L('否')}]]</td>
</tr>
<tr>
<td>[[${bundle.L('允许分享文件')}]]</td>
<td data-id="FileSharable" th:data-value="${FileSharable}">[[${FileSharable ? bundle.L('是') : bundle.L('否')}]]</td>
</tr>
<tr>
<td width="40%">[[${bundle.L('公开注册')}]]</td>
<td data-id="OpenSignUp" th:data-value="${OpenSignUp}">[[${OpenSignUp ? bundle.L('是') : bundle.L('否')}]]</td>
@ -100,20 +160,16 @@
<td th:data-id="${commercial > 0 ? 'MultipleSessions' : ''}" th:data-value="${MultipleSessions}">[[${MultipleSessions ? bundle.L('是') : bundle.L('否')}]]</td>
</tr>
<tr>
<td>[[${bundle.L('登录页每日一图')}]]</td>
<td data-id="LiveWallpaper" th:data-value="${LiveWallpaper}">[[${LiveWallpaper ? bundle.L('是') : bundle.L('否')}]]</td>
<td>[[${bundle.L('允许使用时间')}]] <sup class="rbv"></sup></td>
<td th:data-id="${commercial > 1 ? 'AllowUsesTime' : ''}" th:data-value="${AllowUsesTime}" data-optional="true">
<pre class="unstyle">[[${AllowUsesTime ?:bundle.L('不限')}]]</pre>
</td>
</tr>
<tr>
<td>[[${bundle.L('显示页面水印')}]]</td>
<td data-id="MarkWatermark" th:data-value="${MarkWatermark}">[[${MarkWatermark ? bundle.L('是') : bundle.L('否')}]]</td>
</tr>
<tr>
<td>[[${bundle.L('允许分享文件')}]]</td>
<td data-id="FileSharable" th:data-value="${FileSharable}">[[${FileSharable ? bundle.L('是') : bundle.L('否')}]]</td>
</tr>
<tr>
<td>[[${bundle.L('在视图页显示修改历史')}]]</td>
<td data-id="ShowViewHistory" th:data-value="${ShowViewHistory}">[[${ShowViewHistory ? bundle.L('是') : bundle.L('否')}]]</td>
<td>[[${bundle.L('允许使用 IP')}]] <sup class="rbv"></sup></td>
<td th:data-id="${commercial > 1 ? 'AllowUsesIp' : ''}" th:data-value="${AllowUsesIp}" data-optional="true">
<pre class="unstyle">[[${AllowUsesIp ?:bundle.L('不限')}]]</pre>
</td>
</tr>
</tbody>
</table>
@ -141,6 +197,16 @@
</tr>
</tbody>
</table>
<h5>[[${bundle.L('其他')}]]</h5>
<table class="table">
<tbody>
<tr></tr>
<tr>
<td width="40%">[[${bundle.L('在视图页显示修改历史')}]]</td>
<td data-id="ShowViewHistory" th:data-value="${ShowViewHistory}">[[${ShowViewHistory ? bundle.L('是') : bundle.L('否')}]]</td>
</tr>
</tbody>
</table>
<div class="edit-footer">
<button class="btn btn-link">[[${bundle.L('取消')}]]</button>
<button class="btn btn-primary">[[${bundle.L('保存')}]]</button>

View file

@ -109,8 +109,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
html,
body {
font-family: Roboto, 'Hiragina Sans GB', 'San Francisco', 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'Noto Sans SC', 'Microsoft YaHei UI',
'Microsoft YaHei', sans-serif;
font-family: Roboto, 'Hiragina Sans GB', 'San Francisco', 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'Noto Sans SC', 'Microsoft YaHei UI', 'Microsoft YaHei', sans-serif;
}
html {
@ -4020,9 +4019,8 @@ input[type='submit'].btn-block {
line-height: 1.428571;
color: #404040;
vertical-align: middle;
background: #fff
url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%233d3c3c' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E")
no-repeat right 0.75rem center;
background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%233d3c3c' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat
right 0.75rem center;
background-size: 8px 10px;
border: 1px solid #d5d8de;
border-radius: 2px;
@ -5637,16 +5635,7 @@ input[type='submit'].btn-block {
}
.progress-bar-striped {
background-image: linear-gradient(
45deg,
rgba(255, 255, 255, 0.15) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, 0.15) 50%,
rgba(255, 255, 255, 0.15) 75%,
transparent 75%,
transparent
);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-size: 3.077rem 3.077rem;
}
@ -6124,8 +6113,7 @@ button.close {
z-index: 1070;
display: block;
margin: 0;
font-family: Roboto, 'Hiragina Sans GB', San Francisco, 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'WenQuanYi Micro Hei', 'Microsoft YaHei UI',
'Microsoft YaHei', sans-serif;
font-family: Roboto, 'Hiragina Sans GB', San Francisco, 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'WenQuanYi Micro Hei', 'Microsoft YaHei UI', 'Microsoft YaHei', sans-serif;
font-style: normal;
font-weight: 400;
line-height: 1.428571;
@ -6253,8 +6241,7 @@ button.close {
z-index: 1060;
display: block;
max-width: 276px;
font-family: Roboto, 'Hiragina Sans GB', 'San Francisco', 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'Noto Sans SC', 'Microsoft YaHei UI',
'Microsoft YaHei', sans-serif;
font-family: Roboto, 'Hiragina Sans GB', 'San Francisco', 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'Noto Sans SC', 'Microsoft YaHei UI', 'Microsoft YaHei', sans-serif;
font-style: normal;
font-weight: 400;
line-height: 1.428571;
@ -12633,7 +12620,7 @@ a.avatar.x48 img {
padding-left: 55px;
}
.rb-collapsible-sidebar-collapsed .rb-left-sidebar .sidebar-elements > li ul.visible .nav-items .content > ul > li > ul > li > ul> li > ul > li > ul > li> a {
.rb-collapsible-sidebar-collapsed .rb-left-sidebar .sidebar-elements > li ul.visible .nav-items .content > ul > li > ul > li > ul > li > ul > li > ul > li > a {
padding-left: 65px;
}
}
@ -14313,8 +14300,7 @@ a.avatar.x48 img {
}
.rb-sub-header .navbar-nav > .nav-item > .nav-link {
font-family: Roboto, 'Hiragina Sans GB', 'San Francisco', 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'Noto Sans SC', 'Microsoft YaHei UI',
'Microsoft YaHei', sans-serif;
font-family: Roboto, 'Hiragina Sans GB', 'San Francisco', 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'Noto Sans SC', 'Microsoft YaHei UI', 'Microsoft YaHei', sans-serif;
font-size: 1.1rem;
line-height: 40px;
min-width: 100px;
@ -21181,6 +21167,109 @@ fieldset[disabled] .full-calendar .fc-button:hover {
width: 6px;
}
/* jquery.gritter.css */
#gritter-notice-wrapper {
position: fixed;
top: 20px;
right: 20px;
width: 301px;
z-index: 9999;
}
#gritter-notice-wrapper.top-left {
left: 20px;
right: auto;
}
#gritter-notice-wrapper.bottom-right {
top: auto;
left: auto;
bottom: 20px;
right: 20px;
}
#gritter-notice-wrapper.bottom-left {
top: auto;
right: auto;
bottom: 20px;
left: 20px;
}
.gritter-item-wrapper {
position: relative;
margin: 0 0 10px 0;
background: url('../images/ie-spacer.gif'); /* ie7/8 fix */
}
.gritter-top {
background: url(../images/gritter.png) no-repeat left -30px;
height: 10px;
}
.hover .gritter-top {
background-position: right -30px;
}
.gritter-bottom {
background: url(../images/gritter.png) no-repeat left bottom;
height: 8px;
margin: 0;
}
.hover .gritter-bottom {
background-position: bottom right;
}
.gritter-item {
display: block;
background: url(../images/gritter.png) no-repeat left -40px;
color: #eee;
padding: 2px 11px 8px 11px;
font-size: 11px;
font-family: verdana;
}
.hover .gritter-item {
background-position: right -40px;
}
.gritter-item p {
padding: 0;
margin: 0;
word-wrap: break-word;
}
.gritter-close {
display: none;
position: absolute;
top: 5px;
left: 3px;
background: url(../images/gritter.png) no-repeat left top;
cursor: pointer;
width: 30px;
height: 30px;
text-indent: -9999em;
}
.gritter-title {
font-size: 14px;
font-weight: bold;
padding: 0 0 7px 0;
display: block;
text-shadow: 1px 1px 0 #000; /* Not supported by IE :( */
}
.gritter-image {
width: 48px;
height: 48px;
float: left;
}
.gritter-with-image,
.gritter-without-image {
padding: 0;
}
.gritter-with-image {
width: 220px;
float: right;
}
/* for the light (white) version of the gritter notice */
.gritter-light .gritter-item,
.gritter-light .gritter-bottom,
.gritter-light .gritter-top,
.gritter-light .gritter-close {
background-image: url(../images/gritter-light.png);
color: #222;
}
.gritter-light .gritter-title {
text-shadow: none;
}
#gritter-notice-wrapper {
width: 360px;
top: 82px;
@ -21543,8 +21632,7 @@ fieldset[disabled] .full-calendar .fc-button:hover {
.select2-container--default .select2-selection--multiple .select2-search--inline .select2-search__field {
line-height: 2rem;
font-family: Roboto, Arial, sans-serif;
font-family: Roboto, 'Hiragina Sans GB', 'San Francisco', 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'Noto Sans SC', 'Microsoft YaHei UI',
'Microsoft YaHei', sans-serif;
font-family: Roboto, 'Hiragina Sans GB', 'San Francisco', 'Helvetica Neue', Helvetica, Arial, PingFangSC-Light, 'Noto Sans SC', 'Microsoft YaHei UI', 'Microsoft YaHei', sans-serif;
font-size: 1rem;
color: #999;
}
@ -21807,8 +21895,7 @@ fieldset[disabled] .full-calendar .fc-button:hover {
border: 1px dashed #bbb;
min-height: 100px;
background-color: #e5e5e5;
background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff),
linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
background-image: linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff), linear-gradient(45deg, #fff 25%, transparent 25%, transparent 75%, #fff 75%, #fff);
background-size: 60px 60px;
background-position: 0 0, 30px 30px;
}
@ -22780,15 +22867,7 @@ div.table-responsive > div.dataTables_wrapper > div.row > div[class^='col-']:las
margin-left: -250%;
-webkit-animation: phAnimation 0.8s linear infinite;
animation: phAnimation 0.8s linear infinite;
background: -webkit-gradient(
linear,
left top,
right top,
color-stop(46%, rgba(255, 255, 255, 0)),
color-stop(50%, rgba(255, 255, 255, 0.35)),
color-stop(54%, rgba(255, 255, 255, 0))
)
50% 50%;
background: -webkit-gradient(linear, left top, right top, color-stop(46%, rgba(255, 255, 255, 0)), color-stop(50%, rgba(255, 255, 255, 0.35)), color-stop(54%, rgba(255, 255, 255, 0))) 50% 50%;
background: linear-gradient(to right, rgba(255, 255, 255, 0) 46%, rgba(255, 255, 255, 0.35) 50%, rgba(255, 255, 255, 0) 54%) 50% 50%;
}

View file

@ -3019,6 +3019,7 @@ form {
top: 9px;
font-size: 1.55rem;
color: #878787;
color: rgba(0, 0, 0, 0.3);
pointer-events: none;
}
@ -3077,6 +3078,7 @@ form {
.search-container > .global-create > .dropdown.show > a {
background: #4285f4;
color: #fff;
transition: background-color 0.3s;
}
.preview-modal {
@ -4328,4 +4330,23 @@ pre.unstyle {
.bg-market {
background-image: linear-gradient(135deg, #2973d7 0%, #26acb9 100%);
}
}
#gritter-notice-wrapper {
position: fixed;
right: 20px;
z-index: 1099;
}
.gritter-item-wrapper .gritter-image > .icon {
font-size: 3rem;
}
.gritter-item-wrapper.color .gritter-item .gritter-img-container {
background-color: rgba(0, 0, 0, 0.1);
}
.gritter-item-wrapper.faster {
-webkit-animation-duration: 200ms;
animation-duration: 200ms;
}

View file

@ -1,10 +1,10 @@
/* eslint-disable no-undef */
/*
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.
*/
/* eslint-disable no-undef, react/display-name */
const wpc = window.__PageConfig
@ -31,7 +31,12 @@ useEditComp = function (name) {
)
} else if ('DefaultLanguage' === name) {
// 借用贵宝地
if (rb.commercial >= 10) _toggleLogo()
if (rb.commercial >= 10) {
_toggleImage('.applogo')
_toggleImage('.bgimg')
} else {
$('.applogo b, .bgimg b').remove()
}
const options = []
for (let k in wpc._LANGS) {
@ -49,24 +54,34 @@ useEditComp = function (name) {
<option value="2">{$L('总是显示')}</option>
</select>
)
} else if ('PageFooter' === name) {
} else if ('PageFooter' === name || 'AllowUsesTime' === name || 'AllowUsesIp' === name) {
return <textarea name={name} className="form-control form-control-sm row3x" maxLength="600" />
}
}
const _toggleLogo = function () {
const $logo = $('.applogo').addClass('edit')
$logo.find('p').removeClass('hide')
const _toggleImage = function (el) {
const $img = $(el).addClass('edit')
$img.find('p').removeClass('hide')
let $current
const $input = $logo.find('input')
const $input = $img.find('input')
$initUploader($input, null, (res) => {
const $img = $current.find('i').css('background-image', `url(${rb.baseUrl}/filex/img/${res.key})`)
changeValue({ target: { name: $img.hasClass('white') ? 'LOGOWhite' : 'LOGO', value: res.key } })
$current.find('>i').css('background-image', `url(${rb.baseUrl}/filex/img/${res.key}?local=true)`)
changeValue({ target: { name: $current.data('id'), value: res.key } })
})
$logo.find('a').click(function () {
$current = $(this)
$input[0].click()
$img
.find('a')
.attr('title', $L('点击上传'))
.on('click', function () {
$current = $(this)
$input[0].click()
})
$img.find('a>b').on('click', function (e) {
$stopEvent(e, true)
$current = $(this).parent()
$current.find('>i').css('background-image', `url(${rb.baseUrl}/assets/img/s.gif)`)
changeValue({ target: { name: $current.data('id'), value: '' } })
})
}

View file

@ -9,13 +9,13 @@ See LICENSE and COMMERCIAL in the project root for license information.
// 公共部分
$(document).ready(() => {
$('.card-header>a').click((e) => {
$('.card-header>a').on('click', (e) => {
$stopEvent(e, true)
enableEditMode()
})
$('.edit-footer>.btn-link').click(() => location.reload())
$('.edit-footer>.btn-primary').click(() => post(__data))
$('.edit-footer>.btn-link').on('click', () => location.reload())
$('.edit-footer>.btn-primary').on('click', () => post(__data))
if (window.ClipboardJS) {
$('a[data-clipboard-text]').each(function () {
@ -54,8 +54,8 @@ const enableEditMode = function () {
const post = function (data) {
for (let name in data) {
if (!data[name]) {
const $field = $('td[data-id=' + name + ']')
if ($field.data('optional')) continue // 可选值
const $field = $(`.syscfg td[data-id=${name}]`)
if ($field.length === 0 || $field.data('optional')) continue // 可选值
const $c = $field.prev().clone()
$c.find('p').remove()

View file

@ -125,7 +125,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
watermark_width: 200,
watermark_font: 'arial',
watermark_fontsize: '15px',
watermark_alpha: 0.06,
watermark_alpha: 0.1,
watermark_parent_width: $(window).width(),
watermark_parent_height: $(window).height(),
monitor: true,

View file

@ -974,6 +974,85 @@ UserPopup.create = function (el) {
// ~~ HTML 内容
const WrapHtml = (htmlContent) => <div dangerouslySetInnerHTML={{ __html: htmlContent }} />
class RbGritter extends React.Component {
constructor(props) {
super(props)
this.state = { ...props }
}
render() {
return (
<div id="gritter-notice-wrapper" className="gritter-main-wrapper">
{this.state.items}
</div>
)
}
_addItem(message, options) {
const itemid = `gritter-item-${$random()}`
const type = options.type || 'success'
const icon = type === 'success' ? 'check' : type === 'danger' ? 'close-circle-o' : 'info-outline'
const item = (
<div key={itemid} id={itemid} className={`gritter-item-wrapper color ${type} animated faster fadeInRight`}>
<div className="gritter-item">
<div className="gritter-img-container">
<span className="gritter-image">
<i className={`icon zmdi zmdi-${icon}`} />
</span>
</div>
<div className="gritter-content gritter-with-image">
<a
className="gritter-close"
tabIndex="1"
onClick={(e) => {
$stopEvent(e, true)
this._removeItem(itemid)
}}
/>
{options.title && <span className="gritter-title">{options.title}</span>}
<p>{message}</p>
</div>
</div>
</div>
)
const itemsNew = this.state.items || []
itemsNew.push(item)
this.setState({ items: itemsNew }, () => {
setTimeout(() => this._removeItem(itemid), options.timeout || 6000)
})
}
_removeItem(itemid) {
const itemsNew = this.state.items.filter((item) => itemid !== item.key)
console.log(itemsNew)
this.setState({ items: itemsNew })
}
// -- Usage
/**
* @param {*} message
* @param {*} options
*/
static create(message, options = {}) {
if (top !== self && parent.RbGritter) {
parent.RbGritter.create(message, options)
} else {
if (this.__$wrapper) {
this.__$wrapper._addItem(message, options)
} else {
const that = this
renderRbcomp(<RbGritter />, null, function () {
that.__$wrapper = this
that.__$wrapper._addItem(message, options)
})
}
}
}
}
/**
* JSX 组件渲染
*

View file

@ -488,7 +488,7 @@ const CellRenders = {
},
render(value, type, width, key) {
const style = { width: (width || COLUMN_MIN_WIDTH) + 'px' }
const style = { width: width || COLUMN_MIN_WIDTH }
if (!value) return this.renderSimple(value, style, key)
else return (this.__renders[type] || this.renderSimple)(value, style, key)
},
@ -955,7 +955,7 @@ class RbViewModal extends React.Component {
<div className="modal-wrapper">
<div className="modal rbview" ref={(c) => (this._rbview = c)}>
<div className="modal-dialog">
<div className="modal-content" style={{ width: this.mcWidth + 'px' }}>
<div className="modal-content" style={{ width: this.mcWidth }}>
<div className={'modal-body iframe rb-loading ' + (this.state.inLoad === true && 'rb-loading-active')}>
<iframe ref={(c) => (this._iframe = c)} className={this.state.isHide ? 'invisible' : ''} src={this.state.showAfterUrl || 'about:blank'} frameBorder="0" scrolling="no" />
<RbSpinner />

View file

@ -22,6 +22,11 @@
color: #fbbc05;
font-size: 5rem;
}
.zmdi.err610::before {
content: '\f1e7';
content: '\f21b';
color: #fbbc05;
}
.error-description > pre:empty {
display: none;
}
@ -47,7 +52,7 @@
<a class="btn btn-xl btn-space btn-secondary" th:href="@{/dashboard/home}" id="goHome">[[${bundle.L('返回首页')}]]</a>
<button class="btn btn-xl btn-space btn-primary" type="button" onclick="location.reload()">[[${bundle.L('重试')}]]</button>
<div class="mt-4">
<a href="https://getrebuild.com/report-issue?title=error-page" target="_blank">[[${bundle.L('报告问题')}]]</a>
<a th:href="${'https://getrebuild.com/report-issue?title=error-page-' + error_code}" target="_blank">[[${bundle.L('报告问题')}]]</a>
</div>
</div>
</div>

View file

@ -3,7 +3,7 @@
<head>
<th:block th:replace="~{/_include/header}" />
<title>[[${bundle.L('用户登录')}]]</title>
<style type="text/css">
<style>
#login-form > .row {
margin-left: -15px !important;
margin-right: -15px !important;
@ -99,6 +99,11 @@
background-color: #eee;
}
</style>
<style th:if="${commercial > 1}">
.rb-bgimg {
background-image: url(../commons/theme/use-bgimg);
}
</style>
</head>
<body class="rb-splash-screen">
<div class="rb-wrapper rb-login">