73 Commits
v4.1 ... v4.2

Author SHA1 Message Date
d066539616 若依 4.2 2020-03-23 09:02:04 +08:00
5c736e96c9 页面滚动显示返回顶部按钮 2020-03-20 14:34:26 +08:00
0307599eed 移动端定时任务&角色管理更多操作可点击 2020-03-20 13:46:43 +08:00
55da596a80 定时任务&角色管理添加更多操作按钮 2020-03-20 13:21:30 +08:00
6fa8c991b8 移动端点击左侧目录不进行菜单切换 2020-03-19 13:48:15 +08:00
51f98aa0cb 代码生成细节优化 2020-03-18 23:05:26 +08:00
07042ac9b1 iframe框架页会话过期弹出超时提示 2020-03-18 22:57:03 +08:00
3df553c488 移动端登录不显示左侧菜单 2020-03-18 18:32:45 +08:00
5426ba9d5e 首页logo固定,不随菜单滚动 2020-03-18 16:06:22 +08:00
6b9ee80ca4 任务分组字典翻译(调度日志详细) 2020-03-18 15:37:47 +08:00
05b5b314ee 字典管理添加缓存读取 2020-03-18 15:03:52 +08:00
f8491c36e2 字典数据列表标签显示样式 2020-03-18 12:45:53 +08:00
06751acbf9 参数管理支持缓存操作 2020-03-18 12:28:36 +08:00
567ab47ae9 日期控件清空结束时间设置开始默认值为2099-12-31 2020-03-14 15:34:33 +08:00
82f8dadbae 表格树添加获取数据后响应回调处理 2020-03-14 11:47:36 +08:00
ca6a4b2ecf 批量替换表前缀调整 2020-03-13 21:56:29 +08:00
9247e004d0 调整包顺序 2020-02-28 21:37:56 +08:00
e1e494de33 !153 支持表格导入模板的弹窗表单加入其它输入控件
Merge pull request !153 from ฅ(̳••̳)ฅ大步/master
2020-02-28 21:34:09 +08:00
3988b12e72 update ruoyi-admin/src/main/resources/static/ruoyi/js/ry-ui.js.
支持导入模板的表单可以添加除了file、updateSupport之外的输入控件。
2020-02-26 14:30:29 +08:00
c6bf712de4 登录页面默认模式设置 2020-02-17 17:28:16 +08:00
18e0a2a27d 重置刷新表格树 2020-02-17 15:50:11 +08:00
6ce34b1790 新增支持导出数据字段排序 2020-02-17 12:16:13 +08:00
b5678994da 修改代码生成部分细节问题 2020-02-10 14:59:31 +08:00
2aa98dcbe1 新增表格参数(是否单选checkbox) 2020-02-05 18:16:52 +08:00
96d0bd2581 README 2020-02-05 18:05:08 +08:00
f826a79633 防止db字段名为一个字母导致出现生成异常 2020-02-02 15:41:56 +08:00
c958d6ec83 添加新群号 2020-01-31 14:44:31 +08:00
5cb3430791 druid未授权不允许访问 2020-01-11 19:33:08 +08:00
d93e43cc2c 表格树父节点兼容0,'0','',null 2020-01-03 17:31:12 +08:00
47f007ba97 添加新群号 2020-01-03 10:58:25 +08:00
f96328ea6b 调整表格树兼容父节点判断 2020-01-02 19:29:55 +08:00
2d55917f2e 必填的项增加星号 2019-12-31 16:34:24 +08:00
1c6e5cf665 修复select2不显示校验错误信息 2019-12-25 16:59:12 +08:00
9d316c44d2 HTML过滤器不替换双引号为",防止json格式无效 2019-12-20 17:27:17 +08:00
2f8422278a 添加HTML过滤器,用于去除XSS漏洞隐患 2019-12-19 17:04:32 +08:00
98dd156396 修复多数据源下enabled=false导致读取不到bean导致异常问题 2019-12-19 16:10:10 +08:00
b65263fdd7 修复翻页记住选择项数据问题 2019-12-19 14:21:31 +08:00
21992c1be7 用户邮箱长度限制20 2019-12-16 11:44:20 +08:00
d80c1d2a73 修改错误页面返回主页出现嵌套问题 2019-12-10 17:20:43 +08:00
55978c7f15 表格浮动提示单双引号转义 2019-12-10 09:55:23 +08:00
b2012e699b 阿里云服务器89元/年,双12年末特惠,爆款产品限时1折 2019-12-09 11:32:53 +08:00
382d1868be 阿里云服务器89元/年,双12年末特惠,爆款产品限时1折 2019-12-09 11:25:49 +08:00
82df046e59 添加新群号 2019-12-04 11:44:26 +08:00
4f116a6a77 更新前后端分离版本链接 2019-12-03 18:05:28 +08:00
77d3db4cb0 代码生成防止缓存内的数据没有及时写入到zip文件 2019-12-02 15:02:31 +08:00
1155bcb22d 支持配置四级菜单 2019-11-27 11:05:10 +08:00
208c4a8417 升级shiro到最新版1.4.2 阻止rememberMe漏洞攻击 2019-11-26 15:33:42 +08:00
62a0018041 升级summernote到最新版本v0.8.12 2019-11-25 12:24:49 +08:00
f276a83956 侧边栏添加一套深蓝色主题 2019-11-22 09:41:04 +08:00
28b8f3e36f Excel注解dateFormat属性为字符串时间时格式处理 2019-11-21 16:33:34 +08:00
56a6e940c2 !146 浏览代码时间字符串处理
Merge pull request !146 from 厚积薄发/master
2019-11-21 16:31:37 +08:00
868edbc88c 时间字符串处理 2019-11-21 10:15:24 +08:00
b05a539970 支持mode配置history(表示去掉地址栏的#) 2019-11-21 09:59:45 +08:00
2c48aedda7 !144 修复War部署无法正常shutdown,ehcache内存泄漏
Merge pull request !144 from wayneliquan/master
2019-11-20 18:52:32 +08:00
87b8d032ca 修复War部署无法正常shutdown,ehcache内存泄漏
Signed-off-by: zhanliquan <zhanliquanit@foxmail.com>
2019-11-20 18:07:54 +08:00
080237cabf 修复War部署无法正常shutdown,ehcache内存泄漏
Signed-off-by: zhanliquan <zhanliquanit@foxmail.com>
2019-11-20 16:54:22 +08:00
005418e065 修复代码生成短字段无法识别问题 2019-11-20 10:44:02 +08:00
b32111f1ab 修复war包部署情况下404、500等页面样式丢失问题 2019-11-18 12:01:38 +08:00
25f51371f5 代码生成模板增加导出功能日志记录 2019-11-16 11:58:07 +08:00
14bad9bf20 2019年度最受欢迎中国开源软件评选
请给若依/RuoYi 投票,谢谢。
2019-11-15 09:55:32 +08:00
da2d0ba32f !143 serviceImpl模版 update方法判断bug修正
Merge pull request !143 from shenbururen/master
2019-11-13 14:55:27 +08:00
0b34c3e910 serviceImpl模版 update方法判断bug修正
应该判断updateTime字段。
2019-11-13 14:03:26 +08:00
1557a858ea 代码生成唯一编号调整为tableId 2019-11-12 15:12:13 +08:00
9a0098cca1 代码生成查询时忽略大小写&翻页记住选中&表注释未填写也允许导入 2019-11-12 15:00:47 +08:00
fe8c142cd6 修改select2选择数量限制提示语 2019-11-08 10:47:07 +08:00
5346af9ab0 全局配置类修改为注解,防止多环境配置下读取问题。 2019-11-07 17:33:28 +08:00
de1979212a 修复多表格情况下,firstLoad只对第一个表格生效 2019-11-07 15:22:42 +08:00
aa0f33b5e7 处理打包出现警告问题 2019-11-06 17:04:25 +08:00
ecb77e2be4 默认主题样式,防止网速慢情况下出现空白 2019-11-06 14:28:23 +08:00
db9d1a7720 修复文件上传多级目录识别问题 2019-11-01 09:31:26 +08:00
6ad6f90968 解码url,防止中文导致页面不能加载问题 2019-10-31 15:25:23 +08:00
b1b0542f72 右键Tab页刷新事件重复请求问题 2019-10-31 11:32:45 +08:00
7e749c25c6 阿里云服务器86元/年,双11冰点底价,错过再等1年 2019-10-24 09:37:19 +08:00
156 changed files with 10574 additions and 8642 deletions

View File

@ -4,11 +4,11 @@
性别男,若依是给还没有出生女儿取的名字(寓意:你若不离不弃,我必生死相依)
若依参考后台模板。有需要可自行到群内下载。
> 如需前后端分离版本,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)
> 如需单应用,请移步 [RuoYi-fast](https://gitee.com/y_project/RuoYi-fast) `(保持同步更新)`,如需其他版本,请移步 [项目扩展](http://doc.ruoyi.vip/ruoyi/document/xmkz.html) `(不定时更新)`
> 阿里云通用云产品1888优惠券 [点我领取](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof)&nbsp;&nbsp;&nbsp;&nbsp;腾讯云通用云产品2860优惠券 [点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)&nbsp;&nbsp;`(仅限新用户)`
> 阿里云通用云产品1888优惠券 [点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof)&nbsp;&nbsp;&nbsp;&nbsp;腾讯云通用云产品2860优惠券 [点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)&nbsp;&nbsp;`(仅限新用户)`
> 阿里云Hi拼购 限量爆款 低至199元/年 [点我进入](https://www.aliyun.com/acts/hi-group-buying?userCode=brki8iof)&nbsp;&nbsp;`(仅限新用户)`
@ -80,11 +80,11 @@
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/bed2b98a44e7ae820c2885329e711965c28.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/5f3d39a141f21f81b90536f391b8408f1fa.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-6d73c2140ce694e3de4c05035fdc1868d4c.png"/></td>
</tr>
</table>
## 若依交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU) [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA) [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [![加入QQ群](https://img.shields.io/badge/已满-1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz) [![加入QQ群](https://img.shields.io/badge/86752435-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) 点击按钮入群。
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU) [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA) [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [![加入QQ群](https://img.shields.io/badge/已满-1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz) [![加入QQ群](https://img.shields.io/badge/已满-86752435-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [![加入QQ群](https://img.shields.io/badge/已满-134072510-blue.svg)](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [![加入QQ群](https://img.shields.io/badge/已满-210336300-blue.svg)](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [![加入QQ群](https://img.shields.io/badge/339522636-blue.svg)](https://jq.qq.com/?_wv=1027&k=5omzbKc)

View File

@ -6,18 +6,18 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId>
<version>4.1.0</version>
<version>4.2.0</version>
<name>ruoyi</name>
<url>http://www.ruoyi.vip</url>
<description>若依管理系统</description>
<properties>
<ruoyi.version>4.1.0</ruoyi.version>
<ruoyi.version>4.2.0</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<shiro.version>1.4.1</shiro.version>
<shiro.version>1.4.2</shiro.version>
<thymeleaf.extras.shiro.version>2.0.0</thymeleaf.extras.shiro.version>
<mybatis.boot.version>1.3.2</mybatis.boot.version>
<druid.version>1.1.14</druid.version>
@ -228,6 +228,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.1.0</version>
<version>4.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
@ -80,6 +80,7 @@
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration>
@ -97,11 +98,11 @@
<version>3.0.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${artifactId}</warName>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
</plugins>
<finalName>${artifactId}</finalName>
<finalName>${project.artifactId}</finalName>
</build>
</project>

View File

@ -132,6 +132,19 @@ public class SysConfigController extends BaseController
return toAjax(configService.deleteConfigByIds(ids));
}
/**
* 清空缓存
*/
@RequiresPermissions("system:config:remove")
@Log(title = "参数管理", businessType = BusinessType.CLEAN)
@GetMapping("/clearCache")
@ResponseBody
public AjaxResult clearCache()
{
configService.clearCache();
return success();
}
/**
* 校验参数键名
*/

View File

@ -125,14 +125,20 @@ public class SysDictTypeController extends BaseController
@ResponseBody
public AjaxResult remove(String ids)
{
try
{
return toAjax(dictTypeService.deleteDictTypeByIds(ids));
}
catch (Exception e)
{
return error(e.getMessage());
}
return toAjax(dictTypeService.deleteDictTypeByIds(ids));
}
/**
* 清空缓存
*/
@RequiresPermissions("system:dict:remove")
@Log(title = "字典类型", businessType = BusinessType.CLEAN)
@GetMapping("/clearCache")
@ResponseBody
public AjaxResult clearCache()
{
dictTypeService.clearCache();
return success();
}
/**

View File

@ -10,6 +10,7 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.framework.util.ShiroUtils;
import com.ruoyi.system.domain.SysMenu;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysMenuService;
/**
@ -23,6 +24,9 @@ public class SysIndexController extends BaseController
@Autowired
private ISysMenuService menuService;
@Autowired
private ISysConfigService configService;
// 系统首页
@GetMapping("/index")
public String index(ModelMap mmap)
@ -33,6 +37,8 @@ public class SysIndexController extends BaseController
List<SysMenu> menus = menuService.selectMenusByUser(user);
mmap.put("menus", menus);
mmap.put("user", user);
mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme"));
mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName"));
mmap.put("copyrightYear", Global.getCopyrightYear());
mmap.put("demoEnabled", Global.isDemoEnabled());
return "index";

View File

@ -0,0 +1,46 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.shiro.service.SysRegisterService;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.service.ISysConfigService;
/**
* 注册验证
*
* @author ruoyi
*/
@Controller
public class SysRegisterController extends BaseController
{
@Autowired
private SysRegisterService registerService;
@Autowired
private ISysConfigService configService;
@GetMapping("/register")
public String register()
{
return "register";
}
@PostMapping("/register")
@ResponseBody
public AjaxResult ajaxRegister(SysUser user)
{
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
{
return error("当前系统没有开启注册功能!");
}
String msg = registerService.register(user);
return StringUtils.isEmpty(msg) ? success() : error(msg);
}
}

View File

@ -22,6 +22,7 @@ import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import com.ruoyi.framework.util.ShiroUtils;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
@ -200,6 +201,33 @@ public class SysUserController extends BaseController
return error();
}
/**
* 进入授权角色页
*/
@GetMapping("/authRole/{userId}")
public String authRole(@PathVariable("userId") Long userId, ModelMap mmap)
{
SysUser user = userService.selectUserById(userId);
// 获取用户所属的角色列表
List<SysUserRole> userRoles = userService.selectUserRoleByUserId(userId);
mmap.put("user", user);
mmap.put("userRoles", userRoles);
return prefix + "/authRole";
}
/**
* 用户授权角色
*/
@RequiresPermissions("system:user:add")
@Log(title = "用户管理", businessType = BusinessType.GRANT)
@PostMapping("/authRole/insertAuthRole")
@ResponseBody
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
{
userService.insertUserAuth(userId, roleIds);
return success();
}
@RequiresPermissions("system:user:remove")
@Log(title = "用户管理", businessType = BusinessType.DELETE)
@PostMapping("/remove")

View File

@ -3,7 +3,7 @@ ruoyi:
# 名称
name: RuoYi
# 版本
version: 4.1.0
version: 4.2.0
# 版权年份
copyrightYear: 2019
# 实例演示开关

View File

@ -41,7 +41,31 @@
timeToIdleSeconds="0"
statistics="true">
</cache>
<!-- 系统缓存 -->
<cache name="sys-cache"
maxEntriesLocalHeap="1000"
eternal="true"
overflowToDisk="true"
statistics="true">
</cache>
<!-- 系统参数缓存 -->
<cache name="sys-config"
maxEntriesLocalHeap="1000"
eternal="true"
overflowToDisk="true"
statistics="true">
</cache>
<!-- 系统字典缓存 -->
<cache name="sys-dict"
maxEntriesLocalHeap="1000"
eternal="true"
overflowToDisk="true"
statistics="true">
</cache>
<!-- 系统会话缓存 -->
<cache name="shiro-activeSessionCache"
maxElementsInMemory="10000"
@ -52,6 +76,6 @@
diskPersistent="true"
diskExpiryThreadIntervalSeconds="600">
</cache>
</ehcache>

File diff suppressed because one or more lines are too long

View File

@ -29,7 +29,7 @@
$.extend($.fn.bootstrapTable.locales, {
formatExport: function () {
return 'Export data';
return '导出';
}
});
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);

View File

@ -241,19 +241,26 @@
// 缓存并格式化数据
var formatData = function(data) {
var _root = options.rootIdValue ? options.rootIdValue : null;
var firstCode = data[0][options.parentCode];
// 父节点属性列表
var parentCodes = [];
var rootFlag = false;
$.each(data, function(index, item) {
if($.inArray(item[options.parentCode], parentCodes) == -1){
parentCodes.push(item[options.parentCode]);
}
});
$.each(data, function(index, item) {
// 添加一个默认属性,用来判断当前节点有没有被显示
item.isShow = false;
// 这里兼容几种常见Root节点写法
// 默认的几种判断
// 顶级节点校验判断兼容0,'0','',null
var _defaultRootFlag = item[options.parentCode] == '0' ||
item[options.parentCode] == 0 ||
item[options.parentCode] == null ||
item[options.parentCode] == firstCode ||
item[options.parentCode] == '';
item[options.parentCode] == 0 ||
item[options.parentCode] == null ||
item[options.parentCode] == '' ||
$.inArray(item[options.code], parentCodes) > 0 && !rootFlag;
if (!item[options.parentCode] || (_root ? (item[options.parentCode] == options.rootIdValue) : _defaultRootFlag)) {
if (!target.data_list["_root_"]) {
rootFlag = true;
if (!target.data_list["_root_"]) {
target.data_list["_root_"] = [];
}
if (!target.data_obj["id_" + item[options.code]]) {

View File

@ -4614,7 +4614,7 @@ S2.define('select2/i18n/en',[],function () {
return '载入更多结果…';
},
maximumSelected: function (args) {
var message = '最多只能选择' + args.maximum + '个项';
var message = '最多只能' + args.maximum + '个项';
if (args.maximum != 1) {
message += 's';

File diff suppressed because one or more lines are too long

View File

@ -5778,7 +5778,7 @@ td.visible-lg {
display: table-cell !important;
}
}
.hidden-xs {
.summernote .hidden-xs {
display: block !important;
}
tr.hidden-xs {

View File

@ -1,155 +1,155 @@
(function($) {
$.extend($.summernote.lang, {
'zh-CN': {
font: {
bold: '粗体',
italic: '斜体',
underline: '下划线',
clear: '清除格式',
height: '行高',
name: '字体',
strikethrough: '删除线',
subscript: '下标',
superscript: '上标',
size: '字号'
},
image: {
image: '图片',
insert: '插入图片',
resizeFull: '缩放至 100%',
resizeHalf: '缩放至 50%',
resizeQuarter: '缩放至 25%',
floatLeft: '靠左浮动',
floatRight: '靠右浮动',
floatNone: '取消浮动',
shapeRounded: '形状: 圆角',
shapeCircle: '形状: 圆',
shapeThumbnail: '形状: 缩略图',
shapeNone: '形状: 无',
dragImageHere: '将图片拖拽至此处',
dropImage: '拖拽图片或文本',
selectFromFiles: '从本地上传',
maximumFileSize: '文件大小最大值',
maximumFileSizeError: '文件大小超出最大值。',
url: '图片地址',
remove: '移除图片',
original: '原始图片'
},
video: {
video: '视频',
videoLink: '视频链接',
insert: '插入视频',
url: '视频地址',
providers: '(优酷, 腾讯, Instagram, DailyMotion, Youtube等)'
},
link: {
link: '链接',
insert: '插入链接',
unlink: '去除链接',
edit: '编辑链接',
textToDisplay: '显示文本',
url: '链接地址',
openInNewWindow: '在新窗口打开'
},
table: {
table: '表格',
addRowAbove: '在上方插入行',
addRowBelow: '在下方插入行',
addColLeft: '在左侧插入列',
addColRight: '在右侧插入列',
delRow: '删除行',
delCol: '删除列',
delTable: '删除表格'
},
hr: {
insert: '水平线'
},
style: {
style: '样式',
p: '普通',
blockquote: '引用',
pre: '代码',
h1: '标题 1',
h2: '标题 2',
h3: '标题 3',
h4: '标题 4',
h5: '标题 5',
h6: '标题 6'
},
lists: {
unordered: '无序列表',
ordered: '有序列表'
},
options: {
help: '帮助',
fullscreen: '全屏',
codeview: '源代码'
},
paragraph: {
paragraph: '段落',
outdent: '减少缩进',
indent: '增加缩进',
left: '左对齐',
center: '居中对齐',
right: '右对齐',
justify: '两端对齐'
},
color: {
recent: '最近使用',
more: '更多',
background: '背景',
foreground: '前景',
transparent: '透明',
setTransparent: '透明',
reset: '重置',
resetToDefault: '默认'
},
shortcut: {
shortcuts: '快捷键',
close: '关闭',
textFormatting: '文本格式',
action: '动作',
paragraphFormatting: '段落格式',
documentStyle: '文档样式',
extraKeys: '额外按键'
},
help: {
insertParagraph: '插入段落',
undo: '撤销',
redo: '重做',
tab: '增加缩进',
untab: '减少缩进',
bold: '粗体',
italic: '斜体',
underline: '下划线',
strikethrough: '删除线',
removeFormat: '清除格式',
justifyLeft: '左对齐',
justifyCenter: '居中对齐',
justifyRight: '右对齐',
justifyFull: '两端对齐',
insertUnorderedList: '无序列表',
insertOrderedList: '有序列表',
outdent: '减少缩进',
indent: '增加缩进',
formatPara: '设置选中内容样式为 普通',
formatH1: '设置选中内容样式为 标题1',
formatH2: '设置选中内容样式为 标题2',
formatH3: '设置选中内容样式为 标题3',
formatH4: '设置选中内容样式为 标题4',
formatH5: '设置选中内容样式为 标题5',
formatH6: '设置选中内容样式为 标题6',
insertHorizontalRule: '插入水平线',
'linkDialog.show': '显示链接对话框'
},
history: {
undo: '撤销',
redo: '重做'
},
specialChar: {
specialChar: '特殊字符',
select: '选取特殊字符'
}
}
});
})(jQuery);
(function($) {
$.extend($.summernote.lang, {
'zh-CN': {
font: {
bold: '粗体',
italic: '斜体',
underline: '下划线',
clear: '清除格式',
height: '行高',
name: '字体',
strikethrough: '删除线',
subscript: '下标',
superscript: '上标',
size: '字号',
},
image: {
image: '图片',
insert: '插入图片',
resizeFull: '缩放至 100%',
resizeHalf: '缩放至 50%',
resizeQuarter: '缩放至 25%',
floatLeft: '靠左浮动',
floatRight: '靠右浮动',
floatNone: '取消浮动',
shapeRounded: '形状: 圆角',
shapeCircle: '形状: 圆',
shapeThumbnail: '形状: 缩略图',
shapeNone: '形状: 无',
dragImageHere: '将图片拖拽至此处',
dropImage: '拖拽图片或文本',
selectFromFiles: '从本地上传',
maximumFileSize: '文件大小最大值',
maximumFileSizeError: '文件大小超出最大值。',
url: '图片地址',
remove: '移除图片',
original: '原始图片',
},
video: {
video: '视频',
videoLink: '视频链接',
insert: '插入视频',
url: '视频地址',
providers: '(优酷, 腾讯, Instagram, DailyMotion, Youtube等)',
},
link: {
link: '链接',
insert: '插入链接',
unlink: '去除链接',
edit: '编辑链接',
textToDisplay: '显示文本',
url: '链接地址',
openInNewWindow: '在新窗口打开',
},
table: {
table: '表格',
addRowAbove: '在上方插入行',
addRowBelow: '在下方插入行',
addColLeft: '在左侧插入列',
addColRight: '在右侧插入列',
delRow: '删除行',
delCol: '删除列',
delTable: '删除表格',
},
hr: {
insert: '水平线',
},
style: {
style: '样式',
p: '普通',
blockquote: '引用',
pre: '代码',
h1: '标题 1',
h2: '标题 2',
h3: '标题 3',
h4: '标题 4',
h5: '标题 5',
h6: '标题 6',
},
lists: {
unordered: '无序列表',
ordered: '有序列表',
},
options: {
help: '帮助',
fullscreen: '全屏',
codeview: '源代码',
},
paragraph: {
paragraph: '段落',
outdent: '减少缩进',
indent: '增加缩进',
left: '左对齐',
center: '居中对齐',
right: '右对齐',
justify: '两端对齐',
},
color: {
recent: '最近使用',
more: '更多',
background: '背景',
foreground: '前景',
transparent: '透明',
setTransparent: '透明',
reset: '重置',
resetToDefault: '默认',
},
shortcut: {
shortcuts: '快捷键',
close: '关闭',
textFormatting: '文本格式',
action: '动作',
paragraphFormatting: '段落格式',
documentStyle: '文档样式',
extraKeys: '额外按键',
},
help: {
insertParagraph: '插入段落',
undo: '撤销',
redo: '重做',
tab: '增加缩进',
untab: '减少缩进',
bold: '粗体',
italic: '斜体',
underline: '下划线',
strikethrough: '删除线',
removeFormat: '清除格式',
justifyLeft: '左对齐',
justifyCenter: '居中对齐',
justifyRight: '右对齐',
justifyFull: '两端对齐',
insertUnorderedList: '无序列表',
insertOrderedList: '有序列表',
outdent: '减少缩进',
indent: '增加缩进',
formatPara: '设置选中内容样式为 普通',
formatH1: '设置选中内容样式为 标题1',
formatH2: '设置选中内容样式为 标题2',
formatH3: '设置选中内容样式为 标题3',
formatH4: '设置选中内容样式为 标题4',
formatH5: '设置选中内容样式为 标题5',
formatH6: '设置选中内容样式为 标题6',
insertHorizontalRule: '插入水平线',
'linkDialog.show': '显示链接对话框',
},
history: {
undo: '撤销',
redo: '重做',
},
specialChar: {
specialChar: '特殊字符',
select: '选取特殊字符',
},
},
});
})(jQuery);

View File

@ -1,3 +0,0 @@
/*! Summernote v0.8.11 | (c) 2013- Alan Hong and other contributors | MIT license */
!function(e){e.extend(e.summernote.lang,{"zh-CN":{font:{bold:"粗体",italic:"斜体",underline:"下划线",clear:"清除格式",height:"行高",name:"字体",strikethrough:"删除线",subscript:"下标",superscript:"上标",size:"字号"},image:{image:"图片",insert:"插入图片",resizeFull:"缩放至 100%",resizeHalf:"缩放至 50%",resizeQuarter:"缩放至 25%",floatLeft:"靠左浮动",floatRight:"靠右浮动",floatNone:"取消浮动",shapeRounded:"形状: 圆角",shapeCircle:"形状: 圆",shapeThumbnail:"形状: 缩略图",shapeNone:"形状: 无",dragImageHere:"将图片拖拽至此处",dropImage:"拖拽图片或文本",selectFromFiles:"从本地上传",maximumFileSize:"文件大小最大值",maximumFileSizeError:"文件大小超出最大值。",url:"图片地址",remove:"移除图片",original:"原始图片"},video:{video:"视频",videoLink:"视频链接",insert:"插入视频",url:"视频地址",providers:"(优酷, 腾讯, Instagram, DailyMotion, Youtube等)"},link:{link:"链接",insert:"插入链接",unlink:"去除链接",edit:"编辑链接",textToDisplay:"显示文本",url:"链接地址",openInNewWindow:"在新窗口打开"},table:{table:"表格",addRowAbove:"在上方插入行",addRowBelow:"在下方插入行",addColLeft:"在左侧插入列",addColRight:"在右侧插入列",delRow:"删除行",delCol:"删除列",delTable:"删除表格"},hr:{insert:"水平线"},style:{style:"样式",p:"普通",blockquote:"引用",pre:"代码",h1:"标题 1",h2:"标题 2",h3:"标题 3",h4:"标题 4",h5:"标题 5",h6:"标题 6"},lists:{unordered:"无序列表",ordered:"有序列表"},options:{help:"帮助",fullscreen:"全屏",codeview:"源代码"},paragraph:{paragraph:"段落",outdent:"减少缩进",indent:"增加缩进",left:"左对齐",center:"居中对齐",right:"右对齐",justify:"两端对齐"},color:{recent:"最近使用",more:"更多",background:"背景",foreground:"前景",transparent:"透明",setTransparent:"透明",reset:"重置",resetToDefault:"默认"},shortcut:{shortcuts:"快捷键",close:"关闭",textFormatting:"文本格式",action:"动作",paragraphFormatting:"段落格式",documentStyle:"文档样式",extraKeys:"额外按键"},help:{insertParagraph:"插入段落",undo:"撤销",redo:"重做",tab:"增加缩进",untab:"减少缩进",bold:"粗体",italic:"斜体",underline:"下划线",strikethrough:"删除线",removeFormat:"清除格式",justifyLeft:"左对齐",justifyCenter:"居中对齐",justifyRight:"右对齐",justifyFull:"两端对齐",insertUnorderedList:"无序列表",insertOrderedList:"有序列表",outdent:"减少缩进",indent:"增加缩进",formatPara:"设置选中内容样式为 普通",formatH1:"设置选中内容样式为 标题1",formatH2:"设置选中内容样式为 标题2",formatH3:"设置选中内容样式为 标题3",formatH4:"设置选中内容样式为 标题4",formatH5:"设置选中内容样式为 标题5",formatH6:"设置选中内容样式为 标题6",insertHorizontalRule:"插入水平线","linkDialog.show":"显示链接对话框"},history:{undo:"撤销",redo:"重做"},specialChar:{specialChar:"特殊字符",select:"选取特殊字符"}}})}(jQuery);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
*
*/
/** 蓝色主题 skin-blue **/
.skin-blue .navbar {
.navbar, .skin-blue .navbar {
background-color: #3c8dbc
}
@ -103,11 +103,6 @@
border-left: none;
}
.skin-blue .nav>li>.treeview-menu {
margin: 0 1px;
background: #2c3b41
}
.skin-blue .sidebar a {
color: #b8c7ce
}
@ -116,15 +111,6 @@
text-decoration: none
}
.skin-blue .treeview-menu>li>a {
color: #8aa4af
}
.skin-blue .treeview-menu>li.active>a,
.skin-blue .treeview-menu>li>a:hover {
color: #fff
}
.skin-blue .sidebar-form {
border-radius: 3px;
border: 1px solid #374850;
@ -292,11 +278,6 @@
border-left: none;
}
.skin-green .nav>li>.treeview-menu {
margin: 0 1px;
background: #2c3b41
}
.skin-green .sidebar a {
color: #b8c7ce
}
@ -305,15 +286,6 @@
text-decoration: none
}
.skin-green .treeview-menu>li>a {
color: #8aa4af
}
.skin-green .treeview-menu>li.active>a,
.skin-green .treeview-menu>li>a:hover {
color: #fff
}
.skin-green .sidebar-form {
border-radius: 3px;
border: 1px solid #374850;
@ -457,11 +429,6 @@
border-bottom: 1px solid #e5e5e5;
}
.skin-red .nav>li>.treeview-menu {
margin: 0 1px;
background: #2c3b41
}
.skin-red .sidebar a {
color: #b8c7ce
}
@ -470,15 +437,6 @@
text-decoration: none
}
.skin-red .treeview-menu>li>a {
color: #8aa4af
}
.skin-red .treeview-menu>li.active>a,
.skin-red .treeview-menu>li>a:hover {
color: #fff
}
.skin-red .sidebar-form {
border-radius: 3px;
border: 1px solid #374850;
@ -622,11 +580,6 @@
border-bottom: 1px solid #e5e5e5;
}
.skin-yellow .nav>li>.treeview-menu {
margin: 0 1px;
background: #2c3b41
}
.skin-yellow .sidebar a {
color: #b8c7ce
}
@ -635,15 +588,6 @@
text-decoration: none
}
.skin-yellow .treeview-menu>li>a {
color: #8aa4af
}
.skin-yellow .treeview-menu>li.active>a,
.skin-yellow .treeview-menu>li>a:hover {
color: #fff
}
.skin-yellow .sidebar-form {
border-radius: 3px;
border: 1px solid #374850;
@ -787,11 +731,6 @@
border-bottom: 1px solid #e5e5e5;
}
.skin-purple .nav>li>.treeview-menu {
margin: 0 1px;
background: #2c3b41
}
.skin-purple .sidebar a {
color: #b8c7ce
}
@ -800,15 +739,6 @@
text-decoration: none
}
.skin-purple .treeview-menu>li>a {
color: #8aa4af
}
.skin-purple .treeview-menu>li.active>a,
.skin-purple .treeview-menu>li>a:hover {
color: #fff
}
.skin-purple .sidebar-form {
border-radius: 3px;
border: 1px solid #374850;
@ -855,7 +785,7 @@
* NAME - .theme-dark/theme-light
*
*/
/** 深主题 .theme-dark **/
/** 深主题 .theme-dark **/
.theme-dark .user-panel>.info>p, .theme-dark .user-panel>.info, .theme-dark .user-panel>.info>a{
color: #fff
}
@ -961,4 +891,94 @@
.fixed-sidebar.theme-light.mini-navbar .nav li:hover>.nav-second-level {
background-color: #f9fafc;
}
/** 深蓝主题 theme-light **/
/**
.skin-blue.theme-blue .logo, .skin-white.theme-blue .logo {
background-color: rgba(15,41,80,1) !important;
color: #fff;
}
**/
.theme-blue .user-panel>.info>p, .theme-blue .user-panel>.info, .theme-blue .user-panel>.info>a{
color: #a3b1cc
}
.theme-blue .nav>li.active{
background-color: rgba(15,41,80,1);
}
.theme-blue .navbar-static-side {
background-color: rgba(15,41,80,1);
box-shadow: 2px 0 2px 0 rgba(29,35,41,.05);
}
.theme-blue .user-panel {
background-color: rgba(15,41,80,1);
}
.theme-blue .navbar-default .nav>li>a {
color: #a3b1cc;
}
.theme-blue.skin-blue .navbar-default .nav>li.active>a {
color: #1890ff;
}
.theme-blue.skin-blue .navbar-default .nav>li.selected>a,
.theme-blue.skin-blue .navbar-default .nav>li.selected>a:focus {
background-color: #1890ff;
}
.theme-blue.skin-green .navbar-default .nav>li.active>a {
color: #52c41a;
}
.theme-blue.skin-green .navbar-default .nav>li.selected>a,
.theme-blue.skin-green .navbar-default .nav>li.selected>a:focus {
background-color: #52c41a;
color: rgba(255,255,255,1);
}
.theme-blue.skin-purple .navbar-default .nav>li.active>a {
color: rgb(114, 46, 209);
}
.theme-blue.skin-purple .navbar-default .nav>li.selected>a,
.theme-blue.skin-purple .navbar-default .nav>li.selected>a:focus {
background-color: #722ed1;
color: rgba(255,255,255,1);
}
.theme-blue.skin-red .navbar-default .nav>li.active>a {
color: rgb(245, 34, 45);
}
.theme-blue.skin-red .navbar-default .nav>li.selected>a,
.theme-blue.skin-red .navbar-default .nav>li.selected>a:focus {
background-color: #f5222d;
color: rgba(255,255,255,1);
}
.theme-blue.skin-yellow .navbar-default .nav>li.active>a {
color: rgb(250, 173, 20);
}
.theme-blue.skin-yellow .navbar-default .nav>li.selected>a,
.theme-blue.skin-yellow .navbar-default .nav>li.selected>a:focus {
background-color: #faad14;
color: rgba(255,255,255,1);
}
.theme-blue .navbar-default .nav>li>a:hover,
.theme-blue .navbar-default .nav>li>a:focus {
background-color: rgba(15,41,80,1);
box-shadow: 2px 0 2px 0 rgba(29,35,41,.05);
}
.fixed-sidebar.theme-blue.mini-navbar .nav li:hover>a> span.nav-label {
background-color: rgba(15,41,80,1);
}
.fixed-sidebar.theme-blue.mini-navbar .nav li:hover>.nav-second-level {
background-color: rgba(15,41,80,1);
}

View File

@ -763,15 +763,15 @@ body.canvas-menu.mini-navbar nav.navbar-static-side {
}
.btn-default {
background-color: #c2c2c2;
border-color: #c2c2c2;
color: #FFFFFF;
background-color: #f4f4f4;
border-color: #ddd;
color: #444;
}
.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {
background-color: #bababa;
border-color: #bababa;
color: #FFFFFF;
background-color: #e7e7e7;
border-color: #e7e7e7;
color: #444;
}
.btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {
@ -6939,7 +6939,7 @@ body.rtls .top-navigation .footer.fixed, body.rtls.top-navigation .footer.fixed
background: #f5f5f5;
}
.nav .logo {
nav .logo {
background-color: #367fa9;
color: #fff;
border-bottom: 0 solid transparent;

View File

@ -18,6 +18,7 @@ user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录

View File

@ -322,12 +322,18 @@
}
/** 表单验证 样式布局 **/
.control-label.is-required:before {
content: '* ';
color: red;
}
label.error {
position: absolute;
right: 18px;
top: 10px;
color: #ef392b;
font-size: 12px
font-size: 12px;
z-index:99;
}
.input-group label.error {
@ -638,7 +644,7 @@ label {
margin: 5px 15px 5px 0px;
}
.select-list li p{
.select-list li p, .select-list li label:not(.radio-box){
float: left;
width: 65px;
margin: 5px 5px 5px 0px;
@ -811,12 +817,26 @@ label {
border: 0px!important;
}
.table-striped .table, .table-striped .table, .table>thead>tr>th, .table>tbody>tr>th, .table>tfoot>tr>th, .table>thead>tr>td, .table>tbody>tr>td, .table>tfoot>tr>td {
.table-striped table>thead>tr>th, .table-striped table>tbody>tr>th, .table-striped table>tfoot>tr>th, .table-striped table>thead>tr>td, .table-striped table>tbody>tr>td, .table-striped table>tfoot>tr>td {
border-bottom: 1px solid #e7eaec!important;
background-color: transparent;
border: 0px;
}
.table-bordered table>thead>tr>th:first-child, .table-bordered table>tbody>tr>td:first-child {
border-left: 1px solid #ddd;
}
.table-bordered table>thead>tr>th:last-child, .table-bordered table>tbody>tr>td:last-child {
border-right: 1px solid #ddd;
}
.table-bordered table>thead>tr>th, .table-bordered table>tbody>tr>td {
border-top: 1px solid #ddd!important;
border-bottom: 1px solid #ddd;
}
.fixed-table-footer {
border-top: 0px solid #ddd;
}
@ -838,10 +858,6 @@ label {
background-color: #eff3f8;
}
.table-bordered td,.table-bordered th {
border: 1px solid #ddd!important
}
.fixed-table-container thead th >.both{
display: inline-block
}
@ -893,7 +909,7 @@ label {
.bootstrap-tree-table .treetable-table thead, .treetable-table tbody tr {display:table;width:100%;table-layout:fixed;}
.bootstrap-tree-table .treetable-thead th{line-height:24px;border: 0 !important;border-radius: 4px;border-left:0px solid #e7eaec !important;border-bottom:1px solid #ccc!important;text-align: left;}
.bootstrap-tree-table .treetable-thead tr :first-child{border-left:0 !important}
.bootstrap-tree-table .treetable-tbody td{overflow:hidden;border: 0 !important;border-left:0px solid #e7eaec !important;border-bottom:1px solid #e7eaec!important;white-space: nowrap; text-overflow: ellipsis;}
.bootstrap-tree-table .treetable-tbody td{border: 0 !important;border-left:0px solid #e7eaec !important;border-bottom:1px solid #e7eaec!important;white-space: nowrap; text-overflow: ellipsis;}
.bootstrap-tree-table .treetable-tbody tr :first-child{border-left:0 !important}
.bootstrap-tree-table .treetable-bars .tool-left, .bootstrap-tree-table .treetable-bars .tool-right{margin-top: 10px; margin-bottom: 10px;}
.bootstrap-tree-table .treetable-bars .tool-left{float: left;}
@ -998,6 +1014,50 @@ label {
background-color: #F5F5F5;
}
/** 气泡弹出框样式 **/
.popover {
font-size: 13px;
max-width: unset;
}
.popover-title {
padding: 8px 14px;
margin: 0 !important;
font-size: 14px;
background-color: #f7f7f7;
border-bottom: 1px solid #ebebeb;
border-radius: 5px 5px 0 0;
}
.popover-content {
padding: 5px;
}
/** 向上滚动样式 **/
#scroll-up {
border-width: 0;
position: fixed;
right: 2px;
z-index: 99;
-webkit-transition-duration: .3s;
transition-duration: .3s;
opacity: 0;
filter: alpha(opacity=0);
bottom: -24px;
visibility: hidden;
background-color: #aaa;
color: #fff;
font-size: 14px;
display: none;
}
#scroll-up.display {
opacity: .7;
filter: alpha(opacity=70);
bottom: 2px;
visibility: visible;
}
::-webkit-scrollbar {
width: 6px;
height: 10px;

View File

@ -7,14 +7,16 @@ layer.config({
skin: 'layer-ext-moon'
});
var isMobile = $.common.isMobile() || $(window).width() < 769;
$(function() {
// MetsiMenu
$('#side-menu').metisMenu();
//固定菜单栏
// 固定菜单栏
$(function() {
$('.sidebar-collapse').slimScroll({
height: '100%',
height: '96%',
railOpacity: 0.9,
alwaysVisible: false
});
@ -22,16 +24,21 @@ $(function() {
// 菜单切换
$('.navbar-minimalize').click(function() {
$("body").toggleClass("mini-navbar");
if (isMobile) {
$("body").toggleClass("canvas-menu");
} else {
$("body").toggleClass("mini-navbar");
}
SmoothlyMenu();
});
$('#side-menu>li').click(function() {
if ($('body').hasClass('mini-navbar')) {
if ($('body').hasClass('canvas-menu mini-navbar')) {
NavToggle();
}
});
$('#side-menu>li li a').click(function() {
$('#side-menu>li li a:not(:has(span))').click(function() {
if ($(window).width() < 769) {
NavToggle();
}
@ -49,9 +56,8 @@ $(function() {
$(window).bind("load resize",
function() {
if ($(this).width() < 769) {
$('body').addClass('mini-navbar');
$('.navbar-static-side').fadeIn();
$(".sidebar-collapse .logo").addClass("hide");
$('body').addClass('canvas-menu');
$("nav .logo").addClass("hide");
$(".slimScrollDiv").css({ "overflow":"hidden" })
}
});
@ -60,21 +66,27 @@ function NavToggle() {
$('.navbar-minimalize').trigger('click');
}
function fixedSidebar() {
$('#side-menu').hide();
$("nav .logo").addClass("hide");
setTimeout(function() {
$('#side-menu').fadeIn(500);
},
100);
}
function SmoothlyMenu() {
if (!$('body').hasClass('mini-navbar')) {
$('#side-menu').hide();
$(".sidebar-collapse .logo").removeClass("hide");
setTimeout(function() {
$('#side-menu').fadeIn(500);
},
100);
} else if ($('body').hasClass('fixed-sidebar')) {
$('#side-menu').hide();
$(".sidebar-collapse .logo").addClass("hide");
setTimeout(function() {
$('#side-menu').fadeIn(500);
},
300);
if (isMobile && !$('body').hasClass('canvas-menu')) {
$('.navbar-static-side').fadeIn();
fixedSidebar();
} else if (!isMobile &&!$('body').hasClass('mini-navbar')) {
fixedSidebar();
$("nav .logo").removeClass("hide");
} else if (isMobile && $('body').hasClass('fixed-sidebar')) {
$('.navbar-static-side').fadeOut();
fixedSidebar();
} else if (!isMobile && $('body').hasClass('fixed-sidebar')) {
fixedSidebar();
} else {
$('#side-menu').removeAttr('style');
}
@ -482,9 +494,13 @@ $(function() {
// 设置锚点
function setIframeUrl(href) {
var nowUrl = window.location.href;
var newUrl = nowUrl.substring(0, nowUrl.indexOf("#"));
window.location.href = newUrl + "#" + href;
if($.common.equals("history", mode)) {
storage.set('publicPath', href);
} else {
var nowUrl = window.location.href;
var newUrl = nowUrl.substring(0, nowUrl.indexOf("#"));
window.location.href = newUrl + "#" + href;
}
}
$(window).keydown(function(event) {
@ -571,7 +587,6 @@ $(function() {
setActiveTab(this);
var target = $('.RuoYi_iframe[data-id="' + this.data('id') + '"]');
var url = target.attr('src');
target.attr('src', url).ready();
$.modal.loading("数据加载中,请稍后...");
target.attr('src', url).load(function () {
$.modal.closeLoading();
@ -588,4 +603,4 @@ $(function() {
},
}
})
});
});

View File

@ -12,6 +12,11 @@ $(function() {
});
}
// 回到顶部绑定
if ($.fn.toTop !== undefined) {
$('#scroll-up').toTop();
}
// select2复选框事件绑定
if ($.fn.select2 !== undefined) {
$.fn.select2.defaults.set( "theme", "bootstrap" );
@ -66,9 +71,9 @@ $(function() {
startDate.config.max.month = date.month - 1;
startDate.config.max.date = date.date;
} else {
startDate.config.max.year = '';
startDate.config.max.month = '';
startDate.config.max.date = '';
startDate.config.max.year = '2099';
startDate.config.max.month = '12';
startDate.config.max.date = '31';
}
}
});
@ -154,6 +159,49 @@ $(function() {
});
});
(function ($) {
'use strict';
$.fn.toTop = function(opt) {
var elem = this;
var win = $(window);
var doc = $('html, body');
var options = $.extend({
autohide: true,
offset: 50,
speed: 500,
position: true,
right: 15,
bottom: 5
}, opt);
elem.css({
'cursor': 'pointer'
});
if (options.autohide) {
elem.css('display', 'none');
}
if (options.position) {
elem.css({
'position': 'fixed',
'right': options.right,
'bottom': options.bottom,
});
}
elem.click(function() {
doc.animate({
scrollTop: 0
}, options.speed);
});
win.scroll(function() {
var scrolling = win.scrollTop();
if (options.autohide) {
if (scrolling > options.offset) {
elem.fadeIn(options.speed);
} else elem.fadeOut(options.speed);
}
});
};
})(jQuery);
/** 刷新选项卡 */
var refreshItem = function(){
var topWindow = $(window.parent.document);

View File

@ -58,6 +58,7 @@ var table = {
showToggle: true,
showExport: false,
clickToSelect: false,
singleSelect: false,
mobileResponsive: true,
rememberSelected: false,
fixedColumns: false,
@ -72,6 +73,7 @@ var table = {
table.config[options.id] = options;
$.table.initEvent();
$('#' + options.id).bootstrapTable({
id: options.id,
url: options.url, // 请求后台的URL*
contentType: "application/x-www-form-urlencoded", // 编码类型
method: 'post', // 请求方式(*
@ -102,6 +104,7 @@ var table = {
showExport: options.showExport, // 是否支持导出文件
uniqueId: options.uniqueId, // 唯 一的标识符
clickToSelect: options.clickToSelect, // 是否启用点击选中行
singleSelect: options.singleSelect, // 是否单选checkbox
mobileResponsive: options.mobileResponsive, // 是否支持移动端适配
detailView: options.detailView, // 是否启用显示细节视图
onClickRow: options.onClickRow, // 点击某行触发的事件
@ -250,7 +253,27 @@ var table = {
table.options.onLoadSuccess(data);
}
// 浮动提示框特效
$("[data-toggle='tooltip']").tooltip();
$(".table [data-toggle='tooltip']").tooltip();
// 气泡弹出框特效
$('.table [data-toggle="popover"]').each(function() {
$(this).popover({ trigger: "manual", html: true, animation: false, container: "body", placement: "left"
}).on("mouseenter",
function() {
var _this = this;
$(this).popover("show");
$(".popover").on("mouseleave", function() {
$(_this).popover('hide');
});
}).on("mouseleave",
function() {
var _this = this;
setTimeout(function() {
if (!$(".popover:hover").length)
$(_this).popover("hide");
}, 100);
});
});
},
// 表格销毁
destroy: function (tableId) {
@ -273,10 +296,11 @@ var table = {
var _target = $.common.isEmpty(target) ? 'copy' : target;
if (_value.length > _length) {
_text = _value.substr(0, _length) + "...";
_value = _value.replace(/\'/g,"");
_value = _value.replace(/\'/g,"&apos;");
_value = _value.replace(/\"/g,"&quot;");
var actions = [];
actions.push($.common.sprintf('<input id="tooltip-show" style="opacity: 0;position: absolute;z-index:-1" type="text" value="%s"/>', _value));
actions.push($.common.sprintf("<a href='###' class='tooltip-show' data-toggle='tooltip' data-target='%s' title='%s'>%s</a>", _target, _value, _text));
actions.push($.common.sprintf('<a href="###" class="tooltip-show" data-toggle="tooltip" data-target="%s" title="%s">%s</a>', _target, _value, _text));
return actions.join('');
} else {
_text = _value;
@ -341,8 +365,12 @@ var table = {
table.set();
$.modal.confirm("确定导出所有" + table.options.modalName + "吗?", function() {
var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
var params = $("#" + table.options.id).bootstrapTable('getOptions');
var dataParam = $("#" + currentId).serializeArray();
dataParam.push({ "name": "orderByColumn", "value": params.sortName });
dataParam.push({ "name": "isAsc", "value": params.sortOrder });
$.modal.loading("正在导出数据,请稍后...");
$.post(table.options.exportUrl, $("#" + currentId).serializeArray(), function(result) {
$.post(table.options.exportUrl, dataParam, function(result) {
if (result.code == web_status.SUCCESS) {
window.location.href = ctx + "common/download?fileName=" + encodeURI(result.msg) + "&delete=" + true;
} else if (result.code == web_status.WARNING) {
@ -391,9 +419,7 @@ var table = {
}
var index = layer.load(2, {shade: false});
$.modal.disable();
var formData = new FormData();
formData.append("file", $('#file')[0].files[0]);
formData.append("updateSupport", $("input[name='updateSupport']").is(':checked'));
var formData = new FormData(layero.find('form')[0]);
$.ajax({
url: table.options.importUrl,
data: formData,
@ -526,7 +552,7 @@ var table = {
height: options.height, // 表格树的高度
expandColumn: options.expandColumn, // 在哪一列上面显示展开按钮
striped: options.striped, // 是否显示行间隔色
bordered: true, // 是否显示边框
bordered: false, // 是否显示边框
toolbar: '#' + options.toolbar, // 指定工作栏
showSearch: options.showSearch, // 是否显示检索信息
showRefresh: options.showRefresh, // 是否显示刷新按钮
@ -555,12 +581,15 @@ var table = {
return $.common.uniqueFn(rows);
},
// 请求获取数据后处理回调函数,校验异常状态提醒
responseHandler: function(data) {
if (data.code != undefined && data.code != 0) {
$.modal.alertWarning(data.msg);
responseHandler: function(res) {
if (typeof table.options.responseHandler == "function") {
table.options.responseHandler(res);
}
if (res.code != undefined && res.code != 0) {
$.modal.alertWarning(res.msg);
return [];
} else {
return data;
return res;
}
},
},
@ -577,6 +606,12 @@ var table = {
} else{
$("#" + tableId).bootstrapTable('refresh');
}
} else if (table.options.type == table_type.bootstrapTreeTable) {
if($.common.isEmpty(tableId)){
$("#" + table.options.id).bootstrapTreeTable('refresh', []);
} else{
$("#" + tableId).bootstrapTreeTable('refresh', []);
}
}
},
// 获取选中复选框项
@ -695,7 +730,7 @@ var table = {
// 弹出层指定宽度
open: function (title, url, width, height, callback) {
//如果是移动端,就使用自适应大小弹窗
if (navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)) {
if ($.common.isMobile()) {
width = 'auto';
height = 'auto';
}
@ -767,7 +802,7 @@ var table = {
// 弹出层全屏
openFull: function (title, url, width, height) {
//如果是移动端,就使用自适应大小弹窗
if (navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)) {
if ($.common.isMobile()) {
width = 'auto';
height = 'auto';
}
@ -880,7 +915,7 @@ var table = {
var _width = $.common.isEmpty(width) ? "800" : width;
var _height = $.common.isEmpty(height) ? ($(window).height() - 50) : height;
//如果是移动端,就使用自适应大小弹窗
if (navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)) {
if ($.common.isMobile()) {
_width = 'auto';
_height = 'auto';
}
@ -1089,7 +1124,9 @@ var table = {
} else if (result.code == web_status.SUCCESS && table.options.type == table_type.bootstrapTreeTable) {
$.modal.msgSuccess(result.msg);
$.treeTable.refresh();
} else if (result.code == web_status.WARNING) {
} else if (result.code == web_status.SUCCESS && table.option.type == undefined) {
$.modal.msgSuccess(result.msg)
} else if (result.code == web_status.WARNING) {
$.modal.alertWarning(result.msg)
} else {
$.modal.alertError(result.msg);
@ -1469,7 +1506,11 @@ var table = {
}  
}
return count;
}
},
// 判断移动端
isMobile: function () {
return navigator.userAgent.match(/(Android|iPhone|SymbianOS|Windows Phone|iPad|iPod)/i);
},
}
});
})(jQuery);

View File

@ -26,7 +26,7 @@ function login() {
data: {
"username": username,
"password": password,
"validateCode" : validateCode,
"validateCode": validateCode,
"rememberMe": rememberMe
},
success: function(r) {

View File

@ -0,0 +1,82 @@
$(function() {
validateRule();
$('.imgcode').click(function() {
var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
$(".imgcode").attr("src", url);
});
});
$.validator.setDefaults({
submitHandler: function() {
register();
}
});
function register() {
$.modal.loading($("#btnSubmit").data("loading"));
var username = $.common.trim($("input[name='username']").val());
var password = $.common.trim($("input[name='password']").val());
var validateCode = $("input[name='validateCode']").val();
$.ajax({
type: "post",
url: ctx + "register",
data: {
"loginName": username,
"password": password,
"validateCode": validateCode
},
success: function(r) {
if (r.code == 0) {
layer.alert("<font color='red'>恭喜你,您的账号 " + username + " 注册成功!</font>", {
icon: 1,
title: "系统提示"
},
function(index) {
//关闭弹窗
layer.close(index);
location.href = ctx + 'login';
});
} else {
$.modal.closeLoading();
$('.imgcode').click();
$(".code").val("");
$.modal.msg(r.msg);
}
}
});
}
function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> ";
$("#registerForm").validate({
rules: {
username: {
required: true,
minlength: 2
},
password: {
required: true,
minlength: 5
},
confirmPassword: {
required: true,
equalTo: "[name='password']"
}
},
messages: {
username: {
required: icon + "请输入您的用户名",
minlength: icon + "用户名不能小于2个字符"
},
password: {
required: icon + "请输入您的密码",
minlength: icon + "密码不能小于5个字符",
},
confirmPassword: {
required: icon + "请再次输入您的密码",
equalTo: icon + "两次密码输入不一致"
}
}
})
}

View File

@ -17,7 +17,7 @@
<h2>若依后台管理系统</h2>
<p>ruoyi是一个完全响应式基于Bootstrap3.3.6最新版本开发的扁平化主题她采用了主流的左右两栏式布局使用了Html5+CSS3等现代技术她提供了诸多的强大的可以重新组合的UI组件并集成了最新的jQuery版本(v2.1.1)当然也集成了很多功能强大用途广泛的就jQuery插件她可以用于所有的Web应用程序<b>网站管理后台</b><b>网站会员中心</b><b>CMS</b><b>CRM</b><b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
<p>
<b>当前版本:</b>v4.1.0
<b>当前版本:</b>v4.2.0
</p>
<p>
<span class="label label-warning">免费开源</span>
@ -56,7 +56,7 @@
<h3>你好,若依 </h3>
<p>H+是一个完全响应式基于Bootstrap3.3.6最新版本开发的扁平化主题她采用了主流的左右两栏式布局使用了Html5+CSS3等现代技术她提供了诸多的强大的可以重新组合的UI组件并集成了最新的jQuery版本(v2.1.1)当然也集成了很多功能强大用途广泛的就jQuery插件她可以用于所有的Web应用程序<b>网站管理后台</b><b>网站会员中心</b><b>CMS</b><b>CRM</b><b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。</p>
<p>
<b>当前版本:</b>v4.1.0
<b>当前版本:</b>v4.2.0
</p>
<p>
<span class="label label-warning">开源免费</span>

View File

@ -9,7 +9,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>用户名称:</label>
<label class="col-sm-4 control-label is-required">用户名称:</label>
<div class="col-sm-8">
<input name="userName" placeholder="请输入用户名称" class="form-control" type="text">
</div>
@ -17,7 +17,7 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>归属部门:</label>
<label class="col-sm-4 control-label is-required">归属部门:</label>
<div class="col-sm-8">
<div class="input-group">
<input name="deptName" type="text" placeholder="请选择归属部门" class="form-control">
@ -30,7 +30,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>手机号码:</label>
<label class="col-sm-4 control-label is-required">手机号码:</label>
<div class="col-sm-8">
<input name="phonenumber" placeholder="请输入手机号码" class="form-control" type="text">
</div>
@ -38,7 +38,7 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>邮箱:</label>
<label class="col-sm-4 control-label is-required">邮箱:</label>
<div class="col-sm-8">
<input name="email" class="form-control" type="text" placeholder="请输入邮箱">
</div>
@ -48,7 +48,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>登录账号:</label>
<label class="col-sm-4 control-label is-required">登录账号:</label>
<div class="col-sm-8">
<input name="loginName" placeholder="请输入登录账号" class="form-control" type="text">
</div>
@ -56,7 +56,7 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>登录密码:</label>
<label class="col-sm-4 control-label is-required">登录密码:</label>
<div class="col-sm-8">
<input name="password" placeholder="请输入登录密码" class="form-control" type="password">
</div>

View File

@ -13,7 +13,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label ">用户姓名:</label>
<label class="col-sm-3 control-label">用户姓名:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="userName" id="userName" required>
</div>

View File

@ -11,7 +11,7 @@
<div class="form-control-static" th:text="${user.userCode}"></div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label ">用户姓名:</label>
<label class="col-sm-3 control-label">用户姓名:</label>
<div class="col-sm-8">
<div class="form-control-static" th:text="${user.userName}"></div>
</div>

View File

@ -14,7 +14,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label ">用户姓名:</label>
<label class="col-sm-3 control-label">用户姓名:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="userName" id="userName" th:field="*{userName}" required>
</div>

View File

@ -77,12 +77,12 @@
});
initChildTable = function(index, row, $detail) {
var cur_table = $detail.html('<table style="table-layout:fixed"></table>').find('table');
$(cur_table).bootstrapTable({
var childTable = $detail.html('<table style="table-layout:fixed"></table>').find('table');
$(childTable).bootstrapTable({
url: prefix + "/list",
method: 'post',
sidePagination: "server",
contentType: "application/x-www-form-urlencoded", // 编码类型
contentType: "application/x-www-form-urlencoded",
queryParams : {
userName: '测试8'
},

View File

@ -97,19 +97,19 @@
<div class="select-list">
<ul>
<li>
<p style="width: 80px">商户编号:</p>
<label style="width: 80px">商户编号:</label>
<input type="text" name="userId"/>
</li>
<li>
<p style="width: 80px">订单号:</p>
<label style="width: 80px">订单号:</label>
<input type="text" name="orderNo"/>
</li>
<li>
<p style="width: 80px">日期:</p>
<label style="width: 80px">日期:</label>
<input type="text" class="time-input" placeholder="日期"/>
</li>
<li class="select-selectpicker">
<p style="width: 80px">状态:</p>
<label style="width: 80px">状态:</label>
<select class="selectpicker" data-none-selected-text="请选择" multiple>
<option value="">所有</option>
<option value="0">初始</option>
@ -119,7 +119,7 @@
</select>
</li>
<li>
<p style="width: 80px">供货商通道:</p>
<label style="width: 80px">供货商通道:</label>
<select>
<option value="">所有</option>
<option value="0">腾讯</option>
@ -128,7 +128,7 @@
</select>
</li>
<li>
<p style="width: 80px">来源:</p>
<label style="width: 80px">来源:</label>
<select>
<option value="">所有</option>
<option value="0">手机</option>
@ -137,7 +137,7 @@
</select>
</li>
<li>
<p style="width: 80px">运营商:</p>
<label style="width: 80px">运营商:</label>
<select>
<option value="">所有</option>
<option value="0">移动</option>
@ -146,7 +146,7 @@
</select>
</li>
<li class="select-time">
<p style="width: 80px">回调时间:</p>
<label style="width: 80px">回调时间:</label>
<input type="text" class="time-input" placeholder="开始时间"/>
<span>-</span>
<input type="text" class="time-input" placeholder="结束时间"/>

View File

@ -4,9 +4,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RuoYi - 404</title>
<link href="/css/bootstrap.min.css" rel="stylesheet"/>
<link href="/css/animate.css" rel="stylesheet"/>
<link href="/css/style.css" rel="stylesheet"/>
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
<link th:href="@{/css/style.css}" rel="stylesheet"/>
</head>
<body class="gray-bg">
<div class="middle-box text-center animated fadeInDown">
@ -14,8 +14,14 @@
<h3 class="font-bold">找不到网页!</h3>
<div class="error-desc">
对不起您正在寻找的页面不存在。尝试检查URL的错误然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。
<a href="javascript:top.document.location.href='/'" class="btn btn-primary m-t">主页</a>
<a href="javascript:index()" class="btn btn-primary m-t">主页</a>
</div>
</div>
<script th:inline="javascript">
var ctx = [[@{/}]];
function index() {
window.parent.frames.location.href = ctx + "index";
}
</script>
</body>
</html>

View File

@ -4,9 +4,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RuoYi - 500</title>
<link href="/css/bootstrap.min.css" rel="stylesheet"/>
<link href="/css/animate.css" rel="stylesheet"/>
<link href="/css/style.css" rel="stylesheet"/>
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
<link th:href="@{/css/style.css}" rel="stylesheet"/>
</head>
<body class="gray-bg">
<div class="middle-box text-center animated fadeInDown">
@ -15,8 +15,14 @@
<div class="error-desc">
服务器遇到意外事件,不允许完成请求。我们抱歉。您可以返回主页面。
<a href="javascript:top.document.location.href='/'" class="btn btn-primary m-t">主页</a>
<a href="javascript:index()" class="btn btn-primary m-t">主页</a>
</div>
</div>
<script th:inline="javascript">
var ctx = [[@{/}]];
function index() {
window.parent.frames.location.href = ctx + "index";
}
</script>
</body>
</html>

View File

@ -4,9 +4,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RuoYi - 403</title>
<link href="/css/bootstrap.min.css" rel="stylesheet"/>
<link href="/css/animate.css" rel="stylesheet"/>
<link href="/css/style.css" rel="stylesheet"/>
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
<link th:href="@{/css/style.css}" rel="stylesheet"/>
</head>
<body class="gray-bg">
<div class="middle-box text-center animated fadeInDown">

View File

@ -4,9 +4,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RuoYi - 403</title>
<link href="/css/bootstrap.min.css" rel="stylesheet"/>
<link href="/css/animate.css" rel="stylesheet"/>
<link href="/css/style.css" rel="stylesheet"/>
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
<link th:href="@{/css/style.css}" rel="stylesheet"/>
</head>
<body class="gray-bg">
<div class="middle-box text-center animated fadeInDown">
@ -15,8 +15,14 @@
<div class="error-desc">
对不起,您没有访问权限,请不要进行非法操作!您可以返回主页面
<a href="javascript:top.document.location.href='/'" class="btn btn-outline btn-primary btn-xs">返回主页</a>
<a href="javascript:index()" class="btn btn-outline btn-primary btn-xs">返回主页</a>
</div>
</div>
<script th:inline="javascript">
var ctx = [[@{/}]];
function index() {
window.parent.frames.location.href = ctx + "index";
}
</script>
</body>
</html>

View File

@ -2,6 +2,7 @@
<head th:fragment=header(title)>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="keywords" content="">
<meta name="description" content="">
<title th:text="${title}"></title>
@ -11,16 +12,17 @@
<!-- bootstrap-table 表格插件样式 -->
<link th:href="@{/ajax/libs/bootstrap-table/bootstrap-table.min.css}" rel="stylesheet"/>
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
<link th:href="@{/css/style.css}" rel="stylesheet"/>
<link th:href="@{/css/style.css?v=20200318}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css}" rel="stylesheet"/>
</head>
<!-- 通用JS -->
<div th:fragment="footer">
<a id="scroll-up" href="#" class="btn btn-sm display"><i class="fa fa-angle-double-up"></i></a>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/js/bootstrap.min.js}"></script>
<!-- bootstrap-table 表格插件 -->
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js?v=20191219}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/locale/bootstrap-table-zh-CN.min.js}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/extensions/mobile/bootstrap-table-mobile.js}"></script>
<script th:src="@{/ajax/libs/bootstrap-table/extensions/toolbar/bootstrap-table-toolbar.min.js}"></script>
@ -39,8 +41,8 @@
<script th:src="@{/ajax/libs/iCheck/icheck.min.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ajax/libs/layui/layui.js}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.1.0}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.1.0}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.2.0}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.2.0}"></script>
<script th:inline="javascript"> var ctx = [[@{/}]]; </script>
</div>
@ -74,7 +76,7 @@
<link th:href="@{/ajax/libs/datapicker/bootstrap-datetimepicker.min.css}" rel="stylesheet"/>
</div>
<div th:fragment="datetimepicker-js">
<script th:src="@{/ajax/libs//datapicker/bootstrap-datetimepicker.min.js}"></script>
<script th:src="@{/ajax/libs/datapicker/bootstrap-datetimepicker.min.js}"></script>
</div>
<!-- ui布局插件 -->

View File

@ -5,9 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit">
<title>若依系统首页</title>
<!--[if lt IE 9]>
<meta http-equiv="refresh" content="0;ie.html"/>
<![endif]-->
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link th:href="@{favicon.ico}" rel="stylesheet"/>
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link th:href="@{/css/jquery.contextMenu.min.css}" rel="stylesheet"/>
@ -15,7 +14,7 @@
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
<link th:href="@{/css/style.css}" rel="stylesheet"/>
<link th:href="@{/css/skins.css}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.1.0}" rel="stylesheet"/>
<link th:href="@{/ruoyi/css/ry-ui.css?v=4.2.0}" rel="stylesheet"/>
</head>
<body class="fixed-sidebar full-height-layout gray-bg" style="overflow: hidden">
<div id="wrapper">
@ -25,13 +24,13 @@
<div class="nav-close">
<i class="fa fa-times-circle"></i>
</div>
<a th:href="@{/index}">
<li class="logo hidden-xs">
<span class="logo-lg">RuoYi</span>
</li>
</a>
<div class="sidebar-collapse">
<ul class="nav" id="side-menu">
<a th:href="@{/index}">
<li class="logo">
<span class="logo-lg" >RuoYi</span>
</li>
</a>
<li>
<div class="user-panel">
<a class="menuItem" title="个人中心" th:href="@{/system/user/profile}">
@ -64,7 +63,13 @@
<a th:if="${#lists.isEmpty(cmenu.children)}" th:class="${cmenu.target == ''} ? |menuItem| : ${cmenu.target}" th:utext="${cmenu.menuName}" th:href="@{${cmenu.url}}">二级菜单</a>
<a th:if="${not #lists.isEmpty(cmenu.children)}" href="#">[[${cmenu.menuName}]]<span class="fa arrow"></span></a>
<ul th:if="${not #lists.isEmpty(cmenu.children)}" class="nav nav-third-level">
<li th:each="emenu : ${cmenu.children}"><a th:class="${emenu.target == ''} ? |menuItem| : ${emenu.target}" th:text="${emenu.menuName}" th:href="@{${emenu.url}}">三级菜单</a></li>
<li th:each="emenu : ${cmenu.children}">
<a th:if="${#lists.isEmpty(emenu.children)}" th:class="${emenu.target == ''} ? |menuItem| : ${emenu.target}" th:text="${emenu.menuName}" th:href="@{${emenu.url}}">三级菜单</a>
<a th:if="${not #lists.isEmpty(emenu.children)}" href="#">[[${emenu.menuName}]]<span class="fa arrow"></span></a>
<ul th:if="${not #lists.isEmpty(emenu.children)}" class="nav nav-four-level">
<li th:each="fmenu : ${emenu.children}"><a th:if="${#lists.isEmpty(fmenu.children)}" th:class="${fmenu.target == ''} ? |menuItem| : ${fmenu.target}" th:text="${fmenu.menuName}" th:href="@{${fmenu.url}}">四级菜单</a></li>
</ul>
</li>
</ul>
</li>
</ul>
@ -175,13 +180,13 @@
</a>
</div>
<ul class="nav navbar-top-links navbar-right welcome-message">
<li><a title="视频教程" href="http://doc.ruoyi.vip/ruoyi/document/spjc.html" target="_blank"><i class="fa fa-video-camera"></i> 视频教程</a></li>
<li><a title="视频教程" href="http://doc.ruoyi.vip/ruoyi/document/spjc.html" target="_blank"><i class="fa fa-video-camera"></i> 视频教程</a></li>
<li><a title="开发文档" href="http://doc.ruoyi.vip" target="_blank"><i class="fa fa-question-circle"></i> 开发文档</a></li>
<li><a title="全屏显示" href="javascript:void(0)" id="fullScreen"><i class="fa fa-arrows-alt"></i> 全屏显示</a></li>
<li class="dropdown user-menu">
<a href="javascript:void(0)" class="dropdown-toggle" data-hover="dropdown">
<img th:src="(${user.avatar} == '') ? @{/img/profile.jpg} : @{${user.avatar}}" class="user-image">
<span class="hidden-xs">[[${user.userName}]]</span>
<span class="hidden-xs">[[${#strings.defaultString(user.userName, '-')}]]</span>
</a>
<ul class="dropdown-menu">
<li class="mt5">
@ -241,22 +246,28 @@
<script th:src="@{/js/jquery.contextMenu.min.js}"></script>
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.1.0}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.1.0}"></script>
<script th:src="@{/ruoyi/js/ry-ui.js?v=4.2.0}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.2.0}"></script>
<script th:src="@{/ruoyi/index.js}"></script>
<script th:src="@{/ajax/libs/fullscreen/jquery.fullscreen.js}"></script>
<script th:inline="javascript">
var ctx = [[@{/}]];
// 皮肤缓存
var skin = storage.get("skin");
// history表示去掉地址的#)否则地址以"#"形式展示
var mode = "history";
// 历史访问路径缓存
var historyPath = storage.get("historyPath");
// 排除非左侧菜单链接
var excludesUrl = ["/system/user/profile"];
// 本地主题优先,未设置取系统配置
if($.common.isNotEmpty(skin)){
$("body").addClass(skin.split('|')[0]);
$("body").addClass(skin.split('|')[1]);
} else {
var sideTheme = [[${@config.getKey('sys.index.sideTheme')}]];
var skinName = [[${@config.getKey('sys.index.skinName')}]];
$("body").addClass(sideTheme);
$("body").addClass(skinName);
$("body").addClass([[${sideTheme}]]);
$("body").addClass([[${skinName}]]);
}
/* 用户管理-重置密码 */
@ -275,18 +286,27 @@ function switchSkin() {
})
}
// 排除非左侧菜单链接
var excludesUrl = ["/system/user/profile"];
/** 刷新时访问路径页签 */
function applyPath(url) {
$('a[href$="' + decodeURI(url) + '"]').click();
if($.inArray(url, excludesUrl)){
$('a[href$="' + url + '"]').parent("li").addClass("selected").parents("li").addClass("active").end().parents("ul").addClass("in");
}
}
$(function() {
var hash = location.hash;
if (hash !== '') {
var url = hash.substring(1, hash.length);
$('a[href$="' + url + '"]').click();
if($.inArray(url, excludesUrl)){
$('a[href$="' + url + '"]').parent("li").addClass("selected").parents("li").addClass("active").end().parents("ul").addClass("in");
}
}
if($.common.equals("history", mode) && window.performance.navigation.type == 1) {
var url = storage.get('publicPath');
if ($.common.isNotEmpty(url)) {
applyPath(url);
}
} else {
var hash = location.hash;
if ($.common.isNotEmpty(hash)) {
var url = hash.substring(1, hash.length);
applyPath(url);
}
}
});
</script>
</body>

View File

@ -3,26 +3,24 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>登录若依系统</title>
<meta name="description" content="若依后台管理框架">
<link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.css" th:href="@{/css/style.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.1.0}" rel="stylesheet"/>
<!--[if lt IE 9]>
<meta http-equiv="refresh" content="0;ie.html" />
<![endif]-->
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.2.0}" rel="stylesheet"/>
<!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="shortcut icon" href="../static/favicon.ico" th:href="@{favicon.ico}"/>
<style type="text/css">label.error { position:inherit; }</style>
<script>
if(window.top!==window.self){window.top.location=window.location};
if(window.top!==window.self){alert('未登录或登录超时。请重新登录');window.top.location=window.location};
</script>
</head>
<body class="signin">
<div class="signinpanel">
<div class="row">
<div class="col-sm-7">
@ -39,18 +37,18 @@
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Thymeleaf</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Bootstrap</li>
</ul>
<strong>还没有账号? <a href="#">立即注册&raquo;</a></strong>
<strong th:if="${@config.getKey('sys.account.registerUser')}">还没有账号? <a th:href="@{/register}">立即注册&raquo;</a></strong>
</div>
</div>
<div class="col-sm-5">
<form id="signupForm">
<form id="signupForm" autocomplete="off">
<h4 class="no-margins">登录:</h4>
<p class="m-t-md">你若不离不弃,我必生死相依</p>
<input type="text" name="username" class="form-control uname" placeholder="用户名" value="admin" />
<input type="password" name="password" class="form-control pword" placeholder="密码" value="admin123" />
<div class="row m-t" th:if="${captchaEnabled==true}">
<div class="col-xs-6">
<input type="text" name="validateCode" class="form-control code" placeholder="验证码" maxlength="5" autocomplete="off">
<input type="text" name="validateCode" class="form-control code" placeholder="验证码" maxlength="5" />
</div>
<div class="col-xs-6">
<a href="javascript:void(0);" title="点击更换验证码">
@ -80,7 +78,7 @@
<script src="../static/ajax/libs/validate/messages_zh.min.js" th:src="@{/ajax/libs/validate/messages_zh.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.1.0}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.2.0}"></script>
<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
</body>
</html>

View File

@ -17,11 +17,9 @@
<div class="col-sm-12">
<blockquote class="text-warning" style="font-size:14px">
领取阿里云通用云产品1888优惠券
<br><a target="_blank" href="https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof">https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof</a><br>
<br><a target="_blank" href="https://www.aliyun.com/minisite/goods?userCode=brki8iof">https://www.aliyun.com/minisite/goods?userCode=brki8iof</a><br>
领取腾讯云通用云产品2860优惠券
<br><a target="_blank" href="https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console">https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console</a><br>
阿里云Hi拼购 限量爆款 低至199元/年
<br><a target="_blank" href="https://www.aliyun.com/acts/hi-group-buying?userCode=brki8iof">https://www.aliyun.com/acts/hi-group-buying?userCode=brki8iof</a>
<h4 class="text-danger">云产品通用红包,可叠加官网常规优惠使用。(仅限新用户)</h4>
</blockquote>
@ -81,7 +79,7 @@
<div class="ibox-content">
<p><i class="fa fa-send-o"></i> 官网:<a href="http://www.ruoyi.vip" target="_blank">http://www.ruoyi.vip</a>
</p>
<p><i class="fa fa-qq"></i> QQ群<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <s>满1145125</s> <a href="https://jq.qq.com/?_wv=1027&k=5IdFWW8" target="_blank">86752435</a>
<p><i class="fa fa-qq"></i> QQ群<s>满1389287</s> <s>满1679294</s> <s>满1529866</s> <s>满1772718</s> <s>满1366522</s> <s>满1382251</s> <s>满1145125</s> <s>满86752435</s> <s>满134072510</s> <s>满210336300</s> <a href="https://jq.qq.com/?_wv=1027&k=5omzbKc" target="_blank">339522636</a>
</p>
<p><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a>
</p>
@ -98,13 +96,78 @@
<div class="ibox-content no-padding">
<div class="panel-body">
<div class="panel-group" id="version">
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v42">v4.2.0</a><code class="pull-right">2020.03.23</code>
</h5>
</div>
<div id="v42" class="panel-collapse collapse in">
<div class="panel-body">
<ol>
<li>用户管理添加分配角色页面</li>
<li>定时任务添加调度日志按钮</li>
<li>新增是否开启用户注册功能</li>
<li>新增页面滚动显示返回顶部按钮</li>
<li>用户&角色&任务添加更多操作按钮</li>
<li>iframe框架页会话过期弹出超时提示</li>
<li>移动端登录不显示左侧菜单</li>
<li>侧边栏添加一套深蓝色主题</li>
<li>首页logo固定不随菜单滚动</li>
<li>支持mode配置history表示去掉地址栏的#</li>
<li>任务分组字典翻译(调度日志详细)</li>
<li>字典管理添加缓存读取</li>
<li>字典数据列表标签显示样式</li>
<li>参数管理支持缓存操作</li>
<li>日期控件清空结束时间设置开始默认值为2099-12-31</li>
<li>表格树添加获取数据后响应回调处理</li>
<li>批量替换表前缀调整</li>
<li>支持表格导入模板的弹窗表单加入其它输入控件</li>
<li>表单重置刷新表格树</li>
<li>新增支持导出数据字段排序</li>
<li>新增表格参数是否单选checkbox</li>
<li>druid未授权不允许访问</li>
<li>表格树父节点兼容0,'0','',null</li>
<li>表单必填的项添加星号</li>
<li>修复select2不显示校验错误信息</li>
<li>添加自定义HTML过滤器</li>
<li>修复多数据源下开关关闭出现异常问题</li>
<li>修复翻页记住选择项数据问题</li>
<li>用户邮箱长度限制20</li>
<li>修改错误页面返回主页出现嵌套问题</li>
<li>表格浮动提示单双引号转义</li>
<li>支持配置四级菜单</li>
<li>升级shiro到最新版1.4.2 阻止rememberMe漏洞攻击</li>
<li>升级summernote到最新版本v0.8.12</li>
<li>导入Excel根据dateFormat属性格式处理</li>
<li>修复War部署无法正常shutdown,ehcache内存泄漏</li>
<li>修复代码生成短字段无法识别问题</li>
<li>修复serviceImpl模版修改方法判断日期错误</li>
<li>代码生成模板增加导出功能日志记录</li>
<li>代码生成唯一编号调整为tableId</li>
<li>代码生成查询时忽略大小写</li>
<li>代码生成支持翻页记住选中</li>
<li>代码生成表注释未填写也允许导入</li>
<li>Global全局配置类修改为注解防止多环境配置下读取问题</li>
<li>修复多表格情况下firstLoad只对第一个表格生效</li>
<li>处理Maven打包出现警告问题</li>
<li>默认主题样式,防止网速慢情况下出现空白</li>
<li>修复文件上传多级目录识别问题</li>
<li>锚链接解码url防止中文导致页面不能加载问题</li>
<li>修复右键Tab页刷新事件重复请求问题</li>
<li>角色禁用&菜单隐藏不查询权限</li>
<li>其他细节优化</li>
</ol>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#version" href="#v41">v4.1.0</a><code class="pull-right">2019.10.22</code>
</h5>
</div>
<div id="v41" class="panel-collapse collapse in">
<div id="v41" class="panel-collapse collapse">
<div class="panel-body">
<ol>
<li>支持多表格实例操作</li>
@ -144,7 +207,7 @@
</ol>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
@ -205,8 +268,8 @@
<li>其他细节优化</li>
</ol>
</div>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">

View File

@ -155,8 +155,9 @@
}
function resetPre() {
$.form.reset();
$("#operlog-form")[0].reset();
$("#businessTypes").selectpicker('refresh');
$.table.search('operlog-form', 'bootstrap-table');
}
</script>
</body>

View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>注册若依系统</title>
<meta name="description" content="若依后台管理框架">
<link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.css" th:href="@{/css/style.css}" rel="stylesheet"/>
<link href="../static/css/login.min.css" th:href="@{/css/login.min.css}" rel="stylesheet"/>
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=4.2.0}" rel="stylesheet"/>
<!-- 360浏览器急速模式 -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="shortcut icon" href="../static/favicon.ico" th:href="@{favicon.ico}"/>
<style type="text/css">label.error { position:inherit; }</style>
</head>
<body class="signin">
<div class="signinpanel">
<div class="row">
<div class="col-sm-7">
<div class="signin-info">
<div class="logopanel m-b">
<h1><img alt="[ 若依 ]" src="../static/ruoyi.png" th:src="@{/ruoyi.png}"></h1>
</div>
<div class="m-b"></div>
<h4>欢迎使用 <strong>若依 后台管理系统</strong></h4>
<ul class="m-b">
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> SpringBoot</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Mybatis</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Shiro</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Thymeleaf</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> Bootstrap</li>
</ul>
<strong>已经注册过? <a th:href="@{/login}">直接登录&raquo;</a></strong>
</div>
</div>
<div class="col-sm-5">
<form id="registerForm" autocomplete="off">
<h4 class="no-margins">注册:</h4>
<p class="m-t-md">你若不离不弃,我必生死相依</p>
<input type="text" name="username" class="form-control uname" placeholder="用户名" maxlength="20" />
<input type="password" name="password" class="form-control pword" placeholder="密码" maxlength="20" />
<input type="password" name="confirmPassword" class="form-control pword" placeholder="确认密码" maxlength="20" />
<div class="row m-t" th:if="${captchaEnabled==true}">
<div class="col-xs-6">
<input type="text" name="validateCode" class="form-control code" placeholder="验证码" maxlength="5" >
</div>
<div class="col-xs-6">
<a href="javascript:void(0);" title="点击更换验证码">
<img th:src="@{captcha/captchaImage(type=${captchaType})}" class="imgcode" width="85%"/>
</a>
</div>
</div>
<div class="checkbox-custom" th:classappend="${captchaEnabled==false} ? 'm-t'">
<input type="checkbox" id="acceptTerm" name="acceptTerm"> <label for="acceptTerm">我已阅读并同意</label>
<a href="https://gitee.com/y_project/RuoYi/blob/master/README.md" target="_blank">使用条款</a>
</div>
<button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证注册,请稍后...">注册</button>
</form>
</div>
</div>
<div class="signup-footer">
<div class="pull-left">
&copy; 2019 All Rights Reserved. RuoYi <br>
</div>
</div>
</div>
<script th:inline="javascript"> var ctx = [[@{/}]]; var captchaType = [[${captchaType}]]; </script>
<!-- 全局js -->
<script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
<script src="../static/js/bootstrap.min.js" th:src="@{/js/bootstrap.min.js}"></script>
<!-- 验证插件 -->
<script src="../static/ajax/libs/validate/jquery.validate.min.js" th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
<script src="../static/ajax/libs/validate/messages_zh.min.js" th:src="@{/ajax/libs/validate/messages_zh.min.js}"></script>
<script src="../static/ajax/libs/layer/layer.min.js" th:src="@{/ajax/libs/layer/layer.min.js}"></script>
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=4.2.0}"></script>
<script src="../static/ruoyi/register.js" th:src="@{/ruoyi/register.js}"></script>
</body>
</html>

View File

@ -118,16 +118,35 @@
</a>
<p class="text-center">黄灰</p>
</li>
<li style="float:left; width: 33.33333%; padding: 5px;">
<a href="javascript:" data-skin="skin-blue|theme-blue" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
<span style="width: 20%; float: left; height: 13px; background: #367fa9"></span>
<span style="width: 80%; float: left; height: 13px; background: #3c8dbc"></span>
<span style="width: 20%; float: left; height: 30px; background: rgba(15,41,80,1)"></span>
<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
</a>
<p class="text-center">蓝浅(新)</p>
</li>
<li style="float:left; width: 33.33333%; padding: 5px;">
<a href="javascript:" data-skin="skin-green|theme-blue" style="display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4)" class="clearfix full-opacity-hover">
<span style="width: 20%; float: left; height: 13px; background: #008d4c"></span>
<span style="width: 80%; float: left; height: 13px; background: #00a65a"></span>
<span style="width: 20%; float: left; height: 30px; background: rgba(15,41,80,1)"></span>
<span style="width: 80%; float: left; height: 30px; background: #f4f5f7"></span>
</a>
<p class="text-center">绿浅(新)</p>
</li>
</ul>
</body>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.1.0}"></script>
<script th:src="@{/ruoyi/js/common.js?v=4.2.0}"></script>
<script type="text/javascript">
//皮肤样式列表
var skins = ["skin-blue", "skin-green", "skin-purple", "skin-red", "skin-yellow"];
// 主题样式列表
var themes = ["theme-dark", "theme-light"];
var themes = ["theme-dark", "theme-light", "theme-blue"];
$("[data-skin]").on('click',
function(e) {

View File

@ -7,19 +7,19 @@
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-config-add" name="form-config-add">
<div class="form-group">
<label class="col-sm-3 control-label">参数名称:</label>
<label class="col-sm-3 control-label is-required">参数名称:</label>
<div class="col-sm-8">
<input id="configName" name="configName" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">参数键名:</label>
<label class="col-sm-3 control-label is-required">参数键名:</label>
<div class="col-sm-8">
<input id="configKey" name="configKey" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">参数键值:</label>
<label class="col-sm-3 control-label is-required">参数键值:</label>
<div class="col-sm-8">
<input id="configValue" name="configValue" class="form-control" type="text" required>
</div>

View File

@ -50,6 +50,9 @@
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:config:export">
<i class="fa fa-download"></i> 导出
</a>
<a class="btn btn-danger" onclick="clearCache()" shiro:hasPermission="system:config:remove">
<i class="fa fa-refresh"></i> 清理缓存
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
@ -131,6 +134,11 @@
};
$.table.init(options);
});
/** 清理参数缓存 */
function clearCache() {
$.operate.get(prefix + "/clearCache");
}
</script>
</body>
</html>

View File

@ -8,19 +8,19 @@
<form class="form-horizontal m" id="form-config-edit" th:object="${config}">
<input id="configId" name="configId" th:field="*{configId}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">参数名称:</label>
<label class="col-sm-3 control-label is-required">参数名称:</label>
<div class="col-sm-8">
<input id="configName" name="configName" th:field="*{configName}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">参数键名:</label>
<label class="col-sm-3 control-label is-required">参数键名:</label>
<div class="col-sm-8">
<input id="configKey" name="configKey" th:field="*{configKey}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">参数键值:</label>
<label class="col-sm-3 control-label is-required">参数键值:</label>
<div class="col-sm-8">
<input id="configValue" name="configValue" th:field="*{configValue}" class="form-control" type="text" required>
</div>

View File

@ -8,7 +8,7 @@
<form class="form-horizontal m" id="form-dept-add">
<input id="treeId" name="parentId" type="hidden" th:value="${dept.deptId}" />
<div class="form-group">
<label class="col-sm-3 control-label ">上级部门:</label>
<label class="col-sm-3 control-label">上级部门:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="text" onclick="selectDeptTree()" id="treeName" readonly="true" th:value="${dept.deptName}">
@ -17,13 +17,13 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">部门名称:</label>
<label class="col-sm-3 control-label is-required">部门名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="deptName" id="deptName" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">显示排序:</label>
<label class="col-sm-3 control-label is-required">显示排序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="orderNum" required>
</div>

View File

@ -9,7 +9,7 @@
<input name="deptId" type="hidden" th:field="*{deptId}" />
<input id="treeId" name="parentId" type="hidden" th:field="*{parentId}" />
<div class="form-group">
<label class="col-sm-3 control-label ">上级部门:</label>
<label class="col-sm-3 control-label">上级部门:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="text" id="treeName" onclick="selectDeptTree()" readonly="true" th:field="*{parentName}">
@ -18,13 +18,13 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">部门名称:</label>
<label class="col-sm-3 control-label is-required">部门名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="deptName" th:field="*{deptName}" id="deptName" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">显示排序:</label>
<label class="col-sm-3 control-label is-required">显示排序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="orderNum" th:field="*{orderNum}" required>
</div>

View File

@ -7,13 +7,13 @@
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-dict-add">
<div class="form-group">
<label class="col-sm-3 control-label ">字典标签:</label>
<label class="col-sm-3 control-label is-required">字典标签:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictLabel" id="dictLabel" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label ">字典键值:</label>
<label class="col-sm-3 control-label is-required">字典键值:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictValue" id="dictValue" required>
</div>
@ -31,7 +31,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">字典排序:</label>
<label class="col-sm-3 control-label is-required">字典排序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictSort" required>
</div>

View File

@ -82,7 +82,11 @@
},
{
field: 'dictLabel',
title: '字典标签'
title: '字典标签',
formatter: function(value, row, index) {
var listClass = $.common.equals("default", row.listClass) || $.common.isEmpty(row.listClass) ? "" : "badge badge-" + row.listClass;
return $.common.sprintf("<span class='%s'>%s</span>", listClass, value);
}
},
{
field: 'dictValue',

View File

@ -8,13 +8,13 @@
<form class="form-horizontal m" id="form-dict-edit" th:object="${dict}">
<input name="dictCode" type="hidden" th:field="*{dictCode}" />
<div class="form-group">
<label class="col-sm-3 control-label ">字典标签:</label>
<label class="col-sm-3 control-label is-required">字典标签:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictLabel" id="dictLabel" th:field="*{dictLabel}" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label ">字典键值:</label>
<label class="col-sm-3 control-label is-required">字典键值:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictValue" id="dictValue" th:field="*{dictValue}" required>
</div>
@ -32,7 +32,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">字典排序:</label>
<label class="col-sm-3 control-label is-required">字典排序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictSort" th:field="*{dictSort}" required>
</div>

View File

@ -7,13 +7,13 @@
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-dict-add">
<div class="form-group">
<label class="col-sm-3 control-label ">字典名称:</label>
<label class="col-sm-3 control-label is-required">字典名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictName" id="dictName" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">字典类型:</label>
<label class="col-sm-3 control-label is-required">字典类型:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictType" id="dictType" required>
</div>

View File

@ -8,13 +8,13 @@
<form class="form-horizontal m" id="form-dict-edit" th:object="${dict}">
<input id="dictId" name="dictId" type="hidden" th:field="*{dictId}" />
<div class="form-group">
<label class="col-sm-3 control-label ">字典名称:</label>
<label class="col-sm-3 control-label is-required">字典名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictName" id="dictName" th:field="*{dictName}" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">字典类型:</label>
<label class="col-sm-3 control-label is-required">字典类型:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="dictType" id="dictType" th:field="*{dictType}" required>
</div>

View File

@ -50,6 +50,9 @@
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:dict:export">
<i class="fa fa-download"></i> 导出
</a>
<a class="btn btn-danger" onclick="clearCache()" shiro:hasPermission="system:dict:remove">
<i class="fa fa-refresh"></i> 清理缓存
</a>
</div>
<div class="col-sm-12 select-table table-striped">
@ -105,7 +108,10 @@
},
{
field: 'remark',
title: '备注'
title: '备注',
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
field: 'createTime',
@ -132,6 +138,11 @@
var url = prefix + '/detail/' + dictId;
$.modal.openTab("字典数据", url);
}
/** 清理字典缓存 */
function clearCache() {
$.operate.get(prefix + "/clearCache");
}
</script>
</body>
</html>

View File

@ -8,7 +8,7 @@
<form class="form-horizontal m" id="form-menu-add">
<input id="treeId" name="parentId" type="hidden" th:value="${menu.menuId}" />
<div class="form-group">
<label class="col-sm-3 control-label ">上级菜单:</label>
<label class="col-sm-3 control-label">上级菜单:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="text" onclick="selectMenuTree()" id="treeName" readonly="true" th:value="${menu.menuName}">
@ -17,7 +17,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">菜单类型:</label>
<label class="col-sm-3 control-label is-required">菜单类型:</label>
<div class="col-sm-8">
<label class="radio-box"> <input type="radio" name="menuType" value="M" /> 目录 </label>
<label class="radio-box"> <input type="radio" name="menuType" value="C" /> 菜单 </label>
@ -25,7 +25,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">菜单名称:</label>
<label class="col-sm-3 control-label is-required">菜单名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="menuName" id="menuName" required>
</div>
@ -53,7 +53,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">显示排序:</label>
<label class="col-sm-3 control-label is-required">显示排序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="orderNum" required>
</div>

View File

@ -9,7 +9,7 @@
<input name="menuId" type="hidden" th:field="*{menuId}" />
<input id="treeId" name="parentId" type="hidden" th:field="*{parentId}" />
<div class="form-group">
<label class="col-sm-3 control-label ">上级菜单:</label>
<label class="col-sm-3 control-label">上级菜单:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="text" onclick="selectMenuTree()" id="treeName" readonly="true" th:value="${menu.parentName == null ? '无' : menu.parentName}">
@ -18,7 +18,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">菜单类型:</label>
<label class="col-sm-3 control-label is-required">菜单类型:</label>
<div class="col-sm-8">
<label class="radio-box"> <input type="radio" th:field="*{menuType}" name="menuType" value="M" /> 目录 </label>
<label class="radio-box"> <input type="radio" th:field="*{menuType}" name="menuType" value="C" /> 菜单 </label>
@ -26,7 +26,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">菜单名称:</label>
<label class="col-sm-3 control-label is-required">菜单名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="menuName" id="menuName" th:field="*{menuName}" required>
</div>
@ -54,7 +54,7 @@
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">显示排序:</label>
<label class="col-sm-3 control-label is-required">显示排序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="orderNum" th:field="*{orderNum}" required>
</div>

View File

@ -91,7 +91,10 @@
field: 'url',
title: '请求地址',
width: '15%',
align: "left"
align: "left",
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
title: '类型',
@ -127,6 +130,9 @@
title: '权限标识',
width: '15%',
align: "left",
formatter: function(value, row, index) {
return $.table.tooltip(value);
}
},
{
title: '操作',

View File

@ -8,7 +8,7 @@
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-notice-add">
<div class="form-group">
<label class="col-sm-2 control-label">公告标题:</label>
<label class="col-sm-2 control-label is-required">公告标题:</label>
<div class="col-sm-10">
<input id="noticeTitle" name="noticeTitle" class="form-control" type="text" required>
</div>

View File

@ -9,7 +9,7 @@
<form class="form-horizontal m" id="form-notice-edit" th:object="${notice}">
<input id="noticeId" name="noticeId" th:field="*{noticeId}" type="hidden">
<div class="form-group">
<label class="col-sm-2 control-label">公告标题:</label>
<label class="col-sm-2 control-label is-required">公告标题:</label>
<div class="col-sm-10">
<input id="noticeTitle" name="noticeTitle" th:field="*{noticeTitle}" class="form-control" type="text" required>
</div>

View File

@ -7,19 +7,19 @@
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-post-add">
<div class="form-group">
<label class="col-sm-3 control-label">岗位名称:</label>
<label class="col-sm-3 control-label is-required">岗位名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="postName" id="postName" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label ">岗位编码:</label>
<label class="col-sm-3 control-label is-required">岗位编码:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="postCode" id="postCode" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">显示顺序:</label>
<label class="col-sm-3 control-label is-required">显示顺序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="postSort" id="postSort" required>
</div>

View File

@ -8,19 +8,19 @@
<form class="form-horizontal m" id="form-post-edit" th:object="${post}">
<input id="postId" name="postId" type="hidden" th:field="*{postId}"/>
<div class="form-group">
<label class="col-sm-3 control-label">岗位名称:</label>
<label class="col-sm-3 control-label is-required">岗位名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="postName" id="postName" th:field="*{postName}" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label ">岗位编码:</label>
<label class="col-sm-3 control-label is-required">岗位编码:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="postCode" id="postCode" th:field="*{postCode}" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">显示顺序:</label>
<label class="col-sm-3 control-label is-required">显示顺序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="postSort" id="postSort" th:field="*{postSort}" required>
</div>

View File

@ -8,20 +8,20 @@
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-role-add">
<div class="form-group">
<label class="col-sm-3 control-label ">角色名称:</label>
<label class="col-sm-3 control-label is-required">角色名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="roleName" id="roleName" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">权限字符:</label>
<label class="col-sm-3 control-label is-required">权限字符:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="roleKey" id="roleKey" required>
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 控制器中定义的权限字符,如:@RequiresRoles("")</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">显示顺序:</label>
<label class="col-sm-3 control-label is-required">显示顺序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="roleSort" id="roleSort" required>
</div>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('角色用户分配')" />
<th:block th:include="include :: header('角色分配用户')" />
</head>
<body class="gray-bg">
<div class="container-div">

View File

@ -9,7 +9,7 @@
<form class="form-horizontal m" id="form-role-edit" th:object="${role}">
<input id="roleId" name="roleId" type="hidden" th:field="*{roleId}"/>
<div class="form-group">
<label class="col-sm-3 control-label ">角色名称:</label>
<label class="col-sm-3 control-label">角色名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="roleName" id="roleName" th:field="*{roleName}" readonly="true"/>
</div>

View File

@ -9,20 +9,20 @@
<form class="form-horizontal m" id="form-role-edit" th:object="${role}">
<input id="roleId" name="roleId" type="hidden" th:field="*{roleId}"/>
<div class="form-group">
<label class="col-sm-3 control-label ">角色名称:</label>
<label class="col-sm-3 control-label is-required">角色名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="roleName" id="roleName" th:field="*{roleName}" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">权限字符:</label>
<label class="col-sm-3 control-label is-required">权限字符:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="roleKey" id="roleKey" th:field="*{roleKey}" required>
<span class="help-block m-b-none"><i class="fa fa-info-circle"></i> 控制器中定义的权限字符,如:@RequiresRoles("")</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">显示顺序:</label>
<label class="col-sm-3 control-label is-required">显示顺序:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="roleSort" id="roleSort" th:field="*{roleSort}" required>
</div>

View File

@ -114,9 +114,11 @@
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.roleId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-primary btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="authDataScope(\'' + row.roleId + '\')"><i class="fa fa-check-square-o"></i>数据权限</a> ');
actions.push('<a class="btn btn-info btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="authUser(\'' + row.roleId + '\')"><i class="fa fa-user"></i>分配用户</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.roleId + '\')"><i class="fa fa-remove"></i>删除</a> ');
var more = [];
more.push("<a class='btn btn-default btn-xs " + editFlag + "' href='javascript:void(0)' onclick='authDataScope(" + row.roleId + ")'><i class='fa fa-check-square-o'></i>数据权限</a> ");
more.push("<a class='btn btn-default btn-xs " + editFlag + "' href='javascript:void(0)' onclick='authUser(" + row.roleId + ")'><i class='fa fa-user'></i>分配用户</a>");
actions.push('<a class="btn btn-info btn-xs" role="button" data-toggle="popover" data-content="' + more.join('') + '"><i class="fa fa-chevron-circle-right"></i>更多操作</a>');
return actions.join('');
}
}]

View File

@ -12,7 +12,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>用户名称:</label>
<label class="col-sm-4 control-label is-required">用户名称:</label>
<div class="col-sm-8">
<input name="userName" placeholder="请输入用户名称" class="form-control" type="text" maxlength="30" required>
</div>
@ -20,7 +20,7 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>归属部门:</label>
<label class="col-sm-4 control-label is-required">归属部门:</label>
<div class="col-sm-8">
<div class="input-group">
<input name="deptName" onclick="selectDeptTree()" id="treeName" type="text" placeholder="请选择归属部门" class="form-control" required>
@ -33,7 +33,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>手机号码:</label>
<label class="col-sm-4 control-label is-required">手机号码:</label>
<div class="col-sm-8">
<input id="phonenumber" name="phonenumber" placeholder="请输入手机号码" class="form-control" type="text" maxlength="11" required>
</div>
@ -41,9 +41,9 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>邮箱:</label>
<label class="col-sm-4 control-label is-required">邮箱:</label>
<div class="col-sm-8">
<input id="email" name="email" class="form-control email" type="text" maxlength="50" placeholder="请输入邮箱" required>
<input id="email" name="email" class="form-control email" type="text" maxlength="20" placeholder="请输入邮箱" required>
</div>
</div>
</div>
@ -51,7 +51,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>登录账号:</label>
<label class="col-sm-4 control-label is-required">登录账号:</label>
<div class="col-sm-8">
<input id="loginName" name="loginName" placeholder="请输入登录账号" class="form-control" type="text" maxlength="30" required>
</div>
@ -59,7 +59,7 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>登录密码:</label>
<label class="col-sm-4 control-label is-required">登录密码:</label>
<div class="col-sm-8">
<input name="password" placeholder="请输入登录密码" class="form-control" type="password" th:value="${@config.getKey('sys.user.initPassword')}" required>
</div>
@ -248,7 +248,7 @@
$(function() {
$('#post').select2({
placeholder:"请选择岗位",
placeholder: "请选择岗位",
allowClear: true
});
})

View File

@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('用户分配角色')" />
</head>
<body>
<div class="main-content">
<form id="form-user-add" class="form-horizontal">
<input type="hidden" id="userId" name="userId" th:value="${user.userId}">
<h4 class="form-header h4">基本信息</h4>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">用户名称:</label>
<div class="col-sm-8">
<input name="userName" class="form-control" type="text" disabled th:value="${user.userName}">
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">登录账号:</label>
<div class="col-sm-8">
<input name="loginName" class="form-control" type="text" disabled th:value="${user.loginName}">
</div>
</div>
</div>
</div>
<h4 class="form-header h4">分配角色</h4>
<div class="row">
<div class="col-sm-12">
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
</form>
</div>
<div class="row">
<div class="col-sm-offset-5 col-sm-10">
<button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
<button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭 </button>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "system/user/authRole";
var userRoles = [[${userRoles}]]
$(function() {
var options = {
url: ctx + "system/role/list",
sortName: "roleSort",
showSearch: false,
showRefresh: false,
showToggle: false,
showColumns: false,
clickToSelect: true,
columns: [{
checkbox: true,
formatter:function (value, row, index) {
for (var i = 0; i < userRoles.length; i++) {
if (userRoles[i].roleId == row.roleId) {
return { checked: true };
}
}
return { checked: false };
}
},
{
field: 'roleId',
title: '角色编号'
},
{
field: 'roleName',
title: '角色名称',
sortable: true
},
{
field: 'roleKey',
title: '权限字符',
sortable: true
},
{
field: 'createTime',
title: '创建时间',
sortable: true
}]
};
$.table.init(options);
});
/* 添加角色-提交 */
function submitHandler(index, layero){
var rows = $.table.selectFirstColumns();
var data = { "userId": $("#userId").val(), "roleIds": rows.join() };
$.operate.saveTab(prefix + "/insertAuthRole", data);
}
</script>
</body>
</html>

View File

@ -13,7 +13,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>用户名称:</label>
<label class="col-sm-4 control-label is-required">用户名称:</label>
<div class="col-sm-8">
<input name="userName" placeholder="请输入用户名称" class="form-control" type="text" maxlength="30" th:field="*{userName}" required>
</div>
@ -21,7 +21,7 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>归属部门:</label>
<label class="col-sm-4 control-label is-required">归属部门:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="text" name="deptName" onclick="selectDeptTree()" id="treeName" th:field="*{dept.deptName}" required>
@ -34,7 +34,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>手机号码:</label>
<label class="col-sm-4 control-label is-required">手机号码:</label>
<div class="col-sm-8">
<input name="phonenumber" placeholder="请输入手机号码" class="form-control" type="text" maxlength="11" th:field="*{phonenumber}" required>
</div>
@ -42,9 +42,9 @@
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>邮箱:</label>
<label class="col-sm-4 control-label is-required">邮箱:</label>
<div class="col-sm-8">
<input name="email" class="form-control email" type="text" maxlength="50" placeholder="请输入邮箱" th:field="*{email}" required>
<input name="email" class="form-control email" type="text" maxlength="20" placeholder="请输入邮箱" th:field="*{email}" required>
</div>
</div>
</div>
@ -52,7 +52,7 @@
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label"><span style="color: red; ">*</span>登录账号:</label>
<label class="col-sm-4 control-label is-required">登录账号:</label>
<div class="col-sm-8">
<input class="form-control" type="text" readonly="true" th:field="*{loginName}"/>
</div>
@ -219,7 +219,7 @@
$(function() {
$('#post').select2({
placeholder:"请选择岗位",
placeholder: "请选择岗位",
allowClear: true
});
})

View File

@ -27,7 +27,7 @@
<b class="font-noraml">手机号码:</b>
<p class="pull-right">[[${user.phonenumber}]]</p>
</li>
<li class="list-group-item"><i class="fa fa-group"></i>
<li class="list-group-item" th:if="${user.dept?.deptName != null}"><i class="fa fa-group"></i>
<b class="font-noraml">所属部门:</b>
<p class="pull-right" >[[${user.dept?.deptName}]] / [[${#strings.defaultString(postGroup,'无岗位')}]]</p>
</li>

View File

@ -8,7 +8,7 @@
<form class="form-horizontal m" id="form-user-resetPwd">
<input name="userId" type="hidden" th:value="${user.userId}" />
<div class="form-group">
<label class="col-sm-3 control-label ">登录名称:</label>
<label class="col-sm-3 control-label">登录名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" readonly="true" name="loginName" th:value="${user.loginName}"/>
</div>

View File

@ -8,7 +8,7 @@
<form class="form-horizontal m" id="form-user-resetPwd">
<input name="userId" type="hidden" th:value="${user.userId}" />
<div class="form-group">
<label class="col-sm-3 control-label ">登录名称:</label>
<label class="col-sm-3 control-label">登录名称:</label>
<div class="col-sm-8">
<input class="form-control" type="text" readonly="true" name="loginName" th:value="${user.loginName}"/>
</div>

View File

@ -166,7 +166,10 @@
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editTab(\'' + row.userId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.userId + '\')"><i class="fa fa-remove"></i>删除</a> ');
actions.push('<a class="btn btn-info btn-xs ' + resetPwdFlag + '" href="javascript:void(0)" onclick="resetPwd(\'' + row.userId + '\')"><i class="fa fa-key"></i>重置</a>');
var more = [];
more.push("<a class='btn btn-default btn-xs " + resetPwdFlag + "' href='javascript:void(0)' onclick='resetPwd(" + row.userId + ")'><i class='fa fa-key'></i>重置密码</a> ");
more.push("<a class='btn btn-default btn-xs " + editFlag + "' href='javascript:void(0)' onclick='authRole(" + row.userId + ")'><i class='fa fa-check-square-o'></i>分配角色</a>");
actions.push('<a class="btn btn-info btn-xs" role="button" data-toggle="popover" data-content="' + more.join('') + '"><i class="fa fa-chevron-circle-right"></i>更多操作</a>');
return actions.join('');
}
}]
@ -219,6 +222,12 @@
$.modal.open("重置密码", url, '800', '300');
}
/* 用户管理-分配角色 */
function authRole(userId) {
var url = prefix + '/authRole/' + userId;
$.modal.openTab("用户分配角色", url);
}
/* 用户状态显示 */
function statusTools(row) {
if (row.status == 1) {

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.1.0</version>
<version>4.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -1,119 +1,93 @@
package com.ruoyi.common.config;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.YamlUtil;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 全局配置类
*
* @author ruoyi
*/
@Component
@ConfigurationProperties(prefix = "ruoyi")
public class Global
{
private static final Logger log = LoggerFactory.getLogger(Global.class);
/** 项目名称 */
private static String name;
private static String NAME = "application.yml";
/** 版本 */
private static String version;
/**
* 当前对象实例
*/
private static Global global;
/** 版权年份 */
private static String copyrightYear;
/**
* 保存全局属性值
*/
private static Map<String, String> map = new HashMap<String, String>();
/** 实例演示开关 */
private static boolean demoEnabled;
private Global()
{
}
/** 上传路径 */
private static String profile;
/**
* 静态工厂方法
*/
public static synchronized Global getInstance()
{
if (global == null)
{
global = new Global();
}
return global;
}
/** 获取地址开关 */
private static boolean addressEnabled;
/**
* 获取配置
*/
public static String getConfig(String key)
{
String value = map.get(key);
if (value == null)
{
Map<?, ?> yamlMap = null;
try
{
yamlMap = YamlUtil.loadYaml(NAME);
value = String.valueOf(YamlUtil.getProperty(yamlMap, key));
map.put(key, value != null ? value : StringUtils.EMPTY);
}
catch (FileNotFoundException e)
{
log.error("获取全局配置异常 {}", key);
}
}
return value;
}
/**
* 获取项目名称
*/
public static String getName()
{
return StringUtils.nvl(getConfig("ruoyi.name"), "RuoYi");
return name;
}
public void setName(String name)
{
Global.name = name;
}
/**
* 获取项目版本
*/
public static String getVersion()
{
return StringUtils.nvl(getConfig("ruoyi.version"), "4.1.0");
return version;
}
public void setVersion(String version)
{
Global.version = version;
}
/**
* 获取版权年份
*/
public static String getCopyrightYear()
{
return StringUtils.nvl(getConfig("ruoyi.copyrightYear"), "2019");
return copyrightYear;
}
/**
* 实例演示开关
*/
public static String isDemoEnabled()
public void setCopyrightYear(String copyrightYear)
{
return StringUtils.nvl(getConfig("ruoyi.demoEnabled"), "true");
Global.copyrightYear = copyrightYear;
}
/**
* 获取ip地址开关
*/
public static Boolean isAddressEnabled()
public static boolean isDemoEnabled()
{
return Boolean.valueOf(getConfig("ruoyi.addressEnabled"));
return demoEnabled;
}
public void setDemoEnabled(boolean demoEnabled)
{
Global.demoEnabled = demoEnabled;
}
/**
* 获取文件上传路径
*/
public static String getProfile()
{
return getConfig("ruoyi.profile");
return profile;
}
public void setProfile(String profile)
{
Global.profile = profile;
}
public static boolean isAddressEnabled()
{
return addressEnabled;
}
public void setAddressEnabled(boolean addressEnabled)
{
Global.addressEnabled = addressEnabled;
}
/**

View File

@ -31,17 +31,17 @@ public class Constants
* 注销
*/
public static final String LOGOUT = "Logout";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
public static final String LOGIN_FAIL = "Error";
/**
* 自动去除表前缀
*/
public static final String AUTO_REOMVE_PRE = "true";
/**
* 当前记录起始索引
*/
@ -62,6 +62,26 @@ public class Constants
*/
public static final String IS_ASC = "isAsc";
/**
* 参数管理 cache name
*/
public static final String SYS_CONFIG_CACHE = "sys-config";
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache name
*/
public static final String SYS_DICT_CACHE = "sys-dict";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 资源映射路径 前缀
*/

View File

@ -20,22 +20,22 @@ public interface ShiroConstants
/**
* 消息key
*/
public static String MESSAGE = "message";
public static final String MESSAGE = "message";
/**
* 错误key
*/
public static String ERROR = "errorMsg";
public static final String ERROR = "errorMsg";
/**
* 编码格式
*/
public static String ENCODING = "UTF-8";
public static final String ENCODING = "UTF-8";
/**
* 当前在线会话
*/
public String ONLINE_SESSION = "online_session";
public static final String ONLINE_SESSION = "online_session";
/**
* 验证码key

View File

@ -89,6 +89,12 @@ public class UserConstants
public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20;
/**
* 用户类型
*/
public static final String SYSTEM_USER_TYPE = "00";
public static final String REGISTER_USER_TYPE = "01";
/**
* 手机号码格式限制
*/

View File

@ -63,6 +63,19 @@ public class BaseController
}
}
/**
* 设置请求排序数据
*/
protected void startOrderBy()
{
PageDomain pageDomain = TableSupport.buildPageRequest();
if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
{
String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
PageHelper.orderBy(orderBy);
}
}
/**
* 获取request
*/

View File

@ -0,0 +1,187 @@
package com.ruoyi.common.utils;
import java.util.Iterator;
import java.util.Set;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.utils.spring.SpringUtils;
/**
* Cache工具类
*
* @author ruoyi
*/
public class CacheUtils
{
private static Logger logger = LoggerFactory.getLogger(CacheUtils.class);
private static CacheManager cacheManager = SpringUtils.getBean(CacheManager.class);
private static final String SYS_CACHE = "sys-cache";
/**
* 获取SYS_CACHE缓存
*
* @param key
* @return
*/
public static Object get(String key)
{
return get(SYS_CACHE, key);
}
/**
* 获取SYS_CACHE缓存
*
* @param key
* @param defaultValue
* @return
*/
public static Object get(String key, Object defaultValue)
{
Object value = get(key);
return value != null ? value : defaultValue;
}
/**
* 写入SYS_CACHE缓存
*
* @param key
* @return
*/
public static void put(String key, Object value)
{
put(SYS_CACHE, key, value);
}
/**
* 从SYS_CACHE缓存中移除
*
* @param key
* @return
*/
public static void remove(String key)
{
remove(SYS_CACHE, key);
}
/**
* 获取缓存
*
* @param cacheName
* @param key
* @return
*/
public static Object get(String cacheName, String key)
{
return getCache(cacheName).get(getKey(key));
}
/**
* 获取缓存
*
* @param cacheName
* @param key
* @param defaultValue
* @return
*/
public static Object get(String cacheName, String key, Object defaultValue)
{
Object value = get(cacheName, getKey(key));
return value != null ? value : defaultValue;
}
/**
* 写入缓存
*
* @param cacheName
* @param key
* @param value
*/
public static void put(String cacheName, String key, Object value)
{
getCache(cacheName).put(getKey(key), value);
}
/**
* 从缓存中移除
*
* @param cacheName
* @param key
*/
public static void remove(String cacheName, String key)
{
getCache(cacheName).remove(getKey(key));
}
/**
* 从缓存中移除所有
*
* @param cacheName
*/
public static void removeAll(String cacheName)
{
Cache<String, Object> cache = getCache(cacheName);
Set<String> keys = cache.keys();
for (Iterator<String> it = keys.iterator(); it.hasNext();)
{
cache.remove(it.next());
}
logger.info("清理缓存: {} => {}", cacheName, keys);
}
/**
* 从缓存中移除指定key
*
* @param keys
*/
public static void removeByKeys(Set<String> keys)
{
removeByKeys(SYS_CACHE, keys);
}
/**
* 从缓存中移除指定key
*
* @param cacheName
* @param keys
*/
public static void removeByKeys(String cacheName, Set<String> keys)
{
for (Iterator<String> it = keys.iterator(); it.hasNext();)
{
remove(it.next());
}
logger.info("清理缓存: {} => {}", cacheName, keys);
}
/**
* 获取缓存键名
*
* @param key
* @return
*/
private static String getKey(String key)
{
return key;
}
/**
* 获得一个Cache没有则显示日志。
*
* @param cacheName
* @return
*/
private static Cache<String, Object> getCache(String cacheName)
{
Cache<String, Object> cache = cacheManager.getCache(cacheName);
if (cache == null)
{
throw new RuntimeException("当前系统中没有定义“" + cacheName + "”这个缓存。");
}
return cache;
}
}

View File

@ -395,4 +395,10 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
}
return sb.toString();
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj)
{
return (T) obj;
}
}

View File

@ -91,7 +91,7 @@ public class FileUploadUtils
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param extension 上传文件类型
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
@ -146,7 +146,7 @@ public class FileUploadUtils
private static final String getPathFileName(String uploadDir, String fileName) throws IOException
{
int dirLastIndex = uploadDir.lastIndexOf("/") + 1;
int dirLastIndex = Global.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
return pathFileName;

View File

@ -58,7 +58,7 @@ public class EscapeUtil
*/
public static String clean(String content)
{
return content.replaceAll(RE_HTML_MARK, "");
return new HTMLFilter().filter(content);
}
/**
@ -145,6 +145,8 @@ public class EscapeUtil
public static void main(String[] args)
{
String html = "<script>alert(1);</script>";
// String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
// String html = "<123";
System.out.println(EscapeUtil.clean(html));
System.out.println(EscapeUtil.escape(html));
System.out.println(EscapeUtil.unescape(html));

View File

@ -0,0 +1,570 @@
package com.ruoyi.common.utils.html;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* HTML过滤器用于去除XSS漏洞隐患。
*
* @author ruoyi
*/
public final class HTMLFilter
{
/**
* regex flag union representing /si modifiers in php
**/
private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
private static final Pattern P_END_ARROW = Pattern.compile("^>");
// private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
private static final Pattern P_AMP = Pattern.compile("&");
private static final Pattern P_QUOTE = Pattern.compile("\"");
private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
// @xxx could grow large... maybe use sesat's ReferenceMap
private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
/**
* set of allowed html elements, along with allowed attributes for each element
**/
private final Map<String, List<String>> vAllowed;
/**
* counts of open tags for each (allowable) html element
**/
private final Map<String, Integer> vTagCounts = new HashMap<>();
/**
* html elements which must always be self-closing (e.g. "<img />")
**/
private final String[] vSelfClosingTags;
/**
* html elements which must always have separate opening and closing tags (e.g. "<b></b>")
**/
private final String[] vNeedClosingTags;
/**
* set of disallowed html elements
**/
private final String[] vDisallowed;
/**
* attributes which should be checked for valid protocols
**/
private final String[] vProtocolAtts;
/**
* allowed protocols
**/
private final String[] vAllowedProtocols;
/**
* tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
**/
private final String[] vRemoveBlanks;
/**
* entities allowed within html markup
**/
private final String[] vAllowedEntities;
/**
* flag determining whether comments are allowed in input String.
*/
private final boolean stripComment;
private final boolean encodeQuotes;
/**
* flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
* becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
*/
private final boolean alwaysMakeTags;
/**
* Default constructor.
*/
public HTMLFilter()
{
vAllowed = new HashMap<>();
final ArrayList<String> a_atts = new ArrayList<>();
a_atts.add("href");
a_atts.add("target");
vAllowed.put("a", a_atts);
final ArrayList<String> img_atts = new ArrayList<>();
img_atts.add("src");
img_atts.add("width");
img_atts.add("height");
img_atts.add("alt");
vAllowed.put("img", img_atts);
final ArrayList<String> no_atts = new ArrayList<>();
vAllowed.put("b", no_atts);
vAllowed.put("strong", no_atts);
vAllowed.put("i", no_atts);
vAllowed.put("em", no_atts);
vSelfClosingTags = new String[] { "img" };
vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" };
vDisallowed = new String[] {};
vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp.
vProtocolAtts = new String[] { "src", "href" };
vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" };
vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
stripComment = true;
encodeQuotes = true;
alwaysMakeTags = true;
}
/**
* Map-parameter configurable constructor.
*
* @param conf map containing configuration. keys match field names.
*/
@SuppressWarnings("unchecked")
public HTMLFilter(final Map<String, Object> conf)
{
assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
vDisallowed = (String[]) conf.get("vDisallowed");
vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
vProtocolAtts = (String[]) conf.get("vProtocolAtts");
vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
vAllowedEntities = (String[]) conf.get("vAllowedEntities");
stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
}
private void reset()
{
vTagCounts.clear();
}
// ---------------------------------------------------------------
// my versions of some PHP library functions
public static String chr(final int decimal)
{
return String.valueOf((char) decimal);
}
public static String htmlSpecialChars(final String s)
{
String result = s;
result = regexReplace(P_AMP, "&amp;", result);
result = regexReplace(P_QUOTE, "&quot;", result);
result = regexReplace(P_LEFT_ARROW, "&lt;", result);
result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
return result;
}
// ---------------------------------------------------------------
/**
* given a user submitted input String, filter out any invalid or restricted html.
*
* @param input text (i.e. submitted by a user) than may contain html
* @return "clean" version of input, with only valid, whitelisted html elements allowed
*/
public String filter(final String input)
{
reset();
String s = input;
s = escapeComments(s);
s = balanceHTML(s);
s = checkTags(s);
s = processRemoveBlanks(s);
s = validateEntities(s);
return s;
}
public boolean isAlwaysMakeTags()
{
return alwaysMakeTags;
}
public boolean isStripComments()
{
return stripComment;
}
private String escapeComments(final String s)
{
final Matcher m = P_COMMENTS.matcher(s);
final StringBuffer buf = new StringBuffer();
if (m.find())
{
final String match = m.group(1); // (.*?)
m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
}
m.appendTail(buf);
return buf.toString();
}
private String balanceHTML(String s)
{
if (alwaysMakeTags)
{
//
// try and form html
//
s = regexReplace(P_END_ARROW, "", s);
// 不追加结束标签
// s = regexReplace(P_BODY_TO_END, "<$1>", s);
s = regexReplace(P_XML_CONTENT, "$1<$2", s);
}
else
{
//
// escape stray brackets
//
s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
//
// the last regexp causes '<>' entities to appear
// (we need to do a lookahead assertion so that the last bracket can
// be used in the next pass of the regexp)
//
s = regexReplace(P_BOTH_ARROWS, "", s);
}
return s;
}
private String checkTags(String s)
{
Matcher m = P_TAGS.matcher(s);
final StringBuffer buf = new StringBuffer();
while (m.find())
{
String replaceStr = m.group(1);
replaceStr = processTag(replaceStr);
m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
}
m.appendTail(buf);
// these get tallied in processTag
// (remember to reset before subsequent calls to filter method)
final StringBuilder sBuilder = new StringBuilder(buf.toString());
for (String key : vTagCounts.keySet())
{
for (int ii = 0; ii < vTagCounts.get(key); ii++)
{
sBuilder.append("</").append(key).append(">");
}
}
s = sBuilder.toString();
return s;
}
private String processRemoveBlanks(final String s)
{
String result = s;
for (String tag : vRemoveBlanks)
{
if (!P_REMOVE_PAIR_BLANKS.containsKey(tag))
{
P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
}
result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
if (!P_REMOVE_SELF_BLANKS.containsKey(tag))
{
P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
}
result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
}
return result;
}
private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s)
{
Matcher m = regex_pattern.matcher(s);
return m.replaceAll(replacement);
}
private String processTag(final String s)
{
// ending tags
Matcher m = P_END_TAG.matcher(s);
if (m.find())
{
final String name = m.group(1).toLowerCase();
if (allowed(name))
{
if (false == inArray(name, vSelfClosingTags))
{
if (vTagCounts.containsKey(name))
{
vTagCounts.put(name, vTagCounts.get(name) - 1);
return "</" + name + ">";
}
}
}
}
// starting tags
m = P_START_TAG.matcher(s);
if (m.find())
{
final String name = m.group(1).toLowerCase();
final String body = m.group(2);
String ending = m.group(3);
// debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
if (allowed(name))
{
final StringBuilder params = new StringBuilder();
final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
final List<String> paramNames = new ArrayList<>();
final List<String> paramValues = new ArrayList<>();
while (m2.find())
{
paramNames.add(m2.group(1)); // ([a-z0-9]+)
paramValues.add(m2.group(3)); // (.*?)
}
while (m3.find())
{
paramNames.add(m3.group(1)); // ([a-z0-9]+)
paramValues.add(m3.group(3)); // ([^\"\\s']+)
}
String paramName, paramValue;
for (int ii = 0; ii < paramNames.size(); ii++)
{
paramName = paramNames.get(ii).toLowerCase();
paramValue = paramValues.get(ii);
// debug( "paramName='" + paramName + "'" );
// debug( "paramValue='" + paramValue + "'" );
// debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
if (allowedAttribute(name, paramName))
{
if (inArray(paramName, vProtocolAtts))
{
paramValue = processParamProtocol(paramValue);
}
params.append(' ').append(paramName).append("=\"").append(paramValue).append("\"");
}
}
if (inArray(name, vSelfClosingTags))
{
ending = " /";
}
if (inArray(name, vNeedClosingTags))
{
ending = "";
}
if (ending == null || ending.length() < 1)
{
if (vTagCounts.containsKey(name))
{
vTagCounts.put(name, vTagCounts.get(name) + 1);
}
else
{
vTagCounts.put(name, 1);
}
}
else
{
ending = " /";
}
return "<" + name + params + ending + ">";
}
else
{
return "";
}
}
// comments
m = P_COMMENT.matcher(s);
if (!stripComment && m.find())
{
return "<" + m.group() + ">";
}
return "";
}
private String processParamProtocol(String s)
{
s = decodeEntities(s);
final Matcher m = P_PROTOCOL.matcher(s);
if (m.find())
{
final String protocol = m.group(1);
if (!inArray(protocol, vAllowedProtocols))
{
// bad protocol, turn into local anchor link instead
s = "#" + s.substring(protocol.length() + 1);
if (s.startsWith("#//"))
{
s = "#" + s.substring(3);
}
}
}
return s;
}
private String decodeEntities(String s)
{
StringBuffer buf = new StringBuffer();
Matcher m = P_ENTITY.matcher(s);
while (m.find())
{
final String match = m.group(1);
final int decimal = Integer.decode(match).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENTITY_UNICODE.matcher(s);
while (m.find())
{
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
buf = new StringBuffer();
m = P_ENCODE.matcher(s);
while (m.find())
{
final String match = m.group(1);
final int decimal = Integer.valueOf(match, 16).intValue();
m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
}
m.appendTail(buf);
s = buf.toString();
s = validateEntities(s);
return s;
}
private String validateEntities(final String s)
{
StringBuffer buf = new StringBuffer();
// validate entities throughout the string
Matcher m = P_VALID_ENTITIES.matcher(s);
while (m.find())
{
final String one = m.group(1); // ([^&;]*)
final String two = m.group(2); // (?=(;|&|$))
m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
}
m.appendTail(buf);
return encodeQuotes(buf.toString());
}
private String encodeQuotes(final String s)
{
if (encodeQuotes)
{
StringBuffer buf = new StringBuffer();
Matcher m = P_VALID_QUOTES.matcher(s);
while (m.find())
{
final String one = m.group(1); // (>|^)
final String two = m.group(2); // ([^<]+?)
final String three = m.group(3); // (<|$)
// 不替换双引号为&quot;防止json格式无效 regexReplace(P_QUOTE, "&quot;", two)
m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
}
m.appendTail(buf);
return buf.toString();
}
else
{
return s;
}
}
private String checkEntity(final String preamble, final String term)
{
return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&amp;" + preamble;
}
private boolean isValidEntity(final String entity)
{
return inArray(entity, vAllowedEntities);
}
private static boolean inArray(final String s, final String[] array)
{
for (String item : array)
{
if (item != null && item.equals(s))
{
return true;
}
}
return false;
}
private boolean allowed(final String name)
{
return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
}
private boolean allowedAttribute(final String name, final String paramName)
{
return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
}
}

View File

@ -224,7 +224,15 @@ public class ExcelUtil<T>
}
else
{
val = Convert.toStr(val);
String dateFormat = field.getAnnotation(Excel.class).dateFormat();
if (StringUtils.isNotEmpty(dateFormat))
{
val = DateUtils.parseDateToStr(dateFormat, (Date) val);
}
else
{
val = Convert.toStr(val);
}
}
}
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType))

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>ruoyi</artifactId>
<groupId>com.ruoyi</groupId>
<version>4.1.0</version>
<version>4.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -47,7 +47,7 @@
</exclusions>
</dependency>
<!-- Shiro使用Srping框架 -->
<!-- Shiro使用Spring框架 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>

View File

@ -92,7 +92,8 @@ public class DataScopeAspect
*
* @param joinPoint 切点
* @param user 用户
* @param alias 别名
* @param deptAlias 部门别名
* @param userAlias 用户别名
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
{

View File

@ -20,6 +20,7 @@ import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.config.properties.DruidProperties;
import com.ruoyi.framework.datasource.DynamicDataSource;
@ -50,14 +51,33 @@ public class DruidConfig
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource)
public DynamicDataSource dataSource(DataSource masterDataSource)
{
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
targetDataSources.put(DataSourceType.SLAVE.name(), slaveDataSource);
setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
return new DynamicDataSource(masterDataSource, targetDataSources);
}
/**
* 设置数据源
*
* @param targetDataSources 备选数据源集合
* @param sourceName 数据源名称
* @param beanName bean名称
*/
public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
{
try
{
DataSource dataSource = SpringUtils.getBean(beanName);
targetDataSources.put(sourceName, dataSource);
}
catch (Exception e)
{
}
}
/**
* 去除监控页面底部的广告
*/
@ -79,6 +99,7 @@ public class DruidConfig
public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
@ -93,6 +114,7 @@ public class DruidConfig
text = text.replaceAll("powered.*?shrek.wang</a>", "");
response.getWriter().write(text);
}
@Override
public void destroy()
{

View File

@ -199,7 +199,7 @@ public class ShiroConfig
* 安全管理器
*/
@Bean
public SecurityManager securityManager(UserRealm userRealm, SpringSessionValidationScheduler springSessionValidationScheduler)
public SecurityManager securityManager(UserRealm userRealm)
{
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
@ -249,12 +249,13 @@ public class ShiroConfig
filterChainDefinitionMap.put("/ajax/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/ruoyi/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
// 退出 logout地址shiro去清除session
filterChainDefinitionMap.put("/logout", "logout");
// 不需要拦截的访问
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
// 注册相关
filterChainDefinitionMap.put("/register", "anon,captchaValidate");
// 系统权限列表
// filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());

View File

@ -47,7 +47,7 @@ public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter
/**
* 验证是否重复提交由子类实现具体的防重复提交的规则
*
* @param httpServletRequest
* @param request
* @return
* @throws Exception
*/

View File

@ -1,6 +1,8 @@
package com.ruoyi.framework.manager;
import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -20,11 +22,15 @@ public class ShutdownManager
@Autowired(required = false)
private SpringSessionValidationScheduler springSessionValidationScheduler;
@Autowired(required = false)
private EhCacheManager ehCacheManager;
@PreDestroy
public void destroy()
{
shutdownSpringSessionValidationScheduler();
shutdownAsyncManager();
shutdownEhCacheManager();
}
/**
@ -61,4 +67,21 @@ public class ShutdownManager
logger.error(e.getMessage(), e);
}
}
private void shutdownEhCacheManager()
{
try
{
logger.info("====关闭缓存====");
if (ehCacheManager != null)
{
CacheManager cacheManager = ehCacheManager.getCacheManager();
cacheManager.shutdown();
}
}
catch (Exception e)
{
logger.error(e.getMessage(), e);
}
}
}

Some files were not shown because too many files have changed in this diff Show More