1042 changed files with 297227 additions and 94 deletions
@ -1,25 +1,46 @@ |
|||
# ---> Java |
|||
# Compiled class file |
|||
*.class |
|||
###################################################################### |
|||
# Build Tools |
|||
|
|||
# Log file |
|||
*.log |
|||
.gradle |
|||
/build/ |
|||
!gradle/wrapper/gradle-wrapper.jar |
|||
|
|||
target/ |
|||
!.mvn/wrapper/maven-wrapper.jar |
|||
|
|||
# BlueJ files |
|||
*.ctxt |
|||
###################################################################### |
|||
# IDE |
|||
|
|||
# Mobile Tools for Java (J2ME) |
|||
.mtj.tmp/ |
|||
### STS ### |
|||
.apt_generated |
|||
.classpath |
|||
.factorypath |
|||
.project |
|||
.settings |
|||
.springBeans |
|||
|
|||
# Package Files # |
|||
*.jar |
|||
*.war |
|||
*.nar |
|||
*.ear |
|||
*.zip |
|||
*.tar.gz |
|||
*.rar |
|||
### IntelliJ IDEA ### |
|||
.idea |
|||
*.iws |
|||
*.iml |
|||
*.ipr |
|||
|
|||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml |
|||
hs_err_pid* |
|||
### JRebel ### |
|||
rebel.xml |
|||
### NetBeans ### |
|||
nbproject/private/ |
|||
build/* |
|||
nbbuild/ |
|||
dist/ |
|||
nbdist/ |
|||
.nb-gradle/ |
|||
|
|||
###################################################################### |
|||
# Others |
|||
*.log |
|||
*.xml.versionsBackup |
|||
*.swp |
|||
|
|||
!*/build/*.java |
|||
!*/build/*.html |
|||
!*/build/*.xml |
After Width: | Height: | Size: 13 KiB |
@ -1,73 +1,20 @@ |
|||
Apache License |
|||
Version 2.0, January 2004 |
|||
http://www.apache.org/licenses/ |
|||
|
|||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION |
|||
|
|||
1. Definitions. |
|||
|
|||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. |
|||
|
|||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. |
|||
|
|||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. |
|||
|
|||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. |
|||
|
|||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. |
|||
|
|||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. |
|||
|
|||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). |
|||
|
|||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. |
|||
|
|||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." |
|||
|
|||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. |
|||
|
|||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. |
|||
|
|||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. |
|||
|
|||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: |
|||
|
|||
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and |
|||
|
|||
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and |
|||
|
|||
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and |
|||
|
|||
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. |
|||
|
|||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. |
|||
|
|||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. |
|||
|
|||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. |
|||
|
|||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. |
|||
|
|||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. |
|||
|
|||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. |
|||
|
|||
END OF TERMS AND CONDITIONS |
|||
|
|||
APPENDIX: How to apply the Apache License to your work. |
|||
|
|||
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. |
|||
|
|||
Copyright [yyyy] [name of copyright owner] |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2018 RuoYi |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy of |
|||
this software and associated documentation files (the "Software"), to deal in |
|||
the Software without restriction, including without limitation the rights to |
|||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
|||
the Software, and to permit persons to whom the Software is furnished to do so, |
|||
subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
@ -1,3 +1,102 @@ |
|||
# win-print-server |
|||
<p align="center"> |
|||
<img alt="logo" src="https://oscimg.oschina.net/oscnet/up-dd77653d7c9f197dd9d93684f3c8dcfbab6.png"> |
|||
</p> |
|||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v4.7.9</h1> |
|||
<h4 align="center">基于SpringBoot开发的轻量级Java快速开发框架</h4> |
|||
<p align="center"> |
|||
<a href="https://gitee.com/y_project/RuoYi/stargazers"><img src="https://gitee.com/y_project/RuoYi/badge/star.svg?theme=gvp"></a> |
|||
<a href="https://gitee.com/y_project/RuoYi"><img src="https://img.shields.io/badge/RuoYi-v4.7.9-brightgreen.svg"></a> |
|||
<a href="https://gitee.com/y_project/RuoYi/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a> |
|||
</p> |
|||
|
|||
打印服务 |
|||
## 平台简介 |
|||
|
|||
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。 |
|||
|
|||
性别男,若依是给女儿取的名字(寓意:你若不离不弃,我必生死相依) |
|||
|
|||
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。 |
|||
|
|||
* 前后端分离版本,请移步[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud) |
|||
* 感谢 [hplus](https://gitee.com/hplus_admin/hplus) 后台主题 UI 框架。 |
|||
* 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip) |
|||
* 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console) |
|||
|
|||
## 内置功能 |
|||
|
|||
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 |
|||
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 |
|||
3. 岗位管理:配置系统用户所属担任职务。 |
|||
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 |
|||
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 |
|||
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 |
|||
7. 参数管理:对系统动态配置常用参数。 |
|||
8. 通知公告:系统通知公告信息发布维护。 |
|||
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 |
|||
10. 登录日志:系统登录日志记录查询包含登录异常。 |
|||
11. 在线用户:当前系统中活跃用户状态监控。 |
|||
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 |
|||
13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 |
|||
14. 系统接口:根据业务代码自动生成相关的api接口文档。 |
|||
15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 |
|||
16. 缓存监控:对系统的缓存查询,删除、清空等操作。 |
|||
17. 在线构建器:拖动表单元素生成相应的HTML代码。 |
|||
18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 |
|||
|
|||
## 在线体验 |
|||
|
|||
- admin/admin123 |
|||
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。 |
|||
|
|||
演示地址:http://ruoyi.vip |
|||
文档地址:http://doc.ruoyi.vip |
|||
|
|||
## 演示图 |
|||
|
|||
<table> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-42e518aa72a24d228427a1261cb3679f395.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-7f20dd0edba25e5187c5c4dd3ec7d3d9797.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-2dae3d87f6a8ca05057db059cd9a411d51d.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-ea4d98423471e55fba784694e45d12bd4bb.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-7f6c6e9f5873efca09bd2870ee8468b8fce.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-c708b65f2c382a03f69fe1efa8d341e6cff.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-9ab586c47dd5c7b92bca0d727962c90e3b8.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-ef954122a2080e02013112db21754b955c6.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-088edb4d531e122415a1e2342bccb1a9691.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-f886fe19bd820c0efae82f680223cac196c.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-c7a2eb71fa65d6e660294b4bccca613d638.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-e60137fb0787defe613bd83331dc4755a70.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-7c51c1b5758f0a0f92ed3c60469b7526f9f.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-15181aed45bb2461aa97b594cbf2f86ea5f.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-83326ad52ea63f67233d126226738054d98.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-3bd6d31e913b70df00107db51d64ef81df7.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-70a2225836bc82042a6785edf6299e2586a.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-0184d6ab01fdc6667a14327fcaf8b46345d.png"/></td> |
|||
</tr> |
|||
<tr> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-64d8086dc2c02c8f71170290482f7640098.png"/></td> |
|||
<td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td> |
|||
</tr> |
|||
</table> |
|||
|
|||
|
|||
## 若依交流群 |
|||
|
|||
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) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) [](https://jq.qq.com/?_wv=1027&k=58cPoHA) [](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [](https://jq.qq.com/?_wv=1027&k=5yugASz) [](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [](https://jq.qq.com/?_wv=1027&k=5omzbKc) [](https://jq.qq.com/?_wv=1027&k=qPIKBb7s) [](https://jq.qq.com/?_wv=1027&k=4NsjKbtU) [](https://jq.qq.com/?_wv=1027&k=VD2pkz2G) [](https://jq.qq.com/?_wv=1027&k=HlshFwkJ) [](https://jq.qq.com/?_wv=1027&k=0ARRrO9V) [](https://jq.qq.com/?_wv=1027&k=up9k3ZXJ) [](https://jq.qq.com/?_wv=1027&k=540WfdEr) [](https://jq.qq.com/?_wv=1027&k=ss91fC4t) [](https://jq.qq.com/?_wv=1027&k=Cqd66IKe) [](https://jq.qq.com/?_wv=1027&k=7FplYUnR) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=lqMHu_5Fskm7H2S1vNAQTtzAUokVydwc&authKey=ptw0Fpch5pbNocML3CIJKKqZBaq2DI7cusKuzIgfMNiY3t9Pvd9hP%2BA8WYx3yaY1&noverify=0&group_code=174942938) [](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=blYlRDmwZXSXI5pVrPPU7ZJ1stFJ6Q2Q&authKey=ForGBWffHVlPt9NE3d7g4DoOIouBh%2BqvAj2lp1CLReHfZAUaK7SRrdwsChKpRJDJ&noverify=0&group_code=287843737) |
@ -0,0 +1,12 @@ |
|||
@echo off |
|||
echo. |
|||
echo [信息] 清理工程target生成路径。 |
|||
echo. |
|||
|
|||
%~d0 |
|||
cd %~dp0 |
|||
|
|||
cd .. |
|||
call mvn clean |
|||
|
|||
pause |
@ -0,0 +1,12 @@ |
|||
@echo off |
|||
echo. |
|||
echo [信息] 打包Web工程,生成war/jar包文件。 |
|||
echo. |
|||
|
|||
%~d0 |
|||
cd %~dp0 |
|||
|
|||
cd .. |
|||
call mvn clean package -Dmaven.test.skip=true |
|||
|
|||
pause |
@ -0,0 +1,14 @@ |
|||
@echo off |
|||
echo. |
|||
echo [信息] 使用Jar命令运行Web工程。 |
|||
echo. |
|||
|
|||
cd %~dp0 |
|||
@cd ../win-admin/target |
|||
set JAVA_HOME=D:\jdk-11 |
|||
set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m |
|||
|
|||
java -jar %JAVA_OPTS% win-admin.jar |
|||
|
|||
cd bin |
|||
pause |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,131 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<!-- <meta name="viewport" content="width=device-width,initial-scale=1.0" />--> |
|||
<title></title> |
|||
<style> |
|||
.box { |
|||
font-size: 14px; |
|||
display: flex; |
|||
margin-top: 0px; |
|||
width: 100vw; |
|||
height: 100vh; |
|||
} |
|||
.left { |
|||
border: 1px solid #b1b1b1; |
|||
border-collapse: collapse; |
|||
flex: 1; |
|||
width: 100% |
|||
} |
|||
.left-item { |
|||
display: flex; |
|||
} |
|||
.bold-font{ |
|||
font-weight: bold; |
|||
font-size: 28px; |
|||
} |
|||
|
|||
.label { |
|||
border-bottom: 1px solid #b1b1b1; |
|||
border-right: 1px solid #b1b1b1; |
|||
width: 60px; |
|||
padding: 0px 5px; |
|||
height: 58px; |
|||
line-height: 58px; |
|||
} |
|||
.value { |
|||
border-bottom: 1px solid #b1b1b1; |
|||
border-right: 1px solid #b1b1b1; |
|||
padding: 0px 5px; |
|||
height: 58px; |
|||
flex: 1; |
|||
width: 0px; |
|||
display: flex; |
|||
align-items: center; |
|||
word-break: break-all; |
|||
} |
|||
|
|||
.right { |
|||
width: 300px; |
|||
} |
|||
|
|||
/*.image {*/ |
|||
/* width: calc(170px);*/ |
|||
/* height: 176px;*/ |
|||
/* border-bottom: 1px solid #b1b1b1;*/ |
|||
/* border-top: 1px solid #b1b1b1;*/ |
|||
/* border-right: 1px solid #b1b1b1;*/ |
|||
/*}*/ |
|||
|
|||
.image { |
|||
width: 172px; |
|||
height: 172px; |
|||
border: 1px solid #b1b1b1; |
|||
/* width: calc(100% - 4px); |
|||
height: calc(100% - 4px); */ |
|||
padding: 2px; |
|||
} |
|||
|
|||
@page { |
|||
margin:10pt 25pt 0pt 25pt; |
|||
@bottom-right { |
|||
content: "Page " counter(page) " of " counter(pages); |
|||
} |
|||
|
|||
} |
|||
@media only screen{ |
|||
p{ |
|||
font-size: 24pt; |
|||
} |
|||
h1{ |
|||
font-size: 36pt; |
|||
} |
|||
h2{ |
|||
font-size:28pt |
|||
} |
|||
} |
|||
</style> |
|||
</head> |
|||
<body > |
|||
<div class="box" style="page-break-before:always;"> |
|||
<table class="left" > |
|||
<tr style="height: 40vh"> |
|||
<td class="label">物品代码</td> |
|||
<td class="value bold-font" id="name1">${itemCode}</td> |
|||
<td colspan="2" style="text-align:center"><img class="image" th:src="${imageSrc}" /></td> |
|||
</tr> |
|||
<tr style="height: 12vh"> |
|||
<td class="label">物品名称</td> |
|||
<td class="value" id="name2">${itemName}</td> |
|||
<td class="label">批次</td> |
|||
<td class="value">${batchCode}</td> |
|||
</tr> |
|||
<tr style="height: 12vh"> |
|||
<td class="label">包装名称</td> |
|||
<td class="value">${uomName}</td> |
|||
<td class="label">物料类型</td> |
|||
<td class="value">${itemType}</td> |
|||
</tr> |
|||
<tr style="height: 12vh"> |
|||
<td class="label">包装号</td> |
|||
<td class="value">${uomCode}</td> |
|||
<td class="label">供应商</td> |
|||
<td class="value">${supplierCode}</td> |
|||
</tr> |
|||
<tr style="height: 12vh"> |
|||
<td class="label">父包装号</td> |
|||
<td class="value">${puomCode}</td> |
|||
<td class="label">打印时间</td> |
|||
<td class="value">${printDate}</td> |
|||
</tr> |
|||
<tr style="height: 12vh"> |
|||
<td class="label">ASN</td> |
|||
<td class="value">${asnCode}</td> |
|||
<td class="label">数量</td> |
|||
<td class="value">${counts}</td> |
|||
</tr> |
|||
</table> |
|||
|
|||
</div> |
|||
</body> |
|||
</html> |
@ -0,0 +1,329 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
|
|||
<groupId>com.win</groupId> |
|||
<artifactId>win</artifactId> |
|||
<version>4.7.9</version> |
|||
|
|||
<name>win</name> |
|||
<url>http://www.ruoyi.vip</url> |
|||
<description>闻荫打印服务系统</description> |
|||
|
|||
<properties> |
|||
<win.version>4.7.9</win.version> |
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
|||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
|||
<java.version>17</java.version> |
|||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> |
|||
<shiro.version>2.0.1</shiro.version> |
|||
<mybatis-spring-boot.version>3.0.3</mybatis-spring-boot.version> |
|||
<thymeleaf.extras.shiro.version>2.1.0</thymeleaf.extras.shiro.version> |
|||
<druid.version>1.2.23</druid.version> |
|||
<bitwalker.version>1.21</bitwalker.version> |
|||
<kaptcha.version>2.3.3</kaptcha.version> |
|||
<pagehelper.boot.version>2.1.0</pagehelper.boot.version> |
|||
<fastjson.version>1.2.83</fastjson.version> |
|||
<oshi.version>6.6.1</oshi.version> |
|||
<commons.io.version>2.16.1</commons.io.version> |
|||
<poi.version>4.1.2</poi.version> |
|||
<velocity.version>2.3</velocity.version> |
|||
<springdoc.version>2.5.0</springdoc.version> |
|||
</properties> |
|||
|
|||
<!-- 依赖声明 --> |
|||
<dependencyManagement> |
|||
<dependencies> |
|||
|
|||
<!-- SpringBoot的依赖配置--> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-dependencies</artifactId> |
|||
<version>3.3.0</version> |
|||
<type>pom</type> |
|||
<scope>import</scope> |
|||
</dependency> |
|||
|
|||
<!-- 阿里数据库连接池 --> |
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>druid-spring-boot-3-starter</artifactId> |
|||
<version>${druid.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 验证码 --> |
|||
<dependency> |
|||
<groupId>pro.fessional</groupId> |
|||
<artifactId>kaptcha</artifactId> |
|||
<version>${kaptcha.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- Shiro核心框架 --> |
|||
<dependency> |
|||
<groupId>org.apache.shiro</groupId> |
|||
<artifactId>shiro-core</artifactId> |
|||
<classifier>jakarta</classifier> |
|||
<version>${shiro.version}</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>org.apache.shiro</groupId> |
|||
<artifactId>shiro-web</artifactId> |
|||
<classifier>jakarta</classifier> |
|||
<version>${shiro.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- Shiro使用Spring框架 --> |
|||
<dependency> |
|||
<groupId>org.apache.shiro</groupId> |
|||
<artifactId>shiro-spring</artifactId> |
|||
<classifier>jakarta</classifier> |
|||
<version>${shiro.version}</version> |
|||
<!-- 排除仍使用了javax.servlet的依赖 --> |
|||
<exclusions> |
|||
<exclusion> |
|||
<groupId>org.apache.shiro</groupId> |
|||
<artifactId>shiro-web</artifactId> |
|||
</exclusion> |
|||
</exclusions> |
|||
</dependency> |
|||
|
|||
<!-- Shiro使用EhCache缓存框架 --> |
|||
<dependency> |
|||
<groupId>org.apache.shiro</groupId> |
|||
<artifactId>shiro-ehcache</artifactId> |
|||
<version>${shiro.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- thymeleaf模板引擎和shiro框架的整合 --> |
|||
<dependency> |
|||
<groupId>com.github.theborakompanioni</groupId> |
|||
<artifactId>thymeleaf-extras-shiro</artifactId> |
|||
<version>${thymeleaf.extras.shiro.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- mybatis依赖 --> |
|||
<dependency> |
|||
<groupId>org.mybatis.spring.boot</groupId> |
|||
<artifactId>mybatis-spring-boot-starter</artifactId> |
|||
<version>${mybatis-spring-boot.version}</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>com.mysql</groupId> |
|||
<artifactId>mysql-connector-j</artifactId> |
|||
<version>8.1.0</version> |
|||
</dependency> |
|||
|
|||
<dependency> |
|||
<groupId>jakarta.servlet</groupId> |
|||
<artifactId>jakarta.servlet-api</artifactId> |
|||
<version>6.0.0</version> |
|||
</dependency> |
|||
|
|||
<!-- 解析客户端操作系统、浏览器等 --> |
|||
<dependency> |
|||
<groupId>eu.bitwalker</groupId> |
|||
<artifactId>UserAgentUtils</artifactId> |
|||
<version>${bitwalker.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- pagehelper 分页插件 --> |
|||
<dependency> |
|||
<groupId>com.github.pagehelper</groupId> |
|||
<artifactId>pagehelper-spring-boot-starter</artifactId> |
|||
<version>${pagehelper.boot.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 获取系统信息 --> |
|||
<dependency> |
|||
<groupId>com.github.oshi</groupId> |
|||
<artifactId>oshi-core</artifactId> |
|||
<version>${oshi.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- spring-doc --> |
|||
<dependency> |
|||
<groupId>org.springdoc</groupId> |
|||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> |
|||
<version>${springdoc.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- io常用工具类 --> |
|||
<dependency> |
|||
<groupId>commons-io</groupId> |
|||
<artifactId>commons-io</artifactId> |
|||
<version>${commons.io.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- excel工具 --> |
|||
<dependency> |
|||
<groupId>org.apache.poi</groupId> |
|||
<artifactId>poi-ooxml</artifactId> |
|||
<version>${poi.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- velocity代码生成使用模板 --> |
|||
<dependency> |
|||
<groupId>org.apache.velocity</groupId> |
|||
<artifactId>velocity-engine-core</artifactId> |
|||
<version>${velocity.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 阿里JSON解析器 --> |
|||
<dependency> |
|||
<groupId>com.alibaba</groupId> |
|||
<artifactId>fastjson</artifactId> |
|||
<version>${fastjson.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 定时任务--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-quartz</artifactId> |
|||
<version>${win.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 代码生成--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-generator</artifactId> |
|||
<version>${win.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 核心模块--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-framework</artifactId> |
|||
<version>${win.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 系统模块--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-system</artifactId> |
|||
<version>${win.version}</version> |
|||
</dependency> |
|||
|
|||
<!-- 通用工具--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-common</artifactId> |
|||
<version>${win.version}</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-print</artifactId> |
|||
<version>${win.version}</version> |
|||
</dependency> |
|||
<!-- 糊涂工具--> |
|||
<dependency> |
|||
<groupId>cn.hutool</groupId> |
|||
<artifactId>hutool-all</artifactId> |
|||
<version>5.8.16</version> |
|||
</dependency> |
|||
<!--pdf工具 --> |
|||
<!-- https://mvnrepository.com/artifact/com.itextpdf/html2pdf --> |
|||
<dependency> |
|||
<groupId>com.itextpdf</groupId> |
|||
<artifactId>html2pdf</artifactId> |
|||
<version>2.1.5</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.itextpdf</groupId> |
|||
<artifactId>itext7-core</artifactId> |
|||
<version>7.1.8</version> |
|||
<type>pom</type> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>org.xhtmlrenderer</groupId> |
|||
<artifactId>flying-saucer-pdf</artifactId> |
|||
<version>9.8.0</version> |
|||
</dependency> |
|||
<!--二维码工具 --> |
|||
<!-- https://mvnrepository.com/artifact/com.google.zxing/core --> |
|||
<dependency> |
|||
<groupId>com.google.zxing</groupId> |
|||
<artifactId>core</artifactId> |
|||
<version>3.5.3</version> |
|||
</dependency> |
|||
<dependency> |
|||
<groupId>com.google.zxing</groupId> |
|||
<artifactId>javase</artifactId> |
|||
<version>3.5.3</version> |
|||
</dependency> |
|||
<!--ureport --> |
|||
|
|||
|
|||
</dependencies> |
|||
|
|||
</dependencyManagement> |
|||
|
|||
<modules> |
|||
<module>win-admin</module> |
|||
<module>win-framework</module> |
|||
<module>win-system</module> |
|||
<module>win-quartz</module> |
|||
<module>win-generator</module> |
|||
<module>win-common</module> |
|||
<module>win-print</module> |
|||
</modules> |
|||
<packaging>pom</packaging> |
|||
|
|||
<build> |
|||
<plugins> |
|||
<plugin> |
|||
<groupId>org.apache.maven.plugins</groupId> |
|||
<artifactId>maven-compiler-plugin</artifactId> |
|||
<version>3.13.0</version> |
|||
<configuration> |
|||
<parameters>true</parameters> |
|||
<source>${java.version}</source> |
|||
<target>${java.version}</target> |
|||
<encoding>${project.build.sourceEncoding}</encoding> |
|||
</configuration> |
|||
</plugin> |
|||
<plugin> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-maven-plugin</artifactId> |
|||
<version>3.3.0</version> |
|||
</plugin> |
|||
</plugins> |
|||
</build> |
|||
|
|||
<repositories> |
|||
<repository> |
|||
<id>public</id> |
|||
<name>aliyun nexus</name> |
|||
<url>https://maven.aliyun.com/repository/public</url> |
|||
<releases> |
|||
<enabled>true</enabled> |
|||
</releases> |
|||
</repository> |
|||
<repository> |
|||
<id>central</id> |
|||
<name>aliyun central</name> |
|||
<url>https://maven.aliyun.com/repository/central</url> |
|||
<releases> |
|||
<enabled>true</enabled> |
|||
</releases> |
|||
</repository> |
|||
</repositories> |
|||
|
|||
<pluginRepositories> |
|||
<pluginRepository> |
|||
<id>public</id> |
|||
<name>aliyun nexus</name> |
|||
<url>https://maven.aliyun.com/repository/public</url> |
|||
<releases> |
|||
<enabled>true</enabled> |
|||
</releases> |
|||
<snapshots> |
|||
<enabled>false</enabled> |
|||
</snapshots> |
|||
</pluginRepository> |
|||
|
|||
</pluginRepositories> |
|||
|
|||
</project> |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,67 @@ |
|||
@echo off |
|||
|
|||
rem jar平级目录 |
|||
set AppName=win-admin.jar |
|||
|
|||
rem JVM参数 |
|||
set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" |
|||
|
|||
|
|||
ECHO. |
|||
ECHO. [1] 启动%AppName% |
|||
ECHO. [2] 关闭%AppName% |
|||
ECHO. [3] 重启%AppName% |
|||
ECHO. [4] 启动状态 %AppName% |
|||
ECHO. [5] 退 出 |
|||
ECHO. |
|||
|
|||
ECHO.请输入选择项目的序号: |
|||
set /p ID= |
|||
IF "%id%"=="1" GOTO start |
|||
IF "%id%"=="2" GOTO stop |
|||
IF "%id%"=="3" GOTO restart |
|||
IF "%id%"=="4" GOTO status |
|||
IF "%id%"=="5" EXIT |
|||
PAUSE |
|||
:start |
|||
for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( |
|||
set pid=%%a |
|||
set image_name=%%b |
|||
) |
|||
if defined pid ( |
|||
echo %%is running |
|||
PAUSE |
|||
) |
|||
|
|||
start javaw %JVM_OPTS% -jar %AppName% |
|||
|
|||
echo starting…… |
|||
echo Start %AppName% success... |
|||
goto:eof |
|||
|
|||
rem 函数stop通过jps命令查找pid并结束进程 |
|||
:stop |
|||
for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( |
|||
set pid=%%a |
|||
set image_name=%%b |
|||
) |
|||
if not defined pid (echo process %AppName% does not exists) else ( |
|||
echo prepare to kill %image_name% |
|||
echo start kill %pid% ... |
|||
rem 根据进程ID,kill进程 |
|||
taskkill /f /pid %pid% |
|||
) |
|||
goto:eof |
|||
:restart |
|||
call :stop |
|||
call :start |
|||
goto:eof |
|||
:status |
|||
for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do ( |
|||
set pid=%%a |
|||
set image_name=%%b |
|||
) |
|||
if not defined pid (echo process %AppName% is dead ) else ( |
|||
echo %image_name% is running |
|||
) |
|||
goto:eof |
@ -0,0 +1,86 @@ |
|||
#!/bin/sh |
|||
# ./ry.sh start 启动 stop 停止 restart 重启 status 状态 |
|||
AppName=win-admin.jar |
|||
|
|||
# JVM参数 |
|||
JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC" |
|||
APP_HOME=`pwd` |
|||
LOG_PATH=$APP_HOME/logs/$AppName.log |
|||
|
|||
if [ "$1" = "" ]; |
|||
then |
|||
echo -e "\033[0;31m 未输入操作名 \033[0m \033[0;34m {start|stop|restart|status} \033[0m" |
|||
exit 1 |
|||
fi |
|||
|
|||
if [ "$AppName" = "" ]; |
|||
then |
|||
echo -e "\033[0;31m 未输入应用名 \033[0m" |
|||
exit 1 |
|||
fi |
|||
|
|||
function start() |
|||
{ |
|||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` |
|||
|
|||
if [ x"$PID" != x"" ]; then |
|||
echo "$AppName is running..." |
|||
else |
|||
nohup java $JVM_OPTS -jar $AppName > /dev/null 2>&1 & |
|||
echo "Start $AppName success..." |
|||
fi |
|||
} |
|||
|
|||
function stop() |
|||
{ |
|||
echo "Stop $AppName" |
|||
|
|||
PID="" |
|||
query(){ |
|||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'` |
|||
} |
|||
|
|||
query |
|||
if [ x"$PID" != x"" ]; then |
|||
kill -TERM $PID |
|||
echo "$AppName (pid:$PID) exiting..." |
|||
while [ x"$PID" != x"" ] |
|||
do |
|||
sleep 1 |
|||
query |
|||
done |
|||
echo "$AppName exited." |
|||
else |
|||
echo "$AppName already stopped." |
|||
fi |
|||
} |
|||
|
|||
function restart() |
|||
{ |
|||
stop |
|||
sleep 2 |
|||
start |
|||
} |
|||
|
|||
function status() |
|||
{ |
|||
PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l` |
|||
if [ $PID != 0 ];then |
|||
echo "$AppName is running..." |
|||
else |
|||
echo "$AppName is not running..." |
|||
fi |
|||
} |
|||
|
|||
case $1 in |
|||
start) |
|||
start;; |
|||
stop) |
|||
stop;; |
|||
restart) |
|||
restart;; |
|||
status) |
|||
status;; |
|||
*) |
|||
|
|||
esac |
@ -0,0 +1,174 @@ |
|||
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; |
|||
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; |
|||
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; |
|||
DROP TABLE IF EXISTS QRTZ_LOCKS; |
|||
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; |
|||
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS; |
|||
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; |
|||
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; |
|||
DROP TABLE IF EXISTS QRTZ_TRIGGERS; |
|||
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; |
|||
DROP TABLE IF EXISTS QRTZ_CALENDARS; |
|||
|
|||
-- ---------------------------- |
|||
-- 1、存储每一个已配置的 jobDetail 的详细信息 |
|||
-- ---------------------------- |
|||
create table QRTZ_JOB_DETAILS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
job_name varchar(200) not null comment '任务名称', |
|||
job_group varchar(200) not null comment '任务组名', |
|||
description varchar(250) null comment '相关介绍', |
|||
job_class_name varchar(250) not null comment '执行任务类名称', |
|||
is_durable varchar(1) not null comment '是否持久化', |
|||
is_nonconcurrent varchar(1) not null comment '是否并发', |
|||
is_update_data varchar(1) not null comment '是否更新数据', |
|||
requests_recovery varchar(1) not null comment '是否接受恢复执行', |
|||
job_data blob null comment '存放持久化job对象', |
|||
primary key (sched_name, job_name, job_group) |
|||
) engine=innodb comment = '任务详细信息表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 2、 存储已配置的 Trigger 的信息 |
|||
-- ---------------------------- |
|||
create table QRTZ_TRIGGERS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
trigger_name varchar(200) not null comment '触发器的名字', |
|||
trigger_group varchar(200) not null comment '触发器所属组的名字', |
|||
job_name varchar(200) not null comment 'qrtz_job_details表job_name的外键', |
|||
job_group varchar(200) not null comment 'qrtz_job_details表job_group的外键', |
|||
description varchar(250) null comment '相关介绍', |
|||
next_fire_time bigint(13) null comment '上一次触发时间(毫秒)', |
|||
prev_fire_time bigint(13) null comment '下一次触发时间(默认为-1表示不触发)', |
|||
priority integer null comment '优先级', |
|||
trigger_state varchar(16) not null comment '触发器状态', |
|||
trigger_type varchar(8) not null comment '触发器的类型', |
|||
start_time bigint(13) not null comment '开始时间', |
|||
end_time bigint(13) null comment '结束时间', |
|||
calendar_name varchar(200) null comment '日程表名称', |
|||
misfire_instr smallint(2) null comment '补偿执行的策略', |
|||
job_data blob null comment '存放持久化job对象', |
|||
primary key (sched_name, trigger_name, trigger_group), |
|||
foreign key (sched_name, job_name, job_group) references QRTZ_JOB_DETAILS(sched_name, job_name, job_group) |
|||
) engine=innodb comment = '触发器详细信息表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 3、 存储简单的 Trigger,包括重复次数,间隔,以及已触发的次数 |
|||
-- ---------------------------- |
|||
create table QRTZ_SIMPLE_TRIGGERS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', |
|||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', |
|||
repeat_count bigint(7) not null comment '重复的次数统计', |
|||
repeat_interval bigint(12) not null comment '重复的间隔时间', |
|||
times_triggered bigint(10) not null comment '已经触发的次数', |
|||
primary key (sched_name, trigger_name, trigger_group), |
|||
foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) |
|||
) engine=innodb comment = '简单触发器的信息表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 4、 存储 Cron Trigger,包括 Cron 表达式和时区信息 |
|||
-- ---------------------------- |
|||
create table QRTZ_CRON_TRIGGERS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', |
|||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', |
|||
cron_expression varchar(200) not null comment 'cron表达式', |
|||
time_zone_id varchar(80) comment '时区', |
|||
primary key (sched_name, trigger_name, trigger_group), |
|||
foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) |
|||
) engine=innodb comment = 'Cron类型的触发器表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 5、 Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型,JobStore 并不知道如何存储实例的时候) |
|||
-- ---------------------------- |
|||
create table QRTZ_BLOB_TRIGGERS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', |
|||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', |
|||
blob_data blob null comment '存放持久化Trigger对象', |
|||
primary key (sched_name, trigger_name, trigger_group), |
|||
foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) |
|||
) engine=innodb comment = 'Blob类型的触发器表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 6、 以 Blob 类型存储存放日历信息, quartz可配置一个日历来指定一个时间范围 |
|||
-- ---------------------------- |
|||
create table QRTZ_CALENDARS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
calendar_name varchar(200) not null comment '日历名称', |
|||
calendar blob not null comment '存放持久化calendar对象', |
|||
primary key (sched_name, calendar_name) |
|||
) engine=innodb comment = '日历信息表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 7、 存储已暂停的 Trigger 组的信息 |
|||
-- ---------------------------- |
|||
create table QRTZ_PAUSED_TRIGGER_GRPS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', |
|||
primary key (sched_name, trigger_group) |
|||
) engine=innodb comment = '暂停的触发器表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 8、 存储与已触发的 Trigger 相关的状态信息,以及相联 Job 的执行信息 |
|||
-- ---------------------------- |
|||
create table QRTZ_FIRED_TRIGGERS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
entry_id varchar(95) not null comment '调度器实例id', |
|||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', |
|||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', |
|||
instance_name varchar(200) not null comment '调度器实例名', |
|||
fired_time bigint(13) not null comment '触发的时间', |
|||
sched_time bigint(13) not null comment '定时器制定的时间', |
|||
priority integer not null comment '优先级', |
|||
state varchar(16) not null comment '状态', |
|||
job_name varchar(200) null comment '任务名称', |
|||
job_group varchar(200) null comment '任务组名', |
|||
is_nonconcurrent varchar(1) null comment '是否并发', |
|||
requests_recovery varchar(1) null comment '是否接受恢复执行', |
|||
primary key (sched_name, entry_id) |
|||
) engine=innodb comment = '已触发的触发器表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 9、 存储少量的有关 Scheduler 的状态信息,假如是用于集群中,可以看到其他的 Scheduler 实例 |
|||
-- ---------------------------- |
|||
create table QRTZ_SCHEDULER_STATE ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
instance_name varchar(200) not null comment '实例名称', |
|||
last_checkin_time bigint(13) not null comment '上次检查时间', |
|||
checkin_interval bigint(13) not null comment '检查间隔时间', |
|||
primary key (sched_name, instance_name) |
|||
) engine=innodb comment = '调度器状态表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 10、 存储程序的悲观锁的信息(假如使用了悲观锁) |
|||
-- ---------------------------- |
|||
create table QRTZ_LOCKS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
lock_name varchar(40) not null comment '悲观锁名称', |
|||
primary key (sched_name, lock_name) |
|||
) engine=innodb comment = '存储的悲观锁信息表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 11、 Quartz集群实现同步机制的行锁表 |
|||
-- ---------------------------- |
|||
create table QRTZ_SIMPROP_TRIGGERS ( |
|||
sched_name varchar(120) not null comment '调度名称', |
|||
trigger_name varchar(200) not null comment 'qrtz_triggers表trigger_name的外键', |
|||
trigger_group varchar(200) not null comment 'qrtz_triggers表trigger_group的外键', |
|||
str_prop_1 varchar(512) null comment 'String类型的trigger的第一个参数', |
|||
str_prop_2 varchar(512) null comment 'String类型的trigger的第二个参数', |
|||
str_prop_3 varchar(512) null comment 'String类型的trigger的第三个参数', |
|||
int_prop_1 int null comment 'int类型的trigger的第一个参数', |
|||
int_prop_2 int null comment 'int类型的trigger的第二个参数', |
|||
long_prop_1 bigint null comment 'long类型的trigger的第一个参数', |
|||
long_prop_2 bigint null comment 'long类型的trigger的第二个参数', |
|||
dec_prop_1 numeric(13,4) null comment 'decimal类型的trigger的第一个参数', |
|||
dec_prop_2 numeric(13,4) null comment 'decimal类型的trigger的第二个参数', |
|||
bool_prop_1 varchar(1) null comment 'Boolean类型的trigger的第一个参数', |
|||
bool_prop_2 varchar(1) null comment 'Boolean类型的trigger的第二个参数', |
|||
primary key (sched_name, trigger_name, trigger_group), |
|||
foreign key (sched_name, trigger_name, trigger_group) references QRTZ_TRIGGERS(sched_name, trigger_name, trigger_group) |
|||
) engine=innodb comment = '同步机制的行锁表'; |
|||
|
|||
commit; |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,722 @@ |
|||
-- ---------------------------- |
|||
-- 1、部门表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_dept; |
|||
create table sys_dept ( |
|||
dept_id bigint(20) not null auto_increment comment '部门id', |
|||
parent_id bigint(20) default 0 comment '父部门id', |
|||
ancestors varchar(50) default '' comment '祖级列表', |
|||
dept_name varchar(30) default '' comment '部门名称', |
|||
order_num int(4) default 0 comment '显示顺序', |
|||
leader varchar(20) default null comment '负责人', |
|||
phone varchar(11) default null comment '联系电话', |
|||
email varchar(50) default null comment '邮箱', |
|||
status char(1) default '0' comment '部门状态(0正常 1停用)', |
|||
del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
primary key (dept_id) |
|||
) engine=innodb auto_increment=200 comment = '部门表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-部门表数据 |
|||
-- ---------------------------- |
|||
insert into sys_dept values(100, 0, '0', '若依科技', 0, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(101, 100, '0,100', '深圳总公司', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(102, 100, '0,100', '长沙分公司', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(103, 101, '0,100,101', '研发部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(104, 101, '0,100,101', '市场部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(105, 101, '0,100,101', '测试部门', 3, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(106, 101, '0,100,101', '财务部门', 4, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(107, 101, '0,100,101', '运维部门', 5, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(108, 102, '0,100,102', '市场部门', 1, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
insert into sys_dept values(109, 102, '0,100,102', '财务部门', 2, '若依', '15888888888', 'ry@qq.com', '0', '0', 'admin', sysdate(), '', null); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 2、用户信息表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_user; |
|||
create table sys_user ( |
|||
user_id bigint(20) not null auto_increment comment '用户ID', |
|||
dept_id bigint(20) default null comment '部门ID', |
|||
login_name varchar(30) not null comment '登录账号', |
|||
user_name varchar(30) default '' comment '用户昵称', |
|||
user_type varchar(2) default '00' comment '用户类型(00系统用户 01注册用户)', |
|||
email varchar(50) default '' comment '用户邮箱', |
|||
phonenumber varchar(11) default '' comment '手机号码', |
|||
sex char(1) default '0' comment '用户性别(0男 1女 2未知)', |
|||
avatar varchar(100) default '' comment '头像路径', |
|||
password varchar(50) default '' comment '密码', |
|||
salt varchar(20) default '' comment '盐加密', |
|||
status char(1) default '0' comment '帐号状态(0正常 1停用)', |
|||
del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', |
|||
login_ip varchar(128) default '' comment '最后登录IP', |
|||
login_date datetime comment '最后登录时间', |
|||
pwd_update_date datetime comment '密码最后更新时间', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default null comment '备注', |
|||
primary key (user_id) |
|||
) engine=innodb auto_increment=100 comment = '用户信息表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-用户信息表数据 |
|||
-- ---------------------------- |
|||
insert into sys_user values(1, 103, 'admin', '若依', '00', 'ry@163.com', '15888888888', '1', '', '29c67a30398638269fe600f73a054934', '111111', '0', '0', '127.0.0.1', null, null, 'admin', sysdate(), '', null, '管理员'); |
|||
insert into sys_user values(2, 105, 'ry', '若依', '00', 'ry@qq.com', '15666666666', '1', '', '8e6d98b90472783cc73c17047ddccf36', '222222', '0', '0', '127.0.0.1', null, null, 'admin', sysdate(), '', null, '测试员'); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 3、岗位信息表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_post; |
|||
create table sys_post |
|||
( |
|||
post_id bigint(20) not null auto_increment comment '岗位ID', |
|||
post_code varchar(64) not null comment '岗位编码', |
|||
post_name varchar(50) not null comment '岗位名称', |
|||
post_sort int(4) not null comment '显示顺序', |
|||
status char(1) not null comment '状态(0正常 1停用)', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default null comment '备注', |
|||
primary key (post_id) |
|||
) engine=innodb comment = '岗位信息表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-岗位信息表数据 |
|||
-- ---------------------------- |
|||
insert into sys_post values(1, 'ceo', '董事长', 1, '0', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_post values(2, 'se', '项目经理', 2, '0', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_post values(3, 'hr', '人力资源', 3, '0', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_post values(4, 'user', '普通员工', 4, '0', 'admin', sysdate(), '', null, ''); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 4、角色信息表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_role; |
|||
create table sys_role ( |
|||
role_id bigint(20) not null auto_increment comment '角色ID', |
|||
role_name varchar(30) not null comment '角色名称', |
|||
role_key varchar(100) not null comment '角色权限字符串', |
|||
role_sort int(4) not null comment '显示顺序', |
|||
data_scope char(1) default '1' comment '数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', |
|||
status char(1) not null comment '角色状态(0正常 1停用)', |
|||
del_flag char(1) default '0' comment '删除标志(0代表存在 2代表删除)', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default null comment '备注', |
|||
primary key (role_id) |
|||
) engine=innodb auto_increment=100 comment = '角色信息表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-角色信息表数据 |
|||
-- ---------------------------- |
|||
insert into sys_role values('1', '超级管理员', 'admin', 1, 1, '0', '0', 'admin', sysdate(), '', null, '超级管理员'); |
|||
insert into sys_role values('2', '普通角色', 'common', 2, 2, '0', '0', 'admin', sysdate(), '', null, '普通角色'); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 5、菜单权限表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_menu; |
|||
create table sys_menu ( |
|||
menu_id bigint(20) not null auto_increment comment '菜单ID', |
|||
menu_name varchar(50) not null comment '菜单名称', |
|||
parent_id bigint(20) default 0 comment '父菜单ID', |
|||
order_num int(4) default 0 comment '显示顺序', |
|||
url varchar(200) default '#' comment '请求地址', |
|||
target varchar(20) default '' comment '打开方式(menuItem页签 menuBlank新窗口)', |
|||
menu_type char(1) default '' comment '菜单类型(M目录 C菜单 F按钮)', |
|||
visible char(1) default 0 comment '菜单状态(0显示 1隐藏)', |
|||
is_refresh char(1) default 1 comment '是否刷新(0刷新 1不刷新)', |
|||
perms varchar(100) default null comment '权限标识', |
|||
icon varchar(100) default '#' comment '菜单图标', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default '' comment '备注', |
|||
primary key (menu_id) |
|||
) engine=innodb auto_increment=2000 comment = '菜单权限表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-菜单信息表数据 |
|||
-- ---------------------------- |
|||
-- 一级菜单 |
|||
insert into sys_menu values('1', '系统管理', '0', '1', '#', '', 'M', '0', '1', '', 'fa fa-gear', 'admin', sysdate(), '', null, '系统管理目录'); |
|||
insert into sys_menu values('2', '系统监控', '0', '2', '#', '', 'M', '0', '1', '', 'fa fa-video-camera', 'admin', sysdate(), '', null, '系统监控目录'); |
|||
insert into sys_menu values('3', '系统工具', '0', '3', '#', '', 'M', '0', '1', '', 'fa fa-bars', 'admin', sysdate(), '', null, '系统工具目录'); |
|||
insert into sys_menu values('4', '若依官网', '0', '4', 'http://ruoyi.vip', 'menuBlank', 'C', '0', '1', '', 'fa fa-location-arrow', 'admin', sysdate(), '', null, '若依官网地址'); |
|||
-- 二级菜单 |
|||
insert into sys_menu values('100', '用户管理', '1', '1', '/system/user', '', 'C', '0', '1', 'system:user:view', 'fa fa-user-o', 'admin', sysdate(), '', null, '用户管理菜单'); |
|||
insert into sys_menu values('101', '角色管理', '1', '2', '/system/role', '', 'C', '0', '1', 'system:role:view', 'fa fa-user-secret', 'admin', sysdate(), '', null, '角色管理菜单'); |
|||
insert into sys_menu values('102', '菜单管理', '1', '3', '/system/menu', '', 'C', '0', '1', 'system:menu:view', 'fa fa-th-list', 'admin', sysdate(), '', null, '菜单管理菜单'); |
|||
insert into sys_menu values('103', '部门管理', '1', '4', '/system/dept', '', 'C', '0', '1', 'system:dept:view', 'fa fa-outdent', 'admin', sysdate(), '', null, '部门管理菜单'); |
|||
insert into sys_menu values('104', '岗位管理', '1', '5', '/system/post', '', 'C', '0', '1', 'system:post:view', 'fa fa-address-card-o', 'admin', sysdate(), '', null, '岗位管理菜单'); |
|||
insert into sys_menu values('105', '字典管理', '1', '6', '/system/dict', '', 'C', '0', '1', 'system:dict:view', 'fa fa-bookmark-o', 'admin', sysdate(), '', null, '字典管理菜单'); |
|||
insert into sys_menu values('106', '参数设置', '1', '7', '/system/config', '', 'C', '0', '1', 'system:config:view', 'fa fa-sun-o', 'admin', sysdate(), '', null, '参数设置菜单'); |
|||
insert into sys_menu values('107', '通知公告', '1', '8', '/system/notice', '', 'C', '0', '1', 'system:notice:view', 'fa fa-bullhorn', 'admin', sysdate(), '', null, '通知公告菜单'); |
|||
insert into sys_menu values('108', '日志管理', '1', '9', '#', '', 'M', '0', '1', '', 'fa fa-pencil-square-o', 'admin', sysdate(), '', null, '日志管理菜单'); |
|||
insert into sys_menu values('109', '在线用户', '2', '1', '/monitor/online', '', 'C', '0', '1', 'monitor:online:view', 'fa fa-user-circle', 'admin', sysdate(), '', null, '在线用户菜单'); |
|||
insert into sys_menu values('110', '定时任务', '2', '2', '/monitor/job', '', 'C', '0', '1', 'monitor:job:view', 'fa fa-tasks', 'admin', sysdate(), '', null, '定时任务菜单'); |
|||
insert into sys_menu values('111', '数据监控', '2', '3', '/monitor/data', '', 'C', '0', '1', 'monitor:data:view', 'fa fa-bug', 'admin', sysdate(), '', null, '数据监控菜单'); |
|||
insert into sys_menu values('112', '服务监控', '2', '4', '/monitor/server', '', 'C', '0', '1', 'monitor:server:view', 'fa fa-server', 'admin', sysdate(), '', null, '服务监控菜单'); |
|||
insert into sys_menu values('113', '缓存监控', '2', '5', '/monitor/cache', '', 'C', '0', '1', 'monitor:cache:view', 'fa fa-cube', 'admin', sysdate(), '', null, '缓存监控菜单'); |
|||
insert into sys_menu values('114', '表单构建', '3', '1', '/tool/build', '', 'C', '0', '1', 'tool:build:view', 'fa fa-wpforms', 'admin', sysdate(), '', null, '表单构建菜单'); |
|||
insert into sys_menu values('115', '代码生成', '3', '2', '/tool/gen', '', 'C', '0', '1', 'tool:gen:view', 'fa fa-code', 'admin', sysdate(), '', null, '代码生成菜单'); |
|||
insert into sys_menu values('116', '系统接口', '3', '3', '/tool/swagger', '', 'C', '0', '1', 'tool:swagger:view', 'fa fa-gg', 'admin', sysdate(), '', null, '系统接口菜单'); |
|||
-- 三级菜单 |
|||
insert into sys_menu values('500', '操作日志', '108', '1', '/monitor/operlog', '', 'C', '0', '1', 'monitor:operlog:view', 'fa fa-address-book', 'admin', sysdate(), '', null, '操作日志菜单'); |
|||
insert into sys_menu values('501', '登录日志', '108', '2', '/monitor/logininfor', '', 'C', '0', '1', 'monitor:logininfor:view', 'fa fa-file-image-o', 'admin', sysdate(), '', null, '登录日志菜单'); |
|||
-- 用户管理按钮 |
|||
insert into sys_menu values('1000', '用户查询', '100', '1', '#', '', 'F', '0', '1', 'system:user:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1001', '用户新增', '100', '2', '#', '', 'F', '0', '1', 'system:user:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1002', '用户修改', '100', '3', '#', '', 'F', '0', '1', 'system:user:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1003', '用户删除', '100', '4', '#', '', 'F', '0', '1', 'system:user:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1004', '用户导出', '100', '5', '#', '', 'F', '0', '1', 'system:user:export', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1005', '用户导入', '100', '6', '#', '', 'F', '0', '1', 'system:user:import', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1006', '重置密码', '100', '7', '#', '', 'F', '0', '1', 'system:user:resetPwd', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 角色管理按钮 |
|||
insert into sys_menu values('1007', '角色查询', '101', '1', '#', '', 'F', '0', '1', 'system:role:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1008', '角色新增', '101', '2', '#', '', 'F', '0', '1', 'system:role:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1009', '角色修改', '101', '3', '#', '', 'F', '0', '1', 'system:role:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1010', '角色删除', '101', '4', '#', '', 'F', '0', '1', 'system:role:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1011', '角色导出', '101', '5', '#', '', 'F', '0', '1', 'system:role:export', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 菜单管理按钮 |
|||
insert into sys_menu values('1012', '菜单查询', '102', '1', '#', '', 'F', '0', '1', 'system:menu:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1013', '菜单新增', '102', '2', '#', '', 'F', '0', '1', 'system:menu:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1014', '菜单修改', '102', '3', '#', '', 'F', '0', '1', 'system:menu:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1015', '菜单删除', '102', '4', '#', '', 'F', '0', '1', 'system:menu:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 部门管理按钮 |
|||
insert into sys_menu values('1016', '部门查询', '103', '1', '#', '', 'F', '0', '1', 'system:dept:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1017', '部门新增', '103', '2', '#', '', 'F', '0', '1', 'system:dept:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1018', '部门修改', '103', '3', '#', '', 'F', '0', '1', 'system:dept:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1019', '部门删除', '103', '4', '#', '', 'F', '0', '1', 'system:dept:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 岗位管理按钮 |
|||
insert into sys_menu values('1020', '岗位查询', '104', '1', '#', '', 'F', '0', '1', 'system:post:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1021', '岗位新增', '104', '2', '#', '', 'F', '0', '1', 'system:post:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1022', '岗位修改', '104', '3', '#', '', 'F', '0', '1', 'system:post:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1023', '岗位删除', '104', '4', '#', '', 'F', '0', '1', 'system:post:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1024', '岗位导出', '104', '5', '#', '', 'F', '0', '1', 'system:post:export', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 字典管理按钮 |
|||
insert into sys_menu values('1025', '字典查询', '105', '1', '#', '', 'F', '0', '1', 'system:dict:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1026', '字典新增', '105', '2', '#', '', 'F', '0', '1', 'system:dict:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1027', '字典修改', '105', '3', '#', '', 'F', '0', '1', 'system:dict:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1028', '字典删除', '105', '4', '#', '', 'F', '0', '1', 'system:dict:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1029', '字典导出', '105', '5', '#', '', 'F', '0', '1', 'system:dict:export', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 参数设置按钮 |
|||
insert into sys_menu values('1030', '参数查询', '106', '1', '#', '', 'F', '0', '1', 'system:config:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1031', '参数新增', '106', '2', '#', '', 'F', '0', '1', 'system:config:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1032', '参数修改', '106', '3', '#', '', 'F', '0', '1', 'system:config:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1033', '参数删除', '106', '4', '#', '', 'F', '0', '1', 'system:config:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1034', '参数导出', '106', '5', '#', '', 'F', '0', '1', 'system:config:export', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 通知公告按钮 |
|||
insert into sys_menu values('1035', '公告查询', '107', '1', '#', '', 'F', '0', '1', 'system:notice:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1036', '公告新增', '107', '2', '#', '', 'F', '0', '1', 'system:notice:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1037', '公告修改', '107', '3', '#', '', 'F', '0', '1', 'system:notice:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1038', '公告删除', '107', '4', '#', '', 'F', '0', '1', 'system:notice:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 操作日志按钮 |
|||
insert into sys_menu values('1039', '操作查询', '500', '1', '#', '', 'F', '0', '1', 'monitor:operlog:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1040', '操作删除', '500', '2', '#', '', 'F', '0', '1', 'monitor:operlog:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1041', '详细信息', '500', '3', '#', '', 'F', '0', '1', 'monitor:operlog:detail', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1042', '日志导出', '500', '4', '#', '', 'F', '0', '1', 'monitor:operlog:export', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 登录日志按钮 |
|||
insert into sys_menu values('1043', '登录查询', '501', '1', '#', '', 'F', '0', '1', 'monitor:logininfor:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1044', '登录删除', '501', '2', '#', '', 'F', '0', '1', 'monitor:logininfor:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1045', '日志导出', '501', '3', '#', '', 'F', '0', '1', 'monitor:logininfor:export', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1046', '账户解锁', '501', '4', '#', '', 'F', '0', '1', 'monitor:logininfor:unlock', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 在线用户按钮 |
|||
insert into sys_menu values('1047', '在线查询', '109', '1', '#', '', 'F', '0', '1', 'monitor:online:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1048', '批量强退', '109', '2', '#', '', 'F', '0', '1', 'monitor:online:batchForceLogout', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1049', '单条强退', '109', '3', '#', '', 'F', '0', '1', 'monitor:online:forceLogout', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 定时任务按钮 |
|||
insert into sys_menu values('1050', '任务查询', '110', '1', '#', '', 'F', '0', '1', 'monitor:job:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1051', '任务新增', '110', '2', '#', '', 'F', '0', '1', 'monitor:job:add', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1052', '任务修改', '110', '3', '#', '', 'F', '0', '1', 'monitor:job:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1053', '任务删除', '110', '4', '#', '', 'F', '0', '1', 'monitor:job:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1054', '状态修改', '110', '5', '#', '', 'F', '0', '1', 'monitor:job:changeStatus', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1055', '任务详细', '110', '6', '#', '', 'F', '0', '1', 'monitor:job:detail', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1056', '任务导出', '110', '7', '#', '', 'F', '0', '1', 'monitor:job:export', '#', 'admin', sysdate(), '', null, ''); |
|||
-- 代码生成按钮 |
|||
insert into sys_menu values('1057', '生成查询', '115', '1', '#', '', 'F', '0', '1', 'tool:gen:list', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1058', '生成修改', '115', '2', '#', '', 'F', '0', '1', 'tool:gen:edit', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1059', '生成删除', '115', '3', '#', '', 'F', '0', '1', 'tool:gen:remove', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1060', '预览代码', '115', '4', '#', '', 'F', '0', '1', 'tool:gen:preview', '#', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_menu values('1061', '生成代码', '115', '5', '#', '', 'F', '0', '1', 'tool:gen:code', '#', 'admin', sysdate(), '', null, ''); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 6、用户和角色关联表 用户N-1角色 |
|||
-- ---------------------------- |
|||
drop table if exists sys_user_role; |
|||
create table sys_user_role ( |
|||
user_id bigint(20) not null comment '用户ID', |
|||
role_id bigint(20) not null comment '角色ID', |
|||
primary key(user_id, role_id) |
|||
) engine=innodb comment = '用户和角色关联表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-用户和角色关联表数据 |
|||
-- ---------------------------- |
|||
insert into sys_user_role values ('1', '1'); |
|||
insert into sys_user_role values ('2', '2'); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 7、角色和菜单关联表 角色1-N菜单 |
|||
-- ---------------------------- |
|||
drop table if exists sys_role_menu; |
|||
create table sys_role_menu ( |
|||
role_id bigint(20) not null comment '角色ID', |
|||
menu_id bigint(20) not null comment '菜单ID', |
|||
primary key(role_id, menu_id) |
|||
) engine=innodb comment = '角色和菜单关联表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-角色和菜单关联表数据 |
|||
-- ---------------------------- |
|||
insert into sys_role_menu values ('2', '1'); |
|||
insert into sys_role_menu values ('2', '2'); |
|||
insert into sys_role_menu values ('2', '3'); |
|||
insert into sys_role_menu values ('2', '4'); |
|||
insert into sys_role_menu values ('2', '100'); |
|||
insert into sys_role_menu values ('2', '101'); |
|||
insert into sys_role_menu values ('2', '102'); |
|||
insert into sys_role_menu values ('2', '103'); |
|||
insert into sys_role_menu values ('2', '104'); |
|||
insert into sys_role_menu values ('2', '105'); |
|||
insert into sys_role_menu values ('2', '106'); |
|||
insert into sys_role_menu values ('2', '107'); |
|||
insert into sys_role_menu values ('2', '108'); |
|||
insert into sys_role_menu values ('2', '109'); |
|||
insert into sys_role_menu values ('2', '110'); |
|||
insert into sys_role_menu values ('2', '111'); |
|||
insert into sys_role_menu values ('2', '112'); |
|||
insert into sys_role_menu values ('2', '113'); |
|||
insert into sys_role_menu values ('2', '114'); |
|||
insert into sys_role_menu values ('2', '115'); |
|||
insert into sys_role_menu values ('2', '116'); |
|||
insert into sys_role_menu values ('2', '500'); |
|||
insert into sys_role_menu values ('2', '501'); |
|||
insert into sys_role_menu values ('2', '1000'); |
|||
insert into sys_role_menu values ('2', '1001'); |
|||
insert into sys_role_menu values ('2', '1002'); |
|||
insert into sys_role_menu values ('2', '1003'); |
|||
insert into sys_role_menu values ('2', '1004'); |
|||
insert into sys_role_menu values ('2', '1005'); |
|||
insert into sys_role_menu values ('2', '1006'); |
|||
insert into sys_role_menu values ('2', '1007'); |
|||
insert into sys_role_menu values ('2', '1008'); |
|||
insert into sys_role_menu values ('2', '1009'); |
|||
insert into sys_role_menu values ('2', '1010'); |
|||
insert into sys_role_menu values ('2', '1011'); |
|||
insert into sys_role_menu values ('2', '1012'); |
|||
insert into sys_role_menu values ('2', '1013'); |
|||
insert into sys_role_menu values ('2', '1014'); |
|||
insert into sys_role_menu values ('2', '1015'); |
|||
insert into sys_role_menu values ('2', '1016'); |
|||
insert into sys_role_menu values ('2', '1017'); |
|||
insert into sys_role_menu values ('2', '1018'); |
|||
insert into sys_role_menu values ('2', '1019'); |
|||
insert into sys_role_menu values ('2', '1020'); |
|||
insert into sys_role_menu values ('2', '1021'); |
|||
insert into sys_role_menu values ('2', '1022'); |
|||
insert into sys_role_menu values ('2', '1023'); |
|||
insert into sys_role_menu values ('2', '1024'); |
|||
insert into sys_role_menu values ('2', '1025'); |
|||
insert into sys_role_menu values ('2', '1026'); |
|||
insert into sys_role_menu values ('2', '1027'); |
|||
insert into sys_role_menu values ('2', '1028'); |
|||
insert into sys_role_menu values ('2', '1029'); |
|||
insert into sys_role_menu values ('2', '1030'); |
|||
insert into sys_role_menu values ('2', '1031'); |
|||
insert into sys_role_menu values ('2', '1032'); |
|||
insert into sys_role_menu values ('2', '1033'); |
|||
insert into sys_role_menu values ('2', '1034'); |
|||
insert into sys_role_menu values ('2', '1035'); |
|||
insert into sys_role_menu values ('2', '1036'); |
|||
insert into sys_role_menu values ('2', '1037'); |
|||
insert into sys_role_menu values ('2', '1038'); |
|||
insert into sys_role_menu values ('2', '1039'); |
|||
insert into sys_role_menu values ('2', '1040'); |
|||
insert into sys_role_menu values ('2', '1041'); |
|||
insert into sys_role_menu values ('2', '1042'); |
|||
insert into sys_role_menu values ('2', '1043'); |
|||
insert into sys_role_menu values ('2', '1044'); |
|||
insert into sys_role_menu values ('2', '1045'); |
|||
insert into sys_role_menu values ('2', '1046'); |
|||
insert into sys_role_menu values ('2', '1047'); |
|||
insert into sys_role_menu values ('2', '1048'); |
|||
insert into sys_role_menu values ('2', '1049'); |
|||
insert into sys_role_menu values ('2', '1050'); |
|||
insert into sys_role_menu values ('2', '1051'); |
|||
insert into sys_role_menu values ('2', '1052'); |
|||
insert into sys_role_menu values ('2', '1053'); |
|||
insert into sys_role_menu values ('2', '1054'); |
|||
insert into sys_role_menu values ('2', '1055'); |
|||
insert into sys_role_menu values ('2', '1056'); |
|||
insert into sys_role_menu values ('2', '1057'); |
|||
insert into sys_role_menu values ('2', '1058'); |
|||
insert into sys_role_menu values ('2', '1059'); |
|||
insert into sys_role_menu values ('2', '1060'); |
|||
insert into sys_role_menu values ('2', '1061'); |
|||
|
|||
-- ---------------------------- |
|||
-- 8、角色和部门关联表 角色1-N部门 |
|||
-- ---------------------------- |
|||
drop table if exists sys_role_dept; |
|||
create table sys_role_dept ( |
|||
role_id bigint(20) not null comment '角色ID', |
|||
dept_id bigint(20) not null comment '部门ID', |
|||
primary key(role_id, dept_id) |
|||
) engine=innodb comment = '角色和部门关联表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-角色和部门关联表数据 |
|||
-- ---------------------------- |
|||
insert into sys_role_dept values ('2', '100'); |
|||
insert into sys_role_dept values ('2', '101'); |
|||
insert into sys_role_dept values ('2', '105'); |
|||
|
|||
-- ---------------------------- |
|||
-- 9、用户与岗位关联表 用户1-N岗位 |
|||
-- ---------------------------- |
|||
drop table if exists sys_user_post; |
|||
create table sys_user_post |
|||
( |
|||
user_id bigint(20) not null comment '用户ID', |
|||
post_id bigint(20) not null comment '岗位ID', |
|||
primary key (user_id, post_id) |
|||
) engine=innodb comment = '用户与岗位关联表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-用户与岗位关联表数据 |
|||
-- ---------------------------- |
|||
insert into sys_user_post values ('1', '1'); |
|||
insert into sys_user_post values ('2', '2'); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 10、操作日志记录 |
|||
-- ---------------------------- |
|||
drop table if exists sys_oper_log; |
|||
create table sys_oper_log ( |
|||
oper_id bigint(20) not null auto_increment comment '日志主键', |
|||
title varchar(50) default '' comment '模块标题', |
|||
business_type int(2) default 0 comment '业务类型(0其它 1新增 2修改 3删除)', |
|||
method varchar(200) default '' comment '方法名称', |
|||
request_method varchar(10) default '' comment '请求方式', |
|||
operator_type int(1) default 0 comment '操作类别(0其它 1后台用户 2手机端用户)', |
|||
oper_name varchar(50) default '' comment '操作人员', |
|||
dept_name varchar(50) default '' comment '部门名称', |
|||
oper_url varchar(255) default '' comment '请求URL', |
|||
oper_ip varchar(128) default '' comment '主机地址', |
|||
oper_location varchar(255) default '' comment '操作地点', |
|||
oper_param varchar(2000) default '' comment '请求参数', |
|||
json_result varchar(2000) default '' comment '返回参数', |
|||
status int(1) default 0 comment '操作状态(0正常 1异常)', |
|||
error_msg varchar(2000) default '' comment '错误消息', |
|||
oper_time datetime comment '操作时间', |
|||
cost_time bigint(20) default 0 comment '消耗时间', |
|||
primary key (oper_id), |
|||
key idx_sys_oper_log_bt (business_type), |
|||
key idx_sys_oper_log_s (status), |
|||
key idx_sys_oper_log_ot (oper_time) |
|||
) engine=innodb auto_increment=100 comment = '操作日志记录'; |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 11、字典类型表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_dict_type; |
|||
create table sys_dict_type |
|||
( |
|||
dict_id bigint(20) not null auto_increment comment '字典主键', |
|||
dict_name varchar(100) default '' comment '字典名称', |
|||
dict_type varchar(100) default '' comment '字典类型', |
|||
status char(1) default '0' comment '状态(0正常 1停用)', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default null comment '备注', |
|||
primary key (dict_id), |
|||
unique (dict_type) |
|||
) engine=innodb auto_increment=100 comment = '字典类型表'; |
|||
|
|||
insert into sys_dict_type values(1, '用户性别', 'sys_user_sex', '0', 'admin', sysdate(), '', null, '用户性别列表'); |
|||
insert into sys_dict_type values(2, '菜单状态', 'sys_show_hide', '0', 'admin', sysdate(), '', null, '菜单状态列表'); |
|||
insert into sys_dict_type values(3, '系统开关', 'sys_normal_disable', '0', 'admin', sysdate(), '', null, '系统开关列表'); |
|||
insert into sys_dict_type values(4, '任务状态', 'sys_job_status', '0', 'admin', sysdate(), '', null, '任务状态列表'); |
|||
insert into sys_dict_type values(5, '任务分组', 'sys_job_group', '0', 'admin', sysdate(), '', null, '任务分组列表'); |
|||
insert into sys_dict_type values(6, '系统是否', 'sys_yes_no', '0', 'admin', sysdate(), '', null, '系统是否列表'); |
|||
insert into sys_dict_type values(7, '通知类型', 'sys_notice_type', '0', 'admin', sysdate(), '', null, '通知类型列表'); |
|||
insert into sys_dict_type values(8, '通知状态', 'sys_notice_status', '0', 'admin', sysdate(), '', null, '通知状态列表'); |
|||
insert into sys_dict_type values(9, '操作类型', 'sys_oper_type', '0', 'admin', sysdate(), '', null, '操作类型列表'); |
|||
insert into sys_dict_type values(10, '系统状态', 'sys_common_status', '0', 'admin', sysdate(), '', null, '登录状态列表'); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 12、字典数据表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_dict_data; |
|||
create table sys_dict_data |
|||
( |
|||
dict_code bigint(20) not null auto_increment comment '字典编码', |
|||
dict_sort int(4) default 0 comment '字典排序', |
|||
dict_label varchar(100) default '' comment '字典标签', |
|||
dict_value varchar(100) default '' comment '字典键值', |
|||
dict_type varchar(100) default '' comment '字典类型', |
|||
css_class varchar(100) default null comment '样式属性(其他样式扩展)', |
|||
list_class varchar(100) default null comment '表格回显样式', |
|||
is_default char(1) default 'N' comment '是否默认(Y是 N否)', |
|||
status char(1) default '0' comment '状态(0正常 1停用)', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default null comment '备注', |
|||
primary key (dict_code) |
|||
) engine=innodb auto_increment=100 comment = '字典数据表'; |
|||
|
|||
insert into sys_dict_data values(1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', '0', 'admin', sysdate(), '', null, '性别男'); |
|||
insert into sys_dict_data values(2, 2, '女', '1', 'sys_user_sex', '', '', 'N', '0', 'admin', sysdate(), '', null, '性别女'); |
|||
insert into sys_dict_data values(3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '0', 'admin', sysdate(), '', null, '性别未知'); |
|||
insert into sys_dict_data values(4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '显示菜单'); |
|||
insert into sys_dict_data values(5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '隐藏菜单'); |
|||
insert into sys_dict_data values(6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); |
|||
insert into sys_dict_data values(7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); |
|||
insert into sys_dict_data values(8, 1, '正常', '0', 'sys_job_status', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); |
|||
insert into sys_dict_data values(9, 2, '暂停', '1', 'sys_job_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); |
|||
insert into sys_dict_data values(10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', '0', 'admin', sysdate(), '', null, '默认分组'); |
|||
insert into sys_dict_data values(11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', '0', 'admin', sysdate(), '', null, '系统分组'); |
|||
insert into sys_dict_data values(12, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '系统默认是'); |
|||
insert into sys_dict_data values(13, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '系统默认否'); |
|||
insert into sys_dict_data values(14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '0', 'admin', sysdate(), '', null, '通知'); |
|||
insert into sys_dict_data values(15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '0', 'admin', sysdate(), '', null, '公告'); |
|||
insert into sys_dict_data values(16, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', '0', 'admin', sysdate(), '', null, '正常状态'); |
|||
insert into sys_dict_data values(17, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '关闭状态'); |
|||
insert into sys_dict_data values(18, 99, '其他', '0', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '其他操作'); |
|||
insert into sys_dict_data values(19, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '新增操作'); |
|||
insert into sys_dict_data values(20, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '修改操作'); |
|||
insert into sys_dict_data values(21, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '删除操作'); |
|||
insert into sys_dict_data values(22, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '授权操作'); |
|||
insert into sys_dict_data values(23, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '导出操作'); |
|||
insert into sys_dict_data values(24, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '导入操作'); |
|||
insert into sys_dict_data values(25, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '强退操作'); |
|||
insert into sys_dict_data values(26, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '生成操作'); |
|||
insert into sys_dict_data values(27, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '清空操作'); |
|||
insert into sys_dict_data values(28, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '正常状态'); |
|||
insert into sys_dict_data values(29, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '停用状态'); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 13、参数配置表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_config; |
|||
create table sys_config ( |
|||
config_id int(5) not null auto_increment comment '参数主键', |
|||
config_name varchar(100) default '' comment '参数名称', |
|||
config_key varchar(100) default '' comment '参数键名', |
|||
config_value varchar(500) default '' comment '参数键值', |
|||
config_type char(1) default 'N' comment '系统内置(Y是 N否)', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default null comment '备注', |
|||
primary key (config_id) |
|||
) engine=innodb auto_increment=100 comment = '参数配置表'; |
|||
|
|||
insert into sys_config values(1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', sysdate(), '', null, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow'); |
|||
insert into sys_config values(2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', sysdate(), '', null, '初始化密码 123456'); |
|||
insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深黑主题theme-dark,浅色主题theme-light,深蓝主题theme-blue'); |
|||
insert into sys_config values(4, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)'); |
|||
insert into sys_config values(5, '用户管理-密码字符范围', 'sys.account.chrtype', '0', 'Y', 'admin', sysdate(), '', null, '默认任意字符范围,0任意(密码可以输入任意字符),1数字(密码只能为0-9数字),2英文字母(密码只能为a-z和A-Z字母),3字母和数字(密码必须包含字母,数字),4字母数字和特殊字符(目前支持的特殊字符包括:~!@#$%^&*()-=_+)'); |
|||
insert into sys_config values(6, '用户管理-初始密码修改策略', 'sys.account.initPasswordModify', '1', 'Y', 'admin', sysdate(), '', null, '0:初始密码修改策略关闭,没有任何提示,1:提醒用户,如果未修改初始密码,则在登录时就会提醒修改密码对话框'); |
|||
insert into sys_config values(7, '用户管理-账号密码更新周期', 'sys.account.passwordValidateDays', '0', 'Y', 'admin', sysdate(), '', null, '密码更新周期(填写数字,数据初始化值为0不限制,若修改必须为大于0小于365的正整数),如果超过这个周期登录系统时,则在登录时就会提醒修改密码对话框'); |
|||
insert into sys_config values(8, '主框架页-菜单导航显示风格', 'sys.index.menuStyle', 'default', 'Y', 'admin', sysdate(), '', null, '菜单导航显示风格(default为左侧导航菜单,topnav为顶部导航菜单)'); |
|||
insert into sys_config values(9, '主框架页-是否开启页脚', 'sys.index.footer', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启底部页脚显示(true显示,false隐藏)'); |
|||
insert into sys_config values(10, '主框架页-是否开启页签', 'sys.index.tagsView', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启菜单多页签显示(true显示,false隐藏)'); |
|||
insert into sys_config values(11, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', sysdate(), '', null, '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)'); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 14、系统访问记录 |
|||
-- ---------------------------- |
|||
drop table if exists sys_logininfor; |
|||
create table sys_logininfor ( |
|||
info_id bigint(20) not null auto_increment comment '访问ID', |
|||
login_name varchar(50) default '' comment '登录账号', |
|||
ipaddr varchar(128) default '' comment '登录IP地址', |
|||
login_location varchar(255) default '' comment '登录地点', |
|||
browser varchar(50) default '' comment '浏览器类型', |
|||
os varchar(50) default '' comment '操作系统', |
|||
status char(1) default '0' comment '登录状态(0成功 1失败)', |
|||
msg varchar(255) default '' comment '提示消息', |
|||
login_time datetime comment '访问时间', |
|||
primary key (info_id), |
|||
key idx_sys_logininfor_s (status), |
|||
key idx_sys_logininfor_lt (login_time) |
|||
) engine=innodb auto_increment=100 comment = '系统访问记录'; |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 15、在线用户记录 |
|||
-- ---------------------------- |
|||
drop table if exists sys_user_online; |
|||
create table sys_user_online ( |
|||
sessionId varchar(50) default '' comment '用户会话id', |
|||
login_name varchar(50) default '' comment '登录账号', |
|||
dept_name varchar(50) default '' comment '部门名称', |
|||
ipaddr varchar(128) default '' comment '登录IP地址', |
|||
login_location varchar(255) default '' comment '登录地点', |
|||
browser varchar(50) default '' comment '浏览器类型', |
|||
os varchar(50) default '' comment '操作系统', |
|||
status varchar(10) default '' comment '在线状态on_line在线off_line离线', |
|||
start_timestamp datetime comment 'session创建时间', |
|||
last_access_time datetime comment 'session最后访问时间', |
|||
expire_time int(5) default 0 comment '超时时间,单位为分钟', |
|||
primary key (sessionId) |
|||
) engine=innodb comment = '在线用户记录'; |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 16、定时任务调度表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_job; |
|||
create table sys_job ( |
|||
job_id bigint(20) not null auto_increment comment '任务ID', |
|||
job_name varchar(64) default '' comment '任务名称', |
|||
job_group varchar(64) default 'DEFAULT' comment '任务组名', |
|||
invoke_target varchar(500) not null comment '调用目标字符串', |
|||
cron_expression varchar(255) default '' comment 'cron执行表达式', |
|||
misfire_policy varchar(20) default '3' comment '计划执行错误策略(1立即执行 2执行一次 3放弃执行)', |
|||
concurrent char(1) default '1' comment '是否并发执行(0允许 1禁止)', |
|||
status char(1) default '0' comment '状态(0正常 1暂停)', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default '' comment '备注信息', |
|||
primary key (job_id, job_name, job_group) |
|||
) engine=innodb auto_increment=100 comment = '定时任务调度表'; |
|||
|
|||
insert into sys_job values(1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_job values(2, '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); |
|||
insert into sys_job values(3, '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', sysdate(), '', null, ''); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 17、定时任务调度日志表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_job_log; |
|||
create table sys_job_log ( |
|||
job_log_id bigint(20) not null auto_increment comment '任务日志ID', |
|||
job_name varchar(64) not null comment '任务名称', |
|||
job_group varchar(64) not null comment '任务组名', |
|||
invoke_target varchar(500) not null comment '调用目标字符串', |
|||
job_message varchar(500) comment '日志信息', |
|||
status char(1) default '0' comment '执行状态(0正常 1失败)', |
|||
exception_info varchar(2000) default '' comment '异常信息', |
|||
create_time datetime comment '创建时间', |
|||
primary key (job_log_id) |
|||
) engine=innodb comment = '定时任务调度日志表'; |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 18、通知公告表 |
|||
-- ---------------------------- |
|||
drop table if exists sys_notice; |
|||
create table sys_notice ( |
|||
notice_id int(4) not null auto_increment comment '公告ID', |
|||
notice_title varchar(50) not null comment '公告标题', |
|||
notice_type char(1) not null comment '公告类型(1通知 2公告)', |
|||
notice_content longblob default null comment '公告内容', |
|||
status char(1) default '0' comment '公告状态(0正常 1关闭)', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(255) default null comment '备注', |
|||
primary key (notice_id) |
|||
) engine=innodb auto_increment=10 comment = '通知公告表'; |
|||
|
|||
-- ---------------------------- |
|||
-- 初始化-公告信息表数据 |
|||
-- ---------------------------- |
|||
insert into sys_notice values('1', '温馨提醒:2018-07-01 若依新版本发布啦', '2', '新版本内容', '0', 'admin', sysdate(), '', null, '管理员'); |
|||
insert into sys_notice values('2', '维护通知:2018-07-01 若依系统凌晨维护', '1', '维护内容', '0', 'admin', sysdate(), '', null, '管理员'); |
|||
insert into sys_notice values('3', '若依开源框架介绍', '1', '<p><span style=\"color: rgb(230, 0, 0);\">项目介绍</span></p><p><font color=\"#333333\">RuoYi开源项目是为企业用户定制的后台脚手架框架,为企业打造的一站式解决方案,降低企业开发成本,提升开发效率。主要包括用户管理、角色管理、部门管理、菜单管理、参数管理、字典管理、</font><span style=\"color: rgb(51, 51, 51);\">岗位管理</span><span style=\"color: rgb(51, 51, 51);\">、定时任务</span><span style=\"color: rgb(51, 51, 51);\">、</span><span style=\"color: rgb(51, 51, 51);\">服务监控、登录日志、操作日志、代码生成等功能。其中,还支持多数据源、数据权限、国际化、Redis缓存、Docker部署、滑动验证码、第三方认证登录、分布式事务、</span><font color=\"#333333\">分布式文件存储</font><span style=\"color: rgb(51, 51, 51);\">、分库分表处理等技术特点。</span></p><p><img src=\"https://foruda.gitee.com/images/1705030583977401651/5ed5db6a_1151004.png\" style=\"width: 64px;\"><br></p><p><span style=\"color: rgb(230, 0, 0);\">官网及演示</span></p><p><span style=\"color: rgb(51, 51, 51);\">若依官网地址: </span><a href=\"http://ruoyi.vip\" target=\"_blank\">http://ruoyi.vip</a><a href=\"http://ruoyi.vip\" target=\"_blank\"></a></p><p><span style=\"color: rgb(51, 51, 51);\">若依文档地址: </span><a href=\"http://doc.ruoyi.vip\" target=\"_blank\">http://doc.ruoyi.vip</a><br></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【不分离版】: </span><a href=\"http://demo.ruoyi.vip\" target=\"_blank\">http://demo.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【分离版本】: </span><a href=\"http://vue.ruoyi.vip\" target=\"_blank\">http://vue.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【微服务版】: </span><a href=\"http://cloud.ruoyi.vip\" target=\"_blank\">http://cloud.ruoyi.vip</a></p><p><span style=\"color: rgb(51, 51, 51);\">演示地址【移动端版】: </span><a href=\"http://h5.ruoyi.vip\" target=\"_blank\">http://h5.ruoyi.vip</a></p><p><br style=\"color: rgb(48, 49, 51); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12px;\"></p>', '0', 'admin', sysdate(), '', null, '管理员'); |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 19、代码生成业务表 |
|||
-- ---------------------------- |
|||
drop table if exists gen_table; |
|||
create table gen_table ( |
|||
table_id bigint(20) not null auto_increment comment '编号', |
|||
table_name varchar(200) default '' comment '表名称', |
|||
table_comment varchar(500) default '' comment '表描述', |
|||
sub_table_name varchar(64) default null comment '关联子表的表名', |
|||
sub_table_fk_name varchar(64) default null comment '子表关联的外键名', |
|||
class_name varchar(100) default '' comment '实体类名称', |
|||
tpl_category varchar(200) default 'crud' comment '使用的模板(crud单表操作 tree树表操作 sub主子表操作)', |
|||
package_name varchar(100) comment '生成包路径', |
|||
module_name varchar(30) comment '生成模块名', |
|||
business_name varchar(30) comment '生成业务名', |
|||
function_name varchar(50) comment '生成功能名', |
|||
function_author varchar(50) comment '生成功能作者', |
|||
form_col_num int(1) default 1 comment '表单布局(单列 双列 三列)', |
|||
gen_type char(1) default '0' comment '生成代码方式(0zip压缩包 1自定义路径)', |
|||
gen_path varchar(200) default '/' comment '生成路径(不填默认项目路径)', |
|||
options varchar(1000) comment '其它生成选项', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
remark varchar(500) default null comment '备注', |
|||
primary key (table_id) |
|||
) engine=innodb auto_increment=1 comment = '代码生成业务表'; |
|||
|
|||
|
|||
-- ---------------------------- |
|||
-- 20、代码生成业务表字段 |
|||
-- ---------------------------- |
|||
drop table if exists gen_table_column; |
|||
create table gen_table_column ( |
|||
column_id bigint(20) not null auto_increment comment '编号', |
|||
table_id bigint(20) comment '归属表编号', |
|||
column_name varchar(200) comment '列名称', |
|||
column_comment varchar(500) comment '列描述', |
|||
column_type varchar(100) comment '列类型', |
|||
java_type varchar(500) comment 'JAVA类型', |
|||
java_field varchar(200) comment 'JAVA字段名', |
|||
is_pk char(1) comment '是否主键(1是)', |
|||
is_increment char(1) comment '是否自增(1是)', |
|||
is_required char(1) comment '是否必填(1是)', |
|||
is_insert char(1) comment '是否为插入字段(1是)', |
|||
is_edit char(1) comment '是否编辑字段(1是)', |
|||
is_list char(1) comment '是否列表字段(1是)', |
|||
is_query char(1) comment '是否查询字段(1是)', |
|||
query_type varchar(200) default 'EQ' comment '查询方式(等于、不等于、大于、小于、范围)', |
|||
html_type varchar(200) comment '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)', |
|||
dict_type varchar(200) default '' comment '字典类型', |
|||
sort int comment '排序', |
|||
create_by varchar(64) default '' comment '创建者', |
|||
create_time datetime comment '创建时间', |
|||
update_by varchar(64) default '' comment '更新者', |
|||
update_time datetime comment '更新时间', |
|||
primary key (column_id) |
|||
) engine=innodb auto_increment=1 comment = '代码生成业务表字段'; |
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,132 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
|||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
|||
<parent> |
|||
<artifactId>win</artifactId> |
|||
<groupId>com.win</groupId> |
|||
<version>4.7.9</version> |
|||
</parent> |
|||
<modelVersion>4.0.0</modelVersion> |
|||
<packaging>jar</packaging> |
|||
<artifactId>win-admin</artifactId> |
|||
|
|||
<description> |
|||
web服务入口 |
|||
</description> |
|||
|
|||
<dependencies> |
|||
|
|||
<!-- SpringBoot集成thymeleaf模板 --> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-starter-thymeleaf</artifactId> |
|||
</dependency> |
|||
|
|||
<!-- spring-boot-devtools --> |
|||
<dependency> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-devtools</artifactId> |
|||
<optional>true</optional> <!-- 表示依赖不会传递 --> |
|||
</dependency> |
|||
|
|||
<!-- spring-doc --> |
|||
<dependency> |
|||
<groupId>org.springdoc</groupId> |
|||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> |
|||
</dependency> |
|||
|
|||
<!-- Mysql驱动包 --> |
|||
<dependency> |
|||
<groupId>com.mysql</groupId> |
|||
<artifactId>mysql-connector-j</artifactId> |
|||
</dependency> |
|||
|
|||
<!-- 核心模块--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-framework</artifactId> |
|||
</dependency> |
|||
|
|||
<!-- 定时任务--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-quartz</artifactId> |
|||
</dependency> |
|||
|
|||
<!-- 代码生成--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-generator</artifactId> |
|||
</dependency> |
|||
<!-- 打印模块--> |
|||
<dependency> |
|||
<groupId>com.win</groupId> |
|||
<artifactId>win-print</artifactId> |
|||
</dependency> |
|||
</dependencies> |
|||
|
|||
<build> |
|||
<plugins> |
|||
<plugin> |
|||
<groupId>org.springframework.boot</groupId> |
|||
<artifactId>spring-boot-maven-plugin</artifactId> |
|||
<version>2.5.15</version> |
|||
<configuration> |
|||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 --> |
|||
</configuration> |
|||
<executions> |
|||
<execution> |
|||
<goals> |
|||
<goal>repackage</goal> |
|||
</goals> |
|||
</execution> |
|||
</executions> |
|||
</plugin> |
|||
<plugin> |
|||
<groupId>org.apache.maven.plugins</groupId> |
|||
<artifactId>maven-war-plugin</artifactId> |
|||
<version>3.1.0</version> |
|||
<configuration> |
|||
<failOnMissingWebXml>false</failOnMissingWebXml> |
|||
<warName>${project.artifactId}</warName> |
|||
</configuration> |
|||
</plugin> |
|||
<!-- YUI Compressor (CSS/JS压缩) |
|||
<plugin> |
|||
<groupId>net.alchim31.maven</groupId> |
|||
<artifactId>yuicompressor-maven-plugin</artifactId> |
|||
<version>1.5.1</version> |
|||
<executions> |
|||
<execution> |
|||
<phase>prepare-package</phase> |
|||
<goals> |
|||
<goal>compress</goal> |
|||
</goals> |
|||
</execution> |
|||
</executions> |
|||
<configuration> |
|||
<encoding>UTF-8</encoding> |
|||
<jswarn>false</jswarn> |
|||
<nosuffix>true</nosuffix> |
|||
<linebreakpos>50000</linebreakpos> |
|||
<sourceDirectory>src/main/resources/static</sourceDirectory> |
|||
<force>true</force> |
|||
<includes> |
|||
<include>**/*.js</include> |
|||
<include>**/*.css</include> |
|||
</includes> |
|||
<excludes> |
|||
<exclude>**/*.min.js</exclude> |
|||
<exclude>**/*.min.css</exclude> |
|||
<exclude>**/fileinput.js</exclude> |
|||
<exclude>**/validate/**</exclude> |
|||
<exclude>**/bootstrap-table/**</exclude> |
|||
</excludes> |
|||
</configuration> |
|||
</plugin> --> |
|||
</plugins> |
|||
<finalName>${project.artifactId}</finalName> |
|||
</build> |
|||
|
|||
</project> |
@ -0,0 +1,23 @@ |
|||
package com.win; |
|||
|
|||
import org.springframework.boot.SpringApplication; |
|||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
|||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; |
|||
import org.springframework.scheduling.annotation.EnableScheduling; |
|||
|
|||
/** |
|||
* 启动程序 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) |
|||
|
|||
public class WinApplication |
|||
{ |
|||
public static void main(String[] args) |
|||
{ |
|||
// System.setProperty("spring.devtools.restart.enabled", "false");
|
|||
SpringApplication.run(WinApplication.class, args); |
|||
System.out.println("(♥◠‿◠)ノ゙ 闻荫打印服务启动成功 ლ(´ڡ`ლ)゙ "); |
|||
} |
|||
} |
@ -0,0 +1,18 @@ |
|||
package com.win; |
|||
|
|||
import org.springframework.boot.builder.SpringApplicationBuilder; |
|||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; |
|||
|
|||
/** |
|||
* web容器中进行部署 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class WinServletInitializer extends SpringBootServletInitializer |
|||
{ |
|||
@Override |
|||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) |
|||
{ |
|||
return application.sources(WinApplication.class); |
|||
} |
|||
} |
@ -0,0 +1,166 @@ |
|||
package com.win.web.controller.common; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.http.MediaType; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
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.win.common.config.WinConfig; |
|||
import com.win.common.config.ServerConfig; |
|||
import com.win.common.constant.Constants; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.utils.StringUtils; |
|||
import com.win.common.utils.file.FileUploadUtils; |
|||
import com.win.common.utils.file.FileUtils; |
|||
|
|||
/** |
|||
* 通用请求处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/common") |
|||
public class CommonController |
|||
{ |
|||
private static final Logger log = LoggerFactory.getLogger(CommonController.class); |
|||
|
|||
@Autowired |
|||
private ServerConfig serverConfig; |
|||
|
|||
private static final String FILE_DELIMETER = ","; |
|||
|
|||
/** |
|||
* 通用下载请求 |
|||
* |
|||
* @param fileName 文件名称 |
|||
* @param delete 是否删除 |
|||
*/ |
|||
@GetMapping("/download") |
|||
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) |
|||
{ |
|||
try |
|||
{ |
|||
if (!FileUtils.checkAllowDownload(fileName)) |
|||
{ |
|||
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName)); |
|||
} |
|||
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); |
|||
String filePath = WinConfig.getDownloadPath() + fileName; |
|||
|
|||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); |
|||
FileUtils.setAttachmentResponseHeader(response, realFileName); |
|||
FileUtils.writeBytes(filePath, response.getOutputStream()); |
|||
if (delete) |
|||
{ |
|||
FileUtils.deleteFile(filePath); |
|||
} |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
log.error("下载文件失败", e); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 通用上传请求(单个) |
|||
*/ |
|||
@PostMapping("/upload") |
|||
@ResponseBody |
|||
public AjaxResult uploadFile(MultipartFile file) throws Exception |
|||
{ |
|||
try |
|||
{ |
|||
// 上传文件路径
|
|||
String filePath = WinConfig.getUploadPath(); |
|||
// 上传并返回新文件名称
|
|||
String fileName = FileUploadUtils.upload(filePath, file); |
|||
String url = serverConfig.getUrl() + fileName; |
|||
AjaxResult ajax = AjaxResult.success(); |
|||
ajax.put("url", url); |
|||
ajax.put("fileName", fileName); |
|||
ajax.put("newFileName", FileUtils.getName(fileName)); |
|||
ajax.put("originalFilename", file.getOriginalFilename()); |
|||
return ajax; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
return AjaxResult.error(e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 通用上传请求(多个) |
|||
*/ |
|||
@PostMapping("/uploads") |
|||
@ResponseBody |
|||
public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception |
|||
{ |
|||
try |
|||
{ |
|||
// 上传文件路径
|
|||
String filePath = WinConfig.getUploadPath(); |
|||
List<String> urls = new ArrayList<String>(); |
|||
List<String> fileNames = new ArrayList<String>(); |
|||
List<String> newFileNames = new ArrayList<String>(); |
|||
List<String> originalFilenames = new ArrayList<String>(); |
|||
for (MultipartFile file : files) |
|||
{ |
|||
// 上传并返回新文件名称
|
|||
String fileName = FileUploadUtils.upload(filePath, file); |
|||
String url = serverConfig.getUrl() + fileName; |
|||
urls.add(url); |
|||
fileNames.add(fileName); |
|||
newFileNames.add(FileUtils.getName(fileName)); |
|||
originalFilenames.add(file.getOriginalFilename()); |
|||
} |
|||
AjaxResult ajax = AjaxResult.success(); |
|||
ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER)); |
|||
ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER)); |
|||
ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER)); |
|||
ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER)); |
|||
return ajax; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
return AjaxResult.error(e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 本地资源通用下载 |
|||
*/ |
|||
@GetMapping("/download/resource") |
|||
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response) |
|||
throws Exception |
|||
{ |
|||
try |
|||
{ |
|||
if (!FileUtils.checkAllowDownload(resource)) |
|||
{ |
|||
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource)); |
|||
} |
|||
// 本地资源路径
|
|||
String localPath = WinConfig.getProfile(); |
|||
// 数据库资源地址
|
|||
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX); |
|||
// 下载名称
|
|||
String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); |
|||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); |
|||
FileUtils.setAttachmentResponseHeader(response, downloadName); |
|||
FileUtils.writeBytes(downloadPath, response.getOutputStream()); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
log.error("下载文件失败", e); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,117 @@ |
|||
package com.win.web.controller.common; |
|||
|
|||
import java.io.BufferedReader; |
|||
import java.io.InputStreamReader; |
|||
import java.lang.reflect.Method; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
|
|||
import com.win.common.config.ServerConfig; |
|||
import com.win.common.config.WinConfig; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.utils.file.FileUploadUtils; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.core.io.ClassPathResource; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
import com.alibaba.fastjson.JSON; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
|
|||
|
|||
/** |
|||
* Ueditor 请求处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@SuppressWarnings("serial") |
|||
@Controller |
|||
@RequestMapping("/ajax/libs/ueditor") |
|||
public class UeditorController extends BaseController |
|||
{ |
|||
private final String METHOD_HEAD = "ueditor"; |
|||
private final String IMGE_PATH = "/ueditor/images/"; |
|||
private final String VIDEO_PATH = "/ueditor/videos/"; |
|||
private final String FILE_PATH = "/ueditor/files/"; |
|||
|
|||
@Autowired |
|||
private ServerConfig serverConfig; |
|||
|
|||
/** |
|||
* ueditor |
|||
*/ |
|||
@ResponseBody |
|||
@RequestMapping(value = "/ueditor/controller") |
|||
public Object ueditor(HttpServletRequest request, @RequestParam(value = "action", required = true) String action, |
|||
MultipartFile upfile) throws Exception |
|||
{ |
|||
List<Object> param = new ArrayList<Object>() |
|||
{ |
|||
{ |
|||
add(action); |
|||
add(upfile); |
|||
} |
|||
}; |
|||
Method method = this.getClass().getMethod(METHOD_HEAD + action, List.class, String.class); |
|||
return method.invoke(this.getClass().newInstance(), param, serverConfig.getUrl()); |
|||
} |
|||
|
|||
/** |
|||
* 读取配置文件 |
|||
*/ |
|||
public JSONObject ueditorconfig(List<Object> param, String fileSuffixUrl) throws Exception |
|||
{ |
|||
ClassPathResource classPathResource = new ClassPathResource("ueditor-config.json"); |
|||
String jsonString = new BufferedReader(new InputStreamReader(classPathResource.getInputStream())).lines().parallel().collect(Collectors.joining(System.lineSeparator())); |
|||
JSONObject json = JSON.parseObject(jsonString, JSONObject.class); |
|||
return json; |
|||
} |
|||
|
|||
/** |
|||
* 上传图片 |
|||
*/ |
|||
public JSONObject ueditoruploadimage(List<Object> param, String fileSuffixUrl) throws Exception |
|||
{ |
|||
JSONObject json = new JSONObject(); |
|||
json.put("state", "SUCCESS"); |
|||
json.put("url", ueditorcore(param, IMGE_PATH, false, fileSuffixUrl)); |
|||
return json; |
|||
} |
|||
|
|||
/** |
|||
* 上传视频 |
|||
*/ |
|||
public JSONObject ueditoruploadvideo(List<Object> param, String fileSuffixUrl) throws Exception |
|||
{ |
|||
JSONObject json = new JSONObject(); |
|||
json.put("state", "SUCCESS"); |
|||
json.put("url", ueditorcore(param, VIDEO_PATH, false, fileSuffixUrl)); |
|||
return json; |
|||
} |
|||
|
|||
/** |
|||
* 上传附件 |
|||
*/ |
|||
public JSONObject ueditoruploadfile(List<Object> param, String fileSuffixUrl) throws Exception |
|||
{ |
|||
JSONObject json = new JSONObject(); |
|||
json.put("state", "SUCCESS"); |
|||
json.put("url", ueditorcore(param, FILE_PATH, true, fileSuffixUrl)); |
|||
return json; |
|||
} |
|||
|
|||
public String ueditorcore(List<Object> param, String path, boolean isFileName, String fileSuffixUrl) |
|||
throws Exception |
|||
{ |
|||
MultipartFile upfile = (MultipartFile) param.get(1); |
|||
// 上传文件路径
|
|||
String filePath = WinConfig.getUploadPath(); |
|||
String fileName = FileUploadUtils.upload(filePath, upfile); |
|||
String url = fileSuffixUrl + fileName; |
|||
return url; |
|||
} |
|||
} |
@ -0,0 +1,98 @@ |
|||
package com.win.web.controller.demo.controller; |
|||
|
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
|
|||
/** |
|||
* 模态窗口 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/demo/modal") |
|||
public class DemoDialogController |
|||
{ |
|||
private String prefix = "demo/modal"; |
|||
|
|||
/** |
|||
* 模态窗口 |
|||
*/ |
|||
@GetMapping("/dialog") |
|||
public String dialog() |
|||
{ |
|||
return prefix + "/dialog"; |
|||
} |
|||
|
|||
/** |
|||
* 弹层组件 |
|||
*/ |
|||
@GetMapping("/layer") |
|||
public String layer() |
|||
{ |
|||
return prefix + "/layer"; |
|||
} |
|||
|
|||
/** |
|||
* 表单 |
|||
*/ |
|||
@GetMapping("/form") |
|||
public String form() |
|||
{ |
|||
return prefix + "/form"; |
|||
} |
|||
|
|||
/** |
|||
* 表格 |
|||
*/ |
|||
@GetMapping("/table") |
|||
public String table() |
|||
{ |
|||
return prefix + "/table"; |
|||
} |
|||
|
|||
/** |
|||
* 表格check |
|||
*/ |
|||
@GetMapping("/check") |
|||
public String check() |
|||
{ |
|||
return prefix + "/table/check"; |
|||
} |
|||
|
|||
/** |
|||
* 表格radio |
|||
*/ |
|||
@GetMapping("/radio") |
|||
public String radio() |
|||
{ |
|||
return prefix + "/table/radio"; |
|||
} |
|||
|
|||
/** |
|||
* 表格回传父窗体 |
|||
*/ |
|||
@GetMapping("/parent") |
|||
public String parent() |
|||
{ |
|||
return prefix + "/table/parent"; |
|||
} |
|||
|
|||
/** |
|||
* 多层窗口frame1 |
|||
*/ |
|||
@GetMapping("/frame1") |
|||
public String frame1() |
|||
{ |
|||
return prefix + "/table/frame1"; |
|||
} |
|||
|
|||
/** |
|||
* 多层窗口frame2 |
|||
*/ |
|||
@GetMapping("/frame2") |
|||
public String frame2() |
|||
{ |
|||
return prefix + "/table/frame2"; |
|||
} |
|||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,35 @@ |
|||
package com.win.web.controller.demo.controller; |
|||
|
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
|
|||
/** |
|||
* 图标相关 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/demo/icon") |
|||
public class DemoIconController |
|||
{ |
|||
private String prefix = "demo/icon"; |
|||
|
|||
/** |
|||
* FontAwesome图标 |
|||
*/ |
|||
@GetMapping("/fontawesome") |
|||
public String fontAwesome() |
|||
{ |
|||
return prefix + "/fontawesome"; |
|||
} |
|||
|
|||
/** |
|||
* Glyphicons图标 |
|||
*/ |
|||
@GetMapping("/glyphicons") |
|||
public String glyphicons() |
|||
{ |
|||
return prefix + "/glyphicons"; |
|||
} |
|||
} |
@ -0,0 +1,326 @@ |
|||
package com.win.web.controller.demo.controller; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.LinkedHashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
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.ResponseBody; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.page.PageDomain; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.core.page.TableSupport; |
|||
import com.win.common.core.text.Convert; |
|||
import com.win.common.exception.ServiceException; |
|||
import com.win.common.utils.StringUtils; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.web.controller.demo.domain.CustomerModel; |
|||
import com.win.web.controller.demo.domain.UserOperateModel; |
|||
|
|||
/** |
|||
* 操作控制 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/demo/operate") |
|||
public class DemoOperateController extends BaseController |
|||
{ |
|||
private String prefix = "demo/operate"; |
|||
|
|||
private final static Map<Integer, UserOperateModel> users = new LinkedHashMap<Integer, UserOperateModel>(); |
|||
{ |
|||
users.put(1, new UserOperateModel(1, "1000001", "测试1", "0", "15888888888", "ry@qq.com", 150.0, "0")); |
|||
users.put(2, new UserOperateModel(2, "1000002", "测试2", "1", "15666666666", "ry@qq.com", 180.0, "1")); |
|||
users.put(3, new UserOperateModel(3, "1000003", "测试3", "0", "15666666666", "ry@qq.com", 110.0, "1")); |
|||
users.put(4, new UserOperateModel(4, "1000004", "测试4", "1", "15666666666", "ry@qq.com", 220.0, "1")); |
|||
users.put(5, new UserOperateModel(5, "1000005", "测试5", "0", "15666666666", "ry@qq.com", 140.0, "1")); |
|||
users.put(6, new UserOperateModel(6, "1000006", "测试6", "1", "15666666666", "ry@qq.com", 330.0, "1")); |
|||
users.put(7, new UserOperateModel(7, "1000007", "测试7", "0", "15666666666", "ry@qq.com", 160.0, "1")); |
|||
users.put(8, new UserOperateModel(8, "1000008", "测试8", "1", "15666666666", "ry@qq.com", 170.0, "1")); |
|||
users.put(9, new UserOperateModel(9, "1000009", "测试9", "0", "15666666666", "ry@qq.com", 180.0, "1")); |
|||
users.put(10, new UserOperateModel(10, "1000010", "测试10", "0", "15666666666", "ry@qq.com", 210.0, "1")); |
|||
users.put(11, new UserOperateModel(11, "1000011", "测试11", "1", "15666666666", "ry@qq.com", 110.0, "1")); |
|||
users.put(12, new UserOperateModel(12, "1000012", "测试12", "0", "15666666666", "ry@qq.com", 120.0, "1")); |
|||
users.put(13, new UserOperateModel(13, "1000013", "测试13", "1", "15666666666", "ry@qq.com", 380.0, "1")); |
|||
users.put(14, new UserOperateModel(14, "1000014", "测试14", "0", "15666666666", "ry@qq.com", 280.0, "1")); |
|||
users.put(15, new UserOperateModel(15, "1000015", "测试15", "0", "15666666666", "ry@qq.com", 570.0, "1")); |
|||
users.put(16, new UserOperateModel(16, "1000016", "测试16", "1", "15666666666", "ry@qq.com", 260.0, "1")); |
|||
users.put(17, new UserOperateModel(17, "1000017", "测试17", "1", "15666666666", "ry@qq.com", 210.0, "1")); |
|||
users.put(18, new UserOperateModel(18, "1000018", "测试18", "1", "15666666666", "ry@qq.com", 340.0, "1")); |
|||
users.put(19, new UserOperateModel(19, "1000019", "测试19", "1", "15666666666", "ry@qq.com", 160.0, "1")); |
|||
users.put(20, new UserOperateModel(20, "1000020", "测试20", "1", "15666666666", "ry@qq.com", 220.0, "1")); |
|||
users.put(21, new UserOperateModel(21, "1000021", "测试21", "1", "15666666666", "ry@qq.com", 120.0, "1")); |
|||
users.put(22, new UserOperateModel(22, "1000022", "测试22", "1", "15666666666", "ry@qq.com", 130.0, "1")); |
|||
users.put(23, new UserOperateModel(23, "1000023", "测试23", "1", "15666666666", "ry@qq.com", 490.0, "1")); |
|||
users.put(24, new UserOperateModel(24, "1000024", "测试24", "1", "15666666666", "ry@qq.com", 570.0, "1")); |
|||
users.put(25, new UserOperateModel(25, "1000025", "测试25", "1", "15666666666", "ry@qq.com", 250.0, "1")); |
|||
users.put(26, new UserOperateModel(26, "1000026", "测试26", "1", "15666666666", "ry@qq.com", 250.0, "1")); |
|||
} |
|||
|
|||
/** |
|||
* 表格 |
|||
*/ |
|||
@GetMapping("/table") |
|||
public String table() |
|||
{ |
|||
return prefix + "/table"; |
|||
} |
|||
|
|||
/** |
|||
* 其他 |
|||
*/ |
|||
@GetMapping("/other") |
|||
public String other() |
|||
{ |
|||
return prefix + "/other"; |
|||
} |
|||
|
|||
/** |
|||
* 查询数据 |
|||
*/ |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(UserOperateModel userModel) |
|||
{ |
|||
TableDataInfo rspData = new TableDataInfo(); |
|||
List<UserOperateModel> userList = new ArrayList<UserOperateModel>(users.values()); |
|||
// 查询条件过滤
|
|||
if (StringUtils.isNotEmpty(userModel.getSearchValue())) |
|||
{ |
|||
userList.clear(); |
|||
for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet()) |
|||
{ |
|||
if (entry.getValue().getUserName().equals(userModel.getSearchValue())) |
|||
{ |
|||
userList.add(entry.getValue()); |
|||
} |
|||
} |
|||
} |
|||
else if (StringUtils.isNotEmpty(userModel.getUserName())) |
|||
{ |
|||
userList.clear(); |
|||
for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet()) |
|||
{ |
|||
if (entry.getValue().getUserName().equals(userModel.getUserName())) |
|||
{ |
|||
userList.add(entry.getValue()); |
|||
} |
|||
} |
|||
} |
|||
PageDomain pageDomain = TableSupport.buildPageRequest(); |
|||
if (null == pageDomain.getPageNum() || null == pageDomain.getPageSize()) |
|||
{ |
|||
rspData.setRows(userList); |
|||
rspData.setTotal(userList.size()); |
|||
return rspData; |
|||
} |
|||
Integer pageNum = (pageDomain.getPageNum() - 1) * 10; |
|||
Integer pageSize = pageDomain.getPageNum() * 10; |
|||
if (pageSize > userList.size()) |
|||
{ |
|||
pageSize = userList.size(); |
|||
} |
|||
rspData.setRows(userList.subList(pageNum, pageSize)); |
|||
rspData.setTotal(userList.size()); |
|||
return rspData; |
|||
} |
|||
|
|||
/** |
|||
* 新增用户 |
|||
*/ |
|||
@GetMapping("/add") |
|||
public String add(ModelMap mmap) |
|||
{ |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存用户 |
|||
*/ |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(UserOperateModel user) |
|||
{ |
|||
Integer userId = users.size() + 1; |
|||
user.setUserId(userId); |
|||
return AjaxResult.success(users.put(userId, user)); |
|||
} |
|||
|
|||
/** |
|||
* 新增保存主子表信息 |
|||
*/ |
|||
@PostMapping("/customer/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(CustomerModel customerModel) |
|||
{ |
|||
System.out.println(customerModel.toString()); |
|||
return AjaxResult.success(); |
|||
} |
|||
|
|||
/** |
|||
* 修改用户 |
|||
*/ |
|||
@GetMapping("/edit/{userId}") |
|||
public String edit(@PathVariable("userId") Integer userId, ModelMap mmap) |
|||
{ |
|||
mmap.put("user", users.get(userId)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存用户 |
|||
*/ |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(UserOperateModel user) |
|||
{ |
|||
return AjaxResult.success(users.put(user.getUserId(), user)); |
|||
} |
|||
|
|||
/** |
|||
* 导出 |
|||
*/ |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(UserOperateModel user) |
|||
{ |
|||
List<UserOperateModel> list = new ArrayList<UserOperateModel>(users.values()); |
|||
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class); |
|||
return util.exportExcel(list, "用户数据"); |
|||
} |
|||
|
|||
/** |
|||
* 下载模板 |
|||
*/ |
|||
@GetMapping("/importTemplate") |
|||
@ResponseBody |
|||
public AjaxResult importTemplate() |
|||
{ |
|||
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class); |
|||
return util.importTemplateExcel("用户数据"); |
|||
} |
|||
|
|||
/** |
|||
* 导入数据 |
|||
*/ |
|||
@PostMapping("/importData") |
|||
@ResponseBody |
|||
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception |
|||
{ |
|||
ExcelUtil<UserOperateModel> util = new ExcelUtil<UserOperateModel>(UserOperateModel.class); |
|||
List<UserOperateModel> userList = util.importExcel(file.getInputStream()); |
|||
String message = importUser(userList, updateSupport); |
|||
return AjaxResult.success(message); |
|||
} |
|||
|
|||
/** |
|||
* 删除用户 |
|||
*/ |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
Integer[] userIds = Convert.toIntArray(ids); |
|||
for (Integer userId : userIds) |
|||
{ |
|||
users.remove(userId); |
|||
} |
|||
return AjaxResult.success(); |
|||
} |
|||
|
|||
/** |
|||
* 查看详细 |
|||
*/ |
|||
@GetMapping("/detail/{userId}") |
|||
public String detail(@PathVariable("userId") Integer userId, ModelMap mmap) |
|||
{ |
|||
mmap.put("user", users.get(userId)); |
|||
return prefix + "/detail"; |
|||
} |
|||
|
|||
@PostMapping("/clean") |
|||
@ResponseBody |
|||
public AjaxResult clean() |
|||
{ |
|||
users.clear(); |
|||
return success(); |
|||
} |
|||
|
|||
/** |
|||
* 导入用户数据 |
|||
* |
|||
* @param userList 用户数据列表 |
|||
* @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 |
|||
* @return 结果 |
|||
*/ |
|||
public String importUser(List<UserOperateModel> userList, Boolean isUpdateSupport) |
|||
{ |
|||
if (StringUtils.isNull(userList) || userList.size() == 0) |
|||
{ |
|||
throw new ServiceException("导入用户数据不能为空!"); |
|||
} |
|||
int successNum = 0; |
|||
int failureNum = 0; |
|||
StringBuilder successMsg = new StringBuilder(); |
|||
StringBuilder failureMsg = new StringBuilder(); |
|||
for (UserOperateModel user : userList) |
|||
{ |
|||
try |
|||
{ |
|||
// 验证是否存在这个用户
|
|||
boolean userFlag = false; |
|||
for (Map.Entry<Integer, UserOperateModel> entry : users.entrySet()) |
|||
{ |
|||
if (entry.getValue().getUserName().equals(user.getUserName())) |
|||
{ |
|||
userFlag = true; |
|||
break; |
|||
} |
|||
} |
|||
if (!userFlag) |
|||
{ |
|||
Integer userId = users.size() + 1; |
|||
user.setUserId(userId); |
|||
users.put(userId, user); |
|||
successNum++; |
|||
successMsg.append("<br/>" + successNum + "、用户 " + user.getUserName() + " 导入成功"); |
|||
} |
|||
else if (isUpdateSupport) |
|||
{ |
|||
users.put(user.getUserId(), user); |
|||
successNum++; |
|||
successMsg.append("<br/>" + successNum + "、用户 " + user.getUserName() + " 更新成功"); |
|||
} |
|||
else |
|||
{ |
|||
failureNum++; |
|||
failureMsg.append("<br/>" + failureNum + "、用户 " + user.getUserName() + " 已存在"); |
|||
} |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
failureNum++; |
|||
String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败:"; |
|||
failureMsg.append(msg + e.getMessage()); |
|||
} |
|||
} |
|||
if (failureNum > 0) |
|||
{ |
|||
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); |
|||
throw new ServiceException(failureMsg.toString()); |
|||
} |
|||
else |
|||
{ |
|||
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); |
|||
} |
|||
return successMsg.toString(); |
|||
} |
|||
} |
@ -0,0 +1,53 @@ |
|||
package com.win.web.controller.demo.controller; |
|||
|
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
|
|||
/** |
|||
* 报表 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/demo/report") |
|||
public class DemoReportController |
|||
{ |
|||
private String prefix = "demo/report"; |
|||
|
|||
/** |
|||
* 百度ECharts |
|||
*/ |
|||
@GetMapping("/echarts") |
|||
public String echarts() |
|||
{ |
|||
return prefix + "/echarts"; |
|||
} |
|||
|
|||
/** |
|||
* 图表插件 |
|||
*/ |
|||
@GetMapping("/peity") |
|||
public String peity() |
|||
{ |
|||
return prefix + "/peity"; |
|||
} |
|||
|
|||
/** |
|||
* 线状图插件 |
|||
*/ |
|||
@GetMapping("/sparkline") |
|||
public String sparkline() |
|||
{ |
|||
return prefix + "/sparkline"; |
|||
} |
|||
|
|||
/** |
|||
* 图表组合 |
|||
*/ |
|||
@GetMapping("/metrics") |
|||
public String metrics() |
|||
{ |
|||
return prefix + "/metrics"; |
|||
} |
|||
} |
File diff suppressed because it is too large
@ -0,0 +1,116 @@ |
|||
package com.win.web.controller.demo.domain; |
|||
|
|||
import java.util.List; |
|||
import org.apache.commons.lang3.builder.ToStringBuilder; |
|||
import org.apache.commons.lang3.builder.ToStringStyle; |
|||
|
|||
/** |
|||
* 客户测试信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class CustomerModel |
|||
{ |
|||
/** |
|||
* 客户姓名 |
|||
*/ |
|||
private String name; |
|||
|
|||
/** |
|||
* 客户手机 |
|||
*/ |
|||
private String phonenumber; |
|||
|
|||
/** |
|||
* 客户性别 |
|||
*/ |
|||
private String sex; |
|||
|
|||
/** |
|||
* 客户生日 |
|||
*/ |
|||
private String birthday; |
|||
|
|||
/** |
|||
* 客户描述 |
|||
*/ |
|||
private String remark; |
|||
|
|||
/** |
|||
* 商品信息 |
|||
*/ |
|||
private List<GoodsModel> goods; |
|||
|
|||
public String getName() |
|||
{ |
|||
return name; |
|||
} |
|||
|
|||
public void setName(String name) |
|||
{ |
|||
this.name = name; |
|||
} |
|||
|
|||
public String getPhonenumber() |
|||
{ |
|||
return phonenumber; |
|||
} |
|||
|
|||
public void setPhonenumber(String phonenumber) |
|||
{ |
|||
this.phonenumber = phonenumber; |
|||
} |
|||
|
|||
|
|||
public String getSex() |
|||
{ |
|||
return sex; |
|||
} |
|||
|
|||
public void setSex(String sex) |
|||
{ |
|||
this.sex = sex; |
|||
} |
|||
|
|||
public String getBirthday() |
|||
{ |
|||
return birthday; |
|||
} |
|||
|
|||
public void setBirthday(String birthday) |
|||
{ |
|||
this.birthday = birthday; |
|||
} |
|||
|
|||
public String getRemark() |
|||
{ |
|||
return remark; |
|||
} |
|||
|
|||
public void setRemark(String remark) |
|||
{ |
|||
this.remark = remark; |
|||
} |
|||
|
|||
public List<GoodsModel> getGoods() |
|||
{ |
|||
return goods; |
|||
} |
|||
|
|||
public void setGoods(List<GoodsModel> goods) |
|||
{ |
|||
this.goods = goods; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
|||
.append("name", getName()) |
|||
.append("phonenumber", getPhonenumber()) |
|||
.append("sex", getSex()) |
|||
.append("birthday", getBirthday()) |
|||
.append("goods", getGoods()) |
|||
.append("remark", getRemark()) |
|||
.toString(); |
|||
} |
|||
} |
@ -0,0 +1,99 @@ |
|||
package com.win.web.controller.demo.domain; |
|||
|
|||
import java.util.Date; |
|||
import org.apache.commons.lang3.builder.ToStringBuilder; |
|||
import org.apache.commons.lang3.builder.ToStringStyle; |
|||
|
|||
/** |
|||
* 商品测试信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
public class GoodsModel |
|||
{ |
|||
/** |
|||
* 商品名称 |
|||
*/ |
|||
private String name; |
|||
|
|||
/** |
|||
* 商品重量 |
|||
*/ |
|||
private Integer weight; |
|||
|
|||
/** |
|||
* 商品价格 |
|||
*/ |
|||
private Double price; |
|||
|
|||
/** |
|||
* 商品日期 |
|||
*/ |
|||
private Date date; |
|||
|
|||
/** |
|||
* 商品种类 |
|||
*/ |
|||
private String type; |
|||
|
|||
public String getName() |
|||
{ |
|||
return name; |
|||
} |
|||
|
|||
public void setName(String name) |
|||
{ |
|||
this.name = name; |
|||
} |
|||
|
|||
public Integer getWeight() |
|||
{ |
|||
return weight; |
|||
} |
|||
|
|||
public void setWeight(Integer weight) |
|||
{ |
|||
this.weight = weight; |
|||
} |
|||
|
|||
public Double getPrice() |
|||
{ |
|||
return price; |
|||
} |
|||
|
|||
public void setPrice(Double price) |
|||
{ |
|||
this.price = price; |
|||
} |
|||
|
|||
public Date getDate() |
|||
{ |
|||
return date; |
|||
} |
|||
|
|||
public void setDate(Date date) |
|||
{ |
|||
this.date = date; |
|||
} |
|||
|
|||
public String getType() |
|||
{ |
|||
return type; |
|||
} |
|||
|
|||
public void setType(String type) |
|||
{ |
|||
this.type = type; |
|||
} |
|||
|
|||
@Override |
|||
public String toString() { |
|||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) |
|||
.append("name", getName()) |
|||
.append("weight", getWeight()) |
|||
.append("price", getPrice()) |
|||
.append("date", getDate()) |
|||
.append("type", getType()) |
|||
.toString(); |
|||
} |
|||
} |
@ -0,0 +1,149 @@ |
|||
package com.win.web.controller.demo.domain; |
|||
|
|||
import java.util.Date; |
|||
import com.win.common.annotation.Excel; |
|||
import com.win.common.annotation.Excel.Type; |
|||
import com.win.common.core.domain.BaseEntity; |
|||
import com.win.common.utils.DateUtils; |
|||
|
|||
public class UserOperateModel extends BaseEntity |
|||
{ |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
private int userId; |
|||
|
|||
@Excel(name = "用户编号") |
|||
private String userCode; |
|||
|
|||
@Excel(name = "用户姓名") |
|||
private String userName; |
|||
|
|||
@Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") |
|||
private String userSex; |
|||
|
|||
@Excel(name = "用户手机") |
|||
private String userPhone; |
|||
|
|||
@Excel(name = "用户邮箱") |
|||
private String userEmail; |
|||
|
|||
@Excel(name = "用户余额") |
|||
private double userBalance; |
|||
|
|||
@Excel(name = "用户状态", readConverterExp = "0=正常,1=停用") |
|||
private String status; |
|||
|
|||
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) |
|||
private Date createTime; |
|||
|
|||
public UserOperateModel() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public UserOperateModel(int userId, String userCode, String userName, String userSex, String userPhone, |
|||
String userEmail, double userBalance, String status) |
|||
{ |
|||
this.userId = userId; |
|||
this.userCode = userCode; |
|||
this.userName = userName; |
|||
this.userSex = userSex; |
|||
this.userPhone = userPhone; |
|||
this.userEmail = userEmail; |
|||
this.userBalance = userBalance; |
|||
this.status = status; |
|||
this.createTime = DateUtils.getNowDate(); |
|||
} |
|||
|
|||
public int getUserId() |
|||
{ |
|||
return userId; |
|||
} |
|||
|
|||
public void setUserId(int userId) |
|||
{ |
|||
this.userId = userId; |
|||
} |
|||
|
|||
public String getUserCode() |
|||
{ |
|||
return userCode; |
|||
} |
|||
|
|||
public void setUserCode(String userCode) |
|||
{ |
|||
this.userCode = userCode; |
|||
} |
|||
|
|||
public String getUserName() |
|||
{ |
|||
return userName; |
|||
} |
|||
|
|||
public void setUserName(String userName) |
|||
{ |
|||
this.userName = userName; |
|||
} |
|||
|
|||
public String getUserSex() |
|||
{ |
|||
return userSex; |
|||
} |
|||
|
|||
public void setUserSex(String userSex) |
|||
{ |
|||
this.userSex = userSex; |
|||
} |
|||
|
|||
public String getUserPhone() |
|||
{ |
|||
return userPhone; |
|||
} |
|||
|
|||
public void setUserPhone(String userPhone) |
|||
{ |
|||
this.userPhone = userPhone; |
|||
} |
|||
|
|||
public String getUserEmail() |
|||
{ |
|||
return userEmail; |
|||
} |
|||
|
|||
public void setUserEmail(String userEmail) |
|||
{ |
|||
this.userEmail = userEmail; |
|||
} |
|||
|
|||
public double getUserBalance() |
|||
{ |
|||
return userBalance; |
|||
} |
|||
|
|||
public void setUserBalance(double userBalance) |
|||
{ |
|||
this.userBalance = userBalance; |
|||
} |
|||
|
|||
public String getStatus() |
|||
{ |
|||
return status; |
|||
} |
|||
|
|||
public void setStatus(String status) |
|||
{ |
|||
this.status = status; |
|||
} |
|||
|
|||
@Override |
|||
public Date getCreateTime() |
|||
{ |
|||
return createTime; |
|||
} |
|||
|
|||
@Override |
|||
public void setCreateTime(Date createTime) |
|||
{ |
|||
this.createTime = createTime; |
|||
} |
|||
} |
@ -0,0 +1,90 @@ |
|||
package com.win.web.controller.monitor; |
|||
|
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
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.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.framework.web.service.CacheService; |
|||
|
|||
/** |
|||
* 缓存监控 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/monitor/cache") |
|||
public class CacheController extends BaseController |
|||
{ |
|||
private String prefix = "monitor/cache"; |
|||
|
|||
@Autowired |
|||
private CacheService cacheService; |
|||
|
|||
@RequiresPermissions("monitor:cache:view") |
|||
@GetMapping() |
|||
public String cache(ModelMap mmap) |
|||
{ |
|||
mmap.put("cacheNames", cacheService.getCacheNames()); |
|||
return prefix + "/cache"; |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:cache:view") |
|||
@PostMapping("/getNames") |
|||
public String getCacheNames(String fragment, ModelMap mmap) |
|||
{ |
|||
mmap.put("cacheNames", cacheService.getCacheNames()); |
|||
return prefix + "/cache::" + fragment; |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:cache:view") |
|||
@PostMapping("/getKeys") |
|||
public String getCacheKeys(String fragment, String cacheName, ModelMap mmap) |
|||
{ |
|||
mmap.put("cacheName", cacheName); |
|||
mmap.put("cacheKeys", cacheService.getCacheKeys(cacheName)); |
|||
return prefix + "/cache::" + fragment; |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:cache:view") |
|||
@PostMapping("/getValue") |
|||
public String getCacheValue(String fragment, String cacheName, String cacheKey, ModelMap mmap) |
|||
{ |
|||
mmap.put("cacheName", cacheName); |
|||
mmap.put("cacheKey", cacheKey); |
|||
mmap.put("cacheValue", cacheService.getCacheValue(cacheName, cacheKey)); |
|||
return prefix + "/cache::" + fragment; |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:cache:view") |
|||
@PostMapping("/clearCacheName") |
|||
@ResponseBody |
|||
public AjaxResult clearCacheName(String cacheName, ModelMap mmap) |
|||
{ |
|||
cacheService.clearCacheName(cacheName); |
|||
return AjaxResult.success(); |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:cache:view") |
|||
@PostMapping("/clearCacheKey") |
|||
@ResponseBody |
|||
public AjaxResult clearCacheKey(String cacheName, String cacheKey, ModelMap mmap) |
|||
{ |
|||
cacheService.clearCacheKey(cacheName, cacheKey); |
|||
return AjaxResult.success(); |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:cache:view") |
|||
@GetMapping("/clearAll") |
|||
@ResponseBody |
|||
public AjaxResult clearAll(ModelMap mmap) |
|||
{ |
|||
cacheService.clearAll(); |
|||
return AjaxResult.success(); |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
package com.win.web.controller.monitor; |
|||
|
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import com.win.common.core.controller.BaseController; |
|||
|
|||
/** |
|||
* druid 监控 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/monitor/data") |
|||
public class DruidController extends BaseController |
|||
{ |
|||
private String prefix = "/druid"; |
|||
|
|||
@RequiresPermissions("monitor:data:view") |
|||
@GetMapping() |
|||
public String index() |
|||
{ |
|||
return redirect(prefix + "/index.html"); |
|||
} |
|||
} |
@ -0,0 +1,31 @@ |
|||
package com.win.web.controller.monitor; |
|||
|
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.framework.web.domain.Server; |
|||
|
|||
/** |
|||
* 服务器监控 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/monitor/server") |
|||
public class ServerController extends BaseController |
|||
{ |
|||
private String prefix = "monitor/server"; |
|||
|
|||
@RequiresPermissions("monitor:server:view") |
|||
@GetMapping() |
|||
public String server(ModelMap mmap) throws Exception |
|||
{ |
|||
Server server = new Server(); |
|||
server.copyTo(); |
|||
mmap.put("server", server); |
|||
return prefix + "/server"; |
|||
} |
|||
} |
@ -0,0 +1,94 @@ |
|||
package com.win.web.controller.monitor; |
|||
|
|||
import java.util.List; |
|||
import com.win.framework.shiro.service.SysPasswordService; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.system.domain.SysLogininfor; |
|||
import com.win.system.service.ISysLogininforService; |
|||
|
|||
/** |
|||
* 系统访问记录 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/monitor/logininfor") |
|||
public class SysLogininforController extends BaseController |
|||
{ |
|||
private String prefix = "monitor/logininfor"; |
|||
|
|||
@Autowired |
|||
private ISysLogininforService logininforService; |
|||
|
|||
@Autowired |
|||
private SysPasswordService passwordService; |
|||
|
|||
@RequiresPermissions("monitor:logininfor:view") |
|||
@GetMapping() |
|||
public String logininfor() |
|||
{ |
|||
return prefix + "/logininfor"; |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:logininfor:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysLogininfor logininfor) |
|||
{ |
|||
startPage(); |
|||
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@Log(title = "登录日志", businessType = BusinessType.EXPORT) |
|||
@RequiresPermissions("monitor:logininfor:export") |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(SysLogininfor logininfor) |
|||
{ |
|||
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor); |
|||
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class); |
|||
return util.exportExcel(list, "登录日志"); |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:logininfor:remove") |
|||
@Log(title = "登录日志", businessType = BusinessType.DELETE) |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
return toAjax(logininforService.deleteLogininforByIds(ids)); |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:logininfor:remove") |
|||
@Log(title = "登录日志", businessType = BusinessType.CLEAN) |
|||
@PostMapping("/clean") |
|||
@ResponseBody |
|||
public AjaxResult clean() |
|||
{ |
|||
logininforService.cleanLogininfor(); |
|||
return success(); |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:logininfor:unlock") |
|||
@Log(title = "账户解锁", businessType = BusinessType.OTHER) |
|||
@PostMapping("/unlock") |
|||
@ResponseBody |
|||
public AjaxResult unlock(String loginName) |
|||
{ |
|||
passwordService.clearLoginRecordCache(loginName); |
|||
return success(); |
|||
} |
|||
} |
@ -0,0 +1,90 @@ |
|||
package com.win.web.controller.monitor; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.system.domain.SysOperLog; |
|||
import com.win.system.service.ISysOperLogService; |
|||
|
|||
/** |
|||
* 操作日志记录 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/monitor/operlog") |
|||
public class SysOperlogController extends BaseController |
|||
{ |
|||
private String prefix = "monitor/operlog"; |
|||
|
|||
@Autowired |
|||
private ISysOperLogService operLogService; |
|||
|
|||
@RequiresPermissions("monitor:operlog:view") |
|||
@GetMapping() |
|||
public String operlog() |
|||
{ |
|||
return prefix + "/operlog"; |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:operlog:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysOperLog operLog) |
|||
{ |
|||
startPage(); |
|||
List<SysOperLog> list = operLogService.selectOperLogList(operLog); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@Log(title = "操作日志", businessType = BusinessType.EXPORT) |
|||
@RequiresPermissions("monitor:operlog:export") |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(SysOperLog operLog) |
|||
{ |
|||
List<SysOperLog> list = operLogService.selectOperLogList(operLog); |
|||
ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class); |
|||
return util.exportExcel(list, "操作日志"); |
|||
} |
|||
|
|||
@Log(title = "操作日志", businessType = BusinessType.DELETE) |
|||
@RequiresPermissions("monitor:operlog:remove") |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
return toAjax(operLogService.deleteOperLogByIds(ids)); |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:operlog:detail") |
|||
@GetMapping("/detail/{operId}") |
|||
public String detail(@PathVariable("operId") Long operId, ModelMap mmap) |
|||
{ |
|||
mmap.put("operLog", operLogService.selectOperLogById(operId)); |
|||
return prefix + "/detail"; |
|||
} |
|||
|
|||
@Log(title = "操作日志", businessType = BusinessType.CLEAN) |
|||
@RequiresPermissions("monitor:operlog:remove") |
|||
@PostMapping("/clean") |
|||
@ResponseBody |
|||
public AjaxResult clean() |
|||
{ |
|||
operLogService.cleanOperLog(); |
|||
return success(); |
|||
} |
|||
} |
@ -0,0 +1,88 @@ |
|||
package com.win.web.controller.monitor; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.Logical; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.core.text.Convert; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.enums.OnlineStatus; |
|||
import com.win.common.utils.ShiroUtils; |
|||
import com.win.framework.shiro.session.OnlineSession; |
|||
import com.win.framework.shiro.session.OnlineSessionDAO; |
|||
import com.win.system.domain.SysUserOnline; |
|||
import com.win.system.service.ISysUserOnlineService; |
|||
|
|||
/** |
|||
* 在线用户监控 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/monitor/online") |
|||
public class SysUserOnlineController extends BaseController |
|||
{ |
|||
private String prefix = "monitor/online"; |
|||
|
|||
@Autowired |
|||
private ISysUserOnlineService userOnlineService; |
|||
|
|||
@Autowired |
|||
private OnlineSessionDAO onlineSessionDAO; |
|||
|
|||
@RequiresPermissions("monitor:online:view") |
|||
@GetMapping() |
|||
public String online() |
|||
{ |
|||
return prefix + "/online"; |
|||
} |
|||
|
|||
@RequiresPermissions("monitor:online:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysUserOnline userOnline) |
|||
{ |
|||
startPage(); |
|||
List<SysUserOnline> list = userOnlineService.selectUserOnlineList(userOnline); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@RequiresPermissions(value = { "monitor:online:batchForceLogout", "monitor:online:forceLogout" }, logical = Logical.OR) |
|||
@Log(title = "在线用户", businessType = BusinessType.FORCE) |
|||
@PostMapping("/batchForceLogout") |
|||
@ResponseBody |
|||
public AjaxResult batchForceLogout(String ids) |
|||
{ |
|||
for (String sessionId : Convert.toStrArray(ids)) |
|||
{ |
|||
SysUserOnline online = userOnlineService.selectOnlineById(sessionId); |
|||
if (online == null) |
|||
{ |
|||
return error("用户已下线"); |
|||
} |
|||
OnlineSession onlineSession = (OnlineSession) onlineSessionDAO.readSession(online.getSessionId()); |
|||
if (onlineSession == null) |
|||
{ |
|||
return error("用户已下线"); |
|||
} |
|||
if (sessionId.equals(ShiroUtils.getSessionId())) |
|||
{ |
|||
return error("当前登录用户无法强退"); |
|||
} |
|||
onlineSessionDAO.delete(onlineSession); |
|||
online.setStatus(OnlineStatus.off_line); |
|||
userOnlineService.saveOnline(online); |
|||
userOnlineService.removeUserCache(online.getLoginName(), sessionId); |
|||
} |
|||
return success(); |
|||
} |
|||
} |
@ -0,0 +1,295 @@ |
|||
package com.win.web.controller.print; |
|||
|
|||
|
|||
import cn.hutool.core.collection.CollUtil; |
|||
import cn.hutool.core.date.DateException; |
|||
import cn.hutool.core.date.DateUtil; |
|||
import cn.hutool.core.io.FileUtil; |
|||
import cn.hutool.core.util.IdUtil; |
|||
import cn.hutool.core.util.ObjectUtil; |
|||
import cn.hutool.core.util.StrUtil; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.itextpdf.kernel.geom.PageSize; |
|||
import com.itextpdf.kernel.pdf.PdfDocument; |
|||
import com.itextpdf.kernel.pdf.PdfReader; |
|||
import com.itextpdf.kernel.pdf.PdfWriter; |
|||
import com.itextpdf.kernel.utils.PdfMerger; |
|||
import com.win.common.config.WinConfig; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.utils.ServletUtils; |
|||
import com.win.common.utils.file.FileUtils; |
|||
import com.win.print.domain.PrintModelDataVo; |
|||
import com.win.print.domain.WinPrintModel; |
|||
import com.win.print.domain.WinPrintModelParams; |
|||
import com.win.print.domain.WinPrintTasksLogs; |
|||
import com.win.print.service.*; |
|||
import com.win.print.util.DataUnitl; |
|||
import com.win.print.util.HTMLConvertUitl; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import jakarta.annotation.Resource; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import org.slf4j.Logger; |
|||
import org.slf4j.LoggerFactory; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.http.MediaType; |
|||
import org.springframework.web.bind.annotation.*; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import java.io.File; |
|||
import java.io.IOException; |
|||
import java.util.*; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
|
|||
/** |
|||
* 客户端打印服务接口 |
|||
*/ |
|||
@Tag(name = "打印服务") |
|||
@RestController |
|||
@RequestMapping("/service/print") |
|||
public class WinPrintServerControler extends BaseController { |
|||
private static final Logger log = LoggerFactory.getLogger(WinPrintServerControler.class); |
|||
private String prefix = "/service/print"; |
|||
@Value("${win.path.template}") |
|||
private String templatePathDefault; //打印模版的存储路径
|
|||
@Value("${win.path.print}") |
|||
private String printFilepath; //生成的打印文件存储路径
|
|||
@Resource |
|||
QRCodeService qrCodeService; |
|||
@Resource |
|||
IWinPrintClientinfoService winPrintClientinfoService; |
|||
@Resource |
|||
IWinPrintModelService winPrintModelService;//模版配置
|
|||
@Resource |
|||
PrintTaskService printTaskService; |
|||
@Resource |
|||
IWinPrintTasksLogsService iPrintTasksLogsService; |
|||
|
|||
@PostMapping("/model") |
|||
@Operation(summary = "模版打印接口,服务调用只处理模版并生成pdf文件!") |
|||
public AjaxResult getclientPdf(@RequestBody PrintModelDataVo dataVo) { |
|||
if (ObjectUtil.isEmpty(dataVo)) { |
|||
return AjaxResult.error("打印失败!空的数据内容!"); |
|||
} |
|||
String fileServer ="http://"+ServletUtils.getRequest().getServerName()+":"+ServletUtils.getRequest().getServerPort()+prefix+"/file";//当前接收打印的服务器URL
|
|||
String modelCode = dataVo.getModelCode(); |
|||
String clientCode = dataVo.getClientCode(); |
|||
String printerName=dataVo.getPrinterName(); |
|||
if (StrUtil.isEmpty(clientCode)) { |
|||
return AjaxResult.error("打印失败!未指定打印客户端!"); |
|||
} |
|||
if (StrUtil.isEmpty(modelCode)) { |
|||
return AjaxResult.error("打印失败!未指定模版!"); |
|||
} |
|||
if (StrUtil.isEmpty(printerName)) { |
|||
return AjaxResult.error("打印失败!未指定打印机!"); |
|||
} |
|||
String requestType=Optional.ofNullable(dataVo.getPrintType()).orElse("normal"); |
|||
Integer copyCounts = Optional.ofNullable(dataVo.getCopyCount()).orElse(1); |
|||
WinPrintModel winPrintModel = winPrintModelService.selectWinPrintModelByCode(modelCode); |
|||
if (ObjectUtil.isEmpty(winPrintModel)) { |
|||
return AjaxResult.error("打印失败!未找到指定模版!"); |
|||
} |
|||
//处理模版文件来源
|
|||
String modelName = winPrintModel.getmFilename(); |
|||
String modelType = winPrintModel.getmType(); |
|||
String modelTypeSrc = winPrintModel.getmTypeSrc(); |
|||
String taskId=Optional.ofNullable(dataVo.getTaskId()).orElse(IdUtil.fastSimpleUUID()); |
|||
String modelPage=winPrintModel.getmPageSize(); |
|||
String isPageRolated=winPrintModel.getIsPageRotate(); |
|||
Date printeDate=null; |
|||
try{ |
|||
printeDate = DateUtil.parse(dataVo.getPrintDate()); //转换时间
|
|||
}catch (DateException dateEx){ |
|||
printeDate=null; |
|||
} |
|||
if(null==printeDate){ |
|||
printeDate=DateUtil.date(); |
|||
} |
|||
if ("STRING".equalsIgnoreCase(modelTypeSrc)){ |
|||
modelName=winPrintModel.getmData(); |
|||
} |
|||
//获取模版纸张类型
|
|||
//log.info();
|
|||
PageSize pageSize = DataUnitl.GetPageSize(modelPage, winPrintModel.getmPageValue(), isPageRolated); |
|||
//生成打印任务文件
|
|||
String pdfDir = DataUnitl.getWorkingDir(printFilepath); |
|||
String templateDir = DataUnitl.getWorkingDir(templatePathDefault); |
|||
if ("PDF".equalsIgnoreCase(modelType)) { |
|||
//渲染打印模版
|
|||
return AjaxResult.error("暂时不支持PDF模版打印!"); |
|||
} |
|||
//获取参数和值-不给值默认空,数据为数组,数组大小为1时调用单页处理,数组大于1时
|
|||
List<WinPrintModelParams> winPrintModelParamsList = winPrintModel.getWinPrintModelParamsList(); |
|||
List<JSONObject> printData = dataVo.getPrintData(); |
|||
if (CollUtil.isNotEmpty(printData)) { |
|||
String pdfPath = pdfDir + "/" ; |
|||
if ("1".equals(dataVo.getDocModel())) { //单文单件务打印
|
|||
String fileName= clientCode + "_" + modelCode + "_"+String.valueOf(System.currentTimeMillis()) + ".pdf"; |
|||
printMutilPage(winPrintModelParamsList, printData, modelName, pageSize, pdfPath +fileName, modelTypeSrc, templateDir); |
|||
//printTaskService.putTaskToQueue(info, DateUtil.now(),fileName,remoteAddr,"model",winPrintModel.getmPageSize(),winPrintModel.getmPageRotate(),1);
|
|||
createTaskLog(clientCode,fileName,taskId,"model",modelCode,printerName, requestType,copyCounts, modelPage, isPageRolated, "",printeDate, fileServer); |
|||
} else { |
|||
AtomicInteger fileCount = new AtomicInteger(1); |
|||
String finalModelName = modelName; |
|||
Date finalPrinteDate = printeDate; |
|||
printData.forEach(pdata -> { |
|||
Map<String, String> modelData = new HashMap<>(); |
|||
winPrintModelParamsList.forEach(item -> { |
|||
if ("QRIMG".equalsIgnoreCase(item.getParamType())) { |
|||
String mg = qrCodeService.getBase64QRCodeSrc(pdata.getString(item.getParamCode()), 172, 172, "png"); |
|||
modelData.put(item.getParamCode(), Optional.ofNullable(mg).orElse("")); |
|||
} else { |
|||
modelData.put(item.getParamCode(), Optional.ofNullable(pdata.getString(item.getParamCode())).orElse("")); |
|||
} |
|||
|
|||
}); |
|||
String pdfFileName = clientCode + "_" + modelCode + "_"+ String.valueOf(fileCount.getAndIncrement()) + "_" + String.valueOf(System.currentTimeMillis()) + ".pdf"; |
|||
File file = new File(pdfPath+pdfFileName); |
|||
printOneByOne(file, modelType, modelData, pageSize, finalModelName, modelTypeSrc, templateDir); |
|||
createTaskLog(clientCode,pdfFileName,taskId,"model",modelCode,printerName, requestType,copyCounts, modelPage, isPageRolated, "", finalPrinteDate,fileServer); |
|||
}); |
|||
|
|||
} |
|||
|
|||
} else { |
|||
return AjaxResult.error("打印数据为空!不能完成打印!"); |
|||
} |
|||
return AjaxResult.success("打印任务已发送,等待打印机处理!"); |
|||
// }else{
|
|||
// return AjaxResult.error("安全验证不通过,不能完成打印请求,请联系管理员!");
|
|||
// }
|
|||
|
|||
} |
|||
|
|||
/** |
|||
* 接收文件打印,不限格式 |
|||
* */ |
|||
@PostMapping("/doc") |
|||
@ResponseBody |
|||
public AjaxResult printDoc(MultipartFile file, String clientCode,String printerName,String printType,String printTime,Integer copyCounts) throws Exception |
|||
{ |
|||
if (StrUtil.isEmpty(clientCode)) { |
|||
return AjaxResult.error("打印失败!未指定打印客户端!"); |
|||
} |
|||
if (StrUtil.isEmpty(printerName)) { |
|||
return AjaxResult.error("打印失败!未指定打印机!"); |
|||
} |
|||
if (file.isEmpty()) { |
|||
return AjaxResult.error("打印失败!不能打印空文件!"); |
|||
} |
|||
String fileServer ="http://"+ServletUtils.getRequest().getServerName()+":"+ServletUtils.getRequest().getServerPort()+prefix+"/file";//当前接收打印的服务器URL
|
|||
String workingDir = DataUnitl.getWorkingDir(printFilepath); |
|||
String fileName=clientCode+"_doc_"+file.getOriginalFilename(); |
|||
FileUtil.writeFromStream(file.getInputStream(), workingDir + "/" + fileName); |
|||
Date printTime_n=null; |
|||
try{ |
|||
printTime_n = DateUtil.parse(printTime); //转换时间
|
|||
}catch (DateException dateEx){ |
|||
printTime_n=null; |
|||
} |
|||
if(null==printTime_n){ |
|||
printTime_n=DateUtil.date(); |
|||
} |
|||
String taskId=IdUtil.fastSimpleUUID(); |
|||
String printType_n = Optional.ofNullable(printType).orElse("doc"); |
|||
Integer copyCounts_n=Optional.ofNullable(copyCounts).orElse(1); |
|||
createTaskLog(clientCode,fileName,taskId,printType_n,"file_model",printerName, "doc",copyCounts,String.valueOf(copyCounts_n) , "N", "", printTime_n,fileServer); |
|||
return AjaxResult.error("打印任务已发送,等待打印机处理!"); |
|||
} |
|||
/** |
|||
* 获取打印文件预览 |
|||
* */ |
|||
@GetMapping("/file/{name}") |
|||
public void pdfview(@PathVariable("name") String fileName, HttpServletResponse response) { |
|||
try |
|||
{ |
|||
String pdfDir = DataUnitl.getWorkingDir(printFilepath)+"/"; |
|||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); |
|||
FileUtils.setAttachmentResponseHeader(response, fileName); |
|||
FileUtils.writeBytes(pdfDir+fileName, response.getOutputStream()); |
|||
|
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
e.printStackTrace(); |
|||
}; |
|||
} |
|||
|
|||
/** |
|||
* 单页打印 |
|||
*/ |
|||
private void printOneByOne(File pdfFileName, String modeType, Map<String, String> data, PageSize pageSize, String modelName, String modeTypeSrc, String templatePath) { |
|||
try { |
|||
if ("PDF".equalsIgnoreCase(modeType)) { |
|||
log.info("处理PDF模版"); |
|||
} else if ("freemarker".equalsIgnoreCase(modeType)) { |
|||
log.info("处理freemarker模版"); |
|||
} else { |
|||
log.info("thymeleaf"); |
|||
HTMLConvertUitl.html2Pdf_thymeleaf(pdfFileName, data, pageSize, modelName, modeTypeSrc, templatePath); |
|||
} |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
log.error("printOneByOne-error", e.toString()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 多以合并 |
|||
*/ |
|||
private void printMutilPage(List<WinPrintModelParams> paramList, List<JSONObject> dataList, String modelName, PageSize pageSize, String fileName, String modeTypeSrc, String templatePath) { |
|||
try { |
|||
PdfDocument destDoc = new PdfDocument(new PdfWriter(fileName)); |
|||
destDoc.setDefaultPageSize(pageSize); |
|||
PdfMerger pdfMerger = new PdfMerger(destDoc); |
|||
dataList.forEach(pdata -> { |
|||
try { |
|||
Map<String, String> modelData = new HashMap<>(); |
|||
paramList.forEach(item -> { |
|||
if ("QRIMG".equalsIgnoreCase(item.getParamType())) { |
|||
String mg = qrCodeService.getBase64QRCodeSrc(pdata.getString(item.getParamCode()), 172, 172, "png"); |
|||
modelData.put(item.getParamCode(), Optional.ofNullable(mg).orElse("")); |
|||
} else { |
|||
modelData.put(item.getParamCode(), Optional.ofNullable(pdata.getString(item.getParamCode())).orElse("")); |
|||
} |
|||
}); |
|||
File tempFile = File.createTempFile("temp_" + String.valueOf(System.currentTimeMillis()), ".pdf"); |
|||
HTMLConvertUitl.html2Pdf_thymeleaf(tempFile, modelData, pageSize, modelName, modeTypeSrc, templatePath); |
|||
PdfDocument sourcePdf = new PdfDocument(new PdfReader(tempFile)); |
|||
pdfMerger.merge(sourcePdf, 1, sourcePdf.getNumberOfPages()); |
|||
sourcePdf.close(); |
|||
tempFile.delete(); |
|||
} catch (IOException e) { |
|||
throw new RuntimeException(e); |
|||
} |
|||
}); |
|||
pdfMerger.close(); |
|||
} catch (IOException e) { |
|||
e.printStackTrace(); |
|||
log.error("printMutilPage-error", e.toString()); |
|||
} |
|||
} |
|||
private void createTaskLog(String clientCode, String fileName, String taskId, String printType, String modelCode, String printerName, String requestType, Integer copyCounts, String modelPage, String isPageRolated, String remark, Date printTime,String fileServer){ |
|||
WinPrintTasksLogs logs=new WinPrintTasksLogs(); |
|||
logs.setClientCode(clientCode); |
|||
logs.setTaskId(Optional.ofNullable(taskId).orElse(IdUtil.fastSimpleUUID())); |
|||
logs.setCreatedBy(WinConfig.getClientCode()); |
|||
logs.setCreatedTime(DateUtil.date()); |
|||
logs.setDataFile(fileName); |
|||
logs.setIpAddr(fileServer); |
|||
logs.setPrintType(printType); |
|||
logs.setModelCode(modelCode); |
|||
logs.setPrinterName(printerName); |
|||
logs.setRequestType(requestType); |
|||
logs.setTaskStatus("0"); |
|||
logs.setSettingCode(""); |
|||
logs.setCopyCounts(copyCounts); |
|||
logs.setModelPage(modelPage); |
|||
logs.setIsPageRolated(isPageRolated); |
|||
logs.setRemark(remark); |
|||
logs.setPrintTime(printTime); |
|||
iPrintTasksLogsService.insertWinPrintTasksLogs(logs); |
|||
} |
|||
} |
@ -0,0 +1,197 @@ |
|||
package com.win.web.controller.print; |
|||
|
|||
|
|||
import cn.hutool.core.collection.CollUtil; |
|||
import cn.hutool.core.io.FileUtil; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.itextpdf.kernel.geom.PageSize; |
|||
import com.itextpdf.kernel.pdf.PdfDocument; |
|||
import com.itextpdf.kernel.pdf.PdfReader; |
|||
import com.itextpdf.kernel.pdf.PdfWriter; |
|||
import com.itextpdf.kernel.utils.PdfMerger; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.print.domain.ClientPrintTaskVo; |
|||
import com.win.print.domain.EnumDocFlavor; |
|||
import com.win.print.domain.PrintRequestAttributeVo; |
|||
import com.win.print.service.QRCodeService; |
|||
import com.win.print.util.HTMLConvertUitl; |
|||
import com.win.print.util.PrinterUtil; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import jakarta.annotation.Resource; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import javax.print.DocFlavor; |
|||
import javax.print.DocPrintJob; |
|||
import javax.print.PrintException; |
|||
import javax.print.attribute.PrintRequestAttributeSet; |
|||
import javax.print.attribute.standard.MediaSize; |
|||
import java.io.File; |
|||
import java.io.FileInputStream; |
|||
import java.io.FileOutputStream; |
|||
import java.io.IOException; |
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
import java.util.concurrent.atomic.AtomicInteger; |
|||
|
|||
@Tag(name = "用户信息管理") |
|||
@RestController |
|||
@RequestMapping("/service/test") |
|||
public class WinPrintServerControlerTest extends BaseController { |
|||
private String prefix = "/service/test"; |
|||
@Value("${win.path.template}") |
|||
private String templatePath; |
|||
@Value("${win.path.print}") |
|||
private String printFilepath; |
|||
@Resource |
|||
QRCodeService qrCodeService; |
|||
@GetMapping("/pdf") |
|||
@Operation(summary = "生成模版的PDf文件") |
|||
public AjaxResult getclientPdf(@RequestParam("clientCode") String clientCode, @RequestParam("clientPwd") String clientPwd) throws IOException { |
|||
String token="html2PdfPage"; |
|||
PageSize pageSize = PageSize.A5.rotate(); |
|||
//生成打印任务文件
|
|||
//HTMLConvertUitl.html2PdfPage(null,HTMLConvertUitl.testData(),"supplier.html",pageSize);
|
|||
return AjaxResult.success(token); |
|||
} |
|||
@GetMapping("/qrcode") |
|||
@Operation(summary = "获取") |
|||
public AjaxResult getQrcode() throws IOException { |
|||
String content = "@RequestParam(\"data\") JSONObject data, @RequestParam(\"modelCode\") String modelCode"; |
|||
String property = System.getProperty("user.dir"); |
|||
String fileType="jpeg"; |
|||
String imageFile=property+"/"+String.valueOf(System.currentTimeMillis())+".jpeg"; |
|||
qrCodeService.getImageFile(content,200,200,imageFile,fileType); |
|||
return AjaxResult.success(imageFile); |
|||
} |
|||
|
|||
/** |
|||
* ,@RequestParam("data") JSONObject data, |
|||
* @RequestParam("modelCode") String modelCode*/ |
|||
@GetMapping("/print/file") |
|||
@Operation(summary = "打印文件") |
|||
public void printFile(HttpServletResponse response) throws IOException, PrintException { |
|||
PrintRequestAttributeVo vo= new PrintRequestAttributeVo(); |
|||
vo.setIsPortrait(false); |
|||
vo.setPaperType(MediaSize.ISO.A5); |
|||
vo.setIsPortrait(true); |
|||
for(int i=0;i<100;i++){ |
|||
print(vo,null); |
|||
} |
|||
|
|||
} |
|||
@GetMapping("/print/single") |
|||
@Operation(summary = "打印文件") |
|||
public AjaxResult printSingle(HttpServletResponse response) throws IOException, PrintException { |
|||
PrintRequestAttributeVo vo= new PrintRequestAttributeVo(); |
|||
vo.setIsPortrait(false); |
|||
vo.setPaperType(MediaSize.ISO.A5); |
|||
vo.setIsPortrait(true); |
|||
List<JSONObject> dataList=new ArrayList<>(); |
|||
for(int i=0;i<100;i++){ |
|||
JSONObject jb=new JSONObject(); |
|||
dataList.add(jb); |
|||
} |
|||
|
|||
printMutilPage(dataList,null,"test_001"); |
|||
return AjaxResult.success("打印任务处理完成!等待打印!"); |
|||
} |
|||
@PostMapping("/print/pda") |
|||
@Operation(summary = "打印数据请求打印") |
|||
@ResponseBody |
|||
public AjaxResult printImage(HttpServletResponse response, |
|||
@RequestParam("dataList") List<JSONObject> dataList, |
|||
@RequestParam("modelCode") String modelCode ) |
|||
{ |
|||
if(CollUtil.isNotEmpty(dataList)){ |
|||
PrintRequestAttributeVo vo= new PrintRequestAttributeVo(); |
|||
vo.setPaperType(MediaSize.ISO.A5); |
|||
vo.setIsPortrait(true); |
|||
dataList.forEach(item->{ |
|||
print(vo,null); |
|||
}); |
|||
return AjaxResult.success("数据已经发送打印!请注意查看!"); |
|||
}else{ |
|||
return AjaxResult.error("打印数据为空!不能打印!"); |
|||
} |
|||
|
|||
} |
|||
private void print(PrintRequestAttributeVo vo,String printerName){ |
|||
try { |
|||
// 创建临时文件
|
|||
File tempFile = File.createTempFile("temp_"+String.valueOf(System.currentTimeMillis()), ".pdf"); |
|||
FileOutputStream fileOutputStream = new FileOutputStream(tempFile); |
|||
System.out.println("Temporary file created: " + tempFile.getAbsolutePath()); |
|||
HTMLConvertUitl.html2PdfStream(templatePath,fileOutputStream,HTMLConvertUitl.testData(),"FILE","supplier.html"); |
|||
putJob(tempFile.getAbsolutePath(),printerName,vo); |
|||
// 使用完毕后删除临时文件
|
|||
tempFile.delete(); //删除临时文件
|
|||
//tempFile.deleteOnExit();// 文件将在 JVM 结束时被删除
|
|||
} catch (IOException | PrintException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
|
|||
private void printMutilPage(List<JSONObject> dataList,String printerName,String clientName){ |
|||
try { |
|||
// 创建临时文件
|
|||
String property = System.getProperty("user.dir"); |
|||
String fileTarget=property+"/"+clientName+"_"+String.valueOf(System.currentTimeMillis())+".pdf"; |
|||
PdfDocument destDoc = new PdfDocument(new PdfWriter(fileTarget)); |
|||
PageSize pageSize = PageSize.A5.rotate(); //横向生成
|
|||
destDoc.setDefaultPageSize(pageSize); |
|||
PdfMerger pdfMerger=new PdfMerger(destDoc); |
|||
//pdfMerger.setCloseSourceDocuments(true);
|
|||
PrintRequestAttributeVo vo= new PrintRequestAttributeVo(); |
|||
vo.setPaperType(MediaSize.ISO.A5); |
|||
vo.setIsPortrait(true); |
|||
if(CollUtil.isNotEmpty(dataList)) { |
|||
AtomicInteger pageNumber = new AtomicInteger(1); |
|||
dataList.forEach(item-> { |
|||
String filename=""; |
|||
try { |
|||
///
|
|||
PdfDocument sourcePdf = new PdfDocument(new PdfReader(filename)); |
|||
pdfMerger.merge(sourcePdf,1,sourcePdf.getNumberOfPages()); |
|||
sourcePdf.close(); |
|||
|
|||
} catch (IOException e) { |
|||
throw new RuntimeException(e); |
|||
}finally { |
|||
FileUtil.del(filename); |
|||
} |
|||
|
|||
}); |
|||
//destDoc.close();
|
|||
pdfMerger.close(); |
|||
putJob(fileTarget,printerName,vo); |
|||
} |
|||
|
|||
//tempFile.deleteOnExit();// 文件将在 JVM 结束时被删除
|
|||
} catch (IOException | PrintException e) { |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
private void putJob(String fileName,String printerName,PrintRequestAttributeVo vo) throws PrintException, IOException { |
|||
FileInputStream fileIn = new FileInputStream(fileName); |
|||
DocPrintJob pringJobByName = PrinterUtil.getPringJobByName(printerName); |
|||
DocFlavor docFlavor = PrinterUtil.getDocFlavor(EnumDocFlavor.IS_AUTOSENSE); |
|||
PrintRequestAttributeSet printRequestAttribute = PrinterUtil.getPrintRequestAttribute(vo,"test"); |
|||
PrinterUtil.sendJobtoPrinter(pringJobByName, PrinterUtil.getSimpleDoc(fileIn, docFlavor), printRequestAttribute); |
|||
fileIn.close(); |
|||
} |
|||
/** |
|||
* |
|||
* */ |
|||
@PostMapping("/print/client") |
|||
@Operation(summary = "客户端打印") |
|||
@ResponseBody |
|||
public AjaxResult printClient(ClientPrintTaskVo taskVo) |
|||
{ |
|||
String token=""; |
|||
return AjaxResult.success(token); |
|||
} |
|||
} |
@ -0,0 +1,92 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.awt.image.BufferedImage; |
|||
import java.io.IOException; |
|||
import jakarta.annotation.Resource; |
|||
import javax.imageio.ImageIO; |
|||
import jakarta.servlet.ServletOutputStream; |
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import jakarta.servlet.http.HttpSession; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.servlet.ModelAndView; |
|||
import com.google.code.kaptcha.Constants; |
|||
import com.google.code.kaptcha.Producer; |
|||
import com.win.common.core.controller.BaseController; |
|||
|
|||
/** |
|||
* 图片验证码(支持算术形式) |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/captcha") |
|||
public class SysCaptchaController extends BaseController |
|||
{ |
|||
@Resource(name = "captchaProducer") |
|||
private Producer captchaProducer; |
|||
|
|||
@Resource(name = "captchaProducerMath") |
|||
private Producer captchaProducerMath; |
|||
|
|||
/** |
|||
* 验证码生成 |
|||
*/ |
|||
@GetMapping(value = "/captchaImage") |
|||
public ModelAndView getKaptchaImage(HttpServletRequest request, HttpServletResponse response) |
|||
{ |
|||
ServletOutputStream out = null; |
|||
try |
|||
{ |
|||
HttpSession session = request.getSession(); |
|||
response.setDateHeader("Expires", 0); |
|||
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); |
|||
response.addHeader("Cache-Control", "post-check=0, pre-check=0"); |
|||
response.setHeader("Pragma", "no-cache"); |
|||
response.setContentType("image/jpeg"); |
|||
|
|||
String type = request.getParameter("type"); |
|||
String capStr = null; |
|||
String code = null; |
|||
BufferedImage bi = null; |
|||
if ("math".equals(type)) |
|||
{ |
|||
String capText = captchaProducerMath.createText(); |
|||
capStr = capText.substring(0, capText.lastIndexOf("@")); |
|||
code = capText.substring(capText.lastIndexOf("@") + 1); |
|||
bi = captchaProducerMath.createImage(capStr); |
|||
} |
|||
else if ("char".equals(type)) |
|||
{ |
|||
capStr = code = captchaProducer.createText(); |
|||
bi = captchaProducer.createImage(capStr); |
|||
} |
|||
session.setAttribute(Constants.KAPTCHA_SESSION_KEY, code); |
|||
out = response.getOutputStream(); |
|||
ImageIO.write(bi, "jpg", out); |
|||
out.flush(); |
|||
|
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
e.printStackTrace(); |
|||
} |
|||
finally |
|||
{ |
|||
try |
|||
{ |
|||
if (out != null) |
|||
{ |
|||
out.close(); |
|||
} |
|||
} |
|||
catch (IOException e) |
|||
{ |
|||
e.printStackTrace(); |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
} |
@ -0,0 +1,157 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.system.domain.SysConfig; |
|||
import com.win.system.service.ISysConfigService; |
|||
|
|||
/** |
|||
* 参数配置 信息操作处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/config") |
|||
public class SysConfigController extends BaseController |
|||
{ |
|||
private String prefix = "system/config"; |
|||
|
|||
@Autowired |
|||
private ISysConfigService configService; |
|||
|
|||
@RequiresPermissions("system:config:view") |
|||
@GetMapping() |
|||
public String config() |
|||
{ |
|||
return prefix + "/config"; |
|||
} |
|||
|
|||
/** |
|||
* 查询参数配置列表 |
|||
*/ |
|||
@RequiresPermissions("system:config:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysConfig config) |
|||
{ |
|||
startPage(); |
|||
List<SysConfig> list = configService.selectConfigList(config); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@Log(title = "参数管理", businessType = BusinessType.EXPORT) |
|||
@RequiresPermissions("system:config:export") |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(SysConfig config) |
|||
{ |
|||
List<SysConfig> list = configService.selectConfigList(config); |
|||
ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class); |
|||
return util.exportExcel(list, "参数数据"); |
|||
} |
|||
|
|||
/** |
|||
* 新增参数配置 |
|||
*/ |
|||
@GetMapping("/add") |
|||
public String add() |
|||
{ |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存参数配置 |
|||
*/ |
|||
@RequiresPermissions("system:config:add") |
|||
@Log(title = "参数管理", businessType = BusinessType.INSERT) |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysConfig config) |
|||
{ |
|||
if (!configService.checkConfigKeyUnique(config)) |
|||
{ |
|||
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); |
|||
} |
|||
config.setCreateBy(getLoginName()); |
|||
return toAjax(configService.insertConfig(config)); |
|||
} |
|||
|
|||
/** |
|||
* 修改参数配置 |
|||
*/ |
|||
@RequiresPermissions("system:config:edit") |
|||
@GetMapping("/edit/{configId}") |
|||
public String edit(@PathVariable("configId") Long configId, ModelMap mmap) |
|||
{ |
|||
mmap.put("config", configService.selectConfigById(configId)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存参数配置 |
|||
*/ |
|||
@RequiresPermissions("system:config:edit") |
|||
@Log(title = "参数管理", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysConfig config) |
|||
{ |
|||
if (!configService.checkConfigKeyUnique(config)) |
|||
{ |
|||
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); |
|||
} |
|||
config.setUpdateBy(getLoginName()); |
|||
return toAjax(configService.updateConfig(config)); |
|||
} |
|||
|
|||
/** |
|||
* 删除参数配置 |
|||
*/ |
|||
@RequiresPermissions("system:config:remove") |
|||
@Log(title = "参数管理", businessType = BusinessType.DELETE) |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
configService.deleteConfigByIds(ids); |
|||
return success(); |
|||
} |
|||
|
|||
/** |
|||
* 刷新参数缓存 |
|||
*/ |
|||
@RequiresPermissions("system:config:remove") |
|||
@Log(title = "参数管理", businessType = BusinessType.CLEAN) |
|||
@GetMapping("/refreshCache") |
|||
@ResponseBody |
|||
public AjaxResult refreshCache() |
|||
{ |
|||
configService.resetConfigCache(); |
|||
return success(); |
|||
} |
|||
|
|||
/** |
|||
* 校验参数键名 |
|||
*/ |
|||
@PostMapping("/checkConfigKeyUnique") |
|||
@ResponseBody |
|||
public boolean checkConfigKeyUnique(SysConfig config) |
|||
{ |
|||
return configService.checkConfigKeyUnique(config); |
|||
} |
|||
} |
@ -0,0 +1,187 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.constant.UserConstants; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.Ztree; |
|||
import com.win.common.core.domain.entity.SysDept; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.StringUtils; |
|||
import com.win.system.service.ISysDeptService; |
|||
|
|||
/** |
|||
* 部门信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/dept") |
|||
public class SysDeptController extends BaseController |
|||
{ |
|||
private String prefix = "system/dept"; |
|||
|
|||
@Autowired |
|||
private ISysDeptService deptService; |
|||
|
|||
@RequiresPermissions("system:dept:view") |
|||
@GetMapping() |
|||
public String dept() |
|||
{ |
|||
return prefix + "/dept"; |
|||
} |
|||
|
|||
@RequiresPermissions("system:dept:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public List<SysDept> list(SysDept dept) |
|||
{ |
|||
List<SysDept> deptList = deptService.selectDeptList(dept); |
|||
return deptList; |
|||
} |
|||
|
|||
/** |
|||
* 新增部门 |
|||
*/ |
|||
@GetMapping("/add/{parentId}") |
|||
public String add(@PathVariable("parentId") Long parentId, ModelMap mmap) |
|||
{ |
|||
if (!getSysUser().isAdmin()) |
|||
{ |
|||
parentId = getSysUser().getDeptId(); |
|||
} |
|||
mmap.put("dept", deptService.selectDeptById(parentId)); |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存部门 |
|||
*/ |
|||
@Log(title = "部门管理", businessType = BusinessType.INSERT) |
|||
@RequiresPermissions("system:dept:add") |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysDept dept) |
|||
{ |
|||
if (!deptService.checkDeptNameUnique(dept)) |
|||
{ |
|||
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); |
|||
} |
|||
dept.setCreateBy(getLoginName()); |
|||
return toAjax(deptService.insertDept(dept)); |
|||
} |
|||
|
|||
/** |
|||
* 修改部门 |
|||
*/ |
|||
@RequiresPermissions("system:dept:edit") |
|||
@GetMapping("/edit/{deptId}") |
|||
public String edit(@PathVariable("deptId") Long deptId, ModelMap mmap) |
|||
{ |
|||
deptService.checkDeptDataScope(deptId); |
|||
SysDept dept = deptService.selectDeptById(deptId); |
|||
if (StringUtils.isNotNull(dept) && 100L == deptId) |
|||
{ |
|||
dept.setParentName("无"); |
|||
} |
|||
mmap.put("dept", dept); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存部门 |
|||
*/ |
|||
@Log(title = "部门管理", businessType = BusinessType.UPDATE) |
|||
@RequiresPermissions("system:dept:edit") |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysDept dept) |
|||
{ |
|||
Long deptId = dept.getDeptId(); |
|||
deptService.checkDeptDataScope(deptId); |
|||
if (!deptService.checkDeptNameUnique(dept)) |
|||
{ |
|||
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); |
|||
} |
|||
else if (dept.getParentId().equals(deptId)) |
|||
{ |
|||
return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); |
|||
} |
|||
else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0) |
|||
{ |
|||
return AjaxResult.error("该部门包含未停用的子部门!"); |
|||
} |
|||
dept.setUpdateBy(getLoginName()); |
|||
return toAjax(deptService.updateDept(dept)); |
|||
} |
|||
|
|||
/** |
|||
* 删除 |
|||
*/ |
|||
@Log(title = "部门管理", businessType = BusinessType.DELETE) |
|||
@RequiresPermissions("system:dept:remove") |
|||
@GetMapping("/remove/{deptId}") |
|||
@ResponseBody |
|||
public AjaxResult remove(@PathVariable("deptId") Long deptId) |
|||
{ |
|||
if (deptService.selectDeptCount(deptId) > 0) |
|||
{ |
|||
return AjaxResult.warn("存在下级部门,不允许删除"); |
|||
} |
|||
if (deptService.checkDeptExistUser(deptId)) |
|||
{ |
|||
return AjaxResult.warn("部门存在用户,不允许删除"); |
|||
} |
|||
deptService.checkDeptDataScope(deptId); |
|||
return toAjax(deptService.deleteDeptById(deptId)); |
|||
} |
|||
|
|||
/** |
|||
* 校验部门名称 |
|||
*/ |
|||
@PostMapping("/checkDeptNameUnique") |
|||
@ResponseBody |
|||
public boolean checkDeptNameUnique(SysDept dept) |
|||
{ |
|||
return deptService.checkDeptNameUnique(dept); |
|||
} |
|||
|
|||
/** |
|||
* 选择部门树 |
|||
* |
|||
* @param deptId 部门ID |
|||
* @param excludeId 排除ID |
|||
*/ |
|||
@GetMapping(value = { "/selectDeptTree/{deptId}", "/selectDeptTree/{deptId}/{excludeId}" }) |
|||
public String selectDeptTree(@PathVariable("deptId") Long deptId, |
|||
@PathVariable(value = "excludeId", required = false) Long excludeId, ModelMap mmap) |
|||
{ |
|||
mmap.put("dept", deptService.selectDeptById(deptId)); |
|||
mmap.put("excludeId", excludeId); |
|||
return prefix + "/tree"; |
|||
} |
|||
|
|||
/** |
|||
* 加载部门列表树(排除下级) |
|||
*/ |
|||
@GetMapping("/treeData/{excludeId}") |
|||
@ResponseBody |
|||
public List<Ztree> treeDataExcludeChild(@PathVariable(value = "excludeId", required = false) Long excludeId) |
|||
{ |
|||
SysDept dept = new SysDept(); |
|||
dept.setExcludeId(excludeId); |
|||
List<Ztree> ztrees = deptService.selectDeptTreeExcludeChild(dept); |
|||
return ztrees; |
|||
} |
|||
} |
@ -0,0 +1,121 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.entity.SysDictData; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.system.service.ISysDictDataService; |
|||
|
|||
/** |
|||
* 数据字典信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/dict/data") |
|||
public class SysDictDataController extends BaseController |
|||
{ |
|||
private String prefix = "system/dict/data"; |
|||
|
|||
@Autowired |
|||
private ISysDictDataService dictDataService; |
|||
|
|||
@RequiresPermissions("system:dict:view") |
|||
@GetMapping() |
|||
public String dictData() |
|||
{ |
|||
return prefix + "/data"; |
|||
} |
|||
|
|||
@PostMapping("/list") |
|||
@RequiresPermissions("system:dict:list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysDictData dictData) |
|||
{ |
|||
startPage(); |
|||
List<SysDictData> list = dictDataService.selectDictDataList(dictData); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@Log(title = "字典数据", businessType = BusinessType.EXPORT) |
|||
@RequiresPermissions("system:dict:export") |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(SysDictData dictData) |
|||
{ |
|||
List<SysDictData> list = dictDataService.selectDictDataList(dictData); |
|||
ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class); |
|||
return util.exportExcel(list, "字典数据"); |
|||
} |
|||
|
|||
/** |
|||
* 新增字典类型 |
|||
*/ |
|||
@GetMapping("/add/{dictType}") |
|||
public String add(@PathVariable("dictType") String dictType, ModelMap mmap) |
|||
{ |
|||
mmap.put("dictType", dictType); |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存字典类型 |
|||
*/ |
|||
@Log(title = "字典数据", businessType = BusinessType.INSERT) |
|||
@RequiresPermissions("system:dict:add") |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysDictData dict) |
|||
{ |
|||
dict.setCreateBy(getLoginName()); |
|||
return toAjax(dictDataService.insertDictData(dict)); |
|||
} |
|||
|
|||
/** |
|||
* 修改字典类型 |
|||
*/ |
|||
@RequiresPermissions("system:dict:edit") |
|||
@GetMapping("/edit/{dictCode}") |
|||
public String edit(@PathVariable("dictCode") Long dictCode, ModelMap mmap) |
|||
{ |
|||
mmap.put("dict", dictDataService.selectDictDataById(dictCode)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存字典类型 |
|||
*/ |
|||
@Log(title = "字典数据", businessType = BusinessType.UPDATE) |
|||
@RequiresPermissions("system:dict:edit") |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysDictData dict) |
|||
{ |
|||
dict.setUpdateBy(getLoginName()); |
|||
return toAjax(dictDataService.updateDictData(dict)); |
|||
} |
|||
|
|||
@Log(title = "字典数据", businessType = BusinessType.DELETE) |
|||
@RequiresPermissions("system:dict:remove") |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
dictDataService.deleteDictDataByIds(ids); |
|||
return success(); |
|||
} |
|||
} |
@ -0,0 +1,188 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.Ztree; |
|||
import com.win.common.core.domain.entity.SysDictType; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.system.service.ISysDictTypeService; |
|||
|
|||
/** |
|||
* 数据字典信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/dict") |
|||
public class SysDictTypeController extends BaseController |
|||
{ |
|||
private String prefix = "system/dict/type"; |
|||
|
|||
@Autowired |
|||
private ISysDictTypeService dictTypeService; |
|||
|
|||
@RequiresPermissions("system:dict:view") |
|||
@GetMapping() |
|||
public String dictType() |
|||
{ |
|||
return prefix + "/type"; |
|||
} |
|||
|
|||
@PostMapping("/list") |
|||
@RequiresPermissions("system:dict:list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysDictType dictType) |
|||
{ |
|||
startPage(); |
|||
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@Log(title = "字典类型", businessType = BusinessType.EXPORT) |
|||
@RequiresPermissions("system:dict:export") |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(SysDictType dictType) |
|||
{ |
|||
|
|||
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType); |
|||
ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class); |
|||
return util.exportExcel(list, "字典类型"); |
|||
} |
|||
|
|||
/** |
|||
* 新增字典类型 |
|||
*/ |
|||
@GetMapping("/add") |
|||
public String add() |
|||
{ |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存字典类型 |
|||
*/ |
|||
@Log(title = "字典类型", businessType = BusinessType.INSERT) |
|||
@RequiresPermissions("system:dict:add") |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysDictType dict) |
|||
{ |
|||
if (!dictTypeService.checkDictTypeUnique(dict)) |
|||
{ |
|||
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); |
|||
} |
|||
dict.setCreateBy(getLoginName()); |
|||
return toAjax(dictTypeService.insertDictType(dict)); |
|||
} |
|||
|
|||
/** |
|||
* 修改字典类型 |
|||
*/ |
|||
@RequiresPermissions("system:dict:edit") |
|||
@GetMapping("/edit/{dictId}") |
|||
public String edit(@PathVariable("dictId") Long dictId, ModelMap mmap) |
|||
{ |
|||
mmap.put("dict", dictTypeService.selectDictTypeById(dictId)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存字典类型 |
|||
*/ |
|||
@Log(title = "字典类型", businessType = BusinessType.UPDATE) |
|||
@RequiresPermissions("system:dict:edit") |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysDictType dict) |
|||
{ |
|||
if (!dictTypeService.checkDictTypeUnique(dict)) |
|||
{ |
|||
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); |
|||
} |
|||
dict.setUpdateBy(getLoginName()); |
|||
return toAjax(dictTypeService.updateDictType(dict)); |
|||
} |
|||
|
|||
@Log(title = "字典类型", businessType = BusinessType.DELETE) |
|||
@RequiresPermissions("system:dict:remove") |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
dictTypeService.deleteDictTypeByIds(ids); |
|||
return success(); |
|||
} |
|||
|
|||
/** |
|||
* 刷新字典缓存 |
|||
*/ |
|||
@RequiresPermissions("system:dict:remove") |
|||
@Log(title = "字典类型", businessType = BusinessType.CLEAN) |
|||
@GetMapping("/refreshCache") |
|||
@ResponseBody |
|||
public AjaxResult refreshCache() |
|||
{ |
|||
dictTypeService.resetDictCache(); |
|||
return success(); |
|||
} |
|||
|
|||
/** |
|||
* 查询字典详细 |
|||
*/ |
|||
@RequiresPermissions("system:dict:list") |
|||
@GetMapping("/detail/{dictId}") |
|||
public String detail(@PathVariable("dictId") Long dictId, ModelMap mmap) |
|||
{ |
|||
mmap.put("dict", dictTypeService.selectDictTypeById(dictId)); |
|||
mmap.put("dictList", dictTypeService.selectDictTypeAll()); |
|||
return "system/dict/data/data"; |
|||
} |
|||
|
|||
/** |
|||
* 校验字典类型 |
|||
*/ |
|||
@PostMapping("/checkDictTypeUnique") |
|||
@ResponseBody |
|||
public boolean checkDictTypeUnique(SysDictType dictType) |
|||
{ |
|||
return dictTypeService.checkDictTypeUnique(dictType); |
|||
} |
|||
|
|||
/** |
|||
* 选择字典树 |
|||
*/ |
|||
@GetMapping("/selectDictTree/{columnId}/{dictType}") |
|||
public String selectDeptTree(@PathVariable("columnId") Long columnId, @PathVariable("dictType") String dictType, |
|||
ModelMap mmap) |
|||
{ |
|||
mmap.put("columnId", columnId); |
|||
mmap.put("dict", dictTypeService.selectDictTypeByType(dictType)); |
|||
return prefix + "/tree"; |
|||
} |
|||
|
|||
/** |
|||
* 加载字典列表树 |
|||
*/ |
|||
@GetMapping("/treeData") |
|||
@ResponseBody |
|||
public List<Ztree> treeData() |
|||
{ |
|||
List<Ztree> ztrees = dictTypeService.selectDictTree(new SysDictType()); |
|||
return ztrees; |
|||
} |
|||
} |
@ -0,0 +1,178 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import jakarta.servlet.http.Cookie; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
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.ResponseBody; |
|||
import com.win.common.config.WinConfig; |
|||
import com.win.common.constant.ShiroConstants; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.entity.SysMenu; |
|||
import com.win.common.core.domain.entity.SysUser; |
|||
import com.win.common.core.text.Convert; |
|||
import com.win.common.utils.CookieUtils; |
|||
import com.win.common.utils.DateUtils; |
|||
import com.win.common.utils.ServletUtils; |
|||
import com.win.common.utils.StringUtils; |
|||
import com.win.framework.shiro.service.SysPasswordService; |
|||
import com.win.system.service.ISysConfigService; |
|||
import com.win.system.service.ISysMenuService; |
|||
|
|||
/** |
|||
* 首页 业务处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
public class SysIndexController extends BaseController |
|||
{ |
|||
@Autowired |
|||
private ISysMenuService menuService; |
|||
|
|||
@Autowired |
|||
private ISysConfigService configService; |
|||
|
|||
@Autowired |
|||
private SysPasswordService passwordService; |
|||
|
|||
// 系统首页
|
|||
@GetMapping("/index") |
|||
public String index(ModelMap mmap) |
|||
{ |
|||
// 取身份信息
|
|||
SysUser user = getSysUser(); |
|||
// 根据用户id取出菜单
|
|||
List<SysMenu> menus = menuService.selectMenusByUser(user); |
|||
mmap.put("menus", menus); |
|||
mmap.put("user", user); |
|||
mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme")); |
|||
mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName")); |
|||
Boolean footer = Convert.toBool(configService.selectConfigByKey("sys.index.footer"), true); |
|||
Boolean tagsView = Convert.toBool(configService.selectConfigByKey("sys.index.tagsView"), true); |
|||
mmap.put("footer", footer); |
|||
mmap.put("tagsView", tagsView); |
|||
mmap.put("mainClass", contentMainClass(footer, tagsView)); |
|||
mmap.put("copyrightYear", WinConfig.getCopyrightYear()); |
|||
mmap.put("demoEnabled", WinConfig.isDemoEnabled()); |
|||
mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate())); |
|||
mmap.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate())); |
|||
mmap.put("isMobile", ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent"))); |
|||
|
|||
// 菜单导航显示风格
|
|||
String menuStyle = configService.selectConfigByKey("sys.index.menuStyle"); |
|||
// 移动端,默认使左侧导航菜单,否则取默认配置
|
|||
String indexStyle = ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")) ? "index" : menuStyle; |
|||
|
|||
// 优先Cookie配置导航菜单
|
|||
Cookie[] cookies = ServletUtils.getRequest().getCookies(); |
|||
for (Cookie cookie : cookies) |
|||
{ |
|||
if (StringUtils.isNotEmpty(cookie.getName()) && "nav-style".equalsIgnoreCase(cookie.getName())) |
|||
{ |
|||
indexStyle = cookie.getValue(); |
|||
break; |
|||
} |
|||
} |
|||
String webIndex = "topnav".equalsIgnoreCase(indexStyle) ? "index-topnav" : "index"; |
|||
return webIndex; |
|||
} |
|||
|
|||
// 锁定屏幕
|
|||
@GetMapping("/lockscreen") |
|||
public String lockscreen(ModelMap mmap) |
|||
{ |
|||
mmap.put("user", getSysUser()); |
|||
ServletUtils.getSession().setAttribute(ShiroConstants.LOCK_SCREEN, true); |
|||
return "lock"; |
|||
} |
|||
|
|||
// 解锁屏幕
|
|||
@PostMapping("/unlockscreen") |
|||
@ResponseBody |
|||
public AjaxResult unlockscreen(String password) |
|||
{ |
|||
SysUser user = getSysUser(); |
|||
if (StringUtils.isNull(user)) |
|||
{ |
|||
return AjaxResult.error("服务器超时,请重新登录"); |
|||
} |
|||
if (passwordService.matches(user, password)) |
|||
{ |
|||
ServletUtils.getSession().removeAttribute(ShiroConstants.LOCK_SCREEN); |
|||
return AjaxResult.success(); |
|||
} |
|||
return AjaxResult.error("密码不正确,请重新输入。"); |
|||
} |
|||
|
|||
// 切换主题
|
|||
@GetMapping("/system/switchSkin") |
|||
public String switchSkin() |
|||
{ |
|||
return "skin"; |
|||
} |
|||
|
|||
// 切换菜单
|
|||
@GetMapping("/system/menuStyle/{style}") |
|||
public void menuStyle(@PathVariable String style, HttpServletResponse response) |
|||
{ |
|||
CookieUtils.setCookie(response, "nav-style", style); |
|||
} |
|||
|
|||
// 系统介绍
|
|||
@GetMapping("/system/main") |
|||
public String main(ModelMap mmap) |
|||
{ |
|||
mmap.put("version", WinConfig.getVersion()); |
|||
return "main"; |
|||
} |
|||
|
|||
// content-main class
|
|||
public String contentMainClass(Boolean footer, Boolean tagsView) |
|||
{ |
|||
if (!footer && !tagsView) |
|||
{ |
|||
return "tagsview-footer-hide"; |
|||
} |
|||
else if (!footer) |
|||
{ |
|||
return "footer-hide"; |
|||
} |
|||
else if (!tagsView) |
|||
{ |
|||
return "tagsview-hide"; |
|||
} |
|||
return StringUtils.EMPTY; |
|||
} |
|||
|
|||
// 检查初始密码是否提醒修改
|
|||
public boolean initPasswordIsModify(Date pwdUpdateDate) |
|||
{ |
|||
Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify")); |
|||
return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null; |
|||
} |
|||
|
|||
// 检查密码是否过期
|
|||
public boolean passwordIsExpiration(Date pwdUpdateDate) |
|||
{ |
|||
Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays")); |
|||
if (passwordValidateDays != null && passwordValidateDays > 0) |
|||
{ |
|||
if (StringUtils.isNull(pwdUpdateDate)) |
|||
{ |
|||
// 如果从未修改过初始密码,直接提醒过期
|
|||
return true; |
|||
} |
|||
Date nowDate = DateUtils.getNowDate(); |
|||
return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays; |
|||
} |
|||
return false; |
|||
} |
|||
} |
@ -0,0 +1,82 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import jakarta.servlet.http.HttpServletRequest; |
|||
import jakarta.servlet.http.HttpServletResponse; |
|||
import org.apache.shiro.SecurityUtils; |
|||
import org.apache.shiro.authc.AuthenticationException; |
|||
import org.apache.shiro.authc.UsernamePasswordToken; |
|||
import org.apache.shiro.subject.Subject; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.text.Convert; |
|||
import com.win.common.utils.ServletUtils; |
|||
import com.win.common.utils.StringUtils; |
|||
import com.win.framework.web.service.ConfigService; |
|||
|
|||
/** |
|||
* 登录验证 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
public class SysLoginController extends BaseController |
|||
{ |
|||
/** |
|||
* 是否开启记住我功能 |
|||
*/ |
|||
@Value("${shiro.rememberMe.enabled: false}") |
|||
private boolean rememberMe; |
|||
|
|||
@Autowired |
|||
private ConfigService configService; |
|||
|
|||
@GetMapping("/login") |
|||
public String login(HttpServletRequest request, HttpServletResponse response, ModelMap mmap) |
|||
{ |
|||
// 如果是Ajax请求,返回Json字符串。
|
|||
if (ServletUtils.isAjaxRequest(request)) |
|||
{ |
|||
return ServletUtils.renderString(response, "{\"code\":\"1\",\"msg\":\"未登录或登录超时。请重新登录\"}"); |
|||
} |
|||
// 是否开启记住我
|
|||
mmap.put("isRemembered", rememberMe); |
|||
// 是否开启用户注册
|
|||
mmap.put("isAllowRegister", Convert.toBool(configService.getKey("sys.account.registerUser"), false)); |
|||
return "login"; |
|||
} |
|||
|
|||
@PostMapping("/login") |
|||
@ResponseBody |
|||
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe) |
|||
{ |
|||
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe); |
|||
Subject subject = SecurityUtils.getSubject(); |
|||
try |
|||
{ |
|||
subject.login(token); |
|||
return success(); |
|||
} |
|||
catch (AuthenticationException e) |
|||
{ |
|||
String msg = "用户或密码错误"; |
|||
if (StringUtils.isNotEmpty(e.getMessage())) |
|||
{ |
|||
msg = e.getMessage(); |
|||
} |
|||
return error(msg); |
|||
} |
|||
} |
|||
|
|||
@GetMapping("/unauth") |
|||
public String unauth() |
|||
{ |
|||
return "error/unauth"; |
|||
} |
|||
} |
@ -0,0 +1,197 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.Ztree; |
|||
import com.win.common.core.domain.entity.SysMenu; |
|||
import com.win.common.core.domain.entity.SysRole; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.ShiroUtils; |
|||
import com.win.framework.shiro.util.AuthorizationUtils; |
|||
import com.win.system.service.ISysMenuService; |
|||
|
|||
/** |
|||
* 菜单信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/menu") |
|||
public class SysMenuController extends BaseController |
|||
{ |
|||
private String prefix = "system/menu"; |
|||
|
|||
@Autowired |
|||
private ISysMenuService menuService; |
|||
|
|||
@RequiresPermissions("system:menu:view") |
|||
@GetMapping() |
|||
public String menu() |
|||
{ |
|||
return prefix + "/menu"; |
|||
} |
|||
|
|||
@RequiresPermissions("system:menu:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public List<SysMenu> list(SysMenu menu) |
|||
{ |
|||
Long userId = ShiroUtils.getUserId(); |
|||
List<SysMenu> menuList = menuService.selectMenuList(menu, userId); |
|||
return menuList; |
|||
} |
|||
|
|||
/** |
|||
* 删除菜单 |
|||
*/ |
|||
@Log(title = "菜单管理", businessType = BusinessType.DELETE) |
|||
@RequiresPermissions("system:menu:remove") |
|||
@GetMapping("/remove/{menuId}") |
|||
@ResponseBody |
|||
public AjaxResult remove(@PathVariable("menuId") Long menuId) |
|||
{ |
|||
if (menuService.selectCountMenuByParentId(menuId) > 0) |
|||
{ |
|||
return AjaxResult.warn("存在子菜单,不允许删除"); |
|||
} |
|||
if (menuService.selectCountRoleMenuByMenuId(menuId) > 0) |
|||
{ |
|||
return AjaxResult.warn("菜单已分配,不允许删除"); |
|||
} |
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo(); |
|||
return toAjax(menuService.deleteMenuById(menuId)); |
|||
} |
|||
|
|||
/** |
|||
* 新增 |
|||
*/ |
|||
@GetMapping("/add/{parentId}") |
|||
public String add(@PathVariable("parentId") Long parentId, ModelMap mmap) |
|||
{ |
|||
SysMenu menu = null; |
|||
if (0L != parentId) |
|||
{ |
|||
menu = menuService.selectMenuById(parentId); |
|||
} |
|||
else |
|||
{ |
|||
menu = new SysMenu(); |
|||
menu.setMenuId(0L); |
|||
menu.setMenuName("主目录"); |
|||
} |
|||
mmap.put("menu", menu); |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存菜单 |
|||
*/ |
|||
@Log(title = "菜单管理", businessType = BusinessType.INSERT) |
|||
@RequiresPermissions("system:menu:add") |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysMenu menu) |
|||
{ |
|||
if (!menuService.checkMenuNameUnique(menu)) |
|||
{ |
|||
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); |
|||
} |
|||
menu.setCreateBy(getLoginName()); |
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo(); |
|||
return toAjax(menuService.insertMenu(menu)); |
|||
} |
|||
|
|||
/** |
|||
* 修改菜单 |
|||
*/ |
|||
@RequiresPermissions("system:menu:edit") |
|||
@GetMapping("/edit/{menuId}") |
|||
public String edit(@PathVariable("menuId") Long menuId, ModelMap mmap) |
|||
{ |
|||
mmap.put("menu", menuService.selectMenuById(menuId)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存菜单 |
|||
*/ |
|||
@Log(title = "菜单管理", businessType = BusinessType.UPDATE) |
|||
@RequiresPermissions("system:menu:edit") |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysMenu menu) |
|||
{ |
|||
if (!menuService.checkMenuNameUnique(menu)) |
|||
{ |
|||
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); |
|||
} |
|||
menu.setUpdateBy(getLoginName()); |
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo(); |
|||
return toAjax(menuService.updateMenu(menu)); |
|||
} |
|||
|
|||
/** |
|||
* 选择菜单图标 |
|||
*/ |
|||
@GetMapping("/icon") |
|||
public String icon() |
|||
{ |
|||
return prefix + "/icon"; |
|||
} |
|||
|
|||
/** |
|||
* 校验菜单名称 |
|||
*/ |
|||
@PostMapping("/checkMenuNameUnique") |
|||
@ResponseBody |
|||
public boolean checkMenuNameUnique(SysMenu menu) |
|||
{ |
|||
return menuService.checkMenuNameUnique(menu); |
|||
} |
|||
|
|||
/** |
|||
* 加载角色菜单列表树 |
|||
*/ |
|||
@GetMapping("/roleMenuTreeData") |
|||
@ResponseBody |
|||
public List<Ztree> roleMenuTreeData(SysRole role) |
|||
{ |
|||
Long userId = ShiroUtils.getUserId(); |
|||
List<Ztree> ztrees = menuService.roleMenuTreeData(role, userId); |
|||
return ztrees; |
|||
} |
|||
|
|||
/** |
|||
* 加载所有菜单列表树 |
|||
*/ |
|||
@GetMapping("/menuTreeData") |
|||
@ResponseBody |
|||
public List<Ztree> menuTreeData() |
|||
{ |
|||
Long userId = ShiroUtils.getUserId(); |
|||
List<Ztree> ztrees = menuService.menuTreeData(userId); |
|||
return ztrees; |
|||
} |
|||
|
|||
/** |
|||
* 选择菜单树 |
|||
*/ |
|||
@GetMapping("/selectMenuTree/{menuId}") |
|||
public String selectMenuTree(@PathVariable("menuId") Long menuId, ModelMap mmap) |
|||
{ |
|||
mmap.put("menu", menuService.selectMenuById(menuId)); |
|||
return prefix + "/tree"; |
|||
} |
|||
} |
@ -0,0 +1,124 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.system.domain.SysNotice; |
|||
import com.win.system.service.ISysNoticeService; |
|||
|
|||
/** |
|||
* 公告 信息操作处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/notice") |
|||
public class SysNoticeController extends BaseController |
|||
{ |
|||
private String prefix = "system/notice"; |
|||
|
|||
@Autowired |
|||
private ISysNoticeService noticeService; |
|||
|
|||
@RequiresPermissions("system:notice:view") |
|||
@GetMapping() |
|||
public String notice() |
|||
{ |
|||
return prefix + "/notice"; |
|||
} |
|||
|
|||
/** |
|||
* 查询公告列表 |
|||
*/ |
|||
@RequiresPermissions("system:notice:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysNotice notice) |
|||
{ |
|||
startPage(); |
|||
List<SysNotice> list = noticeService.selectNoticeList(notice); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
/** |
|||
* 新增公告 |
|||
*/ |
|||
@GetMapping("/add") |
|||
public String add() |
|||
{ |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存公告 |
|||
*/ |
|||
@RequiresPermissions("system:notice:add") |
|||
@Log(title = "通知公告", businessType = BusinessType.INSERT) |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysNotice notice) |
|||
{ |
|||
notice.setCreateBy(getLoginName()); |
|||
return toAjax(noticeService.insertNotice(notice)); |
|||
} |
|||
|
|||
/** |
|||
* 修改公告 |
|||
*/ |
|||
@RequiresPermissions("system:notice:edit") |
|||
@GetMapping("/edit/{noticeId}") |
|||
public String edit(@PathVariable("noticeId") Long noticeId, ModelMap mmap) |
|||
{ |
|||
mmap.put("notice", noticeService.selectNoticeById(noticeId)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存公告 |
|||
*/ |
|||
@RequiresPermissions("system:notice:edit") |
|||
@Log(title = "通知公告", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysNotice notice) |
|||
{ |
|||
notice.setUpdateBy(getLoginName()); |
|||
return toAjax(noticeService.updateNotice(notice)); |
|||
} |
|||
|
|||
/** |
|||
* 查询公告详细 |
|||
*/ |
|||
@RequiresPermissions("system:notice:list") |
|||
@GetMapping("/view/{noticeId}") |
|||
public String view(@PathVariable("noticeId") Long noticeId, ModelMap mmap) |
|||
{ |
|||
mmap.put("notice", noticeService.selectNoticeById(noticeId)); |
|||
return prefix + "/view"; |
|||
} |
|||
|
|||
/** |
|||
* 删除公告 |
|||
*/ |
|||
@RequiresPermissions("system:notice:remove") |
|||
@Log(title = "通知公告", businessType = BusinessType.DELETE) |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
return toAjax(noticeService.deleteNoticeByIds(ids)); |
|||
} |
|||
} |
@ -0,0 +1,162 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.system.domain.SysPost; |
|||
import com.win.system.service.ISysPostService; |
|||
|
|||
/** |
|||
* 岗位信息操作处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/post") |
|||
public class SysPostController extends BaseController |
|||
{ |
|||
private String prefix = "system/post"; |
|||
|
|||
@Autowired |
|||
private ISysPostService postService; |
|||
|
|||
@RequiresPermissions("system:post:view") |
|||
@GetMapping() |
|||
public String operlog() |
|||
{ |
|||
return prefix + "/post"; |
|||
} |
|||
|
|||
@RequiresPermissions("system:post:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysPost post) |
|||
{ |
|||
startPage(); |
|||
List<SysPost> list = postService.selectPostList(post); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@Log(title = "岗位管理", businessType = BusinessType.EXPORT) |
|||
@RequiresPermissions("system:post:export") |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(SysPost post) |
|||
{ |
|||
List<SysPost> list = postService.selectPostList(post); |
|||
ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class); |
|||
return util.exportExcel(list, "岗位数据"); |
|||
} |
|||
|
|||
@RequiresPermissions("system:post:remove") |
|||
@Log(title = "岗位管理", businessType = BusinessType.DELETE) |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
try |
|||
{ |
|||
return toAjax(postService.deletePostByIds(ids)); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
return error(e.getMessage()); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 新增岗位 |
|||
*/ |
|||
@GetMapping("/add") |
|||
public String add() |
|||
{ |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存岗位 |
|||
*/ |
|||
@RequiresPermissions("system:post:add") |
|||
@Log(title = "岗位管理", businessType = BusinessType.INSERT) |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysPost post) |
|||
{ |
|||
if (!postService.checkPostNameUnique(post)) |
|||
{ |
|||
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); |
|||
} |
|||
else if (!postService.checkPostCodeUnique(post)) |
|||
{ |
|||
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); |
|||
} |
|||
post.setCreateBy(getLoginName()); |
|||
return toAjax(postService.insertPost(post)); |
|||
} |
|||
|
|||
/** |
|||
* 修改岗位 |
|||
*/ |
|||
@RequiresPermissions("system:post:edit") |
|||
@GetMapping("/edit/{postId}") |
|||
public String edit(@PathVariable("postId") Long postId, ModelMap mmap) |
|||
{ |
|||
mmap.put("post", postService.selectPostById(postId)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存岗位 |
|||
*/ |
|||
@RequiresPermissions("system:post:edit") |
|||
@Log(title = "岗位管理", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysPost post) |
|||
{ |
|||
if (!postService.checkPostNameUnique(post)) |
|||
{ |
|||
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); |
|||
} |
|||
else if (!postService.checkPostCodeUnique(post)) |
|||
{ |
|||
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); |
|||
} |
|||
post.setUpdateBy(getLoginName()); |
|||
return toAjax(postService.updatePost(post)); |
|||
} |
|||
|
|||
/** |
|||
* 校验岗位名称 |
|||
*/ |
|||
@PostMapping("/checkPostNameUnique") |
|||
@ResponseBody |
|||
public boolean checkPostNameUnique(SysPost post) |
|||
{ |
|||
return postService.checkPostNameUnique(post); |
|||
} |
|||
|
|||
/** |
|||
* 校验岗位编码 |
|||
*/ |
|||
@PostMapping("/checkPostCodeUnique") |
|||
@ResponseBody |
|||
public boolean checkPostCodeUnique(SysPost post) |
|||
{ |
|||
return postService.checkPostCodeUnique(post); |
|||
} |
|||
} |
@ -0,0 +1,181 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
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.PostMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RequestParam; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.config.WinConfig; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.entity.SysUser; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.DateUtils; |
|||
import com.win.common.utils.ShiroUtils; |
|||
import com.win.common.utils.StringUtils; |
|||
import com.win.common.utils.file.FileUploadUtils; |
|||
import com.win.common.utils.file.MimeTypeUtils; |
|||
import com.win.framework.shiro.service.SysPasswordService; |
|||
import com.win.system.service.ISysUserService; |
|||
|
|||
/** |
|||
* 个人信息 业务处理 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/user/profile") |
|||
public class SysProfileController extends BaseController |
|||
{ |
|||
private static final Logger log = LoggerFactory.getLogger(SysProfileController.class); |
|||
|
|||
private String prefix = "system/user/profile"; |
|||
|
|||
@Autowired |
|||
private ISysUserService userService; |
|||
|
|||
@Autowired |
|||
private SysPasswordService passwordService; |
|||
|
|||
/** |
|||
* 个人信息 |
|||
*/ |
|||
@GetMapping() |
|||
public String profile(ModelMap mmap) |
|||
{ |
|||
SysUser user = getSysUser(); |
|||
mmap.put("user", user); |
|||
mmap.put("roleGroup", userService.selectUserRoleGroup(user.getUserId())); |
|||
mmap.put("postGroup", userService.selectUserPostGroup(user.getUserId())); |
|||
return prefix + "/profile"; |
|||
} |
|||
|
|||
@GetMapping("/checkPassword") |
|||
@ResponseBody |
|||
public boolean checkPassword(String password) |
|||
{ |
|||
SysUser user = getSysUser(); |
|||
return passwordService.matches(user, password); |
|||
} |
|||
|
|||
@GetMapping("/resetPwd") |
|||
public String resetPwd(ModelMap mmap) |
|||
{ |
|||
SysUser user = getSysUser(); |
|||
mmap.put("user", userService.selectUserById(user.getUserId())); |
|||
return prefix + "/resetPwd"; |
|||
} |
|||
|
|||
@Log(title = "重置密码", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/resetPwd") |
|||
@ResponseBody |
|||
public AjaxResult resetPwd(String oldPassword, String newPassword) |
|||
{ |
|||
SysUser user = getSysUser(); |
|||
if (!passwordService.matches(user, oldPassword)) |
|||
{ |
|||
return error("修改密码失败,旧密码错误"); |
|||
} |
|||
if (passwordService.matches(user, newPassword)) |
|||
{ |
|||
return error("新密码不能与旧密码相同"); |
|||
} |
|||
user.setSalt(ShiroUtils.randomSalt()); |
|||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), newPassword, user.getSalt())); |
|||
user.setPwdUpdateDate(DateUtils.getNowDate()); |
|||
if (userService.resetUserPwd(user) > 0) |
|||
{ |
|||
setSysUser(userService.selectUserById(user.getUserId())); |
|||
return success(); |
|||
} |
|||
return error("修改密码异常,请联系管理员"); |
|||
} |
|||
|
|||
/** |
|||
* 修改用户 |
|||
*/ |
|||
@GetMapping("/edit") |
|||
public String edit(ModelMap mmap) |
|||
{ |
|||
SysUser user = getSysUser(); |
|||
mmap.put("user", userService.selectUserById(user.getUserId())); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改头像 |
|||
*/ |
|||
@GetMapping("/avatar") |
|||
public String avatar(ModelMap mmap) |
|||
{ |
|||
SysUser user = getSysUser(); |
|||
mmap.put("user", userService.selectUserById(user.getUserId())); |
|||
return prefix + "/avatar"; |
|||
} |
|||
|
|||
/** |
|||
* 修改用户 |
|||
*/ |
|||
@Log(title = "个人信息", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/update") |
|||
@ResponseBody |
|||
public AjaxResult update(SysUser user) |
|||
{ |
|||
SysUser currentUser = getSysUser(); |
|||
currentUser.setUserName(user.getUserName()); |
|||
currentUser.setEmail(user.getEmail()); |
|||
currentUser.setPhonenumber(user.getPhonenumber()); |
|||
currentUser.setSex(user.getSex()); |
|||
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser)) |
|||
{ |
|||
return error("修改用户'" + currentUser.getLoginName() + "'失败,手机号码已存在"); |
|||
} |
|||
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser)) |
|||
{ |
|||
return error("修改用户'" + currentUser.getLoginName() + "'失败,邮箱账号已存在"); |
|||
} |
|||
if (userService.updateUserInfo(currentUser) > 0) |
|||
{ |
|||
setSysUser(userService.selectUserById(currentUser.getUserId())); |
|||
return success(); |
|||
} |
|||
return error(); |
|||
} |
|||
|
|||
/** |
|||
* 保存头像 |
|||
*/ |
|||
@Log(title = "个人信息", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/updateAvatar") |
|||
@ResponseBody |
|||
public AjaxResult updateAvatar(@RequestParam("avatarfile") MultipartFile file) |
|||
{ |
|||
SysUser currentUser = getSysUser(); |
|||
try |
|||
{ |
|||
if (!file.isEmpty()) |
|||
{ |
|||
String avatar = FileUploadUtils.upload(WinConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION); |
|||
currentUser.setAvatar(avatar); |
|||
if (userService.updateUserInfo(currentUser) > 0) |
|||
{ |
|||
setSysUser(userService.selectUserById(currentUser.getUserId())); |
|||
return success(); |
|||
} |
|||
} |
|||
return error(); |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
log.error("修改头像失败!", e); |
|||
return error(e.getMessage()); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,46 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.ResponseBody; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.entity.SysUser; |
|||
import com.win.common.utils.StringUtils; |
|||
import com.win.framework.shiro.service.SysRegisterService; |
|||
import com.win.system.service.ISysConfigService; |
|||
|
|||
/** |
|||
* 注册验证 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
public class SysRegisterController extends BaseController |
|||
{ |
|||
@Autowired |
|||
private SysRegisterService registerService; |
|||
|
|||
@Autowired |
|||
private ISysConfigService configService; |
|||
|
|||
@GetMapping("/register") |
|||
public String register() |
|||
{ |
|||
return "register"; |
|||
} |
|||
|
|||
@PostMapping("/register") |
|||
@ResponseBody |
|||
public AjaxResult ajaxRegister(SysUser user) |
|||
{ |
|||
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) |
|||
{ |
|||
return error("当前系统没有开启注册功能!"); |
|||
} |
|||
String msg = registerService.register(user); |
|||
return StringUtils.isEmpty(msg) ? success() : error(msg); |
|||
} |
|||
} |
@ -0,0 +1,322 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.Ztree; |
|||
import com.win.common.core.domain.entity.SysRole; |
|||
import com.win.common.core.domain.entity.SysUser; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.framework.shiro.util.AuthorizationUtils; |
|||
import com.win.system.domain.SysUserRole; |
|||
import com.win.system.service.ISysDeptService; |
|||
import com.win.system.service.ISysRoleService; |
|||
import com.win.system.service.ISysUserService; |
|||
|
|||
/** |
|||
* 角色信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/role") |
|||
public class SysRoleController extends BaseController |
|||
{ |
|||
private String prefix = "system/role"; |
|||
|
|||
@Autowired |
|||
private ISysRoleService roleService; |
|||
|
|||
@Autowired |
|||
private ISysUserService userService; |
|||
|
|||
@Autowired |
|||
private ISysDeptService deptService; |
|||
|
|||
@RequiresPermissions("system:role:view") |
|||
@GetMapping() |
|||
public String role() |
|||
{ |
|||
return prefix + "/role"; |
|||
} |
|||
|
|||
@RequiresPermissions("system:role:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysRole role) |
|||
{ |
|||
startPage(); |
|||
List<SysRole> list = roleService.selectRoleList(role); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@Log(title = "角色管理", businessType = BusinessType.EXPORT) |
|||
@RequiresPermissions("system:role:export") |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(SysRole role) |
|||
{ |
|||
List<SysRole> list = roleService.selectRoleList(role); |
|||
ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class); |
|||
return util.exportExcel(list, "角色数据"); |
|||
} |
|||
|
|||
/** |
|||
* 新增角色 |
|||
*/ |
|||
@GetMapping("/add") |
|||
public String add() |
|||
{ |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存角色 |
|||
*/ |
|||
@RequiresPermissions("system:role:add") |
|||
@Log(title = "角色管理", businessType = BusinessType.INSERT) |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysRole role) |
|||
{ |
|||
if (!roleService.checkRoleNameUnique(role)) |
|||
{ |
|||
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); |
|||
} |
|||
else if (!roleService.checkRoleKeyUnique(role)) |
|||
{ |
|||
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); |
|||
} |
|||
role.setCreateBy(getLoginName()); |
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo(); |
|||
return toAjax(roleService.insertRole(role)); |
|||
|
|||
} |
|||
|
|||
/** |
|||
* 修改角色 |
|||
*/ |
|||
@RequiresPermissions("system:role:edit") |
|||
@GetMapping("/edit/{roleId}") |
|||
public String edit(@PathVariable("roleId") Long roleId, ModelMap mmap) |
|||
{ |
|||
roleService.checkRoleDataScope(roleId); |
|||
mmap.put("role", roleService.selectRoleById(roleId)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存角色 |
|||
*/ |
|||
@RequiresPermissions("system:role:edit") |
|||
@Log(title = "角色管理", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysRole role) |
|||
{ |
|||
roleService.checkRoleAllowed(role); |
|||
roleService.checkRoleDataScope(role.getRoleId()); |
|||
if (!roleService.checkRoleNameUnique(role)) |
|||
{ |
|||
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); |
|||
} |
|||
else if (!roleService.checkRoleKeyUnique(role)) |
|||
{ |
|||
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); |
|||
} |
|||
role.setUpdateBy(getLoginName()); |
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo(); |
|||
return toAjax(roleService.updateRole(role)); |
|||
} |
|||
|
|||
/** |
|||
* 角色分配数据权限 |
|||
*/ |
|||
@GetMapping("/authDataScope/{roleId}") |
|||
public String authDataScope(@PathVariable("roleId") Long roleId, ModelMap mmap) |
|||
{ |
|||
mmap.put("role", roleService.selectRoleById(roleId)); |
|||
return prefix + "/dataScope"; |
|||
} |
|||
|
|||
/** |
|||
* 保存角色分配数据权限 |
|||
*/ |
|||
@RequiresPermissions("system:role:edit") |
|||
@Log(title = "角色管理", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/authDataScope") |
|||
@ResponseBody |
|||
public AjaxResult authDataScopeSave(SysRole role) |
|||
{ |
|||
roleService.checkRoleAllowed(role); |
|||
roleService.checkRoleDataScope(role.getRoleId()); |
|||
role.setUpdateBy(getLoginName()); |
|||
if (roleService.authDataScope(role) > 0) |
|||
{ |
|||
setSysUser(userService.selectUserById(getUserId())); |
|||
return success(); |
|||
} |
|||
return error(); |
|||
} |
|||
|
|||
@RequiresPermissions("system:role:remove") |
|||
@Log(title = "角色管理", businessType = BusinessType.DELETE) |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
return toAjax(roleService.deleteRoleByIds(ids)); |
|||
} |
|||
|
|||
/** |
|||
* 校验角色名称 |
|||
*/ |
|||
@PostMapping("/checkRoleNameUnique") |
|||
@ResponseBody |
|||
public boolean checkRoleNameUnique(SysRole role) |
|||
{ |
|||
return roleService.checkRoleNameUnique(role); |
|||
} |
|||
|
|||
/** |
|||
* 校验角色权限 |
|||
*/ |
|||
@PostMapping("/checkRoleKeyUnique") |
|||
@ResponseBody |
|||
public boolean checkRoleKeyUnique(SysRole role) |
|||
{ |
|||
return roleService.checkRoleKeyUnique(role); |
|||
} |
|||
|
|||
/** |
|||
* 选择菜单树 |
|||
*/ |
|||
@GetMapping("/selectMenuTree") |
|||
public String selectMenuTree() |
|||
{ |
|||
return prefix + "/tree"; |
|||
} |
|||
|
|||
/** |
|||
* 角色状态修改 |
|||
*/ |
|||
@Log(title = "角色管理", businessType = BusinessType.UPDATE) |
|||
@RequiresPermissions("system:role:edit") |
|||
@PostMapping("/changeStatus") |
|||
@ResponseBody |
|||
public AjaxResult changeStatus(SysRole role) |
|||
{ |
|||
roleService.checkRoleAllowed(role); |
|||
roleService.checkRoleDataScope(role.getRoleId()); |
|||
return toAjax(roleService.changeStatus(role)); |
|||
} |
|||
|
|||
/** |
|||
* 分配用户 |
|||
*/ |
|||
@RequiresPermissions("system:role:edit") |
|||
@GetMapping("/authUser/{roleId}") |
|||
public String authUser(@PathVariable("roleId") Long roleId, ModelMap mmap) |
|||
{ |
|||
mmap.put("role", roleService.selectRoleById(roleId)); |
|||
return prefix + "/authUser"; |
|||
} |
|||
|
|||
/** |
|||
* 查询已分配用户角色列表 |
|||
*/ |
|||
@RequiresPermissions("system:role:list") |
|||
@PostMapping("/authUser/allocatedList") |
|||
@ResponseBody |
|||
public TableDataInfo allocatedList(SysUser user) |
|||
{ |
|||
startPage(); |
|||
List<SysUser> list = userService.selectAllocatedList(user); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
/** |
|||
* 取消授权 |
|||
*/ |
|||
@RequiresPermissions("system:role:edit") |
|||
@Log(title = "角色管理", businessType = BusinessType.GRANT) |
|||
@PostMapping("/authUser/cancel") |
|||
@ResponseBody |
|||
public AjaxResult cancelAuthUser(SysUserRole userRole) |
|||
{ |
|||
return toAjax(roleService.deleteAuthUser(userRole)); |
|||
} |
|||
|
|||
/** |
|||
* 批量取消授权 |
|||
*/ |
|||
@RequiresPermissions("system:role:edit") |
|||
@Log(title = "角色管理", businessType = BusinessType.GRANT) |
|||
@PostMapping("/authUser/cancelAll") |
|||
@ResponseBody |
|||
public AjaxResult cancelAuthUserAll(Long roleId, String userIds) |
|||
{ |
|||
return toAjax(roleService.deleteAuthUsers(roleId, userIds)); |
|||
} |
|||
|
|||
/** |
|||
* 选择用户 |
|||
*/ |
|||
@GetMapping("/authUser/selectUser/{roleId}") |
|||
public String selectUser(@PathVariable("roleId") Long roleId, ModelMap mmap) |
|||
{ |
|||
mmap.put("role", roleService.selectRoleById(roleId)); |
|||
return prefix + "/selectUser"; |
|||
} |
|||
|
|||
/** |
|||
* 查询未分配用户角色列表 |
|||
*/ |
|||
@RequiresPermissions("system:role:list") |
|||
@PostMapping("/authUser/unallocatedList") |
|||
@ResponseBody |
|||
public TableDataInfo unallocatedList(SysUser user) |
|||
{ |
|||
startPage(); |
|||
List<SysUser> list = userService.selectUnallocatedList(user); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
/** |
|||
* 批量选择用户授权 |
|||
*/ |
|||
@RequiresPermissions("system:role:edit") |
|||
@Log(title = "角色管理", businessType = BusinessType.GRANT) |
|||
@PostMapping("/authUser/selectAll") |
|||
@ResponseBody |
|||
public AjaxResult selectAuthUserAll(Long roleId, String userIds) |
|||
{ |
|||
roleService.checkRoleDataScope(roleId); |
|||
return toAjax(roleService.insertAuthUsers(roleId, userIds)); |
|||
} |
|||
|
|||
/** |
|||
* 加载角色部门(数据权限)列表树 |
|||
*/ |
|||
@RequiresPermissions("system:role:edit") |
|||
@GetMapping("/deptTreeData") |
|||
@ResponseBody |
|||
public List<Ztree> deptTreeData(SysRole role) |
|||
{ |
|||
List<Ztree> ztrees = deptService.roleDeptTreeData(role); |
|||
return ztrees; |
|||
} |
|||
} |
@ -0,0 +1,353 @@ |
|||
package com.win.web.controller.system; |
|||
|
|||
import java.util.List; |
|||
import java.util.stream.Collectors; |
|||
import org.apache.commons.lang3.ArrayUtils; |
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.ui.ModelMap; |
|||
import org.springframework.validation.annotation.Validated; |
|||
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.ResponseBody; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
import com.win.common.annotation.Log; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.AjaxResult; |
|||
import com.win.common.core.domain.Ztree; |
|||
import com.win.common.core.domain.entity.SysDept; |
|||
import com.win.common.core.domain.entity.SysRole; |
|||
import com.win.common.core.domain.entity.SysUser; |
|||
import com.win.common.core.page.TableDataInfo; |
|||
import com.win.common.core.text.Convert; |
|||
import com.win.common.enums.BusinessType; |
|||
import com.win.common.utils.DateUtils; |
|||
import com.win.common.utils.ShiroUtils; |
|||
import com.win.common.utils.StringUtils; |
|||
import com.win.common.utils.poi.ExcelUtil; |
|||
import com.win.framework.shiro.service.SysPasswordService; |
|||
import com.win.framework.shiro.util.AuthorizationUtils; |
|||
import com.win.system.service.ISysDeptService; |
|||
import com.win.system.service.ISysPostService; |
|||
import com.win.system.service.ISysRoleService; |
|||
import com.win.system.service.ISysUserService; |
|||
|
|||
/** |
|||
* 用户信息 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/system/user") |
|||
public class SysUserController extends BaseController |
|||
{ |
|||
private String prefix = "system/user"; |
|||
|
|||
@Autowired |
|||
private ISysUserService userService; |
|||
|
|||
@Autowired |
|||
private ISysRoleService roleService; |
|||
|
|||
@Autowired |
|||
private ISysDeptService deptService; |
|||
|
|||
@Autowired |
|||
private ISysPostService postService; |
|||
|
|||
@Autowired |
|||
private SysPasswordService passwordService; |
|||
|
|||
@RequiresPermissions("system:user:view") |
|||
@GetMapping() |
|||
public String user() |
|||
{ |
|||
return prefix + "/user"; |
|||
} |
|||
|
|||
@RequiresPermissions("system:user:list") |
|||
@PostMapping("/list") |
|||
@ResponseBody |
|||
public TableDataInfo list(SysUser user) |
|||
{ |
|||
startPage(); |
|||
List<SysUser> list = userService.selectUserList(user); |
|||
return getDataTable(list); |
|||
} |
|||
|
|||
@Log(title = "用户管理", businessType = BusinessType.EXPORT) |
|||
@RequiresPermissions("system:user:export") |
|||
@PostMapping("/export") |
|||
@ResponseBody |
|||
public AjaxResult export(SysUser user) |
|||
{ |
|||
List<SysUser> list = userService.selectUserList(user); |
|||
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class); |
|||
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 message = userService.importUser(userList, updateSupport, getLoginName()); |
|||
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("用户数据"); |
|||
} |
|||
|
|||
/** |
|||
* 新增用户 |
|||
*/ |
|||
@GetMapping("/add") |
|||
public String add(ModelMap mmap) |
|||
{ |
|||
mmap.put("roles", roleService.selectRoleAll().stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); |
|||
mmap.put("posts", postService.selectPostAll()); |
|||
return prefix + "/add"; |
|||
} |
|||
|
|||
/** |
|||
* 新增保存用户 |
|||
*/ |
|||
@RequiresPermissions("system:user:add") |
|||
@Log(title = "用户管理", businessType = BusinessType.INSERT) |
|||
@PostMapping("/add") |
|||
@ResponseBody |
|||
public AjaxResult addSave(@Validated SysUser user) |
|||
{ |
|||
deptService.checkDeptDataScope(user.getDeptId()); |
|||
roleService.checkRoleDataScope(user.getRoleIds()); |
|||
if (!userService.checkLoginNameUnique(user)) |
|||
{ |
|||
return error("新增用户'" + user.getLoginName() + "'失败,登录账号已存在"); |
|||
} |
|||
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) |
|||
{ |
|||
return error("新增用户'" + user.getLoginName() + "'失败,手机号码已存在"); |
|||
} |
|||
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) |
|||
{ |
|||
return error("新增用户'" + user.getLoginName() + "'失败,邮箱账号已存在"); |
|||
} |
|||
user.setSalt(ShiroUtils.randomSalt()); |
|||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt())); |
|||
user.setPwdUpdateDate(DateUtils.getNowDate()); |
|||
user.setCreateBy(getLoginName()); |
|||
return toAjax(userService.insertUser(user)); |
|||
} |
|||
|
|||
/** |
|||
* 修改用户 |
|||
*/ |
|||
@RequiresPermissions("system:user:edit") |
|||
@GetMapping("/edit/{userId}") |
|||
public String edit(@PathVariable("userId") Long userId, ModelMap mmap) |
|||
{ |
|||
userService.checkUserDataScope(userId); |
|||
List<SysRole> roles = roleService.selectRolesByUserId(userId); |
|||
mmap.put("user", userService.selectUserById(userId)); |
|||
mmap.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); |
|||
mmap.put("posts", postService.selectPostsByUserId(userId)); |
|||
return prefix + "/edit"; |
|||
} |
|||
|
|||
/** |
|||
* 查询用户详细 |
|||
*/ |
|||
@RequiresPermissions("system:user:list") |
|||
@GetMapping("/view/{userId}") |
|||
public String view(@PathVariable("userId") Long userId, ModelMap mmap) |
|||
{ |
|||
userService.checkUserDataScope(userId); |
|||
mmap.put("user", userService.selectUserById(userId)); |
|||
mmap.put("roleGroup", userService.selectUserRoleGroup(userId)); |
|||
mmap.put("postGroup", userService.selectUserPostGroup(userId)); |
|||
return prefix + "/view"; |
|||
} |
|||
|
|||
/** |
|||
* 修改保存用户 |
|||
*/ |
|||
@RequiresPermissions("system:user:edit") |
|||
@Log(title = "用户管理", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/edit") |
|||
@ResponseBody |
|||
public AjaxResult editSave(@Validated SysUser user) |
|||
{ |
|||
userService.checkUserAllowed(user); |
|||
userService.checkUserDataScope(user.getUserId()); |
|||
deptService.checkDeptDataScope(user.getDeptId()); |
|||
roleService.checkRoleDataScope(user.getRoleIds()); |
|||
if (!userService.checkLoginNameUnique(user)) |
|||
{ |
|||
return error("修改用户'" + user.getLoginName() + "'失败,登录账号已存在"); |
|||
} |
|||
else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) |
|||
{ |
|||
return error("修改用户'" + user.getLoginName() + "'失败,手机号码已存在"); |
|||
} |
|||
else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) |
|||
{ |
|||
return error("修改用户'" + user.getLoginName() + "'失败,邮箱账号已存在"); |
|||
} |
|||
user.setUpdateBy(getLoginName()); |
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo(); |
|||
return toAjax(userService.updateUser(user)); |
|||
} |
|||
|
|||
@RequiresPermissions("system:user:resetPwd") |
|||
@GetMapping("/resetPwd/{userId}") |
|||
public String resetPwd(@PathVariable("userId") Long userId, ModelMap mmap) |
|||
{ |
|||
mmap.put("user", userService.selectUserById(userId)); |
|||
return prefix + "/resetPwd"; |
|||
} |
|||
|
|||
@RequiresPermissions("system:user:resetPwd") |
|||
@Log(title = "重置密码", businessType = BusinessType.UPDATE) |
|||
@PostMapping("/resetPwd") |
|||
@ResponseBody |
|||
public AjaxResult resetPwdSave(SysUser user) |
|||
{ |
|||
userService.checkUserAllowed(user); |
|||
userService.checkUserDataScope(user.getUserId()); |
|||
user.setSalt(ShiroUtils.randomSalt()); |
|||
user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt())); |
|||
if (userService.resetUserPwd(user) > 0) |
|||
{ |
|||
if (ShiroUtils.getUserId().longValue() == user.getUserId().longValue()) |
|||
{ |
|||
setSysUser(userService.selectUserById(user.getUserId())); |
|||
} |
|||
return success(); |
|||
} |
|||
return error(); |
|||
} |
|||
|
|||
/** |
|||
* 进入授权角色页 |
|||
*/ |
|||
@GetMapping("/authRole/{userId}") |
|||
public String authRole(@PathVariable("userId") Long userId, ModelMap mmap) |
|||
{ |
|||
SysUser user = userService.selectUserById(userId); |
|||
// 获取用户所属的角色列表
|
|||
List<SysRole> roles = roleService.selectRolesByUserId(userId); |
|||
mmap.put("user", user); |
|||
mmap.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); |
|||
return prefix + "/authRole"; |
|||
} |
|||
|
|||
/** |
|||
* 用户授权角色 |
|||
*/ |
|||
@RequiresPermissions("system:user:edit") |
|||
@Log(title = "用户管理", businessType = BusinessType.GRANT) |
|||
@PostMapping("/authRole/insertAuthRole") |
|||
@ResponseBody |
|||
public AjaxResult insertAuthRole(Long userId, Long[] roleIds) |
|||
{ |
|||
userService.checkUserDataScope(userId); |
|||
roleService.checkRoleDataScope(roleIds); |
|||
userService.insertUserAuth(userId, roleIds); |
|||
AuthorizationUtils.clearAllCachedAuthorizationInfo(); |
|||
return success(); |
|||
} |
|||
|
|||
@RequiresPermissions("system:user:remove") |
|||
@Log(title = "用户管理", businessType = BusinessType.DELETE) |
|||
@PostMapping("/remove") |
|||
@ResponseBody |
|||
public AjaxResult remove(String ids) |
|||
{ |
|||
if (ArrayUtils.contains(Convert.toLongArray(ids), getUserId())) |
|||
{ |
|||
return error("当前用户不能删除"); |
|||
} |
|||
return toAjax(userService.deleteUserByIds(ids)); |
|||
} |
|||
|
|||
/** |
|||
* 校验用户名 |
|||
*/ |
|||
@PostMapping("/checkLoginNameUnique") |
|||
@ResponseBody |
|||
public boolean checkLoginNameUnique(SysUser user) |
|||
{ |
|||
return userService.checkLoginNameUnique(user); |
|||
} |
|||
|
|||
/** |
|||
* 校验手机号码 |
|||
*/ |
|||
@PostMapping("/checkPhoneUnique") |
|||
@ResponseBody |
|||
public boolean checkPhoneUnique(SysUser user) |
|||
{ |
|||
return userService.checkPhoneUnique(user); |
|||
} |
|||
|
|||
/** |
|||
* 校验email邮箱 |
|||
*/ |
|||
@PostMapping("/checkEmailUnique") |
|||
@ResponseBody |
|||
public boolean checkEmailUnique(SysUser user) |
|||
{ |
|||
return userService.checkEmailUnique(user); |
|||
} |
|||
|
|||
/** |
|||
* 用户状态修改 |
|||
*/ |
|||
@Log(title = "用户管理", businessType = BusinessType.UPDATE) |
|||
@RequiresPermissions("system:user:edit") |
|||
@PostMapping("/changeStatus") |
|||
@ResponseBody |
|||
public AjaxResult changeStatus(SysUser user) |
|||
{ |
|||
userService.checkUserAllowed(user); |
|||
userService.checkUserDataScope(user.getUserId()); |
|||
return toAjax(userService.changeStatus(user)); |
|||
} |
|||
|
|||
/** |
|||
* 加载部门列表树 |
|||
*/ |
|||
@RequiresPermissions("system:user:list") |
|||
@GetMapping("/deptTreeData") |
|||
@ResponseBody |
|||
public List<Ztree> deptTreeData() |
|||
{ |
|||
List<Ztree> ztrees = deptService.selectDeptTree(new SysDept()); |
|||
return ztrees; |
|||
} |
|||
|
|||
/** |
|||
* 选择部门树 |
|||
* |
|||
* @param deptId 部门ID |
|||
*/ |
|||
@RequiresPermissions("system:user:list") |
|||
@GetMapping("/selectDeptTree/{deptId}") |
|||
public String selectDeptTree(@PathVariable("deptId") Long deptId, ModelMap mmap) |
|||
{ |
|||
mmap.put("dept", deptService.selectDeptById(deptId)); |
|||
return prefix + "/deptTree"; |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
package com.win.web.controller.tool; |
|||
|
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import com.win.common.core.controller.BaseController; |
|||
|
|||
/** |
|||
* build 表单构建 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/tool/build") |
|||
public class BuildController extends BaseController |
|||
{ |
|||
private String prefix = "tool/build"; |
|||
|
|||
@RequiresPermissions("tool:build:view") |
|||
@GetMapping() |
|||
public String build() |
|||
{ |
|||
return prefix + "/build"; |
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
package com.win.web.controller.tool; |
|||
|
|||
import org.apache.shiro.authz.annotation.RequiresPermissions; |
|||
import org.springframework.stereotype.Controller; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import com.win.common.core.controller.BaseController; |
|||
|
|||
/** |
|||
* swagger 接口 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Controller |
|||
@RequestMapping("/tool/swagger") |
|||
public class SwaggerController extends BaseController |
|||
{ |
|||
@RequiresPermissions("tool:swagger:view") |
|||
@GetMapping() |
|||
public String index() |
|||
{ |
|||
return redirect("/swagger-ui/index.html"); |
|||
} |
|||
} |
@ -0,0 +1,175 @@ |
|||
package com.win.web.controller.tool; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.LinkedHashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import org.springframework.web.bind.annotation.DeleteMapping; |
|||
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.PutMapping; |
|||
import org.springframework.web.bind.annotation.RequestBody; |
|||
import org.springframework.web.bind.annotation.RequestMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
import com.win.common.core.controller.BaseController; |
|||
import com.win.common.core.domain.R; |
|||
import com.win.common.utils.StringUtils; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
|
|||
/** |
|||
* swagger 用户测试方法 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Tag(name = "用户信息管理") |
|||
@RestController |
|||
@RequestMapping("/test/user") |
|||
public class TestController extends BaseController |
|||
{ |
|||
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>(); |
|||
{ |
|||
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888")); |
|||
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666")); |
|||
} |
|||
|
|||
@Operation(summary = "获取用户列表") |
|||
@GetMapping("/list") |
|||
public R<List<UserEntity>> userList() |
|||
{ |
|||
List<UserEntity> userList = new ArrayList<UserEntity>(users.values()); |
|||
return R.ok(userList); |
|||
} |
|||
|
|||
@Operation(summary = "获取用户详细") |
|||
@GetMapping("/{userId}") |
|||
public R<UserEntity> getUser(@PathVariable(name = "userId") |
|||
Integer userId) |
|||
{ |
|||
if (!users.isEmpty() && users.containsKey(userId)) |
|||
{ |
|||
return R.ok(users.get(userId)); |
|||
} |
|||
else |
|||
{ |
|||
return R.fail("用户不存在"); |
|||
} |
|||
} |
|||
|
|||
@Operation(summary = "新增用户") |
|||
@PostMapping("/save") |
|||
public R<String> save(UserEntity user) |
|||
{ |
|||
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) |
|||
{ |
|||
return R.fail("用户ID不能为空"); |
|||
} |
|||
users.put(user.getUserId(), user); |
|||
return R.ok(); |
|||
} |
|||
|
|||
@Operation(summary = "更新用户") |
|||
@PutMapping("/update") |
|||
public R<String> update(@RequestBody |
|||
UserEntity user) |
|||
{ |
|||
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) |
|||
{ |
|||
return R.fail("用户ID不能为空"); |
|||
} |
|||
if (users.isEmpty() || !users.containsKey(user.getUserId())) |
|||
{ |
|||
return R.fail("用户不存在"); |
|||
} |
|||
users.remove(user.getUserId()); |
|||
users.put(user.getUserId(), user); |
|||
return R.ok(); |
|||
} |
|||
|
|||
@Operation(summary = "删除用户信息") |
|||
@DeleteMapping("/{userId}") |
|||
public R<String> delete(@PathVariable(name = "userId") |
|||
Integer userId) |
|||
{ |
|||
if (!users.isEmpty() && users.containsKey(userId)) |
|||
{ |
|||
users.remove(userId); |
|||
return R.ok(); |
|||
} |
|||
else |
|||
{ |
|||
return R.fail("用户不存在"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Schema(description = "用户实体") |
|||
class UserEntity |
|||
{ |
|||
@Schema(title = "用户ID") |
|||
private Integer userId; |
|||
|
|||
@Schema(title = "用户名称") |
|||
private String username; |
|||
|
|||
@Schema(title = "用户密码") |
|||
private String password; |
|||
|
|||
@Schema(title = "用户手机") |
|||
private String mobile; |
|||
|
|||
public UserEntity() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public UserEntity(Integer userId, String username, String password, String mobile) |
|||
{ |
|||
this.userId = userId; |
|||
this.username = username; |
|||
this.password = password; |
|||
this.mobile = mobile; |
|||
} |
|||
|
|||
public Integer getUserId() |
|||
{ |
|||
return userId; |
|||
} |
|||
|
|||
public void setUserId(Integer userId) |
|||
{ |
|||
this.userId = userId; |
|||
} |
|||
|
|||
public String getUsername() |
|||
{ |
|||
return username; |
|||
} |
|||
|
|||
public void setUsername(String username) |
|||
{ |
|||
this.username = username; |
|||
} |
|||
|
|||
public String getPassword() |
|||
{ |
|||
return password; |
|||
} |
|||
|
|||
public void setPassword(String password) |
|||
{ |
|||
this.password = password; |
|||
} |
|||
|
|||
public String getMobile() |
|||
{ |
|||
return mobile; |
|||
} |
|||
|
|||
public void setMobile(String mobile) |
|||
{ |
|||
this.mobile = mobile; |
|||
} |
|||
} |
@ -0,0 +1,65 @@ |
|||
package com.win.web.core.config; |
|||
|
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
import com.win.common.config.WinConfig; |
|||
import io.swagger.v3.oas.models.Components; |
|||
import io.swagger.v3.oas.models.OpenAPI; |
|||
import io.swagger.v3.oas.models.info.Contact; |
|||
import io.swagger.v3.oas.models.info.Info; |
|||
import io.swagger.v3.oas.models.security.SecurityRequirement; |
|||
import io.swagger.v3.oas.models.security.SecurityScheme; |
|||
|
|||
/** |
|||
* Swagger2的接口配置 |
|||
* |
|||
* @author ruoyi |
|||
*/ |
|||
@Configuration |
|||
public class SwaggerConfig |
|||
{ |
|||
/** 系统基础配置 */ |
|||
@Autowired |
|||
private WinConfig ruoyiConfig; |
|||
|
|||
/** |
|||
* 自定义的 OpenAPI 对象 |
|||
*/ |
|||
@Bean |
|||
public OpenAPI customOpenApi() |
|||
{ |
|||
return new OpenAPI().components(new Components() |
|||
// 设置认证的请求头
|
|||
.addSecuritySchemes("apikey", securityScheme())) |
|||
.addSecurityItem(new SecurityRequirement().addList("apikey")) |
|||
.info(getApiInfo()); |
|||
} |
|||
|
|||
@Bean |
|||
public SecurityScheme securityScheme() |
|||
{ |
|||
return new SecurityScheme() |
|||
.type(SecurityScheme.Type.APIKEY) |
|||
.name("Authorization") |
|||
.in(SecurityScheme.In.HEADER) |
|||
.scheme("Bearer"); |
|||
} |
|||
|
|||
/** |
|||
* 添加摘要信息 |
|||
*/ |
|||
@SuppressWarnings("static-access") |
|||
public Info getApiInfo() |
|||
{ |
|||
return new Info() |
|||
// 设置标题
|
|||
.title("标题:若依管理系统_接口文档") |
|||
// 描述
|
|||
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...") |
|||
// 作者信息
|
|||
.contact(new Contact().name(ruoyiConfig.getName())) |
|||
// 版本
|
|||
.version("版本号:" + ruoyiConfig.getVersion()); |
|||
} |
|||
} |
@ -0,0 +1,61 @@ |
|||
# 数据源配置 |
|||
spring: |
|||
datasource: |
|||
type: com.alibaba.druid.pool.DruidDataSource |
|||
driverClassName: com.mysql.cj.jdbc.Driver |
|||
druid: |
|||
# 主库数据源 |
|||
master: |
|||
url: jdbc:mysql://localhost:3306/ry?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 |
|||
username: root |
|||
password: password |
|||
# 从库数据源 |
|||
slave: |
|||
# 从数据源开关/默认关闭 |
|||
enabled: false |
|||
url: |
|||
username: |
|||
password: |
|||
# 初始连接数 |
|||
initialSize: 5 |
|||
# 最小连接池数量 |
|||
minIdle: 10 |
|||
# 最大连接池数量 |
|||
maxActive: 20 |
|||
# 配置获取连接等待超时的时间 |
|||
maxWait: 60000 |
|||
# 配置连接超时时间 |
|||
connectTimeout: 30000 |
|||
# 配置网络超时时间 |
|||
socketTimeout: 60000 |
|||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 |
|||
timeBetweenEvictionRunsMillis: 60000 |
|||
# 配置一个连接在池中最小生存的时间,单位是毫秒 |
|||
minEvictableIdleTimeMillis: 300000 |
|||
# 配置一个连接在池中最大生存的时间,单位是毫秒 |
|||
maxEvictableIdleTimeMillis: 900000 |
|||
# 配置检测连接是否有效 |
|||
validationQuery: SELECT 1 FROM DUAL |
|||
testWhileIdle: true |
|||
testOnBorrow: false |
|||
testOnReturn: false |
|||
webStatFilter: |
|||
enabled: true |
|||
statViewServlet: |
|||
enabled: true |
|||
# 设置白名单,不填则允许所有访问 |
|||
allow: |
|||
url-pattern: /druid/* |
|||
# 控制台管理用户名和密码 |
|||
login-username: ruoyi |
|||
login-password: 123456 |
|||
filter: |
|||
stat: |
|||
enabled: true |
|||
# 慢SQL记录 |
|||
log-slow-sql: true |
|||
slow-sql-millis: 1000 |
|||
merge-sql: true |
|||
wall: |
|||
config: |
|||
multi-statement-allow: true |
@ -0,0 +1,57 @@ |
|||
spring: |
|||
datasource: |
|||
type: com.alibaba.druid.pool.DruidDataSource |
|||
driver-class-name: com.mysql.cj.jdbc.Driver |
|||
druid: |
|||
master: |
|||
url: jdbc:mysql://localhost:3306/winps?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 |
|||
username: root |
|||
password: root123456 |
|||
slave: |
|||
enabled: false |
|||
url: jdbc:sqlite:D:\ideaworkspace\win-print-server-1.0\win-admin\src\main\resources\winpsdb.db?date_string_format=yyyy-MM-dd HH:mm:ss |
|||
username: |
|||
password: |
|||
# 初始连接数 |
|||
initialSize: 5 |
|||
# 最小连接池数量 |
|||
minIdle: 10 |
|||
# 最大连接池数量 |
|||
maxActive: 20 |
|||
# 配置获取连接等待超时的时间 |
|||
maxWait: 60000 |
|||
# 配置连接超时时间 |
|||
connectTimeout: 30000 |
|||
# 配置网络超时时间 |
|||
socketTimeout: 60000 |
|||
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 |
|||
timeBetweenEvictionRunsMillis: 60000 |
|||
# 配置一个连接在池中最小生存的时间,单位是毫秒 |
|||
minEvictableIdleTimeMillis: 300000 |
|||
# 配置一个连接在池中最大生存的时间,单位是毫秒 |
|||
maxEvictableIdleTimeMillis: 900000 |
|||
# 配置检测连接是否有效 |
|||
validationQuery: SELECT 1 FROM sys_config |
|||
testWhileIdle: true |
|||
testOnBorrow: false |
|||
testOnReturn: false |
|||
webStatFilter: |
|||
enabled: true |
|||
statViewServlet: |
|||
enabled: true |
|||
# 设置白名单,不填则允许所有访问 |
|||
allow: |
|||
url-pattern: /druid/* |
|||
# 控制台管理用户名和密码 |
|||
login-username: ruoyi |
|||
login-password: 123456 |
|||
filter: |
|||
stat: |
|||
enabled: true |
|||
# 慢SQL记录 |
|||
log-slow-sql: true |
|||
slow-sql-millis: 1000 |
|||
merge-sql: true |
|||
wall: |
|||
config: |
|||
multi-statement-allow: true |
@ -0,0 +1,157 @@ |
|||
# 项目相关配置 |
|||
win: |
|||
# 名称 |
|||
name: win |
|||
#客户端编码 |
|||
# 版本 |
|||
version: 4.7.9 |
|||
# 版权年份 |
|||
copyrightYear: 2024 |
|||
# 实例演示开关 |
|||
demoEnabled: false |
|||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) |
|||
profile: D:/win/uploadPath |
|||
# 获取ip地址开关 |
|||
addressEnabled: false |
|||
clientCode: node_001 |
|||
path: |
|||
template: /models |
|||
print: /print |
|||
|
|||
|
|||
# 开发环境配置 |
|||
server: |
|||
# 服务器的HTTP端口,默认为80 |
|||
port: 8001 |
|||
servlet: |
|||
# 应用的访问路径 |
|||
context-path: / |
|||
tomcat: |
|||
# tomcat的URI编码 |
|||
uri-encoding: UTF-8 |
|||
# 连接数满后的排队数,默认为100 |
|||
accept-count: 1000 |
|||
threads: |
|||
# tomcat最大线程数,默认为200 |
|||
max: 800 |
|||
# Tomcat启动初始化的线程数,默认值10 |
|||
min-spare: 100 |
|||
|
|||
# 日志配置 |
|||
logging: |
|||
level: |
|||
com.win: debug |
|||
org.springframework: warn |
|||
|
|||
# 用户配置 |
|||
user: |
|||
password: |
|||
# 密码错误{maxRetryCount}次锁定10分钟 |
|||
maxRetryCount: 5 |
|||
|
|||
# Spring配置 |
|||
spring: |
|||
# 模板引擎 |
|||
thymeleaf: |
|||
mode: HTML |
|||
encoding: utf-8 |
|||
# 禁用缓存 |
|||
cache: false |
|||
# 资源信息 |
|||
messages: |
|||
# 国际化资源文件路径 |
|||
basename: static/i18n/messages |
|||
jackson: |
|||
time-zone: GMT+8 |
|||
date-format: yyyy-MM-dd HH:mm:ss |
|||
profiles: |
|||
active: local |
|||
# 文件上传 |
|||
servlet: |
|||
multipart: |
|||
# 单个文件大小 |
|||
max-file-size: 10MB |
|||
# 设置总上传的文件大小 |
|||
max-request-size: 20MB |
|||
# 服务模块 |
|||
devtools: |
|||
restart: |
|||
# 热部署开关 |
|||
enabled: true |
|||
|
|||
# MyBatis |
|||
mybatis: |
|||
# 搜索指定包别名 |
|||
typeAliasesPackage: com.win.**.domain |
|||
# 配置mapper的扫描,找到所有的mapper.xml映射文件 |
|||
mapperLocations: classpath*:mapper/**/*Mapper.xml |
|||
# 加载全局的配置文件 |
|||
configLocation: classpath:mybatis/mybatis-config.xml |
|||
|
|||
# PageHelper分页插件 |
|||
pagehelper: |
|||
helperDialect: mysql |
|||
supportMethodsArguments: true |
|||
params: count=countSql |
|||
|
|||
# Shiro |
|||
shiro: |
|||
user: |
|||
# 登录地址 |
|||
loginUrl: /login |
|||
# 权限认证失败地址 |
|||
unauthorizedUrl: /unauth |
|||
# 首页地址 |
|||
indexUrl: /index |
|||
# 验证码开关 |
|||
captchaEnabled: false |
|||
# 验证码类型 math 数字计算 char 字符验证 |
|||
captchaType: math |
|||
cookie: |
|||
# 设置Cookie的域名 默认空,即当前访问的域名 |
|||
domain: |
|||
# 设置cookie的有效访问路径 |
|||
path: / |
|||
# 设置HttpOnly属性 |
|||
httpOnly: true |
|||
# 设置Cookie的过期时间,天为单位 |
|||
maxAge: 30 |
|||
# 设置密钥,务必保持唯一性(生成方式,直接拷贝到main运行即可)Base64.encodeToString(CipherUtils.generateNewKey(128, "AES").getEncoded()) (默认启动生成随机秘钥,随机秘钥会导致之前客户端RememberMe Cookie无效,如设置固定秘钥RememberMe Cookie则有效) |
|||
cipherKey: |
|||
session: |
|||
# Session超时时间,-1代表永不过期(默认30分钟) |
|||
expireTime: 30 |
|||
# 同步session到数据库的周期(默认1分钟) |
|||
dbSyncPeriod: 1 |
|||
# 相隔多久检查一次session的有效性,默认就是10分钟 |
|||
validationInterval: 10 |
|||
# 同一个用户最大会话数,比如2的意思是同一个账号允许最多同时两个人登录(默认-1不限制) |
|||
maxSession: -1 |
|||
# 踢出之前登录的/之后登录的用户,默认踢出之前登录的用户 |
|||
kickoutAfter: false |
|||
rememberMe: |
|||
# 是否开启记住我 |
|||
enabled: true |
|||
|
|||
# Springdoc配置 |
|||
springdoc: |
|||
api-docs: |
|||
path: /v3/api-docs |
|||
swagger-ui: |
|||
enabled: true |
|||
path: /swagger-ui.html |
|||
tags-sorter: alpha |
|||
group-configs: |
|||
- group: 'default' |
|||
display-name: '测试模块' |
|||
paths-to-match: '/**' |
|||
packages-to-scan: com.win.web.controller.tool |
|||
|
|||
# 防止XSS攻击 |
|||
xss: |
|||
# 过滤开关 |
|||
enabled: true |
|||
# 排除链接(多个用逗号分隔) |
|||
excludes: /system/notice/* |
|||
# 匹配链接 |
|||
urlPatterns: /system/*,/monitor/*,/tool/* |
@ -0,0 +1,24 @@ |
|||
Application Version: ${ruoyi.version} |
|||
Spring Boot Version: ${spring-boot.version} |
|||
//////////////////////////////////////////////////////////////////// |
|||
// _ooOoo_ // |
|||
// o8888888o // |
|||
// 88" . "88 // |
|||
// (| ^_^ |) // |
|||
// O\ = /O // |
|||
// ____/`---'\____ // |
|||
// .' \\| |// `. // |
|||
// / \\||| : |||// \ // |
|||
// / _||||| -:- |||||- \ // |
|||
// | | \\\ - /// | | // |
|||
// | \_| ''\---/'' | | // |
|||
// \ .-\__ `-` ___/-. / // |
|||
// ___`. .' /--.--\ `. . ___ // |
|||
// ."" '< `.___\_<|>_/___.' >'"". // |
|||
// | | : `- \`.;`\ _ /`;.`/ - ` : | | // |
|||
// \ \ `-. \_ __\ /__ _/ .-` / / // |
|||
// ========`-.____`-.___\_____/___.-`____.-'======== // |
|||
// `=---=' // |
|||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // |
|||
// 佛祖保佑 永不宕机 永无BUG // |
|||
//////////////////////////////////////////////////////////////////// |
@ -0,0 +1,91 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<ehcache name="ruoyi" updateCheck="false"> |
|||
|
|||
<!-- 磁盘缓存位置 --> |
|||
<diskStore path="java.io.tmpdir"/> |
|||
|
|||
<!-- maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制 --> |
|||
<!-- maxElementsInMemory: 在内存中缓存的element的最大数目。--> |
|||
<!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 --> |
|||
<!-- timeToIdleSeconds:失效前的空闲秒数,当eternal为false时,这个属性才有效,0为不限制 --> |
|||
<!-- timeToLiveSeconds:失效前的存活秒数,创建时间到失效时间的间隔为存活时间,当eternal为false时,这个属性才有效,0为不限制 --> |
|||
<!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 --> |
|||
<!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 --> |
|||
|
|||
<!-- 默认缓存 --> |
|||
<defaultCache |
|||
maxEntriesLocalHeap="1000" |
|||
eternal="false" |
|||
timeToIdleSeconds="3600" |
|||
timeToLiveSeconds="3600" |
|||
overflowToDisk="false"> |
|||
</defaultCache> |
|||
|
|||
<!-- 登录记录缓存 锁定10分钟 --> |
|||
<cache name="loginRecordCache" |
|||
maxEntriesLocalHeap="2000" |
|||
eternal="false" |
|||
timeToIdleSeconds="600" |
|||
timeToLiveSeconds="0" |
|||
overflowToDisk="false" |
|||
statistics="false"> |
|||
</cache> |
|||
|
|||
<!-- 系统活跃用户缓存 --> |
|||
<cache name="sys-userCache" |
|||
maxEntriesLocalHeap="10000" |
|||
overflowToDisk="false" |
|||
eternal="false" |
|||
diskPersistent="false" |
|||
timeToLiveSeconds="0" |
|||
timeToIdleSeconds="0" |
|||
statistics="false"> |
|||
</cache> |
|||
|
|||
<!-- 系统用户授权缓存 没必要过期 --> |
|||
<cache name="sys-authCache" |
|||
maxEntriesLocalHeap="10000" |
|||
overflowToDisk="false" |
|||
eternal="false" |
|||
diskPersistent="false" |
|||
timeToLiveSeconds="0" |
|||
timeToIdleSeconds="0" |
|||
memoryStoreEvictionPolicy="LRU" |
|||
statistics="false"/> |
|||
|
|||
<!-- 系统缓存 --> |
|||
<cache name="sys-cache" |
|||
maxEntriesLocalHeap="1000" |
|||
eternal="true" |
|||
overflowToDisk="true" |
|||
statistics="false"> |
|||
</cache> |
|||
|
|||
<!-- 系统参数缓存 --> |
|||
<cache name="sys-config" |
|||
maxEntriesLocalHeap="1000" |
|||
eternal="true" |
|||
overflowToDisk="true" |
|||
statistics="false"> |
|||
</cache> |
|||
|
|||
<!-- 系统字典缓存 --> |
|||
<cache name="sys-dict" |
|||
maxEntriesLocalHeap="1000" |
|||
eternal="true" |
|||
overflowToDisk="true" |
|||
statistics="false"> |
|||
</cache> |
|||
|
|||
<!-- 系统会话缓存 --> |
|||
<cache name="shiro-activeSessionCache" |
|||
maxEntriesLocalHeap="10000" |
|||
overflowToDisk="false" |
|||
eternal="false" |
|||
diskPersistent="false" |
|||
timeToLiveSeconds="0" |
|||
timeToIdleSeconds="0" |
|||
statistics="false"/> |
|||
|
|||
</ehcache> |
|||
|
@ -0,0 +1,93 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<configuration> |
|||
<!-- 日志存放路径 --> |
|||
<property name="log.path" value="/home/ruoyi/logs" /> |
|||
<!-- 日志输出格式 --> |
|||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" /> |
|||
|
|||
<!-- 控制台输出 --> |
|||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> |
|||
<encoder> |
|||
<pattern>${log.pattern}</pattern> |
|||
</encoder> |
|||
</appender> |
|||
|
|||
<!-- 系统日志输出 --> |
|||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
|||
<file>${log.path}/sys-info.log</file> |
|||
<!-- 循环政策:基于时间创建日志文件 --> |
|||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
|||
<!-- 日志文件名格式 --> |
|||
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern> |
|||
<!-- 日志最大的历史 60天 --> |
|||
<maxHistory>60</maxHistory> |
|||
</rollingPolicy> |
|||
<encoder> |
|||
<pattern>${log.pattern}</pattern> |
|||
</encoder> |
|||
<filter class="ch.qos.logback.classic.filter.LevelFilter"> |
|||
<!-- 过滤的级别 --> |
|||
<level>INFO</level> |
|||
<!-- 匹配时的操作:接收(记录) --> |
|||
<onMatch>ACCEPT</onMatch> |
|||
<!-- 不匹配时的操作:拒绝(不记录) --> |
|||
<onMismatch>DENY</onMismatch> |
|||
</filter> |
|||
</appender> |
|||
|
|||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
|||
<file>${log.path}/sys-error.log</file> |
|||
<!-- 循环政策:基于时间创建日志文件 --> |
|||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
|||
<!-- 日志文件名格式 --> |
|||
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern> |
|||
<!-- 日志最大的历史 60天 --> |
|||
<maxHistory>60</maxHistory> |
|||
</rollingPolicy> |
|||
<encoder> |
|||
<pattern>${log.pattern}</pattern> |
|||
</encoder> |
|||
<filter class="ch.qos.logback.classic.filter.LevelFilter"> |
|||
<!-- 过滤的级别 --> |
|||
<level>ERROR</level> |
|||
<!-- 匹配时的操作:接收(记录) --> |
|||
<onMatch>ACCEPT</onMatch> |
|||
<!-- 不匹配时的操作:拒绝(不记录) --> |
|||
<onMismatch>DENY</onMismatch> |
|||
</filter> |
|||
</appender> |
|||
|
|||
<!-- 用户访问日志输出 --> |
|||
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
|||
<file>${log.path}/sys-user.log</file> |
|||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
|||
<!-- 按天回滚 daily --> |
|||
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern> |
|||
<!-- 日志最大的历史 60天 --> |
|||
<maxHistory>60</maxHistory> |
|||
</rollingPolicy> |
|||
<encoder> |
|||
<pattern>${log.pattern}</pattern> |
|||
</encoder> |
|||
</appender> |
|||
|
|||
<!-- 系统模块日志级别控制 --> |
|||
<logger name="com.win" level="info" /> |
|||
<!-- Spring日志级别控制 --> |
|||
<logger name="org.springframework" level="warn" /> |
|||
|
|||
<root level="info"> |
|||
<appender-ref ref="console" /> |
|||
</root> |
|||
|
|||
<!--系统操作日志--> |
|||
<root level="info"> |
|||
<appender-ref ref="file_info" /> |
|||
<appender-ref ref="file_error" /> |
|||
</root> |
|||
|
|||
<!--系统用户操作日志--> |
|||
<logger name="sys-user" level="info"> |
|||
<appender-ref ref="sys-user"/> |
|||
</logger> |
|||
</configuration> |
@ -0,0 +1,20 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE configuration |
|||
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" |
|||
"http://mybatis.org/dtd/mybatis-3-config.dtd"> |
|||
<configuration> |
|||
<!-- 全局参数 --> |
|||
<settings> |
|||
<!-- 使全局的映射器启用或禁用缓存 --> |
|||
<setting name="cacheEnabled" value="true" /> |
|||
<!-- 允许JDBC 支持自动生成主键 --> |
|||
<setting name="useGeneratedKeys" value="true" /> |
|||
<!-- 配置默认的执行器.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 --> |
|||
<setting name="defaultExecutorType" value="SIMPLE" /> |
|||
<!-- 指定 MyBatis 所用日志的具体实现 --> |
|||
<setting name="logImpl" value="SLF4J" /> |
|||
<!-- 使用驼峰命名法转换字段 --> |
|||
<!-- <setting name="mapUnderscoreToCamelCase" value="true"/> --> |
|||
</settings> |
|||
|
|||
</configuration> |
@ -0,0 +1,617 @@ |
|||
/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */ |
|||
/* |
|||
|
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2007-2013 Einar Lielmanis and contributors. |
|||
|
|||
Permission is hereby granted, free of charge, to any person |
|||
obtaining a copy of this software and associated documentation files |
|||
(the "Software"), to deal in the Software without restriction, |
|||
including without limitation the rights to use, copy, modify, merge, |
|||
publish, distribute, sublicense, and/or sell copies of the Software, |
|||
and to permit persons to whom the Software is furnished to do so, |
|||
subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be |
|||
included in all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
|||
|
|||
|
|||
Style HTML |
|||
--------------- |
|||
|
|||
Written by Nochum Sossonko, (nsossonko@hotmail.com) |
|||
|
|||
Based on code initially developed by: Einar Lielmanis, <elfz@laacz.lv> |
|||
http://jsbeautifier.org/
|
|||
|
|||
Usage: |
|||
style_html(html_source); |
|||
|
|||
style_html(html_source, options); |
|||
|
|||
The options are: |
|||
indent_size (default 4) — indentation size, |
|||
indent_char (default space) — character to indent with, |
|||
max_char (default 250) - maximum amount of characters per line (0 = disable) |
|||
brace_style (default "collapse") - "collapse" | "expand" | "end-expand" |
|||
put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line. |
|||
unformatted (defaults to inline tags) - list of tags, that shouldn't be reformatted |
|||
indent_scripts (default normal) - "keep"|"separate"|"normal" |
|||
|
|||
e.g. |
|||
|
|||
style_html(html_source, { |
|||
'indent_size': 2, |
|||
'indent_char': ' ', |
|||
'max_char': 78, |
|||
'brace_style': 'expand', |
|||
'unformatted': ['a', 'sub', 'sup', 'b', 'i', 'u'] |
|||
}); |
|||
*/ |
|||
|
|||
(function() { |
|||
|
|||
function style_html(html_source, options, js_beautify, css_beautify) { |
|||
//Wrapper function to invoke all the necessary constructors and deal with the output.
|
|||
|
|||
var multi_parser, |
|||
indent_size, |
|||
indent_character, |
|||
max_char, |
|||
brace_style, |
|||
unformatted; |
|||
|
|||
options = options || {}; |
|||
indent_size = options.indent_size || 4; |
|||
indent_character = options.indent_char || ' '; |
|||
brace_style = options.brace_style || 'collapse'; |
|||
max_char = options.max_char === 0 ? Infinity : options.max_char || 250; |
|||
unformatted = options.unformatted || ['a', 'span', 'bdo', 'em', 'strong', 'dfn', 'code', 'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'q', 'sub', 'sup', 'tt', 'i', 'b', 'big', 'small', 'u', 's', 'strike', 'font', 'ins', 'del', 'pre', 'address', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']; |
|||
|
|||
function Parser() { |
|||
|
|||
this.pos = 0; //Parser position
|
|||
this.token = ''; |
|||
this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
|
|||
this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
|
|||
parent: 'parent1', |
|||
parentcount: 1, |
|||
parent1: '' |
|||
}; |
|||
this.tag_type = ''; |
|||
this.token_text = this.last_token = this.last_text = this.token_type = ''; |
|||
|
|||
this.Utils = { //Uilities made available to the various functions
|
|||
whitespace: "\n\r\t ".split(''), |
|||
single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed,?php,?,?='.split(','), //all the single tags for HTML
|
|||
extra_liners: 'head,body,/html'.split(','), //for tags that need a line of whitespace before them
|
|||
in_array: function (what, arr) { |
|||
for (var i=0; i<arr.length; i++) { |
|||
if (what === arr[i]) { |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
}; |
|||
|
|||
this.get_content = function () { //function to capture regular content between tags
|
|||
|
|||
var input_char = '', |
|||
content = [], |
|||
space = false; //if a space is needed
|
|||
|
|||
while (this.input.charAt(this.pos) !== '<') { |
|||
if (this.pos >= this.input.length) { |
|||
return content.length?content.join(''):['', 'TK_EOF']; |
|||
} |
|||
|
|||
input_char = this.input.charAt(this.pos); |
|||
this.pos++; |
|||
this.line_char_count++; |
|||
|
|||
if (this.Utils.in_array(input_char, this.Utils.whitespace)) { |
|||
if (content.length) { |
|||
space = true; |
|||
} |
|||
this.line_char_count--; |
|||
continue; //don't want to insert unnecessary space
|
|||
} |
|||
else if (space) { |
|||
if (this.line_char_count >= this.max_char) { //insert a line when the max_char is reached
|
|||
content.push('\n'); |
|||
for (var i=0; i<this.indent_level; i++) { |
|||
content.push(this.indent_string); |
|||
} |
|||
this.line_char_count = 0; |
|||
} |
|||
else{ |
|||
content.push(' '); |
|||
this.line_char_count++; |
|||
} |
|||
space = false; |
|||
} |
|||
content.push(input_char); //letter at-a-time (or string) inserted to an array
|
|||
} |
|||
return content.length?content.join(''):''; |
|||
}; |
|||
|
|||
this.get_contents_to = function (name) { //get the full content of a script or style to pass to js_beautify
|
|||
if (this.pos === this.input.length) { |
|||
return ['', 'TK_EOF']; |
|||
} |
|||
var input_char = ''; |
|||
var content = ''; |
|||
var reg_match = new RegExp('</' + name + '\\s*>', 'igm'); |
|||
reg_match.lastIndex = this.pos; |
|||
var reg_array = reg_match.exec(this.input); |
|||
var end_script = reg_array?reg_array.index:this.input.length; //absolute end of script
|
|||
if(this.pos < end_script) { //get everything in between the script tags
|
|||
content = this.input.substring(this.pos, end_script); |
|||
this.pos = end_script; |
|||
} |
|||
return content; |
|||
}; |
|||
|
|||
this.record_tag = function (tag){ //function to record a tag and its parent in this.tags Object
|
|||
if (this.tags[tag + 'count']) { //check for the existence of this tag type
|
|||
this.tags[tag + 'count']++; |
|||
this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
|
|||
} |
|||
else { //otherwise initialize this tag type
|
|||
this.tags[tag + 'count'] = 1; |
|||
this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
|
|||
} |
|||
this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)
|
|||
this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
|
|||
}; |
|||
|
|||
this.retrieve_tag = function (tag) { //function to retrieve the opening tag to the corresponding closer
|
|||
if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
|
|||
var temp_parent = this.tags.parent; //check to see if it's a closable tag.
|
|||
while (temp_parent) { //till we reach '' (the initial value);
|
|||
if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
|
|||
break; |
|||
} |
|||
temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
|
|||
} |
|||
if (temp_parent) { //if we caught something
|
|||
this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
|
|||
this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
|
|||
} |
|||
delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
|
|||
delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
|
|||
if (this.tags[tag + 'count'] === 1) { |
|||
delete this.tags[tag + 'count']; |
|||
} |
|||
else { |
|||
this.tags[tag + 'count']--; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
this.get_tag = function (peek) { //function to get a full tag and parse its type
|
|||
var input_char = '', |
|||
content = [], |
|||
comment = '', |
|||
space = false, |
|||
tag_start, tag_end, |
|||
orig_pos = this.pos, |
|||
orig_line_char_count = this.line_char_count; |
|||
|
|||
peek = peek !== undefined ? peek : false; |
|||
|
|||
do { |
|||
if (this.pos >= this.input.length) { |
|||
if (peek) { |
|||
this.pos = orig_pos; |
|||
this.line_char_count = orig_line_char_count; |
|||
} |
|||
return content.length?content.join(''):['', 'TK_EOF']; |
|||
} |
|||
|
|||
input_char = this.input.charAt(this.pos); |
|||
this.pos++; |
|||
this.line_char_count++; |
|||
|
|||
if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
|
|||
space = true; |
|||
this.line_char_count--; |
|||
continue; |
|||
} |
|||
|
|||
if (input_char === "'" || input_char === '"') { |
|||
if (!content[1] || content[1] !== '!') { //if we're in a comment strings don't get treated specially
|
|||
input_char += this.get_unformatted(input_char); |
|||
space = true; |
|||
} |
|||
} |
|||
|
|||
if (input_char === '=') { //no space before =
|
|||
space = false; |
|||
} |
|||
|
|||
if (content.length && content[content.length-1] !== '=' && input_char !== '>' && space) { |
|||
//no space after = or before >
|
|||
if (this.line_char_count >= this.max_char) { |
|||
this.print_newline(false, content); |
|||
this.line_char_count = 0; |
|||
} |
|||
else { |
|||
content.push(' '); |
|||
this.line_char_count++; |
|||
} |
|||
space = false; |
|||
} |
|||
if (input_char === '<') { |
|||
tag_start = this.pos - 1; |
|||
} |
|||
content.push(input_char); //inserts character at-a-time (or string)
|
|||
} while (input_char !== '>'); |
|||
|
|||
var tag_complete = content.join(''); |
|||
var tag_index; |
|||
if (tag_complete.indexOf(' ') !== -1) { //if there's whitespace, thats where the tag name ends
|
|||
tag_index = tag_complete.indexOf(' '); |
|||
} |
|||
else { //otherwise go with the tag ending
|
|||
tag_index = tag_complete.indexOf('>'); |
|||
} |
|||
var tag_check = tag_complete.substring(1, tag_index).toLowerCase(); |
|||
if (tag_complete.charAt(tag_complete.length-2) === '/' || |
|||
this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)
|
|||
if ( ! peek) { |
|||
this.tag_type = 'SINGLE'; |
|||
} |
|||
} |
|||
else if (tag_check === 'script') { //for later script handling
|
|||
if ( ! peek) { |
|||
this.record_tag(tag_check); |
|||
this.tag_type = 'SCRIPT'; |
|||
} |
|||
} |
|||
else if (tag_check === 'style') { //for future style handling (for now it justs uses get_content)
|
|||
if ( ! peek) { |
|||
this.record_tag(tag_check); |
|||
this.tag_type = 'STYLE'; |
|||
} |
|||
} |
|||
else if (this.is_unformatted(tag_check, unformatted)) { // do not reformat the "unformatted" tags
|
|||
comment = this.get_unformatted('</'+tag_check+'>', tag_complete); //...delegate to get_unformatted function
|
|||
content.push(comment); |
|||
// Preserve collapsed whitespace either before or after this tag.
|
|||
if (tag_start > 0 && this.Utils.in_array(this.input.charAt(tag_start - 1), this.Utils.whitespace)){ |
|||
content.splice(0, 0, this.input.charAt(tag_start - 1)); |
|||
} |
|||
tag_end = this.pos - 1; |
|||
if (this.Utils.in_array(this.input.charAt(tag_end + 1), this.Utils.whitespace)){ |
|||
content.push(this.input.charAt(tag_end + 1)); |
|||
} |
|||
this.tag_type = 'SINGLE'; |
|||
} |
|||
else if (tag_check.charAt(0) === '!') { //peek for <!-- comment
|
|||
if (tag_check.indexOf('[if') !== -1) { //peek for <!--[if conditional comment
|
|||
if (tag_complete.indexOf('!IE') !== -1) { //this type needs a closing --> so...
|
|||
comment = this.get_unformatted('-->', tag_complete); //...delegate to get_unformatted
|
|||
content.push(comment); |
|||
} |
|||
if ( ! peek) { |
|||
this.tag_type = 'START'; |
|||
} |
|||
} |
|||
else if (tag_check.indexOf('[endif') !== -1) {//peek for <!--[endif end conditional comment
|
|||
this.tag_type = 'END'; |
|||
this.unindent(); |
|||
} |
|||
else if (tag_check.indexOf('[cdata[') !== -1) { //if it's a <[cdata[ comment...
|
|||
comment = this.get_unformatted(']]>', tag_complete); //...delegate to get_unformatted function
|
|||
content.push(comment); |
|||
if ( ! peek) { |
|||
this.tag_type = 'SINGLE'; //<![CDATA[ comments are treated like single tags
|
|||
} |
|||
} |
|||
else { |
|||
comment = this.get_unformatted('-->', tag_complete); |
|||
content.push(comment); |
|||
this.tag_type = 'SINGLE'; |
|||
} |
|||
} |
|||
else if ( ! peek) { |
|||
if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
|
|||
this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
|
|||
this.tag_type = 'END'; |
|||
} |
|||
else { //otherwise it's a start-tag
|
|||
this.record_tag(tag_check); //push it on the tag stack
|
|||
this.tag_type = 'START'; |
|||
} |
|||
if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
|
|||
this.print_newline(true, this.output); |
|||
} |
|||
} |
|||
|
|||
if (peek) { |
|||
this.pos = orig_pos; |
|||
this.line_char_count = orig_line_char_count; |
|||
} |
|||
|
|||
return content.join(''); //returns fully formatted tag
|
|||
}; |
|||
|
|||
this.get_unformatted = function (delimiter, orig_tag) { //function to return unformatted content in its entirety
|
|||
|
|||
if (orig_tag && orig_tag.toLowerCase().indexOf(delimiter) !== -1) { |
|||
return ''; |
|||
} |
|||
var input_char = ''; |
|||
var content = ''; |
|||
var space = true; |
|||
do { |
|||
|
|||
if (this.pos >= this.input.length) { |
|||
return content; |
|||
} |
|||
|
|||
input_char = this.input.charAt(this.pos); |
|||
this.pos++; |
|||
|
|||
if (this.Utils.in_array(input_char, this.Utils.whitespace)) { |
|||
if (!space) { |
|||
this.line_char_count--; |
|||
continue; |
|||
} |
|||
if (input_char === '\n' || input_char === '\r') { |
|||
content += '\n'; |
|||
/* Don't change tab indention for unformatted blocks. If using code for html editing, this will greatly affect <pre> tags if they are specified in the 'unformatted array' |
|||
for (var i=0; i<this.indent_level; i++) { |
|||
content += this.indent_string; |
|||
} |
|||
space = false; //...and make sure other indentation is erased
|
|||
*/ |
|||
this.line_char_count = 0; |
|||
continue; |
|||
} |
|||
} |
|||
content += input_char; |
|||
this.line_char_count++; |
|||
space = true; |
|||
|
|||
|
|||
} while (content.toLowerCase().indexOf(delimiter) === -1); |
|||
return content; |
|||
}; |
|||
|
|||
this.get_token = function () { //initial handler for token-retrieval
|
|||
var token; |
|||
|
|||
if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript
|
|||
var type = this.last_token.substr(7); |
|||
token = this.get_contents_to(type); |
|||
if (typeof token !== 'string') { |
|||
return token; |
|||
} |
|||
return [token, 'TK_' + type]; |
|||
} |
|||
if (this.current_mode === 'CONTENT') { |
|||
token = this.get_content(); |
|||
if (typeof token !== 'string') { |
|||
return token; |
|||
} |
|||
else { |
|||
return [token, 'TK_CONTENT']; |
|||
} |
|||
} |
|||
|
|||
if (this.current_mode === 'TAG') { |
|||
token = this.get_tag(); |
|||
if (typeof token !== 'string') { |
|||
return token; |
|||
} |
|||
else { |
|||
var tag_name_type = 'TK_TAG_' + this.tag_type; |
|||
return [token, tag_name_type]; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
this.get_full_indent = function (level) { |
|||
level = this.indent_level + level || 0; |
|||
if (level < 1) { |
|||
return ''; |
|||
} |
|||
|
|||
return Array(level + 1).join(this.indent_string); |
|||
}; |
|||
|
|||
this.is_unformatted = function(tag_check, unformatted) { |
|||
//is this an HTML5 block-level link?
|
|||
if (!this.Utils.in_array(tag_check, unformatted)){ |
|||
return false; |
|||
} |
|||
|
|||
if (tag_check.toLowerCase() !== 'a' || !this.Utils.in_array('a', unformatted)){ |
|||
return true; |
|||
} |
|||
|
|||
//at this point we have an tag; is its first child something we want to remain
|
|||
//unformatted?
|
|||
var next_tag = this.get_tag(true /* peek. */); |
|||
|
|||
// tets next_tag to see if it is just html tag (no external content)
|
|||
var tag = (next_tag || "").match(/^\s*<\s*\/?([a-z]*)\s*[^>]*>\s*$/); |
|||
|
|||
// if next_tag comes back but is not an isolated tag, then
|
|||
// let's treat the 'a' tag as having content
|
|||
// and respect the unformatted option
|
|||
if (!tag || this.Utils.in_array(tag, unformatted)){ |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
}; |
|||
|
|||
this.printer = function (js_source, indent_character, indent_size, max_char, brace_style) { //handles input/output and some other printing functions
|
|||
|
|||
this.input = js_source || ''; //gets the input for the Parser
|
|||
this.output = []; |
|||
this.indent_character = indent_character; |
|||
this.indent_string = ''; |
|||
this.indent_size = indent_size; |
|||
this.brace_style = brace_style; |
|||
this.indent_level = 0; |
|||
this.max_char = max_char; |
|||
this.line_char_count = 0; //count to see if max_char was exceeded
|
|||
|
|||
for (var i=0; i<this.indent_size; i++) { |
|||
this.indent_string += this.indent_character; |
|||
} |
|||
|
|||
this.print_newline = function (ignore, arr) { |
|||
this.line_char_count = 0; |
|||
if (!arr || !arr.length) { |
|||
return; |
|||
} |
|||
if (!ignore) { //we might want the extra line
|
|||
while (this.Utils.in_array(arr[arr.length-1], this.Utils.whitespace)) { |
|||
arr.pop(); |
|||
} |
|||
} |
|||
arr.push('\n'); |
|||
for (var i=0; i<this.indent_level; i++) { |
|||
arr.push(this.indent_string); |
|||
} |
|||
}; |
|||
|
|||
this.print_token = function (text) { |
|||
this.output.push(text); |
|||
}; |
|||
|
|||
this.indent = function () { |
|||
this.indent_level++; |
|||
}; |
|||
|
|||
this.unindent = function () { |
|||
if (this.indent_level > 0) { |
|||
this.indent_level--; |
|||
} |
|||
}; |
|||
}; |
|||
return this; |
|||
} |
|||
|
|||
/*_____________________--------------------_____________________*/ |
|||
|
|||
multi_parser = new Parser(); //wrapping functions Parser
|
|||
multi_parser.printer(html_source, indent_character, indent_size, max_char, brace_style); //initialize starting values
|
|||
|
|||
while (true) { |
|||
var t = multi_parser.get_token(); |
|||
multi_parser.token_text = t[0]; |
|||
multi_parser.token_type = t[1]; |
|||
|
|||
if (multi_parser.token_type === 'TK_EOF') { |
|||
break; |
|||
} |
|||
|
|||
switch (multi_parser.token_type) { |
|||
case 'TK_TAG_START': |
|||
multi_parser.print_newline(false, multi_parser.output); |
|||
multi_parser.print_token(multi_parser.token_text); |
|||
multi_parser.indent(); |
|||
multi_parser.current_mode = 'CONTENT'; |
|||
break; |
|||
case 'TK_TAG_STYLE': |
|||
case 'TK_TAG_SCRIPT': |
|||
multi_parser.print_newline(false, multi_parser.output); |
|||
multi_parser.print_token(multi_parser.token_text); |
|||
multi_parser.current_mode = 'CONTENT'; |
|||
break; |
|||
case 'TK_TAG_END': |
|||
//Print new line only if the tag has no content and has child
|
|||
if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') { |
|||
var tag_name = multi_parser.token_text.match(/\w+/)[0]; |
|||
var tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length -1].match(/<\s*(\w+)/); |
|||
if (tag_extracted_from_last_output === null || tag_extracted_from_last_output[1] !== tag_name) { |
|||
multi_parser.print_newline(true, multi_parser.output); |
|||
} |
|||
} |
|||
multi_parser.print_token(multi_parser.token_text); |
|||
multi_parser.current_mode = 'CONTENT'; |
|||
break; |
|||
case 'TK_TAG_SINGLE': |
|||
// Don't add a newline before elements that should remain unformatted.
|
|||
var tag_check = multi_parser.token_text.match(/^\s*<([a-z]+)/i); |
|||
if (!tag_check || !multi_parser.Utils.in_array(tag_check[1], unformatted)){ |
|||
multi_parser.print_newline(false, multi_parser.output); |
|||
} |
|||
multi_parser.print_token(multi_parser.token_text); |
|||
multi_parser.current_mode = 'CONTENT'; |
|||
break; |
|||
case 'TK_CONTENT': |
|||
if (multi_parser.token_text !== '') { |
|||
multi_parser.print_token(multi_parser.token_text); |
|||
} |
|||
multi_parser.current_mode = 'TAG'; |
|||
break; |
|||
case 'TK_STYLE': |
|||
case 'TK_SCRIPT': |
|||
if (multi_parser.token_text !== '') { |
|||
multi_parser.output.push('\n'); |
|||
var text = multi_parser.token_text, |
|||
_beautifier, |
|||
script_indent_level = 1; |
|||
if (multi_parser.token_type === 'TK_SCRIPT') { |
|||
_beautifier = typeof js_beautify === 'function' && js_beautify; |
|||
} else if (multi_parser.token_type === 'TK_STYLE') { |
|||
_beautifier = typeof css_beautify === 'function' && css_beautify; |
|||
} |
|||
|
|||
if (options.indent_scripts === "keep") { |
|||
script_indent_level = 0; |
|||
} else if (options.indent_scripts === "separate") { |
|||
script_indent_level = -multi_parser.indent_level; |
|||
} |
|||
|
|||
var indentation = multi_parser.get_full_indent(script_indent_level); |
|||
if (_beautifier) { |
|||
// call the Beautifier if avaliable
|
|||
text = _beautifier(text.replace(/^\s*/, indentation), options); |
|||
} else { |
|||
// simply indent the string otherwise
|
|||
var white = text.match(/^\s*/)[0]; |
|||
var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1; |
|||
var reindent = multi_parser.get_full_indent(script_indent_level -_level); |
|||
text = text.replace(/^\s*/, indentation) |
|||
.replace(/\r\n|\r|\n/g, '\n' + reindent) |
|||
.replace(/\s*$/, ''); |
|||
} |
|||
if (text) { |
|||
multi_parser.print_token(text); |
|||
multi_parser.print_newline(true, multi_parser.output); |
|||
} |
|||
} |
|||
multi_parser.current_mode = 'TAG'; |
|||
break; |
|||
} |
|||
multi_parser.last_token = multi_parser.token_type; |
|||
multi_parser.last_text = multi_parser.token_text; |
|||
} |
|||
return multi_parser.output.join(''); |
|||
} |
|||
|
|||
// If we're running a web page and don't have either of the above, add our one global
|
|||
window.html_beautify = function(html_source, options) { |
|||
return style_html(html_source, options, window.js_beautify, window.css_beautify); |
|||
}; |
|||
|
|||
}()); |
@ -0,0 +1,620 @@ |
|||
/*! |
|||
* jQuery blockUI plugin |
|||
* Version 2.70.0-2014.11.23 |
|||
* Requires jQuery v1.7 or later |
|||
* |
|||
* Examples at: http://malsup.com/jquery/block/
|
|||
* Copyright (c) 2007-2013 M. Alsup |
|||
* Dual licensed under the MIT and GPL licenses: |
|||
* http://www.opensource.org/licenses/mit-license.php
|
|||
* http://www.gnu.org/licenses/gpl.html
|
|||
* |
|||
* Thanks to Amir-Hossein Sobhi for some excellent contributions! |
|||
*/ |
|||
|
|||
;(function() { |
|||
/*jshint eqeqeq:false curly:false latedef:false */ |
|||
"use strict"; |
|||
|
|||
function setup($) { |
|||
$.fn._fadeIn = $.fn.fadeIn; |
|||
|
|||
var noOp = $.noop || function() {}; |
|||
|
|||
// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
|
|||
// confusing userAgent strings on Vista)
|
|||
var msie = /MSIE/.test(navigator.userAgent); |
|||
var ie6 = /MSIE 6.0/.test(navigator.userAgent) && ! /MSIE 8.0/.test(navigator.userAgent); |
|||
var mode = document.documentMode || 0; |
|||
var setExpr = $.isFunction( document.createElement('div').style.setExpression ); |
|||
|
|||
// global $ methods for blocking/unblocking the entire page
|
|||
$.blockUI = function(opts) { install(window, opts); }; |
|||
$.unblockUI = function(opts) { remove(window, opts); }; |
|||
|
|||
// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
|
|||
$.growlUI = function(title, message, timeout, onClose) { |
|||
var $m = $('<div class="growlUI"></div>'); |
|||
if (title) $m.append('<h1>'+title+'</h1>'); |
|||
if (message) $m.append('<h2>'+message+'</h2>'); |
|||
if (timeout === undefined) timeout = 3000; |
|||
|
|||
// Added by konapun: Set timeout to 30 seconds if this growl is moused over, like normal toast notifications
|
|||
var callBlock = function(opts) { |
|||
opts = opts || {}; |
|||
|
|||
$.blockUI({ |
|||
message: $m, |
|||
fadeIn : typeof opts.fadeIn !== 'undefined' ? opts.fadeIn : 700, |
|||
fadeOut: typeof opts.fadeOut !== 'undefined' ? opts.fadeOut : 1000, |
|||
timeout: typeof opts.timeout !== 'undefined' ? opts.timeout : timeout, |
|||
centerY: false, |
|||
showOverlay: false, |
|||
onUnblock: onClose, |
|||
css: $.blockUI.defaults.growlCSS |
|||
}); |
|||
}; |
|||
|
|||
callBlock(); |
|||
var nonmousedOpacity = $m.css('opacity'); |
|||
$m.mouseover(function() { |
|||
callBlock({ |
|||
fadeIn: 0, |
|||
timeout: 30000 |
|||
}); |
|||
|
|||
var displayBlock = $('.blockMsg'); |
|||
displayBlock.stop(); // cancel fadeout if it has started
|
|||
displayBlock.fadeTo(300, 1); // make it easier to read the message by removing transparency
|
|||
}).mouseout(function() { |
|||
$('.blockMsg').fadeOut(1000); |
|||
}); |
|||
// End konapun additions
|
|||
}; |
|||
|
|||
// plugin method for blocking element content
|
|||
$.fn.block = function(opts) { |
|||
if ( this[0] === window ) { |
|||
$.blockUI( opts ); |
|||
return this; |
|||
} |
|||
var fullOpts = $.extend({}, $.blockUI.defaults, opts || {}); |
|||
this.each(function() { |
|||
var $el = $(this); |
|||
if (fullOpts.ignoreIfBlocked && $el.data('blockUI.isBlocked')) |
|||
return; |
|||
$el.unblock({ fadeOut: 0 }); |
|||
}); |
|||
|
|||
return this.each(function() { |
|||
if ($.css(this,'position') == 'static') { |
|||
this.style.position = 'relative'; |
|||
$(this).data('blockUI.static', true); |
|||
} |
|||
this.style.zoom = 1; // force 'hasLayout' in ie
|
|||
install(this, opts); |
|||
}); |
|||
}; |
|||
|
|||
// plugin method for unblocking element content
|
|||
$.fn.unblock = function(opts) { |
|||
if ( this[0] === window ) { |
|||
$.unblockUI( opts ); |
|||
return this; |
|||
} |
|||
return this.each(function() { |
|||
remove(this, opts); |
|||
}); |
|||
}; |
|||
|
|||
$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
|
|||
|
|||
// override these in your code to change the default behavior and style
|
|||
$.blockUI.defaults = { |
|||
// message displayed when blocking (use null for no message)
|
|||
message: '<div class="loaderbox"><div class="loading-activity"></div> 加载中......</div>', |
|||
|
|||
title: null, // title string; only used when theme == true
|
|||
draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
|
|||
|
|||
theme: false, // set to true to use with jQuery UI themes
|
|||
|
|||
// styles for the message when blocking; if you wish to disable
|
|||
// these and use an external stylesheet then do this in your code:
|
|||
// $.blockUI.defaults.css = {};
|
|||
css: { |
|||
padding: 0, |
|||
margin: 0, |
|||
width: '30%', |
|||
top: '40%', |
|||
left: '35%', |
|||
textAlign: 'center', |
|||
color: '#000', |
|||
border: '0px', |
|||
backgroundColor:'transparent', |
|||
cursor: 'wait' |
|||
}, |
|||
|
|||
// minimal style set used when themes are used
|
|||
themedCSS: { |
|||
width: '30%', |
|||
top: '40%', |
|||
left: '35%' |
|||
}, |
|||
|
|||
// styles for the overlay
|
|||
overlayCSS: { |
|||
backgroundColor: '#000', |
|||
opacity: 0.6, |
|||
cursor: 'wait' |
|||
}, |
|||
|
|||
// style to replace wait cursor before unblocking to correct issue
|
|||
// of lingering wait cursor
|
|||
cursorReset: 'default', |
|||
|
|||
// styles applied when using $.growlUI
|
|||
growlCSS: { |
|||
width: '350px', |
|||
top: '10px', |
|||
left: '', |
|||
right: '10px', |
|||
border: 'none', |
|||
padding: '5px', |
|||
opacity: 0.6, |
|||
cursor: 'default', |
|||
color: '#fff', |
|||
backgroundColor: '#000', |
|||
'-webkit-border-radius':'10px', |
|||
'-moz-border-radius': '10px', |
|||
'border-radius': '10px' |
|||
}, |
|||
|
|||
// IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
|
|||
// (hat tip to Jorge H. N. de Vasconcelos)
|
|||
/*jshint scripturl:true */ |
|||
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank', |
|||
|
|||
// force usage of iframe in non-IE browsers (handy for blocking applets)
|
|||
forceIframe: false, |
|||
|
|||
// z-index for the blocking overlay
|
|||
baseZ: 1000, |
|||
|
|||
// set these to true to have the message automatically centered
|
|||
centerX: true, // <-- only effects element blocking (page block controlled via css above)
|
|||
centerY: true, |
|||
|
|||
// allow body element to be stetched in ie6; this makes blocking look better
|
|||
// on "short" pages. disable if you wish to prevent changes to the body height
|
|||
allowBodyStretch: true, |
|||
|
|||
// enable if you want key and mouse events to be disabled for content that is blocked
|
|||
bindEvents: true, |
|||
|
|||
// be default blockUI will supress tab navigation from leaving blocking content
|
|||
// (if bindEvents is true)
|
|||
constrainTabKey: true, |
|||
|
|||
// fadeIn time in millis; set to 0 to disable fadeIn on block
|
|||
fadeIn: 200, |
|||
|
|||
// fadeOut time in millis; set to 0 to disable fadeOut on unblock
|
|||
fadeOut: 400, |
|||
|
|||
// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
|
|||
timeout: 0, |
|||
|
|||
// disable if you don't want to show the overlay
|
|||
showOverlay: true, |
|||
|
|||
// if true, focus will be placed in the first available input field when
|
|||
// page blocking
|
|||
focusInput: true, |
|||
|
|||
// elements that can receive focus
|
|||
focusableElements: ':input:enabled:visible', |
|||
|
|||
// suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
|
|||
// no longer needed in 2012
|
|||
// applyPlatformOpacityRules: true,
|
|||
|
|||
// callback method invoked when fadeIn has completed and blocking message is visible
|
|||
onBlock: null, |
|||
|
|||
// callback method invoked when unblocking has completed; the callback is
|
|||
// passed the element that has been unblocked (which is the window object for page
|
|||
// blocks) and the options that were passed to the unblock call:
|
|||
// onUnblock(element, options)
|
|||
onUnblock: null, |
|||
|
|||
// callback method invoked when the overlay area is clicked.
|
|||
// setting this will turn the cursor to a pointer, otherwise cursor defined in overlayCss will be used.
|
|||
onOverlayClick: null, |
|||
|
|||
// don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
|
|||
quirksmodeOffsetHack: 4, |
|||
|
|||
// class name of the message block
|
|||
blockMsgClass: 'blockMsg', |
|||
|
|||
// if it is already blocked, then ignore it (don't unblock and reblock)
|
|||
ignoreIfBlocked: false |
|||
}; |
|||
|
|||
// private data and functions follow...
|
|||
|
|||
var pageBlock = null; |
|||
var pageBlockEls = []; |
|||
|
|||
function install(el, opts) { |
|||
var css, themedCSS; |
|||
var full = (el == window); |
|||
var msg = (opts && opts.message !== undefined ? opts.message : undefined); |
|||
opts = $.extend({}, $.blockUI.defaults, opts || {}); |
|||
|
|||
if (opts.ignoreIfBlocked && $(el).data('blockUI.isBlocked')) |
|||
return; |
|||
|
|||
opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {}); |
|||
css = $.extend({}, $.blockUI.defaults.css, opts.css || {}); |
|||
if (opts.onOverlayClick) |
|||
opts.overlayCSS.cursor = 'pointer'; |
|||
|
|||
themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {}); |
|||
msg = msg === undefined ? opts.message : msg; |
|||
|
|||
// remove the current block (if there is one)
|
|||
if (full && pageBlock) |
|||
remove(window, {fadeOut:0}); |
|||
|
|||
// if an existing element is being used as the blocking content then we capture
|
|||
// its current place in the DOM (and current display style) so we can restore
|
|||
// it when we unblock
|
|||
if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) { |
|||
var node = msg.jquery ? msg[0] : msg; |
|||
var data = {}; |
|||
$(el).data('blockUI.history', data); |
|||
data.el = node; |
|||
data.parent = node.parentNode; |
|||
data.display = node.style.display; |
|||
data.position = node.style.position; |
|||
if (data.parent) |
|||
data.parent.removeChild(node); |
|||
} |
|||
|
|||
$(el).data('blockUI.onUnblock', opts.onUnblock); |
|||
var z = opts.baseZ; |
|||
|
|||
// blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
|
|||
// layer1 is the iframe layer which is used to supress bleed through of underlying content
|
|||
// layer2 is the overlay layer which has opacity and a wait cursor (by default)
|
|||
// layer3 is the message content that is displayed while blocking
|
|||
var lyr1, lyr2, lyr3, s; |
|||
if (msie || opts.forceIframe) |
|||
lyr1 = $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>'); |
|||
else |
|||
lyr1 = $('<div class="blockUI" style="display:none"></div>'); |
|||
|
|||
if (opts.theme) |
|||
lyr2 = $('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+ (z++) +';display:none"></div>'); |
|||
else |
|||
lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>'); |
|||
|
|||
if (opts.theme && full) { |
|||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:fixed">'; |
|||
if ( opts.title ) { |
|||
s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>'; |
|||
} |
|||
s += '<div class="ui-widget-content ui-dialog-content"></div>'; |
|||
s += '</div>'; |
|||
} |
|||
else if (opts.theme) { |
|||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(z+10)+';display:none;position:absolute">'; |
|||
if ( opts.title ) { |
|||
s += '<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(opts.title || ' ')+'</div>'; |
|||
} |
|||
s += '<div class="ui-widget-content ui-dialog-content"></div>'; |
|||
s += '</div>'; |
|||
} |
|||
else if (full) { |
|||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>'; |
|||
} |
|||
else { |
|||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>'; |
|||
} |
|||
lyr3 = $(s); |
|||
|
|||
// if we have a message, style it
|
|||
if (msg) { |
|||
if (opts.theme) { |
|||
lyr3.css(themedCSS); |
|||
lyr3.addClass('ui-widget-content'); |
|||
} |
|||
else |
|||
lyr3.css(css); |
|||
} |
|||
|
|||
// style the overlay
|
|||
if (!opts.theme /*&& (!opts.applyPlatformOpacityRules)*/) |
|||
lyr2.css(opts.overlayCSS); |
|||
lyr2.css('position', full ? 'fixed' : 'absolute'); |
|||
|
|||
// make iframe layer transparent in IE
|
|||
if (msie || opts.forceIframe) |
|||
lyr1.css('opacity',0.0); |
|||
|
|||
//$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
|
|||
var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el); |
|||
$.each(layers, function() { |
|||
this.appendTo($par); |
|||
}); |
|||
|
|||
if (opts.theme && opts.draggable && $.fn.draggable) { |
|||
lyr3.draggable({ |
|||
handle: '.ui-dialog-titlebar', |
|||
cancel: 'li' |
|||
}); |
|||
} |
|||
|
|||
// ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
|
|||
var expr = setExpr && (!$.support.boxModel || $('object,embed', full ? null : el).length > 0); |
|||
if (ie6 || expr) { |
|||
// give body 100% height
|
|||
if (full && opts.allowBodyStretch && $.support.boxModel) |
|||
$('html,body').css('height','100%'); |
|||
|
|||
// fix ie6 issue when blocked element has a border width
|
|||
if ((ie6 || !$.support.boxModel) && !full) { |
|||
var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth'); |
|||
var fixT = t ? '(0 - '+t+')' : 0; |
|||
var fixL = l ? '(0 - '+l+')' : 0; |
|||
} |
|||
|
|||
// simulate fixed position
|
|||
$.each(layers, function(i,o) { |
|||
var s = o[0].style; |
|||
s.position = 'absolute'; |
|||
if (i < 2) { |
|||
if (full) |
|||
s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"'); |
|||
else |
|||
s.setExpression('height','this.parentNode.offsetHeight + "px"'); |
|||
if (full) |
|||
s.setExpression('width','jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'); |
|||
else |
|||
s.setExpression('width','this.parentNode.offsetWidth + "px"'); |
|||
if (fixL) s.setExpression('left', fixL); |
|||
if (fixT) s.setExpression('top', fixT); |
|||
} |
|||
else if (opts.centerY) { |
|||
if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'); |
|||
s.marginTop = 0; |
|||
} |
|||
else if (!opts.centerY && full) { |
|||
var top = (opts.css && opts.css.top) ? parseInt(opts.css.top, 10) : 0; |
|||
var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"'; |
|||
s.setExpression('top',expression); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
// show the message
|
|||
if (msg) { |
|||
if (opts.theme) |
|||
lyr3.find('.ui-widget-content').append(msg); |
|||
else |
|||
lyr3.append(msg); |
|||
if (msg.jquery || msg.nodeType) |
|||
$(msg).show(); |
|||
} |
|||
|
|||
if ((msie || opts.forceIframe) && opts.showOverlay) |
|||
lyr1.show(); // opacity is zero
|
|||
if (opts.fadeIn) { |
|||
var cb = opts.onBlock ? opts.onBlock : noOp; |
|||
var cb1 = (opts.showOverlay && !msg) ? cb : noOp; |
|||
var cb2 = msg ? cb : noOp; |
|||
if (opts.showOverlay) |
|||
lyr2._fadeIn(opts.fadeIn, cb1); |
|||
if (msg) |
|||
lyr3._fadeIn(opts.fadeIn, cb2); |
|||
} |
|||
else { |
|||
if (opts.showOverlay) |
|||
lyr2.show(); |
|||
if (msg) |
|||
lyr3.show(); |
|||
if (opts.onBlock) |
|||
opts.onBlock.bind(lyr3)(); |
|||
} |
|||
|
|||
// bind key and mouse events
|
|||
bind(1, el, opts); |
|||
|
|||
if (full) { |
|||
pageBlock = lyr3[0]; |
|||
pageBlockEls = $(opts.focusableElements,pageBlock); |
|||
if (opts.focusInput) |
|||
setTimeout(focus, 20); |
|||
} |
|||
else |
|||
center(lyr3[0], opts.centerX, opts.centerY); |
|||
|
|||
if (opts.timeout) { |
|||
// auto-unblock
|
|||
var to = setTimeout(function() { |
|||
if (full) |
|||
$.unblockUI(opts); |
|||
else |
|||
$(el).unblock(opts); |
|||
}, opts.timeout); |
|||
$(el).data('blockUI.timeout', to); |
|||
} |
|||
} |
|||
|
|||
// remove the block
|
|||
function remove(el, opts) { |
|||
var count; |
|||
var full = (el == window); |
|||
var $el = $(el); |
|||
var data = $el.data('blockUI.history'); |
|||
var to = $el.data('blockUI.timeout'); |
|||
if (to) { |
|||
clearTimeout(to); |
|||
$el.removeData('blockUI.timeout'); |
|||
} |
|||
opts = $.extend({}, $.blockUI.defaults, opts || {}); |
|||
bind(0, el, opts); // unbind events
|
|||
|
|||
if (opts.onUnblock === null) { |
|||
opts.onUnblock = $el.data('blockUI.onUnblock'); |
|||
$el.removeData('blockUI.onUnblock'); |
|||
} |
|||
|
|||
var els; |
|||
if (full) // crazy selector to handle odd field errors in ie6/7
|
|||
els = $('body').children().filter('.blockUI').add('body > .blockUI'); |
|||
else |
|||
els = $el.find('>.blockUI'); |
|||
|
|||
// fix cursor issue
|
|||
if ( opts.cursorReset ) { |
|||
if ( els.length > 1 ) |
|||
els[1].style.cursor = opts.cursorReset; |
|||
if ( els.length > 2 ) |
|||
els[2].style.cursor = opts.cursorReset; |
|||
} |
|||
|
|||
if (full) |
|||
pageBlock = pageBlockEls = null; |
|||
|
|||
if (opts.fadeOut) { |
|||
count = els.length; |
|||
els.stop().fadeOut(opts.fadeOut, function() { |
|||
if ( --count === 0) |
|||
reset(els,data,opts,el); |
|||
}); |
|||
} |
|||
else |
|||
reset(els, data, opts, el); |
|||
} |
|||
|
|||
// move blocking element back into the DOM where it started
|
|||
function reset(els,data,opts,el) { |
|||
var $el = $(el); |
|||
if ( $el.data('blockUI.isBlocked') ) |
|||
return; |
|||
|
|||
els.each(function(i,o) { |
|||
// remove via DOM calls so we don't lose event handlers
|
|||
if (this.parentNode) |
|||
this.parentNode.removeChild(this); |
|||
}); |
|||
|
|||
if (data && data.el) { |
|||
data.el.style.display = data.display; |
|||
data.el.style.position = data.position; |
|||
data.el.style.cursor = 'default'; // #59
|
|||
if (data.parent) |
|||
data.parent.appendChild(data.el); |
|||
$el.removeData('blockUI.history'); |
|||
} |
|||
|
|||
if ($el.data('blockUI.static')) { |
|||
$el.css('position', 'static'); // #22
|
|||
} |
|||
|
|||
if (typeof opts.onUnblock == 'function') |
|||
opts.onUnblock(el,opts); |
|||
|
|||
// fix issue in Safari 6 where block artifacts remain until reflow
|
|||
var body = $(document.body), w = body.width(), cssW = body[0].style.width; |
|||
body.width(w-1).width(w); |
|||
body[0].style.width = cssW; |
|||
} |
|||
|
|||
// bind/unbind the handler
|
|||
function bind(b, el, opts) { |
|||
var full = el == window, $el = $(el); |
|||
|
|||
// don't bother unbinding if there is nothing to unbind
|
|||
if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) |
|||
return; |
|||
|
|||
$el.data('blockUI.isBlocked', b); |
|||
|
|||
// don't bind events when overlay is not in use or if bindEvents is false
|
|||
if (!full || !opts.bindEvents || (b && !opts.showOverlay)) |
|||
return; |
|||
|
|||
// bind anchors and inputs for mouse and key events
|
|||
var events = 'mousedown mouseup keydown keypress keyup touchstart touchend touchmove'; |
|||
if (b) |
|||
$(document).bind(events, opts, handler); |
|||
else |
|||
$(document).unbind(events, handler); |
|||
|
|||
// former impl...
|
|||
// var $e = $('a,:input');
|
|||
// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
|
|||
} |
|||
|
|||
// event handler to suppress keyboard/mouse events when blocking
|
|||
function handler(e) { |
|||
// allow tab navigation (conditionally)
|
|||
if (e.type === 'keydown' && e.keyCode && e.keyCode == 9) { |
|||
if (pageBlock && e.data.constrainTabKey) { |
|||
var els = pageBlockEls; |
|||
var fwd = !e.shiftKey && e.target === els[els.length-1]; |
|||
var back = e.shiftKey && e.target === els[0]; |
|||
if (fwd || back) { |
|||
setTimeout(function(){focus(back);},10); |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
var opts = e.data; |
|||
var target = $(e.target); |
|||
if (target.hasClass('blockOverlay') && opts.onOverlayClick) |
|||
opts.onOverlayClick(e); |
|||
|
|||
// allow events within the message content
|
|||
if (target.parents('div.' + opts.blockMsgClass).length > 0) |
|||
return true; |
|||
|
|||
// allow events for content that is not being blocked
|
|||
return target.parents().children().filter('div.blockUI').length === 0; |
|||
} |
|||
|
|||
function focus(back) { |
|||
if (!pageBlockEls) |
|||
return; |
|||
var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0]; |
|||
if (e) |
|||
e.focus(); |
|||
} |
|||
|
|||
function center(el, x, y) { |
|||
var p = el.parentNode, s = el.style; |
|||
var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth'); |
|||
var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth'); |
|||
if (x) s.left = l > 0 ? (l+'px') : '0'; |
|||
if (y) s.top = t > 0 ? (t+'px') : '0'; |
|||
} |
|||
|
|||
function sz(el, p) { |
|||
return parseInt($.css(el,p),10)||0; |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
/*global define:true */ |
|||
if (typeof define === 'function' && define.amd && define.amd.jQuery) { |
|||
define(['jquery'], setup); |
|||
} else { |
|||
setup(jQuery); |
|||
} |
|||
|
|||
})(); |
@ -0,0 +1,688 @@ |
|||
/*! |
|||
* bootstrap-fileinput v5.5.2 |
|||
* http://plugins.krajee.com/file-input |
|||
* |
|||
* Krajee default styling for bootstrap-fileinput. |
|||
* |
|||
* Author: Kartik Visweswaran |
|||
* Copyright: 2014 - 2022, Kartik Visweswaran, Krajee.com |
|||
* |
|||
* Licensed under the BSD-3-Clause |
|||
* https://github.com/kartik-v/bootstrap-fileinput/blob/master/LICENSE.md |
|||
*/ |
|||
|
|||
.file-loading input[type=file], |
|||
input[type=file].file-loading { |
|||
width: 0; |
|||
height: 0; |
|||
} |
|||
|
|||
.file-no-browse { |
|||
position: absolute; |
|||
left: 50%; |
|||
bottom: 20%; |
|||
width: 1px; |
|||
height: 1px; |
|||
font-size: 0; |
|||
opacity: 0; |
|||
border: none; |
|||
background: none; |
|||
outline: none; |
|||
box-shadow: none; |
|||
} |
|||
|
|||
.kv-hidden, |
|||
.file-caption-icon, |
|||
.file-zoom-dialog .modal-header:before, |
|||
.file-zoom-dialog .modal-header:after, |
|||
.file-input-new .file-preview, |
|||
.file-input-new .close, |
|||
.file-input-new .glyphicon-file, |
|||
.file-input-new .fileinput-remove-button, |
|||
.file-input-new .fileinput-upload-button, |
|||
.file-input-new .no-browse .input-group-btn, |
|||
.file-input-ajax-new .fileinput-remove-button, |
|||
.file-input-ajax-new .fileinput-upload-button, |
|||
.file-input-ajax-new .no-browse .input-group-btn, |
|||
.hide-content .kv-file-content, |
|||
.is-locked .fileinput-upload-button, |
|||
.is-locked .fileinput-remove-button { |
|||
display: none; |
|||
} |
|||
|
|||
.file-caption .input-group { |
|||
align-items: center; |
|||
} |
|||
|
|||
.btn-file input[type=file], |
|||
.file-caption-icon, |
|||
.file-preview .fileinput-remove, |
|||
.krajee-default .file-thumb-progress, |
|||
.file-zoom-dialog .btn-navigate, |
|||
.file-zoom-dialog .floating-buttons { |
|||
position: absolute; |
|||
} |
|||
|
|||
.file-caption-icon .kv-caption-icon { |
|||
line-height: inherit; |
|||
} |
|||
|
|||
.file-input, |
|||
.file-loading:before, |
|||
.btn-file, |
|||
.file-caption, |
|||
.file-preview, |
|||
.krajee-default.file-preview-frame, |
|||
.krajee-default .file-thumbnail-footer, |
|||
.file-zoom-dialog .modal-dialog { |
|||
position: relative; |
|||
} |
|||
|
|||
.file-error-message pre, |
|||
.file-error-message ul, |
|||
.krajee-default .file-actions, |
|||
.krajee-default .file-other-error { |
|||
text-align: left; |
|||
} |
|||
|
|||
.file-error-message pre, |
|||
.file-error-message ul { |
|||
margin: 0; |
|||
} |
|||
|
|||
.krajee-default .file-drag-handle, |
|||
.krajee-default .file-upload-indicator { |
|||
float: left; |
|||
margin-top: 10px; |
|||
width: 16px; |
|||
height: 16px; |
|||
} |
|||
|
|||
.file-thumb-progress .progress, |
|||
.file-thumb-progress .progress-bar { |
|||
font-family: Verdana, Helvetica, sans-serif; |
|||
font-size: 0.7rem; |
|||
} |
|||
|
|||
.krajee-default .file-thumb-progress .progress, |
|||
.kv-upload-progress .progress { |
|||
background-color: #ccc; |
|||
} |
|||
|
|||
.krajee-default .file-caption-info, |
|||
.krajee-default .file-size-info { |
|||
display: block; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
width: 160px; |
|||
height: 15px; |
|||
margin: auto; |
|||
} |
|||
|
|||
.file-zoom-content > .file-object.type-video, |
|||
.file-zoom-content > .file-object.type-flash, |
|||
.file-zoom-content > .file-object.type-image { |
|||
max-width: 100%; |
|||
max-height: 100%; |
|||
width: auto; |
|||
} |
|||
|
|||
.file-zoom-content > .file-object.type-video, |
|||
.file-zoom-content > .file-object.type-flash { |
|||
height: 100%; |
|||
} |
|||
|
|||
.file-zoom-content > .file-object.type-pdf, |
|||
.file-zoom-content > .file-object.type-html, |
|||
.file-zoom-content > .file-object.type-text, |
|||
.file-zoom-content > .file-object.type-default { |
|||
width: 100%; |
|||
} |
|||
|
|||
.file-loading:before { |
|||
content: " Loading..."; |
|||
display: inline-block; |
|||
padding-left: 20px; |
|||
line-height: 16px; |
|||
font-size: 13px; |
|||
font-variant: small-caps; |
|||
color: #999; |
|||
background: transparent url(loading.gif) top left no-repeat; |
|||
} |
|||
|
|||
.file-object { |
|||
margin: 0 0 -5px 0; |
|||
padding: 0; |
|||
} |
|||
|
|||
.btn-file { |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.btn-file input[type=file] { |
|||
top: 0; |
|||
left: 0; |
|||
min-width: 100%; |
|||
min-height: 100%; |
|||
text-align: right; |
|||
opacity: 0; |
|||
background: none repeat scroll 0 0 transparent; |
|||
cursor: inherit; |
|||
display: block; |
|||
} |
|||
|
|||
.btn-file ::-ms-browse { |
|||
font-size: 10000px; |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
|
|||
.file-caption.icon-visible .file-caption-icon { |
|||
display: inline-block; |
|||
} |
|||
|
|||
.file-caption.icon-visible .file-caption-name { |
|||
padding-left: 25px; |
|||
} |
|||
|
|||
.file-caption.icon-visible > .input-group-lg .file-caption-name { |
|||
padding-left: 30px; |
|||
} |
|||
|
|||
.file-caption.icon-visible > .input-group-sm .file-caption-name { |
|||
padding-left: 22px; |
|||
} |
|||
|
|||
.file-caption-name:not(.file-caption-disabled) { |
|||
background-color: transparent; |
|||
} |
|||
|
|||
.file-caption-name.file-processing { |
|||
font-style: italic; |
|||
border-color: #bbb; |
|||
opacity: 0.5; |
|||
} |
|||
|
|||
.file-caption-icon { |
|||
padding: 7px 5px; |
|||
left: 4px; |
|||
} |
|||
|
|||
.input-group-lg .file-caption-icon { |
|||
font-size: 1.25rem; |
|||
} |
|||
|
|||
.input-group-sm .file-caption-icon { |
|||
font-size: 0.875rem; |
|||
padding: 0.25rem; |
|||
} |
|||
|
|||
.file-error-message { |
|||
color: #a94442; |
|||
background-color: #f2dede; |
|||
margin: 5px; |
|||
border: 1px solid #ebccd1; |
|||
border-radius: 4px; |
|||
padding: 15px; |
|||
} |
|||
|
|||
.file-error-message pre { |
|||
margin: 5px 0; |
|||
} |
|||
|
|||
.file-caption-disabled { |
|||
background-color: #eee; |
|||
cursor: not-allowed; |
|||
opacity: 1; |
|||
} |
|||
|
|||
.file-preview { |
|||
border-radius: 5px; |
|||
border: 1px solid #ddd; |
|||
padding: 8px; |
|||
width: 100%; |
|||
margin-bottom: 5px; |
|||
} |
|||
|
|||
.file-preview .btn-xs { |
|||
padding: 1px 5px; |
|||
font-size: 12px; |
|||
line-height: 1.5; |
|||
border-radius: 3px; |
|||
} |
|||
|
|||
.file-preview .fileinput-remove { |
|||
top: 1px; |
|||
right: 1px; |
|||
line-height: 10px; |
|||
} |
|||
|
|||
.file-preview .clickable { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.file-preview-image { |
|||
font: 40px Impact, Charcoal, sans-serif; |
|||
color: #008000; |
|||
width: auto; |
|||
height: auto; |
|||
max-width: 100%; |
|||
max-height: 100%; |
|||
} |
|||
|
|||
.krajee-default.file-preview-frame { |
|||
margin: 8px; |
|||
border: 1px solid rgba(0, 0, 0, 0.2); |
|||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2); |
|||
padding: 6px; |
|||
float: left; |
|||
text-align: center; |
|||
|
|||
} |
|||
|
|||
.krajee-default.file-preview-frame .kv-file-content { |
|||
width: 213px; |
|||
height: 160px; |
|||
} |
|||
|
|||
.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered { |
|||
width: 400px; |
|||
} |
|||
|
|||
.krajee-default.file-preview-frame[data-template="audio"] .kv-file-content { |
|||
width: 240px; |
|||
height: 55px; |
|||
} |
|||
|
|||
.krajee-default.file-preview-frame .file-thumbnail-footer { |
|||
height: 70px; |
|||
} |
|||
|
|||
.krajee-default.file-preview-frame:not(.file-preview-error):hover { |
|||
border: 1px solid rgba(0, 0, 0, 0.3); |
|||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.4); |
|||
} |
|||
|
|||
.krajee-default .file-preview-text { |
|||
color: #428bca; |
|||
border: 1px solid #ddd; |
|||
outline: none; |
|||
resize: none; |
|||
} |
|||
|
|||
.krajee-default .file-preview-html { |
|||
border: 1px solid #ddd; |
|||
} |
|||
|
|||
.krajee-default .file-other-icon { |
|||
font-size: 6em; |
|||
line-height: 1; |
|||
} |
|||
|
|||
.krajee-default .file-footer-buttons { |
|||
float: right; |
|||
} |
|||
|
|||
.krajee-default .file-footer-caption { |
|||
display: block; |
|||
text-align: center; |
|||
padding-top: 4px; |
|||
font-size: 11px; |
|||
color: #999; |
|||
margin-bottom: 30px; |
|||
} |
|||
|
|||
.file-upload-stats { |
|||
font-size: 10px; |
|||
text-align: center; |
|||
width: 100%; |
|||
} |
|||
|
|||
.kv-upload-progress .file-upload-stats { |
|||
font-size: 12px; |
|||
margin: -10px 0 5px; |
|||
} |
|||
|
|||
.krajee-default .file-preview-error { |
|||
opacity: 0.65; |
|||
box-shadow: none; |
|||
} |
|||
|
|||
.krajee-default .file-thumb-progress { |
|||
top: 37px; |
|||
left: 0; |
|||
right: 0; |
|||
} |
|||
|
|||
.krajee-default.kvsortable-ghost { |
|||
background: #e1edf7; |
|||
border: 2px solid #a1abff; |
|||
} |
|||
|
|||
.krajee-default .file-preview-other:hover { |
|||
opacity: 0.8; |
|||
} |
|||
|
|||
.krajee-default .file-preview-frame:not(.file-preview-error) .file-footer-caption:hover { |
|||
color: #000; |
|||
} |
|||
|
|||
.kv-upload-progress .progress { |
|||
height: 20px; |
|||
margin: 10px 0; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.kv-upload-progress .progress-bar { |
|||
height: 20px; |
|||
font-family: Verdana, Helvetica, sans-serif; |
|||
} |
|||
|
|||
|
|||
/*noinspection CssOverwrittenProperties*/ |
|||
|
|||
.file-zoom-dialog .file-other-icon { |
|||
font-size: 22em; |
|||
font-size: 50vmin; |
|||
} |
|||
|
|||
.file-zoom-dialog .modal-dialog { |
|||
width: auto; |
|||
} |
|||
|
|||
.file-zoom-dialog .modal-header { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
.file-zoom-dialog .btn-navigate { |
|||
margin: 0 0.1rem; |
|||
padding: 0; |
|||
font-size: 1.2rem; |
|||
width: 2.4rem; |
|||
height: 2.4rem; |
|||
top: 50%; |
|||
border-radius: 50%; |
|||
text-align: center; |
|||
} |
|||
|
|||
.btn-navigate * { |
|||
width: auto; |
|||
} |
|||
|
|||
.file-zoom-dialog .floating-buttons { |
|||
top: 5px; |
|||
right: 10px; |
|||
} |
|||
|
|||
.file-zoom-dialog .btn-kv-prev { |
|||
left: 0; |
|||
} |
|||
|
|||
.file-zoom-dialog .btn-kv-next { |
|||
right: 0; |
|||
} |
|||
|
|||
.file-zoom-dialog .kv-zoom-header { |
|||
padding: 0.5rem; |
|||
} |
|||
|
|||
.file-zoom-dialog .kv-zoom-body { |
|||
padding: 0.25rem; |
|||
} |
|||
|
|||
.file-zoom-dialog .kv-zoom-description { |
|||
position: absolute; |
|||
opacity: 0.8; |
|||
font-size: 0.8rem; |
|||
background-color: #1a1a1a; |
|||
padding: 1rem; |
|||
text-align: center; |
|||
border-radius: 0.5rem; |
|||
color: #fff; |
|||
left: 15%; |
|||
right: 15%; |
|||
bottom: 15%; |
|||
} |
|||
|
|||
.file-zoom-dialog .kv-desc-hide { |
|||
float: right; |
|||
color: #fff; |
|||
padding: 0 0.1rem; |
|||
background: none; |
|||
border: none; |
|||
} |
|||
|
|||
.file-zoom-dialog .kv-desc-hide:hover { |
|||
opacity: 0.7; |
|||
} |
|||
|
|||
.file-zoom-dialog .kv-desc-hide:focus { |
|||
opacity: 0.9; |
|||
} |
|||
|
|||
.file-input-new .no-browse .form-control { |
|||
border-top-right-radius: 4px; |
|||
border-bottom-right-radius: 4px; |
|||
} |
|||
|
|||
.file-input-ajax-new .no-browse .form-control { |
|||
border-top-right-radius: 4px; |
|||
border-bottom-right-radius: 4px; |
|||
} |
|||
|
|||
.file-caption { |
|||
width: 100%; |
|||
position: relative; |
|||
} |
|||
|
|||
.file-thumb-loading { |
|||
background: transparent url(loading.gif) no-repeat scroll center center content-box !important; |
|||
} |
|||
|
|||
.file-drop-zone { |
|||
border: 1px dashed #aaa; |
|||
min-height: 260px; |
|||
border-radius: 4px; |
|||
text-align: center; |
|||
vertical-align: middle; |
|||
margin: 12px 15px 12px 12px; |
|||
padding: 5px; |
|||
} |
|||
|
|||
.file-drop-zone.clickable:hover { |
|||
border: 2px dashed #999; |
|||
} |
|||
|
|||
.file-drop-zone.clickable:focus { |
|||
border: 2px solid #5acde2; |
|||
} |
|||
|
|||
.file-drop-zone .file-preview-thumbnails { |
|||
cursor: default; |
|||
} |
|||
|
|||
.file-drop-zone-title { |
|||
color: #aaa; |
|||
font-size: 1.6em; |
|||
text-align: center; |
|||
padding: 85px 10px; |
|||
cursor: default; |
|||
} |
|||
|
|||
.file-highlighted { |
|||
border: 2px dashed #999 !important; |
|||
background-color: #eee; |
|||
} |
|||
|
|||
.file-uploading { |
|||
background: url(loading-sm.gif) no-repeat center bottom 10px; |
|||
opacity: 0.65; |
|||
} |
|||
|
|||
.file-zoom-fullscreen .modal-dialog { |
|||
min-width: 100%; |
|||
margin: 0; |
|||
} |
|||
|
|||
.file-zoom-fullscreen .modal-content { |
|||
border-radius: 0; |
|||
box-shadow: none; |
|||
min-height: 100vh; |
|||
} |
|||
|
|||
.file-zoom-fullscreen .kv-zoom-body { |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
.floating-buttons { |
|||
z-index: 3000; |
|||
} |
|||
|
|||
.floating-buttons .btn-kv { |
|||
margin-left: 3px; |
|||
z-index: 3000; |
|||
} |
|||
|
|||
.kv-zoom-actions { |
|||
min-width: 140px; |
|||
} |
|||
|
|||
.kv-zoom-actions .btn-kv { |
|||
margin-left: 3px; |
|||
} |
|||
|
|||
.file-zoom-content { |
|||
text-align: center; |
|||
white-space: nowrap; |
|||
min-height: 300px; |
|||
} |
|||
|
|||
.file-zoom-content:hover { |
|||
background: transparent; |
|||
} |
|||
|
|||
.file-zoom-content .file-preview-image { |
|||
max-height: 100%; |
|||
} |
|||
|
|||
.file-zoom-content .file-preview-video { |
|||
max-height: 100%; |
|||
} |
|||
|
|||
.file-zoom-content > .file-object.type-image { |
|||
height: auto; |
|||
min-height: inherit; |
|||
} |
|||
|
|||
.file-zoom-content > .file-object.type-audio { |
|||
width: auto; |
|||
height: 30px; |
|||
} |
|||
|
|||
@media (min-width: 576px) { |
|||
.file-zoom-dialog .modal-dialog { |
|||
max-width: 500px; |
|||
} |
|||
} |
|||
|
|||
@media (min-width: 992px) { |
|||
.file-zoom-dialog .modal-lg { |
|||
max-width: 800px; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 767px) { |
|||
.file-preview-thumbnails { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
flex-direction: column; |
|||
} |
|||
|
|||
.file-zoom-dialog .modal-header { |
|||
flex-direction: column; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 350px) { |
|||
.krajee-default.file-preview-frame:not([data-template="audio"]) .kv-file-content { |
|||
width: 160px; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 420px) { |
|||
.krajee-default.file-preview-frame .kv-file-content.kv-pdf-rendered { |
|||
width: 100%; |
|||
} |
|||
} |
|||
|
|||
.file-loading[dir=rtl]:before { |
|||
background: transparent url(loading.gif) top right no-repeat; |
|||
padding-left: 0; |
|||
padding-right: 20px; |
|||
} |
|||
|
|||
.clickable .file-drop-zone-title { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.file-sortable .file-drag-handle:hover { |
|||
opacity: 0.7; |
|||
} |
|||
|
|||
.file-sortable .file-drag-handle { |
|||
cursor: grab; |
|||
opacity: 1; |
|||
} |
|||
|
|||
.file-grabbing, |
|||
.file-grabbing * { |
|||
cursor: not-allowed !important; |
|||
} |
|||
|
|||
.file-grabbing .file-preview-thumbnails * { |
|||
cursor: grabbing !important; |
|||
} |
|||
|
|||
.file-preview-frame.sortable-chosen { |
|||
background-color: #d9edf7; |
|||
border-color: #17a2b8; |
|||
box-shadow: none !important; |
|||
} |
|||
|
|||
.file-preview .kv-zoom-cache { |
|||
display: none; |
|||
} |
|||
|
|||
.file-preview-other-frame, .file-preview-object, .kv-file-content, .kv-zoom-body { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.btn-kv-rotate, |
|||
.kv-file-rotate { |
|||
display: none; |
|||
} |
|||
|
|||
.rotatable:not(.hide-rotate) .btn-kv-rotate, |
|||
.rotatable:not(.hide-rotate) .kv-file-rotate { |
|||
display: inline-block; |
|||
} |
|||
|
|||
.rotatable .file-zoom-detail, |
|||
.rotatable .kv-file-content, |
|||
.rotatable .kv-file-content > :first-child { |
|||
transform-origin: center center; |
|||
} |
|||
|
|||
.rotate-animate { |
|||
transition: transform 0.3s ease; |
|||
} |
|||
|
|||
.kv-overflow-hidden { |
|||
overflow: hidden; |
|||
} |
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 847 B |
@ -0,0 +1,459 @@ |
|||
/*! |
|||
* Bootstrap-select v1.13.18 (https://developer.snapappointments.com/bootstrap-select) |
|||
* |
|||
* Copyright 2012-2020 SnapAppointments, LLC |
|||
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE) |
|||
*/ |
|||
|
|||
@-webkit-keyframes bs-notify-fadeOut { |
|||
0% { |
|||
opacity: 0.9; |
|||
} |
|||
100% { |
|||
opacity: 0; |
|||
} |
|||
} |
|||
@-o-keyframes bs-notify-fadeOut { |
|||
0% { |
|||
opacity: 0.9; |
|||
} |
|||
100% { |
|||
opacity: 0; |
|||
} |
|||
} |
|||
@keyframes bs-notify-fadeOut { |
|||
0% { |
|||
opacity: 0.9; |
|||
} |
|||
100% { |
|||
opacity: 0; |
|||
} |
|||
} |
|||
select.bs-select-hidden, |
|||
.bootstrap-select > select.bs-select-hidden, |
|||
select.selectpicker { |
|||
display: none !important; |
|||
} |
|||
.bootstrap-select { |
|||
width: 220px \0; |
|||
/*IE9 and below*/ |
|||
vertical-align: middle; |
|||
} |
|||
.bootstrap-select > .dropdown-toggle { |
|||
position: relative; |
|||
width: 100%; |
|||
text-align: right; |
|||
white-space: nowrap; |
|||
display: -webkit-inline-box; |
|||
display: -webkit-inline-flex; |
|||
display: -ms-inline-flexbox; |
|||
display: inline-flex; |
|||
-webkit-box-align: center; |
|||
-webkit-align-items: center; |
|||
-ms-flex-align: center; |
|||
align-items: center; |
|||
-webkit-box-pack: justify; |
|||
-webkit-justify-content: space-between; |
|||
-ms-flex-pack: justify; |
|||
justify-content: space-between; |
|||
} |
|||
.bootstrap-select > .dropdown-toggle:after { |
|||
margin-top: -1px; |
|||
} |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder:hover, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder:focus, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder:active { |
|||
color: #999; |
|||
} |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:hover, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:hover, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:hover, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:hover, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:hover, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:hover, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:focus, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:focus, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:focus, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:focus, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:focus, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:focus, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:active, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:active, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:active, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:active, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:active, |
|||
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:active { |
|||
color: rgba(255, 255, 255, 0.5); |
|||
} |
|||
.bootstrap-select > select { |
|||
position: absolute !important; |
|||
bottom: 0; |
|||
left: 50%; |
|||
display: block !important; |
|||
width: 0.5px !important; |
|||
height: 100% !important; |
|||
padding: 0 !important; |
|||
opacity: 0 !important; |
|||
border: none; |
|||
z-index: 0 !important; |
|||
} |
|||
.bootstrap-select > select.mobile-device { |
|||
top: 0; |
|||
left: 0; |
|||
display: block !important; |
|||
width: 100% !important; |
|||
z-index: 2 !important; |
|||
} |
|||
.has-error .bootstrap-select .dropdown-toggle, |
|||
.error .bootstrap-select .dropdown-toggle, |
|||
.bootstrap-select.is-invalid .dropdown-toggle, |
|||
.was-validated .bootstrap-select select:invalid + .dropdown-toggle { |
|||
border-color: #b94a48; |
|||
} |
|||
.bootstrap-select.is-valid .dropdown-toggle, |
|||
.was-validated .bootstrap-select select:valid + .dropdown-toggle { |
|||
border-color: #28a745; |
|||
} |
|||
.bootstrap-select.fit-width { |
|||
width: auto !important; |
|||
} |
|||
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) { |
|||
width: 220px; |
|||
} |
|||
.bootstrap-select > select.mobile-device:focus + .dropdown-toggle, |
|||
.bootstrap-select .dropdown-toggle:focus { |
|||
outline: thin dotted #333333 !important; |
|||
outline: 5px auto -webkit-focus-ring-color !important; |
|||
outline-offset: -2px; |
|||
} |
|||
.bootstrap-select.form-control { |
|||
margin-bottom: 0; |
|||
padding: 0; |
|||
border: none; |
|||
height: auto; |
|||
} |
|||
:not(.input-group) > .bootstrap-select.form-control:not([class*="col-"]) { |
|||
width: 100%; |
|||
} |
|||
.bootstrap-select.form-control.input-group-btn { |
|||
float: none; |
|||
z-index: auto; |
|||
} |
|||
.form-inline .bootstrap-select, |
|||
.form-inline .bootstrap-select.form-control:not([class*="col-"]) { |
|||
width: auto; |
|||
} |
|||
.bootstrap-select:not(.input-group-btn), |
|||
.bootstrap-select[class*="col-"] { |
|||
float: none; |
|||
display: inline-block; |
|||
margin-left: 0; |
|||
} |
|||
.bootstrap-select.dropdown-menu-right, |
|||
.bootstrap-select[class*="col-"].dropdown-menu-right, |
|||
.row .bootstrap-select[class*="col-"].dropdown-menu-right { |
|||
float: right; |
|||
} |
|||
.form-inline .bootstrap-select, |
|||
.form-horizontal .bootstrap-select, |
|||
.form-group .bootstrap-select { |
|||
margin-bottom: 0; |
|||
} |
|||
.form-group-lg .bootstrap-select.form-control, |
|||
.form-group-sm .bootstrap-select.form-control { |
|||
padding: 0; |
|||
} |
|||
.form-group-lg .bootstrap-select.form-control .dropdown-toggle, |
|||
.form-group-sm .bootstrap-select.form-control .dropdown-toggle { |
|||
height: 100%; |
|||
font-size: inherit; |
|||
line-height: inherit; |
|||
border-radius: inherit; |
|||
} |
|||
.bootstrap-select.form-control-sm .dropdown-toggle, |
|||
.bootstrap-select.form-control-lg .dropdown-toggle { |
|||
font-size: inherit; |
|||
line-height: inherit; |
|||
border-radius: inherit; |
|||
} |
|||
.bootstrap-select.form-control-sm .dropdown-toggle { |
|||
padding: 0.25rem 0.5rem; |
|||
} |
|||
.bootstrap-select.form-control-lg .dropdown-toggle { |
|||
padding: 0.5rem 1rem; |
|||
} |
|||
.form-inline .bootstrap-select .form-control { |
|||
width: 100%; |
|||
} |
|||
.bootstrap-select.disabled, |
|||
.bootstrap-select > .disabled { |
|||
cursor: not-allowed; |
|||
} |
|||
.bootstrap-select.disabled:focus, |
|||
.bootstrap-select > .disabled:focus { |
|||
outline: none !important; |
|||
} |
|||
.bootstrap-select.bs-container { |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
height: 0 !important; |
|||
padding: 0 !important; |
|||
} |
|||
.bootstrap-select.bs-container .dropdown-menu { |
|||
z-index: 1060; |
|||
} |
|||
.bootstrap-select .dropdown-toggle .filter-option { |
|||
position: static; |
|||
top: 0; |
|||
left: 0; |
|||
float: left; |
|||
height: 100%; |
|||
width: 100%; |
|||
text-align: left; |
|||
overflow: hidden; |
|||
-webkit-box-flex: 0; |
|||
-webkit-flex: 0 1 auto; |
|||
-ms-flex: 0 1 auto; |
|||
flex: 0 1 auto; |
|||
} |
|||
.bs3.bootstrap-select .dropdown-toggle .filter-option { |
|||
padding-right: inherit; |
|||
} |
|||
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option { |
|||
position: absolute; |
|||
padding-top: inherit; |
|||
padding-bottom: inherit; |
|||
padding-left: inherit; |
|||
float: none; |
|||
} |
|||
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner { |
|||
padding-right: inherit; |
|||
} |
|||
.bootstrap-select .dropdown-toggle .filter-option-inner-inner { |
|||
overflow: hidden; |
|||
} |
|||
.bootstrap-select .dropdown-toggle .filter-expand { |
|||
width: 0 !important; |
|||
float: left; |
|||
opacity: 0 !important; |
|||
overflow: hidden; |
|||
} |
|||
.bootstrap-select .dropdown-toggle .caret { |
|||
position: absolute; |
|||
top: 50%; |
|||
right: 12px; |
|||
margin-top: -2px; |
|||
vertical-align: middle; |
|||
} |
|||
.input-group .bootstrap-select.form-control .dropdown-toggle { |
|||
border-radius: inherit; |
|||
} |
|||
.bootstrap-select[class*="col-"] .dropdown-toggle { |
|||
width: 100%; |
|||
} |
|||
.bootstrap-select .dropdown-menu { |
|||
min-width: 100%; |
|||
-webkit-box-sizing: border-box; |
|||
-moz-box-sizing: border-box; |
|||
box-sizing: border-box; |
|||
} |
|||
.bootstrap-select .dropdown-menu > .inner:focus { |
|||
outline: none !important; |
|||
} |
|||
.bootstrap-select .dropdown-menu.inner { |
|||
position: static; |
|||
float: none; |
|||
border: 0; |
|||
padding: 0; |
|||
margin: 0; |
|||
border-radius: 0; |
|||
-webkit-box-shadow: none; |
|||
box-shadow: none; |
|||
} |
|||
.bootstrap-select .dropdown-menu li { |
|||
position: relative; |
|||
} |
|||
.bootstrap-select .dropdown-menu li.active small { |
|||
color: rgba(255, 255, 255, 0.5) !important; |
|||
} |
|||
.bootstrap-select .dropdown-menu li.disabled a { |
|||
cursor: not-allowed; |
|||
} |
|||
.bootstrap-select .dropdown-menu li a { |
|||
cursor: pointer; |
|||
-webkit-user-select: none; |
|||
-moz-user-select: none; |
|||
-ms-user-select: none; |
|||
user-select: none; |
|||
} |
|||
.bootstrap-select .dropdown-menu li a.opt { |
|||
position: relative; |
|||
padding-left: 2.25em; |
|||
} |
|||
.bootstrap-select .dropdown-menu li a span.check-mark { |
|||
display: none; |
|||
} |
|||
.bootstrap-select .dropdown-menu li a span.text { |
|||
display: inline-block; |
|||
} |
|||
.bootstrap-select .dropdown-menu li small { |
|||
padding-left: 0.5em; |
|||
} |
|||
.bootstrap-select .dropdown-menu .notify { |
|||
position: absolute; |
|||
bottom: 5px; |
|||
width: 96%; |
|||
margin: 0 2%; |
|||
min-height: 26px; |
|||
padding: 3px 5px; |
|||
background: #f5f5f5; |
|||
border: 1px solid #e3e3e3; |
|||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); |
|||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); |
|||
pointer-events: none; |
|||
opacity: 0.9; |
|||
-webkit-box-sizing: border-box; |
|||
-moz-box-sizing: border-box; |
|||
box-sizing: border-box; |
|||
} |
|||
.bootstrap-select .dropdown-menu .notify.fadeOut { |
|||
-webkit-animation: 300ms linear 750ms forwards bs-notify-fadeOut; |
|||
-o-animation: 300ms linear 750ms forwards bs-notify-fadeOut; |
|||
animation: 300ms linear 750ms forwards bs-notify-fadeOut; |
|||
} |
|||
.bootstrap-select .no-results { |
|||
padding: 3px; |
|||
background: #f5f5f5; |
|||
margin: 0 5px; |
|||
white-space: nowrap; |
|||
} |
|||
.bootstrap-select.fit-width .dropdown-toggle .filter-option { |
|||
position: static; |
|||
display: inline; |
|||
padding: 0; |
|||
} |
|||
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner, |
|||
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner { |
|||
display: inline; |
|||
} |
|||
.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before { |
|||
content: '\00a0'; |
|||
} |
|||
.bootstrap-select.fit-width .dropdown-toggle .caret { |
|||
position: static; |
|||
top: auto; |
|||
margin-top: -1px; |
|||
} |
|||
.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark { |
|||
position: absolute; |
|||
display: inline-block; |
|||
right: 15px; |
|||
top: 5px; |
|||
} |
|||
.bootstrap-select.show-tick .dropdown-menu li a span.text { |
|||
margin-right: 34px; |
|||
} |
|||
.bootstrap-select .bs-ok-default:after { |
|||
content: ''; |
|||
display: block; |
|||
width: 0.5em; |
|||
height: 1em; |
|||
border-style: solid; |
|||
border-width: 0 0.26em 0.26em 0; |
|||
-webkit-transform-style: preserve-3d; |
|||
transform-style: preserve-3d; |
|||
-webkit-transform: rotate(45deg); |
|||
-ms-transform: rotate(45deg); |
|||
-o-transform: rotate(45deg); |
|||
transform: rotate(45deg); |
|||
} |
|||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle, |
|||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle { |
|||
z-index: 1061; |
|||
} |
|||
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before { |
|||
content: ''; |
|||
border-left: 7px solid transparent; |
|||
border-right: 7px solid transparent; |
|||
border-bottom: 7px solid rgba(204, 204, 204, 0.2); |
|||
position: absolute; |
|||
bottom: -4px; |
|||
left: 9px; |
|||
display: none; |
|||
} |
|||
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after { |
|||
content: ''; |
|||
border-left: 6px solid transparent; |
|||
border-right: 6px solid transparent; |
|||
border-bottom: 6px solid white; |
|||
position: absolute; |
|||
bottom: -4px; |
|||
left: 10px; |
|||
display: none; |
|||
} |
|||
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before { |
|||
bottom: auto; |
|||
top: -4px; |
|||
border-top: 7px solid rgba(204, 204, 204, 0.2); |
|||
border-bottom: 0; |
|||
} |
|||
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after { |
|||
bottom: auto; |
|||
top: -4px; |
|||
border-top: 6px solid white; |
|||
border-bottom: 0; |
|||
} |
|||
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before { |
|||
right: 12px; |
|||
left: auto; |
|||
} |
|||
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after { |
|||
right: 13px; |
|||
left: auto; |
|||
} |
|||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:before, |
|||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:before, |
|||
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:after, |
|||
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:after { |
|||
display: block; |
|||
} |
|||
.bs-searchbox, |
|||
.bs-actionsbox, |
|||
.bs-donebutton { |
|||
padding: 4px 8px; |
|||
} |
|||
.bs-actionsbox { |
|||
width: 100%; |
|||
-webkit-box-sizing: border-box; |
|||
-moz-box-sizing: border-box; |
|||
box-sizing: border-box; |
|||
} |
|||
.bs-actionsbox .btn-group button { |
|||
width: 50%; |
|||
} |
|||
.bs-donebutton { |
|||
float: left; |
|||
width: 100%; |
|||
-webkit-box-sizing: border-box; |
|||
-moz-box-sizing: border-box; |
|||
box-sizing: border-box; |
|||
} |
|||
.bs-donebutton .btn-group button { |
|||
width: 100%; |
|||
} |
|||
.bs-searchbox + .bs-actionsbox { |
|||
padding: 0 8px 4px; |
|||
} |
|||
.bs-searchbox .form-control { |
|||
margin-bottom: 0; |
|||
width: 100%; |
|||
float: none; |
|||
} |
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,95 @@ |
|||
/** |
|||
* @author: Alec Fenichel |
|||
* @webSite: https://fenichelar.com
|
|||
* @update: zhixin wen <wenzhixin2010@gmail.com> |
|||
*/ |
|||
|
|||
var Utils = $.fn.bootstrapTable.utils |
|||
|
|||
$.extend($.fn.bootstrapTable.defaults, { |
|||
autoRefresh: false, |
|||
showAutoRefresh: true, |
|||
autoRefreshInterval: 60, |
|||
autoRefreshSilent: true, |
|||
autoRefreshStatus: true, |
|||
autoRefreshFunction: null |
|||
}) |
|||
|
|||
$.extend($.fn.bootstrapTable.defaults.icons, { |
|||
autoRefresh: { |
|||
bootstrap3: 'glyphicon-time icon-time', |
|||
bootstrap5: 'bi-clock', |
|||
materialize: 'access_time', |
|||
'bootstrap-table': 'icon-clock' |
|||
}[$.fn.bootstrapTable.theme] || 'fa-clock' |
|||
}) |
|||
|
|||
$.extend($.fn.bootstrapTable.locales, { |
|||
formatAutoRefresh () { |
|||
return 'Auto Refresh' |
|||
} |
|||
}) |
|||
|
|||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
init (...args) { |
|||
super.init(...args) |
|||
|
|||
if (this.options.autoRefresh && this.options.autoRefreshStatus) { |
|||
this.setupRefreshInterval() |
|||
} |
|||
} |
|||
|
|||
initToolbar (...args) { |
|||
if (this.options.autoRefresh) { |
|||
this.buttons = Object.assign(this.buttons, { |
|||
autoRefresh: { |
|||
html: ` |
|||
<button class="auto-refresh ${this.constants.buttonsClass} |
|||
${this.options.autoRefreshStatus ? ` ${this.constants.classes.buttonActive}` : ''}" |
|||
type="button" name="autoRefresh" title="${this.options.formatAutoRefresh()}"> |
|||
${this.options.showButtonIcons ? Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, this.options.icons.autoRefresh) : ''} |
|||
${this.options.showButtonText ? this.options.formatAutoRefresh() : ''} |
|||
</button> |
|||
`,
|
|||
event: this.toggleAutoRefresh |
|||
} |
|||
}) |
|||
} |
|||
|
|||
super.initToolbar(...args) |
|||
} |
|||
|
|||
toggleAutoRefresh () { |
|||
if (this.options.autoRefresh) { |
|||
if (this.options.autoRefreshStatus) { |
|||
clearInterval(this.options.autoRefreshFunction) |
|||
this.$toolbar.find('>.columns .auto-refresh') |
|||
.removeClass(this.constants.classes.buttonActive) |
|||
} else { |
|||
this.setupRefreshInterval() |
|||
this.$toolbar.find('>.columns .auto-refresh') |
|||
.addClass(this.constants.classes.buttonActive) |
|||
} |
|||
this.options.autoRefreshStatus = !this.options.autoRefreshStatus |
|||
} |
|||
} |
|||
|
|||
destroy () { |
|||
if (this.options.autoRefresh && this.options.autoRefreshStatus) { |
|||
clearInterval(this.options.autoRefreshFunction) |
|||
} |
|||
|
|||
super.destroy() |
|||
} |
|||
|
|||
setupRefreshInterval () { |
|||
this.options.autoRefreshFunction = setInterval(() => { |
|||
if (!this.options.autoRefresh || !this.options.autoRefreshStatus) { |
|||
return |
|||
} |
|||
this.refresh({ silent: this.options.autoRefreshSilent }) |
|||
}, this.options.autoRefreshInterval * 1000) |
|||
} |
|||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,606 @@ |
|||
/** |
|||
* @author: Dennis Hernández |
|||
* @update zhixin wen <wenzhixin2010@gmail.com> |
|||
*/ |
|||
var Utils = $.fn.bootstrapTable.utils |
|||
var UtilsCookie = { |
|||
cookieIds: { |
|||
sortOrder: 'bs.table.sortOrder', |
|||
sortName: 'bs.table.sortName', |
|||
sortPriority: 'bs.table.sortPriority', |
|||
pageNumber: 'bs.table.pageNumber', |
|||
pageList: 'bs.table.pageList', |
|||
hiddenColumns: 'bs.table.hiddenColumns', |
|||
cardView: 'bs.table.cardView', |
|||
customView: 'bs.table.customView', |
|||
searchText: 'bs.table.searchText', |
|||
reorderColumns: 'bs.table.reorderColumns', |
|||
filterControl: 'bs.table.filterControl', |
|||
filterBy: 'bs.table.filterBy' |
|||
}, |
|||
getCurrentHeader (that) { |
|||
return that.options.height ? that.$tableHeader : that.$header |
|||
}, |
|||
getCurrentSearchControls (that) { |
|||
return that.options.height ? 'table select, table input' : 'select, input' |
|||
}, |
|||
isCookieSupportedByBrowser () { |
|||
return navigator.cookieEnabled |
|||
}, |
|||
isCookieEnabled (that, cookieName) { |
|||
return that.options.cookiesEnabled.includes(cookieName) |
|||
}, |
|||
setCookie (that, cookieName, cookieValue) { |
|||
if ( |
|||
!that.options.cookie || |
|||
!UtilsCookie.isCookieEnabled(that, cookieName) |
|||
) { |
|||
return |
|||
} |
|||
|
|||
return that._storage.setItem(`${that.options.cookieIdTable}.${cookieName}`, cookieValue) |
|||
}, |
|||
getCookie (that, cookieName) { |
|||
if ( |
|||
!cookieName || |
|||
!UtilsCookie.isCookieEnabled(that, cookieName) |
|||
) { |
|||
return null |
|||
} |
|||
|
|||
return that._storage.getItem(`${that.options.cookieIdTable}.${cookieName}`) |
|||
}, |
|||
deleteCookie (that, cookieName) { |
|||
return that._storage.removeItem(`${that.options.cookieIdTable}.${cookieName}`) |
|||
}, |
|||
calculateExpiration (cookieExpire) { |
|||
const time = cookieExpire.replace(/[0-9]*/, '') // s,mi,h,d,m,y
|
|||
|
|||
cookieExpire = cookieExpire.replace(/[A-Za-z]{1,2}/, '') // number
|
|||
|
|||
switch (time.toLowerCase()) { |
|||
case 's': |
|||
cookieExpire = +cookieExpire |
|||
break |
|||
case 'mi': |
|||
cookieExpire *= 60 |
|||
break |
|||
case 'h': |
|||
cookieExpire = cookieExpire * 60 * 60 |
|||
break |
|||
case 'd': |
|||
cookieExpire = cookieExpire * 24 * 60 * 60 |
|||
break |
|||
case 'm': |
|||
cookieExpire = cookieExpire * 30 * 24 * 60 * 60 |
|||
break |
|||
case 'y': |
|||
cookieExpire = cookieExpire * 365 * 24 * 60 * 60 |
|||
break |
|||
default: |
|||
cookieExpire = undefined |
|||
break |
|||
} |
|||
if (!cookieExpire) { |
|||
return '' |
|||
} |
|||
const d = new Date() |
|||
|
|||
d.setTime(d.getTime() + cookieExpire * 1000) |
|||
return d.toGMTString() |
|||
}, |
|||
initCookieFilters (that) { |
|||
setTimeout(() => { |
|||
const parsedCookieFilters = JSON.parse( |
|||
UtilsCookie.getCookie(that, UtilsCookie.cookieIds.filterControl)) |
|||
|
|||
if (!that._filterControlValuesLoaded && parsedCookieFilters) { |
|||
const cachedFilters = {} |
|||
const header = UtilsCookie.getCurrentHeader(that) |
|||
const searchControls = UtilsCookie.getCurrentSearchControls(that) |
|||
|
|||
const applyCookieFilters = (element, filteredCookies) => { |
|||
filteredCookies.forEach(cookie => { |
|||
const value = element.value.toString() |
|||
const text = cookie.text |
|||
|
|||
if ( |
|||
text === '' || |
|||
element.type === 'radio' && |
|||
value !== text |
|||
) { |
|||
return |
|||
} |
|||
|
|||
if ( |
|||
element.tagName === 'INPUT' && |
|||
element.type === 'radio' && |
|||
value === text |
|||
) { |
|||
element.checked = true |
|||
cachedFilters[cookie.field] = text |
|||
} else if (element.tagName === 'INPUT') { |
|||
element.value = text |
|||
cachedFilters[cookie.field] = text |
|||
} else if ( |
|||
element.tagName === 'SELECT' && |
|||
that.options.filterControlContainer |
|||
) { |
|||
element.value = text |
|||
cachedFilters[cookie.field] = text |
|||
} else if (text !== '' && element.tagName === 'SELECT') { |
|||
cachedFilters[cookie.field] = text |
|||
for (const currentElement of element) { |
|||
if (currentElement.value === text) { |
|||
currentElement.selected = true |
|||
return |
|||
} |
|||
} |
|||
const option = document.createElement('option') |
|||
|
|||
option.value = text |
|||
option.text = text |
|||
element.add(option, element[1]) |
|||
element.selectedIndex = 1 |
|||
} |
|||
}) |
|||
} |
|||
|
|||
let filterContainer = header |
|||
|
|||
if (that.options.filterControlContainer) { |
|||
filterContainer = $(`${that.options.filterControlContainer}`) |
|||
} |
|||
|
|||
filterContainer.find(searchControls).each(function () { |
|||
const field = $(this).closest('[data-field]').data('field') |
|||
const filteredCookies = parsedCookieFilters.filter(cookie => cookie.field === field) |
|||
|
|||
applyCookieFilters(this, filteredCookies) |
|||
}) |
|||
|
|||
that.initColumnSearch(cachedFilters) |
|||
that._filterControlValuesLoaded = true |
|||
that.initServer() |
|||
} |
|||
}, 250) |
|||
} |
|||
} |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
cookie: false, |
|||
cookieExpire: '2h', |
|||
cookiePath: null, |
|||
cookieDomain: null, |
|||
cookieSecure: null, |
|||
cookieSameSite: 'Lax', |
|||
cookieIdTable: '', |
|||
cookiesEnabled: [ |
|||
'bs.table.sortOrder', 'bs.table.sortName', 'bs.table.sortPriority', |
|||
'bs.table.pageNumber', 'bs.table.pageList', |
|||
'bs.table.hiddenColumns', 'bs.table.searchText', |
|||
'bs.table.filterControl', 'bs.table.filterBy', |
|||
'bs.table.reorderColumns', 'bs.table.cardView', 'bs.table.customView' |
|||
], |
|||
cookieStorage: 'cookieStorage', // localStorage, sessionStorage, customStorage
|
|||
cookieCustomStorageGet: null, |
|||
cookieCustomStorageSet: null, |
|||
cookieCustomStorageDelete: null, |
|||
// internal variable
|
|||
_filterControls: [], |
|||
_filterControlValuesLoaded: false, |
|||
_storage: { |
|||
setItem: undefined, |
|||
getItem: undefined, |
|||
removeItem: undefined |
|||
} |
|||
}) |
|||
|
|||
$.fn.bootstrapTable.methods.push('getCookies') |
|||
$.fn.bootstrapTable.methods.push('deleteCookie') |
|||
|
|||
Object.assign($.fn.bootstrapTable.utils, { |
|||
setCookie: UtilsCookie.setCookie, |
|||
getCookie: UtilsCookie.getCookie |
|||
}) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
init () { |
|||
if (this.options.cookie) { |
|||
if ( |
|||
this.options.cookieStorage === 'cookieStorage' && |
|||
!UtilsCookie.isCookieSupportedByBrowser() |
|||
) { |
|||
throw new Error('Cookies are not enabled in this browser.') |
|||
} |
|||
|
|||
this.configureStorage() |
|||
|
|||
// FilterBy logic
|
|||
const filterByCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterBy) |
|||
|
|||
if (typeof filterByCookieValue === 'boolean' && !filterByCookieValue) { |
|||
throw new Error('The cookie value of filterBy must be a json!') |
|||
} |
|||
|
|||
let filterByCookie = {} |
|||
|
|||
try { |
|||
filterByCookie = JSON.parse(filterByCookieValue) |
|||
} catch (e) { |
|||
throw new Error('Could not parse the json of the filterBy cookie!') |
|||
} |
|||
this.filterColumns = filterByCookie ? filterByCookie : {} |
|||
|
|||
// FilterControl logic
|
|||
this._filterControls = [] |
|||
this._filterControlValuesLoaded = false |
|||
|
|||
this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ? |
|||
this.options.cookiesEnabled.replace('[', '').replace(']', '') |
|||
.replace(/'/g, '').replace(/ /g, '').split(',') : |
|||
this.options.cookiesEnabled |
|||
|
|||
if (this.options.filterControl) { |
|||
const that = this |
|||
|
|||
this.$el.on('column-search.bs.table', (e, field, text) => { |
|||
let isNewField = true |
|||
|
|||
for (let i = 0; i < that._filterControls.length; i++) { |
|||
if (that._filterControls[i].field === field) { |
|||
that._filterControls[i].text = text |
|||
isNewField = false |
|||
break |
|||
} |
|||
} |
|||
if (isNewField) { |
|||
that._filterControls.push({ |
|||
field, |
|||
text |
|||
}) |
|||
} |
|||
|
|||
UtilsCookie.setCookie(that, UtilsCookie.cookieIds.filterControl, JSON.stringify(that._filterControls)) |
|||
}).on('created-controls.bs.table', UtilsCookie.initCookieFilters(that)) |
|||
} |
|||
} |
|||
super.init() |
|||
} |
|||
|
|||
initServer (...args) { |
|||
if ( |
|||
this.options.cookie && |
|||
this.options.filterControl && |
|||
!this._filterControlValuesLoaded |
|||
) { |
|||
const cookie = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterControl)) |
|||
|
|||
if (cookie) { |
|||
return |
|||
} |
|||
} |
|||
super.initServer(...args) |
|||
} |
|||
|
|||
initTable (...args) { |
|||
super.initTable(...args) |
|||
this.initCookie() |
|||
} |
|||
|
|||
onSort (...args) { |
|||
super.onSort(...args) |
|||
|
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
|
|||
if (this.options.sortName === undefined || this.options.sortOrder === undefined) { |
|||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName) |
|||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder) |
|||
} else { |
|||
this.options.sortPriority = null |
|||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority) |
|||
|
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortOrder, this.options.sortOrder) |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortName, this.options.sortName) |
|||
} |
|||
} |
|||
|
|||
onMultipleSort (...args) { |
|||
super.onMultipleSort(...args) |
|||
|
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
|
|||
if (this.options.sortPriority === undefined) { |
|||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority) |
|||
} else { |
|||
this.options.sortName = undefined |
|||
this.options.sortOrder = undefined |
|||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName) |
|||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder) |
|||
|
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortPriority, JSON.stringify(this.options.sortPriority)) |
|||
} |
|||
} |
|||
|
|||
onPageNumber (...args) { |
|||
super.onPageNumber(...args) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber) |
|||
} |
|||
|
|||
onPageListChange (...args) { |
|||
super.onPageListChange(...args) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageList, |
|||
this.options.pageSize === this.options.formatAllRows() ? 'all' : this.options.pageSize) |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber) |
|||
} |
|||
|
|||
onPagePre (...args) { |
|||
super.onPagePre(...args) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber) |
|||
} |
|||
|
|||
onPageNext (...args) { |
|||
super.onPageNext(...args) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber) |
|||
} |
|||
|
|||
_toggleColumn (...args) { |
|||
super._toggleColumn(...args) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.hiddenColumns, JSON.stringify(this.getHiddenColumns().map(column => column.field))) |
|||
} |
|||
|
|||
_toggleAllColumns (...args) { |
|||
super._toggleAllColumns(...args) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.hiddenColumns, JSON.stringify(this.getHiddenColumns().map(column => column.field))) |
|||
} |
|||
|
|||
toggleView () { |
|||
super.toggleView() |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.cardView, this.options.cardView) |
|||
} |
|||
|
|||
toggleCustomView () { |
|||
super.toggleCustomView() |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.customView, this.customViewDefaultView) |
|||
} |
|||
|
|||
selectPage (page) { |
|||
super.selectPage(page) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, page) |
|||
} |
|||
|
|||
onSearch (event) { |
|||
super.onSearch(event, arguments.length > 1 ? arguments[1] : true) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
if (this.options.search) { |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.searchText, this.searchText) |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber) |
|||
} |
|||
|
|||
initHeader (...args) { |
|||
if (this.options.reorderableColumns && this.options.cookie) { |
|||
this.columnsSortOrder = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.reorderColumns)) |
|||
} |
|||
super.initHeader(...args) |
|||
} |
|||
|
|||
persistReorderColumnsState (that) { |
|||
UtilsCookie.setCookie(that, UtilsCookie.cookieIds.reorderColumns, JSON.stringify(that.columnsSortOrder)) |
|||
} |
|||
|
|||
filterBy (...args) { |
|||
super.filterBy(...args) |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
UtilsCookie.setCookie(this, UtilsCookie.cookieIds.filterBy, JSON.stringify(this.filterColumns)) |
|||
} |
|||
|
|||
initCookie () { |
|||
if (!this.options.cookie) { |
|||
return |
|||
} |
|||
|
|||
if (this.options.cookieIdTable === '' || this.options.cookieExpire === '') { |
|||
console.error('Configuration error. Please review the cookieIdTable and the cookieExpire property. If the properties are correct, then this browser does not support cookies.') |
|||
this.options.cookie = false // Make sure that the cookie extension is disabled
|
|||
return |
|||
} |
|||
|
|||
const sortOrderCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortOrder) |
|||
const sortOrderNameCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortName) |
|||
let sortPriorityCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortPriority) |
|||
const pageNumberCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageNumber) |
|||
const pageListCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageList) |
|||
const searchTextCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.searchText) |
|||
const cardViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.cardView) |
|||
const customViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.customView) |
|||
const hiddenColumnsCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.hiddenColumns) |
|||
|
|||
let hiddenColumnsCookie = {} |
|||
|
|||
try { |
|||
hiddenColumnsCookie = JSON.parse(hiddenColumnsCookieValue) |
|||
} catch (e) { |
|||
throw new Error('Could not parse the json of the hidden columns cookie!', hiddenColumnsCookieValue) |
|||
} |
|||
|
|||
try { |
|||
sortPriorityCookie = JSON.parse(sortPriorityCookie) |
|||
} catch (e) { |
|||
throw new Error('Could not parse the json of the sortPriority cookie!', sortPriorityCookie) |
|||
} |
|||
|
|||
if (!sortPriorityCookie) { |
|||
// sortOrder
|
|||
this.options.sortOrder = sortOrderCookie ? sortOrderCookie : this.options.sortOrder |
|||
// sortName
|
|||
this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : this.options.sortName |
|||
} else { |
|||
this.options.sortOrder = undefined |
|||
this.options.sortName = undefined |
|||
} |
|||
|
|||
// sortPriority
|
|||
this.options.sortPriority = sortPriorityCookie ? sortPriorityCookie : this.options.sortPriority |
|||
|
|||
if (this.options.sortOrder || this.options.sortName) { |
|||
// sortPriority
|
|||
this.options.sortPriority = null |
|||
} |
|||
|
|||
// pageNumber
|
|||
this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber |
|||
// pageSize
|
|||
this.options.pageSize = pageListCookie ? pageListCookie === 'all' ? |
|||
this.options.formatAllRows() : +pageListCookie : this.options.pageSize |
|||
// searchText
|
|||
if (UtilsCookie.isCookieEnabled(this, UtilsCookie.cookieIds.searchText) && this.options.searchText === '') { |
|||
this.options.searchText = searchTextCookie ? searchTextCookie : '' |
|||
} |
|||
// cardView
|
|||
if (cardViewCookie !== null) { |
|||
this.options.cardView = cardViewCookie === 'true' ? cardViewCookie : false |
|||
} |
|||
this.customViewDefaultView = customViewCookie === 'true' |
|||
|
|||
if (hiddenColumnsCookie) { |
|||
for (const column of this.columns) { |
|||
if (!column.switchable) { |
|||
continue |
|||
} |
|||
|
|||
column.visible = this.isSelectionColumn(column) || |
|||
!hiddenColumnsCookie.includes(column.field) |
|||
} |
|||
} |
|||
} |
|||
|
|||
getCookies () { |
|||
const bootstrapTable = this |
|||
const cookies = {} |
|||
|
|||
for (const [key, value] of Object.entries(UtilsCookie.cookieIds)) { |
|||
cookies[key] = UtilsCookie.getCookie(bootstrapTable, value) |
|||
if (key === 'columns' || key === 'hiddenColumns' || key === 'sortPriority') { |
|||
cookies[key] = JSON.parse(cookies[key]) |
|||
} |
|||
} |
|||
return cookies |
|||
} |
|||
|
|||
deleteCookie (cookieName) { |
|||
if (!cookieName) { |
|||
return |
|||
} |
|||
|
|||
UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds[cookieName]) |
|||
} |
|||
|
|||
configureStorage () { |
|||
const that = this |
|||
|
|||
this._storage = {} |
|||
switch (this.options.cookieStorage) { |
|||
case 'cookieStorage': |
|||
this._storage.setItem = function (cookieName, cookieValue) { |
|||
document.cookie = [ |
|||
cookieName, '=', encodeURIComponent(cookieValue), |
|||
`; expires=${UtilsCookie.calculateExpiration(that.options.cookieExpire)}`, |
|||
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '', |
|||
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '', |
|||
that.options.cookieSecure ? '; secure' : '', |
|||
`;SameSite=${that.options.cookieSameSite}` |
|||
].join('') |
|||
} |
|||
this._storage.getItem = function (cookieName) { |
|||
const value = `; ${document.cookie}` |
|||
const parts = value.split(`; ${cookieName}=`) |
|||
|
|||
return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null |
|||
} |
|||
this._storage.removeItem = function (cookieName) { |
|||
document.cookie = [ |
|||
encodeURIComponent(cookieName), '=', |
|||
'; expires=Thu, 01 Jan 1970 00:00:00 GMT', |
|||
that.options.cookiePath ? `; path=${that.options.cookiePath}` : '', |
|||
that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '', |
|||
`;SameSite=${that.options.cookieSameSite}` |
|||
].join('') |
|||
} |
|||
break |
|||
case 'localStorage': |
|||
this._storage.setItem = function (cookieName, cookieValue) { |
|||
localStorage.setItem(cookieName, cookieValue) |
|||
} |
|||
this._storage.getItem = function (cookieName) { |
|||
return localStorage.getItem(cookieName) |
|||
} |
|||
this._storage.removeItem = function (cookieName) { |
|||
localStorage.removeItem(cookieName) |
|||
} |
|||
break |
|||
case 'sessionStorage': |
|||
this._storage.setItem = function (cookieName, cookieValue) { |
|||
sessionStorage.setItem(cookieName, cookieValue) |
|||
} |
|||
this._storage.getItem = function (cookieName) { |
|||
return sessionStorage.getItem(cookieName) |
|||
} |
|||
this._storage.removeItem = function (cookieName) { |
|||
sessionStorage.removeItem(cookieName) |
|||
} |
|||
break |
|||
case 'customStorage': |
|||
if ( |
|||
!this.options.cookieCustomStorageSet || |
|||
!this.options.cookieCustomStorageGet || |
|||
!this.options.cookieCustomStorageDelete |
|||
) { |
|||
throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete') |
|||
} |
|||
|
|||
this._storage.setItem = function (cookieName, cookieValue) { |
|||
Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageSet, [cookieName, cookieValue], '') |
|||
} |
|||
this._storage.getItem = function (cookieName) { |
|||
return Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageGet, [cookieName], '') |
|||
} |
|||
this._storage.removeItem = function (cookieName) { |
|||
Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageDelete, [cookieName], '') |
|||
} |
|||
|
|||
break |
|||
default: |
|||
throw new Error('Storage method not supported.') |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,135 @@ |
|||
/** |
|||
* @author: Dustin Utecht |
|||
* @github: https://github.com/UtechtDustin
|
|||
*/ |
|||
|
|||
var Utils = $.fn.bootstrapTable.utils |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
customView: false, |
|||
showCustomView: false, |
|||
customViewDefaultView: false |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults.icons, { |
|||
customViewOn: { |
|||
bootstrap3: 'glyphicon glyphicon-list', |
|||
bootstrap5: 'bi-list', |
|||
bootstrap4: 'fa fa-list', |
|||
semantic: 'fa fa-list', |
|||
foundation: 'fa fa-list', |
|||
bulma: 'fa fa-list', |
|||
materialize: 'list' |
|||
}[$.fn.bootstrapTable.theme] || 'fa-list', |
|||
customViewOff: { |
|||
bootstrap3: 'glyphicon glyphicon-eye-open', |
|||
bootstrap5: 'bi-grid', |
|||
bootstrap4: 'fa fa-th', |
|||
semantic: 'fa fa-th', |
|||
foundation: 'fa fa-th', |
|||
bulma: 'fa fa-th', |
|||
materialize: 'grid_on' |
|||
}[$.fn.bootstrapTable.theme] || 'fa-th' |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
onCustomViewPostBody () { |
|||
return false |
|||
}, |
|||
onCustomViewPreBody () { |
|||
return false |
|||
}, |
|||
onToggleCustomView () { |
|||
return false |
|||
} |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.locales, { |
|||
formatToggleCustomViewOn () { |
|||
return 'Show custom view' |
|||
}, |
|||
formatToggleCustomViewOff () { |
|||
return 'Hide custom view' |
|||
} |
|||
}) |
|||
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales) |
|||
|
|||
$.fn.bootstrapTable.methods.push('toggleCustomView') |
|||
|
|||
Object.assign($.fn.bootstrapTable.events, { |
|||
'custom-view-post-body.bs.table': 'onCustomViewPostBody', |
|||
'custom-view-pre-body.bs.table': 'onCustomViewPreBody', |
|||
'toggle-custom-view.bs.table': 'onToggleCustomView' |
|||
}) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
|
|||
init () { |
|||
this.customViewDefaultView = this.options.customViewDefaultView |
|||
|
|||
super.init() |
|||
} |
|||
|
|||
initToolbar (...args) { |
|||
if (this.options.customView && this.options.showCustomView) { |
|||
this.buttons = Object.assign(this.buttons, { |
|||
customView: { |
|||
text: this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn(), |
|||
icon: this.options.customViewDefaultView ? this.options.icons.customViewOn : this.options.icons.customViewOff, |
|||
event: this.toggleCustomView, |
|||
attributes: { |
|||
'aria-label': this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn(), |
|||
title: this.options.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn() |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
super.initToolbar(...args) |
|||
} |
|||
|
|||
initBody () { |
|||
super.initBody() |
|||
|
|||
if (!this.options.customView) { |
|||
return |
|||
} |
|||
|
|||
const $table = this.$el |
|||
const $customViewContainer = this.$container.find('.fixed-table-custom-view') |
|||
|
|||
$table.hide() |
|||
$customViewContainer.hide() |
|||
if (!this.options.customView || !this.customViewDefaultView) { |
|||
$table.show() |
|||
return |
|||
} |
|||
|
|||
const data = this.getData().slice(this.pageFrom - 1, this.pageTo) |
|||
const value = Utils.calculateObjectValue(this, this.options.customView, [data], '') |
|||
|
|||
this.trigger('custom-view-pre-body', data, value) |
|||
if ($customViewContainer.length === 1) { |
|||
$customViewContainer.show().html(value) |
|||
} else { |
|||
this.$tableBody.after(`<div class="fixed-table-custom-view">${value}</div>`) |
|||
} |
|||
|
|||
this.trigger('custom-view-post-body', data, value) |
|||
} |
|||
|
|||
toggleCustomView () { |
|||
this.customViewDefaultView = !this.customViewDefaultView |
|||
|
|||
const icon = this.options.showButtonIcons ? this.customViewDefaultView ? this.options.icons.customViewOn : this.options.icons.customViewOff : '' |
|||
const text = this.options.showButtonText ? this.customViewDefaultView ? this.options.formatToggleCustomViewOff() : this.options.formatToggleCustomViewOn() : '' |
|||
|
|||
this.$toolbar.find('button[name="customView"]') |
|||
.html(`${Utils.sprintf(this.constants.html.icon, this.options.iconsPrefix, icon)} ${text}`) |
|||
.attr('aria-label', text) |
|||
.attr('title', text) |
|||
|
|||
this.initBody() |
|||
this.trigger('toggle-custom-view', this.customViewDefaultView) |
|||
} |
|||
} |
@ -0,0 +1,674 @@ |
|||
/*! X-editable - v1.5.3 |
|||
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery |
|||
* http://github.com/vitalets/x-editable |
|||
* Copyright (c) 2019 Vitaliy Potapov; Licensed MIT */ |
|||
.editableform { |
|||
margin-bottom: 0; /* overwrites bootstrap margin */ |
|||
} |
|||
|
|||
.editableform .control-group { |
|||
margin-bottom: 0; /* overwrites bootstrap margin */ |
|||
white-space: nowrap; /* prevent wrapping buttons on new line */ |
|||
line-height: 20px; /* overwriting bootstrap line-height. See #133 */ |
|||
} |
|||
|
|||
/* |
|||
BS3 fix: stop css from breaking when the form is inside a popup and inside a form with the class .form-horizontal |
|||
See: https://github.com/vitalets/x-editable/issues/682 |
|||
*/ |
|||
.form-horizontal .editable-popup .editableform .form-group { |
|||
margin-left:0; |
|||
margin-right:0; |
|||
} |
|||
|
|||
|
|||
/* |
|||
BS3 width:1005 for inputs breaks editable form in popup |
|||
See: https://github.com/vitalets/x-editable/issues/393 |
|||
*/ |
|||
.editableform .form-control { |
|||
width: auto; |
|||
} |
|||
|
|||
.editable-buttons { |
|||
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ |
|||
vertical-align: top; |
|||
margin-left: 7px; |
|||
/* inline-block emulation for IE7*/ |
|||
zoom: 1; |
|||
*display: inline; |
|||
} |
|||
|
|||
.editable-buttons.editable-buttons-bottom { |
|||
display: block; |
|||
margin-top: 7px; |
|||
margin-left: 0; |
|||
} |
|||
|
|||
.editable-input { |
|||
vertical-align: top; |
|||
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ |
|||
width: auto; /* bootstrap-responsive has width: 100% that breakes layout */ |
|||
white-space: normal; /* reset white-space decalred in parent*/ |
|||
/* display-inline emulation for IE7*/ |
|||
zoom: 1; |
|||
*display: inline; |
|||
} |
|||
|
|||
.editable-buttons .editable-cancel { |
|||
margin-left: 7px; |
|||
} |
|||
|
|||
/*for jquery-ui buttons need set height to look more pretty*/ |
|||
.editable-buttons button.ui-button-icon-only { |
|||
height: 24px; |
|||
width: 30px; |
|||
} |
|||
|
|||
.editableform-loading { |
|||
background: url('loading.gif') center center no-repeat; |
|||
height: 25px; |
|||
width: auto; |
|||
min-width: 25px; |
|||
} |
|||
|
|||
.editable-inline .editableform-loading { |
|||
background-position: left 5px; |
|||
} |
|||
|
|||
.editable-error-block { |
|||
max-width: 300px; |
|||
margin: 5px 0 0 0; |
|||
width: auto; |
|||
white-space: normal; |
|||
} |
|||
|
|||
/*add padding for jquery ui*/ |
|||
.editable-error-block.ui-state-error { |
|||
padding: 3px; |
|||
} |
|||
|
|||
.editable-error { |
|||
color: red; |
|||
} |
|||
|
|||
/* ---- For specific types ---- */ |
|||
|
|||
.editableform .editable-date { |
|||
padding: 0; |
|||
margin: 0; |
|||
float: left; |
|||
} |
|||
|
|||
/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */ |
|||
.editable-inline .add-on .icon-th { |
|||
margin-top: 3px; |
|||
margin-left: 1px; |
|||
} |
|||
|
|||
|
|||
/* checklist vertical alignment */ |
|||
.editable-checklist label input[type="checkbox"], |
|||
.editable-checklist label span { |
|||
vertical-align: middle; |
|||
margin: 0; |
|||
} |
|||
|
|||
.editable-checklist label { |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
/* set exact width of textarea to fit buttons toolbar */ |
|||
.editable-wysihtml5 { |
|||
width: 566px; |
|||
height: 250px; |
|||
} |
|||
|
|||
/* clear button shown as link in date inputs */ |
|||
.editable-clear { |
|||
clear: both; |
|||
font-size: 0.9em; |
|||
text-decoration: none; |
|||
text-align: right; |
|||
} |
|||
|
|||
/* IOS-style clear button for text inputs */ |
|||
.editable-clear-x { |
|||
background: url('clear.png') center center no-repeat; |
|||
display: block; |
|||
width: 13px; |
|||
height: 13px; |
|||
position: absolute; |
|||
opacity: 0.6; |
|||
z-index: 100; |
|||
|
|||
top: 50%; |
|||
right: 6px; |
|||
margin-top: -6px; |
|||
|
|||
} |
|||
|
|||
.editable-clear-x:hover { |
|||
opacity: 1; |
|||
} |
|||
|
|||
.editable-pre-wrapped { |
|||
white-space: pre-wrap; |
|||
} |
|||
|
|||
.editable-container.editable-popup { |
|||
max-width: none !important; /* without this rule poshytip/tooltip does not stretch */ |
|||
} |
|||
|
|||
.editable-container.popover { |
|||
width: auto; /* without this rule popover does not stretch */ |
|||
} |
|||
|
|||
.editable-container.editable-inline { |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
width: auto; |
|||
/* inline-block emulation for IE7*/ |
|||
zoom: 1; |
|||
*display: inline; |
|||
} |
|||
|
|||
.editable-container.ui-widget { |
|||
font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */ |
|||
z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */ |
|||
} |
|||
.editable-click, |
|||
a.editable-click, |
|||
a.editable-click:hover { |
|||
text-decoration: none; |
|||
border-bottom: dashed 1px #0088cc; |
|||
} |
|||
|
|||
.editable-click.editable-disabled, |
|||
a.editable-click.editable-disabled, |
|||
a.editable-click.editable-disabled:hover { |
|||
color: #585858; |
|||
cursor: default; |
|||
border-bottom: none; |
|||
} |
|||
|
|||
.editable-empty, .editable-empty:hover, .editable-empty:focus{ |
|||
font-style: italic; |
|||
color: #DD1144; |
|||
/* border-bottom: none; */ |
|||
text-decoration: none; |
|||
} |
|||
|
|||
.editable-unsaved { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.editable-unsaved:after { |
|||
/* content: '*'*/ |
|||
} |
|||
|
|||
.editable-bg-transition { |
|||
-webkit-transition: background-color 1400ms ease-out; |
|||
-moz-transition: background-color 1400ms ease-out; |
|||
-o-transition: background-color 1400ms ease-out; |
|||
-ms-transition: background-color 1400ms ease-out; |
|||
transition: background-color 1400ms ease-out; |
|||
} |
|||
|
|||
/*see https://github.com/vitalets/x-editable/issues/139 */ |
|||
.form-horizontal .editable |
|||
{ |
|||
padding-top: 5px; |
|||
display:inline-block; |
|||
} |
|||
|
|||
|
|||
/*! |
|||
* Datepicker for Bootstrap |
|||
* |
|||
* Copyright 2012 Stefan Petre |
|||
* Improvements by Andrew Rowls |
|||
* Licensed under the Apache License v2.0 |
|||
* http://www.apache.org/licenses/LICENSE-2.0 |
|||
* |
|||
*/ |
|||
.datepicker { |
|||
padding: 4px; |
|||
-webkit-border-radius: 4px; |
|||
-moz-border-radius: 4px; |
|||
border-radius: 4px; |
|||
direction: ltr; |
|||
/*.dow { |
|||
border-top: 1px solid #ddd !important; |
|||
}*/ |
|||
|
|||
} |
|||
.datepicker-inline { |
|||
width: 220px; |
|||
} |
|||
.datepicker.datepicker-rtl { |
|||
direction: rtl; |
|||
} |
|||
.datepicker.datepicker-rtl table tr td span { |
|||
float: right; |
|||
} |
|||
.datepicker-dropdown { |
|||
top: 0; |
|||
left: 0; |
|||
} |
|||
.datepicker-dropdown:before { |
|||
content: ''; |
|||
display: inline-block; |
|||
border-left: 7px solid transparent; |
|||
border-right: 7px solid transparent; |
|||
border-bottom: 7px solid #ccc; |
|||
border-bottom-color: rgba(0, 0, 0, 0.2); |
|||
position: absolute; |
|||
top: -7px; |
|||
left: 6px; |
|||
} |
|||
.datepicker-dropdown:after { |
|||
content: ''; |
|||
display: inline-block; |
|||
border-left: 6px solid transparent; |
|||
border-right: 6px solid transparent; |
|||
border-bottom: 6px solid #ffffff; |
|||
position: absolute; |
|||
top: -6px; |
|||
left: 7px; |
|||
} |
|||
.datepicker > div { |
|||
display: none; |
|||
} |
|||
.datepicker.days div.datepicker-days { |
|||
display: block; |
|||
} |
|||
.datepicker.months div.datepicker-months { |
|||
display: block; |
|||
} |
|||
.datepicker.years div.datepicker-years { |
|||
display: block; |
|||
} |
|||
.datepicker table { |
|||
margin: 0; |
|||
} |
|||
.datepicker td, |
|||
.datepicker th { |
|||
text-align: center; |
|||
width: 20px; |
|||
height: 20px; |
|||
-webkit-border-radius: 4px; |
|||
-moz-border-radius: 4px; |
|||
border-radius: 4px; |
|||
border: none; |
|||
} |
|||
.table-striped .datepicker table tr td, |
|||
.table-striped .datepicker table tr th { |
|||
background-color: transparent; |
|||
} |
|||
.datepicker table tr td.day:hover { |
|||
background: #eeeeee; |
|||
cursor: pointer; |
|||
} |
|||
.datepicker table tr td.old, |
|||
.datepicker table tr td.new { |
|||
color: #999999; |
|||
} |
|||
.datepicker table tr td.disabled, |
|||
.datepicker table tr td.disabled:hover { |
|||
background: none; |
|||
color: #999999; |
|||
cursor: default; |
|||
} |
|||
.datepicker table tr td.today, |
|||
.datepicker table tr td.today:hover, |
|||
.datepicker table tr td.today.disabled, |
|||
.datepicker table tr td.today.disabled:hover { |
|||
background-color: #fde19a; |
|||
background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); |
|||
background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); |
|||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); |
|||
background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); |
|||
background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); |
|||
background-image: linear-gradient(top, #fdd49a, #fdf59a); |
|||
background-repeat: repeat-x; |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); |
|||
border-color: #fdf59a #fdf59a #fbed50; |
|||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); |
|||
color: #000; |
|||
} |
|||
.datepicker table tr td.today:hover, |
|||
.datepicker table tr td.today:hover:hover, |
|||
.datepicker table tr td.today.disabled:hover, |
|||
.datepicker table tr td.today.disabled:hover:hover, |
|||
.datepicker table tr td.today:active, |
|||
.datepicker table tr td.today:hover:active, |
|||
.datepicker table tr td.today.disabled:active, |
|||
.datepicker table tr td.today.disabled:hover:active, |
|||
.datepicker table tr td.today.active, |
|||
.datepicker table tr td.today:hover.active, |
|||
.datepicker table tr td.today.disabled.active, |
|||
.datepicker table tr td.today.disabled:hover.active, |
|||
.datepicker table tr td.today.disabled, |
|||
.datepicker table tr td.today:hover.disabled, |
|||
.datepicker table tr td.today.disabled.disabled, |
|||
.datepicker table tr td.today.disabled:hover.disabled, |
|||
.datepicker table tr td.today[disabled], |
|||
.datepicker table tr td.today:hover[disabled], |
|||
.datepicker table tr td.today.disabled[disabled], |
|||
.datepicker table tr td.today.disabled:hover[disabled] { |
|||
background-color: #fdf59a; |
|||
} |
|||
.datepicker table tr td.today:active, |
|||
.datepicker table tr td.today:hover:active, |
|||
.datepicker table tr td.today.disabled:active, |
|||
.datepicker table tr td.today.disabled:hover:active, |
|||
.datepicker table tr td.today.active, |
|||
.datepicker table tr td.today:hover.active, |
|||
.datepicker table tr td.today.disabled.active, |
|||
.datepicker table tr td.today.disabled:hover.active { |
|||
background-color: #fbf069 \9; |
|||
} |
|||
.datepicker table tr td.today:hover:hover { |
|||
color: #000; |
|||
} |
|||
.datepicker table tr td.today.active:hover { |
|||
color: #fff; |
|||
} |
|||
.datepicker table tr td.range, |
|||
.datepicker table tr td.range:hover, |
|||
.datepicker table tr td.range.disabled, |
|||
.datepicker table tr td.range.disabled:hover { |
|||
background: #eeeeee; |
|||
-webkit-border-radius: 0; |
|||
-moz-border-radius: 0; |
|||
border-radius: 0; |
|||
} |
|||
.datepicker table tr td.range.today, |
|||
.datepicker table tr td.range.today:hover, |
|||
.datepicker table tr td.range.today.disabled, |
|||
.datepicker table tr td.range.today.disabled:hover { |
|||
background-color: #f3d17a; |
|||
background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a); |
|||
background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a); |
|||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a)); |
|||
background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a); |
|||
background-image: -o-linear-gradient(top, #f3c17a, #f3e97a); |
|||
background-image: linear-gradient(top, #f3c17a, #f3e97a); |
|||
background-repeat: repeat-x; |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0); |
|||
border-color: #f3e97a #f3e97a #edde34; |
|||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); |
|||
-webkit-border-radius: 0; |
|||
-moz-border-radius: 0; |
|||
border-radius: 0; |
|||
} |
|||
.datepicker table tr td.range.today:hover, |
|||
.datepicker table tr td.range.today:hover:hover, |
|||
.datepicker table tr td.range.today.disabled:hover, |
|||
.datepicker table tr td.range.today.disabled:hover:hover, |
|||
.datepicker table tr td.range.today:active, |
|||
.datepicker table tr td.range.today:hover:active, |
|||
.datepicker table tr td.range.today.disabled:active, |
|||
.datepicker table tr td.range.today.disabled:hover:active, |
|||
.datepicker table tr td.range.today.active, |
|||
.datepicker table tr td.range.today:hover.active, |
|||
.datepicker table tr td.range.today.disabled.active, |
|||
.datepicker table tr td.range.today.disabled:hover.active, |
|||
.datepicker table tr td.range.today.disabled, |
|||
.datepicker table tr td.range.today:hover.disabled, |
|||
.datepicker table tr td.range.today.disabled.disabled, |
|||
.datepicker table tr td.range.today.disabled:hover.disabled, |
|||
.datepicker table tr td.range.today[disabled], |
|||
.datepicker table tr td.range.today:hover[disabled], |
|||
.datepicker table tr td.range.today.disabled[disabled], |
|||
.datepicker table tr td.range.today.disabled:hover[disabled] { |
|||
background-color: #f3e97a; |
|||
} |
|||
.datepicker table tr td.range.today:active, |
|||
.datepicker table tr td.range.today:hover:active, |
|||
.datepicker table tr td.range.today.disabled:active, |
|||
.datepicker table tr td.range.today.disabled:hover:active, |
|||
.datepicker table tr td.range.today.active, |
|||
.datepicker table tr td.range.today:hover.active, |
|||
.datepicker table tr td.range.today.disabled.active, |
|||
.datepicker table tr td.range.today.disabled:hover.active { |
|||
background-color: #efe24b \9; |
|||
} |
|||
.datepicker table tr td.selected, |
|||
.datepicker table tr td.selected:hover, |
|||
.datepicker table tr td.selected.disabled, |
|||
.datepicker table tr td.selected.disabled:hover { |
|||
background-color: #9e9e9e; |
|||
background-image: -moz-linear-gradient(top, #b3b3b3, #808080); |
|||
background-image: -ms-linear-gradient(top, #b3b3b3, #808080); |
|||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080)); |
|||
background-image: -webkit-linear-gradient(top, #b3b3b3, #808080); |
|||
background-image: -o-linear-gradient(top, #b3b3b3, #808080); |
|||
background-image: linear-gradient(top, #b3b3b3, #808080); |
|||
background-repeat: repeat-x; |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0); |
|||
border-color: #808080 #808080 #595959; |
|||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); |
|||
color: #fff; |
|||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); |
|||
} |
|||
.datepicker table tr td.selected:hover, |
|||
.datepicker table tr td.selected:hover:hover, |
|||
.datepicker table tr td.selected.disabled:hover, |
|||
.datepicker table tr td.selected.disabled:hover:hover, |
|||
.datepicker table tr td.selected:active, |
|||
.datepicker table tr td.selected:hover:active, |
|||
.datepicker table tr td.selected.disabled:active, |
|||
.datepicker table tr td.selected.disabled:hover:active, |
|||
.datepicker table tr td.selected.active, |
|||
.datepicker table tr td.selected:hover.active, |
|||
.datepicker table tr td.selected.disabled.active, |
|||
.datepicker table tr td.selected.disabled:hover.active, |
|||
.datepicker table tr td.selected.disabled, |
|||
.datepicker table tr td.selected:hover.disabled, |
|||
.datepicker table tr td.selected.disabled.disabled, |
|||
.datepicker table tr td.selected.disabled:hover.disabled, |
|||
.datepicker table tr td.selected[disabled], |
|||
.datepicker table tr td.selected:hover[disabled], |
|||
.datepicker table tr td.selected.disabled[disabled], |
|||
.datepicker table tr td.selected.disabled:hover[disabled] { |
|||
background-color: #808080; |
|||
} |
|||
.datepicker table tr td.selected:active, |
|||
.datepicker table tr td.selected:hover:active, |
|||
.datepicker table tr td.selected.disabled:active, |
|||
.datepicker table tr td.selected.disabled:hover:active, |
|||
.datepicker table tr td.selected.active, |
|||
.datepicker table tr td.selected:hover.active, |
|||
.datepicker table tr td.selected.disabled.active, |
|||
.datepicker table tr td.selected.disabled:hover.active { |
|||
background-color: #666666 \9; |
|||
} |
|||
.datepicker table tr td.active, |
|||
.datepicker table tr td.active:hover, |
|||
.datepicker table tr td.active.disabled, |
|||
.datepicker table tr td.active.disabled:hover { |
|||
background-color: #006dcc; |
|||
background-image: -moz-linear-gradient(top, #0088cc, #0044cc); |
|||
background-image: -ms-linear-gradient(top, #0088cc, #0044cc); |
|||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); |
|||
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); |
|||
background-image: -o-linear-gradient(top, #0088cc, #0044cc); |
|||
background-image: linear-gradient(top, #0088cc, #0044cc); |
|||
background-repeat: repeat-x; |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); |
|||
border-color: #0044cc #0044cc #002a80; |
|||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); |
|||
color: #fff; |
|||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); |
|||
} |
|||
.datepicker table tr td.active:hover, |
|||
.datepicker table tr td.active:hover:hover, |
|||
.datepicker table tr td.active.disabled:hover, |
|||
.datepicker table tr td.active.disabled:hover:hover, |
|||
.datepicker table tr td.active:active, |
|||
.datepicker table tr td.active:hover:active, |
|||
.datepicker table tr td.active.disabled:active, |
|||
.datepicker table tr td.active.disabled:hover:active, |
|||
.datepicker table tr td.active.active, |
|||
.datepicker table tr td.active:hover.active, |
|||
.datepicker table tr td.active.disabled.active, |
|||
.datepicker table tr td.active.disabled:hover.active, |
|||
.datepicker table tr td.active.disabled, |
|||
.datepicker table tr td.active:hover.disabled, |
|||
.datepicker table tr td.active.disabled.disabled, |
|||
.datepicker table tr td.active.disabled:hover.disabled, |
|||
.datepicker table tr td.active[disabled], |
|||
.datepicker table tr td.active:hover[disabled], |
|||
.datepicker table tr td.active.disabled[disabled], |
|||
.datepicker table tr td.active.disabled:hover[disabled] { |
|||
background-color: #0044cc; |
|||
} |
|||
.datepicker table tr td.active:active, |
|||
.datepicker table tr td.active:hover:active, |
|||
.datepicker table tr td.active.disabled:active, |
|||
.datepicker table tr td.active.disabled:hover:active, |
|||
.datepicker table tr td.active.active, |
|||
.datepicker table tr td.active:hover.active, |
|||
.datepicker table tr td.active.disabled.active, |
|||
.datepicker table tr td.active.disabled:hover.active { |
|||
background-color: #003399 \9; |
|||
} |
|||
.datepicker table tr td span { |
|||
display: block; |
|||
width: 23%; |
|||
height: 54px; |
|||
line-height: 54px; |
|||
float: left; |
|||
margin: 1%; |
|||
cursor: pointer; |
|||
-webkit-border-radius: 4px; |
|||
-moz-border-radius: 4px; |
|||
border-radius: 4px; |
|||
} |
|||
.datepicker table tr td span:hover { |
|||
background: #eeeeee; |
|||
} |
|||
.datepicker table tr td span.disabled, |
|||
.datepicker table tr td span.disabled:hover { |
|||
background: none; |
|||
color: #999999; |
|||
cursor: default; |
|||
} |
|||
.datepicker table tr td span.active, |
|||
.datepicker table tr td span.active:hover, |
|||
.datepicker table tr td span.active.disabled, |
|||
.datepicker table tr td span.active.disabled:hover { |
|||
background-color: #006dcc; |
|||
background-image: -moz-linear-gradient(top, #0088cc, #0044cc); |
|||
background-image: -ms-linear-gradient(top, #0088cc, #0044cc); |
|||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc)); |
|||
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc); |
|||
background-image: -o-linear-gradient(top, #0088cc, #0044cc); |
|||
background-image: linear-gradient(top, #0088cc, #0044cc); |
|||
background-repeat: repeat-x; |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); |
|||
border-color: #0044cc #0044cc #002a80; |
|||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); |
|||
color: #fff; |
|||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); |
|||
} |
|||
.datepicker table tr td span.active:hover, |
|||
.datepicker table tr td span.active:hover:hover, |
|||
.datepicker table tr td span.active.disabled:hover, |
|||
.datepicker table tr td span.active.disabled:hover:hover, |
|||
.datepicker table tr td span.active:active, |
|||
.datepicker table tr td span.active:hover:active, |
|||
.datepicker table tr td span.active.disabled:active, |
|||
.datepicker table tr td span.active.disabled:hover:active, |
|||
.datepicker table tr td span.active.active, |
|||
.datepicker table tr td span.active:hover.active, |
|||
.datepicker table tr td span.active.disabled.active, |
|||
.datepicker table tr td span.active.disabled:hover.active, |
|||
.datepicker table tr td span.active.disabled, |
|||
.datepicker table tr td span.active:hover.disabled, |
|||
.datepicker table tr td span.active.disabled.disabled, |
|||
.datepicker table tr td span.active.disabled:hover.disabled, |
|||
.datepicker table tr td span.active[disabled], |
|||
.datepicker table tr td span.active:hover[disabled], |
|||
.datepicker table tr td span.active.disabled[disabled], |
|||
.datepicker table tr td span.active.disabled:hover[disabled] { |
|||
background-color: #0044cc; |
|||
} |
|||
.datepicker table tr td span.active:active, |
|||
.datepicker table tr td span.active:hover:active, |
|||
.datepicker table tr td span.active.disabled:active, |
|||
.datepicker table tr td span.active.disabled:hover:active, |
|||
.datepicker table tr td span.active.active, |
|||
.datepicker table tr td span.active:hover.active, |
|||
.datepicker table tr td span.active.disabled.active, |
|||
.datepicker table tr td span.active.disabled:hover.active { |
|||
background-color: #003399 \9; |
|||
} |
|||
.datepicker table tr td span.old, |
|||
.datepicker table tr td span.new { |
|||
color: #999999; |
|||
} |
|||
.datepicker th.datepicker-switch { |
|||
width: 145px; |
|||
} |
|||
.datepicker thead tr:first-child th, |
|||
.datepicker tfoot tr th { |
|||
cursor: pointer; |
|||
} |
|||
.datepicker thead tr:first-child th:hover, |
|||
.datepicker tfoot tr th:hover { |
|||
background: #eeeeee; |
|||
} |
|||
.datepicker .cw { |
|||
font-size: 10px; |
|||
width: 12px; |
|||
padding: 0 2px 0 5px; |
|||
vertical-align: middle; |
|||
} |
|||
.datepicker thead tr:first-child th.cw { |
|||
cursor: default; |
|||
background-color: transparent; |
|||
} |
|||
.input-append.date .add-on i, |
|||
.input-prepend.date .add-on i { |
|||
display: block; |
|||
cursor: pointer; |
|||
width: 16px; |
|||
height: 16px; |
|||
} |
|||
.input-daterange input { |
|||
text-align: center; |
|||
} |
|||
.input-daterange input:first-child { |
|||
-webkit-border-radius: 3px 0 0 3px; |
|||
-moz-border-radius: 3px 0 0 3px; |
|||
border-radius: 3px 0 0 3px; |
|||
} |
|||
.input-daterange input:last-child { |
|||
-webkit-border-radius: 0 3px 3px 0; |
|||
-moz-border-radius: 0 3px 3px 0; |
|||
border-radius: 0 3px 3px 0; |
|||
} |
|||
.input-daterange .add-on { |
|||
display: inline-block; |
|||
width: auto; |
|||
min-width: 16px; |
|||
height: 18px; |
|||
padding: 4px 5px; |
|||
font-weight: normal; |
|||
line-height: 18px; |
|||
text-align: center; |
|||
text-shadow: 0 1px 0 #ffffff; |
|||
vertical-align: middle; |
|||
background-color: #eeeeee; |
|||
border: 1px solid #ccc; |
|||
margin-left: -5px; |
|||
margin-right: -5px; |
|||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,189 @@ |
|||
/* eslint-disable no-unused-vars */ |
|||
/** |
|||
* @author zhixin wen <wenzhixin2010@gmail.com> |
|||
* extensions: https://github.com/vitalets/x-editable
|
|||
*/ |
|||
|
|||
var Utils = $.fn.bootstrapTable.utils |
|||
|
|||
$.extend($.fn.bootstrapTable.defaults, { |
|||
editable: true, |
|||
onEditableInit () { |
|||
return false |
|||
}, |
|||
onEditableSave (field, row, rowIndex, oldValue, $el) { |
|||
return false |
|||
}, |
|||
onEditableShown (field, row, $el, editable) { |
|||
return false |
|||
}, |
|||
onEditableHidden (field, row, $el, reason) { |
|||
return false |
|||
} |
|||
}) |
|||
|
|||
$.extend($.fn.bootstrapTable.columnDefaults, { |
|||
alwaysUseFormatter: false |
|||
}) |
|||
|
|||
$.extend($.fn.bootstrapTable.events, { |
|||
'editable-init.bs.table': 'onEditableInit', |
|||
'editable-save.bs.table': 'onEditableSave', |
|||
'editable-shown.bs.table': 'onEditableShown', |
|||
'editable-hidden.bs.table': 'onEditableHidden' |
|||
}) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
initTable () { |
|||
super.initTable() |
|||
|
|||
if (!this.options.editable) { |
|||
return |
|||
} |
|||
|
|||
this.editedCells = [] |
|||
$.each(this.columns, (i, column) => { |
|||
if (!column.editable) { |
|||
return |
|||
} |
|||
|
|||
const editableOptions = {} |
|||
const editableDataMarkup = [] |
|||
const editableDataPrefix = 'editable-' |
|||
const processDataOptions = (key, value) => { |
|||
// Replace camel case with dashes.
|
|||
const dashKey = key.replace(/([A-Z])/g, $1 => `-${$1.toLowerCase()}`) |
|||
|
|||
if (dashKey.indexOf(editableDataPrefix) === 0) { |
|||
editableOptions[dashKey.replace(editableDataPrefix, 'data-')] = value |
|||
} |
|||
} |
|||
|
|||
$.each(this.options, processDataOptions) |
|||
|
|||
column.formatter = column.formatter || (value => value) |
|||
column._formatter = column._formatter ? column._formatter : column.formatter |
|||
column.formatter = (value, row, index, field) => { |
|||
let result = Utils.calculateObjectValue(column, column._formatter, [value, row, index], value) |
|||
|
|||
result = typeof result === 'undefined' || result === null ? this.options.undefinedText : result |
|||
if (this.options.uniqueId !== undefined && !column.alwaysUseFormatter) { |
|||
const uniqueId = Utils.getItemField(row, this.options.uniqueId, false) |
|||
|
|||
if ($.inArray(column.field + uniqueId, this.editedCells) !== -1) { |
|||
result = value |
|||
} |
|||
} |
|||
|
|||
$.each(column, processDataOptions) |
|||
|
|||
$.each(editableOptions, (key, value) => { |
|||
editableDataMarkup.push(` ${key}="${value}"`) |
|||
}) |
|||
|
|||
let noEditFormatter = false |
|||
const editableOpts = Utils.calculateObjectValue(column, |
|||
column.editable, [index, row], {}) |
|||
|
|||
if (editableOpts.hasOwnProperty('noEditFormatter')) { |
|||
noEditFormatter = editableOpts.noEditFormatter(value, row, index, field) |
|||
} |
|||
|
|||
if (noEditFormatter === false) { |
|||
return `<a href="javascript:void(0)"
|
|||
data-name="${column.field}" |
|||
data-pk="${row[this.options.idField]}" |
|||
data-value="${result}" |
|||
${editableDataMarkup.join('')}></a>` |
|||
} |
|||
return noEditFormatter |
|||
} |
|||
}) |
|||
} |
|||
|
|||
initBody (fixedScroll) { |
|||
super.initBody(fixedScroll) |
|||
|
|||
if (!this.options.editable) { |
|||
return |
|||
} |
|||
|
|||
$.each(this.columns, (i, column) => { |
|||
if (!column.editable) { |
|||
return |
|||
} |
|||
|
|||
const data = this.getData({ escape: true }) |
|||
const $field = this.$body.find(`a[data-name="${column.field}"]`) |
|||
|
|||
$field.each((i, element) => { |
|||
const $element = $(element) |
|||
const $tr = $element.closest('tr') |
|||
const index = $tr.data('index') |
|||
const row = data[index] |
|||
|
|||
const editableOpts = Utils.calculateObjectValue(column, |
|||
column.editable, [index, row, $element], {}) |
|||
|
|||
$element.editable(editableOpts) |
|||
}) |
|||
|
|||
$field.off('save').on('save', ({ currentTarget }, { submitValue }) => { |
|||
const $this = $(currentTarget) |
|||
const data = this.getData() |
|||
const rowIndex = $this.parents('tr[data-index]').data('index') |
|||
const row = data[rowIndex] |
|||
const oldValue = row[column.field] |
|||
|
|||
if (this.options.uniqueId !== undefined && !column.alwaysUseFormatter) { |
|||
const uniqueId = Utils.getItemField(row, this.options.uniqueId, false) |
|||
|
|||
if ($.inArray(column.field + uniqueId, this.editedCells) === -1) { |
|||
this.editedCells.push(column.field + uniqueId) |
|||
} |
|||
} |
|||
|
|||
submitValue = Utils.escapeHTML(submitValue) |
|||
$this.data('value', submitValue) |
|||
row[column.field] = submitValue |
|||
this.trigger('editable-save', column.field, row, rowIndex, oldValue, $this) |
|||
this.initBody() |
|||
}) |
|||
|
|||
$field.off('shown').on('shown', ({ currentTarget }, editable) => { |
|||
const $this = $(currentTarget) |
|||
const data = this.getData() |
|||
const rowIndex = $this.parents('tr[data-index]').data('index') |
|||
const row = data[rowIndex] |
|||
|
|||
this.trigger('editable-shown', column.field, row, $this, editable) |
|||
}) |
|||
|
|||
$field.off('hidden').on('hidden', ({ currentTarget }, reason) => { |
|||
const $this = $(currentTarget) |
|||
const data = this.getData() |
|||
const rowIndex = $this.parents('tr[data-index]').data('index') |
|||
const row = data[rowIndex] |
|||
|
|||
this.trigger('editable-hidden', column.field, row, $this, reason) |
|||
}) |
|||
}) |
|||
this.trigger('editable-init') |
|||
} |
|||
|
|||
getData (params) { |
|||
const data = super.getData(params) |
|||
|
|||
if (params && params.escape) { |
|||
for (const row of data) { |
|||
for (const [key, value] of Object.entries(row)) { |
|||
if (typeof(value) !== "number") { |
|||
row[key] = Utils.unescapeHTML(value) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return data |
|||
} |
|||
} |
After Width: | Height: | Size: 244 B |
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,335 @@ |
|||
/** |
|||
* @author zhixin wen <wenzhixin2010@gmail.com> |
|||
* extensions: https://github.com/hhurz/tableExport.jquery.plugin
|
|||
*/ |
|||
|
|||
var Utils = $.fn.bootstrapTable.utils |
|||
|
|||
const TYPE_NAME = { |
|||
json: 'JSON', |
|||
xml: 'XML', |
|||
png: 'PNG', |
|||
csv: 'CSV', |
|||
txt: 'TXT', |
|||
sql: 'SQL', |
|||
doc: 'MS-Word', |
|||
excel: 'MS-Excel', |
|||
xlsx: 'MS-Excel (OpenXML)', |
|||
powerpoint: 'MS-Powerpoint', |
|||
pdf: 'PDF' |
|||
} |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
showExport: false, |
|||
exportDataType: 'basic', // basic, all, selected
|
|||
exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'], |
|||
exportOptions: {}, |
|||
exportFooter: false |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.columnDefaults, { |
|||
forceExport: false, |
|||
forceHide: false |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults.icons, { |
|||
export: { |
|||
bootstrap3: 'glyphicon-export icon-share', |
|||
bootstrap5: 'bi-download', |
|||
materialize: 'file_download', |
|||
'bootstrap-table': 'icon-download' |
|||
}[$.fn.bootstrapTable.theme] || 'fa-download' |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.locales, { |
|||
formatExport () { |
|||
return 'Export data' |
|||
} |
|||
}) |
|||
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales) |
|||
|
|||
$.fn.bootstrapTable.methods.push('exportTable') |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
// eslint-disable-next-line no-unused-vars
|
|||
onExportSaved (exportedRows) { |
|||
return false |
|||
}, |
|||
onExportStarted () { |
|||
return false |
|||
} |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.events, { |
|||
'export-saved.bs.table': 'onExportSaved', |
|||
'export-started.bs.table': 'onExportStarted' |
|||
}) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
initToolbar (...args) { |
|||
const o = this.options |
|||
let exportTypes = o.exportTypes |
|||
|
|||
this.showToolbar = this.showToolbar || o.showExport |
|||
|
|||
if (this.options.showExport) { |
|||
|
|||
if (typeof exportTypes === 'string') { |
|||
const types = exportTypes.slice(1, -1).replace(/ /g, '').split(',') |
|||
|
|||
exportTypes = types.map(t => t.slice(1, -1)) |
|||
} |
|||
|
|||
if (typeof o.exportOptions === 'string') { |
|||
o.exportOptions = Utils.calculateObjectValue(null, o.exportOptions) |
|||
} |
|||
|
|||
this.$export = this.$toolbar.find('>.columns div.export') |
|||
if (this.$export.length) { |
|||
this.updateExportButton() |
|||
return |
|||
} |
|||
|
|||
this.buttons = Object.assign(this.buttons, { |
|||
export: { |
|||
html: |
|||
() => { |
|||
if (exportTypes.length === 1) { |
|||
return ` |
|||
<div class="export ${this.constants.classes.buttonsDropdown}" |
|||
data-type="${exportTypes[0]}"> |
|||
<button class="${this.constants.buttonsClass}" |
|||
aria-label="${o.formatExport()}" |
|||
type="button" |
|||
title="${o.formatExport()}"> |
|||
${o.showButtonIcons ? Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.export) : ''} |
|||
${o.showButtonText ? o.formatExport() : ''} |
|||
</button> |
|||
</div> |
|||
` |
|||
} |
|||
|
|||
const html = [] |
|||
|
|||
html.push(` |
|||
<div class="export ${this.constants.classes.buttonsDropdown}"> |
|||
<button class="${this.constants.buttonsClass} dropdown-toggle" |
|||
aria-label="${o.formatExport()}" |
|||
${this.constants.dataToggle}="dropdown" |
|||
type="button" |
|||
title="${o.formatExport()}"> |
|||
${o.showButtonIcons ? Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.export) : ''} |
|||
${o.showButtonText ? o.formatExport() : ''} |
|||
${this.constants.html.dropdownCaret} |
|||
</button> |
|||
${this.constants.html.toolbarDropdown[0]} |
|||
`)
|
|||
|
|||
for (const type of exportTypes) { |
|||
if (TYPE_NAME.hasOwnProperty(type)) { |
|||
const $item = $(Utils.sprintf(this.constants.html.pageDropdownItem, '', TYPE_NAME[type])) |
|||
|
|||
$item.attr('data-type', type) |
|||
html.push($item.prop('outerHTML')) |
|||
} |
|||
} |
|||
|
|||
html.push(this.constants.html.toolbarDropdown[1], '</div>') |
|||
return html.join('') |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
super.initToolbar(...args) |
|||
this.$export = this.$toolbar.find('>.columns div.export') |
|||
|
|||
if (!this.options.showExport) { |
|||
return |
|||
} |
|||
|
|||
this.updateExportButton() |
|||
let $exportButtons = this.$export.find('[data-type]') |
|||
|
|||
if (exportTypes.length === 1) { |
|||
$exportButtons = this.$export |
|||
} |
|||
|
|||
$exportButtons.click(e => { |
|||
e.preventDefault() |
|||
this.trigger('export-started') |
|||
this.exportTable({ |
|||
type: $(e.currentTarget).data('type') |
|||
}) |
|||
}) |
|||
this.handleToolbar() |
|||
} |
|||
|
|||
handleToolbar () { |
|||
if (!this.$export) { |
|||
return |
|||
} |
|||
|
|||
if (super.handleToolbar) { |
|||
super.handleToolbar() |
|||
} |
|||
} |
|||
|
|||
exportTable (options) { |
|||
const o = this.options |
|||
const stateField = this.header.stateField |
|||
const isCardView = o.cardView |
|||
|
|||
const doExport = callback => { |
|||
if (stateField) { |
|||
this.hideColumn(stateField) |
|||
} |
|||
if (isCardView) { |
|||
this.toggleView() |
|||
} |
|||
|
|||
this.columns.forEach(row => { |
|||
if (row.forceHide) { |
|||
this.hideColumn(row.field) |
|||
} |
|||
}) |
|||
|
|||
const data = this.getData() |
|||
|
|||
if (o.detailView && o.detailViewIcon) { |
|||
const detailViewIndex = o.detailViewAlign === 'left' ? 0 : this.getVisibleFields().length + Utils.getDetailViewIndexOffset(this.options) |
|||
|
|||
o.exportOptions.ignoreColumn = [detailViewIndex].concat(o.exportOptions.ignoreColumn || []) |
|||
} |
|||
|
|||
if (o.exportFooter && o.height) { |
|||
const $footerRow = this.$tableFooter.find('tr').first() |
|||
const footerData = {} |
|||
const footerHtml = [] |
|||
|
|||
$.each($footerRow.children(), (index, footerCell) => { |
|||
const footerCellHtml = $(footerCell).children('.th-inner').first().html() |
|||
|
|||
footerData[this.columns[index].field] = footerCellHtml === ' ' ? null : footerCellHtml |
|||
|
|||
// grab footer cell text into cell index-based array
|
|||
footerHtml.push(footerCellHtml) |
|||
}) |
|||
|
|||
this.$body.append(this.$body.children().last()[0].outerHTML) |
|||
const $lastTableRow = this.$body.children().last() |
|||
|
|||
$.each($lastTableRow.children(), (index, lastTableRowCell) => { |
|||
$(lastTableRowCell).html(footerHtml[index]) |
|||
}) |
|||
} |
|||
|
|||
const hiddenColumns = this.getHiddenColumns() |
|||
|
|||
hiddenColumns.forEach(row => { |
|||
if (row.forceExport) { |
|||
this.showColumn(row.field) |
|||
} |
|||
}) |
|||
|
|||
if (typeof o.exportOptions.fileName === 'function') { |
|||
options.fileName = o.exportOptions.fileName() |
|||
} |
|||
|
|||
this.$el.tableExport(Utils.extend({ |
|||
onAfterSaveToFile: () => { |
|||
if (o.exportFooter) { |
|||
this.load(data) |
|||
} |
|||
|
|||
if (stateField) { |
|||
this.showColumn(stateField) |
|||
} |
|||
if (isCardView) { |
|||
this.toggleView() |
|||
} |
|||
|
|||
hiddenColumns.forEach(row => { |
|||
if (row.forceExport) { |
|||
this.hideColumn(row.field) |
|||
} |
|||
}) |
|||
|
|||
this.columns.forEach(row => { |
|||
if (row.forceHide) { |
|||
this.showColumn(row.field) |
|||
} |
|||
}) |
|||
|
|||
if (callback) callback() |
|||
} |
|||
}, o.exportOptions, options)) |
|||
} |
|||
|
|||
if (o.exportDataType === 'all' && o.pagination) { |
|||
const eventName = o.sidePagination === 'server' ? |
|||
'post-body.bs.table' : 'page-change.bs.table' |
|||
const virtualScroll = this.options.virtualScroll |
|||
|
|||
this.$el.one(eventName, () => { |
|||
setTimeout(() => { |
|||
const data = this.getData() |
|||
|
|||
doExport(() => { |
|||
this.options.virtualScroll = virtualScroll |
|||
this.togglePagination() |
|||
}) |
|||
this.trigger('export-saved', data) |
|||
}, 0) |
|||
}) |
|||
this.options.virtualScroll = false |
|||
this.togglePagination() |
|||
} else if (o.exportDataType === 'selected') { |
|||
let data = this.getData() |
|||
let selectedData = this.getSelections() |
|||
const pagination = o.pagination |
|||
|
|||
if (!selectedData.length) { |
|||
return |
|||
} |
|||
|
|||
if (o.sidePagination === 'server') { |
|||
data = { |
|||
total: o.totalRows, |
|||
[this.options.dataField]: data |
|||
} |
|||
selectedData = { |
|||
total: selectedData.length, |
|||
[this.options.dataField]: selectedData |
|||
} |
|||
} |
|||
|
|||
this.load(selectedData) |
|||
if (pagination) { |
|||
this.togglePagination() |
|||
} |
|||
doExport(() => { |
|||
if (pagination) { |
|||
this.togglePagination() |
|||
} |
|||
this.load(data) |
|||
}) |
|||
this.trigger('export-saved', selectedData) |
|||
} else { |
|||
doExport() |
|||
this.trigger('export-saved', this.getData(true)) |
|||
} |
|||
} |
|||
|
|||
updateSelected () { |
|||
super.updateSelected() |
|||
this.updateExportButton() |
|||
} |
|||
|
|||
updateExportButton () { |
|||
if (this.options.exportDataType === 'selected') { |
|||
this.$export.find('> button') |
|||
.prop('disabled', !this.getSelections().length) |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,92 @@ |
|||
/* |
|||
tableExport.jquery.plugin |
|||
Version 1.10.24 |
|||
Copyright (c) 2015-2021 hhurz, https://github.com/hhurz/tableExport.jquery.plugin
|
|||
Based on https://github.com/kayalshri/tableExport.jquery.plugin
|
|||
Licensed under the MIT License |
|||
*/ |
|||
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(d,k,y){d instanceof String&&(d=String(d));for(var C=d.length,v=0;v<C;v++){var R=d[v];if(k.call(y,R,v,d))return{i:v,v:R}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(d,k,y){d!=Array.prototype&&d!=Object.prototype&&(d[k]=y.value)}; |
|||
$jscomp.getGlobal=function(d){return"undefined"!=typeof window&&window===d?d:"undefined"!=typeof global&&null!=global?global:d};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(d,k,y,C){if(k){y=$jscomp.global;d=d.split(".");for(C=0;C<d.length-1;C++){var v=d[C];v in y||(y[v]={});y=y[v]}d=d[d.length-1];C=y[d];k=k(C);k!=C&&null!=k&&$jscomp.defineProperty(y,d,{configurable:!0,writable:!0,value:k})}}; |
|||
$jscomp.polyfill("Array.prototype.find",function(d){return d?d:function(d,y){return $jscomp.findInternal(this,d,y).v}},"es6","es3"); |
|||
(function(d){d.fn.tableExport=function(k){function y(b){var c=[];v(b,"thead").each(function(){c.push.apply(c,v(d(this),a.theadSelector).toArray())});return c}function C(b){var c=[];v(b,"tbody").each(function(){c.push.apply(c,v(d(this),a.tbodySelector).toArray())});a.tfootSelector.length&&v(b,"tfoot").each(function(){c.push.apply(c,v(d(this),a.tfootSelector).toArray())});return c}function v(b,a){var c=b[0].tagName,q=b.parents(c).length;return b.find(a).filter(function(){return q===d(this).closest(c).parents(c).length})} |
|||
function R(b){var a=[],e=0,q=0,f=0;d(b).find("thead").first().find("th").each(function(b,c){b=void 0!==d(c).attr("data-field");"undefined"!==typeof c.parentNode.rowIndex&&q!==c.parentNode.rowIndex&&(q=c.parentNode.rowIndex,e=f=0);var h=J(c);for(e+=h?h:1;f<e;)a[f]=b?d(c).attr("data-field"):f.toString(),f++});return a}function I(b){var a="undefined"!==typeof b[0].rowIndex,e=!1===a&&"undefined"!==typeof b[0].cellIndex,q=e||a?Ja(b):b.is(":visible"),f=b.attr("data-tableexport-display");e&&"none"!==f&& |
|||
"always"!==f&&(b=d(b[0].parentNode),a="undefined"!==typeof b[0].rowIndex,f=b.attr("data-tableexport-display"));a&&"none"!==f&&"always"!==f&&(f=b.closest("table").attr("data-tableexport-display"));return"none"!==f&&(!0===q||"always"===f)}function Ja(b){var a=[];V&&(a=K.filter(function(){var a=!1;this.nodeType===b[0].nodeType&&("undefined"!==typeof this.rowIndex&&this.rowIndex===b[0].rowIndex?a=!0:"undefined"!==typeof this.cellIndex&&this.cellIndex===b[0].cellIndex&&"undefined"!==typeof this.parentNode.rowIndex&& |
|||
"undefined"!==typeof b[0].parentNode.rowIndex&&this.parentNode.rowIndex===b[0].parentNode.rowIndex&&(a=!0));return a}));return!1===V||0===a.length}function ta(b,c,e){var q=!1;I(b)?0<a.ignoreColumn.length&&(-1!==d.inArray(e,a.ignoreColumn)||-1!==d.inArray(e-c,a.ignoreColumn)||S.length>e&&"undefined"!==typeof S[e]&&-1!==d.inArray(S[e],a.ignoreColumn))&&(q=!0):q=!0;return q}function E(b,c,e,q,f){if("function"===typeof f){var h=!1;"function"===typeof a.onIgnoreRow&&(h=a.onIgnoreRow(d(b),e));if(!1===h&& |
|||
(0===a.ignoreRow.length||-1===d.inArray(e,a.ignoreRow)&&-1===d.inArray(e-q,a.ignoreRow))&&I(d(b))){b=v(d(b),c);var n=b.length,l=0,u=0;b.each(function(){var b=d(this),a=J(this),c=T(this),h;d.each(G,function(){if(e>this.s.r&&e<=this.e.r&&l>=this.s.c&&l<=this.e.c)for(h=0;h<=this.e.c-this.s.c;++h)n++,u++,f(null,e,l++)});if(c||a)a=a||1,G.push({s:{r:e,c:l},e:{r:e+(c||1)-1,c:l+a-1}});!1===ta(b,n,u++)&&f(this,e,l++);if(1<a)for(h=0;h<a-1;++h)u++,f(null,e,l++)});d.each(G,function(){if(e>=this.s.r&&e<=this.e.r&& |
|||
l>=this.s.c&&l<=this.e.c)for(ea=0;ea<=this.e.c-this.s.c;++ea)f(null,e,l++)})}}}function ua(b,a,e,d){if("undefined"!==typeof d.images&&(e=d.images[e],"undefined"!==typeof e)){a=a.getBoundingClientRect();var c=b.width/b.height,h=a.width/a.height,q=b.width,l=b.height,u=19.049976/25.4,g=0;h<=c?(l=Math.min(b.height,a.height),q=a.width*l/a.height):h>c&&(q=Math.min(b.width,a.width),l=a.height*q/a.width);q*=u;l*=u;l<b.height&&(g=(b.height-l)/2);try{d.doc.addImage(e.src,b.textPos.x,b.y+g,q,l)}catch(Pa){}b.textPos.x+= |
|||
q}}function va(b,c){if("string"===a.outputMode)return b.output();if("base64"===a.outputMode)return L(b.output());if("window"===a.outputMode)window.URL=window.URL||window.webkitURL,window.open(window.URL.createObjectURL(b.output("blob")));else try{var e=b.output("blob");saveAs(e,a.fileName+".pdf")}catch(q){ka(a.fileName+".pdf","data:application/pdf"+(c?"":";base64")+",",c?b.output("blob"):b.output())}}function wa(b,a,e){var c=0;"undefined"!==typeof e&&(c=e.colspan);if(0<=c){for(var f=b.width,d=b.textPos.x, |
|||
n=a.table.columns.indexOf(a.column),l=1;l<c;l++)f+=a.table.columns[n+l].width;1<c&&("right"===b.styles.halign?d=b.textPos.x+f-b.width:"center"===b.styles.halign&&(d=b.textPos.x+(f-b.width)/2));b.width=f;b.textPos.x=d;"undefined"!==typeof e&&1<e.rowspan&&(b.height*=e.rowspan);if("middle"===b.styles.valign||"bottom"===b.styles.valign)e=("string"===typeof b.text?b.text.split(/\r\n|\r|\n/g):b.text).length||1,2<e&&(b.textPos.y-=(2-1.15)/2*a.row.styles.fontSize*(e-2)/3);return!0}return!1}function xa(b, |
|||
a,e){"undefined"!==typeof b&&null!==b&&(b.hasAttribute("data-tableexport-canvas")?(a=(new Date).getTime(),d(b).attr("data-tableexport-canvas",a),e.images[a]={url:'[data-tableexport-canvas="'+a+'"]',src:null}):"undefined"!==a&&null!=a&&a.each(function(){if(d(this).is("img")){var a=ya(this.src);e.images[a]={url:this.src,src:this.src}}xa(b,d(this).children(),e)}))}function Ka(b,a){function c(b){if(b.url)if(b.src){var c=new Image;q=++f;c.crossOrigin="Anonymous";c.onerror=c.onload=function(){if(c.complete&& |
|||
(0===c.src.indexOf("data:image/")&&(c.width=b.width||c.width||0,c.height=b.height||c.height||0),c.width+c.height)){var e=document.createElement("canvas"),d=e.getContext("2d");e.width=c.width;e.height=c.height;d.drawImage(c,0,0);b.src=e.toDataURL("image/png")}--f||a(q)};c.src=b.url}else{var e=d(b.url);e.length&&(q=++f,html2canvas(e[0]).then(function(c){b.src=c.toDataURL("image/png");--f||a(q)}))}}var q=0,f=0;if("undefined"!==typeof b.images)for(var h in b.images)b.images.hasOwnProperty(h)&&c(b.images[h]); |
|||
(b=f)||(a(q),b=void 0);return b}function za(b,c,e){c.each(function(){if(d(this).is("div")){var c=fa(M(this,"background-color"),[255,255,255]),f=fa(M(this,"border-top-color"),[0,0,0]),h=ha(this,"border-top-width",a.jspdf.unit),n=this.getBoundingClientRect(),l=this.offsetLeft*e.wScaleFactor,u=this.offsetTop*e.hScaleFactor,g=n.width*e.wScaleFactor;n=n.height*e.hScaleFactor;e.doc.setDrawColor.apply(void 0,f);e.doc.setFillColor.apply(void 0,c);e.doc.setLineWidth(h);e.doc.rect(b.x+l,b.y+u,g,n,h?"FD":"F")}else d(this).is("img")&& |
|||
(c=ya(this.src),ua(b,this,c,e));za(b,d(this).children(),e)})}function Aa(b,c,e){if("function"===typeof e.onAutotableText)e.onAutotableText(e.doc,b,c);else{var q=b.textPos.x,f=b.textPos.y,h={halign:b.styles.halign,valign:b.styles.valign};if(c.length){for(c=c[0];c.previousSibling;)c=c.previousSibling;for(var n=!1,l=!1;c;){var u=c.innerText||c.textContent||"",g=u.length&&" "===u[0]?" ":"",k=1<u.length&&" "===u[u.length-1]?" ":"";!0!==a.preserve.leadingWS&&(u=g+la(u));!0!==a.preserve.trailingWS&&(u=ma(u)+ |
|||
k);d(c).is("br")&&(q=b.textPos.x,f+=e.doc.internal.getFontSize());d(c).is("b")?n=!0:d(c).is("i")&&(l=!0);(n||l)&&e.doc.setFontType(n&&l?"bolditalic":n?"bold":"italic");if(g=e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize()){"linebreak"===b.styles.overflow&&q>b.textPos.x&&q+g>b.textPos.x+b.width&&(0<=".,!%*;:=-".indexOf(u.charAt(0))&&(k=u.charAt(0),g=e.doc.getStringUnitWidth(k)*e.doc.internal.getFontSize(),q+g<=b.textPos.x+b.width&&(e.doc.autoTableText(k,q,f,h),u=u.substring(1,u.length)),g= |
|||
e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize()),q=b.textPos.x,f+=e.doc.internal.getFontSize());if("visible"!==b.styles.overflow)for(;u.length&&q+g>b.textPos.x+b.width;)u=u.substring(0,u.length-1),g=e.doc.getStringUnitWidth(u)*e.doc.internal.getFontSize();e.doc.autoTableText(u,q,f,h);q+=g}if(n||l)d(c).is("b")?n=!1:d(c).is("i")&&(l=!1),e.doc.setFontType(n||l?n?"bold":"italic":"normal");c=c.nextSibling}b.textPos.x=q;b.textPos.y=f}else e.doc.autoTableText(b.text,b.textPos.x,b.textPos.y,h)}} |
|||
function W(b,a,e){return null==b?"":b.toString().replace(new RegExp(null==a?"":a.toString().replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1"),"g"),e)}function la(b){return null==b?"":b.toString().replace(/^\s+/,"")}function ma(b){return null==b?"":b.toString().replace(/\s+$/,"")}function La(b){if(0===a.date.html.length)return!1;a.date.pattern.lastIndex=0;var c=a.date.pattern.exec(b);if(null==c)return!1;b=+c[a.date.match_y];if(0>b||8099<b)return!1;var e=1*c[a.date.match_m];c=1*c[a.date.match_d];if(!isFinite(c))return!1; |
|||
var d=new Date(b,e-1,c,0,0,0);return d.getFullYear()===b&&d.getMonth()===e-1&&d.getDate()===c?new Date(Date.UTC(b,e-1,c,0,0,0)):!1}function na(b){b=b||"0";""!==a.numbers.html.thousandsSeparator&&(b=W(b,a.numbers.html.thousandsSeparator,""));"."!==a.numbers.html.decimalMark&&(b=W(b,a.numbers.html.decimalMark,"."));return"number"===typeof b||!1!==jQuery.isNumeric(b)?b:!1}function Ma(b){-1<b.indexOf("%")?(b=na(b.replace(/%/g,"")),!1!==b&&(b/=100)):b=!1;return b}function D(b,c,e,q){var f="",h="text"; |
|||
if(null!==b){var n=d(b);n.removeData("teUserDefText");if(n[0].hasAttribute("data-tableexport-canvas"))var l="";else if(n[0].hasAttribute("data-tableexport-value"))l=(l=n.attr("data-tableexport-value"))?l+"":"",n.data("teUserDefText",1);else if(l=n.html(),"function"===typeof a.onCellHtmlData)l=a.onCellHtmlData(n,c,e,l),n.data("teUserDefText",1);else if(""!==l){b=d.parseHTML(l);var g=0,k=0;l="";d.each(b,function(){if(d(this).is("input"))l+=n.find("input").eq(g++).val();else if(d(this).is("select"))l+= |
|||
n.find("select option:selected").eq(k++).text();else if(d(this).is("br"))l+="<br>";else{if("undefined"===typeof d(this).html())l+=d(this).text();else if(void 0===jQuery().bootstrapTable||!1===d(this).hasClass("fht-cell")&&!1===d(this).hasClass("filterControl")&&0===n.parents(".detail-view").length)l+=d(this).html();if(d(this).is("a")){var b=n.find("a").attr("href")||"";f="function"===typeof a.onCellHtmlHyperlink?f+a.onCellHtmlHyperlink(n,c,e,b,l):"href"===a.htmlHyperlink?f+b:f+l;l=""}}})}if(l&&""!== |
|||
l&&!0===a.htmlContent)f=d.trim(l);else if(l&&""!==l)if(""!==n.attr("data-tableexport-cellformat")){var m=l.replace(/\n/g,"\u2028").replace(/(<\s*br([^>]*)>)/gi,"\u2060"),p=d("<div/>").html(m).contents();b=!1;m="";d.each(p.text().split("\u2028"),function(b,c){0<b&&(m+=" ");!0!==a.preserve.leadingWS&&(c=la(c));m+=!0!==a.preserve.trailingWS?ma(c):c});d.each(m.split("\u2060"),function(b,c){0<b&&(f+="\n");!0!==a.preserve.leadingWS&&(c=la(c));!0!==a.preserve.trailingWS&&(c=ma(c));f+=c.replace(/\u00AD/g, |
|||
"")});f=f.replace(/\u00A0/g," ");if("json"===a.type||"excel"===a.type&&"xmlss"===a.mso.fileFormat||!1===a.numbers.output)b=na(f),!1!==b&&(h="number",f=Number(b));else if(a.numbers.html.decimalMark!==a.numbers.output.decimalMark||a.numbers.html.thousandsSeparator!==a.numbers.output.thousandsSeparator)if(b=na(f),!1!==b){p=(""+b.substr(0>b?1:0)).split(".");1===p.length&&(p[1]="");var t=3<p[0].length?p[0].length%3:0;h="number";f=(0>b?"-":"")+(a.numbers.output.thousandsSeparator?(t?p[0].substr(0,t)+a.numbers.output.thousandsSeparator: |
|||
"")+p[0].substr(t).replace(/(\d{3})(?=\d)/g,"$1"+a.numbers.output.thousandsSeparator):p[0])+(p[1].length?a.numbers.output.decimalMark+p[1]:"")}}else f=l;!0===a.escape&&(f=escape(f));"function"===typeof a.onCellData&&(f=a.onCellData(n,c,e,f,h),n.data("teUserDefText",1))}void 0!==q&&(q.type=h);return f}function Ba(b){return 0<b.length&&!0===a.preventInjection&&0<="=+-@".indexOf(b.charAt(0))?"'"+b:b}function Na(b,a,e){return a+"-"+e.toLowerCase()}function fa(b,a){(b=/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(b))&& |
|||
(a=[parseInt(b[1]),parseInt(b[2]),parseInt(b[3])]);return a}function Ca(b){var a=M(b,"text-align"),e=M(b,"font-weight"),d=M(b,"font-style"),f="";"start"===a&&(a="rtl"===M(b,"direction")?"right":"left");700<=e&&(f="bold");"italic"===d&&(f+=d);""===f&&(f="normal");a={style:{align:a,bcolor:fa(M(b,"background-color"),[255,255,255]),color:fa(M(b,"color"),[0,0,0]),fstyle:f},colspan:J(b),rowspan:T(b)};null!==b&&(b=b.getBoundingClientRect(),a.rect={width:b.width,height:b.height});return a}function J(b){var a= |
|||
d(b).attr("data-tableexport-colspan");"undefined"===typeof a&&d(b).is("[colspan]")&&(a=d(b).attr("colspan"));return parseInt(a)||0}function T(b){var a=d(b).attr("data-tableexport-rowspan");"undefined"===typeof a&&d(b).is("[rowspan]")&&(a=d(b).attr("rowspan"));return parseInt(a)||0}function M(a,c){try{return window.getComputedStyle?(c=c.replace(/([a-z])([A-Z])/,Na),window.getComputedStyle(a,null).getPropertyValue(c)):a.currentStyle?a.currentStyle[c]:a.style[c]}catch(e){}return""}function ha(a,c,e){c= |
|||
M(a,c).match(/\d+/);if(null!==c){c=c[0];a=a.parentElement;var b=document.createElement("div");b.style.overflow="hidden";b.style.visibility="hidden";a.appendChild(b);b.style.width=100+e;e=100/b.offsetWidth;a.removeChild(b);return c*e}return 0}function Oa(a){for(var b=new ArrayBuffer(a.length),e=new Uint8Array(b),d=0;d!==a.length;++d)e[d]=a.charCodeAt(d)&255;return b}function oa(a){var b=a.c,e="";for(++b;b;b=Math.floor((b-1)/26))e=String.fromCharCode((b-1)%26+65)+e;return e+(""+(a.r+1))}function pa(a, |
|||
c){if("undefined"===typeof c||"number"===typeof c)return pa(a.s,a.e);"string"!==typeof a&&(a=oa(a));"string"!==typeof c&&(c=oa(c));return a===c?a:a+":"+c}function Da(a,c){var b=Number(a);if(isFinite(b))return b;var d=1;""!==c.thousandsSeparator&&(a=a.replace(new RegExp("([\\d])"+c.thousandsSeparator+"([\\d])","g"),"$1$2"));"."!==c.decimalMark&&(a=a.replace(new RegExp("([\\d])"+c.decimalMark+"([\\d])","g"),"$1.$2"));a=a.replace(/[$]/g,"").replace(/[%]/g,function(){d*=100;return""});if(isFinite(b=Number(a)))return b/ |
|||
d;a=a.replace(/[(](.*)[)]/,function(a,b){d=-d;return b});return isFinite(b=Number(a))?b/d:b}function ya(a){var b=0,d;if(0===a.length)return b;var q=0;for(d=a.length;q<d;q++){var f=a.charCodeAt(q);b=(b<<5)-b+f;b|=0}return b}function N(b,c,d,q,f,h){var e=!0;"function"===typeof a.onBeforeSaveToFile&&(e=a.onBeforeSaveToFile(b,c,d,q,f),"boolean"!==typeof e&&(e=!0));if(e)try{if(Ea=new Blob([b],{type:d+";charset="+q}),saveAs(Ea,c,!1===h),"function"===typeof a.onAfterSaveToFile)a.onAfterSaveToFile(b,c)}catch(l){ka(c, |
|||
"data:"+d+(q.length?";charset="+q:"")+(f.length?";"+f:"")+",",h?"\ufeff"+b:b)}}function ka(b,c,d){var e=window.navigator.userAgent;if(!1!==b&&window.navigator.msSaveOrOpenBlob)window.navigator.msSaveOrOpenBlob(new Blob([d]),b);else if(!1!==b&&(0<e.indexOf("MSIE ")||e.match(/Trident.*rv\:11\./))){if(c=document.createElement("iframe")){document.body.appendChild(c);c.setAttribute("style","display:none");c.contentDocument.open("txt/plain","replace");c.contentDocument.write(d);c.contentDocument.close(); |
|||
c.contentWindow.focus();switch(b.substr(b.lastIndexOf(".")+1)){case "doc":case "json":case "png":case "pdf":case "xls":case "xlsx":b+=".txt"}c.contentDocument.execCommand("SaveAs",!0,b);document.body.removeChild(c)}}else{var f=document.createElement("a");if(f){var h=null;f.style.display="none";!1!==b?f.download=b:f.target="_blank";"object"===typeof d?(window.URL=window.URL||window.webkitURL,e=[],e.push(d),h=window.URL.createObjectURL(new Blob(e,{type:c})),f.href=h):0<=c.toLowerCase().indexOf("base64,")? |
|||
f.href=c+L(d):f.href=c+encodeURIComponent(d);document.body.appendChild(f);if(document.createEvent)null===ia&&(ia=document.createEvent("MouseEvents")),ia.initEvent("click",!0,!1),f.dispatchEvent(ia);else if(document.createEventObject)f.fireEvent("onclick");else if("function"===typeof f.onclick)f.onclick();setTimeout(function(){h&&window.URL.revokeObjectURL(h);document.body.removeChild(f);if("function"===typeof a.onAfterSaveToFile)a.onAfterSaveToFile(d,b)},100)}}}function L(a){var b,d="",q=0;if("string"=== |
|||
typeof a){a=a.replace(/\x0d\x0a/g,"\n");var f="";for(b=0;b<a.length;b++){var h=a.charCodeAt(b);128>h?f+=String.fromCharCode(h):(127<h&&2048>h?f+=String.fromCharCode(h>>6|192):(f+=String.fromCharCode(h>>12|224),f+=String.fromCharCode(h>>6&63|128)),f+=String.fromCharCode(h&63|128))}a=f}for(;q<a.length;){var n=a.charCodeAt(q++);f=a.charCodeAt(q++);b=a.charCodeAt(q++);h=n>>2;n=(n&3)<<4|f>>4;var l=(f&15)<<2|b>>6;var g=b&63;isNaN(f)?l=g=64:isNaN(b)&&(g=64);d=d+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h)+ |
|||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(n)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(l)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(g)}return d}var a={csvEnclosure:'"',csvSeparator:",",csvUseBOM:!0,date:{html:"dd/mm/yyyy"},displayTableName:!1,escape:!1,exportHiddenCells:!1,fileName:"tableExport",htmlContent:!1,htmlHyperlink:"content",ignoreColumn:[],ignoreRow:[],jsonScope:"all",jspdf:{orientation:"p", |
|||
unit:"pt",format:"a4",margins:{left:20,right:10,top:10,bottom:10},onDocCreated:null,autotable:{styles:{cellPadding:2,rowHeight:12,fontSize:8,fillColor:255,textColor:50,fontStyle:"normal",overflow:"ellipsize",halign:"inherit",valign:"middle"},headerStyles:{fillColor:[52,73,94],textColor:255,fontStyle:"bold",halign:"inherit",valign:"middle"},alternateRowStyles:{fillColor:245},tableExport:{doc:null,onAfterAutotable:null,onBeforeAutotable:null,onAutotableText:null,onTable:null,outputImages:!0}}},mso:{fileFormat:"xlshtml", |
|||
onMsoNumberFormat:null,pageFormat:"a4",pageOrientation:"portrait",rtl:!1,styles:[],worksheetName:"",xslx:{formatId:{date:14,numbers:2}}},numbers:{html:{decimalMark:".",thousandsSeparator:","},output:{decimalMark:".",thousandsSeparator:","}},onAfterSaveToFile:null,onBeforeSaveToFile:null,onCellData:null,onCellHtmlData:null,onCellHtmlHyperlink:null,onIgnoreRow:null,onTableExportBegin:null,onTableExportEnd:null,outputMode:"file",pdfmake:{enabled:!1,docDefinition:{pageSize:"A4",pageOrientation:"portrait", |
|||
styles:{header:{background:"#34495E",color:"#FFFFFF",bold:!0,alignment:"center",fillColor:"#34495E"},alternateRow:{fillColor:"#f5f5f5"}},defaultStyle:{color:"#000000",fontSize:8,font:"Roboto"}},fonts:{}},preserve:{leadingWS:!1,trailingWS:!1},preventInjection:!0,sql:{tableEnclosure:"`",columnEnclosure:"`"},tbodySelector:"tr",tfootSelector:"tr",theadSelector:"tr",tableName:"Table",type:"csv"},O={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89],a5:[419.53, |
|||
595.28],a6:[297.64,419.53],a7:[209.76,297.64],a8:[147.4,209.76],a9:[104.88,147.4],a10:[73.7,104.88],b0:[2834.65,4008.19],b1:[2004.09,2834.65],b2:[1417.32,2004.09],b3:[1000.63,1417.32],b4:[708.66,1000.63],b5:[498.9,708.66],b6:[354.33,498.9],b7:[249.45,354.33],b8:[175.75,249.45],b9:[124.72,175.75],b10:[87.87,124.72],c0:[2599.37,3676.54],c1:[1836.85,2599.37],c2:[1298.27,1836.85],c3:[918.43,1298.27],c4:[649.13,918.43],c5:[459.21,649.13],c6:[323.15,459.21],c7:[229.61,323.15],c8:[161.57,229.61],c9:[113.39, |
|||
161.57],c10:[79.37,113.39],dl:[311.81,623.62],letter:[612,792],"government-letter":[576,756],legal:[612,1008],"junior-legal":[576,360],ledger:[1224,792],tabloid:[792,1224],"credit-card":[153,243]},B=this,ia=null,r=[],w=[],p=0,t="",S=[],G=[],Ea,K=[],V=!1;d.extend(!0,a,k);"xlsx"===a.type&&(a.mso.fileFormat=a.type,a.type="excel");"undefined"!==typeof a.excelFileFormat&&"undefined"===a.mso.fileFormat&&(a.mso.fileFormat=a.excelFileFormat);"undefined"!==typeof a.excelPageFormat&&"undefined"===a.mso.pageFormat&& |
|||
(a.mso.pageFormat=a.excelPageFormat);"undefined"!==typeof a.excelPageOrientation&&"undefined"===a.mso.pageOrientation&&(a.mso.pageOrientation=a.excelPageOrientation);"undefined"!==typeof a.excelRTL&&"undefined"===a.mso.rtl&&(a.mso.rtl=a.excelRTL);"undefined"!==typeof a.excelstyles&&"undefined"===a.mso.styles&&(a.mso.styles=a.excelstyles);"undefined"!==typeof a.onMsoNumberFormat&&"undefined"===a.mso.onMsoNumberFormat&&(a.mso.onMsoNumberFormat=a.onMsoNumberFormat);"undefined"!==typeof a.worksheetName&& |
|||
"undefined"===a.mso.worksheetName&&(a.mso.worksheetName=a.worksheetName);a.mso.pageOrientation="l"===a.mso.pageOrientation.substr(0,1)?"landscape":"portrait";a.date.html=a.date.html||"";if(a.date.html.length){k=[];k.dd="(3[01]|[12][0-9]|0?[1-9])";k.mm="(1[012]|0?[1-9])";k.yyyy="((?:1[6-9]|2[0-2])\\d{2})";k.yy="(\\d{2})";var z=a.date.html.match(/[^a-zA-Z0-9]/)[0];z=a.date.html.toLowerCase().split(z);a.date.regex="^\\s*";a.date.regex+=k[z[0]];a.date.regex+="(.)";a.date.regex+=k[z[1]];a.date.regex+= |
|||
"\\2";a.date.regex+=k[z[2]];a.date.regex+="\\s*$";a.date.pattern=new RegExp(a.date.regex,"g");k=z.indexOf("dd")+1;a.date.match_d=k+(1<k?1:0);k=z.indexOf("mm")+1;a.date.match_m=k+(1<k?1:0);k=(0<=z.indexOf("yyyy")?z.indexOf("yyyy"):z.indexOf("yy"))+1;a.date.match_y=k+(1<k?1:0)}S=R(B);if("function"===typeof a.onTableExportBegin)a.onTableExportBegin();if("csv"===a.type||"tsv"===a.type||"txt"===a.type){var P="",Z=0;G=[];p=0;var qa=function(b,c,e){b.each(function(){t="";E(this,c,p,e+b.length,function(b, |
|||
c,d){var e=t,f="";if(null!==b)if(b=D(b,c,d),c=null===b||""===b?"":b.toString(),"tsv"===a.type)b instanceof Date&&b.toLocaleString(),f=W(c,"\t"," ");else if(b instanceof Date)f=a.csvEnclosure+b.toLocaleString()+a.csvEnclosure;else if(f=Ba(c),f=W(f,a.csvEnclosure,a.csvEnclosure+a.csvEnclosure),0<=f.indexOf(a.csvSeparator)||/[\r\n ]/g.test(f))f=a.csvEnclosure+f+a.csvEnclosure;t=e+(f+("tsv"===a.type?"\t":a.csvSeparator))});t=d.trim(t).substring(0,t.length-1);0<t.length&&(0<P.length&&(P+="\n"),P+=t);p++}); |
|||
return b.length};Z+=qa(d(B).find("thead").first().find(a.theadSelector),"th,td",Z);v(d(B),"tbody").each(function(){Z+=qa(v(d(this),a.tbodySelector),"td,th",Z)});a.tfootSelector.length&&qa(d(B).find("tfoot").first().find(a.tfootSelector),"td,th",Z);P+="\n";if("string"===a.outputMode)return P;if("base64"===a.outputMode)return L(P);if("window"===a.outputMode){ka(!1,"data:text/"+("csv"===a.type?"csv":"plain")+";charset=utf-8,",P);return}N(P,a.fileName+"."+a.type,"text/"+("csv"===a.type?"csv":"plain"), |
|||
"utf-8","","csv"===a.type&&a.csvUseBOM)}else if("sql"===a.type){p=0;G=[];var A="INSERT INTO "+a.sql.tableEnclosure+a.tableName+a.sql.tableEnclosure+" (";r=y(d(B));d(r).each(function(){E(this,"th,td",p,r.length,function(b,c,d){b=D(b,c,d)||"";-1<b.indexOf(a.sql.columnEnclosure)&&(b=W(b.toString(),a.sql.columnEnclosure,a.sql.columnEnclosure+a.sql.columnEnclosure));A+=a.sql.columnEnclosure+b+a.sql.columnEnclosure+","});p++;A=d.trim(A).substring(0,A.length-1)});A+=") VALUES ";w=C(d(B));d(w).each(function(){t= |
|||
"";E(this,"td,th",p,r.length+w.length,function(a,c,d){a=D(a,c,d)||"";-1<a.indexOf("'")&&(a=W(a.toString(),"'","''"));t+="'"+a+"',"});3<t.length&&(A+="("+t,A=d.trim(A).substring(0,A.length-1),A+="),");p++});A=d.trim(A).substring(0,A.length-1);A+=";";if("string"===a.outputMode)return A;if("base64"===a.outputMode)return L(A);N(A,a.fileName+".sql","application/sql","utf-8","",!1)}else if("json"===a.type){var X=[];G=[];r=y(d(B));d(r).each(function(){var a=[];E(this,"th,td",p,r.length,function(b,d,g){a.push(D(b, |
|||
d,g))});X.push(a)});var ra=[];w=C(d(B));d(w).each(function(){var a={},c=0;E(this,"td,th",p,r.length+w.length,function(b,d,f){X.length?a[X[X.length-1][c]]=D(b,d,f):a[c]=D(b,d,f);c++});!1===d.isEmptyObject(a)&&ra.push(a);p++});k="head"===a.jsonScope?JSON.stringify(X):"data"===a.jsonScope?JSON.stringify(ra):JSON.stringify({header:X,data:ra});if("string"===a.outputMode)return k;if("base64"===a.outputMode)return L(k);N(k,a.fileName+".json","application/json","utf-8","base64",!1)}else if("xml"===a.type){p= |
|||
0;G=[];var Q='<?xml version="1.0" encoding="utf-8"?>';Q+="<tabledata><fields>";r=y(d(B));d(r).each(function(){E(this,"th,td",p,r.length,function(a,d,e){Q+="<field>"+D(a,d,e)+"</field>"});p++});Q+="</fields><data>";var Fa=1;w=C(d(B));d(w).each(function(){var a=1;t="";E(this,"td,th",p,r.length+w.length,function(b,d,g){t+="<column-"+a+">"+D(b,d,g)+"</column-"+a+">";a++});0<t.length&&"<column-1></column-1>"!==t&&(Q+='<row id="'+Fa+'">'+t+"</row>",Fa++);p++});Q+="</data></tabledata>";if("string"===a.outputMode)return Q; |
|||
if("base64"===a.outputMode)return L(Q);N(Q,a.fileName+".xml","application/xml","utf-8","base64",!1)}else if("excel"===a.type&&"xmlss"===a.mso.fileFormat){var sa=[],F=[];d(B).filter(function(){return I(d(this))}).each(function(){function b(a,b,c){var f=[];d(a).each(function(){var b=0,e=0;t="";E(this,"td,th",p,c+a.length,function(a,c,h){if(null!==a){var l="";c=D(a,c,h);h="String";if(!1!==jQuery.isNumeric(c))h="Number";else{var n=Ma(c);!1!==n&&(c=n,h="Number",l+=' ss:StyleID="pct1"')}"Number"!==h&&(c= |
|||
c.replace(/\n/g,"<br>"));n=J(a);a=T(a);d.each(f,function(){if(p>=this.s.r&&p<=this.e.r&&e>=this.s.c&&e<=this.e.c)for(var a=0;a<=this.e.c-this.s.c;++a)e++,b++});if(a||n)a=a||1,n=n||1,f.push({s:{r:p,c:e},e:{r:p+a-1,c:e+n-1}});1<n&&(l+=' ss:MergeAcross="'+(n-1)+'"',e+=n-1);1<a&&(l+=' ss:MergeDown="'+(a-1)+'" ss:StyleID="rsp1"');0<b&&(l+=' ss:Index="'+(e+1)+'"',b=0);t+="<Cell"+l+'><Data ss:Type="'+h+'">'+d("<div />").text(c).html()+"</Data></Cell>\r";e++}});0<t.length&&(H+='<Row ss:AutoFitHeight="0">\r'+ |
|||
t+"</Row>\r");p++});return a.length}var c=d(this),e="";"string"===typeof a.mso.worksheetName&&a.mso.worksheetName.length?e=a.mso.worksheetName+" "+(F.length+1):"undefined"!==typeof a.mso.worksheetName[F.length]&&(e=a.mso.worksheetName[F.length]);e.length||(e=c.find("caption").text()||"");e.length||(e="Table "+(F.length+1));e=d.trim(e.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31));F.push(d("<div />").text(e).html());!1===a.exportHiddenCells&&(K=c.find("tr, th, td").filter(":hidden"),V=0<K.length); |
|||
p=0;S=R(this);H="<Table>\r";e=b(y(c),"th,td",0);b(C(c),"td,th",e);H+="</Table>\r";sa.push(H)});k={};z={};for(var m,aa,Y=0,ea=F.length;Y<ea;Y++)m=F[Y],aa=k[m],aa=k[m]=null==aa?1:aa+1,2===aa&&(F[z[m]]=F[z[m]].substring(0,29)+"-1"),1<k[m]?F[Y]=F[Y].substring(0,29)+"-"+k[m]:z[m]=Y;k='<?xml version="1.0" encoding="UTF-8"?>\r<?mso-application progid="Excel.Sheet"?>\r<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"\r xmlns:o="urn:schemas-microsoft-com:office:office"\r xmlns:x="urn:schemas-microsoft-com:office:excel"\r xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"\r xmlns:html="http://www.w3.org/TR/REC-html40">\r<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">\r <Created>'+ |
|||
(new Date).toISOString()+'</Created>\r</DocumentProperties>\r<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">\r <AllowPNG/>\r</OfficeDocumentSettings>\r<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">\r <WindowHeight>9000</WindowHeight>\r <WindowWidth>13860</WindowWidth>\r <WindowTopX>0</WindowTopX>\r <WindowTopY>0</WindowTopY>\r <ProtectStructure>False</ProtectStructure>\r <ProtectWindows>False</ProtectWindows>\r</ExcelWorkbook>\r<Styles>\r <Style ss:ID="Default" ss:Name="Normal">\r <Alignment ss:Vertical="Bottom"/>\r <Borders/>\r <Font/>\r <Interior/>\r <NumberFormat/>\r <Protection/>\r </Style>\r <Style ss:ID="rsp1">\r <Alignment ss:Vertical="Center"/>\r </Style>\r <Style ss:ID="pct1">\r <NumberFormat ss:Format="Percent"/>\r </Style>\r</Styles>\r'; |
|||
for(z=0;z<sa.length;z++)k+='<Worksheet ss:Name="'+F[z]+'" ss:RightToLeft="'+(a.mso.rtl?"1":"0")+'">\r'+sa[z],k=a.mso.rtl?k+'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">\r<DisplayRightToLeft/>\r</WorksheetOptions>\r':k+'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"/>\r',k+="</Worksheet>\r";k+="</Workbook>\r";if("string"===a.outputMode)return k;if("base64"===a.outputMode)return L(k);N(k,a.fileName+".xml","application/xml","utf-8","base64",!1)}else if("excel"=== |
|||
a.type&&"xlsx"===a.mso.fileFormat){var ba=[],Ga=XLSX.utils.book_new();d(B).filter(function(){return I(d(this))}).each(function(){for(var b=d(this),c={},e=this.getElementsByTagName("tr"),g={s:{r:0,c:0},e:{r:0,c:0}},f=[],h,n=[],l=0,u=0,k,m,p,t,r,w=XLSX.SSF.get_table();l<e.length&&1E7>u;++l)if(k=e[l],m=!1,"function"===typeof a.onIgnoreRow&&(m=a.onIgnoreRow(d(k),l)),!0!==m&&(0===a.ignoreRow.length||-1===d.inArray(l,a.ignoreRow)&&-1===d.inArray(l-e.length,a.ignoreRow))&&!1!==I(d(k))){var y=k.children, |
|||
B=0;for(k=0;k<y.length;++k)r=y[k],t=+J(r)||1,B+=t;var z=0;for(k=m=0;k<y.length;++k)if(r=y[k],t=+J(r)||1,h=k+z,!ta(d(r),B,h+(h<m?m-h:0))){z+=t-1;for(h=0;h<f.length;++h){var v=f[h];v.s.c==m&&v.s.r<=u&&u<=v.e.r&&(m=v.e.c+1,h=-1)}(0<(p=+T(r))||1<t)&&f.push({s:{r:u,c:m},e:{r:u+(p||1)-1,c:m+t-1}});var C={type:""};h=D(r,l,k+z,C);v={t:"s",v:h};var A="";if(""!==(d(r).attr("data-tableexport-cellformat")||"")){var x=parseInt(d(r).attr("data-tableexport-xlsxformatid")||0);0===x&&"function"===typeof a.mso.xslx.formatId.numbers&& |
|||
(x=a.mso.xslx.formatId.numbers(d(r),l,k+z));0===x&&"function"===typeof a.mso.xslx.formatId.date&&(x=a.mso.xslx.formatId.date(d(r),l,k+z));if(49===x||"@"===x)A="s";else if("number"===C.type||0<x&&14>x||36<x&&41>x||48===x)A="n";else if("date"===C.type||13<x&&37>x||44<x&&48>x||56===x)A="d"}else A="s";if(null!=h)if(0===h.length)v.t="z";else if(0!==h.trim().length)if("s"===A)d(r).find("a").length&&(h="href"!==a.htmlHyperlink?h:"",v={f:'=HYPERLINK("'+d(r).find("a").attr("href")+(h.length?'","'+h:"")+'")'}); |
|||
else if("function"===C.type)v={f:h};else if("TRUE"===h)v={t:"b",v:!0};else if("FALSE"===h)v={t:"b",v:!1};else if("n"===A||isFinite(Da(h,a.numbers.output))){if(r=Da(h,a.numbers.output),0===x&&"function"!==typeof a.mso.xslx.formatId.numbers&&(x=a.mso.xslx.formatId.numbers),isFinite(r)||isFinite(h))v={t:"n",v:isFinite(r)?r:h,z:"string"===typeof x?x:x in w?w[x]:"0.00"}}else if(!1!==(r=La(h))||"d"===A)0===x&&"function"!==typeof a.mso.xslx.formatId.date&&(x=a.mso.xslx.formatId.date),v={t:"d",v:!1!==r?r: |
|||
h,z:"string"===typeof x?x:x in w?w[x]:"m/d/yy"};c[oa({c:m,r:u})]=v;g.e.c<m&&(g.e.c=m);m+=t}++u}f.length&&(c["!merges"]=f);n.length&&(c["!rows"]=n);g.e.r=u-1;c["!ref"]=pa(g);1E7<=u&&(c["!fullref"]=pa((g.e.r=e.length-l+u-1,g)));e="";"string"===typeof a.mso.worksheetName&&a.mso.worksheetName.length?e=a.mso.worksheetName+" "+(ba.length+1):"undefined"!==typeof a.mso.worksheetName[ba.length]&&(e=a.mso.worksheetName[ba.length]);e.length||(e=b.find("caption").text()||"");e.length||(e="Table "+(ba.length+ |
|||
1));e=d.trim(e.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31));ba.push(e);XLSX.utils.book_append_sheet(Ga,c,e)});k=XLSX.write(Ga,{type:"binary",bookType:a.mso.fileFormat,bookSST:!1});N(Oa(k),a.fileName+"."+a.mso.fileFormat,"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","UTF-8","",!1)}else if("excel"===a.type||"xls"===a.type||"word"===a.type||"doc"===a.type){k="excel"===a.type||"xls"===a.type?"excel":"word";z="excel"===k?"xls":"doc";m='xmlns:x="urn:schemas-microsoft-com:office:'+ |
|||
k+'"';var H="",ca="";d(B).filter(function(){return I(d(this))}).each(function(){var b=d(this);""===ca&&(ca=a.mso.worksheetName||b.find("caption").text()||"Table",ca=d.trim(ca.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31)));!1===a.exportHiddenCells&&(K=b.find("tr, th, td").filter(":hidden"),V=0<K.length);p=0;G=[];S=R(this);H+="<table><thead>";r=y(b);d(r).each(function(){var b=d(this);t="";E(this,"th,td",p,r.length,function(d,c,f){if(null!==d){var e="";t+="<th";if(a.mso.styles.length){var n=document.defaultView.getComputedStyle(d, |
|||
null),l=document.defaultView.getComputedStyle(b[0],null),g;for(g in a.mso.styles){var k=n[a.mso.styles[g]];""===k&&(k=l[a.mso.styles[g]]);""!==k&&"0px none rgb(0, 0, 0)"!==k&&"rgba(0, 0, 0, 0)"!==k&&(e+=""===e?'style="':";",e+=a.mso.styles[g]+":"+k)}}""!==e&&(t+=" "+e+'"');e=J(d);0<e&&(t+=' colspan="'+e+'"');e=T(d);0<e&&(t+=' rowspan="'+e+'"');t+=">"+D(d,c,f)+"</th>"}});0<t.length&&(H+="<tr>"+t+"</tr>");p++});H+="</thead><tbody>";w=C(b);d(w).each(function(){var b=d(this);t="";E(this,"td,th",p,r.length+ |
|||
w.length,function(c,g,f){if(null!==c){var e=D(c,g,f),n="",l=d(c).attr("data-tableexport-msonumberformat");"undefined"===typeof l&&"function"===typeof a.mso.onMsoNumberFormat&&(l=a.mso.onMsoNumberFormat(c,g,f));"undefined"!==typeof l&&""!==l&&(n="style=\"mso-number-format:'"+l+"'");if(a.mso.styles.length){g=document.defaultView.getComputedStyle(c,null);f=document.defaultView.getComputedStyle(b[0],null);for(var k in a.mso.styles)l=g[a.mso.styles[k]],""===l&&(l=f[a.mso.styles[k]]),""!==l&&"0px none rgb(0, 0, 0)"!== |
|||
l&&"rgba(0, 0, 0, 0)"!==l&&(n+=""===n?'style="':";",n+=a.mso.styles[k]+":"+l)}t+="<td";""!==n&&(t+=" "+n+'"');n=J(c);0<n&&(t+=' colspan="'+n+'"');c=T(c);0<c&&(t+=' rowspan="'+c+'"');"string"===typeof e&&""!==e&&(e=Ba(e),e=e.replace(/\n/g,"<br>"));t+=">"+e+"</td>"}});0<t.length&&(H+="<tr>"+t+"</tr>");p++});a.displayTableName&&(H+="<tr><td></td></tr><tr><td></td></tr><tr><td>"+D(d("<p>"+a.tableName+"</p>"))+"</td></tr>");H+="</tbody></table>"});m='<html xmlns:o="urn:schemas-microsoft-com:office:office" '+ |
|||
m+' xmlns="http://www.w3.org/TR/REC-html40">'+('<meta http-equiv="content-type" content="application/vnd.ms-'+k+'; charset=UTF-8">')+"<head>";"excel"===k&&(m+="\x3c!--[if gte mso 9]>",m+="<xml>",m+="<x:ExcelWorkbook>",m+="<x:ExcelWorksheets>",m+="<x:ExcelWorksheet>",m+="<x:Name>",m+=ca,m+="</x:Name>",m+="<x:WorksheetOptions>",m+="<x:DisplayGridlines/>",a.mso.rtl&&(m+="<x:DisplayRightToLeft/>"),m+="</x:WorksheetOptions>",m+="</x:ExcelWorksheet>",m+="</x:ExcelWorksheets>",m+="</x:ExcelWorkbook>",m+= |
|||
"</xml>",m+="<![endif]--\x3e");m+="<style>";m+="@page { size:"+a.mso.pageOrientation+"; mso-page-orientation:"+a.mso.pageOrientation+"; }";m+="@page Section1 {size:"+O[a.mso.pageFormat][0]+"pt "+O[a.mso.pageFormat][1]+"pt";m+="; margin:1.0in 1.25in 1.0in 1.25in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";m+="div.Section1 {page:Section1;}";m+="@page Section2 {size:"+O[a.mso.pageFormat][1]+"pt "+O[a.mso.pageFormat][0]+"pt";m+=";mso-page-orientation:"+a.mso.pageOrientation+";margin:1.25in 1.0in 1.25in 1.0in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}"; |
|||
m+="div.Section2 {page:Section2;}";m+="br {mso-data-placement:same-cell;}";m+="</style>";m+="</head>";m+="<body>";m+='<div class="Section'+("landscape"===a.mso.pageOrientation?"2":"1")+'">';m+=H;m+="</div>";m+="</body>";m+="</html>";if("string"===a.outputMode)return m;if("base64"===a.outputMode)return L(m);N(m,a.fileName+"."+z,"application/vnd.ms-"+k,"","base64",!1)}else if("png"===a.type)html2canvas(d(B)[0]).then(function(b){b=b.toDataURL();for(var c=atob(b.substring(22)),d=new ArrayBuffer(c.length), |
|||
g=new Uint8Array(d),f=0;f<c.length;f++)g[f]=c.charCodeAt(f);if("string"===a.outputMode)return c;if("base64"===a.outputMode)return L(b);"window"===a.outputMode?window.open(b):N(d,a.fileName+".png","image/png","","",!1)});else if("pdf"===a.type)if(!0===a.pdfmake.enabled){var U={content:[]};d.extend(!0,U,a.pdfmake.docDefinition);G=[];d(B).filter(function(){return I(d(this))}).each(function(){var b=d(this),c=[],e=[];p=0;var g=function(a,b,c){var f=0;d(a).each(function(){var a=[];E(this,b,p,c,function(c, |
|||
d,f){if("undefined"!==typeof c&&null!==c){var e=J(c),h=T(c);c={text:D(c,d,f)||" "};if(1<e||1<h)c.colSpan=e||1,c.rowSpan=h||1}else c={text:" "};0<=b.indexOf("th")&&(c.style="header");a.push(c)});for(var d=a.length;d<c;d++)a.push("");a.length&&e.push(a);f<a.length&&(f=a.length);p++});return f};r=y(b);for(var f=g(r,"th,td",r.length),h=c.length;h<f;h++)c.push("*");w=C(b);f=g(w,"td",r.length+w.length);for(h=c.length;h<f;h++)c.push("*");U.content.push({table:{headerRows:r.length?r.length:null,widths:c, |
|||
body:e},layout:{layout:"noBorders",hLineStyle:function(a,b){return 0},vLineWidth:function(a,b){return 0},hLineColor:function(b,c){return b<c.table.headerRows?a.pdfmake.docDefinition.styles.header.background:a.pdfmake.docDefinition.styles.alternateRow.fillColor},vLineColor:function(b,c){return b<c.table.headerRows?a.pdfmake.docDefinition.styles.header.background:a.pdfmake.docDefinition.styles.alternateRow.fillColor},fillColor:function(b,c,d){return 0===b%2?a.pdfmake.docDefinition.styles.alternateRow.fillColor: |
|||
null}},pageBreak:U.content.length?"before":void 0})});"undefined"!==typeof pdfMake&&"undefined"!==typeof pdfMake.createPdf&&(pdfMake.fonts={Roboto:{normal:"Roboto-Regular.ttf",bold:"Roboto-Medium.ttf",italics:"Roboto-Italic.ttf",bolditalics:"Roboto-MediumItalic.ttf"}},pdfMake.vfs.hasOwnProperty("Mirza-Regular.ttf")?(U.defaultStyle.font="Mirza",d.extend(!0,pdfMake.fonts,{Mirza:{normal:"Mirza-Regular.ttf",bold:"Mirza-Bold.ttf",italics:"Mirza-Medium.ttf",bolditalics:"Mirza-SemiBold.ttf"}})):pdfMake.vfs.hasOwnProperty("gbsn00lp.ttf")? |
|||
(U.defaultStyle.font="gbsn00lp",d.extend(!0,pdfMake.fonts,{gbsn00lp:{normal:"gbsn00lp.ttf",bold:"gbsn00lp.ttf",italics:"gbsn00lp.ttf",bolditalics:"gbsn00lp.ttf"}})):pdfMake.vfs.hasOwnProperty("ZCOOLXiaoWei-Regular.ttf")&&(U.defaultStyle.font="ZCOOLXiaoWei",d.extend(!0,pdfMake.fonts,{ZCOOLXiaoWei:{normal:"ZCOOLXiaoWei-Regular.ttf",bold:"ZCOOLXiaoWei-Regular.ttf",italics:"ZCOOLXiaoWei-Regular.ttf",bolditalics:"ZCOOLXiaoWei-Regular.ttf"}})),d.extend(!0,pdfMake.fonts,a.pdfmake.fonts),pdfMake.createPdf(U).getBuffer(function(b){N(b, |
|||
a.fileName+".pdf","application/pdf","","",!1)}))}else if(!1===a.jspdf.autotable){k={dim:{w:ha(d(B).first().get(0),"width","mm"),h:ha(d(B).first().get(0),"height","mm")},pagesplit:!1};var Ha=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);Ha.addHTML(d(B).first(),a.jspdf.margins.left,a.jspdf.margins.top,k,function(){va(Ha,!1)})}else{var g=a.jspdf.autotable.tableExport;if("string"===typeof a.jspdf.format&&"bestfit"===a.jspdf.format.toLowerCase()){var ja="",da="",Ia=0;d(B).each(function(){if(I(d(this))){var a= |
|||
ha(d(this).get(0),"width","pt");if(a>Ia){a>O.a0[0]&&(ja="a0",da="l");for(var c in O)O.hasOwnProperty(c)&&O[c][1]>a&&(ja=c,da="l",O[c][0]>a&&(da="p"));Ia=a}}});a.jspdf.format=""===ja?"a4":ja;a.jspdf.orientation=""===da?"w":da}if(null==g.doc&&(g.doc=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format),g.wScaleFactor=1,g.hScaleFactor=1,"function"===typeof a.jspdf.onDocCreated))a.jspdf.onDocCreated(g.doc);!0===g.outputImages&&(g.images={});"undefined"!==typeof g.images&&(d(B).filter(function(){return I(d(this))}).each(function(){var b= |
|||
0;G=[];!1===a.exportHiddenCells&&(K=d(this).find("tr, th, td").filter(":hidden"),V=0<K.length);r=y(d(this));w=C(d(this));d(w).each(function(){E(this,"td,th",r.length+b,r.length+w.length,function(a){xa(a,d(a).children(),g)});b++})}),r=[],w=[]);Ka(g,function(){d(B).filter(function(){return I(d(this))}).each(function(){var b;p=0;G=[];!1===a.exportHiddenCells&&(K=d(this).find("tr, th, td").filter(":hidden"),V=0<K.length);S=R(this);g.columns=[];g.rows=[];g.teCells={};if("function"===typeof g.onTable&& |
|||
!1===g.onTable(d(this),a))return!0;a.jspdf.autotable.tableExport=null;var c=d.extend(!0,{},a.jspdf.autotable);a.jspdf.autotable.tableExport=g;c.margin={};d.extend(!0,c.margin,a.jspdf.margins);c.tableExport=g;"function"!==typeof c.beforePageContent&&(c.beforePageContent=function(a){if(1===a.pageCount){var b=a.table.rows.concat(a.table.headerRow);d.each(b,function(){0<this.height&&(this.height+=(2-1.15)/2*this.styles.fontSize,a.table.height+=(2-1.15)/2*this.styles.fontSize)})}});"function"!==typeof c.createdHeaderCell&& |
|||
(c.createdHeaderCell=function(a,b){a.styles=d.extend({},b.row.styles);if("undefined"!==typeof g.columns[b.column.dataKey]){var e=g.columns[b.column.dataKey];if("undefined"!==typeof e.rect){a.contentWidth=e.rect.width;if("undefined"===typeof g.heightRatio||0===g.heightRatio){var f=b.row.raw[b.column.dataKey].rowspan?b.row.raw[b.column.dataKey].rect.height/b.row.raw[b.column.dataKey].rowspan:b.row.raw[b.column.dataKey].rect.height;g.heightRatio=a.styles.rowHeight/f}f=b.row.raw[b.column.dataKey].rect.height* |
|||
g.heightRatio;f>a.styles.rowHeight&&(a.styles.rowHeight=f)}a.styles.halign="inherit"===c.headerStyles.halign?"center":c.headerStyles.halign;a.styles.valign=c.headerStyles.valign;"undefined"!==typeof e.style&&!0!==e.style.hidden&&("inherit"===c.headerStyles.halign&&(a.styles.halign=e.style.align),"inherit"===c.styles.fillColor&&(a.styles.fillColor=e.style.bcolor),"inherit"===c.styles.textColor&&(a.styles.textColor=e.style.color),"inherit"===c.styles.fontStyle&&(a.styles.fontStyle=e.style.fstyle))}}); |
|||
"function"!==typeof c.createdCell&&(c.createdCell=function(a,b){b=g.teCells[b.row.index+":"+b.column.dataKey];a.styles.halign="inherit"===c.styles.halign?"center":c.styles.halign;a.styles.valign=c.styles.valign;"undefined"!==typeof b&&"undefined"!==typeof b.style&&!0!==b.style.hidden&&("inherit"===c.styles.halign&&(a.styles.halign=b.style.align),"inherit"===c.styles.fillColor&&(a.styles.fillColor=b.style.bcolor),"inherit"===c.styles.textColor&&(a.styles.textColor=b.style.color),"inherit"===c.styles.fontStyle&& |
|||
(a.styles.fontStyle=b.style.fstyle))});"function"!==typeof c.drawHeaderCell&&(c.drawHeaderCell=function(a,b){var c=g.columns[b.column.dataKey];return(!0!==c.style.hasOwnProperty("hidden")||!0!==c.style.hidden)&&0<=c.rowIndex?wa(a,b,c):!1});"function"!==typeof c.drawCell&&(c.drawCell=function(a,b){var c=g.teCells[b.row.index+":"+b.column.dataKey];if(!0!==("undefined"!==typeof c&&c.isCanvas))wa(a,b,c)&&(g.doc.rect(a.x,a.y,a.width,a.height,a.styles.fillStyle),"undefined"===typeof c||"undefined"!==typeof c.hasUserDefText&& |
|||
!0===c.hasUserDefText||"undefined"===typeof c.elements||!c.elements.length?Aa(a,{},g):(b=a.height/c.rect.height,b>g.hScaleFactor&&(g.hScaleFactor=b),g.wScaleFactor=a.width/c.rect.width,b=a.textPos.y,za(a,c.elements,g),a.textPos.y=b,Aa(a,c.elements,g)));else{c=c.elements[0];var e=d(c).attr("data-tableexport-canvas"),f=c.getBoundingClientRect();a.width=f.width*g.wScaleFactor;a.height=f.height*g.hScaleFactor;b.row.height=a.height;ua(a,c,e,g)}return!1});g.headerrows=[];r=y(d(this));d(r).each(function(){b= |
|||
0;g.headerrows[p]=[];E(this,"th,td",p,r.length,function(a,c,d){var e=Ca(a);e.title=D(a,c,d);e.key=b++;e.rowIndex=p;g.headerrows[p].push(e)});p++});if(0<p)for(var e=p-1;0<=e;)d.each(g.headerrows[e],function(){var a=this;0<e&&null===this.rect&&(a=g.headerrows[e-1][this.key]);null!==a&&0<=a.rowIndex&&(!0!==a.style.hasOwnProperty("hidden")||!0!==a.style.hidden)&&g.columns.push(a)}),e=0<g.columns.length?-1:e-1;var k=0;w=[];w=C(d(this));d(w).each(function(){var a=[];b=0;E(this,"td,th",p,r.length+w.length, |
|||
function(c,e,f){if("undefined"===typeof g.columns[b]){var h={title:"",key:b,style:{hidden:!0}};g.columns.push(h)}a.push(D(c,e,f));"undefined"!==typeof c&&null!==c?(h=Ca(c),h.isCanvas=c.hasAttribute("data-tableexport-canvas"),h.elements=h.isCanvas?d(c):d(c).children(),"undefined"!==typeof d(c).data("teUserDefText")&&(h.hasUserDefText=!0)):(h=d.extend(!0,{},g.teCells[k+":"+(b-1)]),h.colspan=-1);g.teCells[k+":"+b++]=h});a.length&&(g.rows.push(a),k++);p++});if("function"===typeof g.onBeforeAutotable)g.onBeforeAutotable(d(this), |
|||
g.columns,g.rows,c);g.doc.autoTable(g.columns,g.rows,c);if("function"===typeof g.onAfterAutotable)g.onAfterAutotable(d(this),c);a.jspdf.autotable.startY=g.doc.autoTableEndPosY()+c.margin.top});va(g.doc,"undefined"!==typeof g.images&&!1===jQuery.isEmptyObject(g.images));"undefined"!==typeof g.headerrows&&(g.headerrows.length=0);"undefined"!==typeof g.columns&&(g.columns.length=0);"undefined"!==typeof g.rows&&(g.rows.length=0);delete g.doc;g.doc=null})}if("function"===typeof a.onTableExportEnd)a.onTableExportEnd(); |
|||
return this}})(jQuery); |
@ -0,0 +1,123 @@ |
|||
/** |
|||
* @author: Dennis Hernández |
|||
* @update zhixin wen <wenzhixin2010@gmail.com> |
|||
*/ |
|||
|
|||
const debounce = (func, wait) => { |
|||
let timeout = 0 |
|||
|
|||
return (...args) => { |
|||
const later = () => { |
|||
timeout = 0 |
|||
func(...args) |
|||
} |
|||
|
|||
clearTimeout(timeout) |
|||
timeout = setTimeout(later, wait) |
|||
} |
|||
} |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
mobileResponsive: false, |
|||
minWidth: 562, |
|||
minHeight: undefined, |
|||
heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar
|
|||
checkOnInit: true, |
|||
columnsHidden: [] |
|||
}) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
init (...args) { |
|||
super.init(...args) |
|||
|
|||
if (!this.options.mobileResponsive || !this.options.minWidth) { |
|||
return |
|||
} |
|||
|
|||
if (this.options.minWidth < 100 && this.options.resizable) { |
|||
console.warn('The minWidth when the resizable extension is active should be greater or equal than 100') |
|||
this.options.minWidth = 100 |
|||
} |
|||
|
|||
let old = { |
|||
width: $(window).width(), |
|||
height: $(window).height() |
|||
} |
|||
|
|||
$(window).on('resize orientationchange', debounce(() => { |
|||
// reset view if height has only changed by at least the threshold.
|
|||
const width = $(window).width() |
|||
const height = $(window).height() |
|||
const $activeElement = $(document.activeElement) |
|||
|
|||
if ($activeElement.length && ['INPUT', 'SELECT', 'TEXTAREA'].includes($activeElement.prop('nodeName'))) { |
|||
return |
|||
} |
|||
|
|||
if ( |
|||
Math.abs(old.height - height) > this.options.heightThreshold || |
|||
old.width !== width |
|||
) { |
|||
this.changeView(width, height) |
|||
old = { |
|||
width, |
|||
height |
|||
} |
|||
} |
|||
}, 200)) |
|||
|
|||
if (this.options.checkOnInit) { |
|||
const width = $(window).width() |
|||
const height = $(window).height() |
|||
|
|||
this.changeView(width, height) |
|||
old = { |
|||
width, |
|||
height |
|||
} |
|||
} |
|||
} |
|||
|
|||
conditionCardView () { |
|||
this.changeTableView(false) |
|||
this.showHideColumns(false) |
|||
} |
|||
|
|||
conditionFullView () { |
|||
this.changeTableView(true) |
|||
this.showHideColumns(true) |
|||
} |
|||
|
|||
changeTableView (cardViewState) { |
|||
this.options.cardView = cardViewState |
|||
this.toggleView() |
|||
} |
|||
|
|||
showHideColumns (checked) { |
|||
if (this.options.columnsHidden.length > 0) { |
|||
this.columns.forEach(column => { |
|||
if (this.options.columnsHidden.includes(column.field)) { |
|||
if (column.visible !== checked) { |
|||
this._toggleColumn(this.fieldsColumnsIndex[column.field], checked, true) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
|
|||
changeView (width, height) { |
|||
if (this.options.minHeight) { |
|||
if (width <= this.options.minWidth && height <= this.options.minHeight) { |
|||
this.conditionCardView() |
|||
} else if (width > this.options.minWidth && height > this.options.minHeight) { |
|||
this.conditionFullView() |
|||
} |
|||
} else if (width <= this.options.minWidth) { |
|||
this.conditionCardView() |
|||
} else if (width > this.options.minWidth) { |
|||
this.conditionFullView() |
|||
} |
|||
|
|||
this.resetView() |
|||
} |
|||
} |
@ -0,0 +1,312 @@ |
|||
/** |
|||
* @update zhixin wen <wenzhixin2010@gmail.com> |
|||
*/ |
|||
|
|||
var Utils = $.fn.bootstrapTable.utils |
|||
|
|||
function printPageBuilderDefault (table, styles) { |
|||
return ` |
|||
<html> |
|||
<head> |
|||
${styles} |
|||
<style type="text/css" media="print"> |
|||
@page { |
|||
size: auto; |
|||
margin: 25px 0 25px 0; |
|||
} |
|||
</style> |
|||
<style type="text/css" media="all"> |
|||
table { |
|||
border-collapse: collapse; |
|||
font-size: 12px; |
|||
} |
|||
table, th, td { |
|||
border: 1px solid grey; |
|||
} |
|||
th, td { |
|||
text-align: center; |
|||
vertical-align: middle; |
|||
} |
|||
p { |
|||
font-weight: bold; |
|||
margin-left:20px; |
|||
} |
|||
table { |
|||
width: 94%; |
|||
margin-left: 3%; |
|||
margin-right: 3%; |
|||
} |
|||
div.bs-table-print { |
|||
text-align: center; |
|||
} |
|||
</style> |
|||
</head> |
|||
<title>Print Table</title> |
|||
<body> |
|||
<p>Printed on: ${new Date} </p> |
|||
<div class="bs-table-print">${table}</div> |
|||
</body> |
|||
</html> |
|||
` |
|||
} |
|||
|
|||
Object.assign($.fn.bootstrapTable.locales, { |
|||
formatPrint () { |
|||
return 'Print' |
|||
} |
|||
}) |
|||
Object.assign($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales) |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
showPrint: false, |
|||
printAsFilteredAndSortedOnUI: true, |
|||
printSortColumn: undefined, |
|||
printSortOrder: 'asc', |
|||
printStyles: [], |
|||
printPageBuilder (table, styles) { |
|||
return printPageBuilderDefault(table, styles) |
|||
} |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.columnDefaults, { |
|||
printFilter: undefined, |
|||
printIgnore: false, |
|||
printFormatter: undefined |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults.icons, { |
|||
print: { |
|||
bootstrap3: 'glyphicon-print icon-share', |
|||
bootstrap5: 'bi-printer', |
|||
'bootstrap-table': 'icon-printer' |
|||
}[$.fn.bootstrapTable.theme] || 'fa-print' |
|||
}) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
init (...args) { |
|||
super.init(...args) |
|||
|
|||
if (!this.options.showPrint) { |
|||
return |
|||
} |
|||
|
|||
this.mergedCells = [] |
|||
} |
|||
|
|||
initToolbar (...args) { |
|||
this.showToolbar = this.showToolbar || this.options.showPrint |
|||
|
|||
if (this.options.showPrint) { |
|||
this.buttons = Object.assign(this.buttons, { |
|||
print: { |
|||
text: this.options.formatPrint(), |
|||
icon: this.options.icons.print, |
|||
event: () => { |
|||
this.doPrint(this.options.printAsFilteredAndSortedOnUI ? this.getData() : this.options.data.slice(0)) |
|||
}, |
|||
attributes: { |
|||
'aria-label': this.options.formatPrint(), |
|||
title: this.options.formatPrint() |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
|
|||
super.initToolbar(...args) |
|||
} |
|||
|
|||
mergeCells (options) { |
|||
super.mergeCells(options) |
|||
|
|||
if (!this.options.showPrint) { |
|||
return |
|||
} |
|||
|
|||
let col = this.getVisibleFields().indexOf(options.field) |
|||
|
|||
if (Utils.hasDetailViewIcon(this.options)) { |
|||
col += 1 |
|||
} |
|||
|
|||
this.mergedCells.push({ |
|||
row: options.index, |
|||
col, |
|||
rowspan: options.rowspan || 1, |
|||
colspan: options.colspan || 1 |
|||
}) |
|||
} |
|||
|
|||
doPrint (data) { |
|||
const canPrint = column => { |
|||
return !column.printIgnore && column.visible |
|||
} |
|||
|
|||
const formatValue = (row, i, column) => { |
|||
const value_ = Utils.getItemField(row, column.field, this.options.escape, column.escape) |
|||
const value = Utils.calculateObjectValue(column, |
|||
column.printFormatter || column.formatter, |
|||
[value_, row, i], value_) |
|||
|
|||
return typeof value === 'undefined' || value === null ? |
|||
this.options.undefinedText : value |
|||
} |
|||
|
|||
const buildTable = (data, columnsArray) => { |
|||
const dir = this.$el.attr('dir') || 'ltr' |
|||
const html = [`<table dir="${dir}"><thead>`] |
|||
|
|||
for (const columns of columnsArray) { |
|||
html.push('<tr>') |
|||
for (let h = 0; h < columns.length; h++) { |
|||
if (canPrint(columns[h])) { |
|||
html.push( |
|||
`<th
|
|||
${Utils.sprintf(' rowspan="%s"', columns[h].rowspan)} |
|||
${Utils.sprintf(' colspan="%s"', columns[h].colspan)} |
|||
>${columns[h].title}</th>`) |
|||
} |
|||
} |
|||
html.push('</tr>') |
|||
} |
|||
|
|||
html.push('</thead><tbody>') |
|||
|
|||
const notRender = [] |
|||
|
|||
if (this.mergedCells) { |
|||
for (let mc = 0; mc < this.mergedCells.length; mc++) { |
|||
const currentMergedCell = this.mergedCells[mc] |
|||
|
|||
for (let rs = 0; rs < currentMergedCell.rowspan; rs++) { |
|||
const row = currentMergedCell.row + rs |
|||
|
|||
for (let cs = 0; cs < currentMergedCell.colspan; cs++) { |
|||
const col = currentMergedCell.col + cs |
|||
|
|||
notRender.push(`${row},${col}`) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
for (let i = 0; i < data.length; i++) { |
|||
html.push('<tr>') |
|||
|
|||
const columns = columnsArray.flat(1) |
|||
|
|||
columns.sort((c1, c2) => { |
|||
return c1.colspanIndex - c2.colspanIndex |
|||
}) |
|||
|
|||
for (let j = 0; j < columns.length; j++) { |
|||
if (columns[j].colspanGroup > 0) continue |
|||
|
|||
let rowspan = 0 |
|||
let colspan = 0 |
|||
|
|||
if (this.mergedCells) { |
|||
for (let mc = 0; mc < this.mergedCells.length; mc++) { |
|||
const currentMergedCell = this.mergedCells[mc] |
|||
|
|||
if (currentMergedCell.col === j && currentMergedCell.row === i) { |
|||
rowspan = currentMergedCell.rowspan |
|||
colspan = currentMergedCell.colspan |
|||
} |
|||
} |
|||
} |
|||
|
|||
if ( |
|||
canPrint(columns[j]) && |
|||
( |
|||
!notRender.includes(`${i},${j}`) || |
|||
rowspan > 0 && colspan > 0 |
|||
) |
|||
) { |
|||
if (rowspan > 0 && colspan > 0) { |
|||
html.push(`<td ${Utils.sprintf(' rowspan="%s"', rowspan)} ${Utils.sprintf(' colspan="%s"', colspan)}>`, formatValue(data[i], i, columns[j]), '</td>') |
|||
} else { |
|||
html.push('<td>', formatValue(data[i], i, columns[j]), '</td>') |
|||
} |
|||
} |
|||
} |
|||
|
|||
html.push('</tr>') |
|||
} |
|||
|
|||
html.push('</tbody>') |
|||
if (this.options.showFooter) { |
|||
html.push('<footer><tr>') |
|||
|
|||
for (const columns of columnsArray) { |
|||
for (let h = 0; h < columns.length; h++) { |
|||
if (canPrint(columns)) { |
|||
const footerData = Utils.trToData(columns, this.$el.find('>tfoot>tr')) |
|||
const footerValue = Utils.calculateObjectValue(columns[h], columns[h].footerFormatter, [data], footerData[0] && footerData[0][columns[h].field] || '') |
|||
|
|||
html.push(`<th>${footerValue}</th>`) |
|||
} |
|||
} |
|||
} |
|||
|
|||
html.push('</tr></footer>') |
|||
} |
|||
html.push('</table>') |
|||
return html.join('') |
|||
} |
|||
|
|||
const sortRows = (data, colName, sortOrder) => { |
|||
if (!colName) { |
|||
return data |
|||
} |
|||
let reverse = sortOrder !== 'asc' |
|||
|
|||
reverse = -(+reverse || -1) |
|||
return data.sort((a, b) => reverse * a[colName].localeCompare(b[colName])) |
|||
} |
|||
|
|||
const filterRow = (row, filters) => { |
|||
for (let index = 0; index < filters.length; ++index) { |
|||
if (row[filters[index].colName] !== filters[index].value) { |
|||
return false |
|||
} |
|||
} |
|||
return true |
|||
} |
|||
|
|||
const filterRows = (data, filters) => data.filter(row => filterRow(row, filters)) |
|||
const getColumnFilters = columns => !columns || !columns[0] ? [] : columns[0].filter(col => col.printFilter).map(col => ({ |
|||
colName: col.field, |
|||
value: col.printFilter |
|||
})) |
|||
|
|||
data = filterRows(data, getColumnFilters(this.options.columns)) |
|||
data = sortRows(data, this.options.printSortColumn, this.options.printSortOrder) |
|||
const table = buildTable(data, this.options.columns) |
|||
const newWin = window.open('') |
|||
const printStyles = typeof this.options.printStyles === 'string' ? |
|||
this.options.printStyles.replace(/\[|\]| /g, '').toLowerCase().split(',') : |
|||
this.options.printStyles |
|||
const styles = printStyles.map(it => |
|||
`<link rel="stylesheet" href="${it}" />`).join('') |
|||
|
|||
const calculatedPrintPage = Utils.calculateObjectValue(this, this.options.printPageBuilder, |
|||
[table, styles], printPageBuilderDefault(table, styles)) |
|||
const startPrint = () => { |
|||
newWin.focus() |
|||
newWin.print() |
|||
newWin.close() |
|||
} |
|||
|
|||
newWin.document.write(calculatedPrintPage) |
|||
newWin.document.close() |
|||
|
|||
if (printStyles.length) { |
|||
const links = document.getElementsByTagName('link') |
|||
const lastLink = links[links.length - 1] |
|||
|
|||
lastLink.onload = startPrint |
|||
} else { |
|||
startPrint() |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,212 @@ |
|||
/** |
|||
* @author: Dennis Hernández |
|||
* @update: https://github.com/wenzhixin
|
|||
* @version: v1.2.0 |
|||
*/ |
|||
|
|||
$.akottr.dragtable.prototype._restoreState = function (persistObj) { |
|||
let i = 0 |
|||
|
|||
for (const [field, value] of Object.entries(persistObj)) { |
|||
const $th = this.originalTable.el.find(`th[data-field="${field}"]`) |
|||
|
|||
if (!$th.length) { |
|||
i++ |
|||
continue |
|||
} |
|||
|
|||
this.originalTable.startIndex = $th.prevAll().length + 1 |
|||
this.originalTable.endIndex = parseInt(value, 10) + 1 - i |
|||
this._bubbleCols() |
|||
} |
|||
} |
|||
|
|||
// From MDN site, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
|
|||
const filterFn = () => { |
|||
if (!Array.prototype.filter) { |
|||
Array.prototype.filter = function (fun/* , thisArg*/) { |
|||
if (this === undefined || this === null) { |
|||
throw new TypeError() |
|||
} |
|||
|
|||
const t = Object(this) |
|||
const len = t.length >>> 0 |
|||
|
|||
if (typeof fun !== 'function') { |
|||
throw new TypeError() |
|||
} |
|||
|
|||
const res = [] |
|||
const thisArg = arguments.length >= 2 ? arguments[1] : undefined |
|||
|
|||
for (let i = 0; i < len; i++) { |
|||
if (i in t) { |
|||
const val = t[i] |
|||
|
|||
// NOTE: Technically this should Object.defineProperty at
|
|||
// the next index, as push can be affected by
|
|||
// properties on Object.prototype and Array.prototype.
|
|||
// But this method's new, and collisions should be
|
|||
// rare, so use the more-compatible alternative.
|
|||
if (fun.call(thisArg, val, i, t)) { |
|||
res.push(val) |
|||
} |
|||
} |
|||
} |
|||
|
|||
return res |
|||
} |
|||
} |
|||
} |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
reorderableColumns: false, |
|||
maxMovingRows: 10, |
|||
// eslint-disable-next-line no-unused-vars
|
|||
onReorderColumn (headerFields) { |
|||
return false |
|||
}, |
|||
dragaccept: null |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.events, { |
|||
'reorder-column.bs.table': 'onReorderColumn' |
|||
}) |
|||
|
|||
$.fn.bootstrapTable.methods.push('orderColumns') |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
initHeader (...args) { |
|||
super.initHeader(...args) |
|||
|
|||
if (!this.options.reorderableColumns) { |
|||
return |
|||
} |
|||
|
|||
this.makeColumnsReorderable() |
|||
} |
|||
|
|||
_toggleColumn (...args) { |
|||
super._toggleColumn(...args) |
|||
|
|||
if (!this.options.reorderableColumns) { |
|||
return |
|||
} |
|||
|
|||
this.makeColumnsReorderable() |
|||
} |
|||
|
|||
toggleView (...args) { |
|||
super.toggleView(...args) |
|||
|
|||
if (!this.options.reorderableColumns) { |
|||
return |
|||
} |
|||
|
|||
if (this.options.cardView) { |
|||
return |
|||
} |
|||
|
|||
this.makeColumnsReorderable() |
|||
} |
|||
|
|||
resetView (...args) { |
|||
super.resetView(...args) |
|||
|
|||
if (!this.options.reorderableColumns) { |
|||
return |
|||
} |
|||
|
|||
this.makeColumnsReorderable() |
|||
} |
|||
|
|||
makeColumnsReorderable (order = null) { |
|||
try { |
|||
$(this.$el).dragtable('destroy') |
|||
} catch (e) { |
|||
// do nothing
|
|||
} |
|||
$(this.$el).dragtable({ |
|||
maxMovingRows: this.options.maxMovingRows, |
|||
dragaccept: this.options.dragaccept, |
|||
clickDelay: 200, |
|||
dragHandle: '.th-inner', |
|||
restoreState: order ? order : this.columnsSortOrder, |
|||
beforeStop: table => { |
|||
const sortOrder = {} |
|||
|
|||
table.el.find('th').each((i, el) => { |
|||
sortOrder[$(el).data('field')] = i |
|||
}) |
|||
|
|||
this.columnsSortOrder = sortOrder |
|||
if (this.options.cookie) { |
|||
this.persistReorderColumnsState(this) |
|||
} |
|||
|
|||
const ths = [] |
|||
const formatters = [] |
|||
const columns = [] |
|||
let columnsHidden = [] |
|||
let columnIndex = -1 |
|||
const optionsColumns = [] |
|||
|
|||
this.$header.find('th:not(.detail)').each((i, el) => { |
|||
ths.push($(el).data('field')) |
|||
formatters.push($(el).data('formatter')) |
|||
}) |
|||
|
|||
// Exist columns not shown
|
|||
if (ths.length < this.columns.length) { |
|||
columnsHidden = this.columns.filter(column => !column.visible) |
|||
for (let i = 0; i < columnsHidden.length; i++) { |
|||
ths.push(columnsHidden[i].field) |
|||
formatters.push(columnsHidden[i].formatter) |
|||
} |
|||
} |
|||
|
|||
for (let i = 0; i < ths.length; i++) { |
|||
columnIndex = this.fieldsColumnsIndex[ths[i]] |
|||
if (columnIndex !== -1) { |
|||
this.fieldsColumnsIndex[ths[i]] = i |
|||
this.columns[columnIndex].fieldIndex = i |
|||
columns.push(this.columns[columnIndex]) |
|||
} |
|||
} |
|||
|
|||
this.columns = columns |
|||
|
|||
filterFn() // Support <IE9
|
|||
$.each(this.columns, (i, column) => { |
|||
let found = false |
|||
const field = column.field |
|||
|
|||
this.options.columns[0].filter(item => { |
|||
if (!found && item['field'] === field) { |
|||
optionsColumns.push(item) |
|||
found = true |
|||
return false |
|||
} |
|||
return true |
|||
}) |
|||
}) |
|||
|
|||
this.options.columns[0] = optionsColumns |
|||
|
|||
this.header.fields = ths |
|||
this.header.formatters = formatters |
|||
this.initHeader() |
|||
this.initToolbar() |
|||
this.initSearchText() |
|||
this.initBody() |
|||
this.resetView() |
|||
this.trigger('reorder-column', ths) |
|||
} |
|||
}) |
|||
} |
|||
|
|||
orderColumns (order) { |
|||
this.columnsSortOrder = order |
|||
this.makeColumnsReorderable() |
|||
} |
|||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,145 @@ |
|||
/** |
|||
* @author: Dennis Hernández |
|||
* @update zhixin wen <wenzhixin2010@gmail.com> |
|||
*/ |
|||
|
|||
const rowAttr = (row, index) => ({ |
|||
id: `customId_${index}` |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
reorderableRows: false, |
|||
onDragStyle: null, |
|||
onDropStyle: null, |
|||
onDragClass: 'reorder-rows-on-drag-class', |
|||
dragHandle: '>tbody>tr>td:not(.bs-checkbox)', |
|||
useRowAttrFunc: false, |
|||
// eslint-disable-next-line no-unused-vars
|
|||
onReorderRowsDrag (row) { |
|||
return false |
|||
}, |
|||
// eslint-disable-next-line no-unused-vars
|
|||
onReorderRowsDrop (row) { |
|||
return false |
|||
}, |
|||
// eslint-disable-next-line no-unused-vars
|
|||
onReorderRow (newData) { |
|||
return false |
|||
}, |
|||
onDragStop () {}, |
|||
onAllowDrop () { |
|||
return true |
|||
} |
|||
}) |
|||
|
|||
Object.assign($.fn.bootstrapTable.events, { |
|||
'reorder-row.bs.table': 'onReorderRow' |
|||
}) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
init (...args) { |
|||
if (!this.options.reorderableRows) { |
|||
super.init(...args) |
|||
return |
|||
} |
|||
|
|||
if (this.options.useRowAttrFunc) { |
|||
this.options.rowAttributes = rowAttr |
|||
} |
|||
|
|||
const onPostBody = this.options.onPostBody |
|||
|
|||
this.options.onPostBody = () => { |
|||
setTimeout(() => { |
|||
this.makeRowsReorderable() |
|||
onPostBody.call(this.options, this.options.data) |
|||
}, 1) |
|||
} |
|||
|
|||
super.init(...args) |
|||
} |
|||
|
|||
makeRowsReorderable () { |
|||
this.$el.tableDnD({ |
|||
onDragStyle: this.options.onDragStyle, |
|||
onDropStyle: this.options.onDropStyle, |
|||
onDragClass: this.options.onDragClass, |
|||
onAllowDrop: (hoveredRow, draggedRow) => this.onAllowDrop(hoveredRow, draggedRow), |
|||
onDragStop: (table, draggedRow) => this.onDragStop(table, draggedRow), |
|||
onDragStart: (table, droppedRow) => this.onDropStart(table, droppedRow), |
|||
onDrop: (table, droppedRow) => this.onDrop(table, droppedRow), |
|||
dragHandle: this.options.dragHandle |
|||
}) |
|||
} |
|||
|
|||
onDropStart (table, draggingTd) { |
|||
this.$draggingTd = $(draggingTd).css('cursor', 'move') |
|||
this.draggingIndex = $(this.$draggingTd.parent()).data('index') |
|||
// Call the user defined function
|
|||
this.options.onReorderRowsDrag(this.data[this.draggingIndex]) |
|||
} |
|||
|
|||
onDragStop (table, draggedRow) { |
|||
const rowIndexDraggedRow = $(draggedRow).data('index') |
|||
const draggedRowItem = this.data[rowIndexDraggedRow] |
|||
|
|||
this.options.onDragStop(table, draggedRowItem, draggedRow) |
|||
} |
|||
|
|||
onAllowDrop (hoveredRow, draggedRow) { |
|||
const rowIndexDraggedRow = $(draggedRow).data('index') |
|||
const rowIndexHoveredRow = $(hoveredRow).data('index') |
|||
const draggedRowItem = this.data[rowIndexDraggedRow] |
|||
const hoveredRowItem = this.data[rowIndexHoveredRow] |
|||
|
|||
return this.options.onAllowDrop(hoveredRowItem, draggedRowItem, hoveredRow, draggedRow) |
|||
} |
|||
|
|||
onDrop (table) { |
|||
this.$draggingTd.css('cursor', '') |
|||
const pageNum = this.options.pageNumber |
|||
const pageSize = this.options.pageSize |
|||
const newData = [] |
|||
|
|||
for (let i = 0; i < table.tBodies[0].rows.length; i++) { |
|||
const $tr = $(table.tBodies[0].rows[i]) |
|||
|
|||
newData.push(this.data[$tr.data('index')]) |
|||
$tr.data('index', i) |
|||
} |
|||
|
|||
const draggingRow = this.data[this.draggingIndex] |
|||
const droppedIndex = newData.indexOf(this.data[this.draggingIndex]) |
|||
const droppedRow = this.data[droppedIndex] |
|||
const index = (pageNum - 1) * pageSize + this.options.data.indexOf(this.data[droppedIndex]) |
|||
|
|||
this.options.data.splice(this.options.data.indexOf(draggingRow), 1) |
|||
this.options.data.splice(index, 0, draggingRow) |
|||
|
|||
this.initSearch() |
|||
|
|||
if (this.options.sidePagination === 'server') { |
|||
this.data = [...this.options.data] |
|||
} |
|||
|
|||
// Call the user defined function
|
|||
this.options.onReorderRowsDrop(droppedRow) |
|||
|
|||
// Call the event reorder-row
|
|||
this.trigger('reorder-row', newData, draggingRow, droppedRow) |
|||
} |
|||
|
|||
initSearch () { |
|||
this.ignoreInitSort = true |
|||
super.initSearch() |
|||
} |
|||
|
|||
initSort () { |
|||
if (this.ignoreInitSort) { |
|||
this.ignoreInitSort = false |
|||
return |
|||
} |
|||
|
|||
super.initSort() |
|||
} |
|||
} |
@ -0,0 +1,603 @@ |
|||
/** |
|||
* TableDnD plug-in for JQuery, allows you to drag and drop table rows |
|||
* You can set up various options to control how the system will work |
|||
* Copyright (c) Denis Howlett <denish@isocra.com> |
|||
* License: MIT. |
|||
* See https://github.com/isocra/TableDnD
|
|||
*/ |
|||
!function ($, window, document, undefined) { |
|||
|
|||
var startEvent = 'touchstart mousedown', |
|||
moveEvent = 'touchmove mousemove', |
|||
endEvent = 'touchend mouseup'; |
|||
|
|||
$(document).ready(function () { |
|||
function parseStyle(css) { |
|||
var objMap = {}, |
|||
parts = css.match(/([^;:]+)/g) || []; |
|||
while (parts.length) |
|||
objMap[parts.shift()] = parts.shift().trim(); |
|||
|
|||
return objMap; |
|||
} |
|||
$('table').each(function () { |
|||
if ($(this).data('table') === 'dnd') { |
|||
|
|||
$(this).tableDnD({ |
|||
onDragStyle: $(this).data('ondragstyle') && parseStyle($(this).data('ondragstyle')) || null, |
|||
onDropStyle: $(this).data('ondropstyle') && parseStyle($(this).data('ondropstyle')) || null, |
|||
onDragClass: $(this).data('ondragclass') === undefined && "tDnD_whileDrag" || $(this).data('ondragclass'), |
|||
onDrop: $(this).data('ondrop') && new Function('table', 'row', $(this).data('ondrop')), // 'return eval("'+$(this).data('ondrop')+'");') || null,
|
|||
onDragStart: $(this).data('ondragstart') && new Function('table', 'row' ,$(this).data('ondragstart')), // 'return eval("'+$(this).data('ondragstart')+'");') || null,
|
|||
onDragStop: $(this).data('ondragstop') && new Function('table', 'row' ,$(this).data('ondragstop')), |
|||
scrollAmount: $(this).data('scrollamount') || 5, |
|||
sensitivity: $(this).data('sensitivity') || 10, |
|||
hierarchyLevel: $(this).data('hierarchylevel') || 0, |
|||
indentArtifact: $(this).data('indentartifact') || '<div class="indent"> </div>', |
|||
autoWidthAdjust: $(this).data('autowidthadjust') || true, |
|||
autoCleanRelations: $(this).data('autocleanrelations') || true, |
|||
jsonPretifySeparator: $(this).data('jsonpretifyseparator') || '\t', |
|||
serializeRegexp: $(this).data('serializeregexp') && new RegExp($(this).data('serializeregexp')) || /[^\-]*$/, |
|||
serializeParamName: $(this).data('serializeparamname') || false, |
|||
dragHandle: $(this).data('draghandle') || null |
|||
}); |
|||
} |
|||
|
|||
|
|||
}); |
|||
}); |
|||
|
|||
jQuery.tableDnD = { |
|||
/** Keep hold of the current table being dragged */ |
|||
currentTable: null, |
|||
/** Keep hold of the current drag object if any */ |
|||
dragObject: null, |
|||
/** The current mouse offset */ |
|||
mouseOffset: null, |
|||
/** Remember the old value of X and Y so that we don't do too much processing */ |
|||
oldX: 0, |
|||
oldY: 0, |
|||
|
|||
/** Actually build the structure */ |
|||
build: function(options) { |
|||
// Set up the defaults if any
|
|||
|
|||
this.each(function() { |
|||
// This is bound to each matching table, set up the defaults and override with user options
|
|||
this.tableDnDConfig = $.extend({ |
|||
onDragStyle: null, |
|||
onDropStyle: null, |
|||
// Add in the default class for whileDragging
|
|||
onDragClass: "tDnD_whileDrag", |
|||
onDrop: null, |
|||
onDragStart: null, |
|||
onDragStop: null, |
|||
scrollAmount: 5, |
|||
/** Sensitivity setting will throttle the trigger rate for movement detection */ |
|||
sensitivity: 10, |
|||
/** Hierarchy level to support parent child. 0 switches this functionality off */ |
|||
hierarchyLevel: 0, |
|||
/** The html artifact to prepend the first cell with as indentation */ |
|||
indentArtifact: '<div class="indent"> </div>', |
|||
/** Automatically adjust width of first cell */ |
|||
autoWidthAdjust: true, |
|||
/** Automatic clean-up to ensure relationship integrity */ |
|||
autoCleanRelations: true, |
|||
/** Specify a number (4) as number of spaces or any indent string for JSON.stringify */ |
|||
jsonPretifySeparator: '\t', |
|||
/** The regular expression to use to trim row IDs */ |
|||
serializeRegexp: /[^\-]*$/, |
|||
/** If you want to specify another parameter name instead of the table ID */ |
|||
serializeParamName: false, |
|||
/** If you give the name of a class here, then only Cells with this class will be draggable */ |
|||
dragHandle: null |
|||
}, options || {}); |
|||
|
|||
// Now make the rows draggable
|
|||
$.tableDnD.makeDraggable(this); |
|||
// Prepare hierarchy support
|
|||
this.tableDnDConfig.hierarchyLevel |
|||
&& $.tableDnD.makeIndented(this); |
|||
}); |
|||
|
|||
// Don't break the chain
|
|||
return this; |
|||
}, |
|||
makeIndented: function (table) { |
|||
var config = table.tableDnDConfig, |
|||
rows = table.rows, |
|||
firstCell = $(rows).first().find('td:first')[0], |
|||
indentLevel = 0, |
|||
cellWidth = 0, |
|||
longestCell, |
|||
tableStyle; |
|||
|
|||
if ($(table).hasClass('indtd')) |
|||
return null; |
|||
|
|||
tableStyle = $(table).addClass('indtd').attr('style'); |
|||
$(table).css({whiteSpace: "nowrap"}); |
|||
|
|||
for (var w = 0; w < rows.length; w++) { |
|||
if (cellWidth < $(rows[w]).find('td:first').text().length) { |
|||
cellWidth = $(rows[w]).find('td:first').text().length; |
|||
longestCell = w; |
|||
} |
|||
} |
|||
$(firstCell).css({width: 'auto'}); |
|||
for (w = 0; w < config.hierarchyLevel; w++) |
|||
$(rows[longestCell]).find('td:first').prepend(config.indentArtifact); |
|||
firstCell && $(firstCell).css({width: firstCell.offsetWidth}); |
|||
tableStyle && $(table).css(tableStyle); |
|||
|
|||
for (w = 0; w < config.hierarchyLevel; w++) |
|||
$(rows[longestCell]).find('td:first').children(':first').remove(); |
|||
|
|||
config.hierarchyLevel |
|||
&& $(rows).each(function () { |
|||
indentLevel = $(this).data('level') || 0; |
|||
indentLevel <= config.hierarchyLevel |
|||
&& $(this).data('level', indentLevel) |
|||
|| $(this).data('level', 0); |
|||
for (var i = 0; i < $(this).data('level'); i++) |
|||
$(this).find('td:first').prepend(config.indentArtifact); |
|||
}); |
|||
|
|||
return this; |
|||
}, |
|||
/** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */ |
|||
makeDraggable: function(table) { |
|||
var config = table.tableDnDConfig; |
|||
|
|||
config.dragHandle |
|||
// We only need to add the event to the specified cells
|
|||
&& $(config.dragHandle, table).each(function() { |
|||
if (! $(this).hasClass("nodrag")) { |
|||
// The cell is bound to "this"
|
|||
$(this).bind(startEvent, function(e) { |
|||
if (e.target.tagName === "TD" && event.target.className !== "nodrag") { |
|||
$.tableDnD.initialiseDrag($(this).parents('tr')[0], table, this, e, config); |
|||
return false; |
|||
} |
|||
return true; |
|||
}); |
|||
} |
|||
}) |
|||
// For backwards compatibility, we add the event to the whole row
|
|||
// get all the rows as a wrapped set
|
|||
|| $(table.rows).each(function() { |
|||
// Iterate through each row, the row is bound to "this"
|
|||
if (! $(this).hasClass("nodrag")) { |
|||
$(this).bind(startEvent, function(e) { |
|||
if (e.target.tagName === "TD" && event.target.className !== "nodrag") { |
|||
$.tableDnD.initialiseDrag(this, table, this, e, config); |
|||
return false; |
|||
} |
|||
}).css("cursor", "move"); // Store the tableDnD object
|
|||
} else { |
|||
$(this).css("cursor", ""); // Remove the cursor if we don't have the nodrag class
|
|||
} |
|||
}); |
|||
}, |
|||
currentOrder: function() { |
|||
var rows = this.currentTable.rows; |
|||
return $.map(rows, function (val) { |
|||
return ($(val).data('level') + val.id).replace(/\s/g, ''); |
|||
}).join(''); |
|||
}, |
|||
initialiseDrag: function(dragObject, table, target, e, config) { |
|||
this.dragObject = dragObject; |
|||
this.currentTable = table; |
|||
this.mouseOffset = this.getMouseOffset(target, e); |
|||
this.originalOrder = this.currentOrder(); |
|||
|
|||
// Now we need to capture the mouse up and mouse move event
|
|||
// We can use bind so that we don't interfere with other event handlers
|
|||
$(document) |
|||
.bind(moveEvent, this.mousemove) |
|||
.bind(endEvent, this.mouseup); |
|||
|
|||
// Call the onDragStart method if there is one
|
|||
config.onDragStart |
|||
&& config.onDragStart(table, target); |
|||
}, |
|||
updateTables: function() { |
|||
this.each(function() { |
|||
// this is now bound to each matching table
|
|||
if (this.tableDnDConfig) |
|||
$.tableDnD.makeDraggable(this); |
|||
}); |
|||
}, |
|||
/** Get the mouse coordinates from the event (allowing for browser differences) */ |
|||
mouseCoords: function(e) { |
|||
if (e.originalEvent.changedTouches) |
|||
return { |
|||
x: e.originalEvent.changedTouches[0].clientX, |
|||
y: e.originalEvent.changedTouches[0].clientY |
|||
}; |
|||
|
|||
if(e.pageX || e.pageY) |
|||
return { |
|||
x: e.pageX, |
|||
y: e.pageY |
|||
}; |
|||
|
|||
return { |
|||
x: e.clientX + document.body.scrollLeft - document.body.clientLeft, |
|||
y: e.clientY + document.body.scrollTop - document.body.clientTop |
|||
}; |
|||
}, |
|||
/** Given a target element and a mouse eent, get the mouse offset from that element. |
|||
To do this we need the element's position and the mouse position */ |
|||
getMouseOffset: function(target, e) { |
|||
var mousePos, |
|||
docPos; |
|||
|
|||
e = e || window.event; |
|||
|
|||
docPos = this.getPosition(target); |
|||
mousePos = this.mouseCoords(e); |
|||
|
|||
return { |
|||
x: mousePos.x - docPos.x, |
|||
y: mousePos.y - docPos.y |
|||
}; |
|||
}, |
|||
/** Get the position of an element by going up the DOM tree and adding up all the offsets */ |
|||
getPosition: function(element) { |
|||
var left = 0, |
|||
top = 0; |
|||
|
|||
// Safari fix -- thanks to Luis Chato for this!
|
|||
// Safari 2 doesn't correctly grab the offsetTop of a table row
|
|||
// this is detailed here:
|
|||
// http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
|
|||
// the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
|
|||
// note that firefox will return a text node as a first child, so designing a more thorough
|
|||
// solution may need to take that into account, for now this seems to work in firefox, safari, ie
|
|||
if (element.offsetHeight === 0) |
|||
element = element.firstChild; // a table cell
|
|||
|
|||
while (element.offsetParent) { |
|||
left += element.offsetLeft; |
|||
top += element.offsetTop; |
|||
element = element.offsetParent; |
|||
} |
|||
|
|||
left += element.offsetLeft; |
|||
top += element.offsetTop; |
|||
|
|||
return { |
|||
x: left, |
|||
y: top |
|||
}; |
|||
}, |
|||
autoScroll: function (mousePos) { |
|||
var config = this.currentTable.tableDnDConfig, |
|||
yOffset = window.pageYOffset, |
|||
windowHeight = window.innerHeight |
|||
? window.innerHeight |
|||
: document.documentElement.clientHeight |
|||
? document.documentElement.clientHeight |
|||
: document.body.clientHeight; |
|||
|
|||
// Windows version
|
|||
// yOffset=document.body.scrollTop;
|
|||
if (document.all) |
|||
if (typeof document.compatMode !== 'undefined' |
|||
&& document.compatMode !== 'BackCompat') |
|||
yOffset = document.documentElement.scrollTop; |
|||
else if (typeof document.body !== 'undefined') |
|||
yOffset = document.body.scrollTop; |
|||
|
|||
mousePos.y - yOffset < config.scrollAmount |
|||
&& window.scrollBy(0, - config.scrollAmount) |
|||
|| windowHeight - (mousePos.y - yOffset) < config.scrollAmount |
|||
&& window.scrollBy(0, config.scrollAmount); |
|||
|
|||
}, |
|||
moveVerticle: function (moving, currentRow) { |
|||
|
|||
if (0 !== moving.vertical |
|||
// If we're over a row then move the dragged row to there so that the user sees the
|
|||
// effect dynamically
|
|||
&& currentRow |
|||
&& this.dragObject !== currentRow |
|||
&& this.dragObject.parentNode === currentRow.parentNode) |
|||
0 > moving.vertical |
|||
&& this.dragObject.parentNode.insertBefore(this.dragObject, currentRow.nextSibling) |
|||
|| 0 < moving.vertical |
|||
&& this.dragObject.parentNode.insertBefore(this.dragObject, currentRow); |
|||
|
|||
}, |
|||
moveHorizontal: function (moving, currentRow) { |
|||
var config = this.currentTable.tableDnDConfig, |
|||
currentLevel; |
|||
|
|||
if (!config.hierarchyLevel |
|||
|| 0 === moving.horizontal |
|||
// We only care if moving left or right on the current row
|
|||
|| !currentRow |
|||
|| this.dragObject !== currentRow) |
|||
return null; |
|||
|
|||
currentLevel = $(currentRow).data('level'); |
|||
|
|||
0 < moving.horizontal |
|||
&& currentLevel > 0 |
|||
&& $(currentRow).find('td:first').children(':first').remove() |
|||
&& $(currentRow).data('level', --currentLevel); |
|||
|
|||
0 > moving.horizontal |
|||
&& currentLevel < config.hierarchyLevel |
|||
&& $(currentRow).prev().data('level') >= currentLevel |
|||
&& $(currentRow).children(':first').prepend(config.indentArtifact) |
|||
&& $(currentRow).data('level', ++currentLevel); |
|||
|
|||
}, |
|||
mousemove: function(e) { |
|||
var dragObj = $($.tableDnD.dragObject), |
|||
config = $.tableDnD.currentTable.tableDnDConfig, |
|||
currentRow, |
|||
mousePos, |
|||
moving, |
|||
x, |
|||
y; |
|||
|
|||
e && e.preventDefault(); |
|||
|
|||
if (!$.tableDnD.dragObject) |
|||
return false; |
|||
|
|||
// prevent touch device screen scrolling
|
|||
e.type === 'touchmove' |
|||
&& event.preventDefault(); // TODO verify this is event and not really e
|
|||
|
|||
// update the style to show we're dragging
|
|||
config.onDragClass |
|||
&& dragObj.addClass(config.onDragClass) |
|||
|| dragObj.css(config.onDragStyle); |
|||
|
|||
mousePos = $.tableDnD.mouseCoords(e); |
|||
x = mousePos.x - $.tableDnD.mouseOffset.x; |
|||
y = mousePos.y - $.tableDnD.mouseOffset.y; |
|||
|
|||
// auto scroll the window
|
|||
$.tableDnD.autoScroll(mousePos); |
|||
|
|||
currentRow = $.tableDnD.findDropTargetRow(dragObj, y); |
|||
moving = $.tableDnD.findDragDirection(x, y); |
|||
|
|||
$.tableDnD.moveVerticle(moving, currentRow); |
|||
$.tableDnD.moveHorizontal(moving, currentRow); |
|||
|
|||
return false; |
|||
}, |
|||
findDragDirection: function (x,y) { |
|||
var sensitivity = this.currentTable.tableDnDConfig.sensitivity, |
|||
oldX = this.oldX, |
|||
oldY = this.oldY, |
|||
xMin = oldX - sensitivity, |
|||
xMax = oldX + sensitivity, |
|||
yMin = oldY - sensitivity, |
|||
yMax = oldY + sensitivity, |
|||
moving = { |
|||
horizontal: x >= xMin && x <= xMax ? 0 : x > oldX ? -1 : 1, |
|||
vertical : y >= yMin && y <= yMax ? 0 : y > oldY ? -1 : 1 |
|||
}; |
|||
|
|||
// update the old value
|
|||
if (moving.horizontal !== 0) |
|||
this.oldX = x; |
|||
if (moving.vertical !== 0) |
|||
this.oldY = y; |
|||
|
|||
return moving; |
|||
}, |
|||
/** We're only worried about the y position really, because we can only move rows up and down */ |
|||
findDropTargetRow: function(draggedRow, y) { |
|||
var rowHeight = 0, |
|||
rows = this.currentTable.rows, |
|||
config = this.currentTable.tableDnDConfig, |
|||
rowY = 0, |
|||
row = null; |
|||
|
|||
for (var i = 0; i < rows.length; i++) { |
|||
row = rows[i]; |
|||
rowY = this.getPosition(row).y; |
|||
rowHeight = parseInt(row.offsetHeight) / 2; |
|||
if (row.offsetHeight === 0) { |
|||
rowY = this.getPosition(row.firstChild).y; |
|||
rowHeight = parseInt(row.firstChild.offsetHeight) / 2; |
|||
} |
|||
// Because we always have to insert before, we need to offset the height a bit
|
|||
if (y > (rowY - rowHeight) && y < (rowY + rowHeight)) |
|||
// that's the row we're over
|
|||
// If it's the same as the current row, ignore it
|
|||
if (draggedRow.is(row) |
|||
|| (config.onAllowDrop |
|||
&& !config.onAllowDrop(draggedRow, row)) |
|||
// If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
|
|||
|| $(row).hasClass("nodrop")) |
|||
return null; |
|||
else |
|||
return row; |
|||
} |
|||
return null; |
|||
}, |
|||
processMouseup: function() { |
|||
if (!this.currentTable || !this.dragObject) |
|||
return null; |
|||
|
|||
var config = this.currentTable.tableDnDConfig, |
|||
droppedRow = this.dragObject, |
|||
parentLevel = 0, |
|||
myLevel = 0; |
|||
|
|||
// Unbind the event handlers
|
|||
$(document) |
|||
.unbind(moveEvent, this.mousemove) |
|||
.unbind(endEvent, this.mouseup); |
|||
|
|||
config.hierarchyLevel |
|||
&& config.autoCleanRelations |
|||
&& $(this.currentTable.rows).first().find('td:first').children().each(function () { |
|||
myLevel = $(this).parents('tr:first').data('level'); |
|||
myLevel |
|||
&& $(this).parents('tr:first').data('level', --myLevel) |
|||
&& $(this).remove(); |
|||
}) |
|||
&& config.hierarchyLevel > 1 |
|||
&& $(this.currentTable.rows).each(function () { |
|||
myLevel = $(this).data('level'); |
|||
if (myLevel > 1) { |
|||
parentLevel = $(this).prev().data('level'); |
|||
while (myLevel > parentLevel + 1) { |
|||
$(this).find('td:first').children(':first').remove(); |
|||
$(this).data('level', --myLevel); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
// If we have a dragObject, then we need to release it,
|
|||
// The row will already have been moved to the right place so we just reset stuff
|
|||
config.onDragClass |
|||
&& $(droppedRow).removeClass(config.onDragClass) |
|||
|| $(droppedRow).css(config.onDropStyle); |
|||
|
|||
this.dragObject = null; |
|||
// Call the onDrop method if there is one
|
|||
config.onDrop |
|||
&& this.originalOrder !== this.currentOrder() |
|||
&& $(droppedRow).hide().fadeIn('fast') |
|||
&& config.onDrop(this.currentTable, droppedRow); |
|||
|
|||
// Call the onDragStop method if there is one
|
|||
config.onDragStop |
|||
&& config.onDragStop(this.currentTable, droppedRow); |
|||
|
|||
this.currentTable = null; // let go of the table too
|
|||
}, |
|||
mouseup: function(e) { |
|||
e && e.preventDefault(); |
|||
$.tableDnD.processMouseup(); |
|||
return false; |
|||
}, |
|||
jsonize: function(pretify) { |
|||
var table = this.currentTable; |
|||
if (pretify) |
|||
return JSON.stringify( |
|||
this.tableData(table), |
|||
null, |
|||
table.tableDnDConfig.jsonPretifySeparator |
|||
); |
|||
return JSON.stringify(this.tableData(table)); |
|||
}, |
|||
serialize: function() { |
|||
return $.param(this.tableData(this.currentTable)); |
|||
}, |
|||
serializeTable: function(table) { |
|||
var result = ""; |
|||
var paramName = table.tableDnDConfig.serializeParamName || table.id; |
|||
var rows = table.rows; |
|||
for (var i=0; i<rows.length; i++) { |
|||
if (result.length > 0) result += "&"; |
|||
var rowId = rows[i].id; |
|||
if (rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) { |
|||
rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0]; |
|||
result += paramName + '[]=' + rowId; |
|||
} |
|||
} |
|||
return result; |
|||
}, |
|||
serializeTables: function() { |
|||
var result = []; |
|||
$('table').each(function() { |
|||
this.id && result.push($.param($.tableDnD.tableData(this))); |
|||
}); |
|||
return result.join('&'); |
|||
}, |
|||
tableData: function (table) { |
|||
var config = table.tableDnDConfig, |
|||
previousIDs = [], |
|||
currentLevel = 0, |
|||
indentLevel = 0, |
|||
rowID = null, |
|||
data = {}, |
|||
getSerializeRegexp, |
|||
paramName, |
|||
currentID, |
|||
rows; |
|||
|
|||
if (!table) |
|||
table = this.currentTable; |
|||
if (!table || !table.rows || !table.rows.length) |
|||
return {error: { code: 500, message: "Not a valid table."}}; |
|||
if (!table.id && !config.serializeParamName) |
|||
return {error: { code: 500, message: "No serializable unique id provided."}}; |
|||
|
|||
rows = config.autoCleanRelations |
|||
&& table.rows |
|||
|| $.makeArray(table.rows); |
|||
paramName = config.serializeParamName || table.id; |
|||
currentID = paramName; |
|||
|
|||
getSerializeRegexp = function (rowId) { |
|||
if (rowId && config && config.serializeRegexp) |
|||
return rowId.match(config.serializeRegexp)[0]; |
|||
return rowId; |
|||
}; |
|||
|
|||
data[currentID] = []; |
|||
!config.autoCleanRelations |
|||
&& $(rows[0]).data('level') |
|||
&& rows.unshift({id: 'undefined'}); |
|||
|
|||
|
|||
|
|||
for (var i=0; i < rows.length; i++) { |
|||
if (config.hierarchyLevel) { |
|||
indentLevel = $(rows[i]).data('level') || 0; |
|||
if (indentLevel === 0) { |
|||
currentID = paramName; |
|||
previousIDs = []; |
|||
} |
|||
else if (indentLevel > currentLevel) { |
|||
previousIDs.push([currentID, currentLevel]); |
|||
currentID = getSerializeRegexp(rows[i-1].id); |
|||
} |
|||
else if (indentLevel < currentLevel) { |
|||
for (var h = 0; h < previousIDs.length; h++) { |
|||
if (previousIDs[h][1] === indentLevel) |
|||
currentID = previousIDs[h][0]; |
|||
if (previousIDs[h][1] >= currentLevel) |
|||
previousIDs[h][1] = 0; |
|||
} |
|||
} |
|||
currentLevel = indentLevel; |
|||
|
|||
if (!$.isArray(data[currentID])) |
|||
data[currentID] = []; |
|||
rowID = getSerializeRegexp(rows[i].id); |
|||
rowID && data[currentID].push(rowID); |
|||
} |
|||
else { |
|||
rowID = getSerializeRegexp(rows[i].id); |
|||
rowID && data[currentID].push(rowID); |
|||
} |
|||
} |
|||
return data; |
|||
} |
|||
}; |
|||
|
|||
jQuery.fn.extend( |
|||
{ |
|||
tableDnD : $.tableDnD.build, |
|||
tableDnDUpdate : $.tableDnD.updateTables, |
|||
tableDnDSerialize : $.proxy($.tableDnD.serialize, $.tableDnD), |
|||
tableDnDSerializeAll : $.tableDnD.serializeTables, |
|||
tableDnDData : $.proxy($.tableDnD.tableData, $.tableDnD) |
|||
} |
|||
); |
|||
|
|||
}(jQuery, window, window.document); |
@ -0,0 +1,68 @@ |
|||
/** |
|||
* @author: Dennis Hernández |
|||
* @version: v2.0.0 |
|||
*/ |
|||
|
|||
const isInit = that => that.$el.data('resizableColumns') !== undefined |
|||
|
|||
const initResizable = that => { |
|||
if ( |
|||
that.options.resizable && |
|||
!that.options.cardView && |
|||
!isInit(that) && |
|||
that.$el.is(':visible') |
|||
) { |
|||
that.$el.resizableColumns({ |
|||
store: window.store |
|||
}) |
|||
} |
|||
} |
|||
|
|||
const destroy = that => { |
|||
if (isInit(that)) { |
|||
that.$el.data('resizableColumns').destroy() |
|||
} |
|||
} |
|||
|
|||
const reInitResizable = that => { |
|||
destroy(that) |
|||
initResizable(that) |
|||
} |
|||
|
|||
Object.assign($.fn.bootstrapTable.defaults, { |
|||
resizable: false |
|||
}) |
|||
|
|||
$.BootstrapTable = class extends $.BootstrapTable { |
|||
|
|||
initBody (...args) { |
|||
super.initBody(...args) |
|||
|
|||
this.$el.off('column-switch.bs.table page-change.bs.table') |
|||
.on('column-switch.bs.table page-change.bs.table', () => { |
|||
reInitResizable(this) |
|||
}) |
|||
|
|||
reInitResizable(this) |
|||
} |
|||
|
|||
toggleView (...args) { |
|||
super.toggleView(...args) |
|||
|
|||
if (this.options.resizable && this.options.cardView) { |
|||
// Destroy the plugin
|
|||
destroy(this) |
|||
} |
|||
} |
|||
|
|||
resetView (...args) { |
|||
super.resetView(...args) |
|||
|
|||
if (this.options.resizable) { |
|||
// because in fitHeader function, we use setTimeout(func, 100);
|
|||
setTimeout(() => { |
|||
initResizable(this) |
|||
}, 100) |
|||
} |
|||
} |
|||
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue