Compare commits
67 Commits
Author | SHA1 | Date | |
---|---|---|---|
d872c66d19 | |||
1042b40cfc | |||
070f7bc6bd | |||
4f1c99293f | |||
57fa243747 | |||
04f2607398 | |||
01caa02f5e | |||
e37ec9f8fa | |||
122e8b61a0 | |||
2345dfdf42 | |||
77550e2f11 | |||
ca5b4bc852 | |||
5fc9a63231 | |||
958be505c9 | |||
ec8c7f1d79 | |||
030b61bc37 | |||
619e1d241a | |||
dc07b97cdb | |||
dd37524b04 | |||
8c0ebd008e | |||
0c76d45349 | |||
6237ddb3dc | |||
8643dde074 | |||
d22fa29b65 | |||
b66097c004 | |||
d30dc35e59 | |||
87c38706cd | |||
f04c1fed50 | |||
4474c533e6 | |||
4374a24f79 | |||
383d082194 | |||
e9a7cc7bc7 | |||
8b07f8925f | |||
2af817d8dc | |||
0e240cb244 | |||
fc834b35cb | |||
4fa795dee9 | |||
33788ecd02 | |||
3d3017804d | |||
63ee2ba2e7 | |||
aac46aa353 | |||
c6e4daedd4 | |||
6b9b8ed889 | |||
1f000d9f84 | |||
9d5a702e1f | |||
bb1831f609 | |||
c628cf7ee7 | |||
1de73da333 | |||
c404de1773 | |||
cfcd48b6b2 | |||
a87e1d019d | |||
ef91e71d7b | |||
3bacfc5951 | |||
b5cd54da66 | |||
0e9925a481 | |||
7943b765ca | |||
a74e58f7d5 | |||
ea58f8db9c | |||
89e21eecea | |||
35df1dbcdf | |||
0972bba763 | |||
583b06ca9a | |||
6a4b1898b1 | |||
268f0a6321 | |||
e56a7e7e57 | |||
9d225fecb9 | |||
d24481f9a5 |
36
README.md
36
README.md
@ -2,13 +2,13 @@
|
||||
|
||||
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
|
||||
|
||||
寓意:你若不离不弃,我必生死相依
|
||||
性别男,若依是给还没有出生女儿取的名字(寓意:你若不离不弃,我必生死相依)
|
||||
|
||||
若依基于hplus和inspinia两套后台系统模板开发。有需要可自行到群内下载。
|
||||
|
||||
> RuoYi从3.0开始,进行模块拆分,将原先的单应用转变为多模块,如需单应用,请移步 [RuoYi-fast](https://gitee.com/y_project/RuoYi-fast)
|
||||
|
||||
> 推荐使用阿里云部署,通用云产品代金券 :[点我领取](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof)
|
||||
> 推荐使用阿里云部署,通用云产品代金券 :[点我领取](https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=brki8iof)
|
||||
|
||||
## 内置功能
|
||||
|
||||
@ -26,10 +26,12 @@
|
||||
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
|
||||
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。
|
||||
14. 系统接口:根据业务代码自动生成相关的api接口文档。
|
||||
15. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||
16. 连接池监视:监视当期系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
||||
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
|
||||
16. 在线构建器:拖动表单元素生成相应的HTML代码。
|
||||
17. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。
|
||||
## 在线体验
|
||||
> admin/admin123
|
||||
> admin/admin123
|
||||
> 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
|
||||
|
||||
演示地址:http://ruoyi.vip
|
||||
|
||||
@ -40,31 +42,31 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/25b5e333768d013d45a990c152dbe4d9d6e.jpg"/></td>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194326_GBIJ_1438828.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/dfadf4d864242745486aa0167110dfcbeb8.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194443_Qyuq_1438828.png"/></td>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194501_U7gT_1438828.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/2e1ed87df9b476ed73ed650df20cf009b78.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/91bef110740ba9e36ff00804f8748a787fb.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194525_PApp_1438828.png"/></td>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194535_3EM0_1438828.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/9a2851988f4e7433c9322154534865f57d7.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/396293f80b1e8cce8671f56c296bee78a3a.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194612_kJ4F_1438828.png"/></td>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194623_YEXO_1438828.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/787b3b06430a403655b48b9bcd1fa829555.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/a51820009836276b778bc89d4d0e217e26d.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/0902/132548_ne4U_1438828.png"/></td>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194643_MsxF_1438828.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/5fb138478adeda6825e206d21f67ecd0625.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/fa2f027a10707a4eb4fc47d5ea1c3d2b772.jpg"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194658_40L4_1438828.png"/></td>
|
||||
<td><img src="https://static.oschina.net/uploads/space/2018/1005/194712_2ma3_1438828.png"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/a714056081523b7dfa782cda866e8be4adc.jpg"/></td>
|
||||
<td><img src="https://oscimg.oschina.net/oscnet/ab4b5797dfb2bc68c4974ad5458bd5f5bcf.jpg"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
## 若依交流群
|
||||
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) 点击按钮入群。
|
||||
QQ群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) 点击按钮入群。
|
6
pom.xml
6
pom.xml
@ -6,14 +6,14 @@
|
||||
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<version>3.1</version>
|
||||
<version>3.2</version>
|
||||
|
||||
<name>ruoyi</name>
|
||||
<url>http://www.ruoyi.vip</url>
|
||||
<description>若依管理系统</description>
|
||||
|
||||
<properties>
|
||||
<ruoyi.version>3.1</ruoyi.version>
|
||||
<ruoyi.version>3.2</ruoyi.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
@ -33,7 +33,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>2.0.5.RELEASE</version>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.1</version>
|
||||
<version>3.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
@ -6,10 +6,17 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.config.Global;
|
||||
import com.ruoyi.common.utils.file.FileUtils;
|
||||
import com.ruoyi.framework.config.ServerConfig;
|
||||
import com.ruoyi.framework.util.FileUploadUtils;
|
||||
|
||||
/**
|
||||
* 通用请求处理
|
||||
@ -21,7 +28,21 @@ public class CommonController
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
|
||||
|
||||
@RequestMapping("common/download")
|
||||
/**
|
||||
* 文件上传路径
|
||||
*/
|
||||
public static final String UPLOAD_PATH = "/profile/upload/";
|
||||
|
||||
@Autowired
|
||||
private ServerConfig serverConfig;
|
||||
|
||||
/**
|
||||
* 通用下载请求
|
||||
*
|
||||
* @param fileName 文件名称
|
||||
* @param delete 是否删除
|
||||
*/
|
||||
@GetMapping("common/download")
|
||||
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
|
||||
{
|
||||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
|
||||
@ -31,7 +52,8 @@ public class CommonController
|
||||
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("multipart/form-data");
|
||||
response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, realFileName));
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;fileName=" + setFileDownloadHeader(request, realFileName));
|
||||
FileUtils.writeBytes(filePath, response.getOutputStream());
|
||||
if (delete)
|
||||
{
|
||||
@ -44,6 +66,31 @@ public class CommonController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用上传请求
|
||||
*/
|
||||
@PostMapping("/common/upload")
|
||||
@ResponseBody
|
||||
public AjaxResult uploadFile(MultipartFile file) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
// 上传文件路径
|
||||
String filePath = Global.getUploadPath();
|
||||
// 上传并返回新文件名称
|
||||
String fileName = FileUploadUtils.upload(filePath, file);
|
||||
String url = serverConfig.getUrl() + UPLOAD_PATH + fileName;
|
||||
AjaxResult ajax = AjaxResult.success();
|
||||
ajax.put("fileName", fileName);
|
||||
ajax.put("url", url);
|
||||
return ajax;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
|
||||
{
|
||||
final String agent = request.getHeader("USER-AGENT");
|
||||
|
@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.quartz.domain.SysJob;
|
||||
import com.ruoyi.quartz.service.ISysJobService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
@ -59,7 +59,7 @@ public class SysJobController extends BaseController
|
||||
{
|
||||
List<SysJob> list = jobService.selectJobList(job);
|
||||
ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
|
||||
return util.exportExcel(list, "job");
|
||||
return util.exportExcel(list, "定时任务");
|
||||
}
|
||||
|
||||
@Log(title = "定时任务", businessType = BusinessType.DELETE)
|
||||
|
@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.quartz.domain.SysJobLog;
|
||||
import com.ruoyi.quartz.service.ISysJobLogService;
|
||||
|
||||
@ -58,7 +58,7 @@ public class SysJobLogController extends BaseController
|
||||
{
|
||||
List<SysJobLog> list = jobLogService.selectJobLogList(jobLog);
|
||||
ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
|
||||
return util.exportExcel(list, "jobLog");
|
||||
return util.exportExcel(list, "调度日志");
|
||||
}
|
||||
|
||||
@Log(title = "调度日志", businessType = BusinessType.DELETE)
|
||||
|
@ -11,8 +11,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.system.domain.SysLogininfor;
|
||||
import com.ruoyi.system.service.ISysLogininforService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
@ -56,7 +56,7 @@ public class SysLogininforController extends BaseController
|
||||
{
|
||||
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
|
||||
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
|
||||
return util.exportExcel(list, "logininfor");
|
||||
return util.exportExcel(list, "登陆日志");
|
||||
}
|
||||
|
||||
@RequiresPermissions("monitor:logininfor:remove")
|
||||
|
@ -13,8 +13,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.system.domain.SysOperLog;
|
||||
import com.ruoyi.system.service.ISysOperLogService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
@ -58,7 +58,7 @@ public class SysOperlogController extends BaseController
|
||||
{
|
||||
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
|
||||
ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
|
||||
return util.exportExcel(list, "operLog");
|
||||
return util.exportExcel(list, "操作日志");
|
||||
}
|
||||
|
||||
@RequiresPermissions("monitor:operlog:remove")
|
||||
|
@ -13,12 +13,12 @@ import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.enums.OnlineStatus;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSession;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSessionDAO;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.SysUserOnline;
|
||||
import com.ruoyi.system.service.impl.SysUserOnlineServiceImpl;
|
||||
import com.ruoyi.system.service.ISysUserOnlineService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
|
||||
/**
|
||||
@ -33,7 +33,7 @@ public class SysUserOnlineController extends BaseController
|
||||
private String prefix = "monitor/online";
|
||||
|
||||
@Autowired
|
||||
private SysUserOnlineServiceImpl userOnlineService;
|
||||
private ISysUserOnlineService userOnlineService;
|
||||
|
||||
@Autowired
|
||||
private OnlineSessionDAO onlineSessionDAO;
|
||||
|
@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.SysConfig;
|
||||
import com.ruoyi.system.service.ISysConfigService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
@ -62,7 +62,7 @@ public class SysConfigController extends BaseController
|
||||
{
|
||||
List<SysConfig> list = configService.selectConfigList(config);
|
||||
ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
|
||||
return util.exportExcel(list, "config");
|
||||
return util.exportExcel(list, "参数数据");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,7 +149,7 @@ public class SysDeptController extends BaseController
|
||||
@ResponseBody
|
||||
public List<Map<String, Object>> treeData()
|
||||
{
|
||||
List<Map<String, Object>> tree = deptService.selectDeptTree();
|
||||
List<Map<String, Object>> tree = deptService.selectDeptTree(new SysDept());
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.SysDictData;
|
||||
import com.ruoyi.system.service.ISysDictDataService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
@ -59,7 +59,7 @@ public class SysDictDataController extends BaseController
|
||||
{
|
||||
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
|
||||
ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
|
||||
return util.exportExcel(list, "dictData");
|
||||
return util.exportExcel(list, "字典数据");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.SysDictType;
|
||||
import com.ruoyi.system.service.ISysDictTypeService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
@ -60,7 +60,7 @@ public class SysDictTypeController extends BaseController
|
||||
|
||||
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
|
||||
ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
|
||||
return util.exportExcel(list, "dictType");
|
||||
return util.exportExcel(list, "字典类型");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,8 +13,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.SysNotice;
|
||||
import com.ruoyi.system.service.ISysNoticeService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
|
@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.SysPost;
|
||||
import com.ruoyi.system.service.ISysPostService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
@ -59,7 +59,7 @@ public class SysPostController extends BaseController
|
||||
{
|
||||
List<SysPost> list = postService.selectPostList(post);
|
||||
ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
|
||||
return util.exportExcel(list, "post");
|
||||
return util.exportExcel(list, "岗位数据");
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:post:remove")
|
||||
|
@ -1,13 +1,11 @@
|
||||
package com.ruoyi.web.controller.system;
|
||||
|
||||
import org.apache.shiro.crypto.hash.Md5Hash;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@ -17,6 +15,7 @@ import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.config.Global;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||
import com.ruoyi.framework.util.FileUploadUtils;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
@ -66,54 +65,63 @@ public class SysProfileController extends BaseController
|
||||
public boolean checkPassword(String password)
|
||||
{
|
||||
SysUser user = getSysUser();
|
||||
String encrypt = new Md5Hash(user.getLoginName() + password + user.getSalt()).toHex().toString();
|
||||
if (user.getPassword().equals(encrypt))
|
||||
if (passwordService.matches(user, password))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@GetMapping("/resetPwd/{userId}")
|
||||
public String resetPwd(@PathVariable("userId") Long userId, ModelMap mmap)
|
||||
@GetMapping("/resetPwd")
|
||||
public String resetPwd(ModelMap mmap)
|
||||
{
|
||||
mmap.put("user", userService.selectUserById(userId));
|
||||
SysUser user = getSysUser();
|
||||
mmap.put("user", userService.selectUserById(user.getUserId()));
|
||||
return prefix + "/resetPwd";
|
||||
}
|
||||
|
||||
@Log(title = "重置密码", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/resetPwd")
|
||||
@ResponseBody
|
||||
public AjaxResult resetPwd(SysUser user)
|
||||
public AjaxResult resetPwd(String oldPassword, String newPassword)
|
||||
{
|
||||
user.setSalt(ShiroUtils.randomSalt());
|
||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
|
||||
int rows = userService.resetUserPwd(user);
|
||||
if (rows > 0)
|
||||
SysUser user = getSysUser();
|
||||
if (StringUtils.isNotEmpty(newPassword) && passwordService.matches(user, oldPassword))
|
||||
{
|
||||
setSysUser(userService.selectUserById(user.getUserId()));
|
||||
return success();
|
||||
user.setSalt(ShiroUtils.randomSalt());
|
||||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), newPassword, user.getSalt()));
|
||||
if (userService.resetUserPwd(user) > 0)
|
||||
{
|
||||
setSysUser(userService.selectUserById(user.getUserId()));
|
||||
return success();
|
||||
}
|
||||
return error();
|
||||
}
|
||||
else
|
||||
{
|
||||
return error("修改密码失败,旧密码错误");
|
||||
}
|
||||
return error();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户
|
||||
*/
|
||||
@GetMapping("/edit/{userId}")
|
||||
public String edit(@PathVariable("userId") Long userId, ModelMap mmap)
|
||||
@GetMapping("/edit")
|
||||
public String edit(ModelMap mmap)
|
||||
{
|
||||
mmap.put("user", userService.selectUserById(userId));
|
||||
SysUser user = getSysUser();
|
||||
mmap.put("user", userService.selectUserById(user.getUserId()));
|
||||
return prefix + "/edit";
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改头像
|
||||
*/
|
||||
@GetMapping("/avatar/{userId}")
|
||||
public String avatar(@PathVariable("userId") Long userId, ModelMap mmap)
|
||||
@GetMapping("/avatar")
|
||||
public String avatar(ModelMap mmap)
|
||||
{
|
||||
mmap.put("user", userService.selectUserById(userId));
|
||||
SysUser user = getSysUser();
|
||||
mmap.put("user", userService.selectUserById(user.getUserId()));
|
||||
return prefix + "/avatar";
|
||||
}
|
||||
|
||||
@ -125,9 +133,14 @@ public class SysProfileController extends BaseController
|
||||
@ResponseBody
|
||||
public AjaxResult update(SysUser user)
|
||||
{
|
||||
if (userService.updateUserInfo(user) > 0)
|
||||
SysUser currentUser = getSysUser();
|
||||
currentUser.setUserName(user.getUserName());
|
||||
currentUser.setEmail(user.getEmail());
|
||||
currentUser.setPhonenumber(user.getPhonenumber());
|
||||
currentUser.setSex(user.getSex());
|
||||
if (userService.updateUserInfo(currentUser) > 0)
|
||||
{
|
||||
setSysUser(userService.selectUserById(user.getUserId()));
|
||||
setSysUser(userService.selectUserById(currentUser.getUserId()));
|
||||
return success();
|
||||
}
|
||||
return error();
|
||||
@ -139,17 +152,18 @@ public class SysProfileController extends BaseController
|
||||
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/updateAvatar")
|
||||
@ResponseBody
|
||||
public AjaxResult updateAvatar(SysUser user, @RequestParam("avatarfile") MultipartFile file)
|
||||
public AjaxResult updateAvatar(@RequestParam("avatarfile") MultipartFile file)
|
||||
{
|
||||
SysUser currentUser = getSysUser();
|
||||
try
|
||||
{
|
||||
if (!file.isEmpty())
|
||||
{
|
||||
String avatar = FileUploadUtils.upload(Global.getAvatarPath(), file);
|
||||
user.setAvatar(avatar);
|
||||
if (userService.updateUserInfo(user) > 0)
|
||||
currentUser.setAvatar(avatar);
|
||||
if (userService.updateUserInfo(currentUser) > 0)
|
||||
{
|
||||
setSysUser(userService.selectUserById(user.getUserId()));
|
||||
setSysUser(userService.selectUserById(currentUser.getUserId()));
|
||||
return success();
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,9 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.SysRole;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
@ -60,7 +60,7 @@ public class SysRoleController extends BaseController
|
||||
{
|
||||
List<SysRole> list = roleService.selectRoleList(role);
|
||||
ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
|
||||
return util.exportExcel(list, "role");
|
||||
return util.exportExcel(list, "角色数据");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,4 +181,16 @@ public class SysRoleController extends BaseController
|
||||
{
|
||||
return prefix + "/tree";
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色状态修改
|
||||
*/
|
||||
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
|
||||
@RequiresPermissions("system:role:edit")
|
||||
@PostMapping("/changeStatus")
|
||||
@ResponseBody
|
||||
public AjaxResult changeStatus(SysRole role)
|
||||
{
|
||||
return toAjax(roleService.changeStatus(role));
|
||||
}
|
||||
}
|
@ -11,19 +11,20 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.utils.ExcelUtil;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.framework.shiro.service.SysPasswordService;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
import com.ruoyi.system.service.ISysPostService;
|
||||
import com.ruoyi.system.service.ISysRoleService;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
@ -73,7 +74,29 @@ public class SysUserController extends BaseController
|
||||
{
|
||||
List<SysUser> list = userService.selectUserList(user);
|
||||
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
|
||||
return util.exportExcel(list, "user");
|
||||
return util.exportExcel(list, "用户数据");
|
||||
}
|
||||
|
||||
@Log(title = "用户管理", businessType = BusinessType.IMPORT)
|
||||
@RequiresPermissions("system:user:import")
|
||||
@PostMapping("/importData")
|
||||
@ResponseBody
|
||||
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
|
||||
{
|
||||
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
|
||||
List<SysUser> userList = util.importExcel(file.getInputStream());
|
||||
String operName = getSysUser().getLoginName();
|
||||
String message = userService.importUser(userList, updateSupport, operName);
|
||||
return AjaxResult.success(message);
|
||||
}
|
||||
|
||||
@RequiresPermissions("system:user:view")
|
||||
@GetMapping("/importTemplate")
|
||||
@ResponseBody
|
||||
public AjaxResult importTemplate()
|
||||
{
|
||||
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
|
||||
return util.importTemplateExcel("用户数据");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,4 +225,16 @@ public class SysUserController extends BaseController
|
||||
{
|
||||
return userService.checkEmailUnique(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户状态修改
|
||||
*/
|
||||
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
|
||||
@RequiresPermissions("system:user:edit")
|
||||
@PostMapping("/changeStatus")
|
||||
@ResponseBody
|
||||
public AjaxResult changeStatus(SysUser user)
|
||||
{
|
||||
return toAjax(userService.changeStatus(user));
|
||||
}
|
||||
}
|
@ -14,8 +14,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.support.Convert;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.generator.domain.TableInfo;
|
||||
import com.ruoyi.generator.service.IGenService;
|
||||
import com.ruoyi.framework.web.base.BaseController;
|
||||
|
@ -2,11 +2,11 @@
|
||||
spring:
|
||||
datasource:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
driverClassName: com.mysql.jdbc.Driver
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
druid:
|
||||
# 主库数据源
|
||||
master:
|
||||
url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true
|
||||
url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: password
|
||||
# 从库数据源
|
||||
@ -17,32 +17,33 @@ spring:
|
||||
username:
|
||||
password:
|
||||
# 初始连接数
|
||||
initial-size: 10
|
||||
# 最大连接池数量
|
||||
max-active: 100
|
||||
initialSize: 5
|
||||
# 最小连接池数量
|
||||
min-idle: 10
|
||||
minIdle: 10
|
||||
# 最大连接池数量
|
||||
maxActive: 20
|
||||
# 配置获取连接等待超时的时间
|
||||
max-wait: 60000
|
||||
# 打开PSCache,并且指定每个连接上PSCache的大小
|
||||
pool-prepared-statements: true
|
||||
max-pool-prepared-statement-per-connection-size: 20
|
||||
maxWait: 60000
|
||||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||
timeBetweenEvictionRunsMillis: 60000
|
||||
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||
min-evictable-idle-time-millis: 300000
|
||||
validation-query: SELECT 1 FROM DUAL
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
stat-view-servlet:
|
||||
minEvictableIdleTimeMillis: 300000
|
||||
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||
maxEvictableIdleTimeMillis: 900000
|
||||
# 配置检测连接是否有效
|
||||
validationQuery: SELECT 1 FROM DUAL
|
||||
testWhileIdle: true
|
||||
testOnBorrow: false
|
||||
testOnReturn: false
|
||||
statViewServlet:
|
||||
enabled: true
|
||||
url-pattern: /monitor/druid/*
|
||||
filter:
|
||||
stat:
|
||||
# 慢SQL记录
|
||||
log-slow-sql: true
|
||||
slow-sql-millis: 1000
|
||||
merge-sql: false
|
||||
merge-sql: true
|
||||
wall:
|
||||
config:
|
||||
multi-statement-allow: true
|
@ -3,9 +3,9 @@ ruoyi:
|
||||
# 名称
|
||||
name: RuoYi
|
||||
# 版本
|
||||
version: 3.1.0
|
||||
version: 3.2.0
|
||||
# 版权年份
|
||||
copyrightYear: 2018
|
||||
copyrightYear: 2019
|
||||
# 文件上传路径
|
||||
profile: D:/profile/
|
||||
# 获取ip地址开关
|
||||
|
@ -20,5 +20,5 @@ Spring Boot Version: ${spring-boot.version}
|
||||
// ========`-.____`-.___\_____/___.-`____.-'======== //
|
||||
// `=---=' //
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
|
||||
// 佛祖保佑 永不宕机 永无BUG //
|
||||
// 佛祖保佑 永不宕机 永无BUG //
|
||||
////////////////////////////////////////////////////////////////////
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ehcache name="ruoyi">
|
||||
<ehcache name="ruoyi" updateCheck="false">
|
||||
|
||||
<!-- 磁盘缓存位置 -->
|
||||
<diskStore path="java.io.tmpdir"/>
|
||||
|
@ -6,8 +6,8 @@ user.password.not.match=用户不存在/密码错误
|
||||
user.password.retry.limit.count=密码输入错误{0}次
|
||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
|
||||
user.password.delete=对不起,您的账号已被删除
|
||||
user.blocked=用户已封禁,原因:{0}
|
||||
role.blocked=角色已封禁,原因:{0}
|
||||
user.blocked=用户已封禁,请联系管理员
|
||||
role.blocked=角色已封禁,请联系管理员
|
||||
user.logout.success=退出成功
|
||||
|
||||
length.not.valid=长度必须在{min}到{max}个字符之间
|
||||
|
@ -1,44 +1,35 @@
|
||||
/**
|
||||
* @author: Dennis Hernández
|
||||
* @webSite: http://djhvscf.github.io/Blog
|
||||
* @version: v1.1.0
|
||||
* 基于bootstrap-table-mobile修改
|
||||
* 修正部分iPhone手机不显示卡片视图
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
!function ($) {
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
var showHideColumns = function (that, checked) {
|
||||
if (that.options.columnsHidden.length > 0 ) {
|
||||
$.each(that.columns, function (i, column) {
|
||||
if (that.options.columnsHidden.indexOf(column.field) !== -1) {
|
||||
if (column.visible !== checked) {
|
||||
that.toggleColumn($.fn.bootstrapTable.utils.getFieldIndex(that.columns, column.field), checked, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var resetView = function (that) {
|
||||
if (that.options.height || that.options.showFooter) {
|
||||
setTimeout(function(){
|
||||
that.resetView.call(that);
|
||||
}, 1);
|
||||
setTimeout(that.resetView(), 1);
|
||||
}
|
||||
};
|
||||
|
||||
// 判断是否 iphone
|
||||
var isIPhone = function () {
|
||||
let browserName = navigator.userAgent.toLowerCase();
|
||||
return /(iphone)/i.test(browserName);
|
||||
};
|
||||
|
||||
var changeView = function (that, width, height) {
|
||||
if (that.options.minHeight) {
|
||||
if ((width <= that.options.minWidth) && (height <= that.options.minHeight)) {
|
||||
if (checkValuesLessEqual(width, that.options.minWidth) && checkValuesLessEqual(height, that.options.minHeight)) {
|
||||
conditionCardView(that);
|
||||
} else if ((width > that.options.minWidth) && (height > that.options.minHeight)) {
|
||||
} else if (checkValuesGreater(width, that.options.minWidth) && checkValuesGreater(height, that.options.minHeight)) {
|
||||
conditionFullView(that);
|
||||
}
|
||||
} else {
|
||||
if (width <= that.options.minWidth) {
|
||||
if (checkValuesLessEqual(width, that.options.minWidth) || isIPhone()) {
|
||||
conditionCardView(that);
|
||||
} else if (width > that.options.minWidth) {
|
||||
} else if (checkValuesGreater(width, that.options.minWidth)) {
|
||||
conditionFullView(that);
|
||||
}
|
||||
}
|
||||
@ -46,14 +37,20 @@
|
||||
resetView(that);
|
||||
};
|
||||
|
||||
var checkValuesLessEqual = function (currentValue, targetValue) {
|
||||
return currentValue <= targetValue;
|
||||
};
|
||||
|
||||
var checkValuesGreater = function (currentValue, targetValue) {
|
||||
return currentValue > targetValue;
|
||||
};
|
||||
|
||||
var conditionCardView = function (that) {
|
||||
changeTableView(that, false);
|
||||
showHideColumns(that, false);
|
||||
};
|
||||
|
||||
var conditionFullView = function (that) {
|
||||
changeTableView(that, true);
|
||||
showHideColumns(that, true);
|
||||
};
|
||||
|
||||
var changeTableView = function (that, cardViewState) {
|
||||
@ -61,27 +58,12 @@
|
||||
that.toggleView();
|
||||
};
|
||||
|
||||
var debounce = function(func,wait) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this,
|
||||
args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
func.apply(context,args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
};
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
mobileResponsive: false,
|
||||
minWidth: 562,
|
||||
minHeight: undefined,
|
||||
heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar
|
||||
checkOnInit: true,
|
||||
columnsHidden: []
|
||||
toggled: false
|
||||
});
|
||||
|
||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||
@ -98,39 +80,13 @@
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.options.minWidth < 100 && this.options.resizable) {
|
||||
console.log("The minWidth when the resizable extension is active should be greater or equal than 100");
|
||||
this.options.minWidth = 100;
|
||||
}
|
||||
|
||||
var that = this,
|
||||
old = {
|
||||
width: $(window).width(),
|
||||
height: $(window).height()
|
||||
};
|
||||
|
||||
$(window).on('resize orientationchange',debounce(function (evt) {
|
||||
// reset view if height has only changed by at least the threshold.
|
||||
var height = $(this).height(),
|
||||
width = $(this).width();
|
||||
|
||||
if (Math.abs(old.height - height) > that.options.heightThreshold || old.width != width) {
|
||||
changeView(that, width, height);
|
||||
old = {
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
}
|
||||
},200));
|
||||
var that = this;
|
||||
$(window).resize(function () {
|
||||
changeView(that, $(this).width(), $(this).height())
|
||||
});
|
||||
|
||||
if (this.options.checkOnInit) {
|
||||
var height = $(window).height(),
|
||||
width = $(window).width();
|
||||
changeView(this, width, height);
|
||||
old = {
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
changeView(this, $(window).width(), $(window).height());
|
||||
}
|
||||
};
|
||||
}(jQuery);
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* bootstrap-table - v1.11.0 - 2016-07-02
|
||||
* https://github.com/wenzhixin/bootstrap-table
|
||||
* Copyright (c) 2016 zhixin wen
|
||||
* Licensed MIT License
|
||||
*/
|
||||
!function(a){"use strict";var b=function(b,c){b.options.columnsHidden.length>0&&a.each(b.columns,function(d,e){-1!==b.options.columnsHidden.indexOf(e.field)&&e.visible!==c&&b.toggleColumn(a.fn.bootstrapTable.utils.getFieldIndex(b.columns,e.field),c,!0)})},c=function(a){(a.options.height||a.options.showFooter)&&setTimeout(function(){a.resetView.call(a)},1)},d=function(a,b,d){a.options.minHeight?b<=a.options.minWidth&&d<=a.options.minHeight?e(a):b>a.options.minWidth&&d>a.options.minHeight&&f(a):b<=a.options.minWidth?e(a):b>a.options.minWidth&&f(a),c(a)},e=function(a){g(a,!1),b(a,!1)},f=function(a){g(a,!0),b(a,!0)},g=function(a,b){a.options.cardView=b,a.toggleView()},h=function(a,b){var c;return function(){var d=this,e=arguments,f=function(){c=null,a.apply(d,e)};clearTimeout(c),c=setTimeout(f,b)}};a.extend(a.fn.bootstrapTable.defaults,{mobileResponsive:!1,minWidth:562,minHeight:void 0,heightThreshold:100,checkOnInit:!0,columnsHidden:[]});var i=a.fn.bootstrapTable.Constructor,j=i.prototype.init;i.prototype.init=function(){if(j.apply(this,Array.prototype.slice.apply(arguments)),this.options.mobileResponsive&&this.options.minWidth){this.options.minWidth<100&&this.options.resizable&&(console.log("The minWidth when the resizable extension is active should be greater or equal than 100"),this.options.minWidth=100);var b=this,c={width:a(window).width(),height:a(window).height()};if(a(window).on("resize orientationchange",h(function(){var e=a(this).height(),f=a(this).width();(Math.abs(c.height-e)>b.options.heightThreshold||c.width!=f)&&(d(b,f,e),c={width:f,height:e})},200)),this.options.checkOnInit){var e=a(window).height(),f=a(window).width();d(this,f,e),c={width:f,height:e}}}}}(jQuery);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
@ -0,0 +1,138 @@
|
||||
/**
|
||||
* layer皮肤
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
html #layui_layer_skinmoonstylecss {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 1989px;
|
||||
}
|
||||
|
||||
body .layer-ext-moon[type="dialog"] {
|
||||
min-width: 320px;
|
||||
}
|
||||
body .layer-ext-moon-msg[type="dialog"]{min-width:200px;}
|
||||
body .layer-ext-moon .layui-layer-title {
|
||||
background: #F8F8F8;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
body .layer-ext-moon .layui-layer-content .layui-layer-ico {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
top:18.5px;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-ico0 {
|
||||
background: url(default.png) no-repeat -96px 0;
|
||||
;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-ico1 {
|
||||
background: url(default.png) no-repeat -224px 0;
|
||||
;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-ico2 {
|
||||
background: url(default.png) no-repeat -192px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-ico3 {
|
||||
background: url(default.png) no-repeat -160px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-ico4 {
|
||||
background: url(default.png) no-repeat -320px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-ico5 {
|
||||
background: url(default.png) no-repeat -288px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-ico6 {
|
||||
background: url(default.png) -256px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-ico7 {
|
||||
background: url(default.png) no-repeat -128px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin {
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin a {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin .layui-layer-min cite:hover {
|
||||
background-color: #56abe4;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin .layui-layer-max {
|
||||
background: url(default.png) no-repeat -80px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin .layui-layer-max:hover {
|
||||
background: url(default.png) no-repeat -64px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin {
|
||||
background: url(default.png) no-repeat -32px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin .layui-layer-maxmin:hover {
|
||||
background: url(default.png) no-repeat -16px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin .layui-layer-close1,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2 {
|
||||
background: url(default.png) 0 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-setwin .layui-layer-close1:hover,body .layer-ext-moon .layui-layer-setwin .layui-layer-close2:hover {
|
||||
background: url(default.png) -48px 0;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-padding{padding-top: 24px;}
|
||||
body .layer-ext-moon .layui-layer-btn {
|
||||
text-align: right;
|
||||
padding: 10px 15px 12px;
|
||||
background: #f0f4f7;
|
||||
border-top: 1px #c7c7c7 solid;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-btn a {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
margin: 0 3px;
|
||||
margin-right: 7px;
|
||||
margin-left: 7px;
|
||||
padding: 0 15px;
|
||||
color: #fff;
|
||||
border: 1px solid #0064b6;
|
||||
background: #0071ce;
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
background-repeat: no-repeat;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-btn .layui-layer-btn0 {
|
||||
background: #0071ce;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-btn .layui-layer-btn1 {
|
||||
background: #fff;
|
||||
color: #404a58;
|
||||
border: 1px solid #c0c4cd;
|
||||
border-radius: 3px;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-btn .layui-layer-btn2 {
|
||||
background: #f60;
|
||||
color: #fff;
|
||||
border: 1px solid #f60;
|
||||
border-radius: 3px;
|
||||
}
|
||||
body .layer-ext-moon .layui-layer-btn .layui-layer-btn3 {
|
||||
background: #f00;
|
||||
color: #fff;
|
||||
border: 1px solid #f00;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
body .layer-ext-moon .layui-layer-title span.layui-layer-tabnow{
|
||||
height:47px;
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -1,28 +1,46 @@
|
||||
(function ($) {
|
||||
(function($) {
|
||||
$.extend($.summernote.lang, {
|
||||
'zh-CN': {
|
||||
font: {
|
||||
bold: '粗体',
|
||||
italic: '斜体',
|
||||
underline: '下划线',
|
||||
strikethrough: '删除线',
|
||||
clear: '清除格式',
|
||||
height: '行高',
|
||||
name: '字体',
|
||||
strikethrough: '删除线',
|
||||
subscript: '下标',
|
||||
superscript: '上标',
|
||||
size: '字号'
|
||||
},
|
||||
image: {
|
||||
image: '图片',
|
||||
insert: '插入图片',
|
||||
resizeFull: '调整至 100%',
|
||||
resizeHalf: '调整至 50%',
|
||||
resizeQuarter: '调整至 25%',
|
||||
floatLeft: '左浮动',
|
||||
floatRight: '右浮动',
|
||||
floatNone: '不浮动',
|
||||
dragImageHere: '将图片拖至此处',
|
||||
resizeFull: '缩放至 100%',
|
||||
resizeHalf: '缩放至 50%',
|
||||
resizeQuarter: '缩放至 25%',
|
||||
floatLeft: '靠左浮动',
|
||||
floatRight: '靠右浮动',
|
||||
floatNone: '取消浮动',
|
||||
shapeRounded: '形状: 圆角',
|
||||
shapeCircle: '形状: 圆',
|
||||
shapeThumbnail: '形状: 缩略图',
|
||||
shapeNone: '形状: 无',
|
||||
dragImageHere: '将图片拖拽至此处',
|
||||
dropImage: '拖拽图片或文本',
|
||||
selectFromFiles: '从本地上传',
|
||||
url: '图片地址'
|
||||
maximumFileSize: '文件大小最大值',
|
||||
maximumFileSizeError: '文件大小超出最大值。',
|
||||
url: '图片地址',
|
||||
remove: '移除图片',
|
||||
original: '原始图片'
|
||||
},
|
||||
video: {
|
||||
video: '视频',
|
||||
videoLink: '视频链接',
|
||||
insert: '插入视频',
|
||||
url: '视频地址',
|
||||
providers: '(优酷, 腾讯, Instagram, DailyMotion, Youtube等)'
|
||||
},
|
||||
link: {
|
||||
link: '链接',
|
||||
@ -33,22 +51,22 @@
|
||||
url: '链接地址',
|
||||
openInNewWindow: '在新窗口打开'
|
||||
},
|
||||
video: {
|
||||
video: '视频',
|
||||
videoLink: '视频链接',
|
||||
insert: '插入视频',
|
||||
url: '视频地址',
|
||||
providers: '(优酷, Instagram, DailyMotion, Youtube等)'
|
||||
},
|
||||
table: {
|
||||
table: '表格'
|
||||
table: '表格',
|
||||
addRowAbove: '在上方插入行',
|
||||
addRowBelow: '在下方插入行',
|
||||
addColLeft: '在左侧插入列',
|
||||
addColRight: '在右侧插入列',
|
||||
delRow: '删除行',
|
||||
delCol: '删除列',
|
||||
delTable: '删除表格'
|
||||
},
|
||||
hr: {
|
||||
insert: '水平线'
|
||||
},
|
||||
style: {
|
||||
style: '样式',
|
||||
normal: '普通',
|
||||
p: '普通',
|
||||
blockquote: '引用',
|
||||
pre: '代码',
|
||||
h1: '标题 1',
|
||||
@ -92,11 +110,45 @@
|
||||
textFormatting: '文本格式',
|
||||
action: '动作',
|
||||
paragraphFormatting: '段落格式',
|
||||
documentStyle: '文档样式'
|
||||
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: '选取特殊字符'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,3 +1,3 @@
|
||||
/*! Summernote v0.8.8 | (c) 2013- Alan Hong and other contributors | MIT license */
|
||||
/*! Summernote v0.8.11 | (c) 2013- Alan Hong and other contributors | MIT license */
|
||||
|
||||
!function(a){a.extend(a.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:"将图片拖拽至此处",selectFromFiles:"从本地上传",maximumFileSize:"文件大小最大值",maximumFileSizeError:"文件大小超出最大值。",url:"图片地址",remove:"移除图片"},video:{video:"视频",videoLink:"视频链接",insert:"插入视频",url:"视频地址",providers:"(优酷, 腾讯, Instagram, DailyMotion, Youtube等)"},link:{link:"链接",insert:"插入链接",unlink:"去除链接",edit:"编辑链接",textToDisplay:"显示文本",url:"链接地址",openInNewWindow:"在新窗口打开"},table:{table:"表格"},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:"额外按键"},history:{undo:"撤销",redo:"重做"},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":"显示链接对话框"}}})}(jQuery);
|
||||
!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 it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -84,3 +84,65 @@ body.signin {
|
||||
width:auto
|
||||
}
|
||||
}
|
||||
/*
|
||||
<EFBFBD><EFBFBD>¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD>check<EFBFBD><EFBFBD>ʽ
|
||||
*/
|
||||
.checkbox-custom {
|
||||
position: relative;
|
||||
padding: 0 15px 0 25px;
|
||||
margin-bottom: 7px;
|
||||
margin-top: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
/*
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>checkbox<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>ı<EFBFBD>
|
||||
*/
|
||||
.checkbox-custom input[type="checkbox"] {
|
||||
opacity: 0;/*<2A><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>checkbox<6F><78><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
margin: -6px 0 0 0;
|
||||
top: 50%;
|
||||
left: 3px;
|
||||
}
|
||||
/*
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>checkbox<EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>
|
||||
*/
|
||||
.checkbox-custom label:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -9px;
|
||||
width: 18px;
|
||||
height: 17px;
|
||||
display: inline-block;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #bbb;
|
||||
background: #fff;
|
||||
}
|
||||
/*
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>checkbox<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µ<EFBFBD>checkbox<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
*/
|
||||
.checkbox-custom input[type="checkbox"]:checked +label:after {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
font-family: 'Glyphicons Halflings';
|
||||
content: "\e013";
|
||||
top: 42%;
|
||||
left: 3px;
|
||||
margin-top: -5px;
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: #333;
|
||||
}
|
||||
.checkbox-custom label {
|
||||
cursor: pointer;
|
||||
line-height: 1.2;
|
||||
font-weight: normal;/*<2A>ı<EFBFBD><C4B1><EFBFBD>rememberme<6D><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
|
||||
margin-bottom: 0;
|
||||
text-align: left;
|
||||
}
|
@ -1 +1 @@
|
||||
html{height:100%}body.signin{height:auto;background:url(../img/login-background.jpg) no-repeat center fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;color:rgba(255,255,255,.95)}.signinpanel{width:750px;margin:10% auto 0}.signinpanel .logopanel{float:none;width:auto;padding:0;background:0 0}.signinpanel .signin-info ul{list-style:none;padding:0;margin:20px 0}.signinpanel .form-control{display:block;margin-top:15px}.signinpanel .uname{background:#fff url(../img/user.png) no-repeat 95% center;color:#333}.signinpanel .pword{background:#fff url(../img/locked.png) no-repeat 95% center;color:#333}.signinpanel .code{background:#fff no-repeat 95% center;color:#333;margin:0 0 15px 0}.signinpanel .btn{margin-top:15px}.signinpanel form{background:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.3);-moz-box-shadow:0 3px 0 rgba(12,12,12,.03);-webkit-box-shadow:0 3px 0 rgba(12,12,12,.03);box-shadow:0 3px 0 rgba(12,12,12,.03);-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;padding:30px}.signup-footer{border-top:solid 1px rgba(255,255,255,.3);margin:20px 0;padding-top:15px}@media screen and (max-width:768px){.signinpanel,.signuppanel{margin:0 auto;width:420px!important;padding:20px}.signinpanel form{margin-top:20px}.signup-footer,.signuppanel .form-control{margin-bottom:10px}.signup-footer .pull-left,.signup-footer .pull-right{float:none!important;text-align:center}.signinpanel .signin-info ul{display:none}}@media screen and (max-width:320px){.signinpanel,.signuppanel{margin:0 20px;width:auto}}
|
||||
html{height:100%}body.signin{height:auto;background:url(../img/login-background.jpg) no-repeat center fixed;-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;color:rgba(255,255,255,.95)}.signinpanel{width:750px;margin:10% auto 0}.signinpanel .logopanel{float:none;width:auto;padding:0;background:0}.signinpanel .signin-info ul{list-style:none;padding:0;margin:20px 0}.signinpanel .form-control{display:block;margin-top:15px}.signinpanel .uname{background:#fff url(../img/user.png) no-repeat 95% center;color:#333}.signinpanel .pword{background:#fff url(../img/locked.png) no-repeat 95% center;color:#333}.signinpanel .code{background:#fff no-repeat 95% center;color:#333;margin:0 0 15px 0}.signinpanel .btn{margin-top:15px}.signinpanel form{background:rgba(255,255,255,.2);border:1px solid rgba(255,255,255,.3);-moz-box-shadow:0 3px 0 rgba(12,12,12,.03);-webkit-box-shadow:0 3px 0 rgba(12,12,12,.03);box-shadow:0 3px 0 rgba(12,12,12,.03);-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;padding:30px}.signup-footer{border-top:solid 1px rgba(255,255,255,.3);margin:20px 0;padding-top:15px}@media screen and (max-width:768px){.signinpanel,.signuppanel{margin:0 auto;width:420px!important;padding:20px}.signinpanel form{margin-top:20px}.signup-footer,.signuppanel .form-control{margin-bottom:10px}.signup-footer .pull-left,.signup-footer .pull-right{float:none!important;text-align:center}.signinpanel .signin-info ul{display:none}}@media screen and (max-width:320px){.signinpanel,.signuppanel{margin:0 20px;width:auto}}.checkbox-custom{position:relative;padding:0 15px 0 25px;margin-bottom:7px;margin-top:0;display:inline-block}.checkbox-custom input[type="checkbox"]{opacity:0;position:absolute;cursor:pointer;z-index:2;margin:-6px 0 0 0;top:50%;left:3px}.checkbox-custom label:before{content:'';position:absolute;top:50%;left:0;margin-top:-9px;width:18px;height:17px;display:inline-block;border-radius:2px;border:1px solid #bbb;background:#fff}.checkbox-custom input[type="checkbox"]:checked+label:after{position:absolute;display:inline-block;font-family:'Glyphicons Halflings';content:"\e013";top:42%;left:3px;margin-top:-5px;font-size:11px;line-height:1;width:16px;height:16px;color:#333}.checkbox-custom label{cursor:pointer;line-height:1.2;font-weight:normal;margin-bottom:0;text-align:left}
|
822
ruoyi-admin/src/main/resources/static/css/skins.css
Normal file
822
ruoyi-admin/src/main/resources/static/css/skins.css
Normal file
@ -0,0 +1,822 @@
|
||||
/*
|
||||
*
|
||||
* SKIN blue 若依管理系统
|
||||
* NAME - blue/green/purple/red/yellow
|
||||
*
|
||||
*/
|
||||
/** 蓝色主题 skin-blue **/
|
||||
.skin-blue .navbar {
|
||||
background-color: #3c8dbc
|
||||
}
|
||||
|
||||
.skin-blue .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-blue .navbar .nav>li>a:hover,
|
||||
.skin-blue .navbar .nav>li>a:active,
|
||||
.skin-blue .navbar .nav>li>a:focus,
|
||||
.skin-blue .navbar .nav .open>a,
|
||||
.skin-blue .navbar .nav .open>a:hover,
|
||||
.skin-blue .navbar .nav .open>a:focus,
|
||||
.skin-blue .navbar .nav>.active>a {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #f6f6f6
|
||||
}
|
||||
|
||||
.skin-blue .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-blue .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
|
||||
.skin-blue .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-blue .navbar .sidebar-toggle:hover {
|
||||
background-color: #367fa9
|
||||
}
|
||||
|
||||
@media ( max-width :767px) {
|
||||
.skin-blue .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1)
|
||||
}
|
||||
.skin-blue .navbar .dropdown-menu li a {
|
||||
color: #fff
|
||||
}
|
||||
.skin-blue .navbar .dropdown-menu li a:hover {
|
||||
background: #367fa9
|
||||
}
|
||||
}
|
||||
|
||||
.skin-blue .logo {
|
||||
background-color: #367fa9;
|
||||
color: #fff;
|
||||
border-bottom: 0 solid transparent
|
||||
}
|
||||
|
||||
.skin-blue .logo:hover {
|
||||
background-color: #357ca5
|
||||
}
|
||||
|
||||
.skin-blue li.user-header {
|
||||
background-color: #3c8dbc
|
||||
}
|
||||
|
||||
.skin-blue .content-header {
|
||||
background: transparent
|
||||
}
|
||||
|
||||
.skin-blue .wrapper,
|
||||
.skin-blue .main-sidebar,
|
||||
.skin-blue .left-side {
|
||||
background-color: #222d32
|
||||
}
|
||||
|
||||
.skin-blue .user-panel>.info,
|
||||
.skin-blue .user-panel>.info>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-blue .nav>li.header {
|
||||
color: #4b646f;
|
||||
background: #1a2226
|
||||
}
|
||||
|
||||
.skin-blue .nav>li.active {
|
||||
color: #fff;
|
||||
background: #293846;
|
||||
border-left: 3px solid #3c8dbc;
|
||||
}
|
||||
|
||||
.skin-blue .nav>li.active:last-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.skin-blue .nav>li>.treeview-menu {
|
||||
margin: 0 1px;
|
||||
background: #2c3b41
|
||||
}
|
||||
|
||||
.skin-blue .sidebar a {
|
||||
color: #b8c7ce
|
||||
}
|
||||
|
||||
.skin-blue .sidebar a:hover {
|
||||
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;
|
||||
margin: 10px 10px
|
||||
}
|
||||
|
||||
.skin-blue .sidebar-form input[type="text"],
|
||||
.skin-blue .sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #374850;
|
||||
border: 1px solid transparent;
|
||||
height: 35px
|
||||
}
|
||||
|
||||
.skin-blue .sidebar-form input[type="text"] {
|
||||
color: #666;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px
|
||||
}
|
||||
|
||||
.skin-blue .sidebar-form input[type="text"]:focus,
|
||||
.skin-blue .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666
|
||||
}
|
||||
|
||||
.skin-blue .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
border-left-color: #fff
|
||||
}
|
||||
|
||||
.skin-blue .sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0
|
||||
}
|
||||
|
||||
.skin-blue.layout-top-nav>.logo {
|
||||
background-color: #3c8dbc;
|
||||
color: #fff;
|
||||
border-bottom: 0 solid transparent
|
||||
}
|
||||
|
||||
.skin-blue.layout-top-nav>.logo:hover {
|
||||
background-color: #3b8ab8
|
||||
}
|
||||
|
||||
.skin-blue .content-tabs {
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
}
|
||||
|
||||
.skin-blue.layout-top-nav>.logo {
|
||||
background-color: #3c8dbc;
|
||||
color: #fff;
|
||||
border-bottom: 0 solid transparent
|
||||
}
|
||||
|
||||
.skin-blue.layout-top-nav>.logo:hover {
|
||||
background-color: #3b8ab8
|
||||
}
|
||||
|
||||
/** 绿色主题 skin-green **/
|
||||
.skin-green .navbar {
|
||||
background-color: #00a65a;
|
||||
}
|
||||
|
||||
.skin-green .content-tabs {
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
}
|
||||
|
||||
.skin-green .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-green .navbar .nav>li>a:hover,
|
||||
.skin-green .navbar .nav>li>a:active,
|
||||
.skin-green .navbar .nav>li>a:focus,
|
||||
.skin-green .navbar .nav .open>a,
|
||||
.skin-green .navbar .nav .open>a:hover,
|
||||
.skin-green .navbar .nav .open>a:focus,
|
||||
.skin-green .navbar .nav>.active>a {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #f6f6f6
|
||||
}
|
||||
|
||||
.skin-green .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-green .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
|
||||
.skin-green .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-green .navbar .sidebar-toggle:hover {
|
||||
background-color: #008d4c
|
||||
}
|
||||
|
||||
@media ( max-width :767px) {
|
||||
.skin-green .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1)
|
||||
}
|
||||
.skin-green .navbar .dropdown-menu li a {
|
||||
color: #fff
|
||||
}
|
||||
.skin-green .navbar .dropdown-menu li a:hover {
|
||||
background: #008d4c
|
||||
}
|
||||
}
|
||||
|
||||
.skin-green .logo {
|
||||
background-color: #008d4c;
|
||||
color: #fff;
|
||||
border-bottom: 0 solid transparent
|
||||
}
|
||||
|
||||
.skin-green .logo:hover {
|
||||
background-color: #008749
|
||||
}
|
||||
|
||||
.skin-green li.user-header {
|
||||
background-color: #00a65a
|
||||
}
|
||||
|
||||
.skin-green .content-header {
|
||||
background: transparent
|
||||
}
|
||||
|
||||
.skin-green .wrapper,
|
||||
.skin-green .main-sidebar,
|
||||
.skin-green .left-side {
|
||||
background-color: #222d32
|
||||
}
|
||||
|
||||
.skin-green .user-panel>.info,
|
||||
.skin-green .user-panel>.info>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-green .nav>li.header {
|
||||
color: #4b646f;
|
||||
background: #1a2226;
|
||||
}
|
||||
|
||||
.skin-green .nav>li.active {
|
||||
color: #fff;
|
||||
background: #293846;
|
||||
border-left: 3px solid #00a65a;
|
||||
}
|
||||
|
||||
.skin-green .nav>li.active:last-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.skin-green .nav>li>.treeview-menu {
|
||||
margin: 0 1px;
|
||||
background: #2c3b41
|
||||
}
|
||||
|
||||
.skin-green .sidebar a {
|
||||
color: #b8c7ce
|
||||
}
|
||||
|
||||
.skin-green .sidebar a:hover {
|
||||
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;
|
||||
margin: 10px 10px
|
||||
}
|
||||
|
||||
.skin-green .sidebar-form input[type="text"],
|
||||
.skin-green .sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #374850;
|
||||
border: 1px solid transparent;
|
||||
height: 35px
|
||||
}
|
||||
|
||||
.skin-green .sidebar-form input[type="text"] {
|
||||
color: #666;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px
|
||||
}
|
||||
|
||||
.skin-green .sidebar-form input[type="text"]:focus,
|
||||
.skin-green .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666
|
||||
}
|
||||
|
||||
.skin-green .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
border-left-color: #fff
|
||||
}
|
||||
|
||||
.skin-green .sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0
|
||||
}
|
||||
|
||||
/** 红色主题 skin-red **/
|
||||
.skin-red .navbar {
|
||||
background-color: #dd4b39
|
||||
}
|
||||
|
||||
.skin-red .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-red .navbar .nav>li>a:hover,
|
||||
.skin-red .navbar .nav>li>a:active,
|
||||
.skin-red .navbar .nav>li>a:focus,
|
||||
.skin-red .navbar .nav .open>a,
|
||||
.skin-red .navbar .nav .open>a:hover,
|
||||
.skin-red .navbar .nav .open>a:focus,
|
||||
.skin-red .navbar .nav>.active>a {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #f6f6f6
|
||||
}
|
||||
|
||||
.skin-red .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-red .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
|
||||
.skin-red .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-red .navbar .sidebar-toggle:hover {
|
||||
background-color: #d73925
|
||||
}
|
||||
|
||||
@media ( max-width :767px) {
|
||||
.skin-red .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1)
|
||||
}
|
||||
.skin-red .navbar .dropdown-menu li a {
|
||||
color: #fff
|
||||
}
|
||||
.skin-red .navbar .dropdown-menu li a:hover {
|
||||
background: #d73925
|
||||
}
|
||||
}
|
||||
|
||||
.skin-red .logo {
|
||||
background-color: #d73925;
|
||||
color: #fff;
|
||||
border-bottom: 0 solid transparent
|
||||
}
|
||||
|
||||
.skin-red .logo:hover {
|
||||
background-color: #d33724
|
||||
}
|
||||
|
||||
.skin-red li.user-header {
|
||||
background-color: #dd4b39
|
||||
}
|
||||
|
||||
.skin-red .content-header {
|
||||
background: transparent
|
||||
}
|
||||
|
||||
.skin-red .wrapper,
|
||||
.skin-red .main-sidebar,
|
||||
.skin-red .left-side {
|
||||
background-color: #222d32
|
||||
}
|
||||
|
||||
.skin-red .user-panel>.info,
|
||||
.skin-red .user-panel>.info>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-red .nav>li.header {
|
||||
color: #4b646f;
|
||||
background: #1a2226
|
||||
}
|
||||
|
||||
.skin-red .nav>li.active {
|
||||
color: #fff;
|
||||
border-left: 3px solid #dd4b39;
|
||||
background: #293846;
|
||||
}
|
||||
|
||||
.skin-red .nav>li.active:last-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.skin-red .content-tabs {
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
}
|
||||
|
||||
.skin-red .nav>li>.treeview-menu {
|
||||
margin: 0 1px;
|
||||
background: #2c3b41
|
||||
}
|
||||
|
||||
.skin-red .sidebar a {
|
||||
color: #b8c7ce
|
||||
}
|
||||
|
||||
.skin-red .sidebar a:hover {
|
||||
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;
|
||||
margin: 10px 10px
|
||||
}
|
||||
|
||||
.skin-red .sidebar-form input[type="text"],
|
||||
.skin-red .sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #374850;
|
||||
border: 1px solid transparent;
|
||||
height: 35px
|
||||
}
|
||||
|
||||
.skin-red .sidebar-form input[type="text"] {
|
||||
color: #fff;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px
|
||||
}
|
||||
|
||||
.skin-red .sidebar-form input[type="text"]:focus,
|
||||
.skin-red .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666
|
||||
}
|
||||
|
||||
.skin-red .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
border-left-color: #fff
|
||||
}
|
||||
|
||||
.skin-red .sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0
|
||||
}
|
||||
|
||||
/** 黄色主题 skin-red **/
|
||||
.skin-yellow .navbar {
|
||||
background-color: #f39c12
|
||||
}
|
||||
|
||||
.skin-yellow .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-yellow .navbar .nav>li>a:hover,
|
||||
.skin-yellow .navbar .nav>li>a:active,
|
||||
.skin-yellow .navbar .nav>li>a:focus,
|
||||
.skin-yellow .navbar .nav .open>a,
|
||||
.skin-yellow .navbar .nav .open>a:hover,
|
||||
.skin-yellow .navbar .nav .open>a:focus,
|
||||
.skin-yellow .navbar .nav>.active>a {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #f6f6f6
|
||||
}
|
||||
|
||||
.skin-yellow .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-yellow .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
|
||||
.skin-yellow .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-yellow .navbar .sidebar-toggle:hover {
|
||||
background-color: #e08e0b
|
||||
}
|
||||
|
||||
@media ( max-width :767px) {
|
||||
.skin-yellow .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1)
|
||||
}
|
||||
.skin-yellow .navbar .dropdown-menu li a {
|
||||
color: #fff
|
||||
}
|
||||
.skin-yellow .navbar .dropdown-menu li a:hover {
|
||||
background: #e08e0b
|
||||
}
|
||||
}
|
||||
|
||||
.skin-yellow .logo {
|
||||
background-color: #e08e0b;
|
||||
color: #fff;
|
||||
border-bottom: 0 solid transparent
|
||||
}
|
||||
|
||||
.skin-yellow .logo:hover {
|
||||
background-color: #db8b0b
|
||||
}
|
||||
|
||||
.skin-yellow li.user-header {
|
||||
background-color: #f39c12
|
||||
}
|
||||
|
||||
.skin-yellow .content-header {
|
||||
background: transparent
|
||||
}
|
||||
|
||||
.skin-yellow .wrapper,
|
||||
.skin-yellow .main-sidebar,
|
||||
.skin-yellow .left-side {
|
||||
background-color: #222d32
|
||||
}
|
||||
|
||||
.skin-yellow .user-panel>.info,
|
||||
.skin-yellow .user-panel>.info>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li.header {
|
||||
color: #4b646f;
|
||||
background: #1a2226
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li.active {
|
||||
color: #fff;
|
||||
background: #293846;
|
||||
border-left: 3px solid #f39c12;
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li.active:last-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.skin-yellow .content-tabs {
|
||||
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li>.treeview-menu {
|
||||
margin: 0 1px;
|
||||
background: #2c3b41
|
||||
}
|
||||
|
||||
.skin-yellow .sidebar a {
|
||||
color: #b8c7ce
|
||||
}
|
||||
|
||||
.skin-yellow .sidebar a:hover {
|
||||
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;
|
||||
margin: 10px 10px
|
||||
}
|
||||
|
||||
.skin-yellow .sidebar-form input[type="text"],
|
||||
.skin-yellow .sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #374850;
|
||||
border: 1px solid transparent;
|
||||
height: 35px
|
||||
}
|
||||
|
||||
.skin-yellow .sidebar-form input[type="text"] {
|
||||
color: #666;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px
|
||||
}
|
||||
|
||||
.skin-yellow .sidebar-form input[type="text"]:focus,
|
||||
.skin-yellow .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666
|
||||
}
|
||||
|
||||
.skin-yellow .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
border-left-color: #fff
|
||||
}
|
||||
|
||||
.skin-yellow .sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0
|
||||
}
|
||||
|
||||
/** 紫色主题 skin-purple **/
|
||||
.skin-purple .navbar {
|
||||
background-color: #605ca8
|
||||
}
|
||||
|
||||
.skin-purple .navbar .nav>li>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-purple .navbar .nav>li>a:hover,
|
||||
.skin-purple .navbar .nav>li>a:active,
|
||||
.skin-purple .navbar .nav>li>a:focus,
|
||||
.skin-purple .navbar .nav .open>a,
|
||||
.skin-purple .navbar .nav .open>a:hover,
|
||||
.skin-purple .navbar .nav .open>a:focus,
|
||||
.skin-purple .navbar .nav>.active>a {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
color: #f6f6f6
|
||||
}
|
||||
|
||||
.skin-purple .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-purple .navbar .sidebar-toggle:hover {
|
||||
color: #f6f6f6;
|
||||
background: rgba(0, 0, 0, 0.1)
|
||||
}
|
||||
|
||||
.skin-purple .navbar .sidebar-toggle {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-purple .navbar .sidebar-toggle:hover {
|
||||
background-color: #555299
|
||||
}
|
||||
|
||||
@media ( max-width :767px) {
|
||||
.skin-purple .navbar .dropdown-menu li.divider {
|
||||
background-color: rgba(255, 255, 255, 0.1)
|
||||
}
|
||||
.skin-purple .navbar .dropdown-menu li a {
|
||||
color: #fff
|
||||
}
|
||||
.skin-purple .navbar .dropdown-menu li a:hover {
|
||||
background: #555299
|
||||
}
|
||||
}
|
||||
|
||||
.skin-purple .logo {
|
||||
background-color: #555299;
|
||||
color: #fff;
|
||||
border-bottom: 0 solid transparent
|
||||
}
|
||||
|
||||
.skin-purple .logo:hover {
|
||||
background-color: #545096
|
||||
}
|
||||
|
||||
.skin-purple li.user-header {
|
||||
background-color: #605ca8
|
||||
}
|
||||
|
||||
.skin-purple .content-header {
|
||||
background: transparent
|
||||
}
|
||||
|
||||
.skin-purple .wrapper,
|
||||
.skin-purple .main-sidebar,
|
||||
.skin-purple .left-side {
|
||||
background-color: #222d32
|
||||
}
|
||||
|
||||
.skin-purple .user-panel>.info,
|
||||
.skin-purple .user-panel>.info>a {
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.skin-purple .nav>li.header {
|
||||
color: #4b646f;
|
||||
background: #1a2226
|
||||
}
|
||||
|
||||
.skin-purple .nav>li.active {
|
||||
color: #fff;
|
||||
background: #293846;
|
||||
border-left: 3px solid #605ca8;
|
||||
}
|
||||
|
||||
.skin-purple .nav>li.active:last-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.skin-purple .content-tabs {
|
||||
|
||||
border-bottom: solid 2px #e7eaec;
|
||||
}
|
||||
|
||||
.skin-purple .nav>li>.treeview-menu {
|
||||
margin: 0 1px;
|
||||
background: #2c3b41
|
||||
}
|
||||
|
||||
.skin-purple .sidebar a {
|
||||
color: #b8c7ce
|
||||
}
|
||||
|
||||
.skin-purple .sidebar a:hover {
|
||||
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;
|
||||
margin: 10px 10px
|
||||
}
|
||||
|
||||
.skin-purple .sidebar-form input[type="text"],
|
||||
.skin-purple .sidebar-form .btn {
|
||||
box-shadow: none;
|
||||
background-color: #374850;
|
||||
border: 1px solid transparent;
|
||||
height: 35px
|
||||
}
|
||||
|
||||
.skin-purple .sidebar-form input[type="text"] {
|
||||
color: #666;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 2px
|
||||
}
|
||||
|
||||
.skin-purple .sidebar-form input[type="text"]:focus,
|
||||
.skin-purple .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
background-color: #fff;
|
||||
color: #666
|
||||
}
|
||||
|
||||
.skin-purple .sidebar-form input[type="text"]:focus+.input-group-btn .btn {
|
||||
border-left-color: #fff
|
||||
}
|
||||
|
||||
.skin-purple .sidebar-form .btn {
|
||||
color: #999;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
border-bottom-left-radius: 0
|
||||
}
|
@ -47,28 +47,44 @@ a:focus {
|
||||
}
|
||||
|
||||
.nav.navbar-right>li>a {
|
||||
color: #999c9e;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
height: 50px;
|
||||
padding: 18px 15px;
|
||||
}
|
||||
|
||||
.nav>li.active>a {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.navbar-default .nav>li>a:hover, .navbar-default .nav>li>a:focus {
|
||||
background-color: #293846;
|
||||
color: white;
|
||||
.nav.navbar-right>li>a>.label {
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
right: 5px;
|
||||
text-align: center;
|
||||
font-size: 9px;
|
||||
padding: 2px 4px;
|
||||
line-height: .9;
|
||||
}
|
||||
.nav.navbar-right>li>a:hover {
|
||||
background-color: #367fa9;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav .open>a, .nav .open>a:hover, .nav .open>a:focus {
|
||||
background: #fff;
|
||||
.navbar-default .nav>li>a:hover,
|
||||
.navbar-default .nav>li>a:focus {
|
||||
background-color: #293846;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav>li>a i {
|
||||
margin-right: 6px;
|
||||
.nav .open>a,
|
||||
.nav .open>a:hover,
|
||||
.nav .open>a:focus {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
border: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.navbar-default {
|
||||
@ -77,12 +93,12 @@ a:focus {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.navbar-top-links li {
|
||||
display: inline-block;
|
||||
.nav.navbar-top-links li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.navbar-top-links li:last-child {
|
||||
margin-right: 30px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
body.body-small .navbar-top-links li:last-child {
|
||||
@ -179,7 +195,7 @@ body.body-small .navbar-top-links li:last-child {
|
||||
}
|
||||
|
||||
.nav-header {
|
||||
padding: 33px 25px;
|
||||
padding: 34px 25px 20px 25px;
|
||||
background: url("patterns/header-profile.png") no-repeat;
|
||||
}
|
||||
|
||||
@ -211,7 +227,7 @@ body.body-small .navbar-top-links li:last-child {
|
||||
|
||||
.minimalize-styl-2 {
|
||||
padding: 4px 12px;
|
||||
margin: 14px 5px 5px 20px;
|
||||
margin: 12px 5px 5px 15px;
|
||||
font-size: 14px;
|
||||
float: left;
|
||||
}
|
||||
@ -368,10 +384,6 @@ body.mini-navbar .navbar-default .nav>li>.nav-second-level li a {
|
||||
z-index: 2030;
|
||||
}
|
||||
|
||||
.navbar-fixed-top, .navbar-static-top {
|
||||
background: #f3f3f4;
|
||||
}
|
||||
|
||||
.fixed-nav #wrapper {
|
||||
padding-top: 60px;
|
||||
box-sizing: border-box;
|
||||
@ -460,18 +472,6 @@ body.body-small.fixed-sidebar.mini-navbar .navbar-static-side {
|
||||
.fixed-sidebar.mini-navbar .nav li.active {
|
||||
border-left-width: 0;
|
||||
}
|
||||
/*.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level, .canvas-menu.mini-navbar .nav li:hover>.nav-second-level*/
|
||||
/*{*/
|
||||
/*position: absolute;*/
|
||||
/*left: 70px;*/
|
||||
/*top: 40px;*/
|
||||
/*background-color: #2f4050;*/
|
||||
/*padding: 10px 10px 0 10px;*/
|
||||
/*font-size: 12px;*/
|
||||
/*display: block;*/
|
||||
/*min-width: 140px;*/
|
||||
/*border-radius: 2px;*/
|
||||
/*}*/
|
||||
|
||||
/*伸缩菜单*/
|
||||
.fixed-sidebar.mini-navbar .nav li:hover>a> span.nav-label {
|
||||
@ -485,7 +485,6 @@ body.body-small.fixed-sidebar.mini-navbar .navbar-static-side {
|
||||
.fixed-sidebar.mini-navbar .nav li:hover>.nav-second-level {
|
||||
top: 40px;
|
||||
font-size: 12px;
|
||||
/*padding: 10px 10px 0 10px;*/
|
||||
background-color: #2f4050;
|
||||
}
|
||||
|
||||
@ -5507,8 +5506,8 @@ del {
|
||||
}
|
||||
|
||||
20% {
|
||||
-webkit-transform: scaleY (1);
|
||||
transform: scaleY (1);
|
||||
-webkit-transform: scaleY(1);
|
||||
transform: scaleY(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5567,20 +5566,20 @@ del {
|
||||
transform: translateX(42px) translateY(42px) rotate(-179deg);
|
||||
}
|
||||
|
||||
50 .1 % {
|
||||
-webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);
|
||||
transform: translateX(42px) translateY(42px) rotate(-180deg);
|
||||
}
|
||||
50.1% {
|
||||
-webkit-transform: translateX(42px) translateY(42px) rotate(-180deg);
|
||||
transform: translateX(42px) translateY(42px) rotate(-180deg);
|
||||
}
|
||||
|
||||
75% {
|
||||
-webkit-transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0 .5 );
|
||||
transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0 .5 );
|
||||
}
|
||||
75% {
|
||||
-webkit-transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0 .5 );
|
||||
transform: translateX(0px) translateY(42px) rotate(-270deg) scale(0 .5 );
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(-360deg);
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(-360deg);
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sk-wanderingCubeMove {
|
||||
@ -6567,391 +6566,24 @@ body.rtls .top-navigation .footer.fixed, body.rtls.top-navigation .footer.fixed
|
||||
.rtls .ltr-support {
|
||||
direction: ltr;
|
||||
}
|
||||
/*
|
||||
*
|
||||
* This is style for skin config
|
||||
* Use only in demo theme
|
||||
*
|
||||
*/
|
||||
.skin-setttings .title {
|
||||
background: #efefef;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
display: block;
|
||||
padding: 10px 15px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.setings-item {
|
||||
padding: 10px 30px;
|
||||
}
|
||||
|
||||
.setings-item.nb {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.setings-item.skin {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.setings-item .switch {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.skin-name a {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.setings-item a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.default-skin, .blue-skin, .ultra-skin, .yellow-skin {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.default-skin {
|
||||
font-weight: 600;
|
||||
background: #1ab394;
|
||||
}
|
||||
|
||||
.default-skin:hover {
|
||||
background: #199d82;
|
||||
}
|
||||
|
||||
.blue-skin {
|
||||
font-weight: 600;
|
||||
background: url("patterns/header-profile-skin-blue.png") repeat scroll 0 0;
|
||||
}
|
||||
|
||||
.blue-skin:hover {
|
||||
background: #0d8ddb;
|
||||
}
|
||||
|
||||
.yellow-skin {
|
||||
font-weight: 600;
|
||||
background: url("patterns/header-profile-skin-yellow.png") repeat scroll 0 100%;
|
||||
}
|
||||
|
||||
.yellow-skin:hover {
|
||||
background: #ce8735;
|
||||
}
|
||||
|
||||
.content-tabs {
|
||||
border-bottom: solid 2px #2f4050;
|
||||
}
|
||||
|
||||
.page-tabs a {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.page-tabs a i {
|
||||
color: #ccc;
|
||||
margin-left: 2px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.page-tabs a.active {
|
||||
background: #2f4050;
|
||||
color: #a7b1c2;
|
||||
background: #eaedf1;
|
||||
color: #23508e;
|
||||
}
|
||||
|
||||
.page-tabs a.active:hover, .page-tabs a.active i:hover {
|
||||
background: #293846;
|
||||
color: #fff;
|
||||
}
|
||||
/*
|
||||
*
|
||||
* SKIN blue 若依管理系统
|
||||
* NAME - blue/purple
|
||||
*
|
||||
*/
|
||||
.skin-blue .minimalize-styl-2 {
|
||||
margin: 14px 5px 5px 30px;
|
||||
}
|
||||
|
||||
.skin-blue .navbar-top-links li:last-child {
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.skin-blue.fixed-nav .minimalize-styl-2 {
|
||||
margin: 14px 5px 5px 15px;
|
||||
}
|
||||
|
||||
.skin-blue .spin-icon {
|
||||
background: #0e9aef !important;
|
||||
}
|
||||
|
||||
.skin-blue .nav-header {
|
||||
background: #0e9aef;
|
||||
background: url('patterns/header-profile-skin-blue.png');
|
||||
}
|
||||
|
||||
.skin-blue.mini-navbar .nav-second-level {
|
||||
background: #3e495f;
|
||||
}
|
||||
|
||||
.skin-blue .breadcrumb {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.skin-blue .page-heading {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.skin-blue .nav>li.active {
|
||||
background: #3a4459;
|
||||
}
|
||||
|
||||
.skin-blue .nav>li>a {
|
||||
color: #9ea6b9;
|
||||
}
|
||||
|
||||
.skin-blue .nav>li.active>a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.skin-blue .navbar-minimalize {
|
||||
background: #0e9aef;
|
||||
border-color: #0e9aef;
|
||||
}
|
||||
|
||||
body.skin-blue {
|
||||
background: #3e495f;
|
||||
}
|
||||
|
||||
.skin-blue .navbar-static-top {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.skin-blue .dashboard-header {
|
||||
background: transparent;
|
||||
border-bottom: none !important;
|
||||
border-top: none;
|
||||
padding: 20px 30px 10px 30px;
|
||||
}
|
||||
|
||||
.fixed-nav.skin-blue .navbar-fixed-top {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.skin-blue .wrapper-content {
|
||||
padding: 30px 15px;
|
||||
}
|
||||
|
||||
.skin-blue #page-wrapper {
|
||||
background: #f4f6fa;
|
||||
}
|
||||
|
||||
.skin-blue .ibox-title, .skin-blue .ibox-content {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.skin-blue .ibox-content:last-child {
|
||||
border-style: solid solid solid solid;
|
||||
}
|
||||
|
||||
.skin-blue .nav>li.active {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.skin-blue .nav-header {
|
||||
padding: 35px 25px 25px 25px;
|
||||
}
|
||||
|
||||
.skin-blue .nav-header a.dropdown-toggle {
|
||||
color: #fff;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.skin-blue .nav-header a.dropdown-toggle .text-muted {
|
||||
color: #fff;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.skin-blue .profile-element {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.skin-blue .img-circle {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.skin-blue .navbar-default .nav>li>a:hover, .skin-blue .navbar-default .nav>li>a:focus {
|
||||
background: #39aef5;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.skin-blue .nav.nav-tabs>li.active>a {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.skin-blue .content-tabs {
|
||||
border-bottom: solid 2px #39aef5;
|
||||
}
|
||||
|
||||
.skin-blue .nav.nav-tabs>li.active {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.skin-blue .page-tabs a.active {
|
||||
background: #39aef5;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.skin-blue .page-tabs a.active:hover, .skin-blue .page-tabs a.active i:hover {
|
||||
background: #0e9aef;
|
||||
color: #fff;
|
||||
}
|
||||
/*
|
||||
*
|
||||
* SKIN Yellow 若依管理系统
|
||||
* NAME - Yellow/purple
|
||||
*
|
||||
*/
|
||||
.skin-yellow .minimalize-styl-2 {
|
||||
margin: 14px 5px 5px 30px;
|
||||
}
|
||||
|
||||
.skin-yellow .navbar-top-links li:last-child {
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.skin-yellow.fixed-nav .minimalize-styl-2 {
|
||||
margin: 14px 5px 5px 15px;
|
||||
}
|
||||
|
||||
.skin-yellow .spin-icon {
|
||||
background: #ecba52 !important;
|
||||
}
|
||||
|
||||
body.boxed-layout.skin-yellow #wrapper {
|
||||
background: #3e2c42;
|
||||
}
|
||||
|
||||
.skin-yellow .nav-header {
|
||||
background: #ecba52;
|
||||
background: url('patterns/header-profile-skin-yellow.png');
|
||||
}
|
||||
|
||||
.skin-yellow.mini-navbar .nav-second-level {
|
||||
background: #3e2c42;
|
||||
}
|
||||
|
||||
.skin-yellow .breadcrumb {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.skin-yellow .page-heading {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li.active {
|
||||
background: #38283c;
|
||||
}
|
||||
|
||||
.fixed-nav.skin-yellow .navbar-fixed-top {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li>a {
|
||||
color: #948b96;
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li.active>a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.skin-yellow .navbar-minimalize {
|
||||
background: #ecba52;
|
||||
border-color: #ecba52;
|
||||
}
|
||||
|
||||
body.skin-yellow {
|
||||
background: #3e2c42;
|
||||
}
|
||||
|
||||
.skin-yellow .navbar-static-top {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.skin-yellow .dashboard-header {
|
||||
background: transparent;
|
||||
border-bottom: none !important;
|
||||
border-top: none;
|
||||
padding: 20px 30px 10px 30px;
|
||||
}
|
||||
|
||||
.skin-yellow .wrapper-content {
|
||||
padding: 30px 15px;
|
||||
}
|
||||
|
||||
.skin-yellow #page-wrapper {
|
||||
background: #f4f6fa;
|
||||
}
|
||||
|
||||
.skin-yellow .ibox-title, .skin-yellow .ibox-content {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.skin-yellow .ibox-content:last-child {
|
||||
border-style: solid solid solid solid;
|
||||
}
|
||||
|
||||
.skin-yellow .nav>li.active {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.skin-yellow .nav-header {
|
||||
padding: 35px 25px 25px 25px;
|
||||
}
|
||||
|
||||
.skin-yellow .nav-header a.dropdown-toggle {
|
||||
color: #fff;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.skin-yellow .nav-header a.dropdown-toggle .text-muted {
|
||||
color: #fff;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.skin-yellow .profile-element {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.skin-yellow .img-circle {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.skin-yellow .navbar-default .nav>li>a:hover, .skin-yellow .navbar-default .nav>li>a:focus {
|
||||
background: #38283c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.skin-yellow .nav.nav-tabs>li.active>a {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.skin-yellow .nav.nav-tabs>li.active {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.skin-yellow .content-tabs {
|
||||
border-bottom: solid 2px #3e2c42;
|
||||
}
|
||||
|
||||
.skin-yellow .nav.nav-tabs>li.active {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.skin-yellow .page-tabs a.active {
|
||||
background: #3e2c42;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.skin-yellow .page-tabs a.active:hover, .skin-yellow .page-tabs a.active i:hover {
|
||||
background: #38283c;
|
||||
color: #fff;
|
||||
.page-tabs a.active:hover,
|
||||
.page-tabs a.active i:hover {
|
||||
background: #eaedf1;
|
||||
color: #23508e;
|
||||
}
|
||||
|
||||
@media ( min-width : 768px) {
|
||||
@ -7279,7 +6911,8 @@ body.skin-yellow {
|
||||
}
|
||||
|
||||
.navbar-header {
|
||||
width: 60%;
|
||||
width: 10%;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.bs-glyphicons {
|
||||
@ -7347,3 +6980,99 @@ body.skin-yellow {
|
||||
border-color: #cccccc!important;
|
||||
}
|
||||
|
||||
.folder-list li.active a {
|
||||
color: #2791df;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.nav .logo {
|
||||
background-color: #367fa9;
|
||||
color: #fff;
|
||||
border-bottom: 0 solid transparent;
|
||||
-webkit-transition: width .3s ease-in-out;
|
||||
-o-transition: width .3s ease-in-out;
|
||||
transition: width .3s ease-in-out;
|
||||
display: block;
|
||||
height: 50px;
|
||||
font-size: 20px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
width: 220px;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
padding: 0 15px;
|
||||
font-weight: 300;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.logo-mini {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-lg {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.roleList {
|
||||
color: #d5d5d5;
|
||||
margin-right: 10px;
|
||||
padding-top: 10px;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
.sidebar-collapse .user-panel {
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sidebar-collapse .user-panel .image>img {
|
||||
width: 100%;
|
||||
max-width: 45px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.sidebar-collapse .user-panel>.info {
|
||||
padding: 5px 5px 5px 15px;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
left: 55px;
|
||||
}
|
||||
|
||||
.sidebar-collapse .user-panel>.info a {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.sidebar-collapse .user-panel>.info>p {
|
||||
font-weight: 600;
|
||||
margin-bottom: 9px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.user-panel>.info>a>.fa,
|
||||
.user-panel>.info>a>.ion,
|
||||
.user-panel>.info>a>.glyphicon {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.nav>li:hover .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#content-main.max {
|
||||
height: calc(100% - 110px);
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
z-index: 9998;
|
||||
margin: 0;
|
||||
}
|
@ -1,9 +1,64 @@
|
||||
/**
|
||||
* 通用css样式布局处理
|
||||
* Copyright (c) 2018 ruoyi
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
/** 用户管理 样式布局 */
|
||||
/** 基础通用 **/
|
||||
.pt5 {
|
||||
padding-top: 5px;
|
||||
}
|
||||
.pr5 {
|
||||
padding-right: 5px;
|
||||
}
|
||||
.pb5 {
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.mt5 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.mr5 {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.mb5 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.ml5 {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.mt10 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.mr10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.mb10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ml0 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.mt20 {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.mr20 {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.mb20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.ml20 {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/** 弹层组件 禁用样式 **/
|
||||
.layer-disabled {
|
||||
border: 1px #dedede solid !important;
|
||||
background-color: #f1f1f1 !important;
|
||||
color: #333 !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/** 用户管理 样式布局 **/
|
||||
.box {
|
||||
position: relative;
|
||||
border-radius: 3px;
|
||||
@ -91,7 +146,7 @@
|
||||
margin: 5px 0 5px -25px
|
||||
}
|
||||
|
||||
/** select2 样式修改 */
|
||||
/** select2 样式修改 **/
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #1AB394;
|
||||
border-color: #1AB394;
|
||||
@ -112,7 +167,7 @@
|
||||
padding-right: 10px
|
||||
}
|
||||
|
||||
/** 表单验证 样式布局 */
|
||||
/** 表单验证 样式布局 **/
|
||||
label.error {
|
||||
position: absolute;
|
||||
right: 18px;
|
||||
@ -143,7 +198,7 @@ label.error {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
/** 复选框&单选框 */
|
||||
/** 复选框&单选框 **/
|
||||
.check-box,.radio-box {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
@ -160,7 +215,7 @@ label.error {
|
||||
left: 0
|
||||
}
|
||||
|
||||
/* iCheck */
|
||||
/** iCheck **/
|
||||
.icheckbox-blue,.iradio-blue {
|
||||
display: block;
|
||||
margin: 0;
|
||||
@ -214,7 +269,7 @@ label.error {
|
||||
background-position: -180px 0
|
||||
}
|
||||
|
||||
/** 遮罩层 */
|
||||
/** 遮罩层 **/
|
||||
.loaderbox {
|
||||
display: inline-block;
|
||||
min-width: 125px;
|
||||
@ -281,7 +336,7 @@ label.error {
|
||||
}
|
||||
}
|
||||
|
||||
/** 表单查询条件 */
|
||||
/** 表单查询条件 **/
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@ -409,7 +464,7 @@ label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/** 表格查询数据 */
|
||||
/** 表格查询数据 **/
|
||||
.table-striped {
|
||||
min-height: 75%;
|
||||
}
|
||||
@ -437,7 +492,7 @@ label {
|
||||
border: 1px solid #ddd!important
|
||||
}
|
||||
|
||||
/** 首页样式 */
|
||||
/** 首页样式 **/
|
||||
.ax_close_max {
|
||||
position: fixed;
|
||||
top: 5px;
|
||||
@ -446,3 +501,35 @@ label {
|
||||
display: none;
|
||||
color: #ccc;
|
||||
}
|
||||
.navbar-right > .user-menu > .dropdown-menu {
|
||||
border-top-right-radius:0;
|
||||
border-top-left-radius:0;
|
||||
padding:1px 0 0 0;
|
||||
border-top-width:0;
|
||||
width:138px;
|
||||
}
|
||||
.navbar-right > .user-menu .user-image {
|
||||
float:left;
|
||||
width:27px;
|
||||
height:27px;
|
||||
border-radius:50%;
|
||||
margin-right:8px;
|
||||
margin-top:-3px;
|
||||
}
|
||||
@media (max-width:767px) {
|
||||
.navbar-right > .user-menu .user-image {
|
||||
float:none;
|
||||
margin-right:0;
|
||||
margin-top:-8px;
|
||||
line-height:10px;
|
||||
}
|
||||
}.dropdown-menu > li > a > .glyphicon,.dropdown-menu > li > a > .fa,.dropdown-menu > li > a > .ion {
|
||||
margin-right:10px;
|
||||
}
|
||||
.dropdown-menu > li > a:hover {
|
||||
background-color:#e1e3e9;
|
||||
color:#333;
|
||||
}
|
||||
.dropdown-menu > .divider {
|
||||
background-color:#eee;
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
/**
|
||||
* 菜单处理
|
||||
* 首页方法封装处理
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
layer.config({
|
||||
extend: 'moon/style.css',
|
||||
skin: 'layer-ext-moon'
|
||||
});
|
||||
|
||||
$(function() {
|
||||
// MetsiMenu
|
||||
$('#side-menu').metisMenu();
|
||||
@ -45,6 +51,7 @@ function() {
|
||||
if ($(this).width() < 769) {
|
||||
$('body').addClass('mini-navbar');
|
||||
$('.navbar-static-side').fadeIn();
|
||||
$(".sidebar-collapse .logo").addClass("hide");
|
||||
}
|
||||
});
|
||||
|
||||
@ -55,12 +62,14 @@ function NavToggle() {
|
||||
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);
|
||||
},
|
||||
|
@ -1,8 +1,7 @@
|
||||
/**
|
||||
* 通用方法封装处理
|
||||
* Copyright (c) 2018 ruoyi
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
|
||||
$(function() {
|
||||
// select2复选框事件绑定
|
||||
if ($.fn.select2 !== undefined) {
|
||||
@ -101,7 +100,7 @@ $(function() {
|
||||
$("#bootstrap-table").on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", function () {
|
||||
var ids = $("#bootstrap-table").bootstrapTable("getSelections");
|
||||
$('#toolbar .btn-del').toggleClass('disabled', !ids.length);
|
||||
$('#toolbar .btn-edit').toggleClass('disabled', ids.length!=1);;
|
||||
$('#toolbar .btn-edit').toggleClass('disabled', ids.length!=1);
|
||||
});
|
||||
// tree表格树 展开/折叠
|
||||
var expandFlag = false;
|
||||
@ -191,3 +190,7 @@ $.ajaxSetup({
|
||||
}
|
||||
}
|
||||
});
|
||||
layer.config({
|
||||
extend: 'moon/style.css',
|
||||
skin: 'layer-ext-moon'
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 通用js方法封装处理
|
||||
* Copyright (c) 2018 ruoyi
|
||||
* Copyright (c) 2019 ruoyi
|
||||
*/
|
||||
(function ($) {
|
||||
$.extend({
|
||||
@ -18,6 +18,7 @@
|
||||
_sortName = $.common.isEmpty(options.sortName) ? "" : options.sortName;
|
||||
_striped = $.common.isEmpty(options.striped) ? false : options.striped;
|
||||
_escape = $.common.isEmpty(options.escape) ? false : options.escape;
|
||||
_showFooter = $.common.isEmpty(options.showFooter) ? false : options.showFooter;
|
||||
$('#bootstrap-table').bootstrapTable({
|
||||
url: options.url, // 请求后台的URL(*)
|
||||
contentType: "application/x-www-form-urlencoded", // 编码类型
|
||||
@ -33,6 +34,7 @@
|
||||
pageSize: 10, // 每页的记录行数(*)
|
||||
pageList: [10, 25, 50], // 可供选择的每页的行数(*)
|
||||
escape: _escape, // 转义HTML字符串
|
||||
showFooter: _showFooter, // 是否显示表尾
|
||||
iconSize: 'outline', // 图标大小:undefined默认的按钮尺寸 xs超小按钮sm小按钮lg大按钮
|
||||
toolbar: '#toolbar', // 指定工作栏
|
||||
sidePagination: "server", // 启用服务端分页
|
||||
@ -67,6 +69,13 @@
|
||||
return { rows: [], total: 0 };
|
||||
}
|
||||
},
|
||||
// 序列号生成
|
||||
serialNumber: function (index) {
|
||||
var table = $('#bootstrap-table').bootstrapTable('getOptions');
|
||||
var pageSize = table.pageSize;
|
||||
var pageNumber = table.pageNumber;
|
||||
return pageSize * (pageNumber - 1) + index + 1;
|
||||
},
|
||||
// 搜索-默认第一个form
|
||||
search: function(formId) {
|
||||
var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
|
||||
@ -85,7 +94,7 @@
|
||||
}
|
||||
$("#bootstrap-table").bootstrapTable('refresh', params);
|
||||
},
|
||||
// 下载-默认第一个form
|
||||
// 导出数据
|
||||
exportExcel: function(formId) {
|
||||
var currentId = $.common.isEmpty(formId) ? $('form').attr('id') : formId;
|
||||
$.modal.loading("正在导出数据,请稍后...");
|
||||
@ -98,6 +107,63 @@
|
||||
$.modal.closeLoading();
|
||||
});
|
||||
},
|
||||
// 下载模板
|
||||
importTemplate: function() {
|
||||
$.get($.table._option.importTemplateUrl, function(result) {
|
||||
if (result.code == web_status.SUCCESS) {
|
||||
window.location.href = ctx + "common/download?fileName=" + result.msg + "&delete=" + true;
|
||||
} else {
|
||||
$.modal.alertError(result.msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 导入数据
|
||||
importExcel: function(formId) {
|
||||
var currentId = $.common.isEmpty(formId) ? 'importForm' : formId;
|
||||
$.form.reset(currentId);
|
||||
layer.open({
|
||||
type: 1,
|
||||
area: ['400px', '230px'],
|
||||
fix: false,
|
||||
//不固定
|
||||
maxmin: true,
|
||||
shade: 0.3,
|
||||
title: '导入' + $.table._option.modalName + '数据',
|
||||
content: $('#' + currentId),
|
||||
btn: ['<i class="fa fa-check"></i> 导入', '<i class="fa fa-remove"></i> 取消'],
|
||||
// 弹层外区域关闭
|
||||
shadeClose: true,
|
||||
btn1: function(index, layero){
|
||||
var file = layero.find('#file').val();
|
||||
if (file == '' || (!$.common.endWith(file, '.xls') && !$.common.endWith(file, '.xlsx'))){
|
||||
$.modal.msgWarning("请选择后缀为 “xls”或“xlsx”的文件。");
|
||||
return false;
|
||||
}
|
||||
var index = layer.load(2, {shade: false});
|
||||
var formData = new FormData();
|
||||
formData.append("file", $('#file')[0].files[0]);
|
||||
formData.append("updateSupport", $("input[name='updateSupport']").is(':checked'));
|
||||
$.ajax({
|
||||
url: $.table._option.importUrl,
|
||||
data: formData,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
type: 'POST',
|
||||
success: function (result) {
|
||||
if (result.code == web_status.SUCCESS) {
|
||||
$.modal.closeAll();
|
||||
$.modal.alertSuccess(result.msg);
|
||||
$.table.refresh();
|
||||
} else {
|
||||
layer.close(index);
|
||||
$.modal.alertError(result.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 刷新表格
|
||||
refresh: function() {
|
||||
$("#bootstrap-table").bootstrapTable('refresh', {
|
||||
@ -281,6 +347,10 @@
|
||||
var index = parent.layer.getFrameIndex(window.name);
|
||||
parent.layer.close(index);
|
||||
},
|
||||
// 关闭全部窗体
|
||||
closeAll: function () {
|
||||
layer.closeAll();
|
||||
},
|
||||
// 确认窗体
|
||||
confirm: function (content, callBack) {
|
||||
layer.confirm(content, {
|
||||
@ -384,11 +454,27 @@
|
||||
shade: 0.3,
|
||||
title: title,
|
||||
content: url,
|
||||
btn: ['确定', '关闭'],
|
||||
// 弹层外区域关闭
|
||||
shadeClose: true
|
||||
shadeClose: true,
|
||||
yes: function(index, layero) {
|
||||
var iframeWin = layero.find('iframe')[0];
|
||||
iframeWin.contentWindow.submitHandler();
|
||||
},
|
||||
cancel: function(index) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
layer.full(index);
|
||||
},
|
||||
// 禁用按钮
|
||||
disable: function() {
|
||||
$("a[class*=layui-layer-btn]", window.parent.document).addClass("layer-disabled");
|
||||
},
|
||||
// 启用按钮
|
||||
enable: function() {
|
||||
$("a[class*=layui-layer-btn]", window.parent.document).removeClass("layer-disabled");
|
||||
},
|
||||
// 打开遮罩层
|
||||
loading: function (message) {
|
||||
$.blockUI({ message: '<div class="loaderbox"><div class="loading-activity"></div> ' + message + '</div>' });
|
||||
@ -408,12 +494,14 @@
|
||||
operate: {
|
||||
// 提交数据
|
||||
submit: function(url, type, dataType, data) {
|
||||
$.modal.loading("正在处理中,请稍后...");
|
||||
var config = {
|
||||
url: url,
|
||||
type: type,
|
||||
dataType: dataType,
|
||||
data: data,
|
||||
beforeSend: function () {
|
||||
$.modal.loading("正在处理中,请稍后...");
|
||||
},
|
||||
success: function(result) {
|
||||
$.operate.ajaxSuccess(result);
|
||||
}
|
||||
@ -424,6 +512,10 @@
|
||||
post: function(url, data) {
|
||||
$.operate.submit(url, "post", "json", data);
|
||||
},
|
||||
// get请求传输
|
||||
get: function(url) {
|
||||
$.operate.submit(url, "get", "json", "");
|
||||
},
|
||||
// 详细信息
|
||||
detail: function(id, width, height) {
|
||||
var _url = $.common.isEmpty(id) ? $.table._option.detailUrl : $.table._option.detailUrl.replace("{id}", id);
|
||||
@ -434,7 +526,7 @@
|
||||
_width = 'auto';
|
||||
_height = 'auto';
|
||||
}
|
||||
layer.open({
|
||||
top.layer.open({
|
||||
type: 2,
|
||||
area: [_width + 'px', _height + 'px'],
|
||||
fix: false,
|
||||
@ -443,15 +535,12 @@
|
||||
shade: 0.3,
|
||||
title: $.table._option.modalName + "详细",
|
||||
content: _url,
|
||||
btn: '关闭',
|
||||
btn: ['关闭'],
|
||||
// 弹层外区域关闭
|
||||
shadeClose: true,
|
||||
success: function(layer) {
|
||||
layer[0].childNodes[3].childNodes[0].attributes[0].value='layui-layer-btn1';
|
||||
},
|
||||
btn1: function(index) {
|
||||
layer.close(index);
|
||||
}
|
||||
cancel: function(index){
|
||||
return true;
|
||||
}
|
||||
});
|
||||
},
|
||||
// 删除信息
|
||||
@ -530,12 +619,15 @@
|
||||
},
|
||||
// 保存信息
|
||||
save: function(url, data) {
|
||||
$.modal.loading("正在处理中,请稍后...");
|
||||
var config = {
|
||||
url: url,
|
||||
type: "post",
|
||||
dataType: "json",
|
||||
data: data,
|
||||
beforeSend: function () {
|
||||
$.modal.loading("正在处理中,请稍后...");
|
||||
$.modal.disable();
|
||||
},
|
||||
success: function(result) {
|
||||
$.operate.successCallback(result);
|
||||
}
|
||||
@ -579,6 +671,7 @@
|
||||
$.modal.alertError(result.msg);
|
||||
}
|
||||
$.modal.closeLoading();
|
||||
$.modal.enable();
|
||||
}
|
||||
},
|
||||
// 校验封装处理
|
||||
@ -744,6 +837,17 @@
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 不允许最后层级节点选择
|
||||
notAllowLastLevel: function(_tree) {
|
||||
var nodes = _tree.getSelectedNodes();
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
if (nodes[i].level == nodes.length + 1) {
|
||||
$.modal.msgError("不能选择最后层级节点(" + nodes[i].name + ")");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
// 隐藏/显示搜索栏
|
||||
toggleSearch: function() {
|
||||
$('#search').slideToggle(200);
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
$(function() {
|
||||
validateRule();
|
||||
$(".i-checks").iCheck({checkboxClass:"icheckbox_square-green-login"});
|
||||
$('.imgcode').click(function() {
|
||||
var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
|
||||
$(".imgcode").attr("src", url);
|
||||
|
@ -22,7 +22,7 @@
|
||||
<!-- bootstrap-table 表格插件 -->
|
||||
<script th:src="@{/ajax/libs/bootstrap-table/bootstrap-table.min.js}"></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.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>
|
||||
<!-- jquery-validate 表单验证插件 -->
|
||||
<script th:src="@{/ajax/libs/validate/jquery.validate.min.js}"></script>
|
||||
@ -38,8 +38,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=3.1.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/ry-ui.js?v=3.1.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/common.js?v=3.2.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/ry-ui.js?v=3.2.0}"></script>
|
||||
<script src="http://tajs.qq.com/stats?sId=62048022"></script>
|
||||
<script th:inline="javascript"> var ctx = [[@{/}]]; </script>
|
||||
</div>
|
||||
|
@ -15,7 +15,8 @@
|
||||
<link th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/animate.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/style.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css?v=3.1.0}" rel="stylesheet"/>
|
||||
<link th:href="@{/css/skins.css}" rel="stylesheet"/>
|
||||
<link th:href="@{/ruoyi/css/ry-ui.css?v=3.2.0}" rel="stylesheet"/>
|
||||
<style type="text/css">
|
||||
.nav > li:hover .dropdown-menu {display: block;}
|
||||
#content-main.max { height: calc(100% - 110px); overflow: hidden; width: 100%; height: 100%; left: 0px; position: absolute; top: 0px; z-index: 9998; margin: 0; }
|
||||
@ -31,19 +32,24 @@
|
||||
</div>
|
||||
<div class="sidebar-collapse">
|
||||
<ul class="nav" id="side-menu">
|
||||
<li class="nav-header">
|
||||
<div class="dropdown profile-element"> <span>
|
||||
<img th:src="(${user.avatar} == '') ? @{/img/profile.jpg} : @{/profile/avatar/} + ${user.avatar}" alt="image" class="img-circle" height="60" width="60"/></span>
|
||||
<a data-toggle="dropdown" class="dropdown-toggle" href="#">
|
||||
<span class="clear"><span class="block m-t-xs"><strong class="font-bold" th:text="${user.userName}">用户</strong></span>
|
||||
<span class="text-muted text-xs block"><span th:text="${user.dept?.deptName}">部门</span> <b class="caret"></b></span> </span> </a>
|
||||
<ul class="dropdown-menu animated fadeInRight m-t-xs">
|
||||
<li><a class="menuItem" th:href="@{/system/user/profile}">个人信息</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a th:href="@{logout}">退出</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="logo">
|
||||
<span class="logo-lg">RuoYi</span>
|
||||
</li>
|
||||
<li>
|
||||
<div class="user-panel">
|
||||
<a class="menuItem" title="个人中心" th:href="@{/system/user/profile}">
|
||||
<div class="hide" th:text="个人中心"></div>
|
||||
<div class="pull-left image">
|
||||
<img th:src="(${user.avatar} == '') ? @{/img/profile.jpg} : @{/profile/avatar/} + ${user.avatar}" class="img-circle" alt="User Image">
|
||||
</div>
|
||||
</a>
|
||||
<div class="pull-left info">
|
||||
<p>[[${user.loginName}]]</p>
|
||||
<a href="#"><i class="fa fa-circle text-success"></i> 在线</a>
|
||||
<a th:href="@{logout}" style="padding-left:5px;"><i class="fa fa-sign-out text-danger"></i> 注销</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="active">
|
||||
<a href="index.html"><i class="fa fa-home"></i> <span class="nav-label">主页</span> <span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
@ -74,20 +80,35 @@
|
||||
<!--右侧部分开始-->
|
||||
<div id="page-wrapper" class="gray-bg dashbard-1">
|
||||
<div class="row border-bottom">
|
||||
<nav class="navbar navbar-static-top" role="navigation"
|
||||
style="margin-bottom: 0">
|
||||
<nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0">
|
||||
<div class="navbar-header">
|
||||
|
||||
<a class="navbar-minimalize minimalize-styl-2 btn btn-default " href="#" title="收起菜单">
|
||||
<a class="navbar-minimalize minimalize-styl-2" style="color:#FFF;" href="#" title="收起菜单">
|
||||
<i class="fa fa-bars"></i>
|
||||
</a>
|
||||
</div>
|
||||
<ul class="nav navbar-top-links navbar-right welcome-message">
|
||||
<li>
|
||||
<span class="m-r-sm text-muted">欢迎来到若依管理后台.</span>
|
||||
</li>
|
||||
<li><a id="fullScreen"><i class="fa fa-arrows-alt"></i>全屏</a></li>
|
||||
<li><a th:href="@{logout}"><i class="fa fa-sign-out"></i>退出</a></li>
|
||||
<li><a title="全屏显示" id="fullScreen"><i class="fa fa-arrows-alt"></i> 全屏显示</a></li>
|
||||
<li class="dropdown user-menu">
|
||||
<a href="javascript:" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown">
|
||||
<img th:src="(${user.avatar} == '') ? @{/img/profile.jpg} : @{/profile/avatar/} + ${user.avatar}" class="user-image">
|
||||
<span class="hidden-xs">[[${user.userName}]]</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="mt5">
|
||||
<a th:href="@{/system/user/profile}" class="menuItem">
|
||||
<i class="fa fa-user"></i> 个人中心</a>
|
||||
</li>
|
||||
<li>
|
||||
<a onclick="resetPwd()" class="menuItem">
|
||||
<i class="fa fa-key"></i> 修改密码</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a th:href="@{logout}">
|
||||
<i class="fa fa-sign-out"></i> 退出登录</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
@ -135,9 +156,18 @@
|
||||
<script th:src="@{/js/plugins/metisMenu/jquery.metisMenu.js}"></script>
|
||||
<script th:src="@{/js/plugins/slimscroll/jquery.slimscroll.min.js}"></script>
|
||||
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
|
||||
<script th:src="@{/ajax/libs/layer/layer.min.js}"></script>
|
||||
<script src="http://tajs.qq.com/stats?sId=62048022"></script>
|
||||
<script th:src="@{/ruoyi/js/ry-ui.js?v=3.1.0}"></script>
|
||||
<script th:src="@{/ruoyi/js/ry-ui.js?v=3.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 = [[@{/}]];
|
||||
/*用户管理-重置密码*/
|
||||
function resetPwd() {
|
||||
var url = ctx + 'system/user/profile/resetPwd';
|
||||
$.modal.open("重置密码", url, '800', '500');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -11,8 +11,7 @@
|
||||
<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/ajax/libs/iCheck/custom.css" th:href="@{/ajax/libs/iCheck/custom.css}" rel="stylesheet"/>
|
||||
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=3.1.0}" rel="stylesheet"/>
|
||||
<link href="../static/ruoyi/css/ry-ui.css" th:href="@{/ruoyi/css/ry-ui.css?v=3.2.0}" rel="stylesheet"/>
|
||||
<!--[if lt IE 9]>
|
||||
<meta http-equiv="refresh" content="0;ie.html" />
|
||||
<![endif]-->
|
||||
@ -49,8 +48,8 @@
|
||||
<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 m-b" placeholder="密码" value="admin123" />
|
||||
<div class="row" th:if="${captchaEnabled==true}">
|
||||
<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">
|
||||
</div>
|
||||
@ -60,7 +59,9 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<input class="i-checks" type="checkbox" name="rememberme" /> 记住我
|
||||
<div class="checkbox-custom">
|
||||
<input type="checkbox" id="rememberme" name="rememberme"> <label for="rememberme">记住我</label>
|
||||
</div>
|
||||
<button class="btn btn-success btn-block" id="btnSubmit" data-loading="正在验证登录,请稍后...">登录</button>
|
||||
</form>
|
||||
</div>
|
||||
@ -80,10 +81,9 @@
|
||||
<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/iCheck/icheck.min.js" th:src="@{/ajax/libs/iCheck/icheck.min.js}"></script>
|
||||
<script src="../static/ajax/libs/blockUI/jquery.blockUI.js" th:src="@{/ajax/libs/blockUI/jquery.blockUI.js}"></script>
|
||||
<script src="http://tajs.qq.com/stats?sId=62048022"></script>
|
||||
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=3.1.0}"></script>
|
||||
<script src="../static/ruoyi/js/ry-ui.js" th:src="@{/ruoyi/js/ry-ui.js?v=3.2.0}"></script>
|
||||
<script src="../static/ruoyi/login.js" th:src="@{/ruoyi/login.js}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -77,7 +77,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> <a href="https://jq.qq.com/?_wv=1027&k=5cHeRVW" target="_blank">1679294</a>
|
||||
<p><i class="fa fa-qq"></i> QQ群:<s>满1389287</s> <s>满1679294</s> <a href="https://jq.qq.com/?_wv=1027&k=5YW0wjE" target="_blank">1529866</a>
|
||||
</p>
|
||||
<p><i class="fa fa-weixin"></i> 微信:<a href="javascript:;">/ *若依</a>
|
||||
</p>
|
||||
@ -94,13 +94,53 @@
|
||||
<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="#v32">v3.2.0</a><code class="pull-right">2019.01.18</code>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="v32" class="panel-collapse collapse in">
|
||||
<div class="panel-body">
|
||||
<ol>
|
||||
<li>部门修改时不允许选择最后节点</li>
|
||||
<li>修复部门菜单排序字段无效</li>
|
||||
<li>修复光驱磁盘导致服务监控异常</li>
|
||||
<li>登录界面去除check插件</li>
|
||||
<li>验证码文本字符间距修正</li>
|
||||
<li>升级SpringBoot到最新版本2.1.1</li>
|
||||
<li>升级MYSQL驱动</li>
|
||||
<li>修正登录必填项位置偏移</li>
|
||||
<li>Session会话检查优化</li>
|
||||
<li>Excel注解支持多级获取</li>
|
||||
<li>新增序列号生成方法</li>
|
||||
<li>修复WAR部署tomcat退出线程异常</li>
|
||||
<li>全屏操作增加默认确认/关闭</li>
|
||||
<li>修复个人信息可能导致漏洞</li>
|
||||
<li>字典数据根据下拉选择新增类型</li>
|
||||
<li>升级Summernote到最新版本v0.8.11</li>
|
||||
<li>新增用户数据导入</li>
|
||||
<li>首页主题样式更换</li>
|
||||
<li>layer扩展主题更换</li>
|
||||
<li>用户管理移动端默认隐藏左侧布局</li>
|
||||
<li>详细信息弹出层显示在顶层</li>
|
||||
<li>表格支持切换状态(用户/角色/定时任务)</li>
|
||||
<li>Druid数据源支持配置继承</li>
|
||||
<li>修正部分iPhone手机端表格适配问题</li>
|
||||
<li>新增防止重复提交表单方法</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="#v31">v3.1.0</a><code class="pull-right">2018.12.03</code>
|
||||
</h5>
|
||||
</div>
|
||||
<div id="v31" class="panel-collapse collapse in">
|
||||
<div id="v31" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<ol>
|
||||
<li>新增内网不获取IP地址</li>
|
||||
|
@ -107,12 +107,12 @@
|
||||
title: '执行表达式'
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: '任务状态',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.selectDictLabel(datas, value);
|
||||
}
|
||||
visible: statusFlag == 'hidden' ? false : true,
|
||||
title: '任务状态',
|
||||
align: 'center',
|
||||
formatter: function (value, row, index) {
|
||||
return statusTools(row);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
@ -124,7 +124,6 @@
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
var actions = [];
|
||||
actions.push(statusTools(row));
|
||||
actions.push('<a class="btn btn-primary btn-xs ' + statusFlag + '" href="#" onclick="run(\'' + row.jobId + '\')"><i class="fa fa-play-circle-o"></i> 执行</a> ');
|
||||
actions.push('<a class="btn btn-warning btn-xs ' + detailFlag + '" href="#" onclick="$.operate.detail(\'' + row.jobId + '\')"><i class="fa fa-search"></i>详细</a> ');
|
||||
return actions.join('');
|
||||
@ -133,37 +132,38 @@
|
||||
};
|
||||
$.table.init(options);
|
||||
});
|
||||
|
||||
|
||||
/* 调度任务状态显示 */
|
||||
function statusTools(row) {
|
||||
if (row.status == 1) {
|
||||
return '<a class="btn btn-info btn-xs ' + statusFlag + '" href="#" onclick="start(\'' + row.jobId + '\')"><i class="fa fa-play"></i>启用</a> ';
|
||||
} else {
|
||||
return '<a class="btn btn-danger btn-xs ' + statusFlag + '" href="#" onclick="stop(\'' + row.jobId + '\')"><i class="fa fa-pause"></i>暂停</a> ';
|
||||
}
|
||||
return '<i class=\"fa fa-toggle-off text-info fa-2x\" onclick="start(\'' + row.jobId + '\')"></i> ';
|
||||
} else {
|
||||
return '<i class=\"fa fa-toggle-on text-info fa-2x\" onclick="stop(\'' + row.jobId + '\')"></i> ';
|
||||
}
|
||||
}
|
||||
|
||||
/*立即执行一次*/
|
||||
/* 立即执行一次 */
|
||||
function run(jobId) {
|
||||
$.modal.confirm("确认要立即执行任务吗?", function() {
|
||||
$.operate.post(prefix + "/run", { "jobId": jobId});
|
||||
})
|
||||
}
|
||||
|
||||
/*调度任务-停用*/
|
||||
/* 调度任务-停用 */
|
||||
function stop(jobId) {
|
||||
$.modal.confirm("确认要停用任务吗?", function() {
|
||||
$.operate.post(prefix + "/changeStatus", { "jobId": jobId, "status": 1 });
|
||||
})
|
||||
}
|
||||
|
||||
/*调度任务-启用*/
|
||||
/* 调度任务-启用 */
|
||||
function start(jobId) {
|
||||
$.modal.confirm("确认要启用任务吗?", function() {
|
||||
$.operate.post(prefix + "/changeStatus", { "jobId": jobId, "status": 0 });
|
||||
})
|
||||
}
|
||||
|
||||
//调度日志查询
|
||||
/* 调度日志查询 */
|
||||
function jobLog(id) {
|
||||
var url = ctx + 'monitor/jobLog';
|
||||
createMenuItem(url, "调度日志");
|
||||
|
@ -53,6 +53,12 @@
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
title: "序号",
|
||||
formatter: function (value, row, index) {
|
||||
return $.table.serialNumber(index);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'sessionId',
|
||||
title: '会话编号'
|
||||
|
@ -123,10 +123,13 @@
|
||||
}
|
||||
|
||||
function doSubmit(index, layero){
|
||||
var body = layer.getChildFrame('body', index);
|
||||
$("#treeId").val(body.find('#treeId').val());
|
||||
$("#treeName").val(body.find('#treeName').val());
|
||||
layer.close(index);
|
||||
var tree = layero.find("iframe")[0].contentWindow.$._tree;
|
||||
if ($.tree.notAllowLastLevel(tree)) {
|
||||
var body = layer.getChildFrame('body', index);
|
||||
$("#treeId").val(body.find('#treeId').val());
|
||||
$("#treeName").val(body.find('#treeName').val());
|
||||
layer.close(index);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
@ -35,7 +35,7 @@
|
||||
</div>
|
||||
|
||||
<div class="btn-group-sm hidden-xs" id="toolbar" role="group">
|
||||
<a class="btn btn-success" th:onclick="'javascript:$.operate.add(\''+${dict.dictType}+'\')'" shiro:hasPermission="system:dict:add">
|
||||
<a class="btn btn-success" onclick="add()" shiro:hasPermission="system:dict:add">
|
||||
<i class="fa fa-plus"></i> 新增
|
||||
</a>
|
||||
<a class="btn btn-primary btn-edit disabled" onclick="$.operate.edit()" shiro:hasPermission="system:dict:edit">
|
||||
@ -135,6 +135,12 @@
|
||||
isAsc: params.order
|
||||
};
|
||||
}
|
||||
|
||||
/*字典数据-新增字典*/
|
||||
function add() {
|
||||
var dictType = $("#dictType option:selected").val();
|
||||
$.operate.add(dictType);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -37,12 +37,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-control-static col-sm-offset-9">
|
||||
<button type="submit" class="btn btn-primary">提交</button>
|
||||
<button onclick="$.modal.close()" class="btn btn-danger" type="button">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div th:include="include::footer"></div>
|
||||
@ -50,24 +44,57 @@
|
||||
<script th:src="@{/ajax/libs/summernote/summernote-zh-CN.js}"></script>
|
||||
<script type="text/javascript">
|
||||
var prefix = ctx + "system/notice";
|
||||
|
||||
|
||||
$('.summernote').summernote({
|
||||
height : '220px',
|
||||
lang : 'zh-CN'
|
||||
lang : 'zh-CN',
|
||||
callbacks: {
|
||||
onImageUpload: function (files) {
|
||||
sendFile(files[0], this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 上传文件
|
||||
function sendFile(file, obj) {
|
||||
var data = new FormData();
|
||||
data.append("file", file);
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: ctx + "common/upload",
|
||||
data: data,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
dataType: 'json',
|
||||
success: function(result) {
|
||||
if (result.code == web_status.SUCCESS) {
|
||||
$(obj).summernote('editor.insertImage', result.url, result.fileName);
|
||||
} else {
|
||||
$.modal.alertError(result.msg);
|
||||
}
|
||||
},
|
||||
error: function(error) {
|
||||
$.modal.alertWarning("图片上传失败。");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#form-notice-add").validate({
|
||||
rules:{
|
||||
noticeTitle:{
|
||||
required:true,
|
||||
}
|
||||
},
|
||||
submitHandler: function(form) {
|
||||
var sHTML = $('.summernote').code();
|
||||
$("#noticeContent").val(sHTML);
|
||||
$.operate.save(prefix + "/add", $('#form-notice-add').serialize());
|
||||
}
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
if ($.validate.form()) {
|
||||
var sHTML = $('.summernote').summernote('code');
|
||||
$("#noticeContent").val(sHTML);
|
||||
$.operate.save(prefix + "/add", $('#form-notice-add').serialize());
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -38,12 +38,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-control-static col-sm-offset-9">
|
||||
<button type="submit" class="btn btn-primary">提交</button>
|
||||
<button onclick="$.modal.close()" class="btn btn-danger" type="button">关闭</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div th:include="include::footer"></div>
|
||||
@ -54,25 +48,58 @@
|
||||
|
||||
$(function() {
|
||||
$('.summernote').summernote({
|
||||
height : '220px',
|
||||
lang : 'zh-CN'
|
||||
height : '220px',
|
||||
lang : 'zh-CN',
|
||||
callbacks: {
|
||||
onImageUpload: function (files) {
|
||||
sendFile(files[0], this);
|
||||
}
|
||||
}
|
||||
});
|
||||
var content = $("#noticeContent").val();
|
||||
$('#editor').code(content);
|
||||
$('#editor').summernote('code', content);
|
||||
});
|
||||
|
||||
// 上传文件
|
||||
function sendFile(file, obj) {
|
||||
var data = new FormData();
|
||||
data.append("file", file);
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: ctx + "common/upload",
|
||||
data: data,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
dataType: 'json',
|
||||
success: function(result) {
|
||||
if (result.code == web_status.SUCCESS) {
|
||||
$(obj).summernote('editor.insertImage', result.url, result.fileName);
|
||||
} else {
|
||||
$.modal.alertError(result.msg);
|
||||
}
|
||||
},
|
||||
error: function(error) {
|
||||
$.modal.alertWarning("图片上传失败。");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$("#form-notice-edit").validate({
|
||||
rules:{
|
||||
xxxx:{
|
||||
noticeTitle:{
|
||||
required:true,
|
||||
},
|
||||
},
|
||||
submitHandler: function(form) {
|
||||
var sHTML = $('.summernote').code();
|
||||
$("#noticeContent").val(sHTML);
|
||||
$.operate.save(prefix + "/edit", $('#form-notice-edit').serialize());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function submitHandler() {
|
||||
if ($.validate.form()) {
|
||||
var sHTML = $('.summernote').summernote('code');
|
||||
$("#noticeContent").val(sHTML);
|
||||
$.operate.save(prefix + "/edit", $('#form-notice-edit').serialize());
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -100,12 +100,12 @@
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: '状态',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.selectDictLabel(datas, value);
|
||||
}
|
||||
visible: editFlag == 'hidden' ? false : true,
|
||||
title: '角色状态',
|
||||
align: 'center',
|
||||
formatter: function (value, row, index) {
|
||||
return statusTools(row);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
@ -127,11 +127,34 @@
|
||||
$.table.init(options);
|
||||
});
|
||||
|
||||
/*角色管理-分配数据权限*/
|
||||
/* 角色管理-分配数据权限 */
|
||||
function rule(roleId) {
|
||||
var url = prefix + '/rule/' + roleId;
|
||||
$.modal.open("分配数据权限", url);
|
||||
}
|
||||
|
||||
/* 角色状态显示 */
|
||||
function statusTools(row) {
|
||||
if (row.status == 1) {
|
||||
return '<i class=\"fa fa-toggle-off text-info fa-2x\" onclick="enable(\'' + row.roleId + '\')"></i> ';
|
||||
} else {
|
||||
return '<i class=\"fa fa-toggle-on text-info fa-2x\" onclick="disable(\'' + row.roleId + '\')"></i> ';
|
||||
}
|
||||
}
|
||||
|
||||
/* 角色管理-停用 */
|
||||
function disable(roleId) {
|
||||
$.modal.confirm("确认要停用角色吗?", function() {
|
||||
$.operate.post(prefix + "/changeStatus", { "roleId": roleId, "status": 1 });
|
||||
})
|
||||
}
|
||||
|
||||
/* 角色管理启用 */
|
||||
function enable(roleId) {
|
||||
$.modal.confirm("确认要启用角色吗?", function() {
|
||||
$.operate.post(prefix + "/changeStatus", { "roleId": roleId, "status": 0 });
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -184,7 +184,7 @@
|
||||
|
||||
/*用户管理-修改-选择部门树*/
|
||||
function selectDeptTree() {
|
||||
var deptId = $("#treeId").val();
|
||||
var deptId = $.common.isEmpty($("#treeId").val()) ? "100" : $("#treeId").val();
|
||||
var url = ctx + "system/dept/selectDeptTree/" + deptId;
|
||||
var options = {
|
||||
title: '选择部门',
|
||||
|
@ -4,7 +4,6 @@
|
||||
<title>用户头像修改</title>
|
||||
<link th:href="@{/ajax/libs/cropbox/cropbox.css}" rel="stylesheet"/>
|
||||
<body class="white-bg">
|
||||
<input name="userId" id="userId" type="hidden" th:value="${user.userId}" />
|
||||
<div class="container">
|
||||
<div class="imageBox">
|
||||
<div class="thumbBox"></div>
|
||||
@ -39,7 +38,7 @@ $(window).load(function() {
|
||||
options.imgSrc = e.target.result;
|
||||
//根据MIME判断上传的文件是不是图片类型
|
||||
if((options.imgSrc).indexOf("image/")==-1){
|
||||
parent.layer.alert("文件格式错误,请上传图片类型,如:JPG,JEPG,PNG后缀的文件。", {icon: 2,title:"系统提示"});
|
||||
$.modal.alertWarning("文件格式错误,请上传图片类型,如:JPG,JEPG,PNG后缀的文件。");
|
||||
} else {
|
||||
cropper = $('.imageBox').cropbox(options);
|
||||
}
|
||||
@ -68,7 +67,6 @@ function submitHandler() {
|
||||
var img = cropper.getBlob();
|
||||
var formdata = new FormData();
|
||||
formdata.append("avatarfile", img);
|
||||
formdata.append("userId", $("#userId").val());
|
||||
$.ajax({
|
||||
url: ctx + "system/user/profile/updateAvatar",
|
||||
data: formdata,
|
||||
|
@ -58,20 +58,19 @@
|
||||
|
||||
<div th:include="include::footer"></div>
|
||||
<script>
|
||||
var userId = [[${user.userId}]];
|
||||
/*用户信息-修改*/
|
||||
function edit() {
|
||||
var url = ctx + "system/user/profile/edit/" + userId;
|
||||
var url = ctx + 'system/user/profile/edit';
|
||||
$.modal.open("修改用户", url);
|
||||
}
|
||||
/*用户管理-重置密码*/
|
||||
function resetPwd() {
|
||||
var url = ctx + 'system/user/profile/resetPwd/' + userId;
|
||||
var url = ctx + 'system/user/profile/resetPwd';
|
||||
$.modal.open("重置密码", url, '800', '500');
|
||||
}
|
||||
/*用户管理-头像*/
|
||||
function avatar() {
|
||||
var url = ctx + 'system/user/profile/avatar/' + userId;
|
||||
var url = ctx + 'system/user/profile/avatar';
|
||||
$.modal.open("修改头像", url);
|
||||
}
|
||||
</script>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">新密码:</label>
|
||||
<div class="col-sm-8">
|
||||
<input class="form-control" type="password" name="password" id="password">
|
||||
<input class="form-control" type="password" name="newPassword" id="newPassword">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@ -51,14 +51,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
password: {
|
||||
newPassword: {
|
||||
required: true,
|
||||
minlength: 5,
|
||||
maxlength: 20
|
||||
},
|
||||
confirm: {
|
||||
required: true,
|
||||
equalTo: "#password"
|
||||
equalTo: "#newPassword"
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
@ -66,7 +66,7 @@
|
||||
required: "请输入原密码",
|
||||
remote: "原密码错误"
|
||||
},
|
||||
password: {
|
||||
newPassword: {
|
||||
required: "请输入新密码",
|
||||
minlength: "密码不能小于6个字符",
|
||||
maxlength: "密码不能大于20个字符"
|
||||
|
@ -73,6 +73,9 @@
|
||||
<a class="btn btn-danger btn-del disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:user:remove">
|
||||
<i class="fa fa-remove"></i> 删除
|
||||
</a>
|
||||
<a class="btn btn-info" onclick="$.table.importExcel()" shiro:hasPermission="system:user:import">
|
||||
<i class="fa fa-download"></i> 导入
|
||||
</a>
|
||||
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:user:export">
|
||||
<i class="fa fa-download"></i> 导出
|
||||
</a>
|
||||
@ -83,6 +86,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div th:include="include :: footer"></div>
|
||||
<script th:src="@{/ajax/libs/jquery-layout/jquery.layout-latest.js}"></script>
|
||||
<script th:src="@{/ajax/libs/jquery-ztree/3.5/js/jquery.ztree.all-3.5.js}"></script>
|
||||
@ -94,9 +98,13 @@
|
||||
var prefix = ctx + "system/user";
|
||||
|
||||
$(function() {
|
||||
$('body').layout({ west__size: 185 });
|
||||
queryUserList();
|
||||
queryDeptTree();
|
||||
var panehHidden = false;
|
||||
if ($(this).width() < 769) {
|
||||
panehHidden = true;
|
||||
}
|
||||
$('body').layout({ initClosed: panehHidden, west__size: 185 });
|
||||
queryUserList();
|
||||
queryDeptTree();
|
||||
});
|
||||
|
||||
function queryUserList() {
|
||||
@ -106,6 +114,8 @@
|
||||
updateUrl: prefix + "/edit/{id}",
|
||||
removeUrl: prefix + "/remove",
|
||||
exportUrl: prefix + "/export",
|
||||
importUrl: prefix + "/importData",
|
||||
importTemplateUrl: prefix + "/importTemplate",
|
||||
sortName: "createTime",
|
||||
sortOrder: "desc",
|
||||
modalName: "用户",
|
||||
@ -141,12 +151,12 @@
|
||||
title: '手机'
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: '状态',
|
||||
align: 'center',
|
||||
formatter: function(value, row, index) {
|
||||
return $.table.selectDictLabel(datas, value);
|
||||
}
|
||||
visible: editFlag == 'hidden' ? false : true,
|
||||
title: '用户状态',
|
||||
align: 'center',
|
||||
formatter: function (value, row, index) {
|
||||
return statusTools(row);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'createTime',
|
||||
@ -201,17 +211,52 @@
|
||||
queryDeptTree();
|
||||
});
|
||||
|
||||
/*用户管理-部门*/
|
||||
/* 用户管理-部门 */
|
||||
function dept() {
|
||||
var url = ctx + "system/dept";
|
||||
createMenuItem(url, "部门管理");
|
||||
}
|
||||
|
||||
/*用户管理-重置密码*/
|
||||
/* 用户管理-重置密码 */
|
||||
function resetPwd(userId) {
|
||||
var url = prefix + '/resetPwd/' + userId;
|
||||
$.modal.open("重置密码", url, '800', '300');
|
||||
}
|
||||
|
||||
/* 用户状态显示 */
|
||||
function statusTools(row) {
|
||||
if (row.status == 1) {
|
||||
return '<i class=\"fa fa-toggle-off text-info fa-2x\" onclick="enable(\'' + row.userId + '\')"></i> ';
|
||||
} else {
|
||||
return '<i class=\"fa fa-toggle-on text-info fa-2x\" onclick="disable(\'' + row.userId + '\')"></i> ';
|
||||
}
|
||||
}
|
||||
|
||||
/* 用户管理-停用 */
|
||||
function disable(userId) {
|
||||
$.modal.confirm("确认要停用用户吗?", function() {
|
||||
$.operate.post(prefix + "/changeStatus", { "userId": userId, "status": 1 });
|
||||
})
|
||||
}
|
||||
|
||||
/* 用户管理启用 */
|
||||
function enable(userId) {
|
||||
$.modal.confirm("确认要启用用户吗?", function() {
|
||||
$.operate.post(prefix + "/changeStatus", { "userId": userId, "status": 0 });
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
<form id="importForm" enctype="multipart/form-data" class="mt20 mb10" style="display: none;">
|
||||
<div class="col-xs-offset-1">
|
||||
<input type="file" id="file" name="file"/>
|
||||
<div class="mt10 pt5">
|
||||
<input type="checkbox" id="updateSupport" name="updateSupport" title="如果登录账户已经存在,更新这条数据。"> 是否更新已经存在的用户数据
|
||||
<a onclick="$.table.importTemplate()" class="btn btn-default btn-xs"><i class="fa fa-file-excel-o"></i> 下载模板</a>
|
||||
</div>
|
||||
<font color="red" class="pull-left mt10">
|
||||
提示:仅允许导入“xls”或“xlsx”格式文件!
|
||||
</font>
|
||||
</div>
|
||||
</form>
|
||||
</html>
|
@ -55,6 +55,12 @@
|
||||
columns: [{
|
||||
checkbox: true
|
||||
},
|
||||
{
|
||||
title: "序号",
|
||||
formatter: function (value, row, index) {
|
||||
return $.table.serialNumber(index);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'tableName',
|
||||
title: '表名称',
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.1</version>
|
||||
<version>3.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -37,7 +37,7 @@ public @interface Excel
|
||||
/**
|
||||
* 导出时在excel中每个列的宽 单位为字符
|
||||
*/
|
||||
public double width() default 20;
|
||||
public double width() default 16;
|
||||
|
||||
/**
|
||||
* 文字后缀,如% 90 变成90%
|
||||
@ -63,4 +63,30 @@ public @interface Excel
|
||||
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
|
||||
*/
|
||||
public boolean isExport() default true;
|
||||
|
||||
/**
|
||||
* 另一个类中的属性名称,支持多级获取,以小数点隔开
|
||||
*/
|
||||
public String targetAttr() default "";
|
||||
|
||||
/**
|
||||
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
|
||||
*/
|
||||
Type type() default Type.ALL;
|
||||
|
||||
public enum Type
|
||||
{
|
||||
ALL(0), EXPORT(1), IMPORT(2);
|
||||
private final int value;
|
||||
|
||||
Type(int value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int value()
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
@ -86,7 +86,7 @@ public class Global
|
||||
*/
|
||||
public static String getVersion()
|
||||
{
|
||||
return StringUtils.nvl(getConfig("ruoyi.version"), "3.0.0");
|
||||
return StringUtils.nvl(getConfig("ruoyi.version"), "3.2.0");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,13 +122,21 @@ public class Global
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载上传路径
|
||||
* 获取下载路径
|
||||
*/
|
||||
public static String getDownloadPath()
|
||||
{
|
||||
return getConfig("ruoyi.profile") + "download/";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上传路径
|
||||
*/
|
||||
public static String getUploadPath()
|
||||
{
|
||||
return getConfig("ruoyi.profile") + "upload/";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取作者
|
||||
*/
|
||||
|
@ -0,0 +1,24 @@
|
||||
package com.ruoyi.common.exception;
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class BusinessException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected final String message;
|
||||
|
||||
public BusinessException(String message)
|
||||
{
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
return message;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.ruoyi.framework.web.page;
|
||||
package com.ruoyi.common.page;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.ruoyi.framework.web.page;
|
||||
package com.ruoyi.common.page;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
@ -0,0 +1,406 @@
|
||||
package com.ruoyi.common.reflect;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Date;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.support.Convert;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
|
||||
/**
|
||||
* 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class ReflectUtils
|
||||
{
|
||||
private static final String SETTER_PREFIX = "set";
|
||||
|
||||
private static final String GETTER_PREFIX = "get";
|
||||
|
||||
private static final String CGLIB_CLASS_SEPARATOR = "$$";
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
|
||||
|
||||
/**
|
||||
* 调用Getter方法.
|
||||
* 支持多级,如:对象名.对象名.方法
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> E invokeGetter(Object obj, String propertyName)
|
||||
{
|
||||
Object object = obj;
|
||||
for (String name : StringUtils.split(propertyName, "."))
|
||||
{
|
||||
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
|
||||
object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
|
||||
}
|
||||
return (E) object;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用Setter方法, 仅匹配方法名。
|
||||
* 支持多级,如:对象名.对象名.方法
|
||||
*/
|
||||
public static <E> void invokeSetter(Object obj, String propertyName, E value)
|
||||
{
|
||||
Object object = obj;
|
||||
String[] names = StringUtils.split(propertyName, ".");
|
||||
for (int i = 0; i < names.length; i++)
|
||||
{
|
||||
if (i < names.length - 1)
|
||||
{
|
||||
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
|
||||
object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
|
||||
}
|
||||
else
|
||||
{
|
||||
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
|
||||
invokeMethodByName(object, setterMethodName, new Object[] { value });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> E getFieldValue(final Object obj, final String fieldName)
|
||||
{
|
||||
Field field = getAccessibleField(obj, fieldName);
|
||||
if (field == null)
|
||||
{
|
||||
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
return null;
|
||||
}
|
||||
E result = null;
|
||||
try
|
||||
{
|
||||
result = (E) field.get(obj);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
logger.error("不可能抛出的异常{}", e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
|
||||
*/
|
||||
public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
|
||||
{
|
||||
Field field = getAccessibleField(obj, fieldName);
|
||||
if (field == null)
|
||||
{
|
||||
// throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
field.set(obj, value);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
logger.error("不可能抛出的异常: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接调用对象方法, 无视private/protected修饰符.
|
||||
* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
|
||||
* 同时匹配方法名+参数类型,
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
|
||||
final Object[] args)
|
||||
{
|
||||
if (obj == null || methodName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
|
||||
if (method == null)
|
||||
{
|
||||
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
return (E) method.invoke(obj, args);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
|
||||
throw convertReflectionExceptionToUnchecked(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接调用对象方法, 无视private/protected修饰符,
|
||||
* 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
|
||||
* 只匹配函数名,如果有多个同名函数调用第一个。
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
|
||||
{
|
||||
Method method = getAccessibleMethodByName(obj, methodName, args.length);
|
||||
if (method == null)
|
||||
{
|
||||
// 如果为空不报错,直接返回空。
|
||||
logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
// 类型转换(将参数数据类型转换为目标方法参数类型)
|
||||
Class<?>[] cs = method.getParameterTypes();
|
||||
for (int i = 0; i < cs.length; i++)
|
||||
{
|
||||
if (args[i] != null && !args[i].getClass().equals(cs[i]))
|
||||
{
|
||||
if (cs[i] == String.class)
|
||||
{
|
||||
args[i] = Convert.toStr(args[i]);
|
||||
if (StringUtils.endsWith((String) args[i], ".0"))
|
||||
{
|
||||
args[i] = StringUtils.substringBefore((String) args[i], ".0");
|
||||
}
|
||||
}
|
||||
else if (cs[i] == Integer.class)
|
||||
{
|
||||
args[i] = Convert.toInt(args[i]);
|
||||
}
|
||||
else if (cs[i] == Long.class)
|
||||
{
|
||||
args[i] = Convert.toLong(args[i]);
|
||||
}
|
||||
else if (cs[i] == Double.class)
|
||||
{
|
||||
args[i] = Convert.toDouble(args[i]);
|
||||
}
|
||||
else if (cs[i] == Float.class)
|
||||
{
|
||||
args[i] = Convert.toFloat(args[i]);
|
||||
}
|
||||
else if (cs[i] == Date.class)
|
||||
{
|
||||
if (args[i] instanceof String)
|
||||
{
|
||||
args[i] = DateUtils.parseDate(args[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
args[i] = DateUtil.getJavaDate((Double) args[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (E) method.invoke(obj, args);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
|
||||
throw convertReflectionExceptionToUnchecked(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
|
||||
* 如向上转型到Object仍无法找到, 返回null.
|
||||
*/
|
||||
public static Field getAccessibleField(final Object obj, final String fieldName)
|
||||
{
|
||||
// 为空不报错。直接返回 null
|
||||
if (obj == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Validate.notBlank(fieldName, "fieldName can't be blank");
|
||||
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
|
||||
{
|
||||
try
|
||||
{
|
||||
Field field = superClass.getDeclaredField(fieldName);
|
||||
makeAccessible(field);
|
||||
return field;
|
||||
}
|
||||
catch (NoSuchFieldException e)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
|
||||
* 如向上转型到Object仍无法找到, 返回null.
|
||||
* 匹配函数名+参数类型。
|
||||
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
|
||||
*/
|
||||
public static Method getAccessibleMethod(final Object obj, final String methodName,
|
||||
final Class<?>... parameterTypes)
|
||||
{
|
||||
// 为空不报错。直接返回 null
|
||||
if (obj == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Validate.notBlank(methodName, "methodName can't be blank");
|
||||
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
|
||||
{
|
||||
try
|
||||
{
|
||||
Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
|
||||
makeAccessible(method);
|
||||
return method;
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
|
||||
* 如向上转型到Object仍无法找到, 返回null.
|
||||
* 只匹配函数名。
|
||||
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
|
||||
*/
|
||||
public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
|
||||
{
|
||||
// 为空不报错。直接返回 null
|
||||
if (obj == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Validate.notBlank(methodName, "methodName can't be blank");
|
||||
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
|
||||
{
|
||||
Method[] methods = searchType.getDeclaredMethods();
|
||||
for (Method method : methods)
|
||||
{
|
||||
if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
|
||||
{
|
||||
makeAccessible(method);
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
|
||||
*/
|
||||
public static void makeAccessible(Method method)
|
||||
{
|
||||
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
|
||||
&& !method.isAccessible())
|
||||
{
|
||||
method.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
|
||||
*/
|
||||
public static void makeAccessible(Field field)
|
||||
{
|
||||
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
|
||||
|| Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
|
||||
{
|
||||
field.setAccessible(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
|
||||
* 如无法找到, 返回Object.class.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Class<T> getClassGenricType(final Class clazz)
|
||||
{
|
||||
return getClassGenricType(clazz, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
|
||||
* 如无法找到, 返回Object.class.
|
||||
*/
|
||||
public static Class getClassGenricType(final Class clazz, final int index)
|
||||
{
|
||||
Type genType = clazz.getGenericSuperclass();
|
||||
|
||||
if (!(genType instanceof ParameterizedType))
|
||||
{
|
||||
logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
|
||||
|
||||
if (index >= params.length || index < 0)
|
||||
{
|
||||
logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
|
||||
+ params.length);
|
||||
return Object.class;
|
||||
}
|
||||
if (!(params[index] instanceof Class))
|
||||
{
|
||||
logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
|
||||
return Object.class;
|
||||
}
|
||||
|
||||
return (Class) params[index];
|
||||
}
|
||||
|
||||
public static Class<?> getUserClass(Object instance)
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
throw new RuntimeException("Instance must not be null");
|
||||
}
|
||||
Class clazz = instance.getClass();
|
||||
if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
|
||||
{
|
||||
Class<?> superClass = clazz.getSuperclass();
|
||||
if (superClass != null && !Object.class.equals(superClass))
|
||||
{
|
||||
return superClass;
|
||||
}
|
||||
}
|
||||
return clazz;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 将反射时的checked exception转换为unchecked exception.
|
||||
*/
|
||||
public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
|
||||
{
|
||||
if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
|
||||
|| e instanceof NoSuchMethodException)
|
||||
{
|
||||
return new IllegalArgumentException(msg, e);
|
||||
}
|
||||
else if (e instanceof InvocationTargetException)
|
||||
{
|
||||
return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
|
||||
}
|
||||
return new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
@ -290,7 +290,7 @@ public class Convert
|
||||
/**
|
||||
* 转换为Integer数组<br>
|
||||
*
|
||||
* @param split 被转换的值
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Integer[] toIntArray(String str)
|
||||
@ -301,7 +301,7 @@ public class Convert
|
||||
/**
|
||||
* 转换为Long数组<br>
|
||||
*
|
||||
* @param split 被转换的值
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Long[] toLongArray(String str)
|
||||
@ -335,8 +335,8 @@ public class Convert
|
||||
/**
|
||||
* 转换为Long数组<br>
|
||||
*
|
||||
* @param isIgnoreConvertError 是否忽略转换错误,忽略则给值null
|
||||
* @param values 被转换的值
|
||||
* @param split 分隔符
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static Long[] toLongArray(String split, String str)
|
||||
@ -358,7 +358,7 @@ public class Convert
|
||||
/**
|
||||
* 转换为String数组<br>
|
||||
*
|
||||
* @param split 被转换的值
|
||||
* @param str 被转换的值
|
||||
* @return 结果
|
||||
*/
|
||||
public static String[] toStrArray(String str)
|
||||
|
@ -10,10 +10,10 @@ import java.math.BigDecimal;
|
||||
public class Arith
|
||||
{
|
||||
|
||||
// 默认除法运算精度
|
||||
/** 默认除法运算精度 */
|
||||
private static final int DEF_DIV_SCALE = 10;
|
||||
|
||||
// 这个类不能实例化
|
||||
/** 这个类不能实例化 */
|
||||
private Arith()
|
||||
{
|
||||
}
|
||||
@ -86,6 +86,10 @@ public class Arith
|
||||
}
|
||||
BigDecimal b1 = new BigDecimal(Double.toString(v1));
|
||||
BigDecimal b2 = new BigDecimal(Double.toString(v2));
|
||||
if (b1.compareTo(BigDecimal.ZERO) == 0)
|
||||
{
|
||||
return BigDecimal.ZERO.doubleValue();
|
||||
}
|
||||
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
|
||||
}
|
||||
|
||||
|
@ -1,511 +0,0 @@
|
||||
package com.ruoyi.common.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.apache.poi.hssf.usermodel.DVConstraint;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFont;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.config.Global;
|
||||
|
||||
/**
|
||||
* Excel相关处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class ExcelUtil<T>
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
|
||||
|
||||
public Class<T> clazz;
|
||||
|
||||
public ExcelUtil(Class<T> clazz)
|
||||
{
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对excel表单默认第一个索引名转换成list
|
||||
*
|
||||
* @param input 输入流
|
||||
* @return 转换后集合
|
||||
*/
|
||||
public List<T> importExcel(InputStream input) throws Exception
|
||||
{
|
||||
return importExcel(StringUtils.EMPTY, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对excel表单指定表格索引名转换成list
|
||||
*
|
||||
* @param sheetName 表格索引名
|
||||
* @param input 输入流
|
||||
* @return 转换后集合
|
||||
*/
|
||||
public List<T> importExcel(String sheetName, InputStream input) throws Exception
|
||||
{
|
||||
List<T> list = new ArrayList<T>();
|
||||
|
||||
Workbook workbook = WorkbookFactory.create(input);
|
||||
Sheet sheet = null;
|
||||
if (StringUtils.isNotEmpty(sheetName))
|
||||
{
|
||||
// 如果指定sheet名,则取指定sheet中的内容.
|
||||
sheet = workbook.getSheet(sheetName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果传入的sheet名不存在则默认指向第1个sheet.
|
||||
sheet = workbook.getSheetAt(0);
|
||||
}
|
||||
|
||||
if (sheet == null)
|
||||
{
|
||||
throw new IOException("文件sheet不存在");
|
||||
}
|
||||
|
||||
int rows = sheet.getPhysicalNumberOfRows();
|
||||
|
||||
if (rows > 0)
|
||||
{
|
||||
// 默认序号
|
||||
int serialNum = 0;
|
||||
// 有数据时才处理 得到类的所有field.
|
||||
Field[] allFields = clazz.getDeclaredFields();
|
||||
// 定义一个map用于存放列的序号和field.
|
||||
Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();
|
||||
for (int col = 0; col < allFields.length; col++)
|
||||
{
|
||||
Field field = allFields[col];
|
||||
// 将有注解的field存放到map中.
|
||||
if (field.isAnnotationPresent(Excel.class))
|
||||
{
|
||||
// 设置类的私有字段属性可访问.
|
||||
field.setAccessible(true);
|
||||
fieldsMap.put(++serialNum, field);
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < rows; i++)
|
||||
{
|
||||
// 从第2行开始取数据,默认第一行是表头.
|
||||
Row row = sheet.getRow(i);
|
||||
int cellNum = serialNum;
|
||||
T entity = null;
|
||||
for (int j = 0; j < cellNum; j++)
|
||||
{
|
||||
Cell cell = row.getCell(j);
|
||||
if (cell == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 先设置Cell的类型,然后就可以把纯数字作为String类型读进来了
|
||||
row.getCell(j).setCellType(CellType.STRING);
|
||||
cell = row.getCell(j);
|
||||
}
|
||||
|
||||
String c = cell.getStringCellValue();
|
||||
if (StringUtils.isEmpty(c))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果不存在实例则新建.
|
||||
entity = (entity == null ? clazz.newInstance() : entity);
|
||||
// 从map中得到对应列的field.
|
||||
Field field = fieldsMap.get(j + 1);
|
||||
// 取得类型,并根据对象类型设置值.
|
||||
Class<?> fieldType = field.getType();
|
||||
if (String.class == fieldType)
|
||||
{
|
||||
field.set(entity, String.valueOf(c));
|
||||
}
|
||||
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType))
|
||||
{
|
||||
field.set(entity, Integer.parseInt(c));
|
||||
}
|
||||
else if ((Long.TYPE == fieldType) || (Long.class == fieldType))
|
||||
{
|
||||
field.set(entity, Long.valueOf(c));
|
||||
}
|
||||
else if ((Float.TYPE == fieldType) || (Float.class == fieldType))
|
||||
{
|
||||
field.set(entity, Float.valueOf(c));
|
||||
}
|
||||
else if ((Short.TYPE == fieldType) || (Short.class == fieldType))
|
||||
{
|
||||
field.set(entity, Short.valueOf(c));
|
||||
}
|
||||
else if ((Double.TYPE == fieldType) || (Double.class == fieldType))
|
||||
{
|
||||
field.set(entity, Double.valueOf(c));
|
||||
}
|
||||
else if (Character.TYPE == fieldType)
|
||||
{
|
||||
if ((c != null) && (c.length() > 0))
|
||||
{
|
||||
field.set(entity, Character.valueOf(c.charAt(0)));
|
||||
}
|
||||
}
|
||||
else if (java.util.Date.class == fieldType)
|
||||
{
|
||||
if (cell.getCellTypeEnum() == CellType.NUMERIC)
|
||||
{
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
cell.setCellValue(sdf.format(cell.getNumericCellValue()));
|
||||
c = sdf.format(cell.getNumericCellValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cell.getStringCellValue();
|
||||
}
|
||||
}
|
||||
else if (java.math.BigDecimal.class == fieldType)
|
||||
{
|
||||
c = cell.getStringCellValue();
|
||||
}
|
||||
}
|
||||
if (entity != null)
|
||||
{
|
||||
list.add(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对list数据源将其里面的数据导入到excel表单
|
||||
*
|
||||
* @param list 导出数据集合
|
||||
* @param sheetName 工作表的名称
|
||||
* @return 结果
|
||||
*/
|
||||
public AjaxResult exportExcel(List<T> list, String sheetName)
|
||||
{
|
||||
OutputStream out = null;
|
||||
HSSFWorkbook workbook = null;
|
||||
try
|
||||
{
|
||||
// 得到所有定义字段
|
||||
Field[] allFields = clazz.getDeclaredFields();
|
||||
List<Field> fields = new ArrayList<Field>();
|
||||
// 得到所有field并存放到一个list中.
|
||||
for (Field field : allFields)
|
||||
{
|
||||
if (field.isAnnotationPresent(Excel.class))
|
||||
{
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
|
||||
// 产生工作薄对象
|
||||
workbook = new HSSFWorkbook();
|
||||
// excel2003中每个sheet中最多有65536行
|
||||
int sheetSize = 65536;
|
||||
// 取出一共有多少个sheet.
|
||||
double sheetNo = Math.ceil(list.size() / sheetSize);
|
||||
for (int index = 0; index <= sheetNo; index++)
|
||||
{
|
||||
// 产生工作表对象
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
if (sheetNo == 0)
|
||||
{
|
||||
workbook.setSheetName(index, sheetName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 设置工作表的名称.
|
||||
workbook.setSheetName(index, sheetName + index);
|
||||
}
|
||||
HSSFRow row;
|
||||
HSSFCell cell; // 产生单元格
|
||||
|
||||
// 产生一行
|
||||
row = sheet.createRow(0);
|
||||
// 写入各个字段的列头名称
|
||||
for (int i = 0; i < fields.size(); i++)
|
||||
{
|
||||
Field field = fields.get(i);
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
// 创建列
|
||||
cell = row.createCell(i);
|
||||
// 设置列中写入内容为String类型
|
||||
cell.setCellType(CellType.STRING);
|
||||
HSSFCellStyle cellStyle = workbook.createCellStyle();
|
||||
cellStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
if (attr.name().indexOf("注:") >= 0)
|
||||
{
|
||||
HSSFFont font = workbook.createFont();
|
||||
font.setColor(HSSFFont.COLOR_RED);
|
||||
cellStyle.setFont(font);
|
||||
cellStyle.setFillForegroundColor(HSSFColorPredefined.YELLOW.getIndex());
|
||||
sheet.setColumnWidth(i, 6000);
|
||||
}
|
||||
else
|
||||
{
|
||||
HSSFFont font = workbook.createFont();
|
||||
// 粗体显示
|
||||
font.setBold(true);
|
||||
// 选择需要用到的字体格式
|
||||
cellStyle.setFont(font);
|
||||
cellStyle.setFillForegroundColor(HSSFColorPredefined.LIGHT_YELLOW.getIndex());
|
||||
// 设置列宽
|
||||
sheet.setColumnWidth(i, (int) ((attr.width() + 0.72) * 256));
|
||||
row.setHeight((short) (attr.height() * 20));
|
||||
}
|
||||
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
cellStyle.setWrapText(true);
|
||||
cell.setCellStyle(cellStyle);
|
||||
|
||||
// 写入列名
|
||||
cell.setCellValue(attr.name());
|
||||
|
||||
// 如果设置了提示信息则鼠标放上去提示.
|
||||
if (StringUtils.isNotEmpty(attr.prompt()))
|
||||
{
|
||||
// 这里默认设了2-101列提示.
|
||||
setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, i, i);
|
||||
}
|
||||
// 如果设置了combo属性则本列只能选择不能输入
|
||||
if (attr.combo().length > 0)
|
||||
{
|
||||
// 这里默认设了2-101列只能选择不能输入.
|
||||
setHSSFValidation(sheet, attr.combo(), 1, 100, i, i);
|
||||
}
|
||||
}
|
||||
|
||||
int startNo = index * sheetSize;
|
||||
int endNo = Math.min(startNo + sheetSize, list.size());
|
||||
// 写入各条记录,每条记录对应excel表中的一行
|
||||
HSSFCellStyle cs = workbook.createCellStyle();
|
||||
cs.setAlignment(HorizontalAlignment.CENTER);
|
||||
cs.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
for (int i = startNo; i < endNo; i++)
|
||||
{
|
||||
row = sheet.createRow(i + 1 - startNo);
|
||||
// 得到导出对象.
|
||||
T vo = (T) list.get(i);
|
||||
for (int j = 0; j < fields.size(); j++)
|
||||
{
|
||||
// 获得field.
|
||||
Field field = fields.get(j);
|
||||
// 设置实体类私有属性可访问
|
||||
field.setAccessible(true);
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
try
|
||||
{
|
||||
// 设置行高
|
||||
row.setHeight((short) (attr.height() * 20));
|
||||
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
|
||||
if (attr.isExport())
|
||||
{
|
||||
// 创建cell
|
||||
cell = row.createCell(j);
|
||||
cell.setCellStyle(cs);
|
||||
if (vo == null)
|
||||
{
|
||||
// 如果数据存在就填入,不存在填入空格.
|
||||
cell.setCellValue("");
|
||||
continue;
|
||||
}
|
||||
|
||||
String dateFormat = attr.dateFormat();
|
||||
String readConverterExp = attr.readConverterExp();
|
||||
if (StringUtils.isNotEmpty(dateFormat))
|
||||
{
|
||||
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) field.get(vo)));
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(readConverterExp))
|
||||
{
|
||||
cell.setCellValue(convertByExp(String.valueOf(field.get(vo)), readConverterExp));
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.setCellType(CellType.STRING);
|
||||
// 如果数据存在就填入,不存在填入空格.
|
||||
cell.setCellValue(StringUtils.isNull(field.get(vo)) ? attr.defaultValue() : field.get(vo) + attr.suffix());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("导出Excel失败{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String filename = encodingFilename(sheetName);
|
||||
out = new FileOutputStream(getAbsoluteFile(filename));
|
||||
workbook.write(out);
|
||||
return AjaxResult.success(filename);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("导出Excel异常{}", e.getMessage());
|
||||
return AjaxResult.error("导出Excel失败,请联系网站管理员!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (workbook != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
workbook.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (out != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置单元格上提示
|
||||
*
|
||||
* @param sheet 要设置的sheet.
|
||||
* @param promptTitle 标题
|
||||
* @param promptContent 内容
|
||||
* @param firstRow 开始行
|
||||
* @param endRow 结束行
|
||||
* @param firstCol 开始列
|
||||
* @param endCol 结束列
|
||||
* @return 设置好的sheet.
|
||||
*/
|
||||
public static HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle, String promptContent, int firstRow,
|
||||
int endRow, int firstCol, int endCol)
|
||||
{
|
||||
// 构造constraint对象
|
||||
DVConstraint constraint = DVConstraint.createCustomFormulaConstraint("DD1");
|
||||
// 四个参数分别是:起始行、终止行、起始列、终止列
|
||||
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
|
||||
// 数据有效性对象
|
||||
HSSFDataValidation dataValidationView = new HSSFDataValidation(regions, constraint);
|
||||
dataValidationView.createPromptBox(promptTitle, promptContent);
|
||||
sheet.addValidationData(dataValidationView);
|
||||
return sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置某些列的值只能输入预制的数据,显示下拉框.
|
||||
*
|
||||
* @param sheet 要设置的sheet.
|
||||
* @param textlist 下拉框显示的内容
|
||||
* @param firstRow 开始行
|
||||
* @param endRow 结束行
|
||||
* @param firstCol 开始列
|
||||
* @param endCol 结束列
|
||||
* @return 设置好的sheet.
|
||||
*/
|
||||
public static HSSFSheet setHSSFValidation(HSSFSheet sheet, String[] textlist, int firstRow, int endRow,
|
||||
int firstCol, int endCol)
|
||||
{
|
||||
// 加载下拉列表内容
|
||||
DVConstraint constraint = DVConstraint.createExplicitListConstraint(textlist);
|
||||
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
|
||||
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
|
||||
// 数据有效性对象
|
||||
HSSFDataValidation dataValidationList = new HSSFDataValidation(regions, constraint);
|
||||
sheet.addValidationData(dataValidationList);
|
||||
return sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析导出值 0=男,1=女,2=未知
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @return 解析后值
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String convertByExp(String propertyValue, String converterExp) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (itemArray[0].equals(propertyValue))
|
||||
{
|
||||
return itemArray[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码文件名
|
||||
*/
|
||||
public String encodingFilename(String filename)
|
||||
{
|
||||
filename = UUID.randomUUID().toString() + "_" + filename + ".xls";
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载路径
|
||||
*
|
||||
* @param filename 文件名称
|
||||
*/
|
||||
public String getAbsoluteFile(String filename)
|
||||
{
|
||||
String downloadPath = Global.getDownloadPath() + filename;
|
||||
File desc = new File(downloadPath);
|
||||
if (!desc.getParentFile().exists())
|
||||
{
|
||||
desc.getParentFile().mkdirs();
|
||||
}
|
||||
return downloadPath;
|
||||
}
|
||||
}
|
@ -85,7 +85,7 @@ public class IpUtils
|
||||
/**
|
||||
* 将IPv4地址转换成字节
|
||||
*
|
||||
* @param IPv4地址
|
||||
* @param text IPv4地址
|
||||
* @return byte 字节
|
||||
*/
|
||||
public static byte[] textToNumericFormatV4(String text)
|
||||
|
@ -259,38 +259,46 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
|
||||
/**
|
||||
* 下划线转驼峰命名
|
||||
*/
|
||||
public static String toUnderScoreCase(String s)
|
||||
public static String toUnderScoreCase(String str)
|
||||
{
|
||||
if (s == null)
|
||||
if (str == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean upperCase = false;
|
||||
for (int i = 0; i < s.length(); i++)
|
||||
// 前置字符是否大写
|
||||
boolean preCharIsUpperCase = true;
|
||||
// 当前字符是否大写
|
||||
boolean curreCharIsUpperCase = true;
|
||||
// 下一字符是否大写
|
||||
boolean nexteCharIsUpperCase = true;
|
||||
for (int i = 0; i < str.length(); i++)
|
||||
{
|
||||
char c = s.charAt(i);
|
||||
|
||||
boolean nextUpperCase = true;
|
||||
|
||||
if (i < (s.length() - 1))
|
||||
char c = str.charAt(i);
|
||||
if (i > 0)
|
||||
{
|
||||
nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
|
||||
}
|
||||
|
||||
if ((i > 0) && Character.isUpperCase(c))
|
||||
{
|
||||
if (!upperCase || !nextUpperCase)
|
||||
{
|
||||
sb.append(SEPARATOR);
|
||||
}
|
||||
upperCase = true;
|
||||
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
upperCase = false;
|
||||
preCharIsUpperCase = false;
|
||||
}
|
||||
|
||||
curreCharIsUpperCase = Character.isUpperCase(c);
|
||||
|
||||
if (i < (str.length() - 1))
|
||||
{
|
||||
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
|
||||
}
|
||||
|
||||
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
|
||||
{
|
||||
sb.append(SEPARATOR);
|
||||
}
|
||||
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
|
||||
{
|
||||
sb.append(SEPARATOR);
|
||||
}
|
||||
sb.append(Character.toLowerCase(c));
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
package com.ruoyi.common.utils;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 线程相关工具类.
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class Threads
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
/**
|
||||
* sleep等待,单位为毫秒
|
||||
*/
|
||||
public static void sleep(long milliseconds)
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(milliseconds);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止线程池
|
||||
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
|
||||
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
|
||||
* 如果仍人超時,則強制退出.
|
||||
* 另对在shutdown时线程本身被调用中断做了处理.
|
||||
*/
|
||||
public static void shutdownAndAwaitTermination(ExecutorService pool)
|
||||
{
|
||||
if (pool != null && !pool.isShutdown())
|
||||
{
|
||||
pool.shutdown();
|
||||
try
|
||||
{
|
||||
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
|
||||
{
|
||||
pool.shutdownNow();
|
||||
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
|
||||
{
|
||||
logger.info("Pool did not terminate");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ie)
|
||||
{
|
||||
pool.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,8 @@ public class FileUtils
|
||||
/**
|
||||
* 输出指定文件的byte数组
|
||||
*
|
||||
* @param filename 文件
|
||||
* @param filePath 文件路径
|
||||
* @param os 输出流
|
||||
* @return
|
||||
*/
|
||||
public static void writeBytes(String filePath, OutputStream os) throws IOException
|
||||
|
@ -0,0 +1,752 @@
|
||||
package com.ruoyi.common.utils.poi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.apache.poi.hssf.usermodel.DVConstraint;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
|
||||
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFont;
|
||||
import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.CellType;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.ss.usermodel.FillPatternType;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.ss.usermodel.WorkbookFactory;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.annotation.Excel.Type;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.config.Global;
|
||||
import com.ruoyi.common.exception.BusinessException;
|
||||
import com.ruoyi.common.reflect.ReflectUtils;
|
||||
import com.ruoyi.common.support.Convert;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
/**
|
||||
* Excel相关处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public class ExcelUtil<T>
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
|
||||
|
||||
/**
|
||||
* Excel sheet最大行数,默认65536
|
||||
*/
|
||||
public static final int sheetSize = 65536;
|
||||
|
||||
/**
|
||||
* 工作表名称
|
||||
*/
|
||||
private String sheetName;
|
||||
|
||||
/**
|
||||
* 导出类型(EXPORT:导出数据;IMPORT:导入模板)
|
||||
*/
|
||||
private Type type;
|
||||
|
||||
/**
|
||||
* 工作薄对象
|
||||
*/
|
||||
private Workbook wb;
|
||||
|
||||
/**
|
||||
* 工作表对象
|
||||
*/
|
||||
private Sheet sheet;
|
||||
|
||||
/**
|
||||
* 导入导出数据列表
|
||||
*/
|
||||
private List<T> list;
|
||||
|
||||
/**
|
||||
* 注解列表
|
||||
*/
|
||||
private List<Field> fields;
|
||||
|
||||
/**
|
||||
* 实体对象
|
||||
*/
|
||||
public Class<T> clazz;
|
||||
|
||||
public ExcelUtil(Class<T> clazz)
|
||||
{
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public void init(List<T> list, String sheetName, Type type)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
list = new ArrayList<T>();
|
||||
}
|
||||
this.list = list;
|
||||
this.sheetName = sheetName;
|
||||
this.type = type;
|
||||
createExcelField();
|
||||
createWorkbook();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对excel表单默认第一个索引名转换成list
|
||||
*
|
||||
* @param input 输入流
|
||||
* @return 转换后集合
|
||||
*/
|
||||
public List<T> importExcel(InputStream is) throws Exception
|
||||
{
|
||||
return importExcel(StringUtils.EMPTY, is);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对excel表单指定表格索引名转换成list
|
||||
*
|
||||
* @param sheetName 表格索引名
|
||||
* @param input 输入流
|
||||
* @return 转换后集合
|
||||
*/
|
||||
public List<T> importExcel(String sheetName, InputStream is) throws Exception
|
||||
{
|
||||
this.type = Type.IMPORT;
|
||||
this.wb = WorkbookFactory.create(is);
|
||||
List<T> list = new ArrayList<T>();
|
||||
Sheet sheet = null;
|
||||
if (StringUtils.isNotEmpty(sheetName))
|
||||
{
|
||||
// 如果指定sheet名,则取指定sheet中的内容.
|
||||
sheet = wb.getSheet(sheetName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果传入的sheet名不存在则默认指向第1个sheet.
|
||||
sheet = wb.getSheetAt(0);
|
||||
}
|
||||
|
||||
if (sheet == null)
|
||||
{
|
||||
throw new IOException("文件sheet不存在");
|
||||
}
|
||||
|
||||
int rows = sheet.getPhysicalNumberOfRows();
|
||||
|
||||
if (rows > 0)
|
||||
{
|
||||
// 默认序号
|
||||
int serialNum = 0;
|
||||
// 有数据时才处理 得到类的所有field.
|
||||
Field[] allFields = clazz.getDeclaredFields();
|
||||
// 定义一个map用于存放列的序号和field.
|
||||
Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();
|
||||
for (int col = 0; col < allFields.length; col++)
|
||||
{
|
||||
Field field = allFields[col];
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
|
||||
{
|
||||
// 设置类的私有字段属性可访问.
|
||||
field.setAccessible(true);
|
||||
fieldsMap.put(++serialNum, field);
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < rows; i++)
|
||||
{
|
||||
// 从第2行开始取数据,默认第一行是表头.
|
||||
Row row = sheet.getRow(i);
|
||||
int cellNum = serialNum;
|
||||
T entity = null;
|
||||
for (int column = 0; column < cellNum; column++)
|
||||
{
|
||||
Object val = this.getCellValue(row, column);
|
||||
|
||||
// 如果不存在实例则新建.
|
||||
entity = (entity == null ? clazz.newInstance() : entity);
|
||||
// 从map中得到对应列的field.
|
||||
Field field = fieldsMap.get(column + 1);
|
||||
// 取得类型,并根据对象类型设置值.
|
||||
Class<?> fieldType = field.getType();
|
||||
if (String.class == fieldType)
|
||||
{
|
||||
String s = Convert.toStr(val);
|
||||
if (StringUtils.endsWith(s, ".0"))
|
||||
{
|
||||
val = StringUtils.substringBefore(s, ".0");
|
||||
}
|
||||
else
|
||||
{
|
||||
val = Convert.toStr(val);
|
||||
}
|
||||
}
|
||||
else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType))
|
||||
{
|
||||
val = Convert.toInt(val);
|
||||
}
|
||||
else if ((Long.TYPE == fieldType) || (Long.class == fieldType))
|
||||
{
|
||||
val = Convert.toLong(val);
|
||||
}
|
||||
else if ((Double.TYPE == fieldType) || (Double.class == fieldType))
|
||||
{
|
||||
val = Convert.toDouble(val);
|
||||
}
|
||||
else if ((Float.TYPE == fieldType) || (Float.class == fieldType))
|
||||
{
|
||||
val = Convert.toFloat(val);
|
||||
}
|
||||
else if (Date.class == fieldType)
|
||||
{
|
||||
if (val instanceof String)
|
||||
{
|
||||
val = DateUtils.parseDate(val);
|
||||
}
|
||||
else if (val instanceof Double)
|
||||
{
|
||||
val = DateUtil.getJavaDate((Double) val);
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotNull(fieldType))
|
||||
{
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
String propertyName = field.getName();
|
||||
if (StringUtils.isNotEmpty(attr.targetAttr()))
|
||||
{
|
||||
propertyName = field.getName() + "." + attr.targetAttr();
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(attr.readConverterExp()))
|
||||
{
|
||||
val = reverseByExp(String.valueOf(val), attr.readConverterExp());
|
||||
}
|
||||
ReflectUtils.invokeSetter(entity, propertyName, val);
|
||||
}
|
||||
}
|
||||
list.add(entity);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对list数据源将其里面的数据导入到excel表单
|
||||
*
|
||||
* @param list 导出数据集合
|
||||
* @param sheetName 工作表的名称
|
||||
* @return 结果
|
||||
*/
|
||||
public AjaxResult exportExcel(List<T> list, String sheetName)
|
||||
{
|
||||
this.init(list, sheetName, Type.EXPORT);
|
||||
return exportExcel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对list数据源将其里面的数据导入到excel表单
|
||||
*
|
||||
* @param sheetName 工作表的名称
|
||||
* @return 结果
|
||||
*/
|
||||
public AjaxResult importTemplateExcel(String sheetName)
|
||||
{
|
||||
this.init(null, sheetName, Type.IMPORT);
|
||||
return exportExcel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 对list数据源将其里面的数据导入到excel表单
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
public AjaxResult exportExcel()
|
||||
{
|
||||
OutputStream out = null;
|
||||
try
|
||||
{
|
||||
// 取出一共有多少个sheet.
|
||||
double sheetNo = Math.ceil(list.size() / sheetSize);
|
||||
for (int index = 0; index <= sheetNo; index++)
|
||||
{
|
||||
createSheet(sheetNo, index);
|
||||
Cell cell = null; // 产生单元格
|
||||
|
||||
// 产生一行
|
||||
Row row = sheet.createRow(0);
|
||||
// 写入各个字段的列头名称
|
||||
for (int i = 0; i < fields.size(); i++)
|
||||
{
|
||||
Field field = fields.get(i);
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
// 创建列
|
||||
cell = row.createCell(i);
|
||||
// 设置列中写入内容为String类型
|
||||
cell.setCellType(CellType.STRING);
|
||||
CellStyle cellStyle = wb.createCellStyle();
|
||||
cellStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
if (attr.name().indexOf("注:") >= 0)
|
||||
{
|
||||
Font font = wb.createFont();
|
||||
font.setColor(HSSFFont.COLOR_RED);
|
||||
cellStyle.setFont(font);
|
||||
cellStyle.setFillForegroundColor(HSSFColorPredefined.YELLOW.getIndex());
|
||||
sheet.setColumnWidth(i, 6000);
|
||||
}
|
||||
else
|
||||
{
|
||||
Font font = wb.createFont();
|
||||
// 粗体显示
|
||||
font.setBold(true);
|
||||
// 选择需要用到的字体格式
|
||||
cellStyle.setFont(font);
|
||||
cellStyle.setFillForegroundColor(HSSFColorPredefined.LIGHT_YELLOW.getIndex());
|
||||
// 设置列宽
|
||||
sheet.setColumnWidth(i, (int) ((attr.width() + 0.72) * 256));
|
||||
row.setHeight((short) (attr.height() * 20));
|
||||
}
|
||||
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
cellStyle.setWrapText(true);
|
||||
cell.setCellStyle(cellStyle);
|
||||
|
||||
// 写入列名
|
||||
cell.setCellValue(attr.name());
|
||||
|
||||
// 如果设置了提示信息则鼠标放上去提示.
|
||||
if (StringUtils.isNotEmpty(attr.prompt()))
|
||||
{
|
||||
// 这里默认设了2-101列提示.
|
||||
setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, i, i);
|
||||
}
|
||||
// 如果设置了combo属性则本列只能选择不能输入
|
||||
if (attr.combo().length > 0)
|
||||
{
|
||||
// 这里默认设了2-101列只能选择不能输入.
|
||||
setHSSFValidation(sheet, attr.combo(), 1, 100, i, i);
|
||||
}
|
||||
}
|
||||
if (Type.EXPORT.equals(type))
|
||||
{
|
||||
fillExcelData(index, row, cell);
|
||||
}
|
||||
}
|
||||
String filename = encodingFilename(sheetName);
|
||||
out = new FileOutputStream(getAbsoluteFile(filename));
|
||||
wb.write(out);
|
||||
return AjaxResult.success(filename);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("导出Excel异常{}", e.getMessage());
|
||||
throw new BusinessException("导出Excel失败,请联系网站管理员!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (wb != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
wb.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (out != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 填充excel数据
|
||||
*
|
||||
* @param index 序号
|
||||
* @param row 单元格行
|
||||
* @param cell 类型单元格
|
||||
*/
|
||||
public void fillExcelData(int index, Row row, Cell cell)
|
||||
{
|
||||
int startNo = index * sheetSize;
|
||||
int endNo = Math.min(startNo + sheetSize, list.size());
|
||||
// 写入各条记录,每条记录对应excel表中的一行
|
||||
CellStyle cs = wb.createCellStyle();
|
||||
cs.setAlignment(HorizontalAlignment.CENTER);
|
||||
cs.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
for (int i = startNo; i < endNo; i++)
|
||||
{
|
||||
row = sheet.createRow(i + 1 - startNo);
|
||||
// 得到导出对象.
|
||||
T vo = (T) list.get(i);
|
||||
for (int j = 0; j < fields.size(); j++)
|
||||
{
|
||||
// 获得field.
|
||||
Field field = fields.get(j);
|
||||
// 设置实体类私有属性可访问
|
||||
field.setAccessible(true);
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
try
|
||||
{
|
||||
// 设置行高
|
||||
row.setHeight((short) (attr.height() * 20));
|
||||
// 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
|
||||
if (attr.isExport())
|
||||
{
|
||||
// 创建cell
|
||||
cell = row.createCell(j);
|
||||
cell.setCellStyle(cs);
|
||||
if (vo == null)
|
||||
{
|
||||
// 如果数据存在就填入,不存在填入空格.
|
||||
cell.setCellValue("");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 用于读取对象中的属性
|
||||
Object value = getTargetValue(vo, field, attr);
|
||||
String dateFormat = attr.dateFormat();
|
||||
String readConverterExp = attr.readConverterExp();
|
||||
if (StringUtils.isNotEmpty(dateFormat))
|
||||
{
|
||||
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value));
|
||||
}
|
||||
else if (StringUtils.isNotEmpty(readConverterExp))
|
||||
{
|
||||
cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp));
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.setCellType(CellType.STRING);
|
||||
// 如果数据存在就填入,不存在填入空格.
|
||||
cell.setCellValue(StringUtils.isNull(value) ? attr.defaultValue() : value + attr.suffix());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.error("导出Excel失败{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置单元格上提示
|
||||
*
|
||||
* @param sheet 要设置的sheet.
|
||||
* @param promptTitle 标题
|
||||
* @param promptContent 内容
|
||||
* @param firstRow 开始行
|
||||
* @param endRow 结束行
|
||||
* @param firstCol 开始列
|
||||
* @param endCol 结束列
|
||||
* @return 设置好的sheet.
|
||||
*/
|
||||
public static Sheet setHSSFPrompt(Sheet sheet, String promptTitle, String promptContent, int firstRow, int endRow,
|
||||
int firstCol, int endCol)
|
||||
{
|
||||
// 构造constraint对象
|
||||
DVConstraint constraint = DVConstraint.createCustomFormulaConstraint("DD1");
|
||||
// 四个参数分别是:起始行、终止行、起始列、终止列
|
||||
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
|
||||
// 数据有效性对象
|
||||
HSSFDataValidation dataValidationView = new HSSFDataValidation(regions, constraint);
|
||||
dataValidationView.createPromptBox(promptTitle, promptContent);
|
||||
sheet.addValidationData(dataValidationView);
|
||||
return sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置某些列的值只能输入预制的数据,显示下拉框.
|
||||
*
|
||||
* @param sheet 要设置的sheet.
|
||||
* @param textlist 下拉框显示的内容
|
||||
* @param firstRow 开始行
|
||||
* @param endRow 结束行
|
||||
* @param firstCol 开始列
|
||||
* @param endCol 结束列
|
||||
* @return 设置好的sheet.
|
||||
*/
|
||||
public static Sheet setHSSFValidation(Sheet sheet, String[] textlist, int firstRow, int endRow, int firstCol,
|
||||
int endCol)
|
||||
{
|
||||
// 加载下拉列表内容
|
||||
DVConstraint constraint = DVConstraint.createExplicitListConstraint(textlist);
|
||||
// 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列
|
||||
CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
|
||||
// 数据有效性对象
|
||||
HSSFDataValidation dataValidationList = new HSSFDataValidation(regions, constraint);
|
||||
sheet.addValidationData(dataValidationList);
|
||||
return sheet;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析导出值 0=男,1=女,2=未知
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @return 解析后值
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String convertByExp(String propertyValue, String converterExp) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (itemArray[0].equals(propertyValue))
|
||||
{
|
||||
return itemArray[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 反向解析值 男=0,女=1,未知=2
|
||||
*
|
||||
* @param propertyValue 参数值
|
||||
* @param converterExp 翻译注解
|
||||
* @return 解析后值
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String reverseByExp(String propertyValue, String converterExp) throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
String[] convertSource = converterExp.split(",");
|
||||
for (String item : convertSource)
|
||||
{
|
||||
String[] itemArray = item.split("=");
|
||||
if (itemArray[1].equals(propertyValue))
|
||||
{
|
||||
return itemArray[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
return propertyValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 编码文件名
|
||||
*/
|
||||
public String encodingFilename(String filename)
|
||||
{
|
||||
filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx";
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下载路径
|
||||
*
|
||||
* @param filename 文件名称
|
||||
*/
|
||||
public String getAbsoluteFile(String filename)
|
||||
{
|
||||
String downloadPath = Global.getDownloadPath() + filename;
|
||||
File desc = new File(downloadPath);
|
||||
if (!desc.getParentFile().exists())
|
||||
{
|
||||
desc.getParentFile().mkdirs();
|
||||
}
|
||||
return downloadPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取bean中的属性值
|
||||
*
|
||||
* @param vo 实体对象
|
||||
* @param field 字段
|
||||
* @param excel 注解
|
||||
* @return 最终的属性值
|
||||
* @throws Exception
|
||||
*/
|
||||
private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
|
||||
{
|
||||
Object o = field.get(vo);
|
||||
if (StringUtils.isNotEmpty(excel.targetAttr()))
|
||||
{
|
||||
String target = excel.targetAttr();
|
||||
if (target.indexOf(".") > -1)
|
||||
{
|
||||
String[] targets = target.split("[.]");
|
||||
for (String name : targets)
|
||||
{
|
||||
o = getValue(o, name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
o = getValue(o, target);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* 以类的属性的get方法方法形式获取值
|
||||
*
|
||||
* @param o
|
||||
* @param name
|
||||
* @return value
|
||||
* @throws Exception
|
||||
*/
|
||||
private Object getValue(Object o, String name) throws Exception
|
||||
{
|
||||
if (StringUtils.isNotEmpty(name))
|
||||
{
|
||||
Class<?> clazz = o.getClass();
|
||||
String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
Method method = clazz.getMethod(methodName);
|
||||
o = method.invoke(o);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到所有定义字段
|
||||
*/
|
||||
private void createExcelField()
|
||||
{
|
||||
this.fields = new ArrayList<Field>();
|
||||
Field[] allFields = clazz.getDeclaredFields();
|
||||
// 得到所有field并存放到一个list中.
|
||||
for (Field field : allFields)
|
||||
{
|
||||
Excel attr = field.getAnnotation(Excel.class);
|
||||
if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
|
||||
{
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个工作簿
|
||||
*/
|
||||
public void createWorkbook()
|
||||
{
|
||||
this.wb = new SXSSFWorkbook(500);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建工作表
|
||||
*
|
||||
* @param sheetName,指定Sheet名称
|
||||
* @param sheetNo sheet数量
|
||||
* @param index 序号
|
||||
*/
|
||||
public void createSheet(double sheetNo, int index)
|
||||
{
|
||||
this.sheet = wb.createSheet();
|
||||
// 设置工作表的名称.
|
||||
if (sheetNo == 0)
|
||||
{
|
||||
wb.setSheetName(index, sheetName);
|
||||
}
|
||||
else
|
||||
{
|
||||
wb.setSheetName(index, sheetName + index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单元格值
|
||||
*
|
||||
* @param row 获取的行
|
||||
* @param column 获取单元格列号
|
||||
* @return 单元格值
|
||||
*/
|
||||
public Object getCellValue(Row row, int column)
|
||||
{
|
||||
if (row == null)
|
||||
{
|
||||
return row;
|
||||
}
|
||||
Object val = "";
|
||||
try
|
||||
{
|
||||
Cell cell = row.getCell(column);
|
||||
if (cell != null)
|
||||
{
|
||||
if (cell.getCellTypeEnum() == CellType.NUMERIC)
|
||||
{
|
||||
val = cell.getNumericCellValue();
|
||||
if (HSSFDateUtil.isCellDateFormatted(cell))
|
||||
{
|
||||
val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Double) val % 1 > 0)
|
||||
{
|
||||
val = new DecimalFormat("0.00").format(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = new DecimalFormat("0").format(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.STRING)
|
||||
{
|
||||
val = cell.getStringCellValue();
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.BOOLEAN)
|
||||
{
|
||||
val = cell.getBooleanCellValue();
|
||||
}
|
||||
else if (cell.getCellTypeEnum() == CellType.ERROR)
|
||||
{
|
||||
val = cell.getErrorCellValue();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.1</version>
|
||||
<version>3.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -73,9 +73,9 @@ public class DataScopeAspect
|
||||
|
||||
/**
|
||||
* 数据范围过滤
|
||||
*
|
||||
* @param da 部门表别名
|
||||
* @return 标准连接条件对象
|
||||
* @param joinPoint 切点
|
||||
* @param user 用户
|
||||
* @param alias 别名
|
||||
*/
|
||||
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String alias)
|
||||
{
|
||||
|
@ -121,8 +121,8 @@ public class LogAspect
|
||||
/**
|
||||
* 获取注解中对方法的描述信息 用于Controller层注解
|
||||
*
|
||||
* @param joinPoint 切点
|
||||
* @return 方法描述
|
||||
* @param log 日志
|
||||
* @param operLog 操作日志
|
||||
* @throws Exception
|
||||
*/
|
||||
public void getControllerMethodDescription(Log log, SysOperLog operLog) throws Exception
|
||||
|
@ -19,16 +19,27 @@ public class CaptchaConfig
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty("kaptcha.border", "yes");
|
||||
// 边框颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.border.color", "105,179,90");
|
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.textproducer.font.color", "blue");
|
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty("kaptcha.image.width", "160");
|
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty("kaptcha.image.height", "60");
|
||||
properties.setProperty("kaptcha.textproducer.font.size", "28");
|
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty("kaptcha.textproducer.font.size", "30");
|
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty("kaptcha.session.key", "kaptchaCode");
|
||||
properties.setProperty("kaptcha.textproducer.char.spac", "35");
|
||||
// 验证码文本字符间距 默认为2
|
||||
properties.setProperty("kaptcha.textproducer.char.space", "3");
|
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty("kaptcha.textproducer.char.length", "5");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
|
||||
// 验证码噪点颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.noise.color", "white");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
@ -40,19 +51,33 @@ public class CaptchaConfig
|
||||
{
|
||||
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
|
||||
Properties properties = new Properties();
|
||||
// 是否有边框 默认为true 我们可以自己设置yes,no
|
||||
properties.setProperty("kaptcha.border", "yes");
|
||||
// 边框颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.border.color", "105,179,90");
|
||||
// 验证码文本字符颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.textproducer.font.color", "blue");
|
||||
// 验证码图片宽度 默认为200
|
||||
properties.setProperty("kaptcha.image.width", "160");
|
||||
// 验证码图片高度 默认为50
|
||||
properties.setProperty("kaptcha.image.height", "60");
|
||||
properties.setProperty("kaptcha.textproducer.font.size", "38");
|
||||
// 验证码文本字符大小 默认为40
|
||||
properties.setProperty("kaptcha.textproducer.font.size", "35");
|
||||
// KAPTCHA_SESSION_KEY
|
||||
properties.setProperty("kaptcha.session.key", "kaptchaCodeMath");
|
||||
// 验证码文本生成器
|
||||
properties.setProperty("kaptcha.textproducer.impl", "com.ruoyi.framework.config.KaptchaTextCreator");
|
||||
properties.setProperty("kaptcha.textproducer.char.spac", "5");
|
||||
// 验证码文本字符间距 默认为2
|
||||
properties.setProperty("kaptcha.textproducer.char.space", "3");
|
||||
// 验证码文本字符长度 默认为5
|
||||
properties.setProperty("kaptcha.textproducer.char.length", "6");
|
||||
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
|
||||
properties.setProperty("kaptcha.textproducer.font.names", "Arial,Courier");
|
||||
// 验证码噪点颜色 默认为Color.BLACK
|
||||
properties.setProperty("kaptcha.noise.color", "white");
|
||||
// 干扰实现类
|
||||
properties.setProperty("kaptcha.noise.impl", "com.google.code.kaptcha.impl.NoNoise");
|
||||
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
|
||||
properties.setProperty("kaptcha.obscurificator.impl", "com.google.code.kaptcha.impl.ShadowGimpy");
|
||||
Config config = new Config(properties);
|
||||
defaultKaptcha.setConfig(config);
|
||||
|
@ -8,8 +8,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
|
||||
import com.ruoyi.common.enums.DataSourceType;
|
||||
import com.ruoyi.framework.config.properties.DruidProperties;
|
||||
import com.ruoyi.framework.datasource.DynamicDataSource;
|
||||
|
||||
/**
|
||||
@ -22,17 +24,19 @@ public class DruidConfig
|
||||
{
|
||||
@Bean
|
||||
@ConfigurationProperties("spring.datasource.druid.master")
|
||||
public DataSource masterDataSource()
|
||||
public DataSource masterDataSource(DruidProperties druidProperties)
|
||||
{
|
||||
return DruidDataSourceBuilder.create().build();
|
||||
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
|
||||
return druidProperties.dataSource(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties("spring.datasource.druid.slave")
|
||||
@ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
|
||||
public DataSource slaveDataSource()
|
||||
public DataSource slaveDataSource(DruidProperties druidProperties)
|
||||
{
|
||||
return DruidDataSourceBuilder.create().build();
|
||||
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
|
||||
return druidProperties.dataSource(dataSource);
|
||||
}
|
||||
|
||||
@Bean(name = "dynamicDataSource")
|
||||
|
@ -0,0 +1,40 @@
|
||||
package com.ruoyi.framework.config;
|
||||
|
||||
import org.springframework.boot.web.context.WebServerInitializedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
/**
|
||||
* 服务相关配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class ServerConfig implements ApplicationListener<WebServerInitializedEvent>
|
||||
{
|
||||
private int serverPort;
|
||||
|
||||
public String getUrl()
|
||||
{
|
||||
InetAddress address = null;
|
||||
try
|
||||
{
|
||||
address = InetAddress.getLocalHost();
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "http://" + address.getHostAddress() + ":" + this.serverPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(WebServerInitializedEvent event)
|
||||
{
|
||||
this.serverPort = event.getWebServer().getPort();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.ruoyi.framework.config.properties;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
|
||||
/**
|
||||
* druid 配置属性
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class DruidProperties
|
||||
{
|
||||
@Value("${spring.datasource.druid.initialSize}")
|
||||
private int initialSize;
|
||||
|
||||
@Value("${spring.datasource.druid.minIdle}")
|
||||
private int minIdle;
|
||||
|
||||
@Value("${spring.datasource.druid.maxActive}")
|
||||
private int maxActive;
|
||||
|
||||
@Value("${spring.datasource.druid.maxWait}")
|
||||
private int maxWait;
|
||||
|
||||
@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
|
||||
private int timeBetweenEvictionRunsMillis;
|
||||
|
||||
@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
|
||||
private int minEvictableIdleTimeMillis;
|
||||
|
||||
@Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
|
||||
private int maxEvictableIdleTimeMillis;
|
||||
|
||||
@Value("${spring.datasource.druid.validationQuery}")
|
||||
private String validationQuery;
|
||||
|
||||
@Value("${spring.datasource.druid.testWhileIdle}")
|
||||
private boolean testWhileIdle;
|
||||
|
||||
@Value("${spring.datasource.druid.testOnBorrow}")
|
||||
private boolean testOnBorrow;
|
||||
|
||||
@Value("${spring.datasource.druid.testOnReturn}")
|
||||
private boolean testOnReturn;
|
||||
|
||||
public DruidDataSource dataSource(DruidDataSource datasource)
|
||||
{
|
||||
/** 配置初始化大小、最小、最大 */
|
||||
datasource.setInitialSize(initialSize);
|
||||
datasource.setMaxActive(maxActive);
|
||||
datasource.setMinIdle(minIdle);
|
||||
|
||||
/** 配置获取连接等待超时的时间 */
|
||||
datasource.setMaxWait(maxWait);
|
||||
|
||||
/** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
|
||||
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
||||
|
||||
/** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */
|
||||
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
|
||||
datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
|
||||
|
||||
/**
|
||||
* 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
|
||||
*/
|
||||
datasource.setValidationQuery(validationQuery);
|
||||
/** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */
|
||||
datasource.setTestWhileIdle(testWhileIdle);
|
||||
/** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
|
||||
datasource.setTestOnBorrow(testOnBorrow);
|
||||
/** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
|
||||
datasource.setTestOnReturn(testOnReturn);
|
||||
return datasource;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package com.ruoyi.framework.manager;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import com.ruoyi.common.utils.Threads;
|
||||
|
||||
/**
|
||||
* 异步任务管理器
|
||||
@ -34,10 +35,18 @@ public class AsyncManager
|
||||
/**
|
||||
* 执行任务
|
||||
*
|
||||
* @param 任务task
|
||||
* @param task 任务
|
||||
*/
|
||||
public void execute(TimerTask task)
|
||||
{
|
||||
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止任务线程池
|
||||
*/
|
||||
public void shutdown()
|
||||
{
|
||||
Threads.shutdownAndAwaitTermination(executor);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
package com.ruoyi.framework.manager;
|
||||
|
||||
import com.ruoyi.framework.shiro.web.session.SpringSessionValidationScheduler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
/**
|
||||
* 确保应用退出时能关闭后台线程
|
||||
*
|
||||
* @author cj
|
||||
*/
|
||||
@Component
|
||||
public class ShutdownManager
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger("sys-user");
|
||||
|
||||
@Autowired(required = false)
|
||||
private SpringSessionValidationScheduler springSessionValidationScheduler;
|
||||
|
||||
@PreDestroy
|
||||
public void destroy()
|
||||
{
|
||||
shutdownSpringSessionValidationScheduler();
|
||||
shutdownAsyncManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止Seesion会话检查
|
||||
*/
|
||||
private void shutdownSpringSessionValidationScheduler()
|
||||
{
|
||||
if (springSessionValidationScheduler != null && springSessionValidationScheduler.isEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.info("====关闭会话验证任务====");
|
||||
springSessionValidationScheduler.disableSessionValidation();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止异步执行任务
|
||||
*/
|
||||
private void shutdownAsyncManager()
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.info("====关闭后台任务任务线程池====");
|
||||
AsyncManager.me().shutdown();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
@ -96,7 +96,7 @@ public class SysLoginService
|
||||
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
|
||||
{
|
||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
|
||||
throw new UserBlockedException(user.getRemark());
|
||||
throw new UserBlockedException();
|
||||
}
|
||||
|
||||
passwordService.validate(user, password);
|
||||
|
@ -0,0 +1,62 @@
|
||||
package com.ruoyi.framework.shiro.service;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.apache.shiro.session.Session;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.framework.shiro.session.OnlineSession;
|
||||
import com.ruoyi.system.domain.SysUserOnline;
|
||||
import com.ruoyi.system.service.ISysUserOnlineService;
|
||||
|
||||
/**
|
||||
* 会话db操作处理
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Component
|
||||
public class SysShiroService
|
||||
{
|
||||
@Autowired
|
||||
private ISysUserOnlineService onlineService;
|
||||
|
||||
/**
|
||||
* 删除会话
|
||||
*
|
||||
* @param onlineSession 会话信息
|
||||
*/
|
||||
public void deleteSession(OnlineSession onlineSession)
|
||||
{
|
||||
onlineService.deleteOnlineById(String.valueOf(onlineSession.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话信息
|
||||
*
|
||||
* @param sessionId
|
||||
* @return
|
||||
*/
|
||||
public Session getSession(Serializable sessionId)
|
||||
{
|
||||
SysUserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
|
||||
return StringUtils.isNull(userOnline) ? null : createSession(userOnline);
|
||||
}
|
||||
|
||||
public Session createSession(SysUserOnline userOnline)
|
||||
{
|
||||
OnlineSession onlineSession = new OnlineSession();
|
||||
if (StringUtils.isNotNull(userOnline))
|
||||
{
|
||||
onlineSession.setId(userOnline.getSessionId());
|
||||
onlineSession.setHost(userOnline.getIpaddr());
|
||||
onlineSession.setBrowser(userOnline.getBrowser());
|
||||
onlineSession.setOs(userOnline.getOs());
|
||||
onlineSession.setDeptName(userOnline.getDeptName());
|
||||
onlineSession.setLoginName(userOnline.getLoginName());
|
||||
onlineSession.setStartTimestamp(userOnline.getStartTimestamp());
|
||||
onlineSession.setLastAccessTime(userOnline.getLastAccessTime());
|
||||
onlineSession.setTimeout(userOnline.getExpireTime());
|
||||
}
|
||||
return onlineSession;
|
||||
}
|
||||
}
|
@ -9,8 +9,7 @@ import org.springframework.beans.factory.annotation.Value;
|
||||
import com.ruoyi.common.enums.OnlineStatus;
|
||||
import com.ruoyi.framework.manager.AsyncManager;
|
||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||
import com.ruoyi.system.domain.SysUserOnline;
|
||||
import com.ruoyi.system.service.ISysUserOnlineService;
|
||||
import com.ruoyi.framework.shiro.service.SysShiroService;
|
||||
|
||||
/**
|
||||
* 针对自定义的ShiroSession的db操作
|
||||
@ -31,7 +30,7 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
|
||||
private static final String LAST_SYNC_DB_TIMESTAMP = OnlineSessionDAO.class.getName() + "LAST_SYNC_DB_TIMESTAMP";
|
||||
|
||||
@Autowired
|
||||
private ISysUserOnlineService onlineService;
|
||||
private SysShiroService sysShiroService;
|
||||
|
||||
public OnlineSessionDAO()
|
||||
{
|
||||
@ -52,12 +51,7 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
|
||||
@Override
|
||||
protected Session doReadSession(Serializable sessionId)
|
||||
{
|
||||
SysUserOnline userOnline = onlineService.selectOnlineById(String.valueOf(sessionId));
|
||||
if (userOnline == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return super.doReadSession(sessionId);
|
||||
return sysShiroService.getSession(sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,6 +103,6 @@ public class OnlineSessionDAO extends EnterpriseCacheSessionDAO
|
||||
return;
|
||||
}
|
||||
onlineSession.setStatus(OnlineStatus.off_line);
|
||||
onlineService.deleteOnlineById(String.valueOf(onlineSession.getId()));
|
||||
sysShiroService.deleteSession(onlineSession);
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ public class OnlineSessionFilter extends AccessControlFilter
|
||||
subject.logout();
|
||||
}
|
||||
saveRequestAndRedirectToLogin(request, response);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 跳转到登录页
|
||||
|
@ -8,6 +8,7 @@ import org.apache.shiro.session.mgt.SessionValidationScheduler;
|
||||
import org.apache.shiro.session.mgt.ValidatingSessionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.common.utils.Threads;
|
||||
|
||||
/**
|
||||
* 自定义任务调度器完成
|
||||
@ -17,7 +18,7 @@ import org.slf4j.LoggerFactory;
|
||||
public class SpringSessionValidationScheduler implements SessionValidationScheduler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(SpringSessionValidationScheduler.class);
|
||||
|
||||
|
||||
public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;
|
||||
|
||||
/**
|
||||
@ -134,6 +135,10 @@ public class SpringSessionValidationScheduler implements SessionValidationSchedu
|
||||
log.debug("Stopping Spring Scheduler session validation job...");
|
||||
}
|
||||
|
||||
if (this.enabled)
|
||||
{
|
||||
Threads.shutdownAndAwaitTermination(executorService);
|
||||
}
|
||||
this.enabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,6 @@ public class FileUploadUtils
|
||||
*
|
||||
* @param baseDir 相对应用的基目录
|
||||
* @param file 上传的文件
|
||||
* @param needDatePathAndRandomName 是否需要日期目录和随机文件名前缀
|
||||
* @param extension 上传文件类型
|
||||
* @return 返回上传成功的文件名
|
||||
* @throws FileSizeLimitExceededException 如果超出最大大小
|
||||
|
@ -13,7 +13,7 @@ public class PermissionUtils
|
||||
/**
|
||||
* 权限错误消息提醒
|
||||
*
|
||||
* @param errorMsg 错误信息
|
||||
* @param permissionsStr 错误信息
|
||||
* @return
|
||||
*/
|
||||
public static String getMsg(String permissionsStr)
|
||||
|
@ -19,7 +19,7 @@ import com.ruoyi.system.domain.SysUser;
|
||||
*/
|
||||
public class ShiroUtils
|
||||
{
|
||||
public static Subject getSubjct()
|
||||
public static Subject getSubject()
|
||||
{
|
||||
return SecurityUtils.getSubject();
|
||||
}
|
||||
@ -31,13 +31,13 @@ public class ShiroUtils
|
||||
|
||||
public static void logout()
|
||||
{
|
||||
getSubjct().logout();
|
||||
getSubject().logout();
|
||||
}
|
||||
|
||||
public static SysUser getSysUser()
|
||||
{
|
||||
SysUser user = null;
|
||||
Object obj = getSubjct().getPrincipal();
|
||||
Object obj = getSubject().getPrincipal();
|
||||
if (StringUtils.isNotNull(obj))
|
||||
{
|
||||
user = new SysUser();
|
||||
@ -48,7 +48,7 @@ public class ShiroUtils
|
||||
|
||||
public static void setSysUser(SysUser user)
|
||||
{
|
||||
Subject subject = getSubjct();
|
||||
Subject subject = getSubject();
|
||||
PrincipalCollection principalCollection = subject.getPrincipals();
|
||||
String realmName = principalCollection.getRealmNames().iterator().next();
|
||||
PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
|
||||
@ -75,12 +75,12 @@ public class ShiroUtils
|
||||
|
||||
public static String getIp()
|
||||
{
|
||||
return getSubjct().getSession().getHost();
|
||||
return getSubject().getSession().getHost();
|
||||
}
|
||||
|
||||
public static String getSessionId()
|
||||
{
|
||||
return String.valueOf(getSubjct().getSession().getId());
|
||||
return String.valueOf(getSubject().getSession().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,11 +8,11 @@ import org.springframework.web.bind.annotation.InitBinder;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.page.PageDomain;
|
||||
import com.ruoyi.common.page.TableDataInfo;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.framework.util.ShiroUtils;
|
||||
import com.ruoyi.framework.web.page.PageDomain;
|
||||
import com.ruoyi.framework.web.page.TableDataInfo;
|
||||
import com.ruoyi.framework.web.page.TableSupport;
|
||||
import com.ruoyi.system.domain.SysUser;
|
||||
|
||||
@ -79,6 +79,17 @@ public class BaseController
|
||||
return rows > 0 ? success() : error();
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应返回结果
|
||||
*
|
||||
* @param result 结果
|
||||
* @return 操作结果
|
||||
*/
|
||||
protected AjaxResult toAjax(boolean result)
|
||||
{
|
||||
return result ? success() : error();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回成功
|
||||
*/
|
||||
|
@ -28,6 +28,9 @@ import oshi.util.Util;
|
||||
*/
|
||||
public class Server
|
||||
{
|
||||
|
||||
private static final int OSHI_WAIT_SECOND = 1000;
|
||||
|
||||
/**
|
||||
* CPU相关信息
|
||||
*/
|
||||
@ -126,7 +129,7 @@ public class Server
|
||||
{
|
||||
// CPU信息
|
||||
long[] prevTicks = processor.getSystemCpuLoadTicks();
|
||||
Util.sleep(500);
|
||||
Util.sleep(OSHI_WAIT_SECOND);
|
||||
long[] ticks = processor.getSystemCpuLoadTicks();
|
||||
long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
|
||||
long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
|
||||
|
@ -7,6 +7,7 @@ import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import com.ruoyi.common.base.AjaxResult;
|
||||
import com.ruoyi.common.exception.BusinessException;
|
||||
import com.ruoyi.common.exception.DemoModeException;
|
||||
import com.ruoyi.framework.util.PermissionUtils;
|
||||
|
||||
@ -19,7 +20,7 @@ import com.ruoyi.framework.util.PermissionUtils;
|
||||
public class DefaultExceptionHandler
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(DefaultExceptionHandler.class);
|
||||
|
||||
|
||||
/**
|
||||
* 权限校验失败
|
||||
*/
|
||||
@ -59,7 +60,17 @@ public class DefaultExceptionHandler
|
||||
log.error(e.getMessage(), e);
|
||||
return AjaxResult.error("服务器错误,请联系管理员");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 业务异常
|
||||
*/
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public AjaxResult businessException(BusinessException e)
|
||||
{
|
||||
log.error(e.getMessage(), e);
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 演示模式异常
|
||||
*/
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user